Bootloaders and DFU
USB DFU and other FPGA bootloaders, multiboot.
Cores
ULX3S/ULX4M USB DFU bootloader (had2019-playground) (best)
The gateware ULX3S/ULX4M ship from flash address 0: PicoRV32 + no2usb-derived USB device core enumerating as DFU 1d50:614b, writing the user bitstream to flash 0x200000 via a QSPI master, with a 6-zone alt-setting layout. Fully documented in docs/DFUs.md.
| Repository | emard__had2019-playground: HAD2019 badge playground |
| Files | projects/bootloader/rtl, projects/bootloader/fw, cores/usb/rtl |
| Top module | top |
| Language | Verilog, C |
| License | per file: bootloader RTL BSD-3-Clause, USB core + DFU firmware LGPL-3.0-or-later, picorv32.v ISC (see docs/DFUs.md) |
| FPGA / primitives | ECP5: TRELLIS_IO, OFS1P3DX, IDDRX1F, USRMCLK |
| Tests | none found (cores/usb/sim + project tbs are waveform-only, never run to a pass/fail check) |
On ULX3S: USER_BITSTREAM_ADDR, dfu_zones[0] (fw/usb_dfu.c) and ecpmulti –address must all agree; PROGRAMN (LPF site M4) must loop back for hand-off.
Fomu foboot DFU bootloader (LiteX/VexRiscv + ValentyUSB eptri)
LiteX/Migen-generated SoC on a VexRiscv CPU with ValentyUSB’s eptri (TriEndpointInterface) USB device peripheral providing the DFU class in a single alt-0 interface; boots the flashed user image after a timeout unless the two Fomu touch pads are bridged to force staying in DFU.
| Repository | im-tomu__foboot: Foboot: the Fomu iCE40 UP5K failsafe USB DFU bootloader, LiteX/Migen SoC |
| Files | hw/rtl/VexRiscv_Fomu.v, hw/rtl/spimemio.v, hw/deps/valentyusb/valentyusb/usbcore |
| Top module | VexRiscv |
| Language | Verilog (SpinalHDL-generated VexRiscv core), Python/Migen (SoC + USB peripheral, hw/*.py), C (sw/) |
| License | foboot itself Apache-2.0 (LICENSE); ValentyUSB submodule BSD-3-Clause (hw/deps/valentyusb/LICENSE) |
| FPGA / primitives | iCE40: none (portable) |
| Tests | hw/deps/valentyusb/sim (cocotb, test-eptri.py/cocotb-eptri.py): self-checking, raises TestFailure/uses assertEqual; none found for the SoC or bootloader firmware itself |
On ULX3S: Architecturally unlike every other bootloader-dfu entry here: a LiteX/Migen SoC generated by Python, not hand-written RTL, needing the LiteX build flow rather than a plain yosys+nextpnr Makefile. Its migen/litex/litedram/litex-boards/spibone/compiler_rt submodules were deliberately not fetched in this clone (only hw/deps/valentyusb was), so it cannot be rebuilt from this clone.
Used by 2 other catalogued repos (file copies or module instances found by scan_core_usage.py; heuristic):
- emeb__orangecrab-litex-adc (instantiates
hw/deps/valentyusb/valentyusb/usbcore/cpu/cdc_eptri.py) - orangecrab-fpga__orangecrab-examples (instantiates
litex/deps/valentyusb/valentyusb/usbcore/cpu/cdc_eptri.py)
Hazard3-Doom vendored DFU bootloader (ULX4M-LD validated)
Self-contained fork of the had2019 bootloader (own mk/, cores/, no external Makefile deps), remapped buttons, validated on real ULX4M-LD v0.0.3 (LFE5UM-85F) hardware, with a byte-for-byte readback recovery procedure documented in README_ULX4M_BOOTLOADER.md.
| Repository | ulx3s__hazard3-doom: ulx3s/Hazard3-Doom: Doom |
| Files | bootloader/rtl, bootloader/fw, bootloader/cores |
| Top module | top |
| Language | Verilog, C |
| License | provenance in LICENSES/HAD2019-Bootloader-NOTICE.md; per-file licenses match the emard original (BSD-3/LGPL-3.0+/ISC) |
| FPGA / primitives | ECP5: TRELLIS_IO, OFS1P3DX, IDDRX1F, USRMCLK |
| Tests | none found (same iverilog-compile-only sim rule as the original) |
On ULX3S: Prefer this copy over the emard original for a self-contained tree; same USER_BITSTREAM_ADDR/dfu_zones agreement rule applies.
Machdyne tinydfu-bootloader (ECP5, TinyFPGA-derived USB core)
Per-board ECP5 DFU bootloader (Lakritz/Obst/Konfekt/etc.), always resident at flash 0 and auto-booting the user partition after a timer unless DFU activity intervenes. USB device core is a bit-banged full-speed PHY+SIE (usb_fs_*.v) plus usb_dfu_core.v, adapted by Lawrie Griffiths/Owen Kirby from Luke Valenti’s original TinyFPGA bootloader core (per usb_dfu_core.v header) - a third, independent USB-device lineage distinct from no2usb and ValentyUSB.
| Repository | machdyne__tinydfu-bootloader: TinyDFU Bootloader: multi-board USB DFU bootloader |
| Files | usb/usb_dfu_core.v, usb/usb_dfu_ctrl_ep.v, boards/lakritz/tinydfu_lakritz.v, boards/lakritz/boardinfo.vh |
| Top module | tinydfu_lakritz |
| Language | Verilog |
| License | Apache-2.0 (LICENSE.txt) |
| FPGA / primitives | ECP5: USRMCLK |
| Tests | testbenches/i2c_master_tb.v only (unrelated I2C helper); no USB/DFU-core testbench found |
On ULX3S: Not ULX3S; fills the ECP5 gap in this list with a bootloader that is neither no2usb- nor ValentyUSB-derived. VID:PID 0x16d0:0x116d is per-board, hardcoded in each boards/
no2bootloader (Nitro) iCE40 UP5K DFU bootloader
Complete multi-board iCE40 UP5K DFU bootloader (PicoRV32 SoC + no2usb device core): alt 0 = iCE40 bitstream, alt 1 = RISC-V firmware; SB_WARMBOOT cycles between a boot stub (0x004000), the DFU image (0x040000) and two app images (0x080000/0x0c0000). Used by iCEBreaker-bitsy, reDIP-SID, icE1usb.
| Repository | no2fpga__no2bootloader: Nitro Bootloader: iCE40 UP5K DFU bootloader |
| Files | gateware/ice40/rtl, gateware/cores/no2usb, firmware/fw_dfu.c |
| Top module | top |
| Language | Verilog, C |
| License | HDL CERN-OHL-P-2.0 (own RTL in gateware/ice40/rtl and gateware/cores/no2usb, per LICENSE.md); this repo’s firmware GPL-3.0-or-later (LICENSE.md); no2usb stack LGPL-3.0-or-later, MIT for the tinyusb-driver-reused parts (gateware/cores/no2usb/LICENSE.md) |
| FPGA / primitives | iCE40: SB_PLL40_2F_CORE, SB_PLL40_2F_PAD, SB_IO, SB_WARMBOOT, SB_HFOSC, SB_GB |
| Tests | gateware/ice40/sim/{top_tb.v,dfu_helper_tb.v} + cores/{no2usb,no2misc,no2ice40}/sim: iverilog compile only, no vvp run found in the Makefiles - waveform-only |
On ULX3S: iCE40 UP5K only (SB_WARMBOOT/SB_PLL40_2F); no ECP5 port in this collection. gateware/build (no2build) submodule was deliberately not fetched here, so this clone cannot actually be synthesized or simulated.
no2usb DFU runtime + dfu_helper.v (iCE40)
Button debouncer that reboots into the no2bootloader DFU image via SB_WARMBOOT (long press) or resets the app (short press); the DFU class firmware itself (usb_dfu.c/usb_dfu_rt.c) lives in the fetched no2usb submodule.
| Repository | smunaut__ice40-playground: iCEBreaker: collection of iCE40 UP5K IP cores |
| Files | projects/riscv_usb/rtl/dfu_helper.v |
| Top module | dfu_helper |
| Language | Verilog |
| License | mixed CERN-OHL-P-2.0/LGPL-3.0-or-later/MIT per file (doc/LICENSE-*.txt) |
| FPGA / primitives | iCE40: SB_WARMBOOT |
| Tests | none found for dfu_helper.v itself |
On ULX3S: iCE40-only (SB_WARMBOOT multiboot); porting to ECP5 needs a different warm-boot mechanism plus the no2bootloader project, which is not in this collection.
Full review: smunaut__ice40-playground.
Used by 4 other catalogued repos (file copies or module instances found by scan_core_usage.py; heuristic):
- icebreaker-fpga__icebreaker-verilog-examples (instantiates
icebitsy/blink_count_shift/blink_count_shift.v) - icebreaker-fpga__icetwang (instantiates
soc/ice-twang/rtl/top.v) - no2fpga__no2bootloader (instantiates
gateware/ice40/rtl/top.v) - osmocom__osmo-e1-hardware (instantiates
gateware/e1-tracer/rtl/misc.v)
TinyFPGA USB Bootloader (USB-serial-to-SPI-flash bridge)
Full-speed USB device MAC/PHY presenting a virtual serial port bridged to SPI-flash read/write/erase commands, so a host programmer can reflash the FPGA’s config/user images with no separate USB-JTAG chip; common/ core has no vendor primitives, only the per-board top does.
| Repository | tinyfpga__tinyfpga-bootloader: TinyFPGA USB Bootloader: USB virtual-serial-to-SPI-flash-bridge gateware bootloader; |
| Files | common/usb_fs_rx.v, common/usb_fs_tx.v, common/usb_fs_pe.v, common/usb_serial_ctrl_ep.v, common/usb_spi_bridge_ep.v, common/tinyfpga_bootloader.v |
| Top module | tinyfpga_bootloader |
| Language | Verilog |
| License | Apache-2.0 (LICENSE) |
| FPGA / primitives | iCE40 (also ported to ECP5 12F via Lattice Diamond in boards/TinyFPGA_EX, and to Xilinx Artix-7): none (portable) |
| Tests | self-checking (29 tests/*/test.v via iverilog, TAP-style asserts in expect_usb_ack() etc., tests/test.mk) |
On ULX3S: Not proven on ULX3S; the fielded ULX3S US2 DFU bootloader (had2019-dfu-bootloader) is unrelated (no2usb-derived). An older ULX3S bootloader, emard__tinyfpga-bootloader-ulx3s, was a direct fork of a 60MHz variant of this exact core.
Used by 8 other catalogued repos (file copies or module instances found by scan_core_usage.py; heuristic):
- arisotura__spi_flash (copies
spi_flash/source/usb/usb_serial_ctrl_ep.v) - emard__tinyfpga-bootloader-ulx3s (instantiates
boards/ulx3s/bootloader_ulx3s.v) - fdarling__orangecrab-usb-cdc-demo (copies
tinyfpga_bx_usbserial/usb/usb_serial_ctrl_ep.v) - joshajohnson__ecp5-mini-projects (copies
verilog/common/usb/usb_serial_ctrl_ep.v) - machdyne__tinydfu-bootloader (copies
usb/usb_serial_ctrl_ep.v) - orangecrab-fpga__orangecrab-examples (copies
verilog/usb_acm_device/blocks/usbserial/usb/usb_serial_ctrl_ep.v) - osresearch__spispy (copies
verilog/usb/usb_serial_ctrl_ep.v) - osresearch__up5k (copies
usb/usb_serial_ctrl_ep.v)
Other catalogued projects
Catalogued repos tagged bootloader (39) are listed in the full catalogue.