Repository navigation
Build Backends
A target does not know which toolchain builds it. For each vendor, a platform class names the
device, the I/Os and the constraints, a toolchain class writes the project files and the
scripts, runs the tools and names the bitstream, and vendor primitives (I/O buffers, DDR
registers, clock managers) are only reached through generic specials each backend implements.
Swap --toolchain=diamond for trellis and the same target builds; this is also what keeps
the cores portable (The LiteX approach).
python3 -m litex_boards.targets.lattice_ecp5_evn --toolchain=trellis --build # Yosys, nextpnr, Project Trellis
python3 -m litex_boards.targets.lattice_ecp5_evn --toolchain=diamond --build # the vendor tool, same targetA platform file (litex_boards/platforms/<board>.py, or your own) instantiates the vendor
platform with the device name, the I/O list, the connectors, the default clock, and says which
programmer to use:
from litex.build.generic_platform import *
from litex.build.xilinx import XilinxPlatform
from litex.build.openfpgaloader import OpenFPGALoader
_io = [
("clk100", 0, Pins("E3"), IOStandard("LVCMOS33")),
("user_led", 0, Pins("H5"), IOStandard("LVCMOS33")),
("serial", 0,
Subsignal("tx", Pins("D10")),
Subsignal("rx", Pins("A9")),
IOStandard("LVCMOS33")
),
]
class Platform(XilinxPlatform):
default_clk_name = "clk100"
default_clk_period = 1e9/100e6
def __init__(self, toolchain="vivado"):
XilinxPlatform.__init__(self, "xc7a35ticsg324-1L", _io, toolchain=toolchain)
def create_programmer(self):
return OpenFPGALoader("arty_a7_35t")
def do_finalize(self, fragment):
XilinxPlatform.do_finalize(self, fragment)
self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6)The design requests its pins from it (platform.request("serial")), adds sources and
constraints (add_source, add_period_constraint, add_false_path_constraint,
add_platform_command), and --toolchain selects among the toolchains the family supports;
Add a new board is the step by step page.
Vendor (litex/build/) |
Families | --toolchain |
Programmers |
|---|---|---|---|
xilinx |
Spartan-6, 7-Series, UltraScale, UltraScale+ |
ise; vivado, yosys+nextpnr, openxc7, f4pga; vivado
|
Vivado, openFPGALoader, OpenOCD, XC3SProg, UrJTAG, iMPACT, Adept |
altera |
Cyclone IV, V and 10, MAX 10, Stratix V, Arria, Agilex 3, 5 and 7 | quartus |
USB-Blaster (quartus_pgm), openFPGALoader |
lattice |
iCE40, ECP5, Nexus (CrossLink-NX, Certus-NX) |
icestorm; trellis, diamond; oxide, radiant
|
openFPGALoader, OpenOCD, iceprog, ecpprog, ecpdap, ujprog, tinyprog, pgrcmd, DFU |
gowin |
GW1N, GW2A, GW5A |
gowin, apicula
|
Gowin programmer, openFPGALoader |
efinix |
Trion, Titanium, Topaz | efinity |
Efinix programmer, openFPGALoader |
colognechip |
GateMate A1, A2, A4 |
colognechip, peppercorn
|
openFPGALoader |
microsemi |
IGLOO2, PolarFire, ProASIC3 | libero_soc |
Libero |
quicklogic |
EOS S3 | f4pga |
the QORC SDK tools |
anlogic |
Eagle, Elf |
td (TangDynasty) |
TangDynasty programmer |
sim |
verilator |
SoC simulator |
How each tool is found
-
Vivado, ISE:
vivadoorisein thePATH, orLITEX_ENV_VIVADOandLITEX_ENV_ISEpointing to the install (itssettings64.shis sourced); openxc7 needsCHIPDB, F4PGAF4PGA_INSTALL_DIR. -
Quartus:
quartus_maporquartus_synin thePATH(--synth-tool). -
Yosys and nextpnr flows (icestorm, trellis, oxide, apicula, peppercorn, yosys+nextpnr):
yosysandnextpnr-*in thePATH. -
Diamond, Radiant:
diamondcorpnmaincin thePATH(WSL supported). -
Gowin EDA:
gw_shin thePATH(alsogw_sh.exefrom WSL). -
Efinity:
LITEX_ENV_EFINITYpointing to the install, orefx_run.pyin thePATH. -
CologneChip:
yosys, thenp_rornextpnr-himbaechelin thePATH. -
Libero:
liberoin thePATH; TangDynasty:tdin thePATH; F4PGA:f4pga.
The open-source flows share the Yosys and nextpnr options (--yosys-abc9, --yosys-flow3,
--yosys-nowidelut, --yosys-slang for SystemVerilog sources, --nextpnr-seed,
--nextpnr-timingstrict, --nextpnr-ignoreloops) and the packer ones (--ecppack-compress,
--ecppack-freq, --ecppack-bootaddr, --ecppack-spimode on ECP5, --nexus-es-device,
--force-die and --strategy on GateMate). Vivado has its directives
(--vivado-synth-directive, --vivado-place-directive, --vivado-route-directive...),
--vivado-max-threads, --vivado-report-level, --synth-mode yosys (Yosys synthesis, Vivado
place and route) and --no-project-mode; Efinity --synth-mode speed|area|area2; Radiant
--synth-mode synplify|yosys. python3 target.py --toolchain=<x> --help lists them.
The scripts and project files land in build/<platform>/gateware/ (build_<platform>.sh,
the .tcl, the .xdc, .lpf, .cst, .sdc or .pcf) and can be re-run by hand.
--build-backend edalize hands the generated files to Edalize
instead of LiteX's own scripts (icestorm and f4pga flows).
A core never instantiates a vendor primitive. litex/build/io.py defines generic specials
that each backend lowers to its primitives (<vendor>/common.py, the *_special_overrides):
| Special | Purpose |
|---|---|
DifferentialInput, DifferentialOutput, DifferentialTristate
|
LVDS and other differential I/Os. |
SDRInput, SDROutput, SDRTristate, DDRInput, DDROutput, DDRTristate
|
Registered and double data rate I/Os (I/O registers, ODDR, IDDR). |
SerDesInput, SerDesOutput, SerDesTristate
|
I/O serializers and deserializers where the device has them. |
ClkInput, ClkOutput, Tristate
|
Clock buffers, tristate I/O. |
MultiReg, AsyncResetSynchronizer
|
Clock domain crossing registers and reset synchronizers, with the vendor's attributes. |
The clock managers are in litex/soc/cores/clock/ (Cores), the
transceivers in LiteICLink and in the PHYs of the cores (a LiteEth or LiteDRAM PHY is one file
per family). A design that uses only these specials builds on every vendor; one that needs an
Instance of a vendor primitive keeps it in a device adapter
(architectural_style.md).
platform.add_source("core.v") (or .sv, .vhd, with language= and library=) adds files
to the project; the toolchains that read VHDL or SystemVerilog use them directly, and for the
ones that do not:
-
VHD2VConverterconverts VHDL to Verilog with GHDL at build time (--std=08), flattened with Yosys on request (Microwatt, NEORV32, the CTU CAN FD core use it). -
Amaranth2VConverterelaborates an Amaranth module to Verilog (Minerva, Sentinel, LUNA). -
--yosys-slangmakes the Yosys flows read SystemVerilog through the slang plugin.
Reuse an existing core wraps a core written in any of them.
A build often has to run where the toolchain is (a build server, a Windows machine with the
vendor tools): --build-bundle records every input of a build (the sources, the Python import
roots, the command, the environment) in a .tar.gz under <output-dir>/bundles/ with a
manifest, and litex_build_bundle --run-local <archive> replays it. litex_remote_build --host user@server -- python3 target.py --build does the round trip over SSH: bundle, upload, replay
there, copy build/ back (Tools).
--load calls platform.create_programmer().load_bitstream(...) and --flash
prog.flash(address, file): openFPGALoader for most boards, OpenOCD (with the bscan SPI proxy
bitstreams for flashing through JTAG), the vendor programmers, DFU for the boards with a DFU
bootloader. Load and flash has the installation and the details.
- Add a new board: a platform file of your own, and the platform classes of each vendor.
-
Load and flash: the programmers behind
--loadand--flash. - Reuse an existing core: Verilog, VHDL, SystemVerilog, Amaranth in your SoC.
-
SoC simulator: the
simbackend, Verilator.
Have a question or want to get in touch? Join us on Discord or on IRC: #litex at irc.libera.chat. This wiki is generated from doc/wiki in the LiteX repository: edit it with a pull request.
- Start here
- Build your SoC
- Run software on it
- How LiteX works
- Reference
- Projects and community
- For AI agents