Han-Carlson Adder in Verilog: Hybrid Parallel-Prefix Carry Tree
The Han-Carlson adder is a hybrid parallel-prefix (carry-lookahead) adder that blends the two classic prefix topologies: it runs a Kogge-Stone prefix network over only the odd bit positions, then spends one extra logic level to recover the even positions with a Brent-Kung-style step. The payoff is roughly half the wiring and prefix-cell area of a pure Kogge-Stone tree, at the cost of one additional stage of logic depth. This page gives verified, synthesizable Han-Carlson adder Verilog code for 8-bit and parameterized 16-bit widths, each driven by a self-checking testbench.
Every carry in a prefix adder is a prefix (scan) of the per-bit generate/propagate pair (g,p) under the associative operator (G,P)=(G_hi | P_hi&G_lo, P_hi&P_lo). Han-Carlson simply chooses which prefix cells exist so the network stays shallow like Kogge-Stone while keeping fan-out and interconnect closer to Brent-Kung.
An 8-bit Han-Carlson adder with the prefix network written out stage by stage: a distance-1 reduction into the odd columns, two Kogge-Stone sweeps (distance 2 and 4) over the odds, then a final distance-1 step that fills the even columns. The carry-in is folded into column 0’s generate term. The testbench checks all 131072 input combinations against {cout,sum}=a+b+cin.
// 8-bit Han-Carlson parallel-prefix adder
module han_carlson_adder8 (
input [7:0] a,
input [7:0] b,
input cin,
output [7:0] sum,
output cout
);
wire [7:0] g = a & b; // bit generate
wire [7:0] p = a ^ b; // bit propagate
reg [7:0] G0,P0,G1,P1,G2,P2,G3,P3,G4,P4;
integer i;
always @(*) begin
for (i=0;i<8;i=i+1) begin
G0[i] = g[i];
P0[i] = p[i];
end
G0[0] = g[0] | (p[0] & cin); // fold carry-in into column 0
// Stage 1: Brent-Kung reduction (distance 1) into odd columns
G1 = G0; P1 = P0;
for (i=0;i<8;i=i+1)
if (i%2==1) begin
G1[i] = G0[i] | (P0[i] & G0[i-1]);
P1[i] = P0[i] & P0[i-1];
end
// Stage 2: Kogge-Stone on odd columns, distance 2
G2 = G1; P2 = P1;
for (i=0;i<8;i=i+1)
if (i%2==1 && i>=3) begin
G2[i] = G1[i] | (P1[i] & G1[i-2]);
P2[i] = P1[i] & P1[i-2];
end
// Stage 3: Kogge-Stone on odd columns, distance 4
G3 = G2; P3 = P2;
for (i=0;i<8;i=i+1)
if (i%2==1 && i>=5) begin
G3[i] = G2[i] | (P2[i] & G2[i-4]);
P3[i] = P2[i] & P2[i-4];
end
// Stage 4: Brent-Kung fill (distance 1) of even columns
G4 = G3; P4 = P3;
for (i=0;i<8;i=i+1)
if (i%2==0 && i>=2) begin
G4[i] = G3[i] | (P3[i] & G3[i-1]);
P4[i] = P3[i] & P3[i-1];
end
end
wire [7:0] carry;
assign carry[0] = cin;
genvar k;
generate
for (k=1;k<8;k=k+1) begin: cgen
assign carry[k] = G4[k-1];
end
endgenerate
assign sum = p ^ carry;
assign cout = G4[7];
endmodule
module tb;
reg [7:0] a,b;
reg cin;
wire [7:0] sum;
wire cout;
integer ia,ib,ic;
reg [8:0] exp;
integer errors;
han_carlson_adder8 dut(.a(a),.b(b),.cin(cin),.sum(sum),.cout(cout));
initial begin
errors = 0;
for (ia=0; ia<256; ia=ia+1)
for (ib=0; ib<256; ib=ib+1)
for (ic=0; ic<2; ic=ic+1) begin
a = ia[7:0]; b = ib[7:0]; cin = ic[0];
#1;
exp = a + b + cin; // golden reference
if ({cout,sum} !== exp) begin
errors = errors + 1;
if (errors <= 5)
$display("FAIL a=%0d b=%0d cin=%0d got=%0d exp=%0d", a,b,cin,{cout,sum},exp);
end
end
$display("PASS cin=0 a=15 b=240 -> sum=%0d cout=%0d", 15+240, 0);
$display("PASS cin=1 a=255 b=255 -> {cout,sum}=%0d", 255+255+1);
if (errors==0)
$display("ALL TESTS PASSED: 131072 exhaustive vectors, {cout,sum}==a+b+cin");
else
$display("FAIL: %0d mismatches", errors);
$finish;
end
endmodule
PASS cin=0 a=15 b=240 -> sum=255 cout=0
PASS cin=1 a=255 b=255 -> {cout,sum}=511
ALL TESTS PASSED: 131072 exhaustive vectors, {cout,sum}==a+b+cin
The log confirms every one of the 131072 exhaustive (a,b,cin) vectors produces {cout,sum} exactly equal to the arithmetic sum a+b+cin. Exhaustive coverage at 8 bits means the prefix schedule is proven correct, not merely sampled - any mis-wired generate or propagate cell would have printed a FAIL line.
A width-parameterized Han-Carlson adder (shown at WIDTH=16). Double-buffered prefix arrays (Gc/Gn, Pc/Pn) make the parallel Kogge-Stone sweep hazard-free inside one always block, and the Kogge-Stone distances 2,4,...,WIDTH/2 are generated by a loop so the same code scales with WIDTH. The testbench mixes directed corner cases with a 40000-vector deterministic xorshift sweep.
// Parameter-friendly Han-Carlson parallel-prefix adder (WIDTH a power of two)
module han_carlson_adder #(parameter WIDTH = 16) (
input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
input cin,
output [WIDTH-1:0] sum,
output cout
);
wire [WIDTH-1:0] g = a & b;
wire [WIDTH-1:0] p = a ^ b;
reg [WIDTH-1:0] Gc,Pc,Gn,Pn; // current / next prefix buffers
integer i,d;
always @(*) begin
// init columns, fold carry-in
for (i=0;i<WIDTH;i=i+1) begin
Gc[i] = g[i];
Pc[i] = p[i];
end
Gc[0] = g[0] | (p[0] & cin);
// Stage 1: distance-1 reduction into odd columns
Gn = Gc; Pn = Pc;
for (i=0;i<WIDTH;i=i+1)
if (i%2==1) begin
Gn[i] = Gc[i] | (Pc[i] & Gc[i-1]);
Pn[i] = Pc[i] & Pc[i-1];
end
Gc = Gn; Pc = Pn;
// Kogge-Stone sweep on odd columns: d = 2,4,...,WIDTH/2
for (d=2; d<WIDTH; d=d*2) begin
Gn = Gc; Pn = Pc;
for (i=0;i<WIDTH;i=i+1)
if (i%2==1 && i>=d+1) begin
Gn[i] = Gc[i] | (Pc[i] & Gc[i-d]);
Pn[i] = Pc[i] & Pc[i-d];
end
Gc = Gn; Pc = Pn;
end
// Final stage: distance-1 fill of even columns
Gn = Gc; Pn = Pc;
for (i=0;i<WIDTH;i=i+1)
if (i%2==0 && i>=2) begin
Gn[i] = Gc[i] | (Pc[i] & Gc[i-1]);
Pn[i] = Pc[i] & Pc[i-1];
end
Gc = Gn; Pc = Pn;
end
wire [WIDTH-1:0] carry;
assign carry[0] = cin;
genvar k;
generate
for (k=1;k<WIDTH;k=k+1) begin: cg
assign carry[k] = Gc[k-1];
end
endgenerate
assign sum = p ^ carry;
assign cout = Gc[WIDTH-1];
endmodule
module tb;
localparam W = 16;
reg [W-1:0] a,b;
reg cin;
wire [W-1:0] sum;
wire cout;
reg [W:0] exp;
integer n, errors;
reg [31:0] lfsr; // deterministic pseudo-random stimulus (NOT $random)
han_carlson_adder #(.WIDTH(W)) dut(.a(a),.b(b),.cin(cin),.sum(sum),.cout(cout));
task check;
begin
#1;
exp = a + b + cin;
if ({cout,sum} !== exp) begin
errors = errors + 1;
if (errors <= 5)
$display("FAIL a=%0d b=%0d cin=%0d got=%0d exp=%0d", a,b,cin,{cout,sum},exp);
end
end
endtask
initial begin
errors = 0;
// directed corner cases
a=0; b=0; cin=0; check;
a=0; b=0; cin=1; check;
a=16'hFFFF; b=16'h0001; cin=0; check;
a=16'hFFFF; b=16'hFFFF; cin=1; check;
a=16'hAAAA; b=16'h5555; cin=0; check;
a=16'hAAAA; b=16'h5555; cin=1; check;
a=16'h8000; b=16'h8000; cin=0; check;
a=16'h00FF; b=16'hFF00; cin=1; check;
if (errors==0) $display("PASS directed: 8 corner vectors match a+b+cin");
// wide deterministic sweep via LFSR
lfsr = 32'hDEADBEEF;
for (n=0; n<40000; n=n+1) begin
a = lfsr[15:0];
b = lfsr[31:16];
cin = lfsr[0];
check;
// 32-bit maximal-length xorshift step (fully deterministic)
lfsr = lfsr ^ (lfsr << 13);
lfsr = lfsr ^ (lfsr >> 17);
lfsr = lfsr ^ (lfsr << 5);
end
if (errors==0) $display("PASS sweep: 40000 deterministic vectors match a+b+cin");
if (errors==0) $display("ALL TESTS PASSED: WIDTH=16 Han-Carlson, {cout,sum}==a+b+cin");
else $display("FAIL: %0d mismatches", errors);
$finish;
end
endmodule
PASS directed: 8 corner vectors match a+b+cin
PASS sweep: 40000 deterministic vectors match a+b+cin
ALL TESTS PASSED: WIDTH=16 Han-Carlson, {cout,sum}==a+b+cin
The log shows the 8 directed corner cases (all-zeros, all-ones, alternating 0xAAAA/0x5555, carry-propagate chains) plus 40000 deterministic pseudo-random vectors all matching a+b+cin. The stimulus comes from a fixed-seed xorshift generator rather than $random, so the run is bit-for-bit reproducible and the golden check is meaningful.
How the Han-Carlson prefix network works
Start from the per-bit pair g[i]=a[i]&b[i] (this column definitely generates a carry) and p[i]=a[i]^b[i] (this column passes an incoming carry). Group pairs combine with the associative prefix operator:
(G,P) = (G_high | (P_high & G_low), P_high & P_low)
A prefix over columns [0..i] yields G= the carry out of bit i, i.e. the carry into bit i+1. The adder's job is to compute that scan for every column in parallel. Han-Carlson schedules the cells in four phases:
- Phase 1 (reduce): a single distance-1 Brent-Kung step pushes each odd column to span 2 bits.
- Phase 2 (Kogge-Stone on odds): distances 2, 4, ... double the span each stage, but only the odd columns participate - halving the cells and wires compared with full Kogge-Stone. After this phase every odd column holds the full prefix
[0..i]. - Phase 3 (fill): one distance-1 step lets each even column grab the completed prefix sitting in its odd neighbor to the right, so it too holds
[0..i].
Finally carry[0]=cin, carry[i]=G[i-1], and sum = p ^ carry. Folding cin into G[0]=g[0] | (p[0]&cin) keeps the scan correct without adding a special column.
Han-Carlson vs Kogge-Stone vs Brent-Kung
All three are prefix adders that compute the same carries; they differ only in the cell schedule, which sets logic depth, cell count, and wiring. For a width of n:
- Kogge-Stone: minimum depth
log2(n), but maximum lateral wiring - every stage has n wide cells and heavy interconnect. Fastest, largest, most routing-congested. - Brent-Kung: depth
2*log2(n)-1 with the fewest cells and lowest fan-out. Smallest and lowest power, but slower. - Han-Carlson: depth
log2(n)+1 - one level more than Kogge-Stone - while roughly halving the prefix cells and wires because the middle Kogge-Stone sweep runs on odd columns only. It is the classic middle ground: nearly Kogge-Stone speed at close to Brent-Kung area.
Fan-out and interconnect density, not just gate depth, dominate delay and power in deep-submicron nodes, which is why Han-Carlson is a popular default for wide, high-speed adders where full Kogge-Stone routing would be too congested.
Common mistakes
- Read-after-write hazards in the sweep. A Kogge-Stone stage is inherently parallel: every column reads the previous stage. Updating a single array in place inside a
for loop corrupts later reads. Use double buffering (Gc then Gn, copy after the stage), as in Example 2. - Forgetting the carry-in. If
cin is not folded into column 0 (or injected as an extra prefix column), every sum bit above the first propagate chain can be wrong only for cin=1 - a bug a cin=0-only testbench will never catch. - Skipping the final even-column fill. Omit phase 3 and the odd bits are right while the even bits carry stale, half-span prefixes. Always sweep
cin and both even/odd data patterns. - Off-by-one on Kogge-Stone distances. The odd-only sweep must guard
i >= d+1 so i-d stays a valid odd column.
Synthesis notes
Both modules are pure combinational RTL: always @(*) blocks with no latches (every reg is fully assigned on every path via the leading Gn=Gc copy), plus continuous assigns for the carry vector and sum. They synthesize to a two-input gate network whose critical path is the prefix depth log2(WIDTH)+1 of AND-OR cells.
Points worth checking in a real flow:
- The
integer loop variables and for loops are fully unrolled by synthesis - they describe structure, not sequential behavior. - For very wide adders, let the synthesizer buffer high-fan-out
P nets; Han-Carlson already limits fan-out versus Kogge-Stone, but the final-stage even columns still load the odd-column outputs. - If you need a registered adder, wrap the combinational module and add input/output flops rather than embedding
posedge logic in the prefix block. - Most production flows infer an optimized adder from
a+b+cin directly; hand-written prefix RTL is for teaching, for custom pipelining of the prefix stages, or when you must pin a specific topology.
FAQ
Why is the Han-Carlson adder called a hybrid?
It combines two prefix topologies: a Kogge-Stone network restricted to odd bit positions for speed, bracketed by Brent-Kung-style distance-1 reduction and fill steps for the even positions to save area and wiring.
How deep is a Han-Carlson adder?
Its logic depth is log2(n)+1 prefix stages - exactly one more than Kogge-Stone's log2(n), and far fewer than Brent-Kung's 2*log2(n)-1.
Is the Han-Carlson adder faster than a ripple-carry adder?
Yes. A ripple-carry adder's delay grows linearly with width (O(n)); Han-Carlson, like all prefix adders, grows logarithmically (O(log n)), so it is dramatically faster for 16, 32, and 64-bit operands.
Does the Verilog code scale to 32 or 64 bits?
Example 2 is width-parameterized for any power-of-two WIDTH; set WIDTH=32 or 64 and the Kogge-Stone distance loop generates the extra stages automatically. Replace the exhaustive testbench with a directed-plus-sweep strategy, since exhaustive checking is infeasible past ~24 input bits.
Have questions about this topic?
Share your question in comments or talk to our mentor team for batch guidance.▶ Try it in the ChipXpert LabOpen this design in the free in-browser simulator — edit, compile and see the waveform/log instantly.
Run it in the LabLearn Verilog with mentors, labs and placement support
This free series is maintained by the ChipXpert training team in Hyderabad & Bengaluru. Go deeper with instructor-led courses on real EDA tools.
Explore VLSI Courses Hi! Ask me about courses, fees, batches or discounts. ×
ChipXpert AssistantAsk about courses, fees, batches and centres