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 Lab

Open this design in the free in-browser simulator — edit, compile and see the waveform/log instantly.

Run it in the Lab

Learn 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
Next batch starts 18th November 2026
Start your VLSI career with ChipXpert

Live online and classroom batches in Hyderabad & Bengaluru. Fill in your details and a counsellor will call you back.

  • Real EDA tools in your browser: industry-standard EDAReal EDA tools in your browser
  • Recorded sessions on the elearn portalRecorded sessions
  • Placement assistance: resume, mock interviewsPlacement assistance
  • Merit scholarship up to 60% · EMI optionsScholarship up to 60%
Hi! Ask me about courses, fees, batches or discounts. ×
BENGALURU
HYDERABAD