doc: flesh out "add an FPGA target", explain caveats
Rework tutorial section 6 with a worked XCKU040 example: how to pull IR opcodes/IDCODE from the BSDL (with a grep), a field-by-field table, the verbatim registry entry, and a dedicated section on what `caveats` are (bit-flags for hardware gotchas, not free text) and how to add one. Also fixes the broken in-page anchor links to the section.
This commit is contained in:
115
doc/tutorial.md
115
doc/tutorial.md
@@ -13,7 +13,7 @@ the IDCODE and BSDL filename change.
|
|||||||
- The target's BSDL in `bsdl_files/` (KU15P: `xcku15p_ffve1517.bsd` is
|
- The target's BSDL in `bsdl_files/` (KU15P: `xcku15p_ffve1517.bsd` is
|
||||||
bundled).
|
bundled).
|
||||||
- An entry for the target in `modules/fpga/fpga.c` (KU15P is bundled).
|
- An entry for the target in `modules/fpga/fpga.c` (KU15P is bundled).
|
||||||
See [Adding a new FPGA](#adding-a-new-fpga-target) below.
|
See [Adding a new FPGA](#6-add-a-new-fpga-target) below.
|
||||||
- For SPI flashing, eventually: a BSCAN proxy bitstream — see the
|
- 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.
|
[Phase 2.5 caveat](#phase-25-spi-through-the-bscan-proxy-bridge-bitstream) at the end.
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ Device 0 IDCODE 0x04A56093 -> Xilinx Kintex UltraScale+ XCKU15P [Xilinx UltraS
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you get `not in registry`, add an entry — see
|
If you get `not in registry`, add an entry — see
|
||||||
[Adding a new FPGA](#adding-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.
|
||||||
|
|
||||||
@@ -162,34 +162,101 @@ way; you'd be there for weeks.
|
|||||||
|
|
||||||
## 6. Add a new FPGA target
|
## 6. Add a new FPGA target
|
||||||
|
|
||||||
For an FPGA that's not in the registry yet:
|
The registry in `modules/fpga/fpga.c` holds the per-part facts that
|
||||||
|
can't be derived from the BSDL alone (or are tedious to). The XCKU040
|
||||||
|
entry already there was added exactly with the steps below — use it as
|
||||||
|
your template.
|
||||||
|
|
||||||
1. **Drop the BSDL** in `bsdl_files/`. The file you want is on the
|
### a. Drop the BSDL
|
||||||
vendor's site (Xilinx: in the device download under
|
|
||||||
"BSDL files"; Intel: in Quartus install dir; Lattice: per part).
|
|
||||||
|
|
||||||
2. **Read the facts you need** from the BSDL:
|
Put the part's `.bsd` in `bsdl_files/`. Source: Xilinx/AMD device page
|
||||||
```
|
under "Design Files / BSDL", Intel in the Quartus install, Lattice per
|
||||||
attribute IDCODE_REGISTER ... -> IDCODE pattern (4-bit version
|
part. `jtag_autoinit` will then auto-load it by IDCODE.
|
||||||
masked, lower 28 bits matter)
|
|
||||||
attribute INSTRUCTION_LENGTH ... -> ir_length
|
### b. Pull the facts out of the BSDL
|
||||||
attribute INSTRUCTION_OPCODE ... -> opcodes for IDCODE, EXTEST,
|
|
||||||
SAMPLE, BYPASS, and private
|
Everything you need is in the file:
|
||||||
instructions for the family
|
|
||||||
(USER1, CFG_IN, JPROGRAM,
|
```sh
|
||||||
JSTART, JSHUTDOWN, ISC_DISABLE
|
grep -iE "INSTRUCTION_LENGTH|IDCODE_REGISTER|\b(USER1|CFG_IN|JPROGRAM|JSTART|JSHUTDOWN|ISC_DISABLE)\b" \
|
||||||
on Xilinx)
|
bsdl_files/xcku040_ffva1156.bsd
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Add an entry** to `fpga_registry[]` in `modules/fpga/fpga.c`,
|
For the XCKU040 this yields IR length 6, and the private opcodes
|
||||||
mirroring the existing KU15P entry. Set `proxy_bitstream` to
|
`USER1=000010` (0x02), `CFG_IN=000101` (0x05), `JPROGRAM=001011`
|
||||||
`NULL` for now; wire it up when you have one. Set caveats as
|
(0x0B), `JSTART=001100` (0x0C), etc. The `IDCODE_REGISTER` string is
|
||||||
appropriate (e.g. `FPGA_CAVEAT_CCLK_VIA_STARTUP` for any
|
`XXXX...0010 0000 1001 0011` — the top four bits are the silicon
|
||||||
Xilinx 7-Series/UltraScale/UltraScale+).
|
**revision** and read as `X` (don't-care), which is why the registry
|
||||||
|
masks them off.
|
||||||
|
|
||||||
4. **Rebuild**. The registry is compile-time, no runtime registration.
|
### c. Fill in an `fpga_target`
|
||||||
|
|
||||||
5. **Verify** with `fpga_info` after `jtag_autoinit`.
|
| Field | What it is | XCKU040 |
|
||||||
|
|-------|-----------|---------|
|
||||||
|
| `name` | human-readable label | "Xilinx Kintex UltraScale XCKU040" |
|
||||||
|
| `idcode` | IDCODE pattern (version nibble as 0) | `0x03822093` |
|
||||||
|
| `idcode_mask` | bits that must match; `0x0FFFFFFF` ignores the Xilinx revision nibble | `0x0FFFFFFF` |
|
||||||
|
| `family` | `FPGA_FAMILY_XILINX_7/US/USP` | `FPGA_FAMILY_XILINX_US` |
|
||||||
|
| `bsdl_filename` | basename in `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 (0 = N/A) | from the BSDL |
|
||||||
|
| `proxy_bitstream` | BSCAN proxy `.bit` in `bscan_proxies/`, or `NULL` | `"bscan_spi_xcku040.bit"` |
|
||||||
|
| `caveats` | bit-flags for hardware gotchas (see below) | `FPGA_CAVEAT_CCLK_VIA_STARTUP` |
|
||||||
|
|
||||||
|
The resulting entry (verbatim from `fpga.c`):
|
||||||
|
|
||||||
|
```c
|
||||||
|
{
|
||||||
|
.name = "Xilinx Kintex UltraScale XCKU040",
|
||||||
|
.idcode = 0x03822093,
|
||||||
|
.idcode_mask = 0x0FFFFFFF,
|
||||||
|
.family = FPGA_FAMILY_XILINX_US,
|
||||||
|
.bsdl_filename = "xcku040_ffva1156.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_xcku040.bit",
|
||||||
|
.caveats = FPGA_CAVEAT_CCLK_VIA_STARTUP,
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### What `caveats` means
|
||||||
|
|
||||||
|
`caveats` is a bit-field of `FPGA_CAVEAT_*` flags (in `fpga.h`) marking
|
||||||
|
**known hardware gotchas that change how the tool must drive the
|
||||||
|
part**. It is *not* a free-text note — each flag is something the code
|
||||||
|
(or you) can branch on. Set it to `0` when the part has none you know
|
||||||
|
of. `fpga_info` prints any flag that is set, as a human-readable line.
|
||||||
|
|
||||||
|
Currently one flag exists:
|
||||||
|
|
||||||
|
- `FPGA_CAVEAT_CCLK_VIA_STARTUP` — on Xilinx 7-Series / UltraScale /
|
||||||
|
UltraScale+, the SPI configuration clock **CCLK is not a normal I/O
|
||||||
|
pin**: it is routed through the `STARTUP`/`STARTUPE3` primitive and
|
||||||
|
therefore **cannot be toggled in EXTEST** boundary scan. Practical
|
||||||
|
effect: the slow EXTEST SPI bit-bang can't clock the flash on these
|
||||||
|
parts — you must use the BSCAN proxy (Phase 2.5), where CCLK is driven
|
||||||
|
by the fabric internally and the problem disappears. Set this flag for
|
||||||
|
any 7-Series/US/US+ part.
|
||||||
|
|
||||||
|
To introduce a *new* caveat: add a `#define FPGA_CAVEAT_xxx (1u << n)`
|
||||||
|
in `fpga.h`, OR it into the relevant entries, and (if it should be
|
||||||
|
visible) print it in `cmd_fpga_info` in `script.c`.
|
||||||
|
|
||||||
|
### d. Rebuild and verify
|
||||||
|
|
||||||
|
The registry is compile-time — no runtime registration:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd build && make
|
||||||
|
./bs/bs
|
||||||
|
bs_explorer> jtag_autoinit
|
||||||
|
bs_explorer> fpga_info # should show your part, family, and any caveats
|
||||||
|
```
|
||||||
|
|
||||||
## Phase 2.5: SPI through the BSCAN proxy (bridge bitstream)
|
## Phase 2.5: SPI through the BSCAN proxy (bridge bitstream)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user