doc: refresh README/tutorial/CLAUDE for profiles, clock, SVF
Bring the docs up to date and keep each in its lane: - README (overview): both programming paths (Xilinx proxy flash + SVF), probe profiles, neutral JTAG clock + per-device cap, runtime YAML registry, IGLOO2 bundled; run-from-repo-root fixed - tutorial (user view): probe profiles + jtag_close, the prog tag, a JTAG-clock section, a new "Programming via SVF" section, prog/max_tck in the add-a-target table, troubleshooting rows - CLAUDE.md (design): architecture tree lists the project modules + YAML data files; roadmap gains phases 5 (probes/JTAG-link) and 6 (SVF) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
34
CLAUDE.md
34
CLAUDE.md
@@ -12,28 +12,40 @@ when reality changes, not for every transient task.
|
|||||||
|
|
||||||
`bs_explorer` is an application layer on top of Viveris's
|
`bs_explorer` is an application layer on top of Viveris's
|
||||||
[jtag-boundary-scanner](https://github.com/viveris/jtag-boundary-scanner)
|
[jtag-boundary-scanner](https://github.com/viveris/jtag-boundary-scanner)
|
||||||
library (LGPL). End goal: program SPI configuration memories attached
|
library (LGPL). End goal: program FPGAs/CPLDs over JTAG from a CLI tool
|
||||||
to FPGAs (Xilinx KU15P first, then others) over JTAG, from a CLI tool
|
on a host with an FTDI/Digilent/J-Link probe — Xilinx external SPI
|
||||||
running on a host with an FTDI probe.
|
configuration flash via a BSCAN proxy (started with the KU15P), and
|
||||||
|
other families (Lattice, Microsemi, …) by playing a vendor-exported SVF.
|
||||||
|
|
||||||
The Viveris library itself lives unchanged in `modules/`. Everything
|
The Viveris library itself lives unchanged in `modules/`. Everything
|
||||||
new is in `bs/` (the REPL) and future modules (`fpga/`, `bscan/`,
|
new is in `bs/` (the REPL) and the project modules (`fpga/`, `bscan/`,
|
||||||
`spi_flash/`) sitting alongside the Viveris ones.
|
`spi_flash/`, `svf/`, `probes/`) sitting alongside the Viveris ones.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
bs/ Application (readline REPL, no business logic)
|
bs/ Application (readline REPL, no business logic)
|
||||||
modules/ — Viveris's library (LGPL, unchanged) —
|
modules/
|
||||||
|
— Viveris's library (LGPL, unchanged) —
|
||||||
├── jtag_core/ TAP state machine, IR/DR shifts
|
├── jtag_core/ TAP state machine, IR/DR shifts
|
||||||
├── bsdl_parser/ .bsd loader
|
├── bsdl_parser/ .bsd loader
|
||||||
├── bus_over_jtag/ SPI/I²C/MDIO/parallel mem bit-bang over EXTEST
|
├── bus_over_jtag/ SPI/I²C/MDIO/parallel mem bit-bang over EXTEST
|
||||||
├── drivers/ FTDI, J-Link, Linux GPIO, LPT, Digilent (optional)
|
├── drivers/ FTDI, J-Link, Linux GPIO, LPT, Digilent (optional, dlopen)
|
||||||
├── script/ Script engine (40+ commands, the real UI)
|
├── script/ Script engine (the real UI)
|
||||||
├── config/ Built-in config.script
|
├── config/ Built-in config.script
|
||||||
├── os_interface/ Portable fs/network wrappers
|
├── os_interface/ Portable fs/network wrappers
|
||||||
└── natsort/ Natural pin-name sorting
|
├── natsort/ Natural pin-name sorting
|
||||||
|
— new (this project) —
|
||||||
|
├── fpga/ Registry loader (parses fpga_registry.yaml, libyaml)
|
||||||
|
├── bscan/ JTAG TAP primitives (set_ir/shift_ir/shift_dr/tap_reset/
|
||||||
|
│ idle_cycles) + BSCAN proxy (bitstream load, SPI-over-USER1)
|
||||||
|
├── spi_flash/ SPI NOR chip DB + read/erase/program/verify over a callback
|
||||||
|
├── svf/ SVF player (svf_play): SIR/SDR/RUNTEST/STATE, masked compare
|
||||||
|
└── probes/ Probe-config profiles loader (parses probes.yaml, libyaml)
|
||||||
|
fpga_registry.yaml FPGA registry (IDCODE → BSDL, IR opcodes, proxy, caveats, prog, max_tck)
|
||||||
|
probes.yaml Probe-config profiles (defaults + per-probe overrides)
|
||||||
bsdl_files/ BSDL files for target FPGAs
|
bsdl_files/ BSDL files for target FPGAs
|
||||||
|
bscan_proxies/ BSCAN proxy bitstreams (MIT, from quartiq)
|
||||||
scripts/ Example scripts
|
scripts/ Example scripts
|
||||||
doc/ Tutorial and longer-form docs (doc/tutorial.md is the end-to-end walkthrough)
|
doc/ Tutorial and longer-form docs (doc/tutorial.md is the end-to-end walkthrough)
|
||||||
libs/libftd2xx/ Vendored FTDI SDK
|
libs/libftd2xx/ Vendored FTDI SDK
|
||||||
@@ -49,10 +61,12 @@ Adding a feature usually means adding a new script command in
|
|||||||
| Phase | Module | Status | Summary |
|
| Phase | Module | Status | Summary |
|
||||||
|-------|--------|--------|---------|
|
|-------|--------|--------|---------|
|
||||||
| 1 | `bs/` cleanup, REPL polish, README | **done** (commit `7cb3627`) | Fix format-strings, delete dead code, tab-completion, banner |
|
| 1 | `bs/` cleanup, REPL polish, README | **done** (commit `7cb3627`) | Fix format-strings, delete dead code, tab-completion, banner |
|
||||||
| 2 | `fpga/` | **done** (commit `545fe09`) | Per-target descriptor (IDCODE, BSDL, IR codes, proxy path, caveats). Compile-time registry. |
|
| 2 | `fpga/` | **done** (commit `545fe09`) | Per-target descriptor (IDCODE, BSDL, IR codes, proxy path, caveats). Now a **runtime YAML** registry (`fpga_registry.yaml`, libyaml), later gaining `prog` method + `max_tck_khz`. |
|
||||||
| 2.5 | `bscan/` | **done** (commit `dec0d14`) | Load BSCAN proxy bitstream via `CFG_IN`, expose fast `bscan_spi_xfer()` via `USER1`. Required for realistic flashing speeds. |
|
| 2.5 | `bscan/` | **done** (commit `dec0d14`) | Load BSCAN proxy bitstream via `CFG_IN`, expose fast `bscan_spi_xfer()` via `USER1`. Required for realistic flashing speeds. |
|
||||||
| 3 | `spi_flash/` | **done** (commit `c4afe87`) | Chip DB (JEDEC ID → page/sector/cmd set) + generic `read/erase/program/verify` over an `xfer` callback. detect+read validated on KCU105; erase/program implemented but not yet hardware-tested. |
|
| 3 | `spi_flash/` | **done** (commit `c4afe87`) | Chip DB (JEDEC ID → page/sector/cmd set) + generic `read/erase/program/verify` over an `xfer` callback. detect+read validated on KCU105; erase/program implemented but not yet hardware-tested. |
|
||||||
| 4 | script commands | **done** (commit `d6f843e`) | `flash_detect`, `flash_read` (+file), `flash_erase`, `flash_write`, `flash_verify`. Full set validated on KCU105 (save/erase/write-random/verify/restore round-trip). ~100 KB/s write once the proxy is loaded. |
|
| 4 | script commands | **done** (commit `d6f843e`) | `flash_detect`, `flash_read` (+file), `flash_erase`, `flash_write`, `flash_verify`. Full set validated on KCU105 (save/erase/write-random/verify/restore round-trip). ~100 KB/s write once the proxy is loaded. |
|
||||||
|
| 5 | `probes/` + JTAG-link | **done** | `probes.yaml` probe-config profiles (`jtag_open <idx> <profile>`, `jtag_profiles`, `jtag_close`); driver-neutral `JTAG_TCK_FREQ_KHZ`/`JTAG_RTCK`; device `max_tck_khz` clock cap resolved at `jtag_autoinit`; `prog` method tag. See the config-strategy design note. Validated on the IGLOO2 (FlashPro). |
|
||||||
|
| 6 | `svf/` | **done** (subset, commit `c77d86e`) | SVF player + `svf_play`: SIR/SDR with masked TDO compare, RUNTEST, STATE — single-device. Validated on the IGLOO2 IDCODE; a real Libero SVF and a generic `program` dispatch off the `prog` tag are still TODO. |
|
||||||
|
|
||||||
Move forward phase by phase: validate one with the user before starting
|
Move forward phase by phase: validate one with the user before starting
|
||||||
the next. Don't break the validated path
|
the next. Don't break the validated path
|
||||||
|
|||||||
72
README.md
72
README.md
@@ -1,10 +1,14 @@
|
|||||||
# bs_explorer — Boundary Scan Explorer
|
# bs_explorer — Boundary Scan Explorer
|
||||||
|
|
||||||
Command-line tool to explore a JTAG chain, drive an FPGA's pins through
|
Command-line tool to explore a JTAG chain, drive an FPGA's pins through
|
||||||
boundary scan (BSDL), and program the SPI configuration flash attached
|
boundary scan (BSDL), and **program** parts over JTAG, from a host with
|
||||||
to an FPGA (Xilinx and others) over JTAG — fast, via a BSCAN proxy
|
an FTDI / Digilent / J-Link probe. Two programming paths:
|
||||||
|
|
||||||
|
- **Xilinx external SPI configuration flash** — fast, via a BSCAN proxy
|
||||||
bitstream loaded into the fabric (~100 KB/s), or slowly via EXTEST pin
|
bitstream loaded into the fabric (~100 KB/s), or slowly via EXTEST pin
|
||||||
bit-bang for one-shot checks.
|
bit-bang for one-shot checks;
|
||||||
|
- **everything else** (Lattice, Microsemi, CPLDs, …) — by playing a
|
||||||
|
vendor-exported **SVF** file (`svf_play`), one near-universal backend.
|
||||||
|
|
||||||
Based on the [jtag-boundary-scanner](https://github.com/viveris/jtag-boundary-scanner)
|
Based on the [jtag-boundary-scanner](https://github.com/viveris/jtag-boundary-scanner)
|
||||||
library by Viveris (LGPL).
|
library by Viveris (LGPL).
|
||||||
@@ -14,15 +18,17 @@ library by Viveris (LGPL).
|
|||||||
- JTAG chain detection through FTDI / J-Link / Linux GPIO / Digilent SMT2 probes: OK
|
- JTAG chain detection through FTDI / J-Link / Linux GPIO / Digilent SMT2 probes: OK
|
||||||
- Automatic BSDL loading by IDCODE: OK
|
- Automatic BSDL loading by IDCODE: OK
|
||||||
- Pin control in SAMPLE / EXTEST, incl. slow SPI bit-bang: OK
|
- Pin control in SAMPLE / EXTEST, incl. slow SPI bit-bang: OK
|
||||||
- Per-FPGA registry (IDCODE → BSDL, IR opcodes, proxy, caveats): OK
|
- FPGA registry (runtime YAML: IDCODE → BSDL, IR opcodes, proxy, caveats, programming method): OK
|
||||||
|
- Probe-config profiles (`probes.yaml`) + driver-neutral JTAG clock with per-device cap: OK
|
||||||
- BSCAN proxy SPI bridge (load proxy bitstream, talk SPI via `USER1`): OK
|
- BSCAN proxy SPI bridge (load proxy bitstream, talk SPI via `USER1`): OK
|
||||||
- SPI flash detect / read / erase / program / verify: OK (~100 KB/s via the proxy)
|
- SPI flash detect / read / erase / program / verify: OK (~100 KB/s via the proxy)
|
||||||
|
- SVF player (`svf_play`) — program any device from a vendor-exported SVF: OK (single-device subset)
|
||||||
|
|
||||||
Bundled BSDLs: Xilinx Kintex UltraScale+ KU15P
|
Bundled BSDLs: Xilinx Kintex UltraScale+ KU15P
|
||||||
(`bsdl_files/xcku15p_ffve1517.bsd`) and Kintex UltraScale KU040
|
(`xcku15p_ffve1517.bsd`), Kintex UltraScale KU040 (`xcku040_ffva1156.bsd`),
|
||||||
(`bsdl_files/xcku040_ffva1156.bsd`). Add more by dropping `.bsd` files
|
and Microsemi IGLOO2 M2GL010T (`m2gl010t-fg484.bsd`). Add more by dropping
|
||||||
in `bsdl_files/` (see [`doc/tutorial.md`](doc/tutorial.md) for adding a
|
`.bsd` files in `bsdl_files/` plus an entry in `fpga_registry.yaml` (see
|
||||||
target).
|
[`doc/tutorial.md`](doc/tutorial.md) for adding a target).
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
@@ -56,15 +62,23 @@ cmake -DBS_ENABLE_DIGILENT=OFF ..
|
|||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
|
Run from the repository root so the runtime data files are found — they
|
||||||
|
are looked up relative to the current directory:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd build
|
./build/bs/bs
|
||||||
./bs/bs
|
|
||||||
```
|
```
|
||||||
|
|
||||||
At startup, `bs_explorer` looks for a `config.script` file in the
|
`bs_explorer` reads, when present in that directory:
|
||||||
current directory to override default settings (FTDI clock, TRST/SRST
|
|
||||||
pin mapping, etc.). See `modules/config/config.script` for the full
|
- `config.script` — overrides built-in probe variables (FTDI clock,
|
||||||
list of variables.
|
TRST/SRST pin mapping, …); see `modules/config/config.script` for the
|
||||||
|
full list. Loaded at startup.
|
||||||
|
- `probes.yaml` — probe-config profiles, applied with
|
||||||
|
`jtag_open <idx> <profile>` (`$BS_PROBES` overrides the path).
|
||||||
|
- `fpga_registry.yaml` — the FPGA target registry
|
||||||
|
(`$BS_FPGA_REGISTRY` overrides the path).
|
||||||
|
- `bsdl_files/`, `bscan_proxies/` — BSDLs and proxy bitstreams.
|
||||||
|
|
||||||
## REPL
|
## REPL
|
||||||
|
|
||||||
@@ -76,31 +90,39 @@ list of variables.
|
|||||||
|
|
||||||
## Typical flow
|
## Typical flow
|
||||||
|
|
||||||
|
**Xilinx external SPI flash — via the BSCAN proxy:**
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# 1. List probes, open one by its index (the [N] in the list)
|
# 1. List probes, open one by its index ([N]). A probe that needs tweaks
|
||||||
|
# (e.g. an embedded FlashPro) takes a profile from probes.yaml:
|
||||||
bs_explorer> jtag_probes
|
bs_explorer> jtag_probes
|
||||||
[0] 0x00000000 <probe description>
|
bs_explorer> jtag_profiles # available profiles
|
||||||
bs_explorer> jtag_open 0 # or the raw 0x id shown next to it
|
bs_explorer> jtag_open 0 # or: jtag_open 0 <profile>
|
||||||
|
|
||||||
# 2. Scan the chain and auto-load matching BSDLs
|
# 2. Scan the chain and auto-load matching BSDLs
|
||||||
bs_explorer> jtag_autoinit
|
bs_explorer> jtag_autoinit # fpga_info then shows the prog method
|
||||||
|
|
||||||
# 3. Load the BSCAN proxy into the fabric (fast SPI bridge)
|
# 3. Load the BSCAN proxy into the fabric (fast SPI bridge)
|
||||||
bs_explorer> bscan_load_bitstream 0 bscan_proxies/bscan_spi_xcku040.bit
|
bs_explorer> bscan_load_bitstream 0 bscan_proxies/bscan_spi_xcku040.bit
|
||||||
|
|
||||||
# 4. Talk to the SPI flash through the proxy
|
# 4. Talk to the SPI flash through the proxy
|
||||||
bs_explorer> flash_detect 0 # JEDEC ID -> chip name / size
|
bs_explorer> flash_detect 0 # JEDEC ID -> chip name / size
|
||||||
bs_explorer> flash_read 0 0x0 256 # hex dump
|
|
||||||
bs_explorer> flash_erase 0 0x10000 4096
|
|
||||||
bs_explorer> flash_write 0 0x10000 image.bin
|
bs_explorer> flash_write 0 0x10000 image.bin
|
||||||
bs_explorer> flash_verify 0 0x10000 image.bin
|
bs_explorer> flash_verify 0 0x10000 image.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Anything else (Lattice, Microsemi, …) — play a vendor-exported SVF:**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bs_explorer> jtag_open 0 <profile> # e.g. flashpro for a Microsemi kit
|
||||||
|
bs_explorer> jtag_autoinit # identify; prog method should be 'svf'
|
||||||
|
bs_explorer> svf_play design.svf # exported from Libero / Diamond / Radiant
|
||||||
|
```
|
||||||
|
|
||||||
The slow EXTEST path (bit-bang SPI on boundary-scan pins, `jtag_mode 0
|
The slow EXTEST path (bit-bang SPI on boundary-scan pins, `jtag_mode 0
|
||||||
EXTEST` + `jtag_spi_*`) is only useful for one-shot checks — see the
|
EXTEST` + `jtag_spi_*`) is only useful for one-shot checks. A minimal
|
||||||
tutorial. A minimal example script is in `scripts/example_script.txt`;
|
example script is in `scripts/example_script.txt`; the full walkthrough
|
||||||
the full walkthrough (probe → proxy → flash) lives in
|
lives in [`doc/tutorial.md`](doc/tutorial.md).
|
||||||
[`doc/tutorial.md`](doc/tutorial.md).
|
|
||||||
|
|
||||||
## Main commands
|
## Main commands
|
||||||
|
|
||||||
@@ -159,6 +181,8 @@ modules/
|
|||||||
├── fpga/ Registry loader (parses fpga_registry.yaml at runtime)
|
├── fpga/ Registry loader (parses fpga_registry.yaml at runtime)
|
||||||
├── bscan/ JTAG TAP primitives + BSCAN proxy (bitstream, SPI-over-USER1)
|
├── bscan/ JTAG TAP primitives + BSCAN proxy (bitstream, SPI-over-USER1)
|
||||||
├── spi_flash/ SPI NOR chip database + read/erase/program/verify
|
├── spi_flash/ SPI NOR chip database + read/erase/program/verify
|
||||||
|
├── svf/ SVF player (program from a vendor-exported SVF)
|
||||||
|
├── probes/ Probe-config profiles loader (probes.yaml)
|
||||||
├── script/ Script engine
|
├── script/ Script engine
|
||||||
├── config/ Built-in config.script
|
├── config/ Built-in config.script
|
||||||
├── os_interface/ Portable fs/network wrappers
|
├── os_interface/ Portable fs/network wrappers
|
||||||
|
|||||||
138
doc/tutorial.md
138
doc/tutorial.md
@@ -1,9 +1,16 @@
|
|||||||
# Tutorial — from probe detection to SPI flash
|
# Tutorial — from probe to programmed part
|
||||||
|
|
||||||
This walks through the full `bs_explorer` flow on a Xilinx Kintex
|
This walks through the full `bs_explorer` flow: detect a probe, scan the
|
||||||
UltraScale+ KU15P board connected via an FTDI MPSSE probe. The
|
chain, identify the device, and program it. There are two programming
|
||||||
commands are identical for any FPGA registered in `modules/fpga/`; only
|
paths and the tutorial covers both:
|
||||||
the IDCODE and BSDL filename change.
|
|
||||||
|
- **Xilinx external SPI configuration flash**, via the BSCAN proxy —
|
||||||
|
shown on a Kintex UltraScale+ KU15P / UltraScale KU040;
|
||||||
|
- **any other part** (Lattice, Microsemi, …), by playing a
|
||||||
|
vendor-exported **SVF** — shown on a Microsemi IGLOO2 M2GL010T.
|
||||||
|
|
||||||
|
The early steps are identical for any device in `fpga_registry.yaml`;
|
||||||
|
only the IDCODE and BSDL filename change.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -18,17 +25,17 @@ the IDCODE and BSDL filename change.
|
|||||||
[Phase 2.5 caveat](#phase-25-spi-through-the-bscan-proxy-bridge-bitstream) at the end.
|
[Phase 2.5 caveat](#phase-25-spi-through-the-bscan-proxy-bridge-bitstream) at the end.
|
||||||
|
|
||||||
If your board uses a Digilent JTAG-SMT2 / SMT2-NC module (KCU105,
|
If your board uses a Digilent JTAG-SMT2 / SMT2-NC module (KCU105,
|
||||||
ZCU102, …), you need the optional Digilent backend: install the Adept
|
ZCU102, …), the Digilent backend is built in by default on Linux — just
|
||||||
Runtime system-wide and configure with `cmake -DBS_ENABLE_DIGILENT=ON
|
install the Adept Runtime system-wide so `libdjtg.so`/`libdmgr.so` are
|
||||||
..`. Plain MPSSE does not work on those modules — see the README and
|
present at runtime. Plain MPSSE does not work on those modules — see the
|
||||||
the `Digilent SMT2` block in `CLAUDE.md` for the why.
|
README and the `Digilent SMT2` block in `CLAUDE.md` for the why.
|
||||||
|
|
||||||
## Build & launch
|
## Build & launch
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir build && cd build
|
mkdir build && cd build && cmake .. && make && cd ..
|
||||||
cmake .. && make
|
./build/bs/bs # run from the repo root: probes.yaml, fpga_registry.yaml,
|
||||||
./bs/bs
|
# bsdl_files/ and bscan_proxies/ are looked up in the CWD
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see:
|
You should see:
|
||||||
@@ -69,6 +76,29 @@ If `jtag_open` fails: check `lsusb` for the probe VID:PID, make
|
|||||||
sure the user has access to the USB device (udev rule or group), and
|
sure the user has access to the USB device (udev rule or group), and
|
||||||
confirm no other process holds the probe (e.g. `openocd`).
|
confirm no other process holds the probe (e.g. `openocd`).
|
||||||
|
|
||||||
|
### Probe profiles
|
||||||
|
|
||||||
|
Some probes need pin tweaks the built-in defaults don't cover — e.g. the
|
||||||
|
embedded **FlashPro** on Microsemi eval kits (an FT4232H whose JTAG sits
|
||||||
|
on channel A = index 0 and needs `ADBUS4` left high-Z, or the chain stays
|
||||||
|
silent). `probes.yaml` captures these as named profiles; apply one when
|
||||||
|
opening:
|
||||||
|
|
||||||
|
```
|
||||||
|
bs_explorer> jtag_profiles
|
||||||
|
2 probe profile(s) in probes.yaml:
|
||||||
|
flashpro
|
||||||
|
ft2232h
|
||||||
|
bs_explorer> jtag_open 0 flashpro
|
||||||
|
Applied probe profile 'flashpro'.
|
||||||
|
Probe Ok !
|
||||||
|
```
|
||||||
|
|
||||||
|
`jtag_close` releases the current probe (frees its USB handle) — use it
|
||||||
|
to hand the probe to another tool, or to program two boards on different
|
||||||
|
probes in turn: `jtag_close`, then `jtag_open` the next one and
|
||||||
|
`jtag_autoinit` to rescan.
|
||||||
|
|
||||||
## 2. Scan the JTAG chain
|
## 2. Scan the JTAG chain
|
||||||
|
|
||||||
The fastest path is `jtag_autoinit`: it scans the chain *and*
|
The fastest path is `jtag_autoinit`: it scans the chain *and*
|
||||||
@@ -97,14 +127,38 @@ registry in `fpga_registry.yaml`:
|
|||||||
```
|
```
|
||||||
bs_explorer> fpga_info
|
bs_explorer> fpga_info
|
||||||
Device 0 IDCODE 0x04A56093 -> Xilinx Kintex UltraScale+ XCKU15P [Xilinx UltraScale+]
|
Device 0 IDCODE 0x04A56093 -> Xilinx Kintex UltraScale+ XCKU15P [Xilinx UltraScale+]
|
||||||
|
prog: proxy_spi
|
||||||
caveat: CCLK routed via STARTUP primitive (not drivable in EXTEST)
|
caveat: CCLK routed via STARTUP primitive (not drivable in EXTEST)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`prog:` is the programming backend the registry assigns the part —
|
||||||
|
`proxy_spi` (Xilinx external flash, [§Phase 2.5](#phase-25-spi-through-the-bscan-proxy-bridge-bitstream))
|
||||||
|
or `svf` ([§Programming via SVF](#programming-via-svf-lattice-microsemi-)).
|
||||||
|
|
||||||
If you get `not in registry`, add an entry — see
|
If you get `not in registry`, add an entry — see
|
||||||
[Adding a new FPGA](#6-add-a-new-fpga-target).
|
[Adding a new FPGA](#6-add-a-new-fpga-target).
|
||||||
|
|
||||||
`fpga_list` prints the whole registry without needing a probe.
|
`fpga_list` prints the whole registry without needing a probe.
|
||||||
|
|
||||||
|
## JTAG clock (optional)
|
||||||
|
|
||||||
|
Each driver has its own default TCK (FTDI 1 MHz, Digilent 4 MHz). To set
|
||||||
|
a single driver-neutral clock, before `jtag_open`:
|
||||||
|
|
||||||
|
```
|
||||||
|
bs_explorer> set JTAG_TCK_FREQ_KHZ 1000
|
||||||
|
```
|
||||||
|
|
||||||
|
It's applied at open (mapped to the FTDI driver's variable, or read
|
||||||
|
directly by the Digilent one). A registry entry may declare a
|
||||||
|
`max_tck_khz`; if your requested clock exceeds it, `jtag_autoinit` clamps
|
||||||
|
it and re-opens the probe at the safe rate:
|
||||||
|
|
||||||
|
```
|
||||||
|
WARNING : JTAG clock 2000 kHz exceeds the device max 1000 kHz; clamping.
|
||||||
|
Re-opening at 1000 kHz and re-scanning.
|
||||||
|
```
|
||||||
|
|
||||||
## 4. (Optional) Sanity-check the low-level JTAG primitives
|
## 4. (Optional) Sanity-check the low-level JTAG primitives
|
||||||
|
|
||||||
Before doing anything fancy, you can verify that `bscan_set_ir` and
|
Before doing anything fancy, you can verify that `bscan_set_ir` and
|
||||||
@@ -206,6 +260,8 @@ Append a list item under `fpgas:` in `fpga_registry.yaml`:
|
|||||||
| `ir_cfg_in` / `ir_user1` / `ir_jprogram` / `ir_jstart` / `ir_jshutdown` / `ir_isc_disable` | private IR opcodes (omit = 0/N/A) | from the BSDL |
|
| `ir_cfg_in` / `ir_user1` / `ir_jprogram` / `ir_jstart` / `ir_jshutdown` / `ir_isc_disable` | private IR opcodes (omit = 0/N/A) | from the BSDL |
|
||||||
| `proxy_bitstream` | BSCAN proxy `.bit` in `bscan_proxies/` (omit if none) | `bscan_spi_xcku040.bit` |
|
| `proxy_bitstream` | BSCAN proxy `.bit` in `bscan_proxies/` (omit if none) | `bscan_spi_xcku040.bit` |
|
||||||
| `caveats` | space/comma-separated flag names (omit if none) | `cclk_via_startup` |
|
| `caveats` | space/comma-separated flag names (omit if none) | `cclk_via_startup` |
|
||||||
|
| `max_tck_khz` | max safe JTAG TCK in kHz; `jtag_autoinit` clamps + re-opens if exceeded (omit = unspecified) | — |
|
||||||
|
| `prog` | programming backend `proxy_spi`/`svf`/`none` (omit → inferred: a proxy ⇒ `proxy_spi`, Microsemi/Lattice ⇒ `svf`) | `proxy_spi` |
|
||||||
|
|
||||||
The resulting entry (verbatim from `fpga_registry.yaml`):
|
The resulting entry (verbatim from `fpga_registry.yaml`):
|
||||||
|
|
||||||
@@ -224,6 +280,7 @@ The resulting entry (verbatim from `fpga_registry.yaml`):
|
|||||||
ir_isc_disable: 0x16
|
ir_isc_disable: 0x16
|
||||||
proxy_bitstream: bscan_spi_xcku040.bit
|
proxy_bitstream: bscan_spi_xcku040.bit
|
||||||
caveats: cclk_via_startup
|
caveats: cclk_via_startup
|
||||||
|
prog: proxy_spi
|
||||||
```
|
```
|
||||||
|
|
||||||
Omit any field that doesn't apply: a missing `proxy_bitstream` means
|
Omit any field that doesn't apply: a missing `proxy_bitstream` means
|
||||||
@@ -365,6 +422,60 @@ OpenOCD's `src/flash/nor/jtagspi.c` so the same bitstreams work. Generic
|
|||||||
flash `read`/`erase`/`program`/`verify` (Phase 3) will be built on top
|
flash `read`/`erase`/`program`/`verify` (Phase 3) will be built on top
|
||||||
of this primitive.
|
of this primitive.
|
||||||
|
|
||||||
|
## Programming via SVF (Lattice, Microsemi, …)
|
||||||
|
|
||||||
|
The BSCAN-proxy path above is Xilinx-specific (external SPI config flash).
|
||||||
|
For everything else, the universal path is to play an **SVF** file
|
||||||
|
exported by the vendor tool — Libero / FlashPro Express (Microsemi),
|
||||||
|
Diamond / Radiant (Lattice), Vivado (Xilinx fabric), Quartus, … The
|
||||||
|
vendor bakes the programming *algorithm* into the SVF; `bs_explorer` just
|
||||||
|
replays its `SIR`/`SDR`/`RUNTEST` vectors and checks the masked `TDO`
|
||||||
|
compares that flag a failed erase/program.
|
||||||
|
|
||||||
|
```
|
||||||
|
bs_explorer> jtag_open 0 flashpro # the probe profile for your kit
|
||||||
|
bs_explorer> jtag_autoinit # fpga_info should show 'prog: svf'
|
||||||
|
bs_explorer> svf_play design.svf
|
||||||
|
...
|
||||||
|
SVF done: 1342 commands, 1338 scans, 71 compares
|
||||||
|
```
|
||||||
|
|
||||||
|
A `TDO` mismatch stops play and points at the failing vector:
|
||||||
|
|
||||||
|
```
|
||||||
|
ERROR : line 842: SDR TDO mismatch at bit 17 (len 696)
|
||||||
|
```
|
||||||
|
|
||||||
|
— usually a wrong device, a too-fast clock, or a part that isn't
|
||||||
|
erased/unlocked.
|
||||||
|
|
||||||
|
You can sanity-check the player without a programming file using a tiny
|
||||||
|
hand-written IDCODE check (after `STATE RESET` the TAP auto-loads IDCODE
|
||||||
|
into DR):
|
||||||
|
|
||||||
|
```
|
||||||
|
! idcode.svf — masked IDCODE check (top nibble = revision)
|
||||||
|
STATE RESET;
|
||||||
|
SDR 32 TDO (0F8031CF) MASK (0FFFFFFF);
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
bs_explorer> svf_play idcode.svf
|
||||||
|
SVF done: 2 commands, 1 scans, 1 compares
|
||||||
|
```
|
||||||
|
|
||||||
|
**Supported subset (single-device chain):** `SIR`/`SDR` with
|
||||||
|
`TDI`/`TDO`/`MASK`/`SMASK` and the masked compare; `RUNTEST` (TCK/SCK
|
||||||
|
counts and SEC delays); `STATE` (RESET/IDLE); `ENDIR`/`ENDDR` (IDLE only);
|
||||||
|
`HIR`/`HDR`/`TIR`/`TDR` (length 0 only); `TRST`; `FREQUENCY`. SMASK is
|
||||||
|
parsed but not applied. Multi-device headers/trailers (non-zero) and
|
||||||
|
non-IDLE end states are rejected with a clear error.
|
||||||
|
|
||||||
|
**Generating the SVF is the closed step.** There is no open-source
|
||||||
|
bitstream/SVF generator for Microsemi (or most vendors) — you need the
|
||||||
|
vendor tool to *produce* the SVF (Libero has a free tier covering the
|
||||||
|
small IGLOO2 parts). `bs_explorer` only *plays* it, which is fully open.
|
||||||
|
|
||||||
## Troubleshooting cheat sheet
|
## Troubleshooting cheat sheet
|
||||||
|
|
||||||
| Symptom | Likely cause |
|
| Symptom | Likely cause |
|
||||||
@@ -376,6 +487,9 @@ of this primitive.
|
|||||||
| `fpga_info` says "not in registry" | Add an entry to `fpga_registry.yaml`. |
|
| `fpga_info` says "not in registry" | Add an entry to `fpga_registry.yaml`. |
|
||||||
| `bscan_shift_dr 32` doesn't return the expected IDCODE | Wrong IR opcode/length, wrong device index, or a multi-device chain (current primitives assume single device). |
|
| `bscan_shift_dr 32` doesn't return the expected IDCODE | Wrong IR opcode/length, wrong device index, or a multi-device chain (current primitives assume single device). |
|
||||||
| `jtag_spi_xfer` is hopelessly slow | That's expected via EXTEST — switch to BSCAN proxy (Phase 2.5). |
|
| `jtag_spi_xfer` is hopelessly slow | That's expected via EXTEST — switch to BSCAN proxy (Phase 2.5). |
|
||||||
|
| Detected fine, then reads turn to garbage / `0x00000000` mid-session | Target board lost power — JTAG floats (the USB probe stays enumerated regardless). Re-power the board. |
|
||||||
|
| FT4232H FlashPro: `jtag_scan` finds 0 devices | JTAG is on channel A (index 0) and needs `ADBUS4` high-Z — open with the profile: `jtag_open 0 flashpro`. |
|
||||||
|
| `svf_play` mismatches only on the very first compare | FTDI link warm-up; `svf_play` handles it, but a bare `bscan_shift_dr` straight after `jtag_open` may need a `jtag_scan` first. |
|
||||||
|
|
||||||
## Where to go from here
|
## Where to go from here
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user