From 25a46a0df887feac9e7430b865abadba2c52be37 Mon Sep 17 00:00:00 2001 From: RossTheRoss Date: Wed, 16 Dec 2020 07:25:14 -0600 Subject: start MP2 --- ee4363/mp2/mipspipe_mp2.v | 125 +++++++++++++++++++++++++++++++++++++++++ ee4363/mp2/test_mipspipe_mp2.v | 53 +++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 ee4363/mp2/mipspipe_mp2.v create mode 100644 ee4363/mp2/test_mipspipe_mp2.v diff --git a/ee4363/mp2/mipspipe_mp2.v b/ee4363/mp2/mipspipe_mp2.v new file mode 100644 index 0000000..2e8b98b --- /dev/null +++ b/ee4363/mp2/mipspipe_mp2.v @@ -0,0 +1,125 @@ +// Incomplete behavioral model of MIPS pipeline + +module mipspipe_mp2 (clock); + // in_out + input clock; + + // Instruction opcodes + parameter LW = 6'b100011, SW = 6'b101011, BEQ = 6'b000100, nop = 32'b00000_100000, ALUop = 6'b0; + reg [31:0] PC, Regs[0:31], IMemory[0:1023], DMemory[0:1023], // instruction and data memories + IFIDIR, IDEXA, IDEXB, IDEXIR, EXMEMIR, EXMEMB, // pipeline latches + EXMEMALUOut, MEMWBValue, MEMWBIR; + + wire [4:0] IDEXrs, IDEXrt, EXMEMrd, MEMWBrd, MEMWBrt; // hold register fields + wire [5:0] EXMEMop, MEMWBop, IDEXop; // hold opcodes + wire [31:0] Ain, Bin; // ALU inputs + + // declare the bypass signals + wire bypassAfromMEM, bypassAfromALUinWB, bypassBfromMEM, bypassBfromALUinWB, bypassAfromLWinWB, bypassBfromLWinWB; + + // Define fields of pipeline latches + assign IDEXrs = IDEXIR[25:21]; // rs field + assign IDEXrt = IDEXIR[20:16]; // rt field + assign EXMEMrd = EXMEMIR[15:11]; // rd field + assign MEMWBrd = MEMWBIR[15:11]; // rd field + assign MEMWBrt = MEMWBIR[20:16]; // rt field -- for loads + assign EXMEMop = EXMEMIR[31:26]; // opcode + assign MEMWBop = MEMWBIR[31:26]; // opcode + assign IDEXop = IDEXIR[31:26]; // opcode + + + // The bypass to input A from the MEM stage for an ALU operation + assign bypassAfromMEM = (IDEXrs == EXMEMrd) & (IDEXrs!=0) & (EXMEMop==ALUop); + // The bypass to input B from the MEM stage for an ALU operation + assign bypassBfromMEM = 0; + // The bypass to input A from the WB stage for an ALU operation + assign bypassAfromALUinWB = 0; + // The bypass to input B from the WB stage for an ALU operation + assign bypassBfromALUinWB = 0; + // 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 = 0; + + // 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? EXMEMALUOut : (bypassAfromALUinWB | bypassAfromLWinWB)? MEMWBValue : 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 = IDEXB; + + + reg [5:0] i; // used to initialize latches + reg [10:0] j,k; // used to initialize memories + + initial begin + PC = 0; + IFIDIR = nop; + IDEXIR = nop; + EXMEMIR = nop; + MEMWBIR = nop; // no-ops in pipeline latches + + for (i = 0;i<=31;i = i+1) Regs[i] = i; // initialize latches + + IMemory[0] = 32'h00412820; + IMemory[1] = 32'h8ca30004; + IMemory[2] = 32'haca70005; + IMemory[3] = 32'h00602020; + IMemory[4] = 32'h01093020; + IMemory[5] = 32'hac06000c; + IMemory[6] = 32'h00c05020; + IMemory[7] = 32'h8c0b0010; + IMemory[8] = 32'h00000020; + IMemory[9] = 32'h002b6020; + for (j=10; j<=1023; j=j+1) IMemory[j] = nop; + + DMemory[0] = 32'h00000000; + DMemory[1] = 32'hffffffff; + DMemory[2] = 32'h00000000; + DMemory[3] = 32'h00000000; + DMemory[4] = 32'hfffffffe; + for (k=5; k<=1023; k=k+1) DMemory[k] = 0; + end + + always @ (posedge clock) + begin + + // FETCH: Fetch instruction & update PC + IFIDIR <= IMemory[PC>>2]; + PC <= PC + 4; + + // DECODE: Read registers + IDEXA <= Regs[IFIDIR[25:21]]; + IDEXB <= Regs[IFIDIR[20:16]]; + IDEXIR <= IFIDIR; + + // EX: Address calculation or ALU operation + if ((IDEXop==LW) |(IDEXop==SW)) // address calculation & copy B + EXMEMALUOut <= Ain +{{16{IDEXIR[15]}}, IDEXIR[15:0]}; + else if (IDEXop==ALUop) begin + case (IDEXIR[5:0]) // R-type instruction + 32: EXMEMALUOut <= Ain + Bin; // add operation + default: ; // other R-type operations: subtract, SLT, etc. + endcase + end + + EXMEMIR <= IDEXIR; + EXMEMB <= Bin; // pass along the IR & B register + + // MEM + 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 + + MEMWBIR <= EXMEMIR; // pass along IR + + // WB + if ((MEMWBop==ALUop) & (MEMWBrd != 0)) // update latches if ALU operation and destination not 0 + Regs[MEMWBrd] <= MEMWBValue; // ALU operation + else if ((MEMWBop == LW)& (MEMWBrt != 0)) // Update latches if load and destination not 0 + Regs[MEMWBrt] <= MEMWBValue; + end + +endmodule + diff --git a/ee4363/mp2/test_mipspipe_mp2.v b/ee4363/mp2/test_mipspipe_mp2.v new file mode 100644 index 0000000..f184011 --- /dev/null +++ b/ee4363/mp2/test_mipspipe_mp2.v @@ -0,0 +1,53 @@ +// +// Test bench for the mipspipe +// Boram Lee +// + +`include "mipspipe_mp2.v" + +module test_mipspipe; + + reg clock; + reg [3:0] clock_cycle; + +// instantiate pipeline module + mipspipe_mp2 u_mipspipe_mp2(clock); + +// initialize clock and cycle counter + initial begin + clock = 0; + clock_cycle=4'h0; + #160 $finish; + end + +// 10 unit clock cycle + always + #5 clock = ~clock; + + always @(posedge clock) + begin + clock_cycle=clock_cycle+1; + end + + +// display contents of pipeline latches at the end of each clock cycle + always @(negedge clock) + begin + $display("\n\nclock cycle = %d",clock_cycle," (time = %1.0t)",$time); + $display("IF/ID registers\n\t IF/ID.PC+4 = %h, IF/ID.IR = %h \n", u_mipspipe_mp2.PC, u_mipspipe_mp2.IFIDIR); + $display("ID/EX registers\n\t ID/EX.rs = %d, ID/EX.rt = %d",u_mipspipe_mp2.IDEXrs,u_mipspipe_mp2.IDEXrt,"\n\t ID/EX.A = %h, ID/EX.B = %h",u_mipspipe_mp2.IDEXA,u_mipspipe_mp2.IDEXB); + $display("\t ID/EX.op = %h\n",u_mipspipe_mp2.IDEXop); + $display("EX/MEM registers\n\t EX/MEM.rs = %d, EX/MEM.rt = %d",u_mipspipe_mp2.IDEXrs,u_mipspipe_mp2.IDEXrt,"\n\t EX/MEM.ALUOut = %h, EX/MEM.ALUout = %h",u_mipspipe_mp2.EXMEMALUOut,u_mipspipe_mp2.EXMEMB); + $display("\t EX/MEM.op = %h\n",u_mipspipe_mp2.EXMEMop); + $display("MEM/WB registers\n\t MEM/WB.rd = %d, MEM/WB.rt = %d",u_mipspipe_mp2.MEMWBrd,u_mipspipe_mp2.MEMWBrt,"\n\t MEM/WB.value = %h",u_mipspipe_mp2.MEMWBValue); + $display("\t EX/MEM.op = %h\n",u_mipspipe_mp2.MEMWBop); + end + +// log to a vcd (variable change dump) file + initial + begin + $dumpfile("test_mipspipe.vcd"); + $dumpvars; + end + +endmodule -- cgit v1.2.3