SCAR Code:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: World Domination
// Engineer: Greg Hendrickson
//
// Create Date: 23:09:34 11/03/2007
// Design Name: Pipelined CPU Stage 1
// Module Name: CPU
// Project Name: Comp Arch Final Project
// Target Devices: Desktop
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Revision 0.02 - Syntax errors fixed
// Revision 0.03 - Logical Errors Fixed
// Revision 0.04 - Rest of code understood
// Revision 0.05 - Added in and understood forwarding the a and b
// Revision 0.06 - Could not find any errors in the forwarding code
// Revision 0.07 - Added in the stalls
// Revision 0.08 - Fixed minor "no-op" syntax error
// Revision 0.09 - Found and fixed instruction forwarding error. Cant do all at end (stall fails)
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module CPU (clock,owbypassBfromMEM,owbypassAfromMEM,,ostall,obypassAfromMEM,obypassBfromMEM,obypassAfromALUinWB,obypassBfromALUinWB,obypassAfromLWinWB,obypassBfromLWinWB);
// Instruction opcodes
parameter LW = 6'b100011, SW = 6'b101011, BEQ=6'b000100, noop = 32'b00000_000000, ALUop=6'b0;
parameter A_ADD = 6''b011111,//31: add operation
A_SUB = 6'b010000,//16 subtract
A_AND = 6'b001000,//8 and
A_NADD = 6'b000111,//7 nand
A_OR = 6'b000100,//4 or
A_NOR = 6'b000011,//3 nor
A_SEQZ = 6'b000010,//2 seqz set equals
A_SLT = 6'b000001;//1 slt operation
input clock;
output owbypassBfromMEM,owbypassAfromMEM,ostall,obypassAfromMEM,obypassBfromMEM,obypassAfromALUinWB,obypassBfromALUinWB,obypassAfromLWinWB,obypassBfromLWinWB;
//output [31:0]oRegs;
reg[31:0] PC, Regs[0:31], IMemory[0:23], DMemory[0:23], // separate memories (they were 1023, i made them, 23)
IFIDIR, IDEXA, IDEXB, IDEXIR, EXMEMIR, EXMEMB,GREGREGIR, // pipeline registers
EXMEMALUOut, MEMWBValue, MEMWBIR; // pipeline registers
wire [4:0] IDEXrs, IDEXrt,EXMEMBrs,GREGrd,EXMEMBrt,IFIDrt,EXMEMrs,EXMEMrt ,IFIDrs,EXMEMrd, MEMWBrd, MEMWBrt; // Access register fields
wire [5:0] EXMEMop, MEMWBop, IDEXop; // Access opcodes
wire [31:0] Ain, Bin; // the ALU inputs
wire [31:0] viewRegs [0:31];
// declare the bypass signals
wire bypassAfromMEM, bypassAfromALUinWB,bypassBfromMEM, bypassBfromALUinWB,
bypassAfromLWinWB, bypassBfromLWinWB,stall;
// These assignment define fields from the pipeline registers
assign IFIDrs = IFIDIR[25:21]; // rs field
assign IFIDrt = IFIDIR[20:16];
assign EXMEMrs= EXMEMIR[25:21];
assign EXMEMrt= EXMEMIR[20:16];
assign EXMEMBrs= EXMEMB[25:21];
assign EXMEMBrt= EXMEMB[20:16];
assign GREGrd = GREGREGIR[15:11];
assign IDEXrs = IDEXIR[25:21]; // rs field
assign IDEXrt = IDEXIR[20:16]; // rt field //changed, was 15,11 now 20-16
assign EXMEMrd = EXMEMIR[15:11]; // rd field
assign MEMWBrd = MEMWBIR[15:11]; //rd field [changed from 20;16] TO 15;11 //double checked, yes
assign MEMWBrt = MEMWBIR[25:20]; //rt field--used for loads//the 21 was a 20 grr
assign EXMEMop = EXMEMIR[31:26]; // the opocde
assign MEMWBop = MEMWBIR[31:26]; // the opcode
assign IDEXop = IDEXIR[31:26] ; // the opcode
// Inputs to the ALU come directly from the ID/EX pipeline registers
//rot in hell (the code, not you :D )
//assign Ain = IDEXA;
//assign Bin = IDEXB;
// The bypass to input A from the MEM stage for an ALU operation
assign wbypassAfromMEM = (IDEXrs == EXMEMrd) & (IDEXrs!=0) & (EXMEMop==ALUop); // yes, bypass
// The bypass to input Bfrom the MEM stage for an ALU operation
assign wbypassBfromMEM = (IDEXrt== EXMEMrd)&(IDEXrt!=0) & (EXMEMop==ALUop); // yes, bypass
// The bypass to input A from the WB stage for an ALU operation
// The bypass to input A from the MEM stage for an ALU operation
assign bypassAfromMEM = (IDEXrs == GREGrd) & (IDEXrs!=0) & (EXMEMop==ALUop); // yes, bypass
// The bypass to input Bfrom the MEM stage for an ALU operation
assign bypassBfromMEM = (IDEXrt== GREGrd)&(IDEXrt!=0) & (EXMEMop==ALUop); // yes, bypass
// The bypass to input A from the WB stage for an ALU operation
assign bypassAfromALUinWB =0;//( IDEXrs == MEMWBrd) & (IDEXrs!=0) & (MEMWBop==ALUop);
// The bypass to input B from the WB stage for an ALU operation
assign bypassBfromALUinWB =0;// (IDEXrt==MEMWBrd) & (IDEXrt!=0) & (MEMWBop==ALUop);
// The bypass to input A from the WB stage for an LW operation
assign bypassAfromLWinWB =( IDEXrs ==MEMWBIR[20:16]) & (IDEXrs!=0) & (MEMWBop==LW);
// The bypass to input B from the WB stage for an LW operation
assign bypassBfromLWinWB = (IDEXrt==MEMWBIR[20:16]) & (IDEXrt!=0) & (MEMWBop==LW);
// The A input to the ALU is bypassed from MEM if there is a bypass there,
// Otherwise from WB if there is a bypass there, and otherwise comes from the IDEX register
assign Ain = bypassAfromMEM? MEMWBrt :
(bypassAfromALUinWB || bypassAfromLWinWB)? MEMWBValue :
wbypassAfromMEM? EXMEMALUOut:IDEXA;
// The B input to the ALU is bypassed from MEM if there is a bypass there,
// Otherwise from WB if there is a bypass there, and otherwise comes from the IDEX register
assign Bin = bypassBfromMEM? MEMWBrt :
(bypassBfromALUinWB || bypassBfromLWinWB)? MEMWBValue:
wbypassBfromMEM? EXMEMALUOut:IDEXB;
//tie them to somthing i can freaking see
assign obypassAfromMEM=bypassAfromMEM;
assign obypassBfromMEM=bypassBfromMEM;
assign obypassAfromALUinWB=bypassAfromALUinWB;
assign obypassBfromALUinWB=bypassBfromALUinWB;
assign obypassAfromLWinWB=bypassAfromLWinWB;
assign obypassBfromLWinWB=bypassBfromLWinWB;
assign owbypassBfromMEM=wbypassBfromMEM;
assign owbypassAfromMEM=wbypassAfromMEM;
//assign oRegs=Regs[31];
// The signal for detecting a stall based on the use of a result from LW
assign stall = (((MEMWBIR[31:26]==LW)||(MEMWBIR[31:26]==LW)) && // source instruction is a load
((((IDEXop==LW)||(IDEXop==SW)) && (IDEXrs==EXMEMrt)) || // stall for address calc
//(((IDEXop==LW)||(IDEXop==SW)) && ((IDEXrs==GREGrd) ||(IDEXrt==GREGrd)))| // stall for address calc
((IDEXop==ALUop) && ((IDEXrs==EXMEMrt)||(IDEXrt==EXMEMrt))))); // ALU use
assign ostall=stall;
reg [5:0] i; //used to initialize registers
initial begin
PC = 0;
IFIDIR=noop; IDEXIR=noop; EXMEMIR=noop; MEMWBIR=noop; // put no-ops in pipeline registers
for (i=0;i<=31;i=i+1) Regs[i] = i+0; //initialize registers--just so they aren?t cares
//Initiialize us up some instructumonenteseses
IMemory[0] <= 32'b00000_000000;//No op
IMemory[1] <= {ALUop,5'd2,5'd4,5'd31,5'b0,A_ADD};//ALU op, reg 2 , and reg 4, put them in reg 31, no shifting, addthems
IMemory[2] <= {ALUop,5'd3,5'd5,5'd30,5'b0,A_ADD};//ALU op, reg 3 , and reg 5, put them in reg 30, no shifting, addthems
IMemory[3] <= {ALUop,5'd9,5'd12,5'd29,5'b0,A_ADD};//ALU op, reg 9 , and reg 12, put them in reg 29, no shifting, addthems
IMemory[4] <= {ALUop,5'd31,5'd2,5'd28,5'b0,A_ADD};//ALU op, reg 31 , and reg 2, put them in reg 28, no shifting, addthems
IMemory[5] <= {ALUop,5'd28,5'd2,5'd27,5'b0,A_ADD};//ALU op, reg 28 , and reg 2, put them in reg 27, no shifting, addthems
IMemory[6] <= {ALUop,5'd27,5'd27,5'd26,5'b0,A_ADD};//ALU op, reg 27 , and reg 27, put them in reg 26, no shifting, addthems
IMemory[7] <= {SW, 5'd0, 5'd31, 16'd8}; //Storing what in r31 to memory 8(slot 2)
// about to try to test the load word stall
IMemory[8]<= {LW, 5'd0, 5'd25, 16'd12};//loading up from meme (slot 3) into reg 25
IMemory[9]<= {LW, 5'd0, 5'd24, 16'd8};//loading up from meme (what we just stored) (slot 2) into reg 24
IMemory[10] <= {ALUop,5'd24,5'd2,5'd23,5'b0,A_ADD};//ALU op, reg 24(stall) , and reg 2, put them in reg 23, no shifting, addthems
//Demoing a little bit of fancy code
IMemory[11] <= {ALUop,5'd5,5'd5,5'd5,5'b0,A_ADD};//ALU op, reg 2 , and reg 2, put them in reg 22, no shifting, addthems
IMemory[12] <= {ALUop,5'd5,5'd5,5'd5,5'b0,A_ADD};//ALU op, reg 22 , and reg 2, put them in reg 22, no shifting, addthems
IMemory[13] <= {ALUop,5'd5,5'd5,5'd5,5'b0,A_ADD};//ALU op, reg 22 , and reg 2, put them in reg 22, no shifting, addthems
for (i=14;i<=31;i=i+1) IMemory[i] = noop; //initialize registers--just so they aren?t cares
for (i=0;i<=31;i=i+1) DMemory[i] = i+100;
// Add stimulus here
end
always @ (posedge clock) begin
// Remember that ALL these actions happen every pipestage and with the use of <= they happen in parallel!
// first instruction in the pipeline is being fetched
if (~stall) begin // the first three pipeline stages stall if there is a load hazard
IFIDIR <= IMemory[PC>>2];
PC <= PC + 4;
//end // Fetch & increment PC
// second instruction in pipeline is fetching registers
IDEXA <= Regs[IFIDIR[25:21]]; IDEXB <= Regs[IFIDIR[20:16]]; // get two registers
// third instruction is doing address calculation or ALU operation
if ((IDEXop==LW) |(IDEXop==SW)) // address calculation
EXMEMALUOut <= IDEXA +{{16{IDEXIR[15]}}, IDEXIR[15:0]};
else if (IDEXop==ALUop) case (IDEXIR[5:0]) //case for the various R-type instructions
31: EXMEMALUOut <= Ain + Bin; //add operation
16: EXMEMALUOut <= Ain - Bin; //subtract operation
8: EXMEMALUOut <= Ain & Bin; //and operation
7: EXMEMALUOut <= ~(Ain & Bin); //nadd operation
4: EXMEMALUOut <= Ain | Bin; //or operation
3: EXMEMALUOut <= ~(Ain | Bin); //nor operation
2: EXMEMALUOut <= ((Ain - Bin)==0)?1:0; //seqz operation
1: EXMEMALUOut <= Ain < Bin ? 1:0; //slt operation
5: EXMEMALUOut <= Ain * Bin;
default: ; //other R-type operations: subtract, SLT, etc.
endcase
IDEXIR <= IFIDIR; EXMEMIR <= IDEXIR; EXMEMB <= IDEXB;// passing along instructions
end
else EXMEMIR <= noop; //Freeze first three stages of pipeline; inject a nop into the EX output
//Mem stage of pipeline
if (EXMEMop==ALUop)
MEMWBValue <= EXMEMALUOut; //pass along ALU result
else if (EXMEMop == LW)
MEMWBValue <= DMemory[EXMEMALUOut>>2];
else if (EXMEMop == SW)
DMemory[EXMEMALUOut>>2] <=EXMEMB; //store [from top, it is 15:0)stage3
// the WB stage
if ((MEMWBop==ALUop) & (MEMWBrd != 0)) // update registers if ALU operation and destination not 0
Regs[MEMWBrd] <= MEMWBValue; // ALU operation
else if ((MEMWBop == LW)& (MEMWBrt != 0)) // Update registers if load and destination not 0//was emememop
Regs[MEMWBIR[20:16]]<=MEMWBValue;
//Regs[MEMWBrt] <= MEMWBValue;
MEMWBIR <= EXMEMIR; GREGREGIR<=MEMWBIR;//pass along
end
endmodule
and the test bench