Day 88: The forwarding unit in RTL
The forwarding unit in RTL
Implement forwarding (Stage 1, Day 44): compare the destination register of the instruction in EX/MEM and MEM/WB against the source registers of the instruction in EX, and drive the ALU-input forwarding muxes when they match (and the destination isn't x0 and reg_write is set). EX/MEM takes priority over MEM/WB when both match. This small block eliminates the stall for most back-to-back dependencies.
// forwardA/forwardB select the EX-stage ALU operands
always @(*) begin
forwardA = 2'b00; // 00 = register, 10 = EX/MEM, 01 = MEM/WB
forwardB = 2'b00;
// EX/MEM has priority (most recent)
if (exmem.reg_write && exmem.rd != 0 && exmem.rd == idex.rs1) forwardA = 2'b10;
else if (memwb.reg_write && memwb.rd != 0 && memwb.rd == idex.rs1) forwardA = 2'b01;
if (exmem.reg_write && exmem.rd != 0 && exmem.rd == idex.rs2) forwardB = 2'b10;
else if (memwb.reg_write && memwb.rd != 0 && memwb.rd == idex.rs2) forwardB = 2'b01;
endPriority and the x0 guard
Two correctness details: EX/MEM wins over MEM/WB (the newer result is the right one), and you must exclude `x0` (forwarding a write to x0 would inject a stale zero). Miss either and you'll see subtle, data-dependent failures — exactly the kind the ISS comparison (Day 86) catches instantly.
Progress for Day 88
When both EX/MEM and MEM/WB could forward the same source register, which should the forwarding unit choose?