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

SKILL.md

GitHub

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 .bit produced 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 .xsa hand-off to Vitis (export hardware with bitstream).

When NOT to use

  • Timing is not met / design is not routed. A .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.
  • 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 .ltx probes 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.

  1. 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.
  2. 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.
  3. Implementation is complete and current — 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.
  4. 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.

  1. 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.)
    • On completion, open_implemented_design so the reports below read the routed netlist, not synthesis.
  2. 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.

  3. 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.

  4. 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_summary output in this session. Never infer it.

Phase B — Generate the bitstream

  1. Generate — generate_bitstream (synchronous; jobs defaults to 4).
    • This step embeds the routed configuration and (if debug cores were inserted) emits a .ltx probes file next to the .bit.
    • On return, capture the reported .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.

Phase C — Deliver to the device

Choose the lane from the Decision table. Establish the hardware connection (common to both lanes) first.

  1. Connect to hardware (JTAG/flash both need this):

    • open_hardware_manager
    • connect_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_program auto-connects and downloads the current project bitstream in one call (and auto-skips Zynq arm_* 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)

  1. Program over JTAG — program_device.
    • Leave bitstream_path empty to use the project default, or pass the path captured in step 5.
    • It auto-associates a .ltx probes 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.

Lane 2 — Non-volatile flash (boots on power-up)

  1. 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).

  2. Build the flash image — generate_mcs.

    • Inputs: 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.
    • For QSPI boot, confirm the design's 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.
  3. Burn the flash — program_flash with the mcs_file from step 8.

    • This writes (and the tool verifies) the configuration memory. Report the tool's verify result as evidence.
  4. 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.

Optional — Hand off to embedded software

  1. 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_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.

Safety rails (do not violate)

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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 .bit path returned by generate_bitstream, and whether a .ltx probes file accompanied it.
  • Target — the discovered device(s) from list_hardware_devices and explicit confirmation it matches the project part.
  • Programming result —
    • Lane 1: program_device status (DONE asserted / configured), and a clear note that this is volatile (lost on power cycle).
    • Lane 2: 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.
  • 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.