Added progsrc string parameter for the hazard and nohazard testbenches to be able to specify what program to run. Added hazard unit and connected it up. Modified pipeline gate/sync registers to disable and/or reset when the hazard unit requests it.
Modified ALU inputs to allow the hazard unit to route a just-completed calculation back around.
This commit is contained in:
1 file changed
+92
-45
+92
-45
@@ -12,52 +12,89 @@
|
|||||||
`include "gatereg.sv"
|
`include "gatereg.sv"
|
||||||
`include "hazard_unit.sv"
|
`include "hazard_unit.sv"
|
||||||
|
|
||||||
module assignment3 #(width=5, romsz=9, ramsz=10)(
|
module assignment3 #(string progsrc, 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
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [31:0] regs_out [32];
|
logic [31:0] regs_out [32];
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
logic [0:0] hazard_m2r_0, hazard_m2r_1, hazard_m2r_2;
|
||||||
|
logic [0:0] hazard_reg_we_1, hazard_reg_we_2, hazard_reg_we_3;
|
||||||
|
logic [0:0] hazard_branch_taken, hazard_jump_taken;
|
||||||
|
logic [4:0] hazard_rt_0, hazard_rt_1;
|
||||||
|
logic [4:0] hazard_rs_0, hazard_rs_1;
|
||||||
|
logic [4:0] hazard_write_reg_0, hazard_write_reg_1, hazard_write_reg_2;
|
||||||
|
// Outputs
|
||||||
|
logic [1:0] hazard_forwardAE, hazard_forwardBE;
|
||||||
|
logic [0:0] hazard_forwardAD, hazard_forwardBD;
|
||||||
|
logic [0:0] hazard_stallF, hazard_stallD;
|
||||||
|
logic [0:0] hazard_flushE, hazard_flushD;
|
||||||
|
hazard_unit hazard_unit(
|
||||||
|
hazard_m2r_1, hazard_rt_1, hazard_rs_1,
|
||||||
|
hazard_reg_we_1, hazard_write_reg_0, /*>Missing*/ hazard_m2r_1,
|
||||||
|
hazard_reg_we_2, hazard_write_reg_1, /*>Missing*/ hazard_m2r_2,
|
||||||
|
hazard_reg_we_3, hazard_write_reg_2, // MISSING,
|
||||||
|
hazard_m2r_0 /* MISSING */, hazard_rs_0, hazard_rt_0,
|
||||||
|
hazard_branch_taken, hazard_jump_taken, // NOTE: We aren't doing branch prediction. Can just be control unit branch
|
||||||
|
hazard_forwardAE, hazard_forwardBE,
|
||||||
|
hazard_forwardAD, hazard_forwardBD, // MISSING
|
||||||
|
hazard_stallF, hazard_stallD,
|
||||||
|
hazard_flushE, hazard_flushD
|
||||||
|
);
|
||||||
|
|
||||||
logic [2**width-1:0] pc_addr, pc_addr_1, pc_addr_2;
|
logic [2**width-1:0] pc_addr, pc_addr_1, 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
|
instruction_counter #(width) PC (clk, rst, ~hazard_stallF, pc_we, pc_addr_write, pc_addr);
|
||||||
instruction_counter #(width) PC (clk, rst, 1'b1, pc_we, pc_addr_write, pc_addr);
|
gatereg #(width, 1) gate_pc_addr(clk, rst, ~hazard_stallF, pc_addr, pc_addr_1); // TODO: Verify if this needs to exist
|
||||||
gatereg #(width, 1) gate_pc_addr(clk, rst, 1'b1, pc_addr, pc_addr_1);
|
gatereg #(width, 1) gate_pc_addr_1(clk, rst | (hazard_branch_taken | hazard_jump_taken), ~hazard_stallD, pc_addr_1, pc_addr_2);
|
||||||
gatereg #(width, 1) gate_pc_addr_1(clk, rst, 1'b1, pc_addr_1, pc_addr_2);
|
|
||||||
|
|
||||||
|
|
||||||
logic [2**width-1:0] rom_rd;
|
logic [2**width-1:0] rom_rd;
|
||||||
logic [2**width-1:0] instruction, instruction_1;
|
logic [2**width-1:0] instruction, instruction_1;
|
||||||
rom #("./asm/bin/ELEC4720-2026s2-Ass-03-NoHazardsDemo.hex", romsz, width) ROM (pc_addr_1[romsz-1:0], rom_rd);
|
rom #(progsrc, romsz, width) ROM (pc_addr_1[romsz-1:0], rom_rd);
|
||||||
gatereg #(width, 1) gate_instruction(clk, rst, 1'b1, rom_rd, instruction);
|
gatereg #(width, 1) gate_instruction(clk, rst | (hazard_branch_taken | hazard_jump_taken), ~hazard_stallD, rom_rd, instruction);
|
||||||
gatereg #(width, 1) gate_instruction_1(clk, rst, 1'b1, instruction, instruction_1);
|
gatereg #(width, 1) gate_instruction_1(clk, rst | hazard_flushE, 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_alu_src, cu_rdst, cu_rw;
|
||||||
|
logic [0:0] cu_m2w_1, cu_rw_1, cu_m2r_1;
|
||||||
|
logic [0:0] cu_m2r_2, cu_rw_2;
|
||||||
logic [3:0] cu_alu_fn, ALU_FN;
|
logic [3:0] cu_alu_fn, ALU_FN;
|
||||||
logic [0:0] B, MEM_WE, RDST, ALU_SRC, REG_WE, REGW_MEM_OR_RD;
|
logic [0:0] B, MEM_WE, RDST, ALU_SRC, REG_WE, REGW_MEM_OR_RD;
|
||||||
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, B, cu_alu_fn, cu_alu_src, cu_rdst, cu_rw
|
||||||
);
|
);
|
||||||
gatereg #(0, 1) gate_cu_rdst (clk, rst, 1'b1, cu_rdst, RDST);
|
gatereg #(0, 1) gate_cu_rdst (clk, rst | hazard_flushE, 1'b1, cu_rdst, RDST);
|
||||||
gatereg #(0, 1) gate_cu_alu_src (clk, rst, 1'b1, cu_alu_src, ALU_SRC);
|
gatereg #(0, 1) gate_cu_alu_src (clk, rst | hazard_flushE, 1'b1, cu_alu_src, ALU_SRC);
|
||||||
gatereg #(2, 1) gate_cu_alu_fn (clk, rst, 1'b1, cu_alu_fn, ALU_FN);
|
gatereg #(2, 1) gate_cu_alu_fn (clk, rst | hazard_flushE, 1'b1, cu_alu_fn, ALU_FN);
|
||||||
|
gatereg #(0, 1) gate_cu_m2w(clk, rst | hazard_flushE, 1'b1, cu_m2w, cu_m2w_1);
|
||||||
|
gatereg #(0, 1) gate_cu_rw(clk, rst | hazard_flushE, 1'b1, cu_rw, cu_rw_1);
|
||||||
|
gatereg #(0, 1) gate_cu_m2r(clk, rst | hazard_flushE, 1'b1, cu_m2r, cu_m2r_1);
|
||||||
|
|
||||||
gatereg #(0, 2) gate_cu_b (clk, rst, 1'b1, cu_b, B);
|
gatereg #(0, 1) gate_cu_m2r_1 (clk, rst, 1'b1, cu_m2r_1, cu_m2r_2);
|
||||||
gatereg #(0, 2) gate_cu_m2w (clk, rst, 1'b1, cu_m2w, MEM_WE);
|
gatereg #(0, 1) gate_cu_m2r_2 (clk, rst, 1'b1, cu_m2r_2, REGW_MEM_OR_RD);
|
||||||
|
|
||||||
gatereg #(0, 3) gate_cu_rw (clk, rst, 1'b1, cu_rw, REG_WE);
|
gatereg #(0, 1) gate_cu_m2w_1 (clk, rst, 1'b1, cu_m2w_1, MEM_WE);
|
||||||
gatereg #(0, 3) gate_cu_m2r (clk, rst, 1'b1, cu_m2r, REGW_MEM_OR_RD);
|
|
||||||
|
gatereg #(0, 1) gate_cu_rw_1 (clk, rst, 1'b1, cu_rw_1, cu_rw_2);
|
||||||
|
gatereg #(0, 1) gate_cu_rw_2 (clk, rst, 1'b1, cu_rw_2, REG_WE);
|
||||||
|
|
||||||
|
assign hazard_m2r_0 = cu_m2r_1;
|
||||||
|
assign hazard_m2r_1 = cu_m2r_2;
|
||||||
|
assign hazard_m2r_2 = REGW_MEM_OR_RD;
|
||||||
|
assign hazard_reg_we_1 = cu_rw_1;
|
||||||
|
assign hazard_reg_we_2 = cu_rw_2;
|
||||||
|
assign hazard_reg_we_3 = REG_WE;
|
||||||
|
|
||||||
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_1, regf_a3_2;
|
||||||
logic [2**width-1:0] rd, rd_mem, rd_alu;
|
logic [2**width-1:0] rd, rd_mem, rd_alu;
|
||||||
assign rd = (REGW_MEM_OR_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
|
gatereg #(3, 1) gate_regf_a3 (clk, rst, 1'b1, regf_a3, regf_a3_1);
|
||||||
gatereg #(3, 2) gate_regf_a3 (clk, rst, 1'b1, regf_a3, regf_a3_2);
|
gatereg #(3, 1) gate_regf_a3_1 (clk, rst, 1'b1, regf_a3_1, regf_a3_2);
|
||||||
register_file #(width, 5) REGS (
|
register_file #(width, 5) REGS (
|
||||||
~clk, REG_WE,
|
~clk, REG_WE,
|
||||||
regf_a3_2[4:0], rd,
|
regf_a3_2[4:0], rd,
|
||||||
@@ -65,48 +102,58 @@ module assignment3 #(width=5, romsz=9, ramsz=10)(
|
|||||||
instruction[20:16], regf_rt,
|
instruction[20:16], regf_rt,
|
||||||
regs_out
|
regs_out
|
||||||
);
|
);
|
||||||
gatereg #(width, 1) gate_regf_rs(clk, rst, 1'b1, regf_rs, regf_rs_1);
|
gatereg #(width, 1) gate_regf_rs(clk, rst | hazard_flushE, 1'b1, regf_rs, regf_rs_1);
|
||||||
gatereg #(width, 1) gate_regf_rt(clk, rst, 1'b1, regf_rt, regf_rt_1);
|
gatereg #(width, 1) gate_regf_rt(clk, rst | hazard_flushE, 1'b1, regf_rt, regf_rt_1);
|
||||||
gatereg #(width, 1) gate_regf_rt_1(clk, rst, 1'b1, regf_rt_1, regf_rt_2);
|
assign hazard_write_reg_0 = regf_a3;
|
||||||
|
assign hazard_write_reg_1 = regf_a3_1;
|
||||||
|
assign hazard_write_reg_2 = regf_a3_2;
|
||||||
|
assign hazard_rs_0 = instruction[25:21];
|
||||||
|
assign hazard_rt_0 = instruction[20:16];
|
||||||
|
assign hazard_rs_1 = instruction_1[25:21];
|
||||||
|
assign hazard_rt_1 = instruction_1[20:16];
|
||||||
|
|
||||||
|
gatereg #(width, 1) gate_regf_rt_1(clk, rst, 1'b1, regf_rt_1, regf_rt_2); // TODO: Remove - is WriteDataE, not rt
|
||||||
|
|
||||||
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'b1, sign_ext_imm, rt_imm);
|
gatereg #(width, 1) gate_sign_ext_imm(clk, rst, 1'b1, sign_ext_imm, rt_imm);
|
||||||
|
|
||||||
// TODO: 3 to 1 MUX for ALU
|
// Inputs
|
||||||
// always_comb begin
|
logic [2**width-1:0] alu_in_a, alu_in_b;
|
||||||
// case (forwardA)
|
always_comb begin
|
||||||
// 2'b00: alu_srcA = idex_readData1;
|
case (hazard_forwardAE)
|
||||||
// 2'b01: alu_srcA = memwb_writedata;
|
2'b00: alu_in_a = regf_rs_1;
|
||||||
// 2'b10: alu_srcA = exmem_aluout;
|
2'b01: alu_in_a = rd;
|
||||||
// default: alu_srcA = idex_readData1;
|
2'b10: alu_in_a = alu_out_1;
|
||||||
// endcase
|
default: alu_in_a = regf_rs_1;
|
||||||
//
|
endcase
|
||||||
// case (forwardB)
|
case (hazard_forwardBE)
|
||||||
// 2'b00: alu_srcB = idex_readData2;
|
2'b00: alu_in_b = regf_rt_1;
|
||||||
// 2'b01: alu_srcB = memwb_writedata;
|
2'b01: alu_in_b = rd;
|
||||||
// 2'b10: alu_srcB = exmem_aluout;
|
2'b10: alu_in_b = alu_out_1;
|
||||||
// default: alu_srcB = idex_readData2;
|
default: alu_in_b = regf_rt_1;
|
||||||
// endcase
|
endcase
|
||||||
// end
|
end
|
||||||
|
// Outputs
|
||||||
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, alu_out, alu_flags[2:0]);
|
alu #(width) ALU (ALU_FN, alu_in_a, (ALU_SRC) ? rt_imm : alu_in_b, alu_out, alu_flags[2:0]);
|
||||||
gatereg #(width, 1) gate_alu_out (clk, rst, 1'b1, 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'b1, alu_out_1, alu_out_2);
|
gatereg #(width, 1) gate_alu_out_1 (clk, rst, 1'b1, alu_out_1, alu_out_2);
|
||||||
gatereg #(2, 1) gate_alu_flags (clk, rst, 1'b1, alu_flags, alu_flags_1);
|
gatereg #(2, 1) gate_alu_flags (clk, rst, 1'b1, alu_flags, alu_flags_1);
|
||||||
assign rd_alu = alu_out_2;
|
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 = (sign_ext_imm << 2) + pc_addr_2;
|
||||||
gatereg #(width, 1) gate_new_pc_addr (clk, rst, 1'b1, 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 & ((hazard_forwardAD ? alu_out_1 : regf_rs) == (hazard_forwardBD ? alu_out_1 : regf_rt));
|
||||||
|
assign hazard_branch_taken = pc_we;
|
||||||
|
assign hazard_jump_taken = pc_we;
|
||||||
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[ramsz-1:0], MEM_WE, regf_rt_2, mem_out);
|
ram #(ramsz, width) RAM (clk, rst, alu_out_1[ramsz-1:0], MEM_WE, alu_in_b, mem_out);
|
||||||
gatereg #(width, 1) gate_mem_out (clk, rst, 1'b1, 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
|
||||||
|
|||||||
Reference in new issue
Block a user