12 · DSP multipliers vs logic

The MAX 10 has hardware multipliers. This example runs the same multiply-accumulate engine twice, once in them and once in ordinary logic, checks both against Python, and measures what each costs.

Verified on the board 2026-10-24 Quartus Prime Lite 17.1 No shield needed Skill: use-dsp-multipliers
Download dsp_multipliers.qar (full project)

The repo keeps the full project (.qar, plus the sources here) but no prebuilt bitstream: one build (a few minutes) makes the .sof on your computer.

The result

One 18 × 18 signed multiplierEmbedded multiplier (DSP)Logic elements
Resources2 multiplier elements, 0 logic elements368 logic elements
Fastest clock for the engine (Fmax, slow corner)175 to 187 MHz81 to 93 MHz
Runs here at100 MHz75 MHz (at 100 MHz it failed timing by 0.78 ns)
Result of 1,000,000 multiply-adds01E17200A92801E17200A928

The Python reference (sim/mac_reference.py) gives 01E17200A928 too. The 10M50 has 288 multiplier elements (144 of 18 × 18), so a design can have up to 144 multiplies running every clock for free. Fmax moves a few MHz between builds; the ranges are from the builds of this example.

The 7-segment display showing PASS.

What you will see

WhereWhat
HEX3..HEX0PASS when both engines match the expected result, FAIL if not, RUN while running
LEDR0, LEDR1, LEDR9DSP done, logic done, pass
KEY0Run again (each run is 10 ms at 100 MHz)
Your PCDSP acc=01E17200A928 cycles=000F4241 and the same for LOGIC (0xF4241 = 1,000,001 clocks)

Block diagram

pll_de10c0 100 MHzc1 75 MHz mac (USE_DSP = 1) @ 100 MHz 2 LFSRs → a, b (18-bit) → mult18_dsp → p → acc += pmultstyle "dsp": embedded multiplier mac (USE_DSP = 0) @ 75 MHz same, with mult18_logicmultstyle "logic": 368 logic elements 50 MHz sidedone → synchronizercompare with expected HEX: PASS USB → PC

How to choose where a multiply goes

(* multstyle = "dsp" *)                       // or "logic"
module mult18_dsp (input signed [17:0] a, input signed [17:0] b, output signed [35:0] p);
  assign p = a * b;
endmodule

Things learned building it

Run it

python scripts/de10.py build examples/12_dsp_multipliers
python scripts/de10.py program examples/12_dsp_multipliers
python scripts/de10.py log 2

Build it yourself

python scripts/new_project.py examples/12_dsp_multipliers mult_top --lib pll print seg7
python scripts/de10.py build examples/12_dsp_multipliers

Test without the board

python examples/12_dsp_multipliers/sim/mac_reference.py 1000      → acc=FFDBBCBDE1C7
python scripts/sim.py examples/12_dsp_multipliers/sim/tb_mac.sv      → both styles FFDBBCBDE1C7   PASS

Files

FileWhat
src/mult_top.svTop: PLL, two engines, compare, display, report
src/mac.svThe engine, plus mult18_dsp and mult18_logic
src/timing.sdcClocks and the false path for the results
sim/mac_reference.py, sim/tb_mac.svPython reference and unit test