Status bits
- F1
- At least one of the bits 14..0 of the ALU output is 1
- M1
- The most significant bit of the ALU output is 1
- EQ
- The input operands of the ALU are equal
- CY
-
The carry-out of the ALU is 1.
- This bit should be set only when the M-bit to the ALU is 1
- OA
-
The is a overflow from the ALU (check overflow computation for 2's
complement addition in an earlier assignment)
-
This should be set only when the ALU is used for arithmetic operations
- OM
- The is a overflow as a result of the multiplication (with respect
to a 16-bit result)
Required status conditions may be computed from these status bits, for example:
-
Whether or not the result of the ALU is zero is indicated by
M1' ∧F1'
-
If the result of the ALU is treated as an unsigned number, then it is positive if
M1 ∨F1
-
If the result of the ALU is treated as a 2's complement number, then it is positive if
M1' ∧F1
Condition codes (CC)
The condition codes are a function of the status bits
- ZERO
- Result of ALU is zero
- POSU
- Result of ALU is positive if treated as an unsigned number
- POS2
- Result of ALU is positive if treated as a 2's complement number
- COUT
- The carry out of the ALU is 1
- EQUL
- Both the operands of the ALU are equal
- OVRA
- The is an overflow from the ALU
- OVRM
- The is an overflow from the multiplier
- MSB1
- The MSB of the ALU is 1
General behaviour of CPU for signals at some pins
- RST - asynchronous reset
- Causes PC to be cleared (all 0's) and the SyR line to be asserted
- SyR - system reset
- Asserted when RST is asserted
- HLD - Hold
- When HLD is found to be asserted, CPU responds by tristating
MAB and MDB and asserting HLA
- HLA - Hold acknowledge
- Asserted in response to HLD being asserted
- IO/M'
- Indicates whether address on MAB is for memory or IO device
- INT - Interrupt
- For this CPU, RSB is set to all 0's, and when INT is asserted, IV is set 001
Machine instructions
The generic m/c instruction formats are given below.
There are eight GPRs each of 16 bits.
Note the presence of a number of organisational registers in the data
path which are not visible to the programmer and so are not architectural
registers.
The memory address space is restricted to 216 addresses.
I/O mapped input/output is used.
The i/o address space is restricted to 25 addresses.
The most significant seven bits of each instruction serve as
the opcode.
However, not all instructions use all the seven bits, leaving some of the
bits as don't cares.
It is not even always necessary to examine all the bits of the opcode
that are used to decode the instruction,
e.g. the ADD and ADI and similar instructions.
This ISA does not conform to the load-store architecture because access
to the memory is not restricted to load and store instructions.
In general, the instructions require multiple clock cycles to execute.
Execution of all instructions start with fetching the instruction
and updating the PC to point to the next instruction, as detailed
below, in terms of the micro operations needed to realise the same.
- Instruction fetching
- State IFetch:
- MAB ← PC [xMAB←10, wMAB←1]
- MDB ← MEM [wMDB←1]
- IR ← MDB [wIR←1]
- PC ← PC+2 [P/M'←1, xPC←11, wPC←1]
- Instruction decoding
- State IDecode
- Examine bits of the opcode (colour highlighted most
significant bits of the instruction)
- Perform multiway branching to one of the following cases
depending on the opcode that is matched
- ADD Ra Rb Rc (and similar instructions with two register
operands)
-
- aaaaa: 5-bit ALU operation;
Ra, Rb, Rc: register index (3-bits each)
- Ra ← Rb + Rc
- State IExRR:
- ALU.left ← RegFile.D3
- ALU.right ← RegFile.D2 [tbR←1]
- RegFile.D1 ← ALU.out [tbA←1, wR←1]
- ADI Ra Rb Imm (and similar instructions with register
and immediate operands)
-
- Imm: 16-bit immediate operand
- Ra ← Rb + Imm (in the following word)
- State IExRI:
- ALU.left ← RegFile.D3
- {* ALU.R ← Imm *}
- PC ← PC+2 [P/M'←1, xPC←11, wPC←1]
- MAB ← PC [xMAB←10, wMAB←1]
- MDB ← MEM [wMDB←1]
- ALU.right ← MDB [tbD←1]
- RegFile.D1 ← ALU.out [tbA←1, wR←1]
- MUL Ra Rb Rc
-
- Ra ← Rb × Rc
- State IExM:
- MUL.left ← RegFile.D3
- MUL.right ← RegFile.D2 [tbR←1]
- RegFile.D1 ← MUL.out [tbM←1, wR←1]
- BRU M
-
- Branch unconditionally to memory address stored in following word
- State IExBU:
- MAB ← PC [xMAB←10, wMAB←1]
- MDB ← MEM [wMDB←1]
- PC ← MDB [xPC←10, wPC←1]
- BRC CC M
-
- Branch conditionally, if CC is satisfied
- State IExBC:
- MAB ← PC [xMAB←10, wMAB←1]
- MDB ← MEM [wMDB←1]
- PC ← MDB if CC else PC ← PC+2
[wPC←1, P/M'←1, xPC←
if (brFn(SBVec, CC)) 10 else 11]
- BSR M
-
- Branch to subroutine at memory address stored in following word.
Use one of the CPU registers as the stack pointer
(SPReg).
- State IExJS1: {* get and save subroutine address in T *}
- MAB ← PC [xMAB←10, wMAB←1]
- T ← MDB ← MEM {* via ALU *}
[wMDB←1, tbD←1, IR.aaaaa←?ALU.R, tbA←1, wT←1]
- State IExJS2:
- PC ← T [xPC← 01, wPC←1] {* PC←subAddr *}
- {* Push return address to stack *}
- MDB ← PC+2
[P/M'←1, xMDB←01, tbE←11, wMDB←1]
- MAB ← SPReg ← SPReg+2
{* IR.Ra=IR.Rc=SPReg *}
[IR.aaaaa←?INC2, tbA←1,
xMAB←00 wMAB←1, wR←1]
- RET
-
- Return from subroutine
- State IExRS1:
- {* Pop return address from stack (through ALU) *}
- MAB ← SPReg; {* IR.Ra=IR.Rc=SPReg *}
[IR.aaaaa←?ALU.R, tbA←1, xMAB←00 wMAB←1]
- PC ← MDB ← MEM [wMDB←1, xPC←10, wPC←1]
- State IExRS2: {* Can this separate step be avoided? *}
- SPReg ← SPReg-2
[IR.aaaaa←?DEC2, tbA←1, wR←1]
{* IR.Ra=IR.Rc=SPReg *}
- TRP
-
- TRAP - generate a software interrupt.
RSB is set to all 0's, and when INT is asserted, IVX is
set to the bits from the instruction marked as IVX
- State IExTR1:
- {* Push return address to stack *}
- MDB ← PC+2
[P/M'←1, xMDB←01, tbE←11, wMDB←1]
- MAB ← SPReg ← SPReg+2 {* IR.Ra=IR.Rc=SPReg *}
[IR.aaaaa←?INC2, tbA←1,
xMAB←00 wMAB←1, wR←1]
- State IExTR2:
- {* Save resolved trap address in PC *}
- IV ←? IR(2..0) {* RSB ← 0 *}
- PC ← INTVecAddr [xPC←00, wPC←1]
- {* Push SBVec to stack *}
- MDB ← SBVec
[xMDB ← 11 tbE←11, wMDB←1]
- MAB ← SPReg ← SPReg+2 {* IR.Ra=IR.Rc=SPReg *}
[IR.aaaaa←?INC2, tbA←1,
xMAB←00 wMAB←1, wR←1]
- intMask←?1; privFlag←?1
- RTI
-
- Return from interrupt
- State IExRT1:
- {* Pop SBVec from stack *}
- MAB ← SPReg;
{* from SPReg, through ALU, IR.Ra=IR.Rc=SPReg *}
[IR.aaaaa←?ALU.L, tbA←1,
xMAB←00 wMAB←1]
- SBVec ← MDB ← MEM
[wMDB←1, tbD←1]
- intMask←?0; privFlag←?0
- State IExRT2:
- {* Pop return address from stack (through ALU) *}
- MAB ← SPReg ← SPReg-2
wMAB←1]
[IR.aaaaa←?DEC2, tbA←1, xMAB←00
{* IR.Ra=IR.Rc=SPReg *}
- PC ← MDB ← MEM [wMDB←1, xPC←10, wPC←1]
- State IExRT3: {* Can this separate step be avoided? *}
- SPReg ← SPReg-2
[IR.aaaaa←?DEC2, tbA←1, wR←1]
{* IR.Ra=IR.Rc=SPReg *}
- HLT
-
- HALT - suspend CPU execution until receipt of interrupt
- State IExHLT:
- {* If intMask flag is set or INT is clear,
Controller NextState←HLT *}
- INP P
-
- Input from address P in IO space
- Ra ← IO[P]
- State IExI:
- MAB ← IO::P [xMAB←01, wMAB←1]
- Ra ← MDB ← MEM {* via ALU *}
[wMDB←1, tbD←1, IR.aaaaa←?ALU.R, tbA←1, wR←1,
IO/M;←1]
- OUT P
-
- Output to address P in IO space
- IO[P] ← Rc
- State IExO:
- MAB ← IO::P [xMAB←01, wMAB←1]
- MEM ← MDB ← Rc {* via ALU *}
[IR.aaaaa←?ALU.L, tbA←1, xMDB←10, tbE←1,
wMDB←1, IO/M;←1]
- LDM Ra, M
-
- Ra ← MEM[M]
- State IExLM1:
- PC ← PC+2 [P/M'←1, xPC←11, wPC←1]
- MAB ← PC [xMAB←10, wMAB←1]
- T ← MDB ← MEM {* via ALU *}
[tbD←1, IR.aaaaa←?ALU.R, wMDB←1, wT←1]
- State IExLM2:
- MAB ← T [xMAB←11]
- ALU.right ← MDB [tbD←1]
- {* IR.aaaaa ←? ALU.R *}
- RegFile.D1 ← ALU.out [tbA←1, wR←1]
- STM Rc, M
-
- MEM[M] ← Ra
- State IExSM1:
- PC ← PC+2 [P/M'←1, xPC←11, wPC←1]
- MAB ← PC [xMAB←10, wMAB←1]
- T ← MDB ← MEM {* via ALU *}
[tbD←1, IR.aaaaa←?ALU.R, wMDB←1, wT←1]
- State IExSM2:
- MAB ← T [xMAB←11]
- MDB ← RegFile.D3
[IR.aaaaa ←? ALU.L, tbA←1, xMDB←10, tbE←1]
- LDX Ra, M, Rb
-
- Ra ← MEM[M+Rb]
- State IExLX1:
- PC ← PC+2 [P/M'←1, xPC←11, wPC←1]
- MAB ← PC [xMAB←10, wMAB←1]
- MDB ← MEM [wMDB←1]
- T ← MDB + Rb;
[IR.aaaaa←? PLUS, tbD←1, wT←1]
- State IExLX2:
- MAB ← T [xMAB←11]
- ALU.right ← MDB [tbD←1]
- {* IR.aaaaa ←? ALU.R *}
- RegFile.D1 ← ALU.out [tbA←1, wR←1]
- STX Rc, M, Rb
-
- MEM[M+Rb] ← Rc
- State IExSX1:
- PC ← PC+2 [P/M'←1, xPC←11, wPC←1]
- MAB ← PC [xMAB←10, wMAB←1]
- MDB ← MEM [wMDB←1]
- T ← MDB + Rb;
[IR.aaaaa←? PLUS, tbD←1, wT←1]
- State IExSX2:
- MAB ← T [xMAB←11]
- MDB ← RegFile.D3
[IR.aaaaa ←? ALU.L, tbA←1, xMDB←10, tbE←1]
- External interrupt handling
- {* if intMask flag is set or INT is clear,
Controller NextState←IFetch *}
- State cpuINT1:
- {* Stamp TRP instruction to IR with IVX bits from external
source *}
- State cpuINT2:
- {* Push return address (current PC value) to stack *}
- MDB ← PC
[xMDB←00, tbE←11, wMDB←1]
- MAB ← SPReg ← SPReg+2 {* IR.Ra=IR.Rc=SPReg *}
[IR.aaaaa←?INC2, tbA←1,
xMAB←00 wMAB←1, wR←1]
- {* Controller NextState←IExTR2 *}
- HLD signal handling
- State cpuHLD:
- {* if HLD is set, Controller NextState←cpuHLD
else Controller NextState←IFetch *}
- {* Busy waiting by CPU, how can this be made productive? *}
- {* Useful for DMA operation *}
Critique
Deviations from load/store architecture
A direct deviation is observed in the BSR, RET, TRP and RTI instructions
where accesses to the memory are required in course of executing the
instructions.
A more subtle deviation occurs in the multi-word instructions entailing
a second memory reference after the basic instruction fetch step.
This is caused by the fact that only 16 bits are available per word and
not enough bits are available for encoding all instrucions within a single
word; the situation is remedied when 32 bits are available per word.
Deviations from RISC architecture
Instructions that are complex in nature are: BSR, RET, TRP, RTI;
these can be split into simpler instructions
Design organisation
The datapath should be in pure in structural form, just as it would be if
components were to be wired on to a bread board.
The controller should be in behavioural form, so that its behaviour can be
ascertained by inspecting the given behaviour.
Do not use delays anywhere in your design as those are not synthesisable.
The verilog for your datapath and controller should be fully synthesisable.
It is expected that it will be possible to map your design onto an FPGA and execute
small programs stored in an EPROM.
Your design should be in two files as follows:
- Single verilog file for datapath including components not explicitly
specified, but required to complete the design
- Single verilog file for controller
- Test bench