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

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
    • Controller and Datapath
    • Moore vs Mealy
    • State Encoding
    • Multi-Cycle Sequencers
      • The Sequencer Mindset
      • Shift-Add Multiply
      • Memory Read Sequencer with Latency
      • Sequencer Robustness
    • UART Transmitter
    • Memory Controller
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Multi-Cycle Sequencers
  1. Topics
  2. RTL Design
  3. FSM & Control
  4. Multi-Cycle Sequencers
  5. Shift-Add Multiply

Part 4 · FSM & Control · Intermediate

Shift-Add Multiply

An 8-bit shift-add multiplier using one adder over eight steps, tested exhaustively.

On this page

    Why this matters

    A W-bit multiplier built from one adder takes W cycles, and the cycle count has a trap: done, busy and the next accepted start are three different edges. The product is also wrong if the multiplicand register is W bits wide.

    After this lesson you can: build a shift-add multiplier, state its latency from acceptance to done, and say when the next start is accepted.

    Long multiplication in hardware

    Binary long multiplication adds the multiplicand, shifted by each set bit of the multiplier. The example below is 13 × 11 = 143.

    Diagram
          1101   (13, multiplicand)
        x 1011   (11, multiplier)
        ------
          1101   bit 0 = 1: add 13 << 0 =   13
         1101    bit 1 = 1: add 13 << 1 =   26
        0000     bit 2 = 0: nothing
       1101      bit 3 = 1: add 13 << 3 =  104
      --------
      10001111   = 143

    The hardware runs one bit per cycle. The multiplicand shifts left, the multiplier shifts right, and an accumulator adds the multiplicand when bit 0 is set.

    Watching it run

    The waveform shows 13 × 11. Eight iterations follow the load; the pre-edge consumer observes done at edge 9 when acceptance is edge 0. This is nine inclusive load/working slots.

    • Start: start pulses and busy rises while the operands load.

    • Steps 1 to 2: the accumulator becomes 13, then 39 (0x27).

    • Steps 3 to 4: bit 2 adds nothing, then bit 3 brings the total to 143 (0x8f).

    • Steps 5 to 8: the higher bits are 0, so nothing more is added. Completion follows the eighth iteration.

    Step

    Multiplier bit

    Action

    Accumulator

    1

    1

    add 13

    13

    2

    1

    add 26

    39

    3

    0

    add nothing

    39

    4

    1

    add 104

    143

    5 to 8

    0

    add nothing

    143

    Cost and speed

    busy stays high during the DONE pulse and falls only on return to IDLE. Offer the next start as soon as busy is low; the next rising edge accepts it. Completion and acceptance availability are separate: done marks a valid product, while !busy marks readiness for a new operation.

    • Latency convention: acceptance is edge 0; iterations run at edges 1 through W. Product and done are available after edge W; a rising-edge consumer samples them at W + 1. The test's inclusive load/working-slot count is W + 1 (9 for W = 8), not nine elapsed periods from acceptance. DONE returns to IDLE after edge W + 1, so the earliest next acceptance is W + 2.

    • Area: one 2W-bit adder, three registers (accumulator, multiplicand, multiplier) and a counter.

    • Speedups: stop early when the remaining multiplier bits are zero (variable latency), or handle 2 bits per cycle (radix-4).

    For signed operands, use a Booth recoding or sign-correct the result. The unsigned design above is the foundation for both.

    Edge (W = 8)

    Action / result

    0

    Accept and load operands into RUN

    1 through 8

    One iteration per edge; done and final product available after edge 8

    9

    Consumer samples done/product; return to IDLE after edge

    10

    Earliest next acceptance; initiation interval is 10 periods

    Common mistakes

    Common pitfall

    The multiplicand register must be 2W bits wide: after W left shifts its top bit reaches position 2W−1. Using a W-bit register silently drops the high bits and gives wrong products for large operands. The exhaustive test catches this at, for example, 255 × 255.

    Check yourself Why does the multiplier shift right while the multiplicand shifts left?

    So that the multiplier's current bit is always bit 0 (cheap to test), while the multiplicand grows by a factor of two per step, which is exactly the weight of the next multiplier bit.

    Testbench

    The complete multiplier and the exhaustive testbench over all input pairs, plus directed restarts on the first cycle where busy is low.

    shift_add_mul.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 shift_add_mul #(parameter int W = 8) (
      input  logic           clk, rst_n,
      input  logic           start,
      input  logic [W-1:0]   a, b,
      output logic           busy, done,
      output logic [2*W-1:0] product
    );
      typedef enum logic [1:0] {IDLE, RUN, DONE} state_t;
      state_t state;
    
      logic [2*W-1:0] mcand;          // multiplicand, shifts left each step
      logic [W-1:0]   mplier;         // multiplier, shifts right each step
      logic [2*W-1:0] acc;            // running sum
      logic [$clog2(W+1)-1:0] count;  // steps remaining
    
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin
          state <= IDLE; mcand <= '0; mplier <= '0; acc <= '0; count <= '0;
        end else begin
          unique case (state)
            IDLE: if (start) begin
              mcand  <= {{W{1'b0}}, a};
              mplier <= b;
              acc    <= '0;
              count  <= W[$clog2(W+1)-1:0];
              state  <= RUN;
            end
            RUN: begin
              if (mplier[0]) acc <= acc + mcand;          // add the shifted multiplicand if this bit is 1
              mcand  <= mcand << 1;
              mplier <= mplier >> 1;
              count  <= count - 1'b1;
              if (count == 1) state <= DONE;
            end
            DONE: state <= IDLE;
            default: state <= IDLE;
          endcase
        end
    
      assign busy    = (state != IDLE);               // includes DONE: !busy means start can be accepted
      assign done    = (state == DONE);
      assign product = acc;
    endmodule
    

    Remember

    • Acceptance is edge 0, iterations run at edges 1 to W, and the product and done follow edge W. The earliest next acceptance is edge W + 2.

    • done marks a valid product, and !busy marks readiness for a new operation. They are different signals.

    • The multiplicand register must be 2W bits wide, or the high bits are silently dropped.

    Rule of thumb: count latency from the acceptance edge and say which edge a consumer samples on.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Combinational arithmetic

    • Memory read sequencer

    Previous

    104 / 350

    Next: Memory Read Sequencer with Latency

    Up next

    Up nextMemory Read Sequencer with Latency

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Sequencer Robustness
    13 x 11 = 143, sampled just before each edgeclkstartbusydonemultiplier (hex)0b5210product (hex)0d278f
    13 × 11. The accumulator becomes 13 after the first step, 39 (0x27) after the second, stays at 39 for the 0 bit, and reaches 143 (0x8f) after the fourth. Iterations 5 through 8 add nothing. With acceptance at edge 0, done rises after edge 8 and is observed pre-edge at edge 9.