From oh-my-fpga
Generate a bitstream and program a Xilinx FPGA over JTAG, or build an MCS image and burn it into SPI/BPI configuration flash for power-on boot. Invoke when the user says "program the board", "generate bitstream", "flash the device", "download to FPGA", "burn the flash", "load my design onto the board", "make a .mcs / .bit", or "why won't my board come up after power cycle". Covers the full hand-off from a routed implementation to live silicon: DRC + route + timing sign-off gating, .bit generation, hardware-server / JTAG connect, volatile JTAG download, and non-volatile flash programming (generate_mcs + add_flash_configuration + program_flash). Requires the SynthPilot MCP server with Vivado running and the Tcl server connected; flash / JTAG steps additionally require a physical board cabled to the host (or reachable through a remote hw_server).
How this skill is triggered — by the user, by Claude, or both
Slash command
/oh-my-fpga:bitstream-programThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A methodology playbook for taking a **routed implementation** all the way to
A methodology playbook for taking a routed implementation all the way to live silicon — either a volatile JTAG download (lost on power cycle) or a non-volatile flash burn (boots on power-up). Programming hardware is a one-way, physical action: this skill is deliberately conservative. It refuses to fabricate a "programmed OK" claim, refuses to skip sign-off gates, and hands control back to the human at every ambiguous fork (which device, which flash part, which boot mode).
This skill is a strategy layer over the SynthPilot MCP server. It does not write code; it decides which real tools to call, in what order, and when to STOP.
.bit produced from the current implemented design..mcs/.bin) into SPI/BPI configuration
memory so the FPGA boots it automatically on power-up..xsa hand-off to Vitis (export hardware with bitstream)..bit from a design with
setup/hold violations may program but will behave non-deterministically. Close
timing first (use the timing-closure skill). Do not generate a sign-off
bitstream over an open WNS violation without an explicit, stated user override..ltx probes file.Do not assume state. Probe it with real tools before acting.
test_connection. If this fails,
nothing downstream can work; stop and tell the user to start Vivado and the
Tcl server.get_project_info. Confirm the
part/board matches what the user intends to program. The wrong part silently
produces a bitstream the device will reject.get_run_status. The
implementation run must be route_design Complete (or equivalent "routed").
If it is synth-only, out of date, or failed, the design is not ready —
go run/finish implementation (see Methodology step 1) before any bitstream.State everything you found before proceeding. If a prerequisite is missing, report it and stop — do not improvise around a missing board or an unrouted run.
The flow has three phases: (A) sign-off gate → (B) bitstream → (C) deliver to device. Phase C splits into a volatile JTAG lane and a non-volatile flash lane. Pick the lane from the decision table below; do not run both blindly.
A bitstream is only as trustworthy as the implemented design behind it. These are fresh-evidence gates: read them now, do not trust a prior claim.
Ensure a complete implementation exists.
get_run_status → if not routed, run it. For multi-minute P&R prefer the
async pattern: run_implementation_async, then poll get_run_status until
complete. (run_implementation is the synchronous fallback for short runs.)open_implemented_design so the reports below read the
routed netlist, not synthesis.Route completeness — report_route_status. Every net must be fully
routed. Any unrouted / partially-routed / conflict nets ⇒ not signable —
stop and route (or report the failure). A .bit over an incomplete route is
invalid.
DRC — report_drc. Resolve (or consciously, with the user, accept)
Critical Warnings/Errors before programming. Bitstream-relevant DRCs
(e.g. DRC BIVRT, unconstrained I/O, config-bank/voltage, BUFGCE/clock
placement) can produce a .bit that damages or refuses to configure the part.
Do not waive a config/IO DRC just to get a green light — see Safety rails.
Timing sign-off — report_timing_summary. Read WNS/TNS/WHS fresh.
Gate rule: a "ready to program" claim REQUIRES fresh
report_route_status+report_drc+report_timing_summaryoutput in this session. Never infer it.
generate_bitstream (synchronous; jobs defaults to 4).
.ltx probes file next to the .bit..bit path. If generation fails, read
the error summary it returns — common causes are config-bank voltage
(CONFIG_VOLTAGE/CFGBVS) or BITSTREAM.* property DRCs surfaced only at
write time. Fix the property/constraint (smallest safe change), re-run the
Phase-A DRC, and regenerate. Do not retry blindly.Choose the lane from the Decision table. Establish the hardware connection (common to both lanes) first.
Connect to hardware (JTAG/flash both need this):
open_hardware_managerconnect_hardware_server (defaults to localhost:3121; pass a url for a
remote hw_server).open_hardware_target (empty arg auto-selects the first target).list_hardware_devices — confirm the discovered device matches the
project part from step (Prereq 2). If the chain is empty, STOP: no board /
bad cable / hw_server not running. If the part mismatches, STOP and ask —
programming the wrong device is a hardware risk.Shortcut:
quick_programauto-connects and downloads the current project bitstream in one call (and auto-skips Zynqarm_*debug devices). Prefer it only when the chain is unambiguous (single FPGA, default hw_server) and Phase A has already passed. For multi-device chains, remote servers, or any ambiguity, use the explicit connect chain above so you can verify the device before committing.
program_device.
bitstream_path empty to use the project default, or pass the path
captured in step 5..ltx probes file found beside the bitstream and
refreshes the device afterward.refresh_hardware_device.Pick the flash part — ask, don't guess. The configuration-memory part
number and interface (SPI x1/x2/x4, QSPI, BPI) are board-specific. The
wrong part/width burns a non-bootable image. If the user hasn't named the
exact part, ask. Then add_flash_configuration with the correct
flash_type (e.g. a s25fl…, mt25q…, etc. part string).
Build the flash image — generate_mcs.
bitstream_path (from step 5), an output mcs_path, and
flash_size (MB) that matches the physical flash density (default 128).
A size larger than the device, or a wrong start address, yields a
non-bootable image.BITSTREAM.CONFIG.SPI_BUSWIDTH /
CONFIG.CONFIGRATE match the flash wiring; a x4 image into x1 wiring won't
boot. If these properties are unset, raise it before burning.Burn the flash — program_flash with the mcs_file from step 8.
Prove it boots from flash — the only real test of a flash burn. A
successful write+verify proves the bytes are in flash; it does not prove
the FPGA will configure from them. Instruct the user to set the board to the
correct boot mode (e.g. QSPI/Master-SPI strap or MODE[2:0] pins),
power-cycle, and confirm the DONE LED / design behavior. Then
refresh_hardware_device / list_hardware_devices to see the device now
re-configured from flash. If it doesn't come up, this is the classic
"won't come up after power cycle" failure — go to the troubleshooting table.
export_hardware
(include_bitstream=True) to emit the .xsa, then hand off to the embedded
skill. Do not attempt the software build here.| Symptom / request | Likely cause | Smallest safe action (in order) |
|---|---|---|
| "Just test it on the bench now" | Volatile download is fine | Lane 1: program_device (or quick_program if chain is unambiguous) |
| "It must boot by itself on power-up" | Needs non-volatile config memory | Lane 2: add_flash_configuration → generate_mcs → program_flash → verify boot |
generate_bitstream fails with CFGBVS/CONFIG_VOLTAGE DRC | Config bank voltage not declared | Add/correct CFGBVS/CONFIG_VOLTAGE in XDC (constraint, not RTL), re-run report_drc, regen |
generate_bitstream fails with unconstrained-I/O DRC | Pins/IOSTANDARD missing | Add I/O constraints (create_io_constraint), re-run report_drc, regenerate |
list_hardware_devices returns empty | No board / cable / hw_server down | STOP. Ask user to connect & power the board; check JTAG cable; confirm hw_server running |
| Discovered device ≠ project part | Wrong board, wrong target, or wrong project open | STOP. Do not program. Reconcile target vs part with the user |
Zynq: extra arm_* targets on chain | PS debug devices appear alongside the PL | Program the PL FPGA device; quick_program auto-skips arm_* |
| JTAG download works, but dead after power cycle | Design was only in volatile SRAM config, not in flash | Lane 2: program flash + set correct boot-mode straps + power-cycle |
| Flash burned + verified, still won't boot from flash | Wrong boot mode, wrong flash part/size, or bus width | Re-check flash_type & flash_size vs board; check boot-mode pins & SPI_BUSWIDTH; re-burn |
| WNS < 0 but user wants a bitstream | Design not signed off | Report violation; default = refuse sign-off .bit; build only on explicit "bench test anyway" |
| Need Vitis / software image | Hardware hand-off | export_hardware(include_bitstream=True) → embedded skill |
Programming is iterative only on failure-to-configure; a clean program is a single pass. The loop exists to converge a non-booting device, one change-class per iteration so cause→effect is attributable.
[Phase A gates] → generate_bitstream → connect HW → verify device==part
→ program (Lane 1 or Lane 2) → READ device status (fresh)
│
configured/DONE asserted? ──yes──► STOP (success, with evidence)
│ no
▼
Classify ONE failure class (boot mode | flash part/size | bus width |
config DRC | wrong device) → apply ONE fix
→ re-verify with a tool → loop
STOP immediately (do not iterate) when:
refresh_hardware_device / list_hardware_devices.STOP and present options (don't thrash) when:
flash_type
once) and it still won't boot. Surface the remaining hypotheses (boot-mode
straps, flash density, bus width, board power) with their costs, and hand
back to the human. Do not loop on flash parts blindly — each burn wears the
device and may not be the real cause.No fake-pass on the sign-off gate. Never waive a route/DRC/timing failure
— or apply set_false_path / waive_lint_violation / disable a DRC — purely
to make generate_bitstream succeed or to declare the design "ready". A
config-bank, I/O, or clocking DRC can mean the bitstream will not configure
or could electrically stress the part. If a violation might be real, fix it
or ask the user; state any assumption explicitly.
Evidence before claims — always. "Bitstream generated", "device
programmed", "flash verified", "boots from flash" each REQUIRE the
corresponding fresh tool output in this session
(generate_bitstream path, program_device/program_flash status,
refresh_hardware_device/list_hardware_devices). Never infer success from a
prior step, and never report a flash burn as "boots" until a power-cycle
re-config is observed.
Confirm the target device before you commit. Always reconcile
list_hardware_devices against the project part before program_device /
program_flash. Programming the wrong device or wrong flash part is a physical
hazard, not a software typo.
Ask before destructive / board-specific choices. Flash part number, flash size, bus width, and boot mode are board facts you cannot derive from the project. If unknown, ask — do not pick a plausible default and burn it.
Smallest safe change first. Bitstream-write DRC failures are almost always
constraint/property fixes (XDC: CFGBVS, CONFIG_VOLTAGE, IOSTANDARD,
BITSTREAM.*), not RTL. Fix constraints first. Recommend — never silently
apply — any RTL change; that re-opens synth/impl and a new sign-off.
Volatile vs non-volatile must be stated. Always tell the user whether what
you just did survives a power cycle. A JTAG program_device does not; only
a flash burn does.
One change-class per iteration. When chasing a non-booting board, change exactly one thing (boot mode or flash part or bus width) and re-measure, so the fix that worked is unambiguous.
Report concisely, with evidence quoted from tool output, not narration:
.bit path returned by generate_bitstream, and whether a
.ltx probes file accompanied it.list_hardware_devices and explicit
confirmation it matches the project part.program_device status (DONE asserted / configured), and a clear
note that this is volatile (lost on power cycle).flash_type, flash_size, the .mcs path, the program_flash
write+verify result, and the boot-mode + power-cycle instruction the user
must perform — plus the post-power-cycle list_hardware_devices evidence if
obtained.Never end with an unverified "done." End with the evidence, or with the precise reason you stopped.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub lnc0831/oh-my-fpga --plugin oh-my-fpga