CS 61C (Fall 2007)

Project 4

Submit as "proj4".  Due 2:45pm 11/14/2007.

Administrative details

This project is due November 14. This is an individual assignment; you must work alone. Submit your solution, files named CPU.v, ALU.v, Control.v and ALUControl.v as proj4.

We will be testing your solution in ModelSim using a variety of testbenches. We will also be examining your solution for use of forbidden behavioral Verilog constructs, for example, always, initial, and $display; occurrences of these constructs in your submitted modules will lose you a significant amount of points.  Please read the Verilog Circuit Rules carefully.

Finally we will be running the autograder (or at least a subset of it) at least once on solutions submitted early.  This will be our chance to test the autograder and your chance to test the project.  We are hoping to run the autograder on Nov 7th, and e-mail you the logs, allowing you an extra chance to debug your code.

Getting started

Copy the directory contents of ~cs61c/files/proj/4 to ~/proj4 or some other suitable directory. It includes several files: CPU.v, Blocks.v, shells for the modules you must implement and several data files for testing your code. These are described below.

Appropriate background material is found in sections 5.1-5.4 and C.1-C.2 in P&H.


In this project you implement, in Verilog, and simulate a simple MIPS processor. You will build the datapath from a library of predesigned blocks and the controller from primitive gates. Your implementation will be done in structural Verilog.  Below is a specific list of the allowed Verilog constructs for the circuits in this project.  You are not allowed to use any behavioral constructs (always or initial) except in the testbench.  You will find a list of the generally disallowed Verilog constructs in the Verilog Circuit Rules.  You will find a partial list of allowed constructs on the Verilog Green Card.  Note that some of the blocks we have given you are written in ways which make them invalid circuits, and so are not good examples for your code.  Following are the allowed constructs for this project:

The motivation behind this project is to help you understand the detailed operation of processors. Processor implementations are complex, even the simple MIPS; a good understanding of their operation comes only after the experience you will gain by implementing and simulating a processor for yourself.  By understanding the inner workings of a processor, you will become far better equipped to understand operating systems, compilers, computer architecture, parallel programming, and in general this will help you be a better programmer, even if you never design another processor.

This project is based on the design presented in chapter 5 of P&H. Except for a few simple modifications, mentioned below, your implementation should match the one presented in the book.


You will design a module named CPU whose parameters are as follows:

	module CPU(Clock, Reset, Break, BreakCode, Dump); 
		input		Clock, Reset, Dump;
		output		Break;
		output	[19:0]	BreakCode;

Clock and Reset are the clock and reset signals; use of Reset is described in the "Sub-blocks" section. Break is asserted when the break instruction is encountered (see below).  Dump should be connected to the Memory and RegFile modules (see the "Sub-blocks" section).

Your processor must correctly execute the lw, sw, beq, and, or, addu, subu, slt, j, jal, jr, lui, ori, and break instructions. j, jal, jr, lui, ori, and break are not part of the design of P&H Figure 5.17; the addition of a jump to the design is described on P&H pages 313 and 314.

The break instruction simplifies testing the processor.  The break instruction is listed on the back of the green card, in Appendix A of P&H and in the MARS (mars-cs61c) help.  The break instruction has a opcode of 6'b000000, and a funct field 6'b001101 and the 20bits in the middle should be output on the BreakCode output of your CPU. Upon execution of the break instruction, your processor will simply assert the Break port on the CPU module, output the middle 20bits of the break instruction on the BreakCode output of CPU.v and stop executing.  The testbench module will use this signal to dump memory and stop the simulation.

We provide you with a file Blocks.v that contains behavioral Verilog definitions for modules that you can use for some of the blocks shown in P&H Figure 5.17. (The section "Sub-blocks" below provides some details about the modules in this file.) The exceptions are the blocks labeled Control, ALUControl and ALU, which you will have to implement for yourself using primitive gates or 1-bit assign statements (which are trivially equivalent to primitive gates). See section C.2 (in the appendix) for additional information on the control blocks.  Note that you may make any necessary changes to the code in Control.v including adding ports or changing port widths, but you should not need to change the ports on CPU.v, ALU.v or ALUControl.v.  Let us know if you think otherwise, we are open to new ideas.  Finally, beware of relying strictly on Appendix C of P&H, as we are implementing a slightly different instruction set (e.g. addu instead of add).

Consider implementing and testing the break instruction before you work on anything else.  You should also write testbenches for all of the modules you implement, not just the complete ALU.

The basic strategy for running programs on your simulated processor is as follows. At startup the contents of both the instruction and data memories are read from files by the Verilog runtime system. Simulated processor execution proceeds until a break instruction is executed, at which point the data memory is dumped to a different file. You can then inspect the file to see if the program executed correctly. Of course, this scenario assumes that all is well with your processor. For debugging, you should display internal signals of your circuit in the ModelSim Wave window as described in the ModelSim Tutorial.

Test programs in the ~cs61c/files/proj/4 directory

There are several files in the ~cs61c/files/proj/4 directory that you may find useful for testing your simulation.

The tests in this files will probably not reveal all your bugs. In particular, they contain only instructions implemented in Figure 5.17 of P&H.

You can create your own test files by loading .s files into MARS (mars-cs61c) and then clicking the "Save Dump" button as you did for proj3, be sure to select the .text or .data segment as appropriate, and the Hexadecimal Listing format before dumping. If you wish to dump files for your proj3, you should use the Binary format.  Also, do not forget to terminate your programs with a break instruction.

These files will be read in by the RAM and ROM modules in Blocks.v.  See the "Sub-blocks" section below for more information.


In CPUTestBench.v you will find the basic testbench which we will be using to autograde your project. Feel free to use it as a starting point for writing your own testbenches.

Note that you will need to name your test files properly, as the Memory and ROM modules always load their contents from certain filenames.  See below for more information.


The file Blocks.v contains behavioral definitions of the modules that you should instantiate to implement your processor. Although these could have been implemented at the gate level, we have used behavioral constructs to speed up the simulation. The comments preceding each module describe its operation. In particular, notice the various uses of the Dump and Reset signals:

Submission requirements

Submit the Verilog files CPU.v, ALU.v, Control.v and ALUControl.v that contains your CPU module, the ALU and the control modules. We will instantiate and test your CPU module as shown above in the testbench in CPUTestBench.v.  Make sure that the port names in your module match those used above, and that you haven't used any forbidden Verilog constructs.