Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
    • Combinational Timing Overview
    • Muxes, Decoders and Encoders
    • Arithmetic Blocks
      • Adder Building Blocks
      • Ripple Carry and Carry Lookahead
      • Shift-Add Multiplier
      • Wallace-Tree Multiplier Intuition
    • Comparators and Shifters
    • Tri-State and Shared Buses
    • Latch Inference
    • Arithmetic Datapaths
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

←Arithmetic Blocks
  1. Topics
  2. RTL Design
  3. Combinational Design
  4. Arithmetic Blocks
  5. Wallace-Tree Multiplier Intuition
On this page

    Part 2 of 9, lesson 11 of 25Part 2 of 9/Combinational/Lesson 11 of 25Intermediate

    Wallace-Tree Multiplier Intuition

    Skip every carry until the last step: compress three numbers into two and shrink N rows in log depth.

    Adding 32 partial products with ordinary adders makes each add wait for a full carry chain. Carry-save adders postpone the carries, so a 32 x 32 multiply needs only about 8 reduction levels and one final add.

    After this lesson you can: reduce rows with carry-save adders, follow bit weights through a compressor, and estimate the number of levels for a given row count.

    Postpone carries to the end

    Adding N numbers with ordinary adders makes every addition wait for a full carry chain. A carry-save adder (CSA) takes three numbers and reduces them to two: a sum vector and a carry vector.

    It uses one independent full adder per bit position, so there is no carry propagation. Only the last step needs a real carry-propagate adder.

    Block

    Inputs

    Outputs

    Delay

    Carry-propagate adder

    2 numbers

    1 number

    Grows with width (carry chain)

    Carry-save adder (3:2 compressor)

    3 numbers

    2 numbers (sum, carry)

    One full-adder delay, independent of width

    The compressor works bitwise: at each position it adds three bits x + y + z into a sum bit (weight 1) and a carry bit (weight 2). The invariant is simply that the total value is preserved:

    x+y+z=s+2c

    Follow the bit weights

    Unsigned 3x3 example: 111 x 111. Boxed triples become one dot in the same column and one in the next higher-weight column. Every panel totals 49.

    For 7 x 7, the three nonzero partial-product rows are 00111, 01110 and 11100. At weight 4, three ones represent 12: the compressor emits one sum dot of weight 4 and one saved carry dot of weight 8. The next panel has three weight-8 dots; a second stage turns those 24 into a weight-8 sum and a weight-16 carry. No column consumes a carry from its neighbour within the same stage.

    The last panel has at most two dots per column. One way to arrange them into two rows is 11111 (31) and 10010 (18). Only now do we propagate carries to get 110001 (49). These are unsigned bit heaps; signed multiplication also needs its sign-bit treatment.

    The same invariant in vector form

    Diagram
    x = 00111 =  7
    y = 01110 = 14
    z = 11100 = 28
    s = x XOR y XOR z                 = 10101 = 21
    c = (x AND y) OR (x AND z) OR (y AND z)
                                      = 01110 = 14
    saved carry, widened then shifted = 011100 = 28
    final add: 010101 + 011100         = 110001 = 49

    The vector compressor groups all columns at once, so its two rows need not match the dot diagram's staged column grouping. Both preserve the same total. The unshifted c stores a carry at its source position; shift it left once, retaining the new top bit, before adding it to s. Adding s + c would incorrectly give 35.

    Check yourself Three ones at weight 16 enter a compressor. What weights leave?

    One sum bit at weight 16 and one carry bit at weight 32: 16+16+16=16+32. The carry belongs to the next column, not to another full adder in this same compression stage.

    Rows are compressed 3-to-2 level by level. Only the final adder has a carry chain.

    How many levels

    Each CSA level reduces the number of rows by a factor of 2/3. The most rows that k levels can reduce to two are 2, 3, 4, 6, 9, 13, 19, 28, 42, 63, ... (each is ⌊1.5 × the previous⌋). So the depth grows like log₁.₅ of the number of rows:

    Partial products (rows)

    CSA levels

    Example

    3

    1

    4

    2

    the example above

    5–6

    3

    7–9

    4

    10–13

    5

    14–19

    6

    16×16 multiplier (16 rows)

    20–28

    7

    29–42

    8

    32×32 multiplier (32 rows)

    A Wallace tree applies this reduction as early and as aggressively as possible. A Dadda tree uses the same stage count but fewer compressors.

    Both finish with a fast carry-propagate adder. Compared with an array multiplier, whose depth is proportional to N, the tree's depth is proportional to log N.

    Common mistakes

    You do not hand-write a Wallace tree. Writing a * b lets synthesis (or a datapath generator) choose a tree structure when timing demands it. The intuition tells you why a multiplier can meet a fast clock, and why wide multipliers are large.

    “How can a 32×32 multiplier be fast?” Answer: reduce 32 partial products to two with carry-save adders in about 8 levels with no carry propagation, then do one fast final add.

    Check yourself Why is a carry-save adder's delay independent of the operand width?

    Each bit position uses its own full adder, and no position waits for another: the carry output is saved as a separate vector rather than fed into the next position. Delay is one full-adder delay regardless of width.

    Check yourself Four rows enter the example tree above. Predict how many CSA levels run before the final add.

    Two: the first CSA reduces three rows to two vectors, and the second CSA folds in the fourth row. Only then does one carry-propagate adder run.

    Check yourself A 16 by 16 multiplier has 16 rows. Predict the CSA depth from the table above.

    6 levels: 16 falls in the 14–19 row. Depth grows with log N, not N.

    Do

    Avoid

    Write a * b and let the tool build the tree

    Hand-writing CSA trees in RTL by hand

    Budget area for wide multipliers; trees are large

    Assuming a 32 by 32 multiply is as cheap as an add

    Testbench

    A two-level CSA reduction checked against a+b+c+d for all 65536 inputs.

    csa.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    module csa #(parameter int W = 8) (
      input  logic [W-1:0] x, y, z,
      output logic [W-1:0] s, c           // value = s + (c << 1)
    );
      assign s = x ^ y ^ z;                              // per-bit sum
      assign c = (x & y) | (x & z) | (y & z);            // per-bit carry (majority)
    endmodule
    
    // Four rows reduced with two CSA levels, then one ordinary add
    module add4_csa (
      input  logic [3:0] a, b, c, d,
      output logic [5:0] sum
    );
      logic [5:0] s1, c1, s2, c2;
      csa #(6) l1 (.x({2'b0,a}), .y({2'b0,b}), .z({2'b0,c}), .s(s1), .c(c1));
      // c1[5] is 0 here. Bits [5:4] of all three l1 inputs are zero. At full width, keep every carry bit.
      csa #(6) l2 (.x(s1), .y({c1[4:0],1'b0}), .z({2'b0,d}), .s(s2), .c(c2));
      // c2[5] is 0 here. The three bit-5 inputs (s1[5], c1[4], and the zero bit) are all 0. At full width, keep every carry bit.
      assign sum = s2 + {c2[4:0], 1'b0};                 // single carry-propagate add at the end
    endmodule
    
    module tb_csa;
      timeunit 1ns; timeprecision 1ps;
      logic [3:0] a, b, c, d;
      logic [5:0] sum;
      add4_csa dut (.*);
      int errors = 0;
      int expected;
      initial begin
        for (int i = 0; i < 65536; i++) begin            // every combination of four 4-bit rows
          {a, b, c, d} = i[15:0]; #1;
          expected = int'(a) + int'(b) + int'(c) + int'(d);
          if (sum !== expected[5:0]) begin
            errors++;
            $display("FAIL csa: a=%0d b=%0d c=%0d d=%0d expected=%0d actual=%b",
                     a, b, c, d, expected, sum);
          end
        end
        if (errors != 0) $fatal(1, "FAIL csa: %0d mismatching cases", errors);
        if (errors == 0) $display("PASS: two CSA levels plus one add equal a+b+c+d for all 65536 inputs");
        $finish;
      end
    endmodule
    • A carry-save adder turns three rows into two (a sum vector and a carry vector) with no carry propagation, and keeps the total value.

    • Each level cuts the rows by 2/3, so depth grows like log 1.5 of the row count.

    • Only the last step is a real carry-propagate adder.

    Rule of thumb: write a * b and let synthesis choose the tree.

    • Code lab: Build a carry-save adder slice

    • Interview: run a mock interview on this topic

    Related topics

    • Shift-add multiplier

    • RTL for timing

    Previous

    47 / 350

    Next: Comparators and Shifters

    Up next

    Up nextComparators and Shifters

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Adder Building Blocks
    • Ripple Carry and Carry Lookahead