Day 87: Pipelining the core: the five stages in RTL
Pipelining the core: five stages in RTL
Convert the working single-cycle core into the 5-stage pipeline (Stage 1, Days 43–47): insert pipeline registers — IF/ID, ID/EX, EX/MEM, MEM/WB — that carry each instruction's data *and its control signals* from stage to stage. The datapath logic barely changes; what's new is the plumbing that keeps five instructions in flight, each seeing the right version of every signal.
// ID/EX pipeline register: latch everything EX and later stages need
always @(posedge clk or negedge rst_n) begin
if (!rst_n) idex <= '0;
else if (!stall) begin
idex.rd1 <= rd1;
idex.rd2 <= rd2;
idex.imm <= imm;
idex.rs1 <= instr_id[19:15]; // for forwarding compare
idex.rs2 <= instr_id[24:20];
idex.rd_addr <= instr_id[11:7];
idex.ctrl <= ctrl; // ALL control signals travel along
end
endControl travels with the instruction
The key insight of pipelining RTL: control signals aren't computed once and held — they're generated in ID and carried down the pipeline in the registers, so each stage applies the control belonging to *its* instruction. Package all control into a struct that rides ID/EX → EX/MEM → MEM/WB, and each stage uses the slice it needs. Get this and the pipeline is mostly plumbing.
Progress for Day 87
When pipelining, why must the control signals travel through the pipeline registers alongside the data?