Project 1 – Single Cycle MIPS

Due: Friday, 9/15/2017.

The goal of this project is to implement the MIPS single cycle CPU from activity 06. This header file defines many/all of the MIPS bits/vectors and is useful when completing this assignment. Below is how to include this file in Verilog.

The Patterson & Hennessy single cycle CPU (FIGURE 4.24) is shown above. This datapath can execute most instructions, missing is support for the JAL and JR instructions (you can add these later). We have already developed the instruction fetch, jump, and control logic. We are left with the registers, ALU, and data memory. (note: we moved ALU control internal to the control module). Implementing the registers and data memory is very similar to instruction memory. Each defines an array of bit vectors and accesses them accordingly. In behavioral Verilog modeling for the ALU is very simple, a case statement on the control input is sufficient (see activity 05 for a table of the control signals). The goal of this activity is to finish the basic single cycle CPU.

  • Your system must be able to execute basic MIPS code (see Building MIPS binary code).
  • You must simulate two syscalls: print integer (1), and exit (10).
  • You do not have to implement any delays.
  • At the end of the simulation (syscall 10), print a summary of simulation statistics. At a minimum include total simulation time, number of clock cycles, number of instructions executed, and IPC (instructions per clock).

Notes

  • The GNU C compiler, gcc, assumes there is a one-instruction branch delay slot. Your simulator must be able to deal with this correctly (i.e., always execute the instruction following a branch or jump before setting the PC to the new target).

Building MIPS binary code

To test your program we need to generate binary machine code to load into your memory module. We could hand write machine code (not fun), or use the GNU assembler to help us out. If you save the program add_test.s you can use the following Makefile to compile it to a Verilog-compatible $readmemh format file. First, you’ll want to add the path  /usr/remote/mipsel/bin  to your path (e.g., for bash do:  export PATH=$PATH:/usr/remote/mipsel/bin). This is the location of the MIPS cross compiler and other utilities.

add_test.s

Makefile

When you run  make the output should look like this:

Because we are compiling on a little-endian Intel CPU, we have to byte-swap the output to big-endian format. You can now use $readmemh to load this program from the add_test.v file into your simulated CPU’s program memory.

You should have noticed this program uses two syscalls, 1 (print integer) and 10 (exit). The generated machine code for the syscall is 0x0000000C. Your simulator should check for this value from program memory and handle the syscall accordingly. For example, when you read syscall and $v0 == 1, you will have to $display (or $strobe) something from Verilog. If $v0 == 10, you will call $finish. Also, notice the first few bytes are a binary header (call the .reginfo section) added by the GNU assembler. Your MIPS processor should skip these lines and begin executing at word address 0x00100008 (byte address 0x00400020).

Test

One of the first recursive functions we use in CSCI203 generates the Fibonacci sequence. This is intuitive to implement recursively. This will also be a good test of our processor’s ability to properly handle branches and the stack. The C code is below. Translate this to assembly (test with MARS using the 206 lab for reference). Your MIPS assembly Fibonacci program should generate (print) a few Fibonacci numbers and stop. You can check CSCI206’s Lab 5/Lab 6 for basic MIPS stack usage. Remember that you need to implement a memory module to store the stack segment and that you will have to initialize the stack pointer ($sp) to this segment! Also, remember you will have to implement all instructions on your Verilog CPU needed to execute this code!

Submit

Create a git repo on github or gitlab. Submit a zip/tgz file of your entire project working folder to google classroom. You should include all Verilog files including a testbench that runs add_test and/or Fibonacci and a readme file that explains the design, compilation, execution, and testing methodology (i.e., explain how you know it’s working “it outputs 3” is not sufficient).

Grading Rubric

Sophisticated [10] Competent [8] Still Improving [6 or less]
Design [10] Modular, logical, concise, module parameters used. No single “big” module. Some modularity (as in sophisticated) but one module with a disproportionate amount of code. Insufficient modularity, more than one long/ overly complex module.
Documentation [10] Readme sufficiently explains the design, compilation, execution, and testing methodology. The code contains module-level comments and inline comments where appropriate. Readme missing one feature, or no module-level comments, or no inline comments Missing more than 1 of the previously listed items.
Programs (add_test, Fibonacci) [10] Fibonacci executes and generates correct output. After simulation useful statistics are displayed in a visually appealing format. Fibo/add_test works but produces some unwanted output or post-execution statistics need improvement Fibo does not execute correctly but add_test is working. (score 0 if neither program works.)
Print Friendly

CC BY-NC-SA 4.0
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Posted in Projects