Sei sulla pagina 1di 23

CMPEN 331.

001

MIPS Processor Pipeline Implementation


Project Write-Up

Matthew McTaggart

Project Abstract:
This project demonstrates the implementation of the 32bit MIPS processor architecture. The general
data path flow is shown in the following figure.

The dataflow is controlled by a clock which controls the program counter (PC) increment and the
pipeline registers given as IF/ID, ID/EX, EX/MEM, and MEM/WB. The five stages in this processor
architecture are the instruction fetch (IF), instruction decode (ID), execution (EX), data memory (MEM),
and write back (WB). In the case for the project, the instruction fetch is controlled by a slider switch
where the user enters the instructions into the pipeline on the positive edge, this is noted as the clock to
the system, and is called userinput. As per specification, the only output of the system is when the first
instruction has passed through the entire pipeline; this is denoted by the signal Status.

Introduction:
The MIPS instruction fetch implementation is based from the following schematic. The PCSrc signal and
the EX/MEM values are passed from the EX/MEM latch register. These control the program counter if a
branch on equal instruction occurs. The program counter is used to pass the instruction from the
instruction memory and the program counter increment is used to continually increment the program
counter such that instructions can be passed into the pipeline sequentially from the instruction memory
file.

Instruction Memory Module Initialization*


Instruction Memory (Hex) [0:8]
002300AA
10654321
00100022
8C123456
8F123456
AD654321
13012345
AC654321
12012345
Note 128, 32bit Instructions Total
All other memory is initialized to 0.

Once the instruction has been fetched, it is passed to the instruction decode where the controls bits are
determined, and the registers to be read and written to. The WB, M, EX signals are passed through the
pipeline as control bits for the corresponding stages. The register is written to once instructed to from
the RegWrite signal from the WB stage. The register to be written to, and the value to be written for
that register, are determined from the WB stages multiplexor (mux).
In the execution stage, the branch address, if a branch on equal occurs, is determined from adding the
program counter increment and the sign extension of the 16bit address field characteristic of the MIPS Iformat. The jump signal, or the PCSrc is dependent on the ALUResult being zero, asserting the Zero
signal, and the M branch control signal being asserted.

The RegDst source is controlled from the EX control bit, and passes the correct destination register to for
write back depending on whether the instruction is MIPS R-format or MIPS I-format. The first five bits of
the instruction is the function bits, and this controls the ALU function through the ALU Control module.
Finally the second ALU data source is controlled by the ALUScr control signal. This controls whether
Read Data 2 passes to the ALU, for MIPS R-format, or the sign extension of the immediate, for MIPS I
format.

Register Module Initialization*


Registers (Hex) [0:9]
000000AA
00000011
00000022
00000033
00000044
00000055
00000066
00000077
00000088
00000099
All other registers are cycled through that order for all 32 registers. I had to change from the original
register values because when load words and store word instructions were occurring, the offset and the
dataout from the registers are well outside of the 128 data memory entries. Also, with this change, the
data memory entries was increased to 32,767 because the store word and load word instructions could
have an offset value of up to 65,536. For the defined instruction memories, that largest offset is about
17,185. Vivado was not able to simulate the testbench with the data memories needed for the original
register value initializations stated in the project. This was done for the simulation only.
The MEM and WB stage implementations are based from the following schematic. These particular
stages are responsible for deciding which register will be written to and what data will be written to said
register. The WB mux is responsible for determining the data, and the EX mux data coming from the
MEM/WB latch will determine which register the data is written to.

The Branch AND gate controls the PcScr in the instruction fetch stage, and the MemWrite and MemRead
signals are controlled by the control signals passed from the execution stage. The destination of the
write back mux is determined from the control signal MemToReg passed from the execution stage.

Data Memory Module Initialization*


Data Memory (Hex) [0:8]
002300AA
10654321
00100022
8C123456
8F123456
AD654321
13012345
AC654321
12012345
Note 32,767, 32bit Data Memories Total
All other data memory is initialized to 0. Data memory was increased for reason discussed above.
All of the latch registers, are all initialized to zero when the system starts. The values change once the
instruction memories are passed through.
This MIPS processor architecture is beneficial for computer organization because it is able to do all basic
functions such as arithmetic operations, loading and storing to memory and branching. It is also
beneficial because 32bit architecture can be performed fairly quickly in comparison to 64bit
architecture, where some slowdown can occur. The data path design used in this lab has limitations
however, because it is unable to detect and handle hazards, and controlling pipeline throughput by
utilizing forwarding methods between each pipeline stage.

Output Waveform:

Testbench Code:
ID/EX Register Latch Output

EX/MEM Register Latch Output

MEM/WB Register Latch Output

Testbench Code:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Peter Rancourt & Matthew McTaggart
// Engineer: CMPEN331.001
//////////////////////////////////////////////////////////////////////////////////

module testbench();

//IF
reg clock;
wire [31:0] InstMem;
wire [31:0] PcIncr;
//IFID Latch
wire [31:0] InstMem1;
wire [31:0] PcIncr1;

//ID
wire [1:0] WB;
wire [2:0] M;
wire [3:0] EX;
wire [31:0] IDIFPcIncr;
wire [31:0] Data1;
wire [31:0] Data2;
wire [31:0] SE;
wire [4:0] Rt;
wire [4:0] Rd;
//IDEX Latch
wire [1:0] WB1;
wire [2:0] M1;
wire [3:0] EX1;
wire [31:0] IDIFPcIncr1;
wire [31:0] Data11;
wire [31:0] Data21;
wire [31:0] SE1;
wire [4:0] Rt1;
wire [4:0] Rd1;

//EX
wire [1:0] WB2;
wire [2:0] M2;
wire [31:0] AdderOut2;
wire AluZero2;
wire [31:0] AluOut2;
wire [31:0] Data22;
wire [4:0] MuxOutReg2;
wire [2:0] AluCont;
//EXMEM Latch
wire [1:0] WB3;
wire [2:0] M3;
wire [31:0] AdderOut3;
wire AluZero3;
wire [31:0] AluOut3;
wire [31:0] Data23;
wire [4:0] MuxOutReg3;

//MEM
wire [1:0] WB4;
wire [31:0] ReadData4;
wire [31:0] AluResult4;
wire [4:0] MuxOutReg4;
wire BranchPcMux;
//MEMWB Latch
wire [1:0] WB5;
wire [31:0] ReadData5;
wire [31:0] AluResult5;
wire [4:0] MuxOutReg5;

//WB Stage
wire [31:0] WBMuxOut;

//To Write Data ID Stage

wire Status;

//MODULE INSTANTIATIONS
//IF
IFSTAGE

ifTest(clock,BranchPcMux,AdderOut3,InstMem,PcIncr);

IFIDLATCH

ifLatchTest(clock,InstMem,PcIncr,InstMem1,PcIncr1);

//ID
IDSTAGE
idTest(InstMem1,PcIncr1,WB5[1],MuxOutReg5,WBMuxOut,WB,M,EX,IDIFPcIncr,Data1,Data2,SE,Rt,Rd);
IDEXLATCH
idLatchTest(clock,WB,M,EX,IDIFPcIncr,Data1,Data2,SE,Rt,Rd,WB1,M1,EX1,IDIFPcIncr1,Data11,Data21,SE
1,Rt1,Rd1);
//EX
EXSTAGE
exTest(WB1,M1,EX1,IDIFPcIncr1,Data11,Data21,SE1,Rt1,Rd1,WB2,M2,AdderOut2,AluZero2,AluOut2,Data22,
MuxOutReg2,AluCont);
EXMEMLATCH
exLatchTest(clock,WB2,M2,AdderOut2,AluZero2,AluOut2,Data22,MuxOutReg2,WB3,M3,AdderOut3,AluZero3,A
luOut3,Data23,MuxOutReg3);
//MEM
MEMSTAGE
memTest(WB3,M3,AdderOut3,AluZero3,AluOut3,Data23,MuxOutReg3,WB4,ReadData4,AluResult4,MuxOutReg4,B
ranchPcMux);
MEMWBLATCH
memLatchTest(clock,WB4,ReadData4,AluResult4,MuxOutReg4,WB5,ReadData5,AluResult5,MuxOutReg5);
//WB
WBSTAGE

wbTest(WB5,ReadData5,AluResult5,WBMuxOut);

assign Status = ~MuxOutReg5[4]&~MuxOutReg5[3]&MuxOutReg5[2]&~MuxOutReg5[1]&MuxOutReg5[0];

initial begin
//InstMem = 32'h00000000;
clock = 0; //Cycle 0
#10 clock = 1;
//InstMem = 32'h002300AA;
#5 clock = 0; //Cycle 2
#5 clock = 1;
//InstMem = 32'h10654321;
#5 clock = 0; //Cycle 3
#5 clock = 1;
// InstMem = 32'h00100022;
#5 clock = 0; //Cycle 4
#5 clock = 1;
//InstMem = 32'h8C123456;
#5 clock = 0; //Cycle 5
#5 clock = 1;
//InstMem = 32'h8F123456;
#5 clock = 0; //Cycle 6
#5 clock = 1;
//InstMem = 32'hAD654321;

#5 clock = 0; //Cycle 7
#5 clock = 1;
//InstMem = 32'h13012345;
#5 clock = 0; //Cycle 8
#5 clock = 1;
//InstMem = 32'hAC654321;
#5 clock = 0; //Cycle 9
#5 clock = 1;
//InstMem = 32'h12012345;
#5 clock = 0; //Cycle 10
#5 clock = 1;
//InstMem = 32'h00000000;
#5 clock = 0; //Cycle 11
#5 clock = 1;
//InstMem = 32'h00000000;
#5 clock = 0; //Cycle 12
#5 clock = 1;
//InstMem = 32'h00000000;
#5 clock = 0; //Cycle 13
#5 clock = 1;
//InstMem = 32'h00000000;
#5 clock = 0; //Cycle 14
#5 clock = 1;
//InstMem = 32'h00000000;
#5 clock = 0; //Cycle 15
#5 clock = 1;
//InstMem = 32'h00000000;
#5 clock = 0; //Cycle 16
#5 clock = 1;
//InstMem = 32'h00000000;
end
always @(posedge clock)
begin
#1
$display("T = %d WB(IDEX) = %b M(IDEX) = %b EX(IDEX) = %b PCPass(IDEX) = %d Data1(IDEX) =
%d Data2(IDEX) = %d SExt(IDEX) = %d Rs(IDEX) = %d Rd(IDEX) = %d T = %d WB(EXMEM) = %b M(EXMEM) =
%b Adder(EXMEM) = %d AluZero(EXMEM) = %d AluOut(EXMEM) = %d WriteData(EXMEM) = %d RegMux(EXMEM) =
%d T = %d WB(MEMWB)= %b ReadData(MEMWB) = %d AluResult(MEMWB) = %d WBRegister(MEMWB) =
%d",$time,WB1,M1,EX1,IDIFPcIncr1,Data11,Data21,SE1,Rt1,Rd1,$time,WB3,M3,AdderOut3,AluZero3,AluOut
3,Data23,MuxOutReg3,$time,WB5,ReadData5,AluResult5,MuxOutReg5); end
endmodule

Design Schematic
Overview:
The input is the user control of the instruction fetch, and the output is an LED indication when a branch
instruction occurs.

Part 1 Instruction Fetch and Write Back

Part 2 Instruction Decode

Part 3 Execution Stage

Part 4 Memory Stage

Part 5 Status Output.

The status knows information about the first instruction and indicates that the light should assert once
the condition is met.

Routed Design:

Result Image:

The LED did in fact light up when expected, at T 60ns on the waveform simulation.

Implementation Top Module:


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Matthew McTaggart & Peter Rancourt
// Engineer: CMPEN331.001
//////////////////////////////////////////////////////////////////////////////////

module MIPSprocessor(userinput,Status);

input userinput;
//Slide Input by user to control the instruction fetching. (User
Defined Clock, so to speak). The slider will be indicated in the
output Status;
//On the board, a light will indicate when a branch instruction occurs. We
know that at the second instruction, we'll get an LED lit. It will be defined in the constraints
file.

//IF
wire [31:0] InstMem;
wire [31:0] PcIncr;
//IFID Latch
wire [31:0] InstMem1;
wire [31:0] PcIncr1;

//ID
wire [1:0] WB;
wire [2:0] M;
wire [3:0] EX;
wire [31:0] IDIFPcIncr;
wire [31:0] Data1;
wire [31:0] Data2;
wire [31:0] SE;
wire [4:0] Rt;
wire [4:0] Rd;
//IDEX Latch
wire [1:0] WB1;
wire [2:0] M1;
wire [3:0] EX1;
wire [31:0] IDIFPcIncr1;
wire [31:0] Data11;
wire [31:0] Data21;
wire [31:0] SE1;

wire [4:0] Rt1;


wire [4:0] Rd1;

//EX
wire [1:0] WB2;
wire [2:0] M2;
wire [31:0] AdderOut2;
wire AluZero2;
wire [31:0] AluOut2;
wire [31:0] Data22;
wire [4:0] MuxOutReg2;
wire [2:0] AluCont;
//EXMEM Latch
wire [1:0] WB3;
wire [2:0] M3;
wire [31:0] AdderOut3;
wire AluZero3;
wire [31:0] AluOut3;
wire [31:0] Data23;
wire [4:0] MuxOutReg3;

//MEM
wire [1:0] WB4;
wire [31:0] ReadData4;
wire [31:0] AluResult4;
wire [4:0] MuxOutReg4;
wire BranchPcMux;
//MEMWB Latch
wire [1:0] WB5;
wire [31:0] ReadData5;
wire [31:0] AluResult5;
wire [4:0] MuxOutReg5;

//WB Stage
wire [31:0] WBMuxOut;

//To Write Data ID Stage

wire Status;

//testing
//assign branch = M3[2]&AluZero3;

//wire branch;

//MODULE INSTANTIATIONS
//IF
IFSTAGE

ifTest(userinput,BranchPcMux,AdderOut3,InstMem,PcIncr);

IFIDLATCH

ifLatchTest(userinput,InstMem,PcIncr,InstMem1,PcIncr1);

//ID
IDSTAGE
idTest(InstMem1,PcIncr1,WB5[1],MuxOutReg5,WBMuxOut,WB,M,EX,IDIFPcIncr,Data1,Data2,SE,Rt,Rd);
IDEXLATCH
idLatchTest(userinput,WB,M,EX,IDIFPcIncr,Data1,Data2,SE,Rt,Rd,WB1,M1,EX1,IDIFPcIncr1,Data11,Data2
1,SE1,Rt1,Rd1);
//EX
EXSTAGE
exTest(WB1,M1,EX1,IDIFPcIncr1,Data11,Data21,SE1,Rt1,Rd1,WB2,M2,AdderOut2,AluZero2,AluOut2,Data22,
MuxOutReg2,AluCont);
EXMEMLATCH
exLatchTest(userinput,WB2,M2,AdderOut2,AluZero2,AluOut2,Data22,MuxOutReg2,WB3,M3,AdderOut3,AluZer
o3,AluOut3,Data23,MuxOutReg3);
//MEM
MEMSTAGE
memTest(WB3,M3,AdderOut3,AluZero3,AluOut3,Data23,MuxOutReg3,WB4,ReadData4,AluResult4,MuxOutReg4,B
ranchPcMux);
MEMWBLATCH
memLatchTest(userinput,WB4,ReadData4,AluResult4,MuxOutReg4,WB5,ReadData5,AluResult5,MuxOutReg5);
//WB
WBSTAGE

wbTest(WB5,ReadData5,AluResult5,WBMuxOut);

// This indicates when instruction one makes it through the pipeline.


assign Status = ~MuxOutReg5[4]&~MuxOutReg5[3]&MuxOutReg5[2]&~MuxOutReg5[1]&MuxOutReg5[0];

endmodule

Bonus:
Output Waveform:

We can see in fact we get 12 being written back to register 1 indicated by the last two waveforms.

Results:
The outputs of R1, R2, R3 from the register file:

Results from the Testbench:

Potrebbero piacerti anche