RV32 Booth-MAC Core
projects / digital design / riscv-mac

A Booth multiply‑accumulate unit, inside a five‑stage RISC‑V core

A custom-0 MAC extension with a 64-bit saturating accumulator and Q15 read-out, built on a radix-4 Booth multiplier, integrated into a pipelined RV32IM processor and taken from Verilog to a routed FPGA with open-source tools.

Verilog-2005Icarus VerilogYosys 0.70nextpnr-ecp5LFE5U-85F
Submitted by
Mohsin Mushtaq 2025MECECS001
Mubashir Karim Ganaie 2025MECECS005
Submitted to
Dr. Afshan Amin Khan
Department
Electronics and Communications, NIT Srinagar
placed & routed core · ECP5 tiles X0–55, Y0–27
Core Fmax34.6MHzpost-route, speed grade 6
MAC unit Fmax56.4MHz78.8 MHz on DSP blocks
Logic cells7,5669.0 % of the device
Generic gates25,286core + MAC, 2-input cells
FIR speed-up2.67×unrolled, vs RV32IM
Best CPI1.037unrolled MAC FIR
Unit-level checks88,8960 errors
FIR output128/ 128bit-exact vs golden
Toolchain

Open-source, end to end

RTLVerilog-2005, Icarus Verilog 12, GTKWave
SoftwareProject assembler in Python; RV32IM + custom-0 programs
SynthesisYosys 0.70, generic gates and synth_ecp5
Place and routenextpnr-ecp5 on LFE5U-85F, CABGA756
Gate-level simYosys netlist on the unchanged testbench, zero-delay
Figuresnetlistsvg schematics, trace-based pipeline charts
Architecture

The MAC unit rides the pipeline

The MAC unit's two internal registers line up with the core's EX/MEM and MEM/WB registers, so a mac moves down the pipeline like any other instruction and writes back in WB.

1 · IF2 · ID3 · EX4 · MEM5 · WB IF/IDID/EXEX/MEMMEM/WB FetchDecodeExecuteMemoryWrite-back PC + 4 KiB I-memnext PC / target decode, immediatesreg file + bypasshazard unit forwarding muxesALU, 33×33 RV32Mbranch resolve 16 KiB D-membyte / half / word ALU, load or MACresult → rd MAC STAGE 1MAC STAGE 2 decode + Booth 34×34ACC64 ± · saturate · Q15 taken branch → PC, flush 2 WB → EX forwarding
Memory map
0x0000_0000Instruction memory, 4 KiB, loaded from the program image
0x0001_0000Data memory, 16 KiB, byte enables
custom-0mac msu mul.acc macu rdacc.lo rdacc.hi rdacc.q15 clracc
Design choices
  • AccumulatorA dedicated 64-bit register keeps full precision for 32×32 products with only two register-file read ports.
  • SaturationSigned MACs clamp to the INT64 limits and set a sticky flag; rdacc.q15 turns Q30 into Q15 in one instruction.
  • HazardsOnly a consumer placed directly after a MAC result waits one cycle, exactly like a load; the value then comes from WB.
Floorplan

Every placed cell on the die

Cells from nextpnr coloured by block, over a copper routing-density map. The view opens framed on the logic; zoom out with − for the whole die and ⤢ to come back. Drag to pan, Ctrl/⌘ + scroll to zoom, hover a tile to see what is in it.

X — · Y — · zoom 1.0×

Fmax
Critical path
Logic cells
Flip-flops
Critical path: logic vs routing delay
logicrouting
Sign-off

Every check has its own script

The unit testbenches compare against an independent reference model; the processor runs real RISC-V programs and compares every output sample bit by bit.

CheckResultNotes
Booth multiplier85,545 · 0 errAll 65,536 8-bit pairs, 34-bit corners and 20,000 random pairs
MAC unit testbench3,351 · 0 err13 test groups; scoreboard on rd, ACC, OVF and 2-cycle latency
Gate-level netlistpassYosys netlist on the same testbench, zero-delay
isa_test on the core18 / 18Every instruction class, forwarding, load-use and MAC-use stalls
FIR programs, 4 versions128 / 128 exactUnwanted tone −60.1 dB against a design value of −60.2 dB
Mutation testsall caughtBroken saturation, WB forwarding and stall logic each fail the tests
Yosys check -assert0 issuesNo latches, loops or undriven nets; 179 flip-flops match the RTL
Timing, core at 50 MHz target34.6 MHzCritical path through the single-cycle RV32M multiplier
Performance

Same filter, two instruction sets

A 16-tap Q15 low-pass FIR over 128 samples, measured with the core's cycle counters. All four versions produce the same bit-exact output.

One mac replaces the six-instruction 64-bit multiply-accumulate sequence, and rdacc.q15 replaces a 14-instruction shift-and-saturate routine.

Notes from the build

What the numbers taught

28.9 nscore critical path

The multiply that sets the clock

The pipelined MAC unit is not the slowest path. It runs from WB forwarding, through the forwarding mux and the single-cycle RV32M multiplier on four DSP blocks, into EX/MEM; 18.9 ns of it is routing. Pipelining mul the way the MAC unit already is would be the next timing fix.

−7,109gates saved

One multiplier instead of three

Separate 64-bit products for MUL, MULH, MULHSU and MULHU, plus a register file with a reset, made the first core 22,412 gates. One shared 33×33 multiplier and a reset-free register file in LUT-RAM brought it to 15,303 with identical results.

79 %of MAC gates

Where the Booth area goes

The Booth multiplier is most of the stand-alone MAC unit and the routing hot spot on the die. Yosys' own Booth and Wallace-tree generator saves 21 % of the gates but keeps the same 127-level depth, because the ripple-carry final adder sets it.

1.59× → 2.67×looped → unrolled

What's next

Post-increment loads and a hardware loop would let looped DSP code reach unrolled speed. After that: a parallel-prefix adder for the Booth multiplier, a pipelined RV32M multiplier, block-RAM memories and a run on a real ECP5 board.