a carry-select adder
Suppose you have to set off to a destination but you will not learn until the last moment which of two roads is open. One option is to wait. A bolder option is to send two cars now — one down each road — and simply pick the one that turns out to be valid when the gate finally opens. A carry-select adder plays exactly this game with the unknown carry coming from the lower half of the addition.
Split the word into upper and lower halves. The lower half adds normally and eventually produces its carry-out. But rather than make the upper half wait for that carry, the upper half computes two complete answers at the same time: one assuming the incoming carry will be 0, and one assuming it will be 1. Both finish in parallel while the lower half is still working. When the real carry finally arrives, a multiplexer simply selects whichever precomputed upper-half answer matches. The slow serial dependence is replaced by a fast final choice, because the expensive addition was done speculatively ahead of time.
The cost is honest and obvious: the upper half's adder is duplicated, so you pay nearly double the area for that part to avoid waiting for one carry. Chaining several such blocks lets the carry decision ripple between blocks instead of between every bit, giving a delay that grows roughly like the square root of the width — faster than ripple, simpler than full lookahead. It is a favorite middle-ground design and a clear illustration of the field's recurring move: spend redundant hardware to remove a dependence from the critical path.
For a 16-bit add, compute the low 8 bits normally. Meanwhile the high 8 bits are added twice — once assuming carry-in 0, once assuming carry-in 1. When the low half's carry arrives, a mux picks the matching high result. Both high sums were ready early, so only a mux delay remains.
Precompute both possible upper halves, then select once the real carry is known.
Carry-select trades area for speed by duplicating the upper adder — it does not eliminate the carry dependence, it just hides it behind work done in parallel. Choosing unequal block sizes (smaller blocks first) balances the delays and shaves the worst case further.