Why wide adders get pipelined (and why carry-select)
A plain ripple-carry adder’s critical path grows linearly with operand width — the carry has to propagate all the way from bit 0 to the top bit before the sum is valid. For wide operands, that path alone can limit the whole chip’s clock frequency. Carry-select breaks the dependency by computing the upper half’s sum twice, in parallel — once assuming the lower half produces a carry-out of 0, once assuming it produces a carry-out of 1 — and then simply selecting between the two precomputed results once the real lower-half carry becomes known. That selection is a fast multiplexer, not another full carry chain, so the critical path becomes “lower half’s carry chain, then one mux level” instead of “the full width’s carry chain.”
Pipelining this across two register stages goes one step further: the lower-half addition and both speculative upper-half additions all happen in stage 1 (fully parallel, no dependency between them), and only the final mux-select-and-register happens in stage 2 — keeping each stage’s combinational depth small.
Interface
| Signal | Direction | Width | Description |
|---|---|---|---|
HALF |
parameter | — | Width of each half; total operand width is 2*HALF. |
clk/rst |
input | — | Clock and synchronous, active-high reset. |
in_valid |
input | 1 | High when a, b are a genuine input this cycle. |
a, b |
input | 2*HALF |
Unsigned operands. |
out_valid |
output | 1 | High exactly 2 cycles after the corresponding in_valid. |
sum |
output | 2*HALF |
a + b from 2 cycles earlier (truncated to 2*HALF bits). |
cout |
output | 1 | Carry-out of the full 2*HALF-bit addition, from 2 cycles earlier. |
Correctness constraints
- The final
{cout, sum}must exactly equal the full-width unsigned suma + b(as a2*HALF+1-bit result), for every possible carry pattern across the half boundary — including the case where the lower half is all-ones and adding even1ripples a carry all the way into the upper half. - Both speculative upper-half sums (
hi_sum0, assuming no incoming carry, andhi_sum1, assuming an incoming carry) must be computed and registered in stage 1, with the actual selection deferred to stage 2 based on the real, now-registered lower-half carry (c_lo_r) — the whole point of carry-select is that this selection happens after the carry is known, not before. out_validmust trackin_validwith exactly 2 cycles of latency, correctly propagating bubbles.- The pipeline must accept a new
(a, b)pair every cycle with no stalling.