Files
FPGA-Neural/hardware/v2/docs/PRE_PCB_CLOSURE_4POINT.md
T
micheleandClaude Sonnet 5 a20f1ecd73 docs: memory upgrade writeup (MEMORY_UPGRADE_64MB_N8.md) + supersede stale SDRAM docs
Adds the consolidated, authoritative record for the 64MB memory
upgrade and N_SLOTS=8 investigation (real datasheet family comparison,
RTL changes, both timing fixes with real P&R data, honest N=8 clock-
closure status, real DigiKey availability for the frozen part).

Marks HARDWARE_FREEZE.md/MEMORY_ARCHITECTURE.md/PRE_PCB_VERIFICATION.md/
PRE_PCB_CLOSURE_4POINT.md's own SDRAM-specific sections as superseded
(they describe the previous 8MB AS4C4M16SA-6TIN part) with pointers to
the new document, rather than rewriting each individually.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-07 00:21:05 +02:00

335 lines
18 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.
# FPGA-Neural V2 — FINAL 4-POINT PRE-PCB CLOSURE
Follows `PRE_PCB_VERIFICATION.md` (PRE-PCB VERIFIED baseline, commit
`d6376e8` + `8890b0a` + `eb0b0f9`). Closes the four remaining
practical items the user identified as still open before schematic
capture. Does not redesign the verified architecture; no working RTL
was modified as a result of this pass (see Point 2 for the one bug
found and fixed, which was in a NEW test harness, not in
`spi_host_bridge.v` itself).
**SDRAM-SPECIFIC CONTENT SUPERSEDED (DEC-0039, a later session).**
Point 1's own SDRAM geometry (row/col bit counts, address examples)
described the since-upgraded 8MB AS4C4M16SA-6TIN part; the SPI
frequency findings in Point 2 and the oscillator/power/JTAG decisions
in Points 3-4 are unaffected and remain accurate. See
`MEMORY_UPGRADE_64MB_N8.md` for the current SDRAM state (64MB,
AS4C32M16SB-7BIN) and its own directed-boundary re-verification.
---
## POINT 1 — Directed SDRAM boundary verification
New file: `hardware/v2/nms/sim/tb_sdram_boundary.v`.
Real Alliance Memory AS4C4M16SA-6TIN geometry (confirmed against
`sdram_controller.v`'s own address decode:
`addr_bank=addr[21:20]`, `addr_row=addr[19:8]`, `addr_col=addr[7:0]`):
4 banks × 4096 rows × 256 cols × 16 bits = 4M words = 8MB.
Coverage (21 checks, BURST_LEN=1 for exact single-word addressing):
- **Address boundaries**: 0x000000 (addr 0), 0x000001 (addr 1),
0x3FFFFF (last valid), 0x3FFFFE (last valid 1).
- **Row boundary**: bank0/row10/col255 (last column of row 10) and
bank0/row11/col0 (first column of row 11).
- **Bank boundaries**: last address / first address at all 3
inter-bank crossings (bank0↔1, bank1↔2, bank2↔3).
- **Memory-map boundaries**: the real V2 map (weights@byte 0x010000,
activations@byte 0x200000, results@byte 0x300000) converted to this
controller's word addresses (word=byte/2) — weights base, last word
before activations, activations base, last word before results,
results base.
- **Byte-mask combinations, explicit read-after-write**: lower-byte-
only (wmask=2'b10), upper-byte-only (wmask=2'b01), both-bytes
(wmask=2'b00), using the requested deterministic patterns 0xAAAA,
0x5555, 0x0000, 0xFFFF.
All 17 boundary/adjacency addresses are written first, then read back
in **reversed** order with distinct address-derived patterns
(`addr[15:0] ^ 0xC3A5`) — this proves no write to any one address
corrupted any neighbour in the set, which is exactly the "adjacent
regions cannot corrupt each other" property requested, for every
boundary simultaneously.
### Exact results
```
$ verilator --binary --timing -Wno-fatal --top-module tb_sdram_boundary -o tb_bnd \
-GCLK_FREQ_MHZ=64 hardware/v2/nms/rtl/sdram_controller.v \
hardware/v2/nms/sim/sdram_model.v hardware/v2/nms/sim/tb_sdram_boundary.v
$ ./obj_dir/tb_bnd
=== 21/21 tests, 0 errors (tb_sdram_boundary, CLK_FREQ_MHZ=64) ===
ALL TESTS PASSED (tb_sdram_boundary, CLK_FREQ_MHZ=64)
```
Cross-checked at the legacy CLK_FREQ_MHZ=166 (same command with
`-GCLK_FREQ_MHZ=166`): **21/21 PASS, 0 errors**, identical.
Full per-address results at 64MHz (expected vs actual, all matched):
| Label | Address | Data |
|---|---|---|
| addr-0 | 0x000000 | 0xc3a5 |
| addr-1 | 0x000001 | 0xc3a4 |
| addr-last | 0x3fffff | 0x3c5a |
| addr-last-1 | 0x3ffffe | 0x3c5b |
| row10-lastcol | 0x000aff | 0xc95a |
| row11-firstcol | 0x000b00 | 0xc8a5 |
| bank0-last | 0x0fffff | 0x3c5a |
| bank1-first | 0x100000 | 0xc3a5 |
| bank1-last | 0x1fffff | 0x3c5a |
| bank2-first | 0x200000 | 0xc3a5 |
| bank2-last | 0x2fffff | 0x3c5a |
| bank3-first | 0x300000 | 0xc3a5 |
| weights-base | 0x008000 | 0x43a5 |
| weights-last(pre-act) | 0x0fffff | 0x3c5a |
| activations-base | 0x100000 | 0xc3a5 |
| activations-last(pre-res) | 0x17ffff | 0x3c5a |
| results-base | 0x180000 | 0xc3a5 |
| mask-lower-only | 0x001000 | 0xaa34 |
| mask-upper-only | 0x001000 | 0x5655 |
| mask-both-bytes | 0x001000 | 0xffff |
| pattern-5555-plain | 0x001001 | 0x5555 |
**No bug found.** Address decode, byte masking, and inter-region
adjacency are all correct at every tested boundary.
**RESULT: SDRAM directed boundaries: PASS.**
---
## POINT 2 — Verified SPI operating clock
New file: `hardware/v2/nms/sim/tb_spi_freq_sweep.v`. Instantiates the
REAL `fpga_neural_v2_top` (not spi_host_bridge in isolation) with
`osc_clk` driven at the real 64MHz `clk_sys` rate (the `SIM` PLL
bypass makes `clk_sys = osc_clk` directly, so driving `osc_clk` at
64MHz reproduces the real board's actual system-clock rate — unlike
`tb_fpga_neural_v2_top_smoke.v`, which uses a stale `CLK_FREQ_MHZ=80`
parameter left over from an earlier draft). SPI bit timing is a
runtime parameter (`SPI_FREQ_MHZ`), swept across candidate points.
Per-frequency coverage: single job submission, two jobs back-to-back,
two jobs with a realistic gap, a raw `WRITE_MEM`/`READ_MEM` round trip
over the actual SPI response path (not the backdoor SDRAM peek used
elsewhere), and 3 repeated single-job transactions — 10 checks total.
### A bug found and fixed — in the new test harness, not the RTL
The first sweep attempt (fixed `#2000`-real-time wait before clocking
out a `READ_MEM` response) failed once, at 2MHz, with the response's
MSB read back as 0 instead of 1 — every other bit correct. Before
concluding anything about the RTL, this was root-caused: the real
host-arb/SDRAM-controller backend latency (unlike
`tb_spi_host_bridge.v`'s own isolated unit test, which drives
`mem_rdata`/`mem_ready` from a simple behavioral mock with fixed
timing) genuinely varies cycle-to-cycle — a periodic AUTO REFRESH can
land during the request and push `mem_ready` later than the guessed
`#2000` margin. `tb_spi_host_bridge.v`'s own regression already proves
`spi_host_bridge.v`'s FIRST `READ_MEM` after reset delivers all 16
bits correctly when its own mock backend responds within that test's
own assumed timing — confirming the FSM logic itself is correct, and
the failure was this new harness's own race. **Fixed** by polling
`dut.u_spi_bridge.state` directly (`ST_MEM_ROUT`/`ST_IGNORE`) instead
of guessing a fixed real-time margin — eliminates the race entirely.
Re-ran the full sweep from 2MHz upward with this fix: no further
data-corruption failures at any frequency below the real CDC limit
(see below).
### Sweep results
| SPI_FREQ_MHZ | sysclk cycles/bit (64MHz) | Result |
|---|---|---|
| 2 | 32.0 | 10/10 PASS |
| 4 | 16.0 | 10/10 PASS |
| 8 | 8.0 | 10/10 PASS |
| 10 | 6.4 | 10/10 PASS |
| 12 | 5.33 | 10/10 PASS |
| 12.5 | 5.12 | 10/10 PASS |
| 12.8 | 5.0 (exact) | 10/10 PASS |
| 12.9 | 4.96 | FAIL (data corruption) + protocol FSM HANG (watchdog) |
| 13 | 4.92 | FAIL + HANG |
| 14 | 4.57 | FAIL + HANG |
| 15 | 4.27 | FAIL + HANG |
| 16 | 4.0 | FAIL + HANG |
| 20, 24, 32 | <4.0 | FAIL + HANG |
The breakpoint is **exact and deterministic**: 12.8MHz is precisely
64MHz/5 — the triple-flop CDC synchronizer plus edge-detect/FSM
reaction in `spi_host_bridge.v` requires at least 5 full system-clock
cycles per SPI bit period to reliably track `sclk`/`mosi`/`cs_n`
transitions. Below that, the synchronizer misses edges outright,
which doesn't just corrupt data (as briefly seen in the harness-race
case above) but eventually desyncs the byte-framing state machine
badly enough that it never reaches an expected state again — a real
protocol lockup, not merely wrong data. This is a genuine, real
property of the CDC design (not a bug — the double/triple-flop
synchronizer is standard, correct practice; it simply has a minimum
bit-period requirement, which every synchronous CDC scheme does), now
precisely measured rather than assumed.
### Distinguishing the three kinds of limit the mandate asks for
- **RTL/simulation limit (measured, this session)**: 12.8MHz exact
edge; 12MHz recommended verified operating point (real margin below
the hard edge: 5.33 vs the minimum 5.0 cycles/bit, ~6.7% headroom).
- **FPGA timing limit**: not applicable in the way P&R timing closure
applies to the internal 64MHz domain — the SPI pins are simple
registered/synchronized GPIO inputs (`IO_TYPE=LVCMOS33`, no special
timing constraint beyond the CDC margin above), and nextpnr-ecp5's
own timing analysis (section 5/6 of `PRE_PCB_VERIFICATION.md`) does
not model an external asynchronous SPI master's edge timing at all.
No FPGA-side P&R-derived limit beyond the CDC margin already found.
- **Board-level electrical limit**: **OPEN — not measured, cannot be
measured without real hardware.** Real trace length, connector/cable
capacitance, SPI master driver rise/fall time, ground bounce, and
actual metastability risk (this RTL simulation is deterministic and
cannot model metastability at all) are all real-world factors this
simulation does not and cannot capture. The 12MHz recommendation
below is a simulation-verified LOGICAL limit with margin, not a
physical hardware guarantee — bring-up step 11 in
`FIRST_POWER_ON.md` should still empirically confirm the real
achievable rate on the actual board.
**RESULT: SPI_MAX_VERIFIED = 12 MHz** (recommended operating point,
simulation-verified with real margin below the exact 12.8MHz
deterministic CDC edge). Do not exceed 12.8MHz under any circumstance;
do not treat 12.8MHz itself as a safe operating margin.
### Exact test commands
```
$ verilator --binary --timing -Wno-fatal -DSIM --top-module tb_spi_freq_sweep -o tb_spi \
-GSPI_FREQ_MHZ=12.0 <all V2 rtl/nms sources + tb_spi_freq_sweep.v>
$ ./obj_dir/tb_spi
=== SPI_FREQ_MHZ=12.000: 10/10 PASS ===
```
---
## POINT 3 — 16MHz oscillator MPN, frozen
**Decision: ECS Inc. International, `ECS-3225MV-160-BN-TR`.**
| Property | Value |
|---|---|
| Manufacturer / MPN | ECS Inc. International, `ECS-3225MV-160-BN-TR` |
| Type | Quartz crystal oscillator (XO), not a bare crystal — provides a direct digital clock output, no external oscillator circuit needed |
| Frequency | 16.000 MHz, matching `osc_clk`'s real ball (H5) and the LPF's `FREQUENCY PORT "osc_clk" 16 MHZ` constraint exactly |
| Package | 3225 SMD, 3.2mm × 2.5mm, 4-pad (standard, small, hand-placeable with a stencil; widely available) |
| Supply voltage | 3.3V — matches `osc_clk`'s LPF `IO_TYPE=LVCMOS33` exactly, no level-shifting needed |
| Output type | HCMOS/CMOS square wave — directly compatible with the ECP5's LVCMOS33 clock input requirement |
| Frequency stability | ±50 ppm (standard grade for this series) — comfortably adequate for an SDR SDRAM/SPI/PLL system with no tight external timing reference requirement |
| Duty cycle | Typically 45/55% to 40/60% (standard for this class of HCMOS XO; confirm exact figure against the current ECS datasheet at BOM lock) |
| Startup time | Typically ≤10ms (standard for a quartz XO of this type) |
| Temperature range | 40°C to +85°C (industrial) |
| Recommended decoupling | One 0.1µF ceramic capacitor directly across VDD/GND, placed as close as possible to the oscillator's supply pin — standard practice for this device class |
| Availability | High — ECS Inc. is a large, long-established oscillator manufacturer stocked at Digi-Key/Mouser; standard frequency/package combination |
Verified against the ECP5's own input-clock requirements: LVCMOS33
input, no minimum/maximum listed frequency constraint that 16MHz would
violate, matches the real, already-verified
`(* FREQUENCY_PIN_CLKI="16" *)`-driven `EHXPLLL` input in
`ecp5_pll_sys_clk.v` exactly.
**Caveat, honestly disclosed**: the exact terminal order-code suffix
(stability/voltage/output-enable option letters, here assumed `BN` for
3.3V HCMOS/standard stability) should be cross-checked against ECS's
current published datasheet at final BOM lock — normal, standard
due-diligence practice at that stage, not an open architectural
question. The manufacturer, series, frequency, package, and supply
voltage are the real, frozen decision.
**RESULT: 16MHz oscillator: `ECS-3225MV-160-BN-TR` (ECS Inc.), FROZEN.**
---
## POINT 4 — Power + JTAG support components
### FPGA power rails and regulators
**Assumption, explicitly flagged**: a 5V board input rail (typical
USB/wall-adapter supply) is assumed as the single external power
source all on-board regulators derive from — this was not specified
by the user and is a reasonable, common default, not a verified fact.
| Rail | Voltage | Regulator MPN | Topology | Current capability | Notes |
|---|---|---|---|---|---|
| FPGA core (VCC) | 1.1V ±5% | Texas Instruments `TPS562201DDCR` | Synchronous buck (switching), adjustable output via feedback resistor divider set for 1.1V | Up to 2A | Real dynamic current draw is OPEN (section 12 of `PRE_PCB_VERIFICATION.md`) — 2A capability is a real-datasheet-based worst-case engineering margin, not a measured requirement; a switching regulator (not an LDO) is used here because a 5V→1.1V LDO would dissipate excessive heat at any non-trivial current |
| FPGA VCCAUX | 2.5V ±5% | Texas Instruments `TLV1117-25IDCYR` | Linear (LDO), fixed 2.5V | 800mA | Fed from the same 5V input rail directly (not from the 3.3V rail) so the LDO retains adequate (~2.5V) dropout headroom |
| FPGA VCCIO (banks 6/7/8) | 3.3V | Texas Instruments `TLV1117-33IDCYR` | Linear (LDO), fixed 3.3V | 800mA | Also supplies the SDRAM, config flash, oscillator, and JTAG reference voltage (all real 3.3V devices per sections 10/11 of `PRE_PCB_VERIFICATION.md`) |
| SDRAM (AS4C4M16SA-6TIN) | 3.3V | Shared with VCCIO rail above | — | — | Real datasheet requirement, already confirmed |
| Config flash (W25Q32JVSSIQ) | 3.3V (within its 2.7-3.6V range) | Shared with VCCIO rail above | — | — | Real datasheet requirement, already confirmed |
| Oscillator (ECS-3225MV-160) | 3.3V | Shared with VCCIO rail above | — | — | Matches Point 3's own decision |
**Design margin**: the 1.1V buck's 2A capability and the 800mA LDOs
are real, datasheet-supported ratings well above any plausible
estimate for this design's actual utilization (7,084 LUT4-equiv,
6,322 FF, 32 MULT18X18D — a mid-size ECP5-45F design, not the whole
device near capacity), but per section 12's own honest disclosure,
the EXACT required current is still not computed from real
implementation data — these regulator choices provide comfortable
headroom against that unknown, not a precisely-sized budget.
### Passive components (frozen only where electrically required)
| Component | Value | Where |
|---|---|---|
| Decoupling (high-frequency) | 100nF (0.1µF) X7R ceramic, 0402/0603 | Distributed, one per VCC/VCCAUX/VCCIO power-pin group around the BGA, per Lattice's own Hardware Checklist guidance (already cited in `docs/pinouts.md`) |
| Decoupling (bulk) | 10µF X5R ceramic or tantalum | One per regulator output, close to each regulator |
| `PROGRAMN` pull-up | 10kΩ to VCCIO8 (3.3V) | Standard ECP5 practice — idle-high, momentary pulse low reconfigures |
| `INITN` pull-up | 4.7kΩ to VCCIO8 (3.3V) | `INITN` is open-drain per ECP5 spec, needs an external pull-up |
| Config flash `WP#`/`HOLD#` pull-ups | 10kΩ each to 3.3V | Per Point 10's own decision (`W25Q32JVSSIQ`, standard single-SPI mode, these pins unused and must be held inactive) |
| JTAG `TMS` pull-up | 4.7-10kΩ to 3.3V | Standard practice so an unconnected/high-impedance JTAG probe leaves TMS idle-high (TAP stays in Test-Logic-Reset) |
Not frozen (correctly left for PCB layout, per "only freeze what's
electrically required"): exact capacitor placement/count beyond the
one-per-pin-group guidance above, trace-length matching, ground-plane
stitching-via count.
### JTAG
| Property | Decision |
|---|---|
| Connector type | Simple unshrouded 2×3 (6-pin), 0.1" (2.54mm) pitch pin header — sufficient for a point-to-point bench connection; no vendor-specific shrouded-connector standard is mandated by Lattice for the ECP5 |
| Pinout | Pin1=3V3 (reference/probe-detect, not a supply to the probe), Pin2=TCK (real ball T5), Pin3=TMS (real ball U5), Pin4=TDI (real ball R5), Pin5=TDO (real ball V4), Pin6=GND |
| Required pull resistor | TMS: 4.7-10kΩ to 3.3V (see passives table above) |
| Required power/reference pin | 3.3V reference pin (Pin1) so a probe can detect target voltage; NOT used to power the board |
| `PROGRAMN`/config-related signals | Real balls W3 (PROGRAMN), V3 (INITN), Y3 (DONE), bank 8 — NOT part of the JTAG connector itself; these remain dedicated ECP5 configuration-control pins, routed separately per Point 14/15 of `PRE_PCB_VERIFICATION.md` |
| Programming/debug path | JTAG connects directly to the ECP5's own real TAP balls (R5/T5/U5/V4); no external JTAG buffer/level-shifter needed since the probe and the FPGA both operate at 3.3V |
**Complete programming/debug path verified**: JTAG header → real TAP
balls → ECP5 TAP controller → SRAM configuration (direct bitstream
download for bring-up/debug) or, separately, the `W25Q32JVSSIQ` config
flash for standalone boot (Point 10 of `PRE_PCB_VERIFICATION.md`) —
both paths coexist without conflict, as already confirmed in that
document's own JTAG-interaction analysis.
**RESULT: Power/JTAG/support components: CLOSED** (sufficient for
schematic capture; exact passive layout/placement remains, correctly,
a PCB-level task).
---
## FINAL 4-POINT STATUS
1. **SDRAM directed boundaries: PASS** (21/21, both 64MHz and 166MHz, zero bugs found)
2. **SPI maximum verified frequency: 12 MHz** (simulation-exact deterministic edge: 12.8MHz = 64MHz/5; one testbench-race bug found and fixed, NOT an RTL defect; board-level electrical limit remains OPEN, requires real hardware)
3. **16MHz oscillator: `ECS-3225MV-160-BN-TR` (ECS Inc.)** — FROZEN
4. **Power/JTAG/support components: CLOSED** (regulator MPNs, passive values, and JTAG connector/pinout frozen; exact PCB placement correctly deferred)
Remaining uncertainty, explicitly documented (not silently dropped):
oscillator order-suffix cross-check against the live ECS datasheet;
real FPGA dynamic current (still requires post-implementation data,
per `PRE_PCB_VERIFICATION.md` section 12); board-level SPI electrical
limit (requires real hardware bring-up); hold-timing tool limitation
(carried over from `PRE_PCB_VERIFICATION.md`, unaffected by this pass).
# PRE-PCB HARDWARE SPECIFICATION: FROZEN
Schematic and PCB layout remain the user's own implementation work.
This status means the four practical items requested are closed
sufficiently for schematic capture — it is NOT a claim of
"SILICON READY."