Skip to content

VHDL · Chapter 17.3 · FPGA-Oriented VHDL Design

Inferring DSP and Multiplier Blocks

A multiply is expensive in LUTs but cheap in a DSP block, the FPGA's dedicated arithmetic slice: a pipelined multiplier fused with an adder or accumulator and wrapped in input and output registers. Inferring it is mostly about the arithmetic shape, since a plain multiply infers the multiplier, a multiply-add infers a multiply-accumulate, and an accumulate infers the accumulator. The single most important habit is registering the inputs and outputs so the tool can use the DSP's internal pipeline registers, which is what unlocks its high speed; an unregistered multiply maps to a slow, large LUT version instead. This lesson also covers the per-DSP width limit and how wider multiplies combine several blocks, where signed and unsigned come from, the optional pre-adder, and forcing the mapping with an attribute.

Foundation15 min readVHDLFPGADSPMultiplierMACPipelining

1. Engineering intuition — feed the DSP the way it's built

A DSP slice is not just a multiplier; it is a multiplier wrapped in registers with an accumulator behind it, designed to run fast precisely because those registers pipeline the multiply. So inferring a DSP well is about handing it the shape it wants: a multiply (or multiply-add, or accumulate) with its inputs and outputs registered, so the tool slots your registers into the DSP's own pipeline stages. Give it an unregistered, combinational multiply and the synthesizer either builds a slow LUT multiplier or a DSP that can't run fast. Register generously around arithmetic and the DSP runs near its peak frequency; that registering — which on an FPGA is essentially free (16.6) — is the whole trick.

2. Formal explanation — multiplier, MAC, and accumulator inference

dsp_inference.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
signal a, b : signed(17 downto 0);          -- within a DSP's width (signed from the type)
 
-- MULTIPLY → DSP multiplier. REGISTER inputs + output → uses the DSP's internal pipeline registers.
process (clk) begin if rising_edge(clk) then
  a_r    <= a;  b_r <= b;                    -- INPUT registers (DSP stage)
  prod_r <= a_r * b_r;                       -- OUTPUT register (DSP stage) → high Fmax
end if; end process;
 
-- MULTIPLY-ADD → DSP MAC:
mac_r <= a_r * b_r + c_r;                    -- multiply then add, fused in the DSP
 
-- ACCUMULATE → DSP accumulator (e.g. FIR/dot-product):
process (clk) begin if rising_edge(clk) then
  acc <= acc + a_r * b_r;                    -- multiply-accumulate in the DSP's adder
end if; end process;
 
-- WIDTH: each DSP has a max operand size (e.g. ~18x25/27); wider multiplies COMBINE several DSPs.
-- FORCE: attribute use_dsp of prod_r : signal is "yes";   -- (vendor-specific, 16.8)

A numeric_std multiply infers the DSP multiplier; multiply-add infers a MAC; accumulate infers the accumulator. Register inputs and outputs so the tool maps your registers to the DSP's internal pipeline stages (the key to Fmax). Width limits per DSP; wider ops combine DSPs. Signed/unsigned from the type; optional pre-adder; use_dsp to force.

3. Production usage — a pipelined multiply-accumulate

pipelined_mac.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- A dot-product / FIR tap: register inputs, multiply, accumulate — all in DSP slices.
process (clk) begin
  if rising_edge(clk) then
    x_r <= x;  coef_r <= coef;                       -- DSP input registers
    if start = '1' then acc <= (others => '0');
    else                acc <= acc + x_r * coef_r;   -- DSP MAC: pipelined multiply-accumulate
    end if;
  end if;
end process;
result <= std_logic_vector(acc);
 
-- WIDE multiply needing more than one DSP: the tool stitches DSPs together automatically
-- when operands exceed a single DSP's width (e.g. 32x32 from several 18x25 blocks).

What hardware does this become? A chain of DSP slices: the input registers (x_r, coef_r) become the DSP's input pipeline stage, the x_r * coef_r the DSP multiplier, and acc + ... the DSP's accumulator — a multiply-accumulate running at high Fmax because every stage is registered inside the block. A wider operand than one DSP supports causes the tool to combine multiple DSPs transparently. Skip the registers, and the same math falls into slow LUT logic or an underutilized DSP. So the design rule is simple and high-impact: register around every multiply so it lands in a properly-pipelined DSP.

4. Structural interpretation — the DSP slice

DSP slice: input registers, multiplier, accumulator/adder, output registerinput registersa_r, b_r (DSP stage)multipliera_r * b_radder / accumulator+ c or acc (MAC)output registerresult (DSP stage) → highFmax12
A DSP slice is a pipelined multiplier fused with an adder/accumulator and surrounded by input and output registers. Registering the operands maps them to the DSP's input pipeline stage; the multiply maps to the DSP multiplier; an add or accumulate maps to the DSP's adder/accumulator; and registering the result maps to its output stage — so a fully-registered multiply, multiply-add, or accumulate runs at high Fmax inside one block. Operands must fit the DSP's width limit, or several DSPs combine for wider multiplies; signed/unsigned comes from the type. This is a DSP-mapping structure; the waveform below shows the pipelined, registered MAC result.

5. Simulation interpretation — the pipelined MAC

Registered DSP MAC: pipeline latency, then one result per cycle

8 cycles
Registered DSP MAC: pipeline latency, then one result per cycleinput registers capture x,coef; prod (registered multiply) followsinput registers captur…accumulator adds each product: acc = 2, 6, C, 14, 1E (running sum)accumulator adds each …registered stages give pipeline latency but one MAC per cycleregistered stages give…clkx12345000coef22222000prod02468AAAacc0026C141E1Et0t1t2t3t4t5t6t7
Each cycle the DSP registers the operands, multiplies (prod), and accumulates into acc. There is a fixed pipeline latency from the input registers to the result, but a new multiply-accumulate completes every cycle — the high-throughput behavior the DSP's internal registers enable. The registering is exactly what lets the block run at its rated frequency; an unregistered multiply would be slower and might miss the DSP entirely.

6. Debugging example — the multiply that didn't use the DSP (or ran slow)

Expected: a fast multiply in a DSP block. Observed: synthesis builds a large LUT multiplier, or the DSP is used but timing is poor (low Fmax on the multiply path). Root cause: the multiply was unregistered (purely combinational), so the tool could not place registers in the DSP's internal pipeline stages — it either fell back to LUT logic or used a DSP without its registers, capping speed; or the operands exceeded one DSP's width without being structured to combine cleanly. Fix: register the inputs and output around the multiply so they map to the DSP's pipeline stages (the key to Fmax), keep operands within the width limit (or let the tool combine DSPs), match signed/unsigned to the type, and force with use_dsp if needed. Engineering takeaway: to get a fast DSP multiply, register around it so the DSP's internal pipeline registers are used — an unregistered multiply is slow and may not even land in a DSP.

register_the_multiply.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- BUG: combinational multiply → LUT multiplier or DSP without its pipeline regs → slow.
-- prod <= a * b;   -- no registers around it
-- FIX: register inputs and output → DSP internal pipeline → high Fmax.
process (clk) begin if rising_edge(clk) then
  a_r <= a; b_r <= b; prod_r <= a_r * b_r;
end if; end process;

7. Common mistakes & what to watch for

  • Unregistered multiplies. Register inputs/outputs so the DSP's internal pipeline registers are used — the key to Fmax; otherwise slow or LUT-mapped.
  • Exceeding DSP width. Operands beyond one DSP's size combine several DSPs; keep widths in mind for resource count.
  • Wrong signedness. signed/unsigned (the type) sets the multiply; a mismatch gives wrong results or misses optimizations.
  • Multiply in a long combinational path. Pipeline it (register around it) so the critical path doesn't stall Fmax (16.6).
  • Fighting inference. Prefer the registered numeric_std pattern; use use_dsp only when the tool picks wrong.

8. Engineering insight & continuity

DSP inference maps arithmetic onto the FPGA's dedicated slices: a numeric_std multiply → the multiplier, a multiply-add → a MAC, an accumulate → the accumulator — and the decisive habit is registering inputs and outputs so the DSP's internal pipeline registers are used, unlocking high Fmax (with width limits combining multiple DSPs as needed). Registers are cheap on an FPGA, so register generously around every multiply. With block RAM and DSP — the two big dedicated resources — covered, the remaining FPGA concern is the clocking that drives them: the next lesson, Clocking Resources and Clock Management — global buffers, PLLs/MMCMs, and generating the clocks a design needs.