Writing a + b asks for an adder but names no architecture. The tool picks ripple, lookahead, select, or prefix from timing and area constraints, width, and context.
The same plus can map differently under different constraints. A tight timing goal steers toward a faster, larger structure, while a tight area goal steers toward a ripple-like one; the exact choice varies by tool and library.
Adding M operands with M - 1 propagating adders ripples M - 1 times. Carry-save avoids that by never propagating until the end.
A 3:2 compressor takes three bits of equal weight and emits a sum bit and a carry bit. The carry bit has weight one higher, so the carry vector enters the next stage shifted by one with a zero in the lowest bit.
Ones among the 3 inputs | s (parity) | cout (majority) |
|---|---|---|
0 | 0 | 0 |
1 | 1 | 0 |
2 | 0 | 1 |
3 | 1 | 1 |
Compressor levels reduce M vectors to 2, then one carry-propagating adder finishes. The calc block counts full adders for four 8-bit operands.
4 operands of 8 bits each
first compressor level: 8 full adders turn 3 operands into sum and carry vectors
second level: 8 full adders turn those 2 vectors plus the fourth operand into 2 vectors
compressor full adders: 2 x 8 = 16 = (4 - 2) x 8
then one 8-bit carry-propagating adder finishes the sumThe Yosys script builds a structural 4-bit ripple and a 4-bit plus operator. It runs generic passes only, so the counts below are structural properties, not library mapping.
The ripple side pins at least 4 xor cells and 4 and cells. The plus side pins at least one add cell, which is how the operator survives generic optimization.
read_verilog <<EOV
module ripple4(input [3:0] a, b, input cin, output [3:0] s, output cout);
wire [4:0] c;
assign c[0] = cin;
assign s[0] = a[0] ^ b[0] ^ c[0];
assign c[1] = (a[0] & b[0]) | (c[0] & (a[0] ^ b[0]));
assign s[1] = a[1] ^ b[1] ^ c[1];
assign c[2] = (a[1] & b[1]) | (c[1] & (a[1] ^ b[1]));
assign s[2] = a[2] ^ b[2] ^ c[2];
assign c[3] = (a[2] & b[2]) | (c[2] & (a[2] ^ b[2]));
assign s[3] = a[3] ^ b[3] ^ c[3];
assign c[4] = (a[3] & b[3]) | (c[3] & (a[3] ^ b[3]));
assign cout = c[4];
endmodule
EOV
hierarchy -check -top ripple4
proc
opt_clean
check
stat
select -assert-min 4 t:$xor
select -assert-min 4 t:$and
design -reset
read_verilog <<EOV
module plus4(input [3:0] a, b, input cin, output [3:0] s, output cout);
assign {cout, s} = a + b + cin;
endmodule
EOV
hierarchy -check -top plus4
proc
opt_clean
check
stat
select -assert-min 1 t:$add
log PASS: 4-bit ripple and plus-operator adders map as asserted under generic passes8 full adders, one per bit. A sum vector and a carry vector come out, and the final sum still needs a propagating adder.
The structural ripple stays as bit-level logic while the plus operator survives generic passes as an arithmetic cell. Mapping to real gates happens later and varies by library.