SPI Master/Slave IP
A memory-mapped SPI core that puts a full master and a full slave behind two independent AXI4-Lite register banks in one core. All four SPI transfer modes standard 4-wire, 3-wire half duplex, Dual and Quad are selected from the register map at run time, with no rebuild between them.
Overview
The RunX SPI Controller (spi_top) instantiates a master that generates
chip select and the serial clock, and a slave that is clocked by an
external master, each with its own AXI4-Lite register bank and neither
wired to the other inside the core. A transfer is set up by writing the
clock rate, mode and framing into CFG, the payload into the TXD
registers, and the enable/start bits into CTRL; the result appears in the
RXD registers once the hardware-owned done indication changes state.
Two build-time generics let one RTL source scale to exactly what an
application needs: G_ROLE selects master-only, slave-only or both, and
G_MODE can fix a single transfer mode at elaboration instead of leaving
it runtime-selectable. Together they cut the core from 3441 LUTs (both
roles, every mode runtime-selectable) to 729 LUTs (master-only, STD-only)
a 79% reduction with the same source.
Specifications
| Specification | Value |
|---|---|
| Bus interface | AMBA AXI4-Lite × 2 (independent master and slave register banks) |
| Transfer modes | STD (4-wire) · 3-wire · Dual · Quad runtime-selectable by default |
| SPI modes | 0 – 3 (all CPOL/CPHA combinations) |
| Bit order | MSB-first or LSB-first, run-time selectable |
| Transfer size | 1 – 123 bits, over a 128-bit flat payload |
| Registers | 12 × 32-bit per side, offsets 0x00 – 0x2C |
| Interrupt | One level-sensitive line per side, driven by a toggling done bit |
| Clock domains | 1 (clk_i) the slave oversamples the external SCK rather than using it as a clock |
| Source language | VHDL, with a Verilog wrapper (IP_spi.v) for packagers |
| Vendor support | AMD Xilinx (built & timing-closed) · Altera (synthesized) · Lattice · Microchip |
| Logic (AMD/Xilinx, Zynq UltraScale+) | 3441 LUT (both roles, runtime) down to 729 LUT (master-only, STD-only) |
| Fmax (AMD/Xilinx) | 97.0 MHz tested operating point (reference design, +4.890 ns WNS) |
Resource figures are out-of-context Vivado 2025.2 synthesis of spi_top on
xck26-sfvc784-2LV-c; Fmax is the routed timing of the reference design and
is a tested point, not a swept maximum. Altera (Quartus Prime,
Agilex 3) Fmax ranges 222–320 MHz across the same role/mode matrix, from
~800 LUT/ALUT (master-only, STD-only) to ~5000 (both roles, runtime mode).
Standard-mode frame
A standard-mode (4-wire) transfer: the master drives chip select and the
serial clock, and MOSI/MISO shift a full-duplex payload for as many clocks
as CTRL.data_size selects.
How it compares
| RunX SPI | AMD/Xilinx AXI Quad SPI | Altera SPI core | |
|---|---|---|---|
| Resource usage | 729 – 3441 LUT / 540-1120 FF (role/mode dependent) | 442-479 LUT / 676 FF (role/mode dependent) | 922 ALM / 1320 FF |
| Fmax | 97.0 MHz tested (Xilinx) | 276 MHz | 302 MHz |
| Master + slave in one core | Yes, independent register banks | No, one has to be selected | No, one has to be selected |
| Runtime mode switching | STD / 3-wire / Dual / Quad, at run time | STD / Dual / Quad, at elaboration | STD / Dual / Quad, at run time |
| Software controllable | 12 registers per side + bare-metal C driver | bare-metal C driver | bare-metal C driver |
Other columns are to be completed from the current vendor datasheets & implementations.. Resource and frequency figures are only comparable when measured on the same device family and speed grade, so each cell should record the part it was taken on.
Parameterisation
| Parameter | Purpose |
|---|---|
G_MODE | RUNTIME (default) keeps every transfer mode selectable at run time; STD/3WIRE/DUAL/QUAD fixes one mode at elaboration |
G_ROLE | BOTH (default) instantiates master and slave; MASTER/SLAVE builds a single-role core |
G_BIT_SIZE | Payload width, 128 bits by default |
G_DW / G_AW | AXI4-Lite data/address widths, 32-bit / 8-bit by default |
G_DEVICE | Vendor inference hint: Xilinx · Altera · Lattice · Microchip · generic |
Verification
| Aspect | Detail |
|---|---|
| Environment | SystemVerilog regression testbench plus a passive protocol checker |
| Scenario coverage | 436 regression configurations across all four modes, all CPOL/CPHA combinations, transfer sizes and turnaround positions |
| Protocol compliance | ~49,450 passive-checker assertions |
| Synthesis/timing | Clean on the Zynq UltraScale+ reference design (Vivado) |
| Current status | Simulation passing; Validated with various different SPI modules |
Deliverables
- ✓ Synthesizable VHDL RTL source, five modules under
spi_top - ✓ Verilog wrapper (
IP_spi.v) for IP packagers - ✓ Bare-metal C driver for both sides (Apache-2.0), blocking and non-blocking
- ✓ Reference pseudocode documenting the register-level sequence
- ✓ SystemVerilog regression testbench and protocol checker
- ✓ Timing constraints (XDC) from the reference design
- ✓ Product User Guide (PDF)
- ✓ Block diagram and waveform sources
Why this core
Runtime flexibility, build-time economy. Every transfer mode is
register-selectable by default, and when an application only ever needs
one mode or one role, G_ROLE/G_MODE recover up to 79% of the LUTs a
fully flexible build would cost the same source serves both cases.
Master and slave from one core. Independent AXI4-Lite register banks for each side mean one bitstream can drive external SPI devices, answer an external master, or bridge the two, without instantiating two separate IPs.
Open driver, licensed RTL. The bare-metal C driver is Apache-2.0 and can be redistributed with an end product; the RTL itself is licensed separately, under NDA.
Software included. A complete driver blocking, timeout and non-blocking paths, for both master and slave ships with the core, not just register-level pseudocode.
© 2026 RunX Technology Inc. · Mission-Critical FPGA Design www.run-x.com · info@run-x.com