SPI-over-JTAG bridges: adding new parts¶
This page documents how to build SPI-over-JTAG (SOJ) bridge bitstreams for
new FPGA parts. The sources live in
src/transport_db/spiOverJtag/
(the source README in that directory is the canonical copy for contributors
working in the tree). For how bridges work at runtime, read
SPI-over-JTAG bridges — theory of operation.
Why bridges exist¶
Lattice ECP3/ECP5, Gowin GW2/GW5, and Cologne Chip GateMate have an
internal interface to access external SPI flash via JTAG. In contrast,
accessing SPI flash on Xilinx, Efinix and Altera Cyclone FPGAs
requires loading a dedicated bitstream that bridges the JTAG and SPI
interfaces. spiOverJtag contains those bridge bitstreams.
Important notes
spiOverJtagsupports single-wire mode only (MOSI/MISO) for maximum board compatibility.- Existing bridge bitstreams are versioned in the repository. Rebuild is typically required only when adding support for a missing FPGA model/package.
Dependencies¶
makegzippython3- Python package:
edalize - Vendor toolchains (depending on target family):
- Xilinx: Vivado and/or ISE
- Altera: Quartus
- Efinix: Efinity
Notes:
build.pyis used for Xilinx and Altera targets.efinix_build.pyis used for Efinix targets.
Build generalities¶
All steps below are performed from the spiOverJtag sub-directory.
Generated outputs:
- Xilinx:
spiOverJtag_<part>.bit.gz - Efinix:
spiOverJtag_efinix_<part>.bit.gz - Altera:
spiOverJtag_<part>.rbf.gz
Build command examples:
# Xilinx Artix7 35t
make spiOverJtag_xc7a35t.bit.gz
# Altera Cyclone10CL 016
make spiOverJtag_10cl016484.rbf.gz
# Efinix Trion T13 F256
make spiOverJtag_efinix_t13f256.bit.gz
Clean temporary/build files:
make clean
Package-specific bitstreams¶
Some boards within the same FPGA family/size use different SPI flash pin
mappings depending on the device package. When the SPI pins differ between
packages, build.py must produce a distinct bitstream per package rather
than aliasing one build to every package via symlinks.
To build a package-specific bitstream, pass the full device name
(device + package) to make. Example for the QMTech XC7A100T (FGG676)
core board:
make spiOverJtag_xc7a100tfgg676.bit.gz
This consumes constr_xc7a_fgg676.xdc and produces a bitstream wired to
the FGG676 SPI dedicated configuration pins (C8/B19/A18/B18/A19).
Add support for a new device¶
1. Register the part in Makefile¶
Add the short part name into the appropriate list:
XILINX_PARTSALTERA_PARTSEFINIX_PARTS
2. Update build script mappings¶
For Xilinx (build.py), the approach depends on family:
- for
Artix,Kintex 7andSpartan 7, size and packages are provided via thepackagesdict; - for other devices,
pkg_name(Vivado) ortool_options(ISE) must be updated to add the relationship between FPGA model/size/package and device/package.
For Altera (build.py): the full_part dict must be updated to match the
short format and a Quartus-compatible device name.
For Efinix (efinix_build.py): the script contains pin mapping data for
Trion and Titanium devices. Update efinix_pinout with a new sub-dict that
provides the pin name for each SPI IO, and add an entry for the new FPGA to
the timing_models dict. For Titanium devices, ensure the package mapping
exists in efinix_pinout["Titanium"] and the corresponding timing model
exists in timing_models.
3. Add constraints (if required)¶
spiOverJtag already contains many constraint files. Devices in the same
family with the same package usually share the same JTAG and SPI pinout
(for example, Xilinx Artix-7 devices with ftg256 can reuse
constr_xc7a_ftg256 regardless of device size). This step is only required
when a package is not yet available for a given FPGA family.
Add the constraint file expected by the mapping:
- Xilinx Vivado:
constr_<name>.xdc - Xilinx ISE:
constr_<name>.ucf - Altera: no explicit constraint file in this directory (handled by Quartus and the script flow)
- Efinix: generated/handled by
efinix_build.py; update script data for new package pinouts when needed
4. Build the bitstream¶
Run the target build command and verify the compressed file is generated:
# Xilinx/Efinix
make spiOverJtag_<new-part>.bit.gz
# or for Altera
make spiOverJtag_<new-part>.rbf.gz
At the end of the tool execution, a new bitstream should be present in the current directory.
Note The directory
tmp_<part>/(ortmp_efinix_<part>/) is the working directory and may be removed after bitstream generation.
Installing the result¶
Copy the generated file to the installation share directory with the
naming convention spiOverJtag_<part>.bit.gz (or bpiOverJtag_<part>),
where <part> matches the device + package string of the part catalog.
The binary finds it through the configured data directory, overridable with
OPENFPGALOADER_SOJ_DIR.