restructure: code+libs under src/, runtime resources under data/
Separate the two concerns the repo root was mixing:
- src/ — bs/, modules/, libs/ (code + vendored libs)
- data/ — fpga_registry.yaml, probes.yaml, bsdl_files/, bscan_proxies/,
scripts/ (everything the tool reads at runtime, CWD-relative)
- doc/ — kept at the root
CMake: repoint DIR_MODULES/DIR_LIBS and add_subdirectory at src/; emit
the binary at the build/ root (build/bs) via CMAKE_RUNTIME_OUTPUT_DIRECTORY
instead of the nested build/src/bs/. The jtag_core ../../libs path still
resolves since modules and libs moved together.
Runtime default paths now point under data/ (fpga.c, probes.c, script.c
bsdl_files lookup, init.c config.script). Docs (README/tutorial/CLAUDE)
updated for the new layout, src/ module paths, and ./build/bs.
Validated on the IGLOO2/FlashPro: profiles, autoinit, and svf_play all
work run from the repo root.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -9,17 +9,17 @@ paths and the tutorial covers both:
|
||||
- **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`;
|
||||
The early steps are identical for any device in `data/fpga_registry.yaml`;
|
||||
only the IDCODE and BSDL filename change.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A JTAG probe physically wired to the target's TCK/TDI/TDO/TMS/TRST.
|
||||
- `libftd2xx` reachable at runtime (already vendored under
|
||||
`libs/libftd2xx/`).
|
||||
- The target's BSDL in `bsdl_files/` (KU15P: `xcku15p_ffve1517.bsd` is
|
||||
`src/libs/libftd2xx/`).
|
||||
- The target's BSDL in `data/bsdl_files/` (KU15P: `xcku15p_ffve1517.bsd` is
|
||||
bundled).
|
||||
- An entry for the target in `fpga_registry.yaml` (KU15P is bundled).
|
||||
- An entry for the target in `data/fpga_registry.yaml` (KU15P is bundled).
|
||||
See [Adding a new FPGA](#6-add-a-new-fpga-target) below.
|
||||
- For SPI flashing, eventually: a BSCAN proxy bitstream — see the
|
||||
[Phase 2.5 caveat](#phase-25-spi-through-the-bscan-proxy-bridge-bitstream) at the end.
|
||||
@@ -34,8 +34,8 @@ README and the `Digilent SMT2` block in `CLAUDE.md` for the why.
|
||||
|
||||
```sh
|
||||
mkdir build && cd build && cmake .. && make && cd ..
|
||||
./build/bs/bs # run from the repo root: probes.yaml, fpga_registry.yaml,
|
||||
# bsdl_files/ and bscan_proxies/ are looked up in the CWD
|
||||
./build/bs # run from the repo root: data/probes.yaml, data/fpga_registry.yaml,
|
||||
# data/bsdl_files/ and data/bscan_proxies/ are looked up in the CWD
|
||||
```
|
||||
|
||||
You should see:
|
||||
@@ -81,12 +81,12 @@ confirm no other process holds the probe (e.g. `openocd`).
|
||||
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
|
||||
silent). `data/probes.yaml` captures these as named profiles; apply one when
|
||||
opening:
|
||||
|
||||
```
|
||||
bs_explorer> jtag_profiles
|
||||
2 probe profile(s) in probes.yaml:
|
||||
2 probe profile(s) in data/probes.yaml:
|
||||
flashpro
|
||||
ft2232h
|
||||
bs_explorer> jtag_open 0 flashpro
|
||||
@@ -102,7 +102,7 @@ probes in turn: `jtag_close`, then `jtag_open` the next one and
|
||||
## 2. Scan the JTAG chain
|
||||
|
||||
The fastest path is `jtag_autoinit`: it scans the chain *and*
|
||||
auto-loads every BSDL in `bsdl_files/` whose IDCODE matches a device.
|
||||
auto-loads every BSDL in `data/bsdl_files/` whose IDCODE matches a device.
|
||||
|
||||
```
|
||||
bs_explorer> jtag_autoinit
|
||||
@@ -122,7 +122,7 @@ mis-wired. Power-cycle and re-check the harness before going further.
|
||||
## 3. Identify the FPGA against the registry
|
||||
|
||||
`fpga_info` walks the chain and matches each IDCODE against the
|
||||
registry in `fpga_registry.yaml`:
|
||||
registry in `data/fpga_registry.yaml`:
|
||||
|
||||
```
|
||||
bs_explorer> fpga_info
|
||||
@@ -216,7 +216,7 @@ way; you'd be there for weeks.
|
||||
|
||||
## 6. Add a new FPGA target
|
||||
|
||||
The registry — `fpga_registry.yaml` at the repo root — holds the
|
||||
The registry — `data/fpga_registry.yaml` at the repo root — holds the
|
||||
per-part facts that can't be derived from the BSDL alone (or are tedious
|
||||
to). It's parsed at runtime, so adding a part is **editing YAML, no
|
||||
rebuild**. The XCKU040 entry already there was added exactly with the
|
||||
@@ -224,7 +224,7 @@ steps below — use it as your template.
|
||||
|
||||
### a. Drop the BSDL
|
||||
|
||||
Put the part's `.bsd` in `bsdl_files/`. Source: Xilinx/AMD device page
|
||||
Put the part's `.bsd` in `data/bsdl_files/`. Source: Xilinx/AMD device page
|
||||
under "Design Files / BSDL", Intel in the Quartus install, Lattice per
|
||||
part, Microsemi/Microchip via Libero. `jtag_autoinit` will then
|
||||
auto-load it by IDCODE.
|
||||
@@ -235,7 +235,7 @@ Everything you need is in the file:
|
||||
|
||||
```sh
|
||||
grep -iE "INSTRUCTION_LENGTH|IDCODE_REGISTER|\b(USER1|CFG_IN|JPROGRAM|JSTART|JSHUTDOWN|ISC_DISABLE)\b" \
|
||||
bsdl_files/xcku040_ffva1156.bsd
|
||||
data/bsdl_files/xcku040_ffva1156.bsd
|
||||
```
|
||||
|
||||
For the XCKU040 this yields IR length 6, and the private opcodes
|
||||
@@ -247,7 +247,7 @@ masks them off.
|
||||
|
||||
### c. Add a YAML entry
|
||||
|
||||
Append a list item under `fpgas:` in `fpga_registry.yaml`:
|
||||
Append a list item under `fpgas:` in `data/fpga_registry.yaml`:
|
||||
|
||||
| Key | What it is | XCKU040 |
|
||||
|-----|-----------|---------|
|
||||
@@ -255,15 +255,15 @@ Append a list item under `fpgas:` in `fpga_registry.yaml`:
|
||||
| `idcode` | IDCODE pattern (version nibble as 0) | `0x03822093` |
|
||||
| `idcode_mask` | bits that must match; `0x0FFFFFFF` ignores the Xilinx revision nibble (default `0xFFFFFFFF`) | `0x0FFFFFFF` |
|
||||
| `family` | `xilinx_7/us/usp`, `microsemi_igloo2/smartfusion2`, `lattice_machxo2/3` | `xilinx_us` |
|
||||
| `bsdl` | basename in `bsdl_files/` | `xcku040_ffva1156.bsd` |
|
||||
| `bsdl` | basename in `data/bsdl_files/` | `xcku040_ffva1156.bsd` |
|
||||
| `ir_length` | IR width in bits | `6` |
|
||||
| `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 `data/bscan_proxies/` (omit if none) | `bscan_spi_xcku040.bit` |
|
||||
| `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 `data/fpga_registry.yaml`):
|
||||
|
||||
```yaml
|
||||
- name: "Xilinx Kintex UltraScale XCKU040"
|
||||
@@ -318,7 +318,7 @@ The registry is loaded at runtime, so just (re)start bs_explorer from
|
||||
the repo root and check:
|
||||
|
||||
```sh
|
||||
./build/bs/bs
|
||||
./build/bs
|
||||
bs_explorer> fpga_list # your part should appear, with its source file
|
||||
bs_explorer> jtag_autoinit
|
||||
bs_explorer> fpga_info # should show your part, family, and any caveats
|
||||
@@ -339,10 +339,10 @@ internally — so the `STARTUPE3`/CCLK problem of EXTEST disappears.
|
||||
### Get the bridge bitstream
|
||||
|
||||
Pre-built proxies live in `quartiq/bscan_spi_bitstreams` (MIT). Drop
|
||||
the one for your part in `bscan_proxies/`:
|
||||
the one for your part in `data/bscan_proxies/`:
|
||||
|
||||
```sh
|
||||
curl -L -o bscan_proxies/bscan_spi_xcku040.bit \
|
||||
curl -L -o data/bscan_proxies/bscan_spi_xcku040.bit \
|
||||
https://raw.githubusercontent.com/quartiq/bscan_spi_bitstreams/master/bscan_spi_xcku040.bit
|
||||
```
|
||||
|
||||
@@ -367,9 +367,9 @@ PATH=$PATH:/opt/Xilinx/Vivado/2022.2/bin \
|
||||
The XCKU15P first has to be **added to the generator's device table**
|
||||
(a Migen platform entry) — it's not just a command-line part flag.
|
||||
|
||||
Once built, drop `bscan_spi_xcku15p.bit` into `bscan_proxies/` (it's
|
||||
MIT, like the KU040 — keep `bscan_proxies/LICENSE.quartiq`) and set the
|
||||
`proxy_bitstream` field on the KU15P entry in `fpga_registry.yaml`
|
||||
Once built, drop `bscan_spi_xcku15p.bit` into `data/bscan_proxies/` (it's
|
||||
MIT, like the KU040 — keep `data/bscan_proxies/LICENSE.quartiq`) and set the
|
||||
`proxy_bitstream` field on the KU15P entry in `data/fpga_registry.yaml`
|
||||
(currently omitted).
|
||||
|
||||
### Load the bridge and talk SPI
|
||||
@@ -377,7 +377,7 @@ MIT, like the KU040 — keep `bscan_proxies/LICENSE.quartiq`) and set the
|
||||
```
|
||||
bs_explorer> jtag_open 1
|
||||
bs_explorer> jtag_autoinit
|
||||
bs_explorer> bscan_load_bitstream 0 bscan_proxies/bscan_spi_xcku040.bit
|
||||
bs_explorer> bscan_load_bitstream 0 data/bscan_proxies/bscan_spi_xcku040.bit
|
||||
bs_explorer> bscan_jedec 0
|
||||
JEDEC ID: 20 BB 19 (manufacturer 0x20, device 0xBB19)
|
||||
```
|
||||
@@ -414,7 +414,7 @@ read-latency skew.
|
||||
### The transfer primitive
|
||||
|
||||
`bscan_spi_xfer(jc, t, tx, txlen, rx, rxlen)` in
|
||||
`modules/bscan/bscan.c` performs one CS-framed transaction:
|
||||
`src/modules/bscan/bscan.c` performs one CS-framed transaction:
|
||||
clock out `txlen` MOSI bytes, then read `rxlen` MISO bytes. It builds
|
||||
the quartiq/OpenOCD jtagspi DR frame
|
||||
(`marker | bit-count | MOSI | latency-skip | MISO`) and matches
|
||||
@@ -484,7 +484,7 @@ small IGLOO2 parts). `bs_explorer` only *plays* it, which is fully open.
|
||||
| `jtag_autoinit` finds 0 devices | TDI/TDO swap, TRST held low, voltage mismatch, or chain broken. |
|
||||
| All IDCODEs read `0xFFFFFFFF` | TDO floats high — broken TDO link, wrong voltage reference, or a Digilent SMT2 module being driven via raw FTDI MPSSE (use the Digilent backend instead). |
|
||||
| All IDCODEs read `0x00000000` | TDO tied low or no clock reaching the target. |
|
||||
| `fpga_info` says "not in registry" | Add an entry to `fpga_registry.yaml`. |
|
||||
| `fpga_info` says "not in registry" | Add an entry to `data/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). |
|
||||
| `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. |
|
||||
@@ -498,4 +498,4 @@ small IGLOO2 parts). `bs_explorer` only *plays* it, which is fully open.
|
||||
technical decisions (machine-independent).
|
||||
- `README.md` is the user-facing summary.
|
||||
- The original Viveris library and its docs live untouched under
|
||||
`modules/jtag_core/`, `modules/bsdl_parser/`, `modules/bus_over_jtag/`.
|
||||
`src/modules/jtag_core/`, `src/modules/bsdl_parser/`, `src/modules/bus_over_jtag/`.
|
||||
|
||||
Reference in New Issue
Block a user