Fixed initialisation bug and compilation error in gatereg module. Added mips_pipelined to test suite. Fixed several bugs in assignment3 MIPS module
This commit is contained in:
4 files changed
+154
-29
No files matched your search
+30
-26
@@ -15,7 +15,7 @@
|
|||||||
`include "seven_seg_4digit.sv"
|
`include "seven_seg_4digit.sv"
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
module assignment3 #(width, romsz, ramsz)(
|
module assignment3 #(width=5, romsz=9, ramsz=10)(
|
||||||
input logic [0:0] clk, input logic [0:0] rst
|
input logic [0:0] clk, input logic [0:0] rst
|
||||||
`ifdef QUARTUS_SYNTH
|
`ifdef QUARTUS_SYNTH
|
||||||
,
|
,
|
||||||
@@ -29,21 +29,23 @@ module assignment3 #(width, romsz, ramsz)(
|
|||||||
output logic[7:0] out_seg_3
|
output logic[7:0] out_seg_3
|
||||||
`endif
|
`endif
|
||||||
);
|
);
|
||||||
|
logic [31:0] regs_out [32];
|
||||||
|
|
||||||
logic [2**width-1:0] pc_addr, pc_addr_2;
|
logic [2**width-1:0] pc_addr, pc_addr_2;
|
||||||
logic [2**width-1:0] pc_addr_write;
|
logic [2**width-1:0] pc_addr_write;
|
||||||
logic [0:0] pc_we;
|
logic [0:0] pc_we;
|
||||||
// TODO: Verify if we need a clk gating on pc_addr
|
// TODO: Verify if we need a clk gating on pc_addr
|
||||||
instruction_counter #(width) PC (clk, rst, pc_we, pc_addr_write, pc_addr);
|
instruction_counter #(width) PC (clk, rst, pc_we, pc_addr_write, pc_addr);
|
||||||
gatereg #(width, 2) gate_pc_addr(clk, rst, 1, pc_addr, pc_addr_2);
|
gatereg #(width, 2) gate_pc_addr_1(clk, rst, 1'b1, pc_addr, pc_addr_2);
|
||||||
|
|
||||||
|
|
||||||
logic [2**width-1:0] rom_rd;
|
logic [2**width-1:0] rom_rd;
|
||||||
logic [2**width-1:0] rom_addr;
|
logic [2**width-1:0] rom_addr;
|
||||||
logic [2**width-1:0] instruction, instruction_1;
|
logic [2**width-1:0] instruction, instruction_1;
|
||||||
rom #(romsz, width) ROM (rom_addr, rom_rd);
|
rom #(romsz, width) ROM (rom_addr[romsz-1:0], rom_rd);
|
||||||
gatereg #(width, 1) gate_pc_addr(clk, rst, 1, pc_addr, rom_addr);
|
gatereg #(width, 1) gate_pc_addr(clk, rst, 1'b1, pc_addr, rom_addr);
|
||||||
gatereg #(width, 1) gate_instruction(clk, rst, 1, rom_rd, instruction);
|
gatereg #(width, 1) gate_instruction(clk, rst, 1'b1, rom_rd, instruction);
|
||||||
gatereg #(width, 1) gate_instruction_1(clk, rst, 1, instruction, instruction_1);
|
gatereg #(width, 1) gate_instruction_1(clk, rst, 1'b1, instruction, instruction_1);
|
||||||
|
|
||||||
|
|
||||||
logic [0:0] cu_m2r, cu_m2w, cu_b, cu_alu_src, cu_rdst, cu_rw;
|
logic [0:0] cu_m2r, cu_m2w, cu_b, cu_alu_src, cu_rdst, cu_rw;
|
||||||
@@ -52,56 +54,58 @@ module assignment3 #(width, romsz, ramsz)(
|
|||||||
control_unit CONTROL_UNIT (instruction[31:26], instruction[5:0],
|
control_unit CONTROL_UNIT (instruction[31:26], instruction[5:0],
|
||||||
cu_m2r, cu_m2w, cu_b, cu_alu_fn, cu_alu_src, cu_rdst, cu_rw
|
cu_m2r, cu_m2w, cu_b, cu_alu_fn, cu_alu_src, cu_rdst, cu_rw
|
||||||
);
|
);
|
||||||
gatereg #(0, 1) gate_cu_rdst (clk, rst, 1, cu_rdst, RDST);
|
gatereg #(0, 1) gate_cu_rdst (clk, rst, 1'b1, cu_rdst, RDST);
|
||||||
gatereg #(0, 1) gate_cu_alu_src (clk, rst, 1, cu_alu_src, ALU_SRC);
|
gatereg #(0, 1) gate_cu_alu_src (clk, rst, 1'b1, cu_alu_src, ALU_SRC);
|
||||||
gatereg #(2, 1) gate_cu_alu_fn (clk, rst, 1, cu_alu_fn, ALU_FN);
|
gatereg #(2, 1) gate_cu_alu_fn (clk, rst, 1'b1, cu_alu_fn, ALU_FN);
|
||||||
|
|
||||||
gatereg #(0, 2) gate_cu_b (clk, rst, 1, cu_b, B);
|
gatereg #(0, 2) gate_cu_b (clk, rst, 1'b1, cu_b, B);
|
||||||
gatereg #(0, 2) gate_cu_m2w (clk, rst, 1, cu_m2w, MEM_WE);
|
gatereg #(0, 2) gate_cu_m2w (clk, rst, 1'b1, cu_m2w, MEM_WE);
|
||||||
|
|
||||||
gatereg #(0, 3) gate_cu_rw (clk, rst, 1, cu_rw, REG_WE);
|
gatereg #(0, 3) gate_cu_rw (clk, rst, 1'b1, cu_rw, REG_WE);
|
||||||
gatereg #(0, 3) gate_cu_m2r (clk, rst, 1, cu_m2r, REGW_MEM_OR_RD);
|
gatereg #(0, 3) gate_cu_m2r (clk, rst, 1'b1, cu_m2r, REGW_MEM_OR_RD);
|
||||||
|
|
||||||
logic [2**width-1:0] regf_rs, regf_rs_1;
|
logic [2**width-1:0] regf_rs, regf_rs_1;
|
||||||
logic [2**width-1:0] regf_rt, regf_rt_1, regf_rt_2;
|
logic [2**width-1:0] regf_rt, regf_rt_1, regf_rt_2;
|
||||||
logic [7:0] regf_a3, regf_a3_2;
|
logic [7:0] regf_a3, regf_a3_2;
|
||||||
assign rd = (REGW_MEM_OR_RD) ? rd_mem : alu_out_2;
|
logic [2**width-1:0] rd, rd_mem, rd_alu;
|
||||||
|
assign rd = (REGW_MEM_OR_RD) ? rd_mem : rd_alu;
|
||||||
assign regf_a3 = (RDST) ? instruction_1[15:11] : instruction_1[20:16];
|
assign regf_a3 = (RDST) ? instruction_1[15:11] : instruction_1[20:16];
|
||||||
// TODO: Connect inputs
|
// TODO: Connect inputs
|
||||||
gatereg #(3, 2) gate_regf_a3 (clk, rst, 1, regf_a3, regf_a3_2);
|
gatereg #(3, 2) gate_regf_a3 (clk, rst, 1'b1, regf_a3, regf_a3_2);
|
||||||
register_file #(width, 5) REGS (
|
register_file #(width, 5) REGS (
|
||||||
~clk, REG_WE,
|
~clk, REG_WE,
|
||||||
regf_a3_2 & 8'b00011111, rd,
|
regf_a3_2[4:0], rd,
|
||||||
instruction[25:21], regf_rs,
|
instruction[25:21], regf_rs,
|
||||||
instruction[20:16], regf_rt,
|
instruction[20:16], regf_rt,
|
||||||
regs_out
|
regs_out
|
||||||
);
|
);
|
||||||
gatereg #(width, 1) gate_regf_rs(clk, rst, 1, regf_rs, regf_rs_1);
|
gatereg #(width, 1) gate_regf_rs(clk, rst, 1'b1, regf_rs, regf_rs_1);
|
||||||
gatereg #(width, 1) gate_regf_rt(clk, rst, 1, regf_rt, regf_rt_1);
|
gatereg #(width, 1) gate_regf_rt(clk, rst, 1'b1, regf_rt, regf_rt_1);
|
||||||
gatereg #(width, 1) gate_regf_rt_1(clk, rst, 1, regf_rt_1, regf_rt_2);
|
gatereg #(width, 1) gate_regf_rt_1(clk, rst, 1'b1, regf_rt_1, regf_rt_2);
|
||||||
|
|
||||||
logic [2**width-1:0] sign_ext_imm, rt_imm;
|
logic [2**width-1:0] sign_ext_imm, rt_imm;
|
||||||
sign_extender #(4, width) SIGNEXT(1'b1, instruction[15:0], sign_ext_imm);
|
sign_extender #(4, width) SIGNEXT(1'b1, instruction[15:0], sign_ext_imm);
|
||||||
gatereg #(width, 1) gate_sign_ext_imm(clk, rst, 1, sign_ext_imm, rt_imm);
|
gatereg #(width, 1) gate_sign_ext_imm(clk, rst, 1'b1, sign_ext_imm, rt_imm);
|
||||||
|
|
||||||
|
|
||||||
logic [2**width-1:0] alu_out, alu_out_1, alu_out_2;
|
logic [2**width-1:0] alu_out, alu_out_1, alu_out_2;
|
||||||
logic [3:0] alu_flags, alu_flags_1;
|
logic [3:0] alu_flags, alu_flags_1;
|
||||||
alu #(width) ALU (ALU_FN, regf_rs_1, (ALU_SRC) ? rt_imm : regf_rt_1, rd_alu, alu_flags);
|
alu #(width) ALU (ALU_FN, regf_rs_1, (ALU_SRC) ? rt_imm : regf_rt_1, alu_out, alu_flags);
|
||||||
gatereg #(width, 1) gate_alu_out (clk, rst, 1, alu_out, alu_out_1);
|
gatereg #(width, 1) gate_alu_out (clk, rst, 1'b1, alu_out, alu_out_1);
|
||||||
gatereg #(width, 1) gate_alu_out_1 (clk, rst, 1, alu_out_1, alu_out_2);
|
gatereg #(width, 1) gate_alu_out_1 (clk, rst, 1'b1, alu_out_1, alu_out_2);
|
||||||
gatereg #(width, 1) gate_alu_flags (clk, rst, 1, alu_flags, alu_flags_1);
|
gatereg #(width, 1) gate_alu_flags (clk, rst, 1'b1, alu_flags, alu_flags_1);
|
||||||
|
assign rd_alu = alu_out_2;
|
||||||
|
|
||||||
logic [2**width-1:0] new_pc_addr, new_pc_addr_1;
|
logic [2**width-1:0] new_pc_addr, new_pc_addr_1;
|
||||||
assign new_pc_addr = (rt_imm << 2) + pc_addr_2;
|
assign new_pc_addr = (rt_imm << 2) + pc_addr_2;
|
||||||
gatereg #(width, 1) gate_new_pc_addr (clk, rst, 1, new_pc_addr, new_pc_addr_1);
|
gatereg #(width, 1) gate_new_pc_addr (clk, rst, 1'b1, new_pc_addr, new_pc_addr_1);
|
||||||
|
|
||||||
|
|
||||||
assign pc_addr_write = new_pc_addr_1;
|
assign pc_addr_write = new_pc_addr_1;
|
||||||
assign pc_we = B & alu_flags_1[2];
|
assign pc_we = B & alu_flags_1[2];
|
||||||
logic [2**width-1:0] mem_out, mem_out_1;
|
logic [2**width-1:0] mem_out, mem_out_1;
|
||||||
ram #(ramsz, width) RAM (clk, rst, alu_out_1, MEM_WE, regf_rt_2, mem_out);
|
ram #(ramsz, width) RAM (clk, rst, alu_out_1, MEM_WE, regf_rt_2, mem_out);
|
||||||
gatereg #(width, 1) gate_mem_out (clk, rst, 1, mem_out, mem_out_1);
|
gatereg #(width, 1) gate_mem_out (clk, rst, 1'b1, mem_out, mem_out_1);
|
||||||
assign rd_mem = mem_out_1;
|
assign rd_mem = mem_out_1;
|
||||||
endmodule
|
endmodule
|
||||||
`endif
|
`endif
|
||||||
+5
-3
@@ -1,5 +1,5 @@
|
|||||||
module gatereg #(width, ndelay=1)(
|
module gatereg #(width, ndelay=1)(
|
||||||
input logic [0:0] clk, input logic [0:0] rst, input logic en[0:0],
|
input logic [0:0] clk, input logic [0:0] rst, input logic [0:0] en,
|
||||||
input logic [2**width-1:0] in, output logic [2**width-1:0] out
|
input logic [2**width-1:0] in, output logic [2**width-1:0] out
|
||||||
);
|
);
|
||||||
logic [2**width-1:0] hold_value[ndelay];
|
logic [2**width-1:0] hold_value[ndelay];
|
||||||
@@ -7,10 +7,12 @@ module gatereg #(width, ndelay=1)(
|
|||||||
assign out = hold_value[ndelay-1];
|
assign out = hold_value[ndelay-1];
|
||||||
always_ff @( posedge clk ) begin
|
always_ff @( posedge clk ) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
hold_value <= {(2**width){0}};
|
for (integer i = 0; i < ndelay; ++i) begin
|
||||||
|
hold_value[i] <= {(2**width){1'b0}};
|
||||||
|
end
|
||||||
end else if (en) begin
|
end else if (en) begin
|
||||||
hold_value[0] <= in;
|
hold_value[0] <= in;
|
||||||
for (int i = 1; i < ndelay; ++i) begin
|
for (integer i = 1; i < ndelay; ++i) begin
|
||||||
hold_value[i] <= hold_value[i-1];
|
hold_value[i] <= hold_value[i-1];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
`include "assignment3.sv"
|
||||||
|
|
||||||
|
`timescale 1us/10ns
|
||||||
|
|
||||||
|
`define PRINT_REGISTERS(regs)\
|
||||||
|
$display("\tt0-t8: \t0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x\n\ts0-s8: \t0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x\n",\
|
||||||
|
regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15], \
|
||||||
|
regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23] \
|
||||||
|
);
|
||||||
|
`define TEST_CHECK(cond) if (cond) begin end else begin \
|
||||||
|
$display("Check %s failed", `"cond`"); \
|
||||||
|
`PRINT_REGISTERS(CPU.REGS.regs); \
|
||||||
|
num_errors += 1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
module mips_pipelined_tb();
|
||||||
|
logic [0:0] clk;
|
||||||
|
logic [0:0] rst;
|
||||||
|
assignment3 CPU (clk, rst);
|
||||||
|
|
||||||
|
initial clk = 0;
|
||||||
|
initial rst = 0;
|
||||||
|
always #1 clk = ~clk;
|
||||||
|
|
||||||
|
integer num_errors = 0;
|
||||||
|
initial begin
|
||||||
|
rst = 1;
|
||||||
|
#2;
|
||||||
|
rst = 0;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
$display("Beginning Pipelined MIPS tests");
|
||||||
|
|
||||||
|
#8; // 4x steps to allow pipeline to fill up
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[8] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[9] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[10] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[11] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[9] == 32'd7);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.RAM.mem[0] == 32'd7);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[10] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[11] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[12] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[10] == 32'd7);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[11] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[12] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[13] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[11] == (CPU.REGS.regs[10] + CPU.REGS.regs[11]) );
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[11] == 32'd14);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[12] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[13] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[14] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[12] == (CPU.REGS.regs[9] - CPU.REGS.regs[11]));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[12] == -32'sd7);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[13] == (CPU.REGS.regs[9] + 3) );
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[13] == 32'd10);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[14] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[15] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[16] == 32'd0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[14] == (CPU.REGS.regs[12] + CPU.REGS.regs[13]));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[14] == 32'd3);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[16] == (CPU.REGS.regs[9] & CPU.REGS.regs[13]));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[16] == 32'd2);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[17] == (CPU.REGS.regs[9] | CPU.REGS.regs[13]));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[17] == 32'd15);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[18] == (CPU.REGS.regs[9] ^ CPU.REGS.regs[13]));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[18] == 32'd13);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[19] == ~(CPU.REGS.regs[9] | CPU.REGS.regs[13]));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[19] == 32'hfffffff0);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[20] == ( $signed(CPU.REGS.regs[12]) < $signed(CPU.REGS.regs[14]) ));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[20] == 32'd1);
|
||||||
|
#2;
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[20] == ( CPU.REGS.regs[12] < CPU.REGS.regs[14] ));
|
||||||
|
`TEST_CHECK(CPU.REGS.regs[20] == 32'd0);
|
||||||
|
|
||||||
|
// TODO: Verify program never branches
|
||||||
|
#2;
|
||||||
|
#2;
|
||||||
|
#2;
|
||||||
|
#2;
|
||||||
|
|
||||||
|
// TODO: Verify final program register state
|
||||||
|
|
||||||
|
|
||||||
|
if (num_errors == 0) begin $display("\x1b[38;5;10mAll pipelined MIPS tests passing\x1b[m");
|
||||||
|
end else begin $display("\x1b[38;5;9m%0d Single-cycle pipelined test(s) failing\x1b[m", num_errors); end
|
||||||
|
|
||||||
|
$dumpflush;
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -5,3 +5,4 @@
|
|||||||
`include "tests/shifter_tb.sv"
|
`include "tests/shifter_tb.sv"
|
||||||
`include "tests/alu_tb.sv"
|
`include "tests/alu_tb.sv"
|
||||||
`include "tests/mips_singlecycle.sv"
|
`include "tests/mips_singlecycle.sv"
|
||||||
|
`include "tests/mips_pipelined.sv"
|
||||||
Reference in new issue
Block a user