Bring-up: W5100 bus self-test, eFuse OVLO bug, Pi SPI EXI host
From the physical V2 bring-up session (2026-09-20): - exi_bba/w5100_selftest.py (NEW): standalone FPGA<->W5100 bus diagnostic. Clock-independent data-bus walk (direct-mode GAR0 read-back, all 8 lines) + MR software-reset self-clear (needs the 25 MHz crystal). Reports 4 verdicts on D6/D7 LEDs AND over UART (115200): GOOD / data-line-N / clock-dead / no-response. Boot wait is 85 ms (> the W5100S 60.3 ms init). On this board: GOOD -- bus + all 8 data lines + 25 MHz clock all verified (unlike V1's broken D3). - REVIEW.md / TODO.md: eFuse U13 OVLO is tied to GND, which on the TPS25961 selects the internal FIXED ~6 V overvoltage cutoff -- so it blocks the 12 V rail entirely (bench-confirmed: 12V_EXI=0, GC_ON=0, W5100 unpowered). FAB- BLOCKER for V2.1: fix with an OVLO divider (~1.1M/100k -> trip ~15 V). Bench workaround: lift U13 pin 2 (OVLO) off GND. Also closed the eFuse-placement, GND-via/3V3-zone, and CC-ESD TODO items. - hardware/re-bba-rb/exi_devid_spi.py (NEW): Pi hardware-SPI (~25 MHz) EXI device-ID host, companion to the bit-bang exi_devid_rpi.py. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""EXI device-ID query over the Pi's HARDWARE SPI (spidev) — a near-full-speed
|
||||
(~25 MHz, close to the GameCube's real ~27 MHz EXI clock) companion to the
|
||||
bit-bang exi_devid_rpi.py.
|
||||
|
||||
Use bit-bang (exi_devid_rpi.py) for a slow logic smoke test; use THIS to prove
|
||||
the FPGA's SPI Mode-3 capture front-end also samples cleanly *at rate* without a
|
||||
GameCube. The Pi 4 SPI SCK is core_clk/even-divisor, so a 27 MHz request lands
|
||||
on ~25 MHz — comfortably inside the design's 54 MHz 2x oversampling (and a hair
|
||||
more margin than the real 27 MHz). Do NOT push past ~27 MHz: the capture domain
|
||||
only closes ~49-58 MHz across seeds, so >~27 MHz input under-samples.
|
||||
|
||||
The FPGA prefetches the reply during a clock-IDLE gap between the header and the
|
||||
data bytes (the GC pauses the clock there), so CS must stay LOW across that gap.
|
||||
spidev toggles CS per call, so we park SPI0's hardware CS on BCM7 (unused) and
|
||||
drive the real CS manually on BCM8. Pi config (then reboot):
|
||||
/boot/firmware/config.txt: dtoverlay=spi0-1cs,cs0_pin=7
|
||||
(That frees BCM8 and puts the unused hw CE0 on BCM7. To go back to the bit-bang
|
||||
script, remove that line + reboot so BCM9/10/11 return to plain GPIO.)
|
||||
|
||||
Wiring (Pi -> FPGA EXI, all 3.3 V, shared GND) — identical to the bit-bang one:
|
||||
SCLK BCM11 (pin 23) -> EXI CLK (FPGA 44)
|
||||
MOSI BCM10 (pin 19) -> EXI MOSI (FPGA 4)
|
||||
MISO BCM9 (pin 21) <- EXI MISO (FPGA 3)
|
||||
CS BCM8 (pin 24) -> EXI CS (FPGA 45) [held low manually across the txn]
|
||||
GND (pin 25) <-> GND
|
||||
Run: sudo python3 exi_devid_spi.py [speed_hz] [gap_us]
|
||||
"""
|
||||
import sys, time
|
||||
import spidev
|
||||
try:
|
||||
import RPi.GPIO as GPIO
|
||||
except ImportError:
|
||||
raise SystemExit("needs RPi.GPIO -> sudo apt install python3-rpi.gpio")
|
||||
|
||||
SPEED = int(sys.argv[1]) if len(sys.argv) > 1 else 27_000_000 # ~25 MHz actual (core/10)
|
||||
GAP_US = int(sys.argv[2]) if len(sys.argv) > 2 else 50 # header->data prefetch gap
|
||||
CS = 8 # BCM8 manual chip-select (hardware CE0 parked on BCM7 by the overlay)
|
||||
|
||||
spi = spidev.SpiDev()
|
||||
spi.open(0, 0)
|
||||
spi.mode = 0b11 # SPI Mode 3: CPOL=1, CPHA=1 (EXI CLK idles high)
|
||||
spi.max_speed_hz = SPEED
|
||||
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(CS, GPIO.OUT, initial=1) # CS idle high
|
||||
|
||||
GPIO.output(CS, 0) # assert CS (active low) for the whole transaction
|
||||
spi.xfer2([0x00, 0x03]) # header: read, addr[12:0]=0, len-1=3 (4 bytes)
|
||||
time.sleep(GAP_US / 1e6) # clock-idle gap -> FPGA prefetches the reply
|
||||
resp = spi.xfer2([0x00] * 6) # clock read bytes; MISO carries the response
|
||||
GPIO.output(CS, 1) # deassert CS
|
||||
spi.close(); GPIO.cleanup()
|
||||
|
||||
print(f"SPI mode 3, {SPEED/1e6:.1f} MHz requested (actual ~= core/even-divisor, ~25 MHz), "
|
||||
f"header->data gap {GAP_US} us")
|
||||
print("read bytes:", " ".join("%02x" % b for b in resp))
|
||||
want = [0x04, 0x02, 0x02, 0x00]
|
||||
if any(resp[i:i + 4] == want for i in range(len(resp) - 3)):
|
||||
print("EXI device-ID 04 02 02 00 -> FOUND. Capture path works at ~full EXI rate!")
|
||||
else:
|
||||
print("device-ID not found. If the slow bit-bang test (exi_devid_rpi.py) PASSES "
|
||||
"but this fails, the front-end is marginal at rate on the flashed seed -> "
|
||||
"reflash the BEST --seeds bitstream, and/or raise the gap (arg2) or lower "
|
||||
"the speed (arg1). Otherwise check wiring/GND and that the FPGA is running.")
|
||||
Reference in New Issue
Block a user