7587636b48
bba_devid fails on a console with 00 04 02 02 -- the ID correct but one byte
late -- and it fails in its REAL shape, with the 16 us gap and exactly four
bytes clocked, so this is not the t_raw_id probe artefact. The register suite
passes, so register-space reads are fine; only command space is affected.
Cause is latency, not phase. A command-space header is two bytes, so the
reply must be in the tx FIFO by the LAST RISING EDGE of the header transfer:
one byte time, 296 ns at 27 MHz. The round trip is rx AsyncFIFO (~125 ns) +
a sync cycle + tx AsyncFIFO (~110 ns) = 280-320 ns, marginal by construction.
HEADER0 already pushed in the same cycle it consumed byte 0, so the FSM side
was already as early as it can be.
The inter-transfer gap cannot rescue it: the load happens on that last rising
edge and the clock is PAUSED afterwards, so no edge exists during the gap for
anything to update. That is why bba_devid's 16 us gap makes no difference.
Pre-pushing the ID at CS-fall does not work either -- the engine's
unconditional per-byte pops would eat it, and the header length is not known
until byte 0 has been decoded, which is the latency in question.
So take the round trip out of the path. The device ID is a hardwired constant
and belongs to the physical interface rather than to the register file, and
byte 0 == 0x00 identifies the query exactly (bit 7 clear = command space, bit
6 clear = read, reg 0). SPIMode3Slave now recognises it and answers
04 02 02 00 from the EXI clock domain, with no CDC at all. The only thing it
needs from sync is id_phase, a single bit that changes once, crossed with an
FFSynchronizer.
The register file's ID path is REMOVED rather than kept as a fallback: left
in, it would push bytes that a 2-byte header has too few pops to drain, which
is exactly how an earlier version made the NEXT enumeration come back a slot
late.
Tests follow the responsibility:
- spi_mode3_slave T7: the query returns 04 02 02 00 with the tx FIFO
deliberately feeding 0x00, so only the fast path can be answering.
- spi_mode3_slave T8: and it is GATED -- with id_arm low, 0x5A comes
through from the FIFO. Without this the fast path would hijack address 0
forever and the GC could never read NCRA back after its own reset.
- bba_register_file T1: retargeted to assert the FSM pushes NOTHING for an
ID query, which is the property that stops stale bytes corrupting the
following transaction.
Note what these tests do NOT establish: bba_top already passed the device ID
at EXI_HALF=1 before this change, because simulation cannot reproduce a
296 ns window miss -- the sync domain's latency relative to the EXI clock in
sim does not match silicon closely enough. T7/T8 prove the fast path works;
the evidence that it is NECESSARY is the hardware result plus the paused-clock
argument above.
--seeds 8: clk 28.4-31.0 MHz, EXI 56.7-64.4 MHz, 8/8 PASS. Best seed 2
(clk 30.98, EXI 59.47), flashed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>