feat: add spi_slave.v physical layer (Phase 4 SPI RTL, part 1/N)

First real RTL piece of the SPI interface (docs §8.1 protocol
draft): the physical layer only -- Mode 0 (CPOL=0, CPHA=0),
MSB-first, byte-level shift register with a 3-stage CDC synchronizer
for SCLK/MOSI/CS_N (the SPI master clock is asynchronous to the
FPGA system clock). Exposes rx_byte/rx_valid, tx_byte/tx_byte_req,
and cs_active/cs_start/cs_end to the (not yet written) protocol
engine.

Documented an important consumer contract on tx_byte_req: it is a
prefetch hint (fires once extra after the last byte of every
transaction, since the slave cannot know in advance whether the
master will keep clocking), not a "byte consumed" event -- a
consumer must advance any stateful pointer (e.g. a RAM read address)
on rx_valid instead, which fires exactly once per real byte
transferred.

sim/spi_slave_tb.v: bit-banged SPI master BFM (4 tests: single byte,
multi-byte in one CS period, back-to-back transactions, slower
SCLK). Two testbench-only bugs found and fixed during bring-up (RTL
itself needed no functional change beyond the tx_byte_req contract
comment): the BFM was advancing its tx queue on tx_byte_req instead
of rx_valid (see contract above), and inter-test reset pulses raced
against posedge clk (blocking `rst=1` landing on the same simulation
time as a clock edge) -- fixed by asserting/deasserting reset on
negedge clk instead.

Verified two ways: Icarus Verilog (4/4 tests pass) and the real
ECP5 toolchain used for prior benchmarks (Yosys 0.68 synth: 0
problems, 41 FF / 55 LUT4, no latches; nextpnr-ecp5 --45k --package
CABGA381 --speed 8 --freq 80: PASS, Fmax 403.23 MHz; ecppack:
bitstream generated with no errors).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
This commit is contained in:
2026-09-02 15:24:17 +02:00
co-authored by Claude Sonnet 5
parent 87efce3d9b
commit d716eb04dd
5 changed files with 14941 additions and 0 deletions
+13327
View File
File diff suppressed because it is too large Load Diff