Title image Fall 2019

RISC CPU Design

Project page


The register layout is shown in the graphic above. The instruction set is given below. It is modeled on the PowerPC RISC architecture, although the size and number of working registers is significantly reduced. Watch the video describing the components (registers, RAM, ROM, and ALU) and data flow. (Note: I make a mistake when I say that the CR output of the ALU should be port mapped to the Condition Register - it should actually be port-mapped to another register, and the assignment from that mapped register to the CR should happen after ALU operations (instructions later).)

Registers A-E, the Stack Pointer, the MBR, and the Instruction Register are all 16 bit registers. The MAR needs to have enough bits to address all of memory (8 bits). The input port is 8 bits, and the output port is 16 bits. The program counter is 8 bits, and the Condition Register is 4 bits. The ALU circuit takes in two 16-bit values and an opcode and outputs the 16-bit result as well as the 4-bits for the Condition Register (though note there is a separate signal mapped to the ALU's output and we assign to the CR only in particular states, so it is a little more complicated than I indicated in the video).

The instructions are 16 bits. All instructions have a 4-bit opcode in bits (15 downto 12), with some instructions having an additional one or two bits of opcode. The remaining bits are used to specify source and destination registers, addresses, or immediate values. Instructions that have an address make use of the low 8 bits of the instruction to hold the information.

InstructionopcodeRemaining bits
Load from RAM0000R-DDD-AAAAAAAA: DDD = dest (table B), R = add register E to immediate value if 1, AAAAAAAA - immediate address value
Store to RAM0001R-SSS-AAAAAAAA: SSS = src (table B), R = add register E to immediate value if 1, AAAAAAAA - immediate address value
Unconditional Branch0010UUUU-AAAAAAAA: U = unused, AAAAAAAA = immediate address value.
Conditional Branch001100-CC-AAAAAAAA: CC = condition (00 = zero, 01 = overflow, 10 = negative, 11 = carry), AAAAAAAA = immediate address value.
Call001101-UU-AAAAAAAA: the cpu should push the PC and CR on the stack and then jump to the immediate address value AAAAAAAA, U = unused.
Return001110-UU-UUUUUUUU: the cpu should pop the CR and then pop the PC to continue execution at the stored address. U = unused.
Exit001111-UU-UUUUUUUU: The CPU should enter a halt state and not leave until the user resets the circuit. U = unused
Push0100SSS-UUUUUUUUU: SSS = src (table C) U = unused, operation puts the value into memory at location SP and increments SP.
Pop0101SSS-UUUUUUUUU: SSS = dest (table C) U = unused, operation reads the value from memory at location SP-1 and decrements SP.
Store to Output0110SSS-UUUUUUUUU: SSS = source (table D) U = unused.
Load from Input0111DDD-UUUUUUUUU: DDD = dest (table B) U = unused.
Add1000SSS-TTT-UUU-DDD: SSS = srcA (table E), DDD = dest (table B), TTT = srcB (table E), U = unused.
Subtract1001SSS-TTT-UUU-DDD: SSS = srcA (table E), DDD = dest (table B), TTT = srcB (table E), U = unused.
And1010SSS-TTT-UUU-DDD: SSS = srcA (table E), DDD = dest (table B), TTT = srcB (table E), U = unused.
Or1011SSS-TTT-UUU-DDD: SSS = srcA (table E), DDD = dest (table B), TTT = srcB (table E), U = unused
Exclusive-or1100SSS-TTT-UUU-DDD: SSS = srcA (table E), DDD = dest (table B), TTT = srcB (table E), U = unused.
Shift1101R-SSS-UUUUU-DDD: SSS = srcA (table E), DDD = dest (table B), R = direction bit '0' = left, '1' = right, maintains sign bit, U = unused.
Rotate1110R-SSS-UUUUU-DDD: SSS = srcA (table E), DDD = dest (table B), R = direction bit '0' = left, '1' = right, U = unused.
Move1111T-(IIIIIIII or SSS-UUUUU)-DDD: DDD = dest (table B), T = if '1', treat next 8 bits as a sign-extended immediate value, else SSS = source location (table D), U = unused.

Below are the tables that show how to interpret the various register selection fields.

Table B
000Register A [RA]
001Register B [RB]
010Register C [RC]
011Register D [RD]
100Register E [RE]
101Stack Pointer [SP]
Table C
000Register A [RA]
001Register B [RB]
010Register C [RC]
011Register D [RD]
100Register E [RE]
101Stack Pointer [SP]
110Program Counter [PC]
111Condition Register [CR]
Table D
000Register A [RA]
001Register B [RB]
010Register C [RC]
011Register D [RD]
100Register E [RE]
101Stack Pointer [SP]
110Program Counter [PC]
111Instruction Register [IR]
Table E
000Register A [RA]
001Register B [RB]
010Register C [RC]
011Register D [RD]
100Register E [RE]
101Stack Pointer [SP]
110Zeros: "0000000000000000"
111Ones: "1111111111111111"

The ALU circuit takes in two source registers and an opcode, and it returns a destination value and a set of condition flags. The ALU opcodes correspond to the low three bits of the 4-bit opcode for instructions 1000 through 1111 (notice this includes the move operation which should just pass through the ALU, so the 111 operation should just assign SRCA to DEST). Assign the ALU opcode signal the IR bits 14 downto 12 in the Exeute-Setup state.

The condition register should be set by the ALU only for instructions at or above 1000: arithmetic, logical, and move instructions. This means we cannot directly port map the CR to the output of the ALU (we need an additional signal).


CPU States

The CPU defined above requires nine states: Start, Fetch, Execute-Setup, Execute-ALU, Execute-MemoryWait, Execute-Write, Execute-ReturnPause1, Execute-ReturnPause2, and Halt.

The Fetch state is a single clock cycle. The execute cycle can take anywhere from three to six clock cycles, depending on the instruction. The Execute-Setup, Execute-ALU, and Execute-Write, are necessary for all instructions. The Execute-MemoryWait state is optional for all instructions except LOAD, POP, and RETURN. The RETURN instruction requires the Execute-ReturnPause1 and Execute-ReturnPause2 after the Execute-Write state in order to load the instruction at the return address into the IR.

Below is a description of what needs to happen in each state. I also made a table describing what needs to happen in each state (columns) for each operation (row). There is also a short movie in which I describe the state machine.