A boot menu / core loader for the MEGA65, built as a reconfigurable module (RM) that runs inside the mega65-shell Xilinx 7-series partial-reconfiguration (DFX) static shell. It is a small picorv32 RISC-V soft SoC — video, keyboard, SD card and QSPI flash — whose firmware presents a menu of loadable cores and swaps them in through the shell's ICAP / IPROG paths.
The menu lists loadable cores from two sources and, on selection, hands off to the shell to bring one in:
- QSPI flash — full
.corimages in 4 MB slots (slot 0 = the shell itself). Booted via anIPROGwarm reconfiguration through the shell's doorbell. - SD card —
*.BINpartial bitstreams streamed through the shell's descriptor loader into the ICAP (replacing this RM in place), plus*.CORfiles that can be flashed into a slot (ENTER on the file).
Flash slots can be programmed from SD .COR files and erased in place (E on a
slot), with a MEGA65-style staged progress bar (erase / program / verify) and
border flashing. Each entry shows a source icon — a chip glyph for flash slots,
an SD-card glyph for SD files.
Two boards are supported from one shared source set:
| Board | Make target suffix | Notes |
|---|---|---|
| MEGA65 R6 | (none) — the default | S25FL512S QSPI flash |
| QMTECH Wukong dev board | _wukong |
S25FL128L QSPI flash |
The SoC and firmware are board-agnostic; only the top wrapper (rm_top_r6.vhd /
rm_top.vhd) and QSPI geometry differ.
firmware/ picorv32 firmware (C + start.S): menu UI, FAT32, QSPI flash driver,
progress bar, MHexes text/screen helpers
src/ RM VHDL: picosoc_top SoC, HDMI/VGA video, keyboard, SD SPI,
QSPI flash controllers (…s25flxxxl / …s25flxxxs), chargen ROM
scripts/ build.tcl (Vivado flow), prog.tcl (JTAG), upload.py (UART),
mk_cor.py (.cor packaging), character_rom.py
ext/ picorv32 CPU (git submodule)
sim/ VHDL testbenches
constr/ board constraints
Requires Vivado 2023.2 (at /opt/Xilinx/Vivado/2023.2/bin/vivado, override with
VIVADO=) and a RISC-V bare-metal toolchain (riscv64-elf-, override with
CROSS=). Clone with submodules:
git clone --recurse-submodules git@github.com:0xa000/mega65-shell-menu.gitThe RM implements against a locked mega65-shell static build; see the
mega65-shell repo for the static side. Common targets (append _wukong for
the Wukong board):
make impl # Step 4: full DFX flow → build/config_picorv32_r6.bit
make full # bake current firmware into BRAM + rebuild the bitstream
make cor # baked build wrapped as build/menu_r6.cor (flash-slot image)
make prog_full # program the full bitstream via JTAG
make upload # push firmware to a running SoC over the UART bootloader
make cleanDuring development the firmware is pushed over UART rather than re-baked into the bitstream (a rebake invalidates every Vivado target). Typical loop:
make prog_full # once — program shell + RM
make upload # after each firmware edit (set PORT= to your serial device)make fw_pkg regenerates the baked BRAM image (build/firmware_pkg.vhd) when
you do want it in the bitstream; make full / make cor do this for you.
- Feed the ICAP loader
.binpartials only (no header) — the config engine skips to the sync word, so a.corheader just rides in front for flash slots. - This is one of the RM-side checkouts of a larger DFX proof-of-concept; the static shell (which owns I/O, clocks and the ICAP/IPROG loader) is the canonical mega65-shell repo.