Practical 6 Single Cycle Processor 2

Objectives

This section is not a list of tasks for you to do. It is a list of skills you will have or things you will know after you complete the practical.

Following completion of this practical you should be able to:

Guidelines

Time Estimate This practical will take approximately 5-8 hours per student, varying depending on your familiarity with Verilog and the single-cycle architecture covered in class.

Alternate instructions (more words) are available here.

Preliminary Tasks

Follow this sequence of instructions to complete the practical. This practical will all be done in your RISC-V-single-cycle-processor repository where you completed Practical 5.

Expand your RISC-V Single-Cycle Processor

You will now add lui, jal, and jalr support to your processor. Similar to before, do the following for each:

1 Add lui support

You will begin by adding the lui (load upper immediate) instruction to your processor. For this you should not need to add any components, but you will need to update Control and a couple existing components.

  1. Control Unit

    1. Edit Control.v to have an additional case for lui (U_OPCODE).
      • HINT: if you modified a mux, you may need to create a new control signal. Instead of making a single-bit control signal into a two-bit signal, we recommend creating a second signal and evaluating both signals when choosing an output for the mux. See the datapath section below for example usage of both signals on one mux.
    2. Be sure to add a test case in tb_Control.v to test lui. Verify your test succeeds before you continue.
  2. Datapath

    • Update ImmGen.v to do the right thing for lui.
    • Edit your MemToReg mux to support more inputs.
    Tip: Expanding the MemToReg mux

    Most likely you will simply modify a mux to use your new control signal. Assumming you've got two signals and your new one is called new_ctl_sig1, your code might start like this:

    
     always @(ctl_sig, X, Y) begin
         if (ctl_sig == 1)
             mux_output 
  3. Test Bench for lui. This will be much like the iterations from the previous practical:

    1. create a memory-U.txt file with a few assembled lui instructions in it. Consider also using some R-type instructions to see if lui properly overwrites the lower bits of a register.
    2. Create a tb_Processor_U.v file to test your memory-U.txt instructions.
      • We recommend you copy one of your other tests from the last practical and edit it.
    3. Run your new tests. Maybe make a waveform to help debug.
    4. Also make sure all the old tests still work with your new Processor
  4. Once you've got lui working, save your progress in git!

    • Be sure to add, commit, and push only the verilog files, changed memory file, and any waveform .do file you edited or created.

2 Add jal

Use the same procedure as you did for lui to implement jal:

  1. Control for jal
    • You'll probably need to add a new signal for this, like jump for the UJ types that will override the branch signal (since jal is not conditional)
    • And add a test to tb_Control.v for jal.
  2. Datapath
    • Use the new control signal to override the branch.
    • Update ImmGen to support UJ-types.
    • Support "Jump" (update the PC) and "Link" (save the PC+4).
      • NOTE: This is trickier than it seems at first because of the timing of how the link address gets written to the register file. Consider looking back at your worksheet submission for Practical5 and review the timing of when registers are written and when the PC updates.
      • Remember: shortly after PC is written, the new pc value (PC+4) changes too! You might end up with the wrong link address if you're not careful.
      • If you need to store data across a clock edge, consider using a register.
  3. Create a test bench tb_Processor_UJ.v and memory file memory-UJ.txt to test your jal instruction.
    • Be sure to test both the jump part (that the PC gets the right new value at the right time) and also the link part (that rd gets the old PC+4 value). You will need at least two ASSERTs for this.
      Tip: check a register's value

      Remember, you can check a register's value inside a test bench with something like UUT.Reg.REGES[i]

  4. Once it's working, do a git add, commit, push to save your changes.

3 Implement jalr

Use the same procedure as you did for jal to implement jalr. While jalr is an I-type, its opcode is unique so you should treat it like a separate format.

Changes here are similar to jal, but instead of setting PC to be PC+offset, you will use a register value. Plan this out carefully. Drawing on the datapath before you write code is critical to get this done quickly.

  1. Control for jalr

    • Update the control unit and test bench as necessary for this instruction.
  2. Datapath

    • This one will be a little easier than jal, but might require editing the mux between the branch target adder and the PC register.
    • You will probably need to use the same register "cache" trick for linking as you did for jal.
  3. Test Bench.

    • Even though this is technically an I-type instruction, you should make a file memory-JALR.txt to test your jalr instruction.
    • Add a test to the I-type test bench for jalr. (Be sure your test bench loads the right memory file when it gets to jalr testing).

4 Testing strategy

(Q) On the practical worksheet, answer the Correctness question about how you chose to design the tests for your testbenches. This is on page 8.

5 Design and Implement a new instruction

Before you begin this part, be sure to add, commit, and push any work you've done to git.

With your team, design a new instruction that's not currently supported by RISC-V. It can have a different format and do pretty much whatever you want.

For ideas, consult your instructor.

  1. Design the instruction

    1. (Q) On the practical questions sheet, identify the command name, syntax, and purpose/usage of your new instruction.
    2. (Q) Draw the instruction format on the practical questions sheet, showing opcode and any other fields. Clearly label each field and it's size (like we did in class).
    3. (Q) Write RTL for your new instruction on the practical questions sheet.
    4. (Q) Edit and highlight the datapath on the practical questions sheet necessary to implement your new instruction.
    5. Plan out your test bench to ensure substantial testing.
  2. Once you've fully designed the instruction, implement it.

    • Control: Update your Control.v unit to support your new instruction. Be sure to write a test like you did for the other instructions.
    • Datapath: Update Processor.v to support your new instruction.
    • Test Bench.
      • Create a memory file with an assembled version of your new instruction to test.
      • Add your tests to tb_Processor.v
      • Your memory file can also contain other instructions (you may want this to "set up" a test for your instruction)
      • We recommend updating one of your team's assemblers to assemble your new instruction to both (a) check that the instruction format and any addressing modes work, and (b) easily create an assembled machine code version of your instruction.
  3. Document it

    • (Q) Take a screenshot in ModelSim running your test for the new instruction. The waveform should be easy to read, and include the console transcript showing the instructions running for the task. Put this into the worksheet.
    • (Q) Answer the Correctness question about how you chose to design the test for this new instruction.

Submission and Grading

Functional Requirements

At the end of the practical you should have done these things:

Git Requirements

In addition to the list below, you should regularly commit and push whenever you fix a bug, work to a stopping point, or make any incremental updates. At minimum, you must have at least 4 commits in your repo for this practical:

Since this is a team-based practical, there should be numerous iterative commits from each team member. The commits listed above are a minimum set.

Remember, Do not add and commit every single file ModelSim creates. Only add, commit, and push .v, .do, and .mpf files.

Commit and push via git either using VSCode’s built-in source control or with the git bash terminal. Be sure to copy your final commit ID number for the final question on the worksheet. This ID number can be found on the commit history tab on your Github repository.

Worksheet Requirement

All the practicals for CSSE232 have these general requirements:

General Requirements for all Practicals

  1. The solution fits the need
  2. Aspects of performance are discussed
  3. The solution is tested for correctness
  4. The submission shows iteration and documentation

Some practicals will hit some of these requirements more than others. But you should always be thinking about them.

(Q) Complete the practical worksheet. Specifically, complete the questions on pages 12-14, including the one that asks for your commit ID.

Final Checklist

Grading Breakdown

Practical 6 Rubric items Possible Points Weight
Worksheet 96 50%
Code 90 50%
Total out of 100%