HDLbits
Start Practicing

RTL Design Patterns/Pipelines

Latency Matching with Shift Registers

medium
pipelinelatency-matchingshift-registeralu

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

  1. ALU path (ALU_LATENCY cycles): op_a/op_b go through a combinational ALU (add/sub/and/or, selected by alu_sel), and the result is registered ALU_LATENCY times.
  2. Passthrough path (delay-matched): op_c is pushed through a shift register exactly ALU_LATENCY entries deep, so it emerges aligned with the ALU result from the same original input cycle.
  3. Combine stage: once both alu_result_r and op_c_matched refer to the same original cycle, they’re added together and registered as the final result.

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’s op_c.
  • The shift register depth must equal ALU_LATENCY exactly, and the design should generalize to any ALU_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_valid must correctly track in_valid through 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).