Merge branch 'main' of ssh://cahute.beafrancois.fr:8329/electronics/bs_explorer
This commit is contained in:
173
doc/build_xilinx_proxy.md
Normal file
173
doc/build_xilinx_proxy.md
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# Building a BSCAN SPI proxy bitstream for a Xilinx FPGA
|
||||||
|
|
||||||
|
The fast SPI-flash path in `bs_explorer` ([tutorial.md, Phase 2.5](tutorial.md#phase-25-spi-through-the-bscan-proxy-bridge-bitstream))
|
||||||
|
loads a tiny "BSCAN proxy" bitstream into the FPGA fabric so SPI can run
|
||||||
|
through the JTAG `USER1` instruction at fabric speed. Pre-built proxies
|
||||||
|
for many parts ship in [quartiq/bscan_spi_bitstreams](https://github.com/quartiq/bscan_spi_bitstreams)
|
||||||
|
(MIT) — that repo also contains the **generator** (Migen + Vivado) used
|
||||||
|
to make them.
|
||||||
|
|
||||||
|
For parts the generator doesn't already know — **all of UltraScale+**
|
||||||
|
(XCKU15P, XCKU3P, XCKU11P, XCZU…, Virtex US+), plus any 7-Series /
|
||||||
|
UltraScale part missing from its table — you have to add a platform
|
||||||
|
entry and build the `.bit` yourself. This document walks through that,
|
||||||
|
using the **Kintex UltraScale+ XCKU15P** as the worked example.
|
||||||
|
|
||||||
|
The same recipe applies to any other Xilinx part: only the device
|
||||||
|
string, package pin LOCs and I/O standard change.
|
||||||
|
|
||||||
|
## What you end up doing
|
||||||
|
|
||||||
|
1. install Vivado and the quartiq generator's Python deps;
|
||||||
|
2. add a Migen **platform entry** for your part (the generator picks
|
||||||
|
parts out of a hard-coded table — it is *not* just a CLI flag);
|
||||||
|
3. run the generator, which calls Vivado to synth / place / route into a
|
||||||
|
`.bit`;
|
||||||
|
4. drop the `.bit` into `data/bscan_proxies/` and reference it from
|
||||||
|
`data/targets.yaml`;
|
||||||
|
5. smoke-test on the board.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **Vivado** matching your part's family. UltraScale+ needs Vivado
|
||||||
|
2019.2 or newer (2022.2 is what quartiq's README pins). The free
|
||||||
|
WebPACK / Standard edition covers the smaller US+ devices like the
|
||||||
|
XCKU3P / XCKU11P; larger parts (KU15P included) may need a paid
|
||||||
|
Vivado licence. ISE 14.7 only for Spartan-6 and earlier.
|
||||||
|
- **Python ≥ 3.8** with `venv`, and the Migen revision pinned in the
|
||||||
|
generator's `requirements.txt`.
|
||||||
|
- Roughly 30–80 GB of disk for Vivado, plus a few GB scratch per
|
||||||
|
synthesis run.
|
||||||
|
|
||||||
|
Confirm Vivado is reachable from your shell:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
source /opt/Xilinx/Vivado/2022.2/settings64.sh
|
||||||
|
vivado -version # should print the version
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1. Clone quartiq and install its Python deps
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/quartiq/bscan_spi_bitstreams
|
||||||
|
cd bscan_spi_bitstreams
|
||||||
|
python3 -m venv --system-site-packages .venv
|
||||||
|
./.venv/bin/pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
`--system-site-packages` lets the venv see a system-wide Migen if one
|
||||||
|
is installed; drop the flag for a fully isolated venv.
|
||||||
|
|
||||||
|
## 2. Add your part to the generator's table
|
||||||
|
|
||||||
|
Open `xilinx_bscan_spi.py`. Near the bottom you'll find a table of
|
||||||
|
`Platform` subclasses, one per supported part, each setting at least:
|
||||||
|
|
||||||
|
- `device` — the full Vivado part string, e.g.
|
||||||
|
`"xcku15p-ffve1517-2-e"`. Speed grade and temp range matter — copy
|
||||||
|
them from your board's schematic or the Vivado project that targets
|
||||||
|
the same silicon.
|
||||||
|
- `toolchain` — `"vivado"` for 7-Series and newer, `"ise"` for older.
|
||||||
|
- The SPI-flash pin **locations** for the part's *configuration bank*
|
||||||
|
(typically `D00_MOSI_0`, `D01_DIN_0`, `FCS_B_0`). **CCLK is not
|
||||||
|
declared here** — it is driven inside the FPGA via `STARTUPE3` for
|
||||||
|
UltraScale/+ and `STARTUPE2` for 7-Series, which the generator
|
||||||
|
already instantiates. (This is exactly what dissolves the
|
||||||
|
`cclk_via_startup` caveat described in `CLAUDE.md`.)
|
||||||
|
- The I/O standard for those pins (`LVCMOS18` for 1.8 V banks like the
|
||||||
|
KCU105/KU15P config bank, `LVCMOS25`/`LVCMOS33` otherwise). Wrong
|
||||||
|
voltage ⇒ Vivado DRC errors, or worse, damaged I/O on the flash.
|
||||||
|
|
||||||
|
Pick the closest existing entry as a template. For the KU15P, the
|
||||||
|
KU040 entry is the right neighbour: same toolchain (`vivado`), same
|
||||||
|
`STARTUPE3`, same bank-0 pinout shape. Duplicate it, change:
|
||||||
|
|
||||||
|
- the **device string** to your part + package + speed grade;
|
||||||
|
- the **pin LOCs** if the package differs (e.g. `FFVE1517` vs
|
||||||
|
`FFVA1156`);
|
||||||
|
- the **class name**, and add it to the dispatch dictionary at the
|
||||||
|
bottom of the file so a CLI key resolves to your new class.
|
||||||
|
|
||||||
|
Cross-check the four pin LOCs against the part's *Package Pin* table
|
||||||
|
in the Xilinx/AMD datasheet — these pads are board-independent (they
|
||||||
|
are the hard-wired configuration-bank pins), but the package suffix
|
||||||
|
changes them.
|
||||||
|
|
||||||
|
## 3. Run the generator
|
||||||
|
|
||||||
|
```sh
|
||||||
|
source /opt/Xilinx/Vivado/2022.2/settings64.sh
|
||||||
|
./.venv/bin/python3 xilinx_bscan_spi.py xcku15p
|
||||||
|
```
|
||||||
|
|
||||||
|
The argument is the **key you added to the dispatch dictionary** in
|
||||||
|
step 2 — not the raw Vivado part string. The script writes a Migen
|
||||||
|
build tree, calls Vivado, and on success drops
|
||||||
|
`bscan_spi_xcku15p.bit` (a few KB — just a `BSCANE2`, a `STARTUPE3`
|
||||||
|
and a small FSM) in the current directory.
|
||||||
|
|
||||||
|
Expect 1–3 minutes on a modern host. A failed run leaves its logs
|
||||||
|
under `build_xcku15p/`; common culprits:
|
||||||
|
|
||||||
|
| Vivado error | Fix |
|
||||||
|
|--------------|-----|
|
||||||
|
| `[Place 30-574]` pin LOC not on package | wrong package suffix in `device`, or copied LOCs from a different package |
|
||||||
|
| `[Drc NSTD-1]` unconstrained I/O | missing I/O standard on a pin → fix the platform entry |
|
||||||
|
| `Part xcku15p-… is not installed` | install the device support pack in Vivado, or pick a part covered by your licence |
|
||||||
|
| Vivado not found | forgot to `source settings64.sh` before launching the generator |
|
||||||
|
|
||||||
|
## 4. Drop it into bs_explorer
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cp bscan_spi_xcku15p.bit /path/to/bs_explorer/data/bscan_proxies/
|
||||||
|
```
|
||||||
|
|
||||||
|
The directory's `LICENSE.quartiq` (MIT) covers your build too — leave
|
||||||
|
it in place. Point the registry entry at the new file (this is the
|
||||||
|
KU15P entry that currently has `proxy_bitstream` omitted in
|
||||||
|
`data/targets.yaml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "Xilinx Kintex UltraScale+ XCKU15P"
|
||||||
|
idcode: 0x04A56093
|
||||||
|
idcode_mask: 0x0FFFFFFF
|
||||||
|
family: xilinx_usp
|
||||||
|
bsdl: xcku15p_ffve1517.bsd
|
||||||
|
ir_length: 6
|
||||||
|
ir_cfg_in: 0x05
|
||||||
|
ir_user1: 0x02
|
||||||
|
ir_jprogram: 0x0B
|
||||||
|
ir_jstart: 0x0C
|
||||||
|
ir_jshutdown: 0x0D
|
||||||
|
ir_isc_disable: 0x16
|
||||||
|
proxy_bitstream: bscan_spi_xcku15p.bit # <-- the file you just built
|
||||||
|
caveats: cclk_via_startup
|
||||||
|
prog: proxy_spi
|
||||||
|
```
|
||||||
|
|
||||||
|
No rebuild — the registry is loaded at runtime.
|
||||||
|
|
||||||
|
## 5. Smoke-test on the board
|
||||||
|
|
||||||
|
```
|
||||||
|
bs_explorer> jtag_open 1
|
||||||
|
bs_explorer> jtag_autoinit
|
||||||
|
bs_explorer> bscan_load_bitstream 0 data/bscan_proxies/bscan_spi_xcku15p.bit
|
||||||
|
bs_explorer> bscan_jedec 0
|
||||||
|
JEDEC ID: 20 BB 19 # or whatever flash your board carries
|
||||||
|
```
|
||||||
|
|
||||||
|
A plausible JEDEC ID — manufacturer byte matching the flash on the
|
||||||
|
schematic (`0x20` Micron, `0xEF` Winbond, `0xC2` Macronix, `0x01`
|
||||||
|
Cypress/Infineon, `0x9D` ISSI, …) — confirms the proxy is wired right:
|
||||||
|
`STARTUPE3` is driving `CCLK`, the `BSCANE2` capture is on `USER1`,
|
||||||
|
and the four pin LOCs match the physical flash. A `00 00 00` or
|
||||||
|
`FF FF FF` reply almost always means one of the LOCs is wrong —
|
||||||
|
re-check the package's configuration-bank pinout.
|
||||||
|
|
||||||
|
## Upstreaming (optional)
|
||||||
|
|
||||||
|
If your new part is broadly useful — any stock dev-board MPSoC, common
|
||||||
|
KU/VU/ZU device — the quartiq project takes PRs against
|
||||||
|
`xilinx_bscan_spi.py`. Once merged, future users get a pre-built
|
||||||
|
`.bit` and skip this whole document.
|
||||||
@@ -353,24 +353,16 @@ The registry entry for the part points at this file via its
|
|||||||
|
|
||||||
quartiq ships `.bit` only for the parts its generator knows — it has
|
quartiq ships `.bit` only for the parts its generator knows — it has
|
||||||
**no UltraScale+** proxy (its single UltraScale entry is the KU040), so
|
**no UltraScale+** proxy (its single UltraScale entry is the KU040), so
|
||||||
the KU15P has to be built from source. You need (o)Migen + Vivado
|
anything in the UltraScale+ family (XCKU15P, XCKU3P, XCKU11P, XCZU…,
|
||||||
(2022.2; ISE 14.7 for older parts). From a clone of the quartiq repo,
|
Virtex US+, …) has to be built from source. You need (o)Migen + Vivado
|
||||||
per its README:
|
(2022.2 for UltraScale/+; ISE 14.7 only for Spartan-6 and earlier).
|
||||||
|
|
||||||
```sh
|
Step-by-step walkthrough in [doc/build_xilinx_proxy.md](build_xilinx_proxy.md),
|
||||||
python3 -m venv --system-site-packages .venv
|
worked out on the KU15P.
|
||||||
./.venv/bin/pip install -r requirements.txt
|
|
||||||
PATH=$PATH:/opt/Xilinx/Vivado/2022.2/bin \
|
|
||||||
./.venv/bin/python3 xilinx_bscan_spi.py ...
|
|
||||||
```
|
|
||||||
|
|
||||||
The XCKU15P first has to be **added to the generator's device table**
|
Once built, drop `bscan_spi_<part>.bit` into `data/bscan_proxies/` (it's
|
||||||
(a Migen platform entry) — it's not just a command-line part flag.
|
|
||||||
|
|
||||||
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
|
MIT, like the KU040 — keep `data/bscan_proxies/LICENSE.quartiq`) and set the
|
||||||
`proxy_bitstream` field on the KU15P entry in `data/targets.yaml`
|
`proxy_bitstream` field on the matching entry in `data/targets.yaml`.
|
||||||
(currently omitted).
|
|
||||||
|
|
||||||
### Load the bridge and talk SPI
|
### Load the bridge and talk SPI
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user