Moved all components to F.Cu
This commit is contained in:
@@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
fpga-icestorm \
|
||||
libusb-1.0-0 \
|
||||
libftdi1-2 \
|
||||
tshark \
|
||||
nodejs npm \
|
||||
graphviz \
|
||||
poppler-utils \
|
||||
@@ -30,13 +31,21 @@ ENV VIRTUAL_ENV=/opt/venv
|
||||
RUN python3 -m venv "$VIRTUAL_ENV"
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
|
||||
# ENV PATH alone is not enough: Debian's /etc/profile REsets PATH unconditionally,
|
||||
# so any *login* shell (VS Code's integrated terminal, `su - vscode`, ssh) drops
|
||||
# /opt/venv/bin and then `python` does not exist at all (slim has only python3).
|
||||
# Re-prepend the venv for login shells so the documented `python -m exi_bba.synth`
|
||||
# works everywhere.
|
||||
RUN printf 'PATH="%s/bin:$PATH"\nexport PATH\n' "$VIRTUAL_ENV" > /etc/profile.d/10-venv.sh
|
||||
|
||||
RUN npm install -g @anthropic-ai/claude-code
|
||||
|
||||
COPY requirements.txt /tmp/requirements.txt
|
||||
RUN pip install --no-cache-dir -r /tmp/requirements.txt
|
||||
|
||||
# pyftdi: programs the FT2232H EEPROM (product string "re-BBA-rb") over libusb.
|
||||
RUN pip install --no-cache-dir pyftdi
|
||||
# pyftdi: programs the FT2232H EEPROM over libusb, and (with pyserial) reads the
|
||||
# FT2232H channel-B UART directly over libusb for bring-up diagnostics.
|
||||
RUN pip install --no-cache-dir pyftdi pyserial
|
||||
|
||||
RUN useradd -m -u 1000 -s /bin/bash vscode \
|
||||
&& echo 'vscode ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/vscode \
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# The devcontainer build uses context ".." (the repo root) but only ever COPYs
|
||||
# requirements.txt. Keep the context small so a rebuild doesn't ship the whole
|
||||
# repo (~333 MB) to the docker daemon.
|
||||
.git/
|
||||
.venv/
|
||||
build/
|
||||
hardware/
|
||||
docs/
|
||||
diagrams/
|
||||
examples/
|
||||
*.vcd
|
||||
*.pcapng
|
||||
*.bin
|
||||
*.asc
|
||||
*.json.gz
|
||||
__pycache__/
|
||||
*.pyc
|
||||
Binary file not shown.
+70
-19
@@ -59,8 +59,10 @@ from exi_bba.bba_top import BBATop
|
||||
# LEDs which are active-low. No physical button exists on this board (the
|
||||
# iCEbreaker's BTN_N was dev-board-only); panel_btn is tied idle instead.
|
||||
# RGB status LED (D11=red/rx, D12=green/tx, D13=yellow/ready) is on the
|
||||
# iCE40UP5K's dedicated SB_RGBA_DRV pins 39/40/41 — fixed by the chip
|
||||
# package on any board, not board-specific, so no resource needed here.
|
||||
# iCE40UP5K's dedicated SB_RGBA_DRV pads 39/40/41. It IS declared as a
|
||||
# "rgb" resource and requested RAW (dir="-") so SB_RGBA_DRV drives the pads
|
||||
# directly — leaving o_RGB* dangling (the old code) never bonds them and the
|
||||
# LEDs stay dark. See the "rgb" Resource + elaborate() below, and BRINGUP.md.
|
||||
|
||||
# nextpnr P&R options. The binding constraint is the isolated 54 MHz capture
|
||||
# domain (the SPI Mode-3 bit engine); the 24 MHz sync domain has wide margin.
|
||||
@@ -75,6 +77,26 @@ from exi_bba.bba_top import BBATop
|
||||
# sync domain. Plain --opt-timing is the better baseline.
|
||||
_PNR_TIMING_OPTS = "--opt-timing"
|
||||
|
||||
# UART pin override for bring-up. The re-bba-rb V1 lab unit had its UART_RXD
|
||||
# trace (FPGA pin 19 → FT2232H pin 39) severed by a via-repair drill hole, and
|
||||
# the 0.5 mm FT2232H pitch is not hand-reworkable. Set env UART_J4=1 to relocate
|
||||
# the UART onto the accessible J4 debug header — DBG0 = J4 pin 2 = FPGA pin 9
|
||||
# (FPGA TX), DBG1 = J4 pin 3 = FPGA pin 10 (FPGA RX), GND = J4 pin 1 — so an
|
||||
# external USB-UART dongle can drive the shell, bypassing the FT2232H channel B
|
||||
# completely. Unset (default) keeps the normal FT2232H channel-B pins
|
||||
# (tx = 19 = UART_RXD net, rx = 18 = UART_TXD net).
|
||||
_UART_TX, _UART_RX = ("9", "10") if os.environ.get("UART_J4") else ("19", "18")
|
||||
|
||||
# ETH_D3 relocation for the damaged V1 lab unit: the W5100 data bit-3 trace
|
||||
# (FPGA pin 28 → W5100 U11 pin 40, top copper) was nicked by a drill hole, and
|
||||
# neither the 0.5 mm pin nor the 0.1 mm trace is hand-reworkable. Set
|
||||
# ETH_D3_PIN=<n> to drive W5100 D3 from a coarse J4 header pad instead, and bodge
|
||||
# that pad to the W5100 D3 net: DBG0=9 (J4 pin2), DBG1=10 (J4 pin3),
|
||||
# DBG2=11 (J4 pin4), DBG3=12 (J4 pin5), DBG4=6 (J4 pin6). NOTE pin 9 collides
|
||||
# with UART_J4 TX — fine for the W5100/eth test builds (no UART), not for the
|
||||
# full UART_J4 design. Default = 28 (real board). See BRINGUP.md.
|
||||
_ETH_D3 = os.environ.get("ETH_D3_PIN", "28")
|
||||
|
||||
|
||||
class IceBreakerPlatform(LatticeICE40Platform):
|
||||
device = "iCE40UP5K"
|
||||
@@ -99,7 +121,7 @@ class IceBreakerPlatform(LatticeICE40Platform):
|
||||
# W5100 indirect parallel bus
|
||||
Resource("w5100", 0,
|
||||
Subsignal("addr", Pins("42 38", dir="o")),
|
||||
Subsignal("data", Pins("34 32 31 28 27 26 25 23", dir="io")),
|
||||
Subsignal("data", Pins(f"34 32 31 {_ETH_D3} 27 26 25 23", dir="io")),
|
||||
Subsignal("cs_n", Pins("43", dir="o")),
|
||||
Subsignal("rd_n", Pins("37", dir="o")),
|
||||
Subsignal("wr_n", Pins("36", dir="o")),
|
||||
@@ -114,11 +136,23 @@ class IceBreakerPlatform(LatticeICE40Platform):
|
||||
Resource("ledr", 0, Pins("48", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
Resource("ledg", 0, Pins("47", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
|
||||
# UART debug console → FT2232H Channel B.
|
||||
# On the PC: open the second USB serial port at 115200 8N1.
|
||||
# RGB status LED on the iCE40UP5K's dedicated SB_RGBA_DRV pads
|
||||
# (39=D11 red, 40=D12 green, 41=D13 yellow). Requested RAW (dir="-") in
|
||||
# elaborate and wired straight from the SB_RGBA_DRV hard block — a normal
|
||||
# buffered (dir="o") output fails nextpnr packing:
|
||||
# "SB_RGB_DRV/SB_RGBA_DRV port connected to more than just package pin!"
|
||||
# (Bug found at bring-up 2026-08-23: these were previously left dangling,
|
||||
# so the rx/tx/ready RGB indicators never lit. See BRINGUP.md item 5.)
|
||||
Resource("rgb", 0,
|
||||
Subsignal("r", Pins("39", dir="o")),
|
||||
Subsignal("g", Pins("40", dir="o")),
|
||||
Subsignal("b", Pins("41", dir="o"))),
|
||||
|
||||
# UART debug console → FT2232H Channel B (or J4 header if UART_J4=1).
|
||||
# On the PC: open the serial port at 115200 8N1.
|
||||
Resource("uart", 0,
|
||||
Subsignal("tx", Pins("19", dir="o")),
|
||||
Subsignal("rx", Pins("18", dir="i")),
|
||||
Subsignal("tx", Pins(_UART_TX, dir="o")),
|
||||
Subsignal("rx", Pins(_UART_RX, dir="i")),
|
||||
Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
]
|
||||
|
||||
@@ -170,20 +204,37 @@ class BBATopSynth(BBATop):
|
||||
if self._status_panel:
|
||||
ledr = platform.request("ledr", 0)
|
||||
ledg = platform.request("ledg", 0)
|
||||
rgb = platform.request("rgb", 0, dir="-") # raw pads (no buffer)
|
||||
led = self.panel_led
|
||||
|
||||
# Green-LED PWM dimming. Both green emitters are over-bright on
|
||||
# the re-bba-rb V1 (bring-up 2026-08-23): the discrete LED_G/D6
|
||||
# heartbeat has a wrong 49.9 Ohm series resistor (R37, should be
|
||||
# ~330 Ohm), and the RGB green D12 die is very efficient even at
|
||||
# the SB_RGBA_DRV minimum current code. The current code is
|
||||
# already the minimum, so time-average both greens down with a
|
||||
# low-duty PWM. Red (D11/LED_R) and yellow (D13) are fine — left
|
||||
# solid. Tune _GRN_DUTY (0..15, /16 duty) at bring-up; see
|
||||
# BRINGUP.md items 1 & 5. PWM freq = 24 MHz/16 = 1.5 MHz (no
|
||||
# visible flicker).
|
||||
_GRN_DUTY = 2 # ~1/8 duty
|
||||
pwm_cnt = Signal(4)
|
||||
grn_pwm = Signal()
|
||||
m.d.sync += pwm_cnt.eq(pwm_cnt + 1)
|
||||
m.d.comb += grn_pwm.eq(pwm_cnt < _GRN_DUTY)
|
||||
|
||||
m.d.comb += [
|
||||
ledg.o.eq(led[0]), # heartbeat (active-high LED)
|
||||
ledr.o.eq(led[1]), # EXI activity (active-high LED)
|
||||
ledg.o.eq(led[0] & grn_pwm), # heartbeat (green) — PWM-dimmed
|
||||
ledr.o.eq(led[1]), # EXI activity (red) — fine
|
||||
# all 3 bits idle/released (active-low idle = 1) — no
|
||||
# physical button exists on this board to read
|
||||
self.panel_btn.eq(C(0b111, 3)),
|
||||
]
|
||||
|
||||
# iCEbreaker RGB LED has no series resistors — must use
|
||||
# SB_RGBA_DRV (raw pad driver with built-in current source).
|
||||
# RGB0=red→rx_act RGB1=green→tx_act RGB2=blue→ready
|
||||
# Verify colour-to-element mapping against schematic at bring-up.
|
||||
# RGB LED has no series resistors — must use SB_RGBA_DRV (raw pad
|
||||
# driver with built-in current source). o_RGB* MUST connect
|
||||
# directly to the pads (rgb.*.io) — a buffered output fails
|
||||
# packing. RGB0=red→rx RGB1=green→tx RGB2=yellow→ready.
|
||||
m.submodules.rgb_drv = Instance("SB_RGBA_DRV",
|
||||
p_CURRENT_MODE="0b1",
|
||||
p_RGB0_CURRENT="0b000001",
|
||||
@@ -191,12 +242,12 @@ class BBATopSynth(BBATop):
|
||||
p_RGB2_CURRENT="0b000001",
|
||||
i_CURREN=Const(1, 1),
|
||||
i_RGBLEDEN=Const(1, 1),
|
||||
i_RGB0PWM=led[2],
|
||||
i_RGB1PWM=led[3],
|
||||
i_RGB2PWM=led[4],
|
||||
o_RGB0=Signal(name="rgb_r"),
|
||||
o_RGB1=Signal(name="rgb_g"),
|
||||
o_RGB2=Signal(name="rgb_b"),
|
||||
i_RGB0PWM=led[2], # rx → red D11 (solid)
|
||||
i_RGB1PWM=led[3] & grn_pwm, # tx → green D12 (PWM-dimmed)
|
||||
i_RGB2PWM=led[4], # ready → yellow D13 (solid)
|
||||
o_RGB0=rgb.r.io,
|
||||
o_RGB1=rgb.g.io,
|
||||
o_RGB2=rgb.b.io,
|
||||
)
|
||||
|
||||
# ── UART debug console/shell → FT2232H Channel B ───────────────
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
# re-bba-rb — bring-up TODO / findings (first physical unit)
|
||||
|
||||
Findings from bringing up the first assembled V1 board (repaired: 7 shorted
|
||||
vias drilled out, some collateral trace damage). Started 2026-08-23. This is a
|
||||
running list — items are **not** being worked yet, just recorded.
|
||||
|
||||
## Established good so far (context)
|
||||
|
||||
- Bitstream flashes + verifies (`iceprog`, channel A); FPGA configures (heartbeat).
|
||||
- FT2232H healthy (channel-A MPSSE + channel-B internal loopback both pass).
|
||||
- **W5100 clock confirmed GOOD** (Y2 25 MHz crystal oscillating): the on-board
|
||||
diagnostic (`scratchpad/w5100_check.py`) shows solid green — MR software-reset
|
||||
self-clears, which only happens on the internal clock.
|
||||
- W5100 register write/read-back works on 7 of 8 data lines.
|
||||
|
||||
## Known damage on THIS unit (self-inflicted, from the via repair — not design bugs)
|
||||
|
||||
- **UART_RXD trace broken** (FPGA pin 19 → FT2232H pin 39). Workaround built:
|
||||
`UART_J4=1` synth build relocates the UART to the J4 header (DBG0=pin9=TX,
|
||||
DBG1=pin10=RX, GND=J4 pin1) for an external USB-UART/Pi dongle.
|
||||
- **ETH_D3 trace broken** (W5100 data bit 3): net `ETH_D3` = FPGA **U9 pin 28**
|
||||
↔ W5100 **U11 pin 40**. Confirmed by the diagnostic's red blink-code (4 blinks
|
||||
= D3). One bodge needed; bridge the drilled break (scrape to trace copper / a
|
||||
via — no need to touch the 0.5 mm chip pads). Optional: remap the FPGA D3 bit
|
||||
to a spare J4 pad (DBG2=pin11=J4 pin4) to make one end a coarse header pad.
|
||||
|
||||
---
|
||||
|
||||
## TODO
|
||||
|
||||
### 1. LED brightness — LED_G and the two transistor-driven LEDs are blindingly bright
|
||||
|
||||
**Observation:** `LED_G` (D6, green) and the two transistor-driven LEDs are far
|
||||
too bright; `LED_R` (D7, red) is fine.
|
||||
|
||||
**Root cause (from netlist):** the series resistors are wrong.
|
||||
- `LED_R` (D7, red): **R38 = 330 Ω** → correct brightness (the reference).
|
||||
- `LED_G` (D6, green): **R37 = 49.9 Ω** → ~25 mA, blinding.
|
||||
- Transistor-driven: **D8** (green, via Q1 S8050) and **D9** (green, via Q2
|
||||
S8550, collector → **R42 = 49.9 Ω** → D9) → same over-drive. (Confirm D8's
|
||||
own series resistor value too.)
|
||||
|
||||
**Fix direction:** raise the 49.9 Ω LED series resistors (**R37**, **R42**, and
|
||||
D8's) to ~**330 Ω–1 kΩ** to match D7. (The 49.9 Ω value looks copy-pasted from
|
||||
the impedance-matching resistors — wrong part for an LED.) The RGB LED
|
||||
(D11/D12/D13 via `SB_RGBA_DRV`, `RGB*_CURRENT=0b000001`) is separate and not
|
||||
part of this complaint. BOM/PCB change for V2; a rework could tack larger
|
||||
resistors on this unit if the brightness is a bench nuisance.
|
||||
|
||||
### 2. GC_ON is not the clean on/off the gateware assumed (sits at 2.3 V; both handover LEDs on)
|
||||
|
||||
**Observation:** `GC_ON` measures **2.3 V** (not a clean rail). With **both USB
|
||||
and GC connected**, both transistor-driven LEDs (D8, D9) are lit — the intent
|
||||
was a power-handover indicator with only ever one active (USB vs GC).
|
||||
|
||||
**Analysis (from netlist):** `GC_ON` = TPS2116 status (net: U2.8 = mux ST,
|
||||
U12.3, FPGA **U9 pin 21**, pulled up by R5 10 k to 3V3; drives Q1 base via R39
|
||||
10 k and Q2 base via R40 10 k). The two indicator transistors are complementary
|
||||
(Q1 = S8050 NPN, Q2 = S8550 PNP) expecting GC_ON to swing rail-to-rail:
|
||||
- At **GC_ON ≈ 2.3 V**, the NPN (Q1, on when base ≳0.7 V) **and** the PNP (Q2, on
|
||||
when base ≲2.6 V) **both conduct** → both D8 and D9 light. There is no clean
|
||||
one-or-the-other point at this intermediate voltage.
|
||||
|
||||
**Two things to resolve:**
|
||||
- **Hardware:** the complementary-transistor indicator doesn't give a clean
|
||||
handover display at the actual GC_ON level. Re-think for V2 (e.g., a comparator
|
||||
/ proper level, or drive the two indicators from a real one-hot power-source
|
||||
signal). First confirm what GC_ON's ST pin actually does across the USB-only /
|
||||
GC-only / both states (TPS2116 ST semantics — see REVIEW.md).
|
||||
- **Gateware:** GC_ON is wired to FPGA pin 21 but **not yet used**. The planned
|
||||
"gate all outputs on GC_ON" (see TODO.md) assumed GC_ON is a clean logic level.
|
||||
2.3 V is above the iCE40 3.3 V-LVCMOS V_IH (~2.0 V) so pin 21 would read HIGH,
|
||||
but it's marginal and the semantics aren't the assumed on/off. Verify the real
|
||||
signal before relying on it for output gating.
|
||||
|
||||
### 3. Functional W5100 test — send a packet capturable in Wireshark (works around broken D3?)
|
||||
|
||||
**Goal:** a test bitstream that makes the W5100 transmit a frame on the wire,
|
||||
captured with Wireshark on the laptop (magjack J2 → laptop).
|
||||
|
||||
**Feasible:** reuse `W5100ParallelMaster` (MACRAW socket 0, or the UDP socket
|
||||
path) with a small periodic trigger + a canned frame. Init runs on NCRA/startup.
|
||||
|
||||
**Caveat — the broken ETH_D3:** every byte written to the W5100 has data bit 3
|
||||
corrupted, so a frame sent *now* would have wrong MAC/ethertype/payload bytes —
|
||||
Wireshark might see a malformed frame (or the W5100 may reject a bad length).
|
||||
- A garbled frame appearing at all would still prove **TX path + PHY + magnetics**
|
||||
work on the wire.
|
||||
- For a **clean, valid** packet capture, do the **ETH_D3 bodge first** (item in
|
||||
"Known damage"). Recommended order: bodge D3 → re-run `w5100_check` (red should
|
||||
go dark) → then this packet test.
|
||||
|
||||
### 4. Bit-bang EXI from a Raspberry Pi to test the FPGA's EXI capture
|
||||
|
||||
**Goal:** validate the EXI Mode-3 capture front-end without a GameCube, by having
|
||||
a Pi emulate the GC EXI master.
|
||||
|
||||
**Approach:** Pi SPI **master, Mode 3 (CPOL=1, CPHA=1)**, 3.3 V (both sides
|
||||
3.3 V — no shifting). Drive the EXI **device-ID query** and check the response:
|
||||
write `0x0000` (2 bytes) then read 4 bytes → must be **`0x04 0x02 0x02 0x00`**.
|
||||
In SPI terms: assert CS, clock out `00 00 xx xx xx xx`, the last 4 MISO bytes are
|
||||
the device ID. A match proves ExiCapture → register file → MISO end-to-end.
|
||||
|
||||
**Connections (FPGA EXI pins):** CLK=44, MOSI=4, MISO=3, CS=45 (INT=46) — reach
|
||||
them at the SP1 edge connector J3 or the damper resistors (R21/R25). Map to Pi:
|
||||
Pi SCLK→CLK, Pi MOSI→MOSI(FPGA in), Pi MISO←MISO(FPGA out), Pi CE→CS, GND↔GND.
|
||||
|
||||
**Notes:** run the Pi SPI **slow** (e.g., 1 MHz) — the capture domain oversamples
|
||||
the EXI clock, so a slow clock is *easier* than the real 27 MHz and fully
|
||||
exercises the Mode-3 logic + register file. Good first EXI smoke test before
|
||||
trusting it against a real console.
|
||||
|
||||
### 5. RGB LEDs (D11 red / D12 green / D13 yellow) — drive bug + brightness
|
||||
|
||||
Two findings, from lighting them for the first time at bring-up:
|
||||
|
||||
**(a) DRIVE BUG — they don't light in the current gateware (functional, not cosmetic).**
|
||||
`SB_RGBA_DRV`'s `o_RGB0/1/2` outputs are left as dangling internal signals in
|
||||
`synth.py` (and were in the first test builds). nextpnr never bonds them to the
|
||||
dedicated RGB pads (pins 39/40/41 — confirmed absent from the PCF), so the driver
|
||||
outputs float and **the LEDs never light**. This means the **rx / tx / ready RGB
|
||||
indicators are non-functional in the default build.**
|
||||
- **Fix (confirmed on the bench):** request the RGB pins *raw* (no SB_IO buffer)
|
||||
and connect the driver outputs directly to the pads:
|
||||
```python
|
||||
rgb = platform.request("rgbpad", 0, dir="-") # Resource: r=39 g=40 b=41
|
||||
Instance("SB_RGBA_DRV", ...,
|
||||
o_RGB0=rgb.r.io, o_RGB1=rgb.g.io, o_RGB2=rgb.b.io)
|
||||
```
|
||||
Connecting through a normal `dir="o"` request fails packing:
|
||||
`ERROR: SB_RGB_DRV/SB_RGBA_DRV port connected to more than just package pin!`
|
||||
- **APPLIED 2026-08-23** in `synth.py`: added a raw `rgb` Resource (39/40/41) and
|
||||
wired `o_RGB0/1/2 = rgb.{r,g,b}.io`; the RGB indicators now light.
|
||||
|
||||
**(b) BRIGHTNESS — only GREEN (D12) is too bright; red (D11) and yellow (D13)
|
||||
are fine.** Measured with the corrected drive at the driver's *minimum* current
|
||||
(`CURRENT_MODE` half, `RGBx_CURRENT=0b000001`). The green die is much more
|
||||
efficient per mA, so at the same minimum current it's blinding while red/yellow
|
||||
look right. Since the current code is already at minimum, the fix is **PWM
|
||||
dimming on green only** — feed a low-duty PWM into `RGB1PWM` (green) instead of a
|
||||
static `1`, and leave red/yellow (`RGB0PWM`/`RGB2PWM`) driven solid.
|
||||
- **APPLIED 2026-08-23** in `synth.py`: a `_GRN_DUTY` (default 2/16 ≈ 1/8) PWM now
|
||||
gates **both** green emitters — `RGB1PWM` (D12) and `LED_G`/D6 (the discrete
|
||||
heartbeat, over-bright from R37 — item 1). Red/yellow/LED_R stay solid. Tune
|
||||
`_GRN_DUTY` (0..15) at the bench. Gateware mitigation; the proper V2 hardware
|
||||
fix for D6 is still R37 → ~330 Ω (item 1).
|
||||
|
||||
### 6. (reserved — Dennis to add)
|
||||
|
||||
_Placeholder for the item Dennis was trying to recall._
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
"""EXI device-ID query for re-bba-rb bring-up — run on a Raspberry Pi wired to
|
||||
the FPGA's EXI pins, to validate the GameCube-facing capture path with NO W5100
|
||||
involved (so it works even on a unit whose W5100/ethernet side is dead).
|
||||
|
||||
It bit-bangs the EXI SPI the way the GameCube does: CLK idles HIGH; the FPGA
|
||||
samples MOSI on the falling edge and drives MISO on the rising edge. It sends
|
||||
the device-ID read header (read 4 bytes @ addr 0 = 0x00 0x03), then pauses (the
|
||||
GC pauses the clock between the header and the data so the FPGA can prefetch the
|
||||
response), then clocks read bytes and looks for the reply 04 02 02 00.
|
||||
|
||||
Wiring (Pi BCM GPIO -> FPGA EXI, all 3.3 V, shared GND):
|
||||
CLK -> EXI CLK (FPGA pin 44)
|
||||
MOSI -> EXI MOSI (FPGA pin 4, an FPGA *input*)
|
||||
MISO <- EXI MISO (FPGA pin 3, an FPGA *output*)
|
||||
CS -> EXI CS (FPGA pin 45)
|
||||
GND <-> GND
|
||||
Reach these at the SP1 edge connector (J3) or on the series damper resistors.
|
||||
Edit the BCM pin numbers below to match your wiring. Run: sudo python3 exi_devid_rpi.py
|
||||
|
||||
Requires the FPGA to be running the full BBA design (e.g. build/seed3/top.bin)
|
||||
and its 12 MHz clock (X1) alive — both independent of the W5100.
|
||||
"""
|
||||
import time
|
||||
try:
|
||||
import RPi.GPIO as GPIO
|
||||
except ImportError:
|
||||
raise SystemExit("needs RPi.GPIO -> sudo apt install python3-rpi.gpio")
|
||||
|
||||
# ---- set these to your actual Pi BCM pin numbers ----
|
||||
CLK, MOSI, MISO, CS = 11, 10, 9, 8
|
||||
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(CLK, GPIO.OUT, initial=1) # CPOL=1: clock idles HIGH
|
||||
GPIO.setup(MOSI, GPIO.OUT, initial=0)
|
||||
GPIO.setup(CS, GPIO.OUT, initial=1) # inactive HIGH
|
||||
GPIO.setup(MISO, GPIO.IN)
|
||||
|
||||
|
||||
def xfer(b):
|
||||
"""Clock one byte MSB-first; FPGA samples MOSI on falling, drives MISO on rising."""
|
||||
r = 0
|
||||
for i in range(7, -1, -1):
|
||||
GPIO.output(MOSI, (b >> i) & 1) # MOSI stable while CLK is high
|
||||
GPIO.output(CLK, 0) # falling edge -> FPGA samples MOSI
|
||||
GPIO.output(CLK, 1) # rising edge -> FPGA drives MISO
|
||||
r = (r << 1) | GPIO.input(MISO)
|
||||
return r
|
||||
|
||||
|
||||
GPIO.output(CS, 0) # assert CS (active low)
|
||||
xfer(0x00) # header byte 0: read, addr[12:6]=0
|
||||
xfer(0x03) # header byte 1: addr[5:0]=0, len-1=3 (4 B)
|
||||
time.sleep(0.001) # gap so the FPGA can prefetch the reply
|
||||
resp = [xfer(0x00) for _ in range(6)] # clock a few read bytes
|
||||
GPIO.output(CS, 1) # deassert CS
|
||||
GPIO.cleanup()
|
||||
|
||||
print("read bytes:", " ".join("%02x" % x for x in resp))
|
||||
want = [0x04, 0x02, 0x02, 0x00]
|
||||
found = any(resp[i:i + 4] == want for i in range(len(resp) - 3))
|
||||
if found:
|
||||
print("EXI device-ID 04 02 02 00 -> FOUND. EXI capture path works!")
|
||||
else:
|
||||
print("device-ID not found. Try: swap to mode-2 edges (move the MISO sample "
|
||||
"to just before the falling edge), check wiring/GND, confirm the FPGA "
|
||||
"is running the BBA design and its 12 MHz clock is alive.")
|
||||
+22159
-22479
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"board": {
|
||||
"active_layer": 2,
|
||||
"active_layer": 0,
|
||||
"active_layer_preset": "",
|
||||
"auto_track_width": true,
|
||||
"hidden_netclasses": [],
|
||||
|
||||
@@ -1035,6 +1035,7 @@
|
||||
"netlist": "",
|
||||
"plot": "gerbers/",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
|
||||
Reference in New Issue
Block a user