EXI bring-up: device enumerates on hardware over the J4 header

First silicon proof of the EXI capture path.  A Pi bit-banging EXI into J4
reads the device ID 04 02 02 00 21/21, NWAYS 0x17, HIPR 0x01, writes and reads
back PAR0-3, writes IMR, and sees NCRA's reset bit self-clear.

Fixes two host-side bugs found getting there:
- exi_devid_rpi.py sampled MISO just after the rising edge, racing the slave's
  own update and landing one bit early (04 came back as 08).  Sample in the
  CLK-low phase, as the simulation does.
- pi-exi-wirecheck.py's bridge scan drove HIGH against pull-downs, but the
  FPGA's SB_IO pull-up out-pulls the Pi's internal pull-down, so every pin
  reported as bridged.  The aggressor now drives LOW against pull-ups.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 18:32:18 +00:00
parent 28b7665b33
commit a082e15c4f
4 changed files with 93 additions and 11 deletions
+28
View File
@@ -259,6 +259,34 @@ edge as the EXI pads (x=13–18 vs x=5–9, both y=0 per icestorm's `pinloc_db`
have perturbed the one placement variable the pin-co-location experiment showed
is worth ±5 MHz — see "Remaining capture bottleneck" above.
**HARDWARE BRING-UP 2026-09-30: the EXI capture path is PROVEN on silicon.**
A Raspberry Pi 4 bit-banging EXI into J4 (EXI_J4 build, seed 8) enumerated the
device and exercised the register file end-to-end:
| test | result |
|---|---|
| device ID @0x0000, 4 B | `04 02 02 00` — **21/21** |
| NWAYS @0x31 | `0x17` — 21/21 |
| HIPR @0x3A | `0x01` — 21/21 |
| PAR0–3 write `DE AD BE EF` + readback | **match**; restore to `00 09 BF 00` verified |
| IMR @0x08 write `0x86` + readback | `0x86` |
| NCRA @0x00 write `0x01` (reset) | self-cleared to `0x00` on the first poll |
Two bring-up gotchas, both cost real debugging time:
- **The master must sample MISO during the CLK-LOW phase.** The FPGA drives MISO
on the RISING edge (Mode 3), so sampling just after that edge races the
slave's own update and lands one bit position early — `04 02 02 00` comes back
as `08 ...`. Sample after taking CLK low, before raising it (this is exactly
what the simulation's `spi_byte` does).
- **Clock EXACTLY the requested byte count on a register read.** Over-clocking
(asking for 4 bytes then clocking 8–12) leaves stale prefetched bytes queued
and desynchronises following transactions — the symptom is a *deterministic*
every-Nth-read correctness cycle that looks like a signal-integrity fault but
is speed-independent. The GC driver never over-clocks a register read, so this
is a probe artefact, NOT a gateware bug; reads ≥ 0x100 deliberately stream
until CS (the DMA path). `hardware/re-bba-rb/exi_regcheck_rpi.py` clocks
correctly and is the reference host-side probe.
**Measured 2026-09-30**, `EXI_J4=1` + socket-3 UDP, `--seeds 8`:
`clk` 29.2–31.4 MHz (PASS on all 8); `capture_clk` **4 of 8 PASS** (seeds 2, 5,
6, 8), best **seed 8 = 63.09 MHz** (+9.1 MHz / 17% margin). Same pass rate as