Files
rebbarb/hardware/re-bba-rb/BRINGUP.md
T

173 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
---
## V2 schematic changes already applied (2026-08-25)
- **U7 EEPROM → 93LC56B** (LCSC C6164, MPN 93LC56BT-I/SN, same SOIC-8). Fixes the
soft-brick (256 B is the FT2232H's full EEPROM size). [TODO/REVIEW updated]
- **All 7 LEDs → Everlight 24-21 reverse-mount 1206** (bottom-viewed, top-populated
single-side assembly): red D7/D11 = **C2892757** (24-21SURC), green
D6/D8/D9/D12 = **C2980185** (24-21/G6C), amber D13 = **C424133** (24-21UYC).
All Vf ≈ 2.0 V (3.3 V-rail + SB_RGBA_DRV safe), moderate mcd. New footprint
`hardware/LED_1206_ReverseMount_Everlight_24-21.kicad_mod` (pad1=cathode,
**ø1.7 mm Edge.Cuts light-window — datasheet-confirmed** 2026-08-28, spec
1.7 mm ±0.1). Refdes text is 1.0 mm (JLC silk floor).
- **LED series resistors R37/R41/R42: 49.9 Ω → 330 Ω** (reused existing part
C25104; R38 already 330). ~3.9 mA vs the blinding ~26 mA — closes item 1's
resistor half. Green PWM (`_GRN_DUTY`) in gateware still applies to D6/D12; the
new green is only 1845 mcd so it can likely be relaxed.
- **Gateware (`synth.py`):** RGB drive bug fixed (raw-pad `o_RGB*`) + green PWM
dimming — see items 1 & 5.
Still open below: GC_ON handover redesign (#2), the datasheet-aperture verify,
EXI/W5100 functional validation (needs a working board), plus the ground-plane
fill for fab.
## 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._