CS 61C (Fall 2007) |
Project 4Submit as "proj4". Due 2:45pm 11/14/2007. |
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.
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:
Control.v
, ALUControl.v
, ALU.v
or those from Blocks.v
.and
, or
, not
, xor
, nand
, nor
, xnor
, buf
) with 1-bit ouputs.{}
and select []
only)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; endmodule
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.
There are several files in the ~cs61c/files/proj/4 directory that you may find useful for testing your simulation.
Consider writing a program with a single break
instruction for your first test. You will do this in lab10.
You can use the break
instruction, with a code, to help debug the control
flow of a program with multiple jumps if you want. For example, by putting
several break
instructions with different BreakCode
values
into your program, you can easily see as a result of the $display
in
our CPUTestBench.v
what the BreakCode
is, telling you
which break
instruction you reached. You might find this helpful
when writing your test code.
For this project you are implementing exactly the same instructions as proj3,
with the exceptions of bne
, sll
, srl
, andi
and addiu
which
were implemented for proj3 but not proj4. Note
that this project includes initialized data memory, so you can use the .data
directive
as needed.
The file inc-loop-test.s contains a simple test program.
The hex listing of the machine code was copied into the file
inc-loop-test.text
,
with the hex listing of the data in
inc-loop-test.data
. Together these can be
used for simulation
(see below).
The file lw-sw-test.s tests the lw and sw instructions.
The file simple-beq-test.s tests lw, sw, and beq.
The file simple-rfmt-test.s tests R-format instructions.
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:
The RAM module initializes data memory from the file named dump.data when
Reset is asserted. It dumps memory to the file dump.out when
Dump
is
asserted. You can generate the dump.data
files by loading
a .s
file into mars-cs61c
and dumping the .data
segment in the Hex Listing
format. Note that the
dump.*
files must be in the same directory as your ModelSim
project (where the vsim.wlf
and transcript
files are).
The ROM module initializes instruction memory (which is read-only) from
the file named dump.text
when Reset
is asserted. You can generate these files by loading a .s
file into
mars-cs61c
and dumping the .text
segment in the Hex Listing
format.
Note that the dump.*
files must be in the same directory as your ModelSim
project (where the vsim.wlf
and transcript
files are).
The machine code dumped by MARS will start at address 0 in the instruction memory,
meaning that your PC
should start at 0.
The RegFile module dumps registers to the console when Dump is asserted.
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.