Lab 08

Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

Digital Design and Computer Architecture

Harris and Harris, Elsevier, 2007

Lab 8: MIPS Single-Cycle Processor

Introduction
In this lab you will build the MIPS single-cycle processor using Verilog. You will combine your ALU from Lab 5 with the code for the rest of the processor taken from the textbook. Then you will load a test program and check that the instructions work. Next, you will implement two new instructions, then write a new test program that confirms the new instructions work as well. By the end of this lab, you should thoroughly understand the internal operation of the MIPS single-cycle processor. Please read and follow the instructions in this lab carefully. In the past, many students have lost points for silly errors like not printing all the signals requested. Before starting this lab, you should be very familiar with the single-cycle implementation of the MIPS processor described in Section 7.3 of your text, Digital Design and Computer Architecture. The single-cycle processor schematic from the text is repeated in Figure 1 for your convenience. This version of the MIPS single-cycle processor can execute the following instructions: add, sub, and, or, slt, lw, sw, beq, addi, and j. Our model of the single-cycle MIPS processor divides the machine into two major units: the control and the datapath. Each unit is constructed from various functional blocks. For example, as shown in the figure on the last page of this lab, the datapath contains the 32bit ALU that you designed in Lab 5, the register file, the sign extension logic, and five multiplexers to choose appropriate operands.

1. MIPS Single-Cycle Processor


The Verilog single-cycle MIPS module given in Section 7.6.1 of the text. The project containing the module can be found in the supplementary lab material available from the textbook website (or in the class directory). Copy the Lab08 folder to your own directory. Now open lab08_xx.ise from your local folder. Look at the mips module, which instantiates two sub-modules, controller and datapath. Then take a look at the controller module and its submodules. It contains two sub-modules: maindec and aludec. The maindec module produces all control signals except those for the ALU. The aludec module produces the control signal, alucontrol[2:0], for the ALU. Make sure you thoroughly understand the

Page 1 of 10

controller module. Correlate signal names in the Verilog code with the wires on the schematic. After you have thoroughly understood the controller module, take a look at the datapath Verilog module. The datapath has quite a few submodules. Make sure you understand why each submodule is there and where each is located on the MIPS single-cycle processor schematic. Youll notice that the alu module has a question mark by it in the Sources window in Xilinx. You will need to add your Verilog module from lab 5. Do so by choosing ProjectAdd Copy of Source and add your alu module. Be sure the module name matches the instance module name (alu), and make sure the inputs and outputs are in the same order as in they are expected in the datapath module. The highest-level module, top, includes the instruction and data memories as well as the processors. Each of the memories is a 64-word 32-bit array. The instruction memory needs to contain some initial values representing the program. The most convenient way to create a memory with initial values is with Xilinxs Core Generator.

2. A Test Program
We will use the following simple program to test that basic instructions work:
# test1.asm # 23 October 2005 David Harris [email protected] # # Test MIPS instructions. #Assembly Code # Machine Code

main:

around:

end:

addi addi addi or and add beq slt beq addi slt add sub j lw sw

$2, $7, $3, $4, $5, $5, $5, $6, $6, $5, $6, $7, $7, end $7, $7,

$0, $0, $0, $7, $3, $5, $7, $3, $0, $0, $7, $6, $7,

5 3 0xc $2 $4 $4 end $4 around 10 $2 $5 $2

0($0) 71($2)

# # # # # # # # # # # # # # # #

20020005 20070003 2003000c 00e22025 00642824 00a42820 10a70008 0064302a 10c00001 2005000a 00e2302a 00c53820 00e23822 0800000f 8c070000 ac470047

Figure 1. MIPS assembly program: test1.asm This code can be found in the supplementary lab material provided on the textbook website under the Lab08 directory. To use this test code, it must be loaded into the MIPS instruction memory. It would be nice to be able to write Verilog code for a memory with some initial values (the test
Page 2 of 10

program), but Synplify Pro and Xilinx do not support this very well yet. Instead, we will use the Xilinx Core Generator feature to produce a memory with initial values. The instruction memory, imem, will be constructed as a CoreGen ROM that will hold the program (the instructions) to execute. Create the ROM by choosing Project->New Source. Select the source type to be IP(CoreGen and Architecture Wizard) and name your memory imem. You can use CoreGen to generate different kinds of modules. In this case, choose Memories and Storage ElementsRAMs & ROMsDistributed Memory. Click NextFinish. It will now ask you to enter the component name (imem), depth (64), width (32) etc. Choose ROM type memory and make sure none of the inputs or outputs are registered. On the left side, a diagram of the symbol will be shown. A is the 6-bit address and SPO is the 32-bit data output. Notice that only a subset of the PC bits (PC7:2) will be used to address the memory. Be sure you understand thoroughly why only these bits are used. When finished, you can click Generate on the lower left corner, and a memory component will be generated and listed in the Generated Modules in the CORE generator. At the same time, a symbol with the same name will be available for use in your Verilog files. To load the ROM with instructions, you need to use Memory Editor in the CORE generator interface to input the contents of the ROM. To do so, highlight your CORE generated module (i.e. imem) in the Sources in Project window in your main Project Navigator window. Then, under the Processes for Source window, expand the Coregen option and double-click on Manage Cores. Choose ToolsMemory Editor, and you will see a window like the one shown in Figure 2. In the case of instruction memory, you will define a 64 word (although you will only use 16 of the available words) 32 bit memory.

Figure 2. Memory Editor Interface

Page 3 of 10

Click on Add Block to enter the Memory Block Name. Name it imem. Enter the Depth as 64 and the Data Width as 32. Make sure the Radix for the Data is 16 (i.e. hexadecimal). Under Configure COE File Parameter Names, choose MEMORY_INITIALIZATION_RADIX for Radix and MEMORY_INITIALIZATION_VECTOR for Data. Now enter the instruction codes (given in Figure 2) into the contents of the ROM. For example instruction 20020005 is entered at Address 00 (Indicated as row Address 00, offset +0 in the window) in the ROM, instruction 20070003 is at Address 01, and so forth. The first three entries in the ROM are shown in Figure 4. The full set of entries is given in Figure 1. It is worth proofreading your entries because any typos will be very tedious to debug later. When you finish entering all the machine instructions at the corresponding addresses, save your memory configuration by choosing FileSave Memory Definition. Now choose FileGenerate to generate a .coe file that can be read by CoreGen. Click on the top option, COE File(s), and click OK. It should now inform you that defintion1_imem.coe has been generated. This file can be imported later to set up the complete 64 word 32 bit instruction ROM. Now close the Memory Editor. You can now exit from the Memory Editor window by choosing FileExit. The main Core Generator window should still be open. Click on the Generated IP tab in the main window. Now right-click on imem and select: RecustomizeUnder Current Project Settings. Click twice. In the last window, select Load Coefficients, and click on Load File. This will bring up a window that will allow you to browse for your .coe file that holds the definition of your ROM contents. Highlight the file and click Open. Then click Show Coefficients Next to spot-check that they match your expectations. Now complete the setting of the ROM by clicking the Generate button. By doing so, the ROM imem is created with the stored instructions you entered and a template with the same name will also be ready to use in Verilog files. When you view the imem module in your Processes in Source window, there should now no longer be a question mark next to it. If there is still a question mark, you need fix your errors. You can edit your core generated module by double-clicking on it. You can also look at the equivalent Verilog code by choosing CoreGenView Verilog Functional Model.

3. Synthesis
Synthesize the highest level module, top. Notice that the only necessary inputs to the highest level module are clk and reset. The other signals are there for verification purposes only. View the synthesis report. There should be no errors or warnings (you can confirm this by looking at the errors tab at the bottom of the screen). View the RTL schematic. resynthesize. If it does not look as you expected, fix the errors and

Page 4 of 10

4. Testing the single-cycle MIPS processor


To test the processor, you will simulate running test1.asm on the Verilog code. In a complex system, if you dont know what to expect the answer should be, you are unlikely to get the right answer. Begin by predicting what should happen on each cycle when running the program. Complete the chart in Table 1 at the end of the lab with your predictions. What address will the final sw instruction write to and what value will it write? View the sources for Behavioral Simulation and look at the testbench module. This Verilog code is for testing your module only and is not synthesizeable. It generates clock and reset inputs for the device under test, top. It also checks for a memory write and verifies the address and data being written. Do these match your expectations from your code analysis in Table 1? Now you are ready to test your MIPS processor. Make sure the testbench file is highlighted in the Sources window and click on ModelSim Simulator -> Simulate Behavioral Model. If the simulation fails being unable to find the imem, go to the Sources for Behavioral Simulation panel, remove imem.xco, and add imem.v (which was generated by CoreGen). Then close ModelSim and try simulating the testbench again. If you should need to synthesize later, replace imem.v with imem.xco again. Now you can view your simulation. It should print simulation succeeded and display the correct values of the major internal busses. If it does not perform as you expected, check your Table 1 entries and see if you made a mistake. You can also check your coefficients file that you entered into the instruction ROM (imem). You can do so by opening the file in the memory editor. (To do so, highlight the file in the Sources window and choose Manage Cores in the Processes window. Now choose Tools -> Memory Editor. Now choose File -> Open Memory Definition. Edit the definition if needed.) If there are no errors in either your table or ROM, modify your Verilog code and fix any bugs. For debugging, you will likely need to make other signals from sub-modules visible in the higher-level module. View the Workspace window in the main ModelSim window. Expand the hierarchy of the modules until you find the module that has the internal signal you would like to view. Double-click on the module and the corresponding Verilog file will open in the far-right window and an objects window listing all the signals will open. You will likely need to expand the objects window to be able to read the signal names. Click on the signal you would like to view in the waveform window and drag it to the waves window. After you have dragged the signals you would like to view to the waves window, you will need to resimulate. You can refer to previous lab handouts if youve forgotten how to do this. (Hint: restart f, then run 1000 or click on the restart and run buttons). During debug, youll likely want to view several internal signals. However, on the final waveform that you turn in, show ONLY the following signals in this order: clk, reset, pc, instr, aluout, writedata, memwrite, and readdata. All the values need to be output in hexadecimal and must be readable to get full credit.
Page 5 of 10

After you have fixed any bugs, print out your final waveform.

5. Modifying the MIPS single-cycle processor


You now need to modify the MIPS single-cycle processor by adding the ori and bne instructions. First, modify the MIPS processor schematic (on the last page) to show what changes are necessary. You can draw your changes directly onto the schematic. Then modify the main decoder and ALU decoder as required. Show your changes in the tables at the end of the lab. Finally, modify the Verilog code as needed to include your modifications.

6. Testing your modified MIPS single-cycle processor


Enter the program, test2.asm, given in Figure 5 into your instruction memory (imem). You need to figure out what the machine code is for the instructions. Also comment each line of code of test2.asm. You can use PCSpim to help convert to machine code, but remember that PCSpim does not give the correct machine code for beq or bne and that the address for jumps is incorrect. Also, youll need to modify the Verilog testbench to check for the correct Simulation Succeeded values at the end of the program. You might find it useful to create a table similar to that of Table 1.
# test2.asm # 23 March 2006 S. Harris [email protected] # # Test MIPS instructions. #Assembly Code main: ori addi ori beq slt bne j here: sub ori there: add sub sw

$t0, $0, 0x8000 $t1, $0, -32768 $t2, $t0, 0x8001 $t0, $t1, there $t3, $t1, $t0 $t3, $0, here there $t2, $t2, $t0 $t0, $t0, 0xFF $t3, $t3, $t2 $t0, $t2, $t0 $t0, 82($t3)

Figure 3. MIPS assembly program: test2.asm test2.asm can be found in the supplementary lab material on the textbook website under the Lab08 directory. Again, for debugging, you might find it useful to make other signals from sub-modules visible in the ModelSim waveform. However, in the final waveform that you turn in, only include the following signals in this order: clk, reset, pc, instr, aluout, writedata, memwrite, and readdata, in that order. Make sure all your waveforms are readable and show values in hexadecimal.

Page 6 of 10

What to Turn In
Please turn in each of the following items, clearly labeled and in the following order: 1. Please indicate how many hours you spent on this lab. This will not affect your grade, but will be helpful for calibrating the workload for next semesters labs. 2. A completed version of Table 1. 3. Marked up versions of the datapath schematic and decoder tables that adds the ori and bne instructions. 4. A printout of your Verilog code for your modified MIPS computer (including ori and bne functionality) with the changes highlighted: 5. Simulation waveforms of: top.v for test1.asm top.v for test2.asm (with your modified single-cycle MIPS processor)

The simulation waveforms should give the signal values in hexadecimal format and should be in the following order: clk, reset, pc, instr, aluout, writedata, memwrite, and readdata. Do not display any other signals in the waveform. Be sure the waveforms match your expectations. Check that the waveforms are zoomed out enough that the grader can read your bus values. Unreadable waveforms will receive no credit. Use several pages as necessary.

Page 7 of 10

Cycle 1 2 3 4 5 6 7 8 9 10 11 12 13 14

reset 1 0 0 0

pc 00 04 08 0C

instr addi $2,$0,5 20020005 addi $7,$0,3 20070003 addi $3,$0,0xc 2003000c

branch 0 0 0

srca 0 0 0

srcb 5 3 12

aluresult 5 3 12

zero 0 0 0

pcsrc 0 0 0

write data x

mem write 0

read data 0 0

Table 1. First fourteen cycles of executing assembly program test1.asm Remember, branch is asserted (1) when the instruction is a branch (beq) instruction. aluout is the output of the ALU at each cycle. zero is high (1) only if aluout is 0. pcsrc, a signal in the datapath, is low (0) when nextpc should be pc+4. pcsrc is high (1) when the nextpc should be the branch target address (pcbranch). You will notice that all of these signals are not available from the top-level module (mips). For debugging, you might want to look at these signals and others.

Page 8 of 10

Jump

31:26 5:0

MemtoReg Control MemWrite Unit Branch ALUControl2:0 Op Funct ALUSrc RegDst RegWrite

PCSrc

CLK 0 1 0 1 PC' PC A RD Instr


25:21

CLK A1 A2 A3 WD3
20:16

CLK WE3 RD1 RD2 Register File 0 WriteReg4:0 1 SrcA Zero ALUResult A WE RD Data Memory WD ReadData 0 Result 1

Instruction Memory

20:16

0 SrcB 1

WriteData

PCJump PCPlus4 4
27:0 31:28

15:11

ImmExt
15:0

Sign Extend

<<2 PCBranch

25:0

<<2

Single-cycle MIPS processor

Page 9 of 10

Extended functionality. Main Decoder:


Instruction R-type lw sw beq addi j ori bne Op5:0 000000 100011 101011 000100 001000 000010 001101 000101 RegWrite 1 1 0 0 1 0 RegDst 1 0 X X 0 X AluSrc1:0 00 01 01 00 01 XX Branch 0 0 0 1 0 X MemWrite 0 0 1 0 0 0 MemtoReg 0 1 X X 0 X ALUOp1:0 10 00 00 01 00 XX Jump 0 0 0 0 0 1

Extended functionality. ALU Decoder:


ALUOp1:0 00 01 10 11 Meaning Add Subtract Look at funct field

Page 10 of 10

You might also like