Why latency matching is necessary
Pipelines rarely have exactly one path from input to output. Very commonly, one branch does real computation (taking one or more cycles) while another branch is “just data along for the ride” — a tag, an address, or in this case a second operand that needs to be combined with the computed result later, once it arrives. If you connect the fast (0-cycle) passthrough path directly to a combine stage that’s waiting on the slow (multi-cycle) computed path, you combine the wrong pair of values: the current cycle’s passthrough operand with a computed result from several cycles ago, belonging to a completely different original input. The fix is always the same shape: insert a shift register of the same depth as the competing path’s latency, so that every signal arriving at a combine point was launched from the same original input cycle.
Structure
- ALU path (
ALU_LATENCYcycles):op_a/op_bgo through a combinational ALU (add/sub/and/or, selected byalu_sel), and the result is registeredALU_LATENCYtimes. - Passthrough path (delay-matched):
op_cis pushed through a shift register exactlyALU_LATENCYentries deep, so it emerges aligned with the ALU result from the same original input cycle. - Combine stage: once both
alu_result_randop_c_matchedrefer to the same original cycle, they’re added together and registered as the finalresult.
Interface
| Signal | Direction | Width | Description |
|---|---|---|---|
ALU_LATENCY |
parameter | — | Cycles the ALU path takes before its result is ready. |
clk/rst |
input | — | Clock and synchronous, active-high reset. |
in_valid |
input | 1 | High when this cycle’s inputs are a genuine, aligned triple. |
op_a, op_b |
input | WIDTH |
ALU operands. |
alu_sel |
input | 2 | ALU operation select. |
op_c |
input | WIDTH |
Passthrough operand, to be delay-matched and combined later. |
out_valid |
output | 1 | High when result is valid. |
result |
output | WIDTH |
alu(op_a, op_b) + op_c, where all three inputs came from the same original input cycle. |
Correctness constraints
op_c_matched(the value actually combined with the ALU result) must always correspond to the same original input cycle as the ALU operands it’s paired with — never a different cycle’sop_c.- The shift register depth must equal
ALU_LATENCYexactly, and the design should generalize to anyALU_LATENCY >= 1— not just the default of 1 — since real ALU/functional-unit latencies vary (a multiplier might take 3 cycles where a simple adder takes 1; both should be able to reuse this same latency-matching shape by changing the parameter). out_validmust correctly trackin_validthrough the full pipeline (ALU latency plus the final combine register), including bubbles.- No combinational shortcut may bypass the shift register for
op_c— it must go through genuine registers, matching real datapath timing (a wire with zero delay would defeat the entire purpose of the exercise).