Part A: addi
Lab 5 is required for Project 3A, and lectures 16-19, Discussion 9, and Homework 4 are highly recommended.
In this part, you will design a skeleton CPU that can execute the addi instruction.
Task 1: Arithmetic Logic Unit (ALU)
Fill in the ALU in alu.circ so that it can perform the required arithmetic calculations. See the course notes for Table 1, which describes the ALU input/output signals.
Task: Implement Table 2 in the course notes, which defines the project-specific ALU operations and associated ALUSel values in the course notes. add is already made for you. You are allowed and encouraged to use built-in Logisim components to implement the arithmetic operations.
Unused values: The ALU tests for Part A only use ALUSel values for the defined operations in Table 2, so your design doesn't need to worry about the unused values (for now).
Testing
Run the test_alu unit tests. Follow the Debugging Unit Tests example in the Testing and Debugging Section.
The test_alu test module contains the following test circuits:
alu-addalu-allalu-logicalu-multalu-shiftalu-slt-sub-bsel
Task 2: Register File (RegFile)
Fill in regfile.circ so that it contains 32 registers that can be written to and read from. See the input/output signals of RegFile in Table 1 of the State Elements section of the course notes.
Additional ouput signals: There are 8 constant output registers are included in the output of the regfile circuit for testing and debugging purposes. Make sure to connect these 8 output pins to their corresponding registers:
ra(x1)sp(x2)t0(x5)t1(x6)t2(x7)s0(x8)s1(x9)a0(x10)
Reminders:
- The
x0register should always contain the 0 value, even if an instruction tries writing to it. - Take advantage of copy-paste! It might be a good idea to make one register completely and use it as a template for the others to avoid repetitive work. You can duplicate a selected component or group of components in Logisim using
Ctrl/Cmd + D. - The
Enablepin on the built-in register may come in handy.
Testing and Debugging
The test_regfile test module contains the following test circuits:
regfile-more-regsregfile-read-onlyregfile-read-writeregfile-x0
Task 3: Immediate Generator
Fill in the immediate generator in imm-gen.circ (not the imm_gen subcircuit in cpu.circ). See the input/output signals of the Immediate Generator in the course notes.
For the rest of Part A, we will be creating just enough of the CPU to execute the addi instruction. In Part B, you will revisit these circuits and expand them to support more instructions.
Part A: Your task is to generate immedates for the addi instruction. You can ignore other immediate types for now, meaning you can ignore ImmSel.
Part B: Generate immediates for all relevant instructions.
Testing and Debugging
You'll have to complete the next task before debugging this one!
Task 4: Datapath
Fill in cpu.circ so that it contains a datapath for a single-cycle (not pipelined) processor that can execute the addi instruction.
You can leave most of the inputs and outputs to the processor unchanged in this task, since they are not needed for the addi instruction. A few components of note:
- Constant register outputs (see RegFile Task)
- Program Counter and Instruction (see below)
- Memory, see course notes. Not needed for Part A.
We know that trying to build a datapath from scratch might be intimidating, so the rest of this section offers more detailed guidance for creating your processor.
Recall the five stages for executing an instruction:
- Instruction Fetch (IF)
- Instruction Decode (ID)
- Execute (EX)
- Memory (MEM)
- Write Back (WB)
Task 4.1: Instruction Fetch
We have already provided a simple implementation of the program counter. It is a 32-bit register that increments by 4 on each clock cycle. The ProgramCounter is connected to IMEM (instruction memory), and the Instruction is returned from IMEM.
Nothing for you to implement in this sub-task!
Task 4.2: Instruction Decode
In this step, we need to break down the Instruction input and send the bits to the right subcircuits.
What type of instruction is addi? What are the different fields in the instruction, and which bits correspond to each field?
addi is an I-type instruction. The fields are:
imm [31-20]rs1 [19-15]funct3 [14-12]rd [11-7]opcode [6-0]
In Logisim, what tool would you use to split out different groups of bits?
Use the splitter to extract each of the 5 fields from the instruction.
Which fields should connect to the register file? Which inputs of the register file should they connect to?
The rs1 bits you split from the instruction should connect to ReadIndex1 on the regfile.
The rd bits you split from the instruction should connect to WriteIndex on the regfile.
I-type instructions don't have rs2 so we can ignore rs2 for now.
Remember to connect the clock to the register file!
What needs to be connected to the immediate generator?
Connect the Instruction to the immediate generator. Your immediate generator from the previous task should take the instruction and output the correct immediate for you.
Task 4.3: Execute
In this step, we will use the decoded instruction fields to compute the actual instruction.
What two data values (A and B) should the addi instruction input to the ALU?
Input A should be the ReadData1 from the regfile.
Input B should be the immediate from the immediate generator.
What ALUSel value should the instruction input to the ALU?
ALUSel selects which computation the ALU will perform. Since we only care about implementing addi for now, we can hard-code ALU to always select the add operation (ALUSel = 0b0000).
Task 4.4: Memory
The addi instruction doesn't use memory, so there's nothing for you to implement in this sub-task!
The memory stage is where the memory can be written to using store instructions and read from using load instructions. Because the addi instruction does not use memory, we do not have to worry about it for Part A. Please ignore the DMEM and leave its I/O pins undriven.
Task 4.5: Write Back
In this step, we will write the result of our addi instruction back into a register.
What data is the addi instruction writing, and where is the instruction writing this data to?
addi takes the result of the addition computation (from the ALU output) and writes it to the register rd.
Connect ALUResult to WriteData on the regfile.
Since the addi instruction always writes to a register, you can hard-wire RegWEn to 1 for now so that register writes are always enabled.
Testing and Debugging
Run the test_addi integration tests. Follow the Debugging Integration Tests example in the Testing and Debugging Section.
The test_addi test module contains the following test circuits:
addi-basicaddi-negativeaddi-positive
Submission and Grading
Submit your repository to the Project 3A assignment on Gradescope. The autograder tests for Part A are the same as the tests you are running locally. Part A is worth 20% of your overall Project 3 grade.
- ALU (7)
- RegFile (8)
addi(5)
Total: 20 points