Lucy’s Design Notebook
Week 1: 09/08/2025 - 09/14/2025
- Worked through “Design Notebooks and Git” and “Development Environment” on the VIP website
- Completed “Getting Started” and “Verilog Language: Basics” on HDLBits
WSL and Ubuntu (and packages) were downloaded using the Windows Powershell terminal. There were no problems in this process. The HDLBits problem sets were a great refresher for me and it does explain in more detail on how Verilog works compared to a circuit.
I am using VS Code for the first time, so I had a hard time navagating the files and learning how to use VS Code with Ubuntu. I hard a hard time creating a branch in my fork repository and could not tell where I was in the repository (main or branch) until I searched up the documentation for Git source control in VS Code.
Remaining Questions: I am still kind of confused with how Ubuntu works with VS Code and where the files are stored (locally?).
Week 2: 09/15/2025 - 09/21/2025
- Completed Program Counter with my partner
We read the documentations on the instruction set and sequential implementation of the RiSC-16 chip. However, we were having trouble understanding what the inputs and outputs should be for the PC.
- One idea was that the 16-bit instruction set in machine code is passed into the module, but that idea was discarded because there was no way of obtaining the addresses of the registers and immediate value through the machine code.
- Another idea was that the opcode, registers, and immediate values are passed into the module as inputs and we would use the opcode to decide on what the output address would be. But, we were unsure on how the incrementation of the PC would work and how the address would be chosen, given two 3-bit registers (A and B).
We consulted Noah about the inputs and outputs of the PC. From my interpretation, he explained that there are 3 possible jumps for the output address: incrementing of 1, jumping to register B (JALR instruction), and jumping to the immediate value (BEQ instruction). For all 3 possible jumps, there should be an input with the 16-bit address. A multiplexer, given an input from another module, is used to choose which address would be the one the PC would actually point to.
My partner and I had some differences in our interpretations, so we decided to write our code in separate files and push both versions to the repository (My PC and My Partner’s PC).
Remaining Questions/Notes: We are unable to test our PC implementations, so we are not sure if either of them are correct. Since we are both taking Computer Architecture this semester, we are not yet sure how the ALU, PC, instruction memory, etc. work together.
Week 3: 09/22/2025 - 09/29/2025
- Fixed PC to pass all testbench tests
- Completed ALU and passed the testbench tests
The sequential implementation document was reviewed to understand how the inputs (given in the slides) were manipulated to be passed into the multiplexers. Since there are four possible operations to choose from—add, bitwise nand, passing src1, and setting EQ if equal—the input FUNC_alu is 2-bits.
The multiplexers inputs are 1-bit signals that choose whether the left-shifted immediate value or the source1 input [MUX_alu1] and the whether the sign-extended immediate value or the source2 input [MUX_alu2] are used as the source inputs for the internal multiplexer of the ALU that operates on the two inputs.
The outputs, EQ (1-bit) and alu_out (16-bit), are selected based on the following operations:
- default: alu_out = 16’b0, EQ = 1’b0
- add: alu_out = src1 + src2
- bitwise nand: alu_out = ~(src1 & src2)
- passing src1 unchanged: alu_out = src1
- setting EQ: alu_out = 16’b0
EQ is always being set to (src1 == src2) for every operation.
For this week’s project, my partner and I worked separately, meeting once to check each other’s progress. Therefore, we worked on separate alu files: My ALU and My Partner’s ALU.
Remaining Question: When fixing the PC, I was confused on why the reset input is negative and why the immediate value is inputted as 7-bit, not 16-bit. When working on the ALU, I had the following questions: When do you decide to make an input/output a register? When do you use a clock and when do you not (depending on if it iterates?).
Week 4: 09/30/2025 - 10/05/2025
- Completed the Register File
- Fixed Register File to pass all test cases in the testbench
The Instruction Set Architecture was reviewed. The 16-bit instruction input was separated into different variables: opCode, rA, rB, rC, signed_imm, and imm. An array of eight 16-bit registers was created.
At first, I thought the opcode would be used to assign the results (rB + rC, rB nand rC, etc) to rA. But, I realized that the calculations are done in the ALU, so the register value should be updated with the values inputted to the register file (alu_out, mem_out, pc).
Looking at the diagram in the Instruction Set Architecture, I think the MUX_tgt is used to determine what value the destination register is updated with, if the WE bit is turned on. The outputs for the register file are determined on the opcode of the inputted instruction.
Testing code with Testbench
There were many syntax and logic errors while testing my code with the testbench. Below are the things I realized and fixed.
- MUX_rf: used to determine if reg_out2 is rA or rC
- The default case is to output 16’b0 for both outputs
- Need to extend the signed_imm and the 10-bit imm for reg_out2
- The register file only updates if:
- WE_rf bit is on
- source register is not register 0
Notes: As I am writing this week’s design notebook, I realize that it doesn’t make sense to update the register using the value of the current instruction’s rA. So, I am unsure as to why my current code (which does the above) passes all the test cases.
Week 5: 10/06/2025 - 10/12/2025
- Fixed register file using the updated testbench, passed all tests
There was no new assignment for this week.
The previous testbench was incorrect because the Register File should not take the instruction, only the registers (rA, rB, rC). While fixing my Register File code using the fixed testbench, I realized the following about my code:
- The Register File should NOT sign-extend or left shift the immediate value; in fact, the register does not take the immediate value as an input at all.
- The opcode should not be an input for any of the modules, only the signals from the Control Unit and the outputs from other modules are inputs.
Week 6: 10/13/2025 - 10/19/2025
- Completed testbench for the Data Memory module
At the start, I created different test cases, like the verfication of the initial values in the memory, testing if the reg_out value was written to the address (alu_out) if WE_dmem = 0 (should not write), and overwriting previously modified memory data. One problem I had was that I was checking all 65536 memory locations, which is very inefficient. So, I changed the tests cases to only check the few memory addresses that were being tested.
The biggest problem that I encountered while writing the testbench was the verilog syntax and logic. Within an initial block, declaring an integer after an executable statements would cause errors and displaying text right after one another would also cause errors. However, all these errors would point to the $finish line at the very end of the code, so it was difficult to know which lines were actually causing errors.
Notes: Wires cannot be declared inside an intial block. However, registers and integers can, but only at the top, before any executable statements.
Week 7: 10/20/2025 - 10/26/2025
- Completed Control and Data Memory modules
- Passed all testcases for the Control module, using the provided testbench
The Control module selects the value of the output signals: WErf, WEdmem, MUXalu1, MUXalu2, MUXrf, MUXtgt, FUNCalu, and MUXpc, based on the opcode input and the EQ signal (only for MUXpc). The first step was to find the corrosponding opcodes to the instructions using the instruction set. The output signals were found by looking at the “Instruction Dataflow” diagrams for each instruction found in the sequential implementation document. Another useful part of the document was the “Putting it all together” section that shows which modules the signals are sent to and describes what the signals are used for in the modules.
Notes: There were some modules that were not used for some instructions and I was not sure if I needed to set the value of the signals that corrolate to the unused modules.