Bitstream program
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).From its SKILL.md
npx -y skills add LNC0831/oh-my-fpga --skill bitstream-programAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 16 stars16 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
18.8 KB, as published. Nobody here has run it
Bitstream Generation & Device Programming
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.
When to use
- User wants a
.bitproduced from the current implemented design. - User wants to download a design to a board over JTAG for a bench test (volatile — gone after power cycle).
- User wants to flash the design (
.mcs/.bin) into SPI/BPI configuration memory so the FPGA boots it automatically on power-up. - User reports a board that "doesn't come up after power cycle" (almost always a flash / boot-mode issue, not a JTAG issue).
- User wants an
.xsahand-off to Vitis (export hardware with bitstream).
When NOT to use
- Timing is not met / design is not routed. A
.bitfrom 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. - Synthesis/implementation has not run or is stale relative to the RTL. Generating a bitstream does not re-run P&R; it ships whatever is in the run. Run/refresh implementation first.
- Debug-core insertion (ILA/VIO) — that belongs to the debug/instrumentation
skill. This skill only consumes an already-inserted
.ltxprobes file. - Pure simulation requests — use the simulation skill.
- Block-design / IP build — use the block-design skill; come back here once a routed implementation exists.
Prerequisites (verify first)
Do not assume state. Probe it with real tools before acting.
- MCP / Vivado / Tcl bridge alive —
test_connection. If this fails, nothing downstream can work; stop and tell the user to start Vivado and the Tcl server. - A project is open and is the right one —
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. - Implementation is complete and current —
get_run_status. The implementation run must beroute_design Complete(or equivalent "routed"). If it issynth-only, out of date, or failed, the design is not ready — go run/finish implementation (see Methodology step 1) before any bitstream. - For any JTAG/flash step: a board is physically present. This cannot be inferred from software state alone. The hardware-manager connect chain (Methodology step 5) is what discovers it; if no target appears, STOP and ask the user to plug in / power on the board and check the cable.
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.
Methodology (real tool calls, in order)
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.
Phase A — Sign-off gate (MUST pass before any bitstream)
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 pollget_run_statusuntil complete. (run_implementationis the synchronous fallback for short runs.)- On completion,
open_implemented_designso 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.bitover 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.bitthat 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.- WNS ≥ 0 and WHS ≥ 0 (no setup/hold failures) ⇒ pass the timing gate.
- WNS < 0 or WHS < 0 ⇒ the design is not signed off. Do not silently proceed. Report the violation and hand back to timing-closure. Only generate a bitstream over open violations if the user explicitly says "I know timing fails, build it anyway for a quick bench test" — and then label the artifact as not sign-off quality in the Output.
Gate rule: a "ready to program" claim REQUIRES fresh
report_route_status+report_drc+report_timing_summaryoutput in this session. Never infer it.
Phase B — Generate the bitstream
- Generate —
generate_bitstream(synchronous;jobsdefaults to 4).- This step embeds the routed configuration and (if debug cores were inserted)
emits a
.ltxprobes file next to the.bit. - On return, capture the reported
.bitpath. If generation fails, read the error summary it returns — common causes are config-bank voltage (CONFIG_VOLTAGE/CFGBVS) orBITSTREAM.*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.
- This step embeds the routed configuration and (if debug cores were inserted)
emits a
Phase C — Deliver to the device
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 tolocalhost:3121; pass aurlfor a remotehw_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.
Lane 1 — Volatile JTAG download (bench test; lost on power cycle)
- Program over JTAG —
program_device.- Leave
bitstream_pathempty to use the project default, or pass the path captured in step 5. - It auto-associates a
.ltxprobes file found beside the bitstream and refreshes the device afterward. - If you need a fresh status snapshot,
refresh_hardware_device. - Verify, don't assume: report the tool's success/DONE status as the evidence. A volatile download is not persistent — say so explicitly so the user knows a power cycle wipes it.
- Leave
Lane 2 — Non-volatile flash (boots on power-up)
-
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_configurationwith the correctflash_type(e.g. as25fl…,mt25q…, etc. part string). -
Build the flash image —
generate_mcs.- Inputs:
bitstream_path(from step 5), an outputmcs_path, andflash_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. - For QSPI boot, confirm the design's
BITSTREAM.CONFIG.SPI_BUSWIDTH/CONFIG.CONFIGRATEmatch the flash wiring; a x4 image into x1 wiring won't boot. If these properties are unset, raise it before burning.
- Inputs:
-
Burn the flash —
program_flashwith themcs_filefrom step 8.- This writes (and the tool verifies) the configuration memory. Report the tool's verify result as evidence.
-
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. Thenrefresh_hardware_device/list_hardware_devicesto 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.
Optional — Hand off to embedded software
- If the user wants Vitis / bare-metal / Linux work,
export_hardware(include_bitstream=True) to emit the.xsa, then hand off to the embedded skill. Do not attempt the software build here.
Decision table — which lane and which fix
| 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 loop + STOP conditions
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:
- No board / chain empty → hand back to user (physical action required).
- Discovered device ≠ project part → never program a mismatched device.
- A DRC/timing gate is failing and the user has not explicitly authorized a non-sign-off build → hand back to the relevant skill.
- Success: the device reports configured / DONE asserted (JTAG lane), or the
board re-configures from flash after a power cycle (flash lane), confirmed by a
fresh
refresh_hardware_device/list_hardware_devices.
STOP and present options (don't thrash) when:
- You've tried the obvious fix in a failure class (e.g. corrected
flash_typeonce) 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.
Safety rails (do not violate)
-
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 makegenerate_bitstreamsucceed 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_bitstreampath,program_device/program_flashstatus,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_devicesagainst the project part beforeprogram_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_devicedoes 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.
Output
Report concisely, with evidence quoted from tool output, not narration:
- Readiness gate — route status (fully routed?), DRC (Critical count and any un-waived items), and timing (WNS / WHS / TNS), each with the tool that produced it. State pass/fail explicitly. If any gate failed and you proceeded anyway, label the artifact NOT sign-off quality and name the override.
- Bitstream — the
.bitpath returned bygenerate_bitstream, and whether a.ltxprobes file accompanied it. - Target — the discovered device(s) from
list_hardware_devicesand explicit confirmation it matches the project part. - Programming result —
- Lane 1:
program_devicestatus (DONE asserted / configured), and a clear note that this is volatile (lost on power cycle). - Lane 2:
flash_type,flash_size, the.mcspath, theprogram_flashwrite+verify result, and the boot-mode + power-cycle instruction the user must perform — plus the post-power-cyclelist_hardware_devicesevidence if obtained.
- Lane 1:
- If stopped: the exact blocking condition (no board / device mismatch / failing gate / exhausted safe options) and the specific decision or physical action handed back to the user — with options + costs, not a guess.
Never end with an unverified "done." End with the evidence, or with the precise reason you stopped.