M src/cpu.sv => src/cpu.sv +10 -0
@@ 33,6 33,12 @@ module cpu(
wire [31:0] jumping_pc_next;
stage_status_t stages_in[1:4];
+
+ /// verilator doesn't like that data taken from stages_out[i]
+ // are used in stages_out[i + 1]. But that shouldn't really matter
+ // as there is not really a cyclic dependency.
+ // It just seems that verilator is not very good at "separating"
+ // array elements
/* verilator lint_off UNOPTFLAT */
stage_status_t stages_out[0:3];
/* verilator lint_on UNOPTFLAT */
@@ 76,6 82,10 @@ module cpu(
pc_next = pc;
end
+ // data for forwarding from the stages
+ // Note: this is a record instead of an array
+ // just because verilator didn't like it as an array
+ // consider switching back to array.
forwarding_data_status_t data_in_pipeline;
assign data_in_pipeline.execute_out = stages_out[EXECUTE].data;
assign data_in_pipeline.access_out = stages_out[ACCESS].data;
M src/forwarder.sv => src/forwarder.sv +1 -0
@@ 14,6 14,7 @@ module forwarder(
// these will be used instead of the register_file_data
//
// if there are multiple matches, the first one is taken
+ // to get the most recent data
always_comb begin
stall = 0;
M src/stages/decode.sv => src/stages/decode.sv +6 -4
@@ 17,8 17,6 @@ module decode(
output stage_status_t stage_out
);
- parameter FORWARDING_STAGES = 3; // , execute(out), memory(out), writeback(in)
-
wire [2:0] alu_op;
wire alu_add_one;
wire alu_negate;
@@ 42,6 40,7 @@ module decode(
wire memory_we;
assign stage_out.data.address = reg_we && !stalling ? reg_rd : 0;
+ assign stage_out.data.valid = 0; // the data cannot be valid at this point;
assign stage_out.pc = stage_in.pc;
@@ 110,6 109,8 @@ module decode(
.data(forwarded_reg_rd2)
);
+ // TODO: this is there twice instead of just once
+ // the second is in execute stage. Maybe merge these?
// alu source 1
reg [31:0] alu_1, alu_2;
always_comb begin
@@ 158,6 159,7 @@ module decode(
wire stalling;
assign stalling = (uses_reg_rd1 && stall_1) || (uses_reg_rd2 && stall_2);
- assign stage_out.valid = !stalling;
- assign stage_out.ready = !stalling;
+ assign stage_out.valid = !stalling && stage_in.valid;
+ assign stage_out.ready = !stalling || !stage_in.valid;
+ // if input is not valid, do not care about stalling...
endmodule
M src/stages/execute.sv => src/stages/execute.sv +7 -5
@@ 9,15 9,17 @@ module execute(
reg [31:0] alu_1, alu_2;
wire [31:0] alu_out;
+ assign stage_out.instruction = stage_in.instruction;
+ assign stage_out.pc = stage_in.pc;
assign stage_out.reg_rd1 = stage_in.reg_rd1;
assign stage_out.reg_rd2 = stage_in.reg_rd2;
- assign stage_out.pc = stage_in.pc;
- assign stage_out.instruction = stage_in.instruction;
- assign stage_out.valid = stage_in.valid;
- assign stage_out.ready = 1;
- assign stage_out.data.valid = stage_in.valid && (stage_in.instruction.reg_rd_src != RD_MEMORY);
+
assign stage_out.data.address = stage_in.valid ? stage_in.data.address : 0;
assign stage_out.data.data = stage_in.instruction.reg_rd_src == RD_PC_PLUS ? stage_in.pc + 4 : alu_out;
+ assign stage_out.data.valid = stage_in.valid && (stage_in.instruction.reg_rd_src != RD_MEMORY);
+
+ assign stage_out.valid = stage_in.valid;
+ assign stage_out.ready = 1;
// alu source 1
always_comb begin
M src/stages/fetch.sv => src/stages/fetch.sv +2 -1
@@ 9,7 9,8 @@ module fetch(
output stage_status_t stage_out
);
assign stage_out.instruction.instruction = mem_instruction;
- assign stage_out.valid = !jump;
assign stage_out.pc = pc;
+
+ assign stage_out.valid = !jump;
assign stage_out.ready = 1;
endmodule
M src/stages/memory_access.sv => src/stages/memory_access.sv +2 -1
@@ 49,6 49,7 @@ module memory_access(
assign stage_out.reg_rd1 = stage_in.reg_rd1;
assign stage_out.reg_rd2 = stage_in.reg_rd2;
+ assign stage_out.data.valid = stage_in.valid;
assign stage_out.data.address = stage_in.valid ? stage_in.data.address : 0;
assign stage_out.data.data =
stage_in.instruction.reg_rd_src == RD_MEMORY ?
@@ 58,7 59,7 @@ module memory_access(
.sext(stage_in.instruction.memory_sign_extension)
) :
stage_in.data.data;
- assign stage_out.data.valid = stage_in.valid;
+
assign stage_out.valid = stage_in.valid;
assign stage_out.ready = 1;
endmodule