docs: EXI edge fix confirmed on hardware; MISO delay is the one open fault
Hardware speed sweep after the Mode 3 fix: ok=[1,1,1,0,0,0] -- register reads are CORRECT up to 4 MHz and fail from 8 MHz. The MOSI edge fix works and the gateware is functionally correct; what remains is a fixed MISO output delay of ~3 capture ticks (~55 ns: 2 stages of input FFSynchronizer plus 1 tick to register the shift). At 27 MHz that is ~2 bits, which is exactly the observed NWAYS read of 05 C0 = 0x17 >> 2, and the 250ns-pass / 125ns-fail threshold brackets the delay at 60-125 ns. Also records that lowering the EXI clock is not available: Swiss hardcodes EXI_SPEED_32MHZ in exi_select(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -232,30 +232,62 @@ still datasheet-from-memory — **confirm at hardware bring-up**.
|
|||||||
|
|
||||||
`bba_top`'s testbench derives the EXI clock from `HALF` (capture ticks per SPI
|
`bba_top`'s testbench derives the EXI clock from `HALF` (capture ticks per SPI
|
||||||
half-period): **EXI = 54 MHz / (2 × HALF)**. The default `HALF=8` gives
|
half-period): **EXI = 54 MHz / (2 × HALF)**. The default `HALF=8` gives
|
||||||
**3.4 MHz** — eight times slower than the real GC's ~27 MHz. At that rate the
|
**3.4 MHz** — eight times slower than the real GC's ~27 MHz, so the suite
|
||||||
entire CDC response latency fits inside one bit time, so the suite passes green
|
passes green on designs that fail outright on a console. `HALF` is
|
||||||
on a design that fails outright on a console. **Both the wrong-header-format
|
`EXI_HALF`-configurable; **run `EXI_HALF=1 python -m exi_bba.bba_top` before
|
||||||
and the TX-pop-threshold bugs reached real hardware with a fully green test
|
trusting any timing-related change.**
|
||||||
suite.**
|
|
||||||
|
|
||||||
`HALF` is now `EXI_HALF`-configurable. **Run `EXI_HALF=1 python -m
|
Worse, **every testbench drives MOSI many capture ticks before toggling the
|
||||||
exi_bba.bba_top` before trusting any timing-related change.**
|
clock**, so MOSI is stable at BOTH edges and the sampling-edge convention is
|
||||||
|
structurally undetectable. That is how a Mode 2/Mode 3 mix-up survived to
|
||||||
|
silicon with a fully green suite. `bba_top`'s master now models a true Mode 3
|
||||||
|
master (drive on falling, sample on rising).
|
||||||
|
|
||||||
Measured 2026-10-03:
|
### ✅ EXI edge convention — FIXED 2026-10-03 (was Mode 2, must be Mode 3)
|
||||||
|
|
||||||
| EXI rate | device ID | NWAYS |
|
The notes below once said "Mode 3 (CPOL=1, CPHA=1)" and then described
|
||||||
|---|---|---|
|
sampling MOSI on the **falling** edge. Idle-high + sample-on-falling is
|
||||||
| `EXI_HALF=8` → 3.4 MHz | `04 02 02 00` ✅ | `0x17` ✅ |
|
**Mode 2**. Real Mode 3 samples on the second edge of each cycle — the
|
||||||
| `EXI_HALF=2` → 13.5 MHz | ✅ | ✅ (TX drops 4 of 34 bytes) |
|
**rising** one — and that is what the GameCube does: it DRIVES MOSI on the
|
||||||
| `EXI_HALF=1` → **27 MHz, the hardware rate** | `02 01 01 00` ❌ | `0x0B` ❌ |
|
falling edge, so sampling there latched the previous bit.
|
||||||
|
|
||||||
⚠️ **OPEN BUG:** at the hardware rate every read comes back **shifted right by
|
Symptom on console: every byte one bit late in both directions, at every clock
|
||||||
one bit** (`04 02 02 00` → `02 01 01 00`; `0x17` → `0x0B` = `0x17 >> 1`). This
|
speed. The `0x80` register-space header byte read as `0x00`, which decodes as a
|
||||||
is a bit-level sampling misalignment, NOT the byte-level response latency that
|
command-space device-ID query, so NWAYS reads returned the device ID and the
|
||||||
was chased earlier — at 54 MHz capture there are only 2 ticks per EXI bit, and
|
speed sweep failed at every index. Raw 8-slot dump, first transaction after an
|
||||||
the 2-stage `FFSynchronizer` on the EXI clock costs 2 ticks, i.e. a whole bit.
|
FPGA reset: `00 00 02 01 01 00 00 00` = `04 02 02 00 >> 1`.
|
||||||
On console the same build returns all zeros. Fix this before any further
|
|
||||||
hardware runs.
|
`SPIMode3Slave(mode2=False)` (the default) now samples MOSI on RISING.
|
||||||
|
`mode2=True` restores the old behaviour, which is what the Pi/J4 probe scripts
|
||||||
|
were written against.
|
||||||
|
|
||||||
|
### ⚠️ OPEN: MISO output is ~2 bits late at 27 MHz
|
||||||
|
|
||||||
|
With MOSI fixed, register reads are **correct up to 4 MHz** and fail from
|
||||||
|
8 MHz (hardware speed sweep 2026-10-03: `ok=[1,1,1,0,0,0]`, highest good
|
||||||
|
index 2). At index 5 a NWAYS read returns `05 C0` = `0x17 >> 2`.
|
||||||
|
|
||||||
|
Cause: the MISO output path is delayed by roughly **3 capture ticks ≈ 55 ns** —
|
||||||
|
2 ticks of input `FFSynchronizer` on EXI CLK plus 1 tick to register the shift.
|
||||||
|
At 27 MHz one bit is 37 ns, so the master samples ~2 bits behind. The failure
|
||||||
|
threshold (pass at 250 ns/bit, fail at 125 ns/bit) brackets the delay at
|
||||||
|
60–125 ns, consistent with that structure.
|
||||||
|
|
||||||
|
**Lowering the EXI clock is NOT an option:** Swiss hardcodes
|
||||||
|
`EXI_SPEED_32MHZ` in `exi_select()` (`cube/patches/bba/bba.c`) — there is no
|
||||||
|
setting to turn down.
|
||||||
|
|
||||||
|
Options, none yet done:
|
||||||
|
1. **Clock the bit engine from the EXI clock itself** (route the pin to a
|
||||||
|
global buffer and make it a real clock domain) — the textbook SPI-slave
|
||||||
|
architecture, removes oversampling and the synchroniser entirely. Biggest
|
||||||
|
change, but the only one that is structurally correct rather than tuned.
|
||||||
|
2. **Output-bit lookahead** — drive the bit the master will sample ~2 bit-times
|
||||||
|
from now. Deterministic compensation for a deterministic delay, but it needs
|
||||||
|
lookahead into the next byte at byte boundaries, and the constant may not
|
||||||
|
hold across parts/temperature.
|
||||||
|
3. **Raise the capture clock** — 81 MHz would give 3× oversampling, but the
|
||||||
|
design's best measured fmax is 67 MHz, so it will not close.
|
||||||
|
|
||||||
### EXI on the J4 debug header (`EXI_J4=1`) — bench host without SP1
|
### EXI on the J4 debug header (`EXI_J4=1`) — bench host without SP1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user