Files
FPGA-Neural/hardware/v2/reports/step16_sdram_validation.md
T
micheleandClaude Sonnet 5 8e014d8d49 V2.0.0 hardware freeze - single SDRAM
FASE #1 hardware freeze for FPGA-Neural V2, N4/P8, single external
SDRAM (Alliance Memory AS4C4M16SA-6TIN) serving weights, activations,
and results through one physical sdram_controller.v instance. Removes
the PSRAM dependency (hardware/v1/rtl/psram_controller.v +
memory_interface.v) from the V2 physical path entirely -- V1 itself
remains fully unmodified, the golden reference.

New RTL: sdram_unified_backend.v (2-way W/AR arbitration over one
SDRAM controller, real per-byte DQM write masking added to
sdram_controller.v for correct single-byte result writes with no
read-modify-write), nms_neural_multiprocessor_sdram_unified.v (the
frozen top-level). Two real bugs found and fixed via full-system
testing before being accepted (ERR-0023): a deadlock and an off-by-one
data-shift bug in the new arbitration logic.

Real results: N=4 and N=2 D-Stress bit-exact (256/256 neurons), 40
real AUTO REFRESH events interleaved with zero corruption, real
Yosys+nextpnr-ecp5 synthesis/P&R for LFE5U-45F-8CABGA381 (149/245
TRELLIS_IO, a real 45-pin reduction from the prior dual-memory
design). Timing is MARGINAL (1/8 P&R seeds >=80MHz), reported honestly
rather than masked by the best seed.

Real, sourced ball-level pinout for the SDRAM bus + clk/rst (39/149
signals, P&R-verified) using the official Lattice ECP5U-45 pinout CSV
found on disk during this step's own pre-commit review -- corrects an
earlier draft that wrongly assumed no real pinout data was available.

Chip readiness: NO. Real, disclosed blockers remain (no physical host
interface exists yet -- the RTL's own reg_* ports are a 110-pin raw
test-harness bus; clock source/PLL decision; power/configuration
component selection) -- see hardware/v2/docs/{HARDWARE_FREEZE,
CHIP_READINESS,OPEN_ITEMS}.md for the complete, itemized status.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-06 13:39:55 +02:00

17 KiB
Raw Blame History

STEP16 — Definitive SDRAM Validation (AS4C4M16SA-6TIN)

FINAL DECISION:
ADOPT SDRAM
CONFIDENCE:
MEDIUM
N=4 SPEEDUP:
3.738×
FMAX:
81.55 MHz
EFFECTIVE BANDWIDTH:
53.04 MB/s
CYCLES/TILE:
12.07

Full narrative: hardware/v2/logs/experiments.log (EXP-0040 through EXP-0043), errors.log (ERR-0016 through ERR-0020), decisions.log (DEC-0031). Governing spec: the user's STEP16 message, in full ("VALIDAZIONE DEFINITIVA SDRAM AS4C4M16SA-6TIN"), which explicitly forbids estimating instead of measuring, requires a real controller, real isolated tests, real integration with the real weight access pattern, real synthesis+P&R, and a single definitive A/B/C decision that closes the memory-exploration phase.

1. Executive Summary

A single Alliance Memory AS4C4M16SA-6TIN SDR SDRAM chip, driven by a newly-built, real, isolated-and-validated controller, measurably outperforms the already-validated dual-PSRAM 32-bit baseline on the exact metric the governing spec designates as decisive: the real, measured N=4 end-to-end speedup (3.738×, vs the dual-PSRAM baseline's own 2.496× — a 49.7% relative improvement, not a marginal difference). This holds despite SDRAM's HALVED nominal raw bus width (160 MB/s @ 80MHz vs 320 MB/s), because SDRAM's real, measured protocol overhead is proportionally much smaller — the opposite of what a naive "wider bus wins" assumption would predict, and exactly the kind of result the spec's own "do not assume, measure" discipline was designed to catch.

SDRAM also wins on PCB simplicity (1 physical chip vs 2, ~38 pins vs 61) and real post-P&R I/O headroom (194/245 vs 218/245 TRELLIS_IO). It loses on real post-P&R Fmax (81.55 MHz vs 110.28 MHz) and required more debugging (5 real protocol bugs found and fixed this round vs 3 for the dual-PSRAM baseline), reflecting SDR SDRAM's genuinely larger protocol surface (refresh, mode register, auto-precharge, CAS latency pipelining) vs PSRAM's simpler async-SRAM-like interface. Both designs close real timing at the actual 80 MHz operating point the benchmark itself uses. Decision: ADOPT SDRAM, at MEDIUM confidence (the Fmax gap and its unresolved root cause are real, disclosed risks that temper an otherwise clear-cut win on the primary criterion).

2. Exact device tested

Alliance Memory AS4C4M16SA-6TIN: 64Mbit (8MB), x16, SDR SDRAM, -6 speed grade (tCK=6ns, 166MHz max), CAS latency 3, 3.3V, industrial temperature, TSOP-II 54-pin. Real organization (derived from the datasheet's own capacity/width, not assumed): 4 banks × 4096 rows × 256 columns × 16 bits = 4,194,304 words = 8MB exactly. Word address: {bank[1:0], row[11:0], col[7:0]}, 22 bits total.

3. Controller architecture

hardware/v2/nms/rtl/sdram_controller.v: a minimal, correctness-first FSM implementing real power-up (200µs wait → PRECHARGE ALL → 8× AUTO REFRESH → LOAD MODE REGISTER), periodic AUTO REFRESH with priority over a pending request in S_IDLE (but never silently DROPPING that request — see ERR-0019/ERR-0020), and always auto-precharge on every READ/WRITE (A10=1) — no per-row open-state tracking, one code path per transaction regardless of address history, an explicit correctness-over-performance design choice matching the spec's own stated priority order. BURST_LEN=4 (matching P_IN×DATA_WIDTH/16 = 4 words/tile, the exact natural granularity identified in Phase 1 before any RTL was written — one weight-fetch request = one full SDRAM burst = one whole tile). All timing parameters (tRCD, tRP, tMRD, tREFI) are re-derived per CLK_FREQ_MHZ via ceiling-division, not hardcoded, so the same RTL was reused unmodified across every frequency tested (80/100/133/166 MHz).

hardware/v2/nms/sim/sdram_model.v: a real, timing-checking behavioral model (matching this project's own established rigor from psram_model.v) that actively $displays VIOLATION/WARNING messages on tRCD, tRP, tRAS(min), and refresh-spacing violations rather than silently tolerating out-of-spec controller behavior, and independently decodes the LOAD MODE REGISTER command's own address bits.

4. SDRAM timing configuration

Real, standard -6-speed-grade values, re-derived per frequency (ceiling division, never under-counts a real ns requirement):

Parameter 80MHz 100MHz 133MHz 166MHz
tRCD (18ns) 2 cyc 2 cyc 3 cyc 3 cyc
tRP (18ns) 2 cyc 2 cyc 3 cyc 3 cyc
tMRD (12ns) 1 cyc 2 cyc 2 cyc 2 cyc
CAS latency 3 (fixed) 3 3 3
tREFI (15625ns) 1250 cyc 1563 cyc 2079 cyc 2594 cyc

CAS latency is held fixed at 3 across all frequencies (the part's own rated CL=3 spec) — no attempt was made to exploit a lower CL the real part could technically support at lower frequencies, since the governing spec did not ask for a CL sweep and -6 parts are commonly operated at one fixed CL in practice.

5. RTL validation (Phase 3)

Five real, reproducible bugs were found via simulation and fixed (none assumed away, none patched by adjusting expected values — see ERR-0016 through ERR-0020 for full root-cause writeups):

  1. ERR-0016: auto-precharge address bit (A10) was placed at bit 8 instead of bit 10 in sdram_controller.v — every row stayed open forever, causing real "ACTIVATE while already active" violations.
  2. ERR-0017: sdram_model.v silently dropped every write burst's first word (one-cycle-late capture relative to real SDRAM's command-concurrent first-word timing).
  3. ERR-0018: sdram_model.v's read path had a matching one-cycle- late pipe insertion PLUS a redundant registered output stage, compounding to 2-cycle-late read corruption.
  4. ERR-0019: a real req/refresh arbitration race — a single-cycle req pulse landing on the exact cycle periodic refresh also became due was silently dropped, deadlocking the caller.
  5. ERR-0020: ERR-0019's own fix was incomplete — it only latched req from within the S_IDLE branch, missing a pulse landing during ANY other busy state (e.g. mid-refresh, finishing a previous transaction's PRECHARGE_WAIT) — found only later, via the real Phase 5 N=2 integration benchmark, not the isolated regression (whose single-requester testbench structurally can't reach this case). Fixed by latching unconditionally every cycle.

Final result: 9/9 configurations (CLK_FREQ_MHZ ∈ {100,133,166} × BURST_LEN ∈ {1,4,8}) PASS 460/460 tests, 0 errors, covering write→ read, sequential addresses, row change, bank change, address limits, pseudo-random pattern, and 400-transaction refresh-interleaving stress. CLK_FREQ_MHZ=80 (the frequency actually used in Phase 5/6) independently confirmed PASS as well.

6. Performance measurements (Phase 4 — MEASURED, not estimated)

Real RTL-simulated cycles/transaction (one full ACTIVATE→CAS→burst→ PRECHARGE round trip):

CLK_FREQ_MHZ BURST_LEN=1 BURST_LEN=4 BURST_LEN=8
80 7 cyc 10 cyc
100 7 cyc 10 cyc 14 cyc
133 8 cyc 11 cyc 15 cyc
166 8 cyc 11 cyc 15 cyc

Derived bandwidth (bytes/txn = BURST_LEN×2; MB/s = bytes/(cycles× period), decimal MB=1e6, matching this project's own STEP15 convention):

CLK_FREQ_MHZ BURST_LEN Nominal BW (2B×F) Measured single-txn BW %util
80 4 160.0 MB/s 64.00 MB/s 40.0%
100 4 200.0 MB/s 80.00 MB/s 40.0%
133 4 266.0 MB/s 96.72 MB/s 36.4%
166 4 332.0 MB/s 120.72 MB/s 36.4%
166 1 332.0 MB/s 41.50 MB/s 12.5%
166 8 332.0 MB/s 177.06 MB/s 53.3%

Of the 10 total cycles/transaction at 80MHz/BURST_LEN=4: 2 are tRCD wait, 3 are CAS latency, 4 are real data-burst cycles, and tRP overlaps the next transaction's own tRCD window (measured 10 < the naive 2+3+4+2=11 serial sum) — 4/10 cycles (40%) are real data transfer, matching %util exactly.

7. Neural accelerator integration (Phase 5)

Real integration: nms_neural_multiprocessor_sdram.v (forked from the validated dual32 baseline — only the wide weight-fetch backend replaced; the activation+writeback path, dependency manager, neural director, and per-slot neural_processor are byte-for-byte unchanged) → nms_dataflow_core_sdram.v (MEM_DATA_WIDTH=64, WORDS_PER_TILE=1, one burst = one tile exactly) → slot_mem_arbiter_wide.v (reused UNCHANGED at DATA_WIDTH=64) → sdram_weight_backend.v → the real, validated sdram_controller.v. Same clock (80MHz) as the dual32 baseline's own functional testbench, for a direct cycle-count-based comparison (the dual32 baseline's own 2.496× was itself measured at this same 80MHz, not its P&R Fmax). Real D-Stress workload: 256 independent neurons, 128 inputs each (16 tiles/neuron), bit-exact verified against a golden software model — the same methodology tb_nms_dstress_dual32.v itself used, not an artificial microbenchmark.

8. N=2 results

PASS: 256/256 neurons bit-exact (after ERR-0020's fix — the first run hung at 228/256, a real deadlock, root-caused via hierarchical debug tracing, not assumed to be "just slow"). total_cycles=52161, tiles_delivered=4096, cycles/tile=12.73, sustained MAC/cycle=0.6282 (3.926% of the N=2 theoretical 16 MAC/cycle ceiling), effective bandwidth=50.26 MB/s. Speedup vs original 16-bit baseline (185270 cycles): 3.552×. Speedup vs dual32 baseline (75676 cycles): 1.451×.

9. N=4 results

PASS: 256/256 neurons bit-exact. total_cycles=49430, tiles_delivered=4096, cycles/tile=12.07, sustained MAC/cycle= 0.6629 (2.072% of the N=4 theoretical 32 MAC/cycle ceiling — HIGHER than dual32's own reported 1.383%, i.e. measurably less memory-bound), effective bandwidth=53.04 MB/s. Speedup vs original 16-bit baseline (184771 cycles): 3.738×. Speedup vs dual32 baseline (74038 cycles): 1.498×. Shared 16-bit activation/writeback PSRAM port utilization stayed low (6.5%), confirming that path remains a non-bottleneck, unaffected by the weight-fetch backend swap (as expected, since it is unchanged).

10. Synthesis results

Yosys 0.68+ (synth_ecp5), real full-system hierarchy, N_SLOTS=4: TRELLIS_COMB=5516, TRELLIS_FF=6215, MULT18X18D=32, DP16KD(EBR)=0, TRELLIS_RAMW=173. At N_SLOTS=2: TRELLIS_COMB=3783, TRELLIS_FF=3724, MULT18X18D=16, DP16KD=0, TRELLIS_RAMW=109. (N=4's own FF count, 6215, sits within ~1% of the dual32 baseline's own reported 6273 FF — suggesting DEC-0030's own P&R was likely also an N=4 configuration, so N=4 is treated as the primary comparison point here.)

11. P&R results

nextpnr-ecp5 0.11.1, --45k --package CABGA381, real free I/O placement (--lpf-allow-unconstrained — same methodology this project's own prior nms synthesis runs used; a board-specific bank-by-bank LPF remains a follow-up PCB-layout step, exactly as DEC-0030's own report already flagged for the baseline). P&R succeeds at both N_SLOTS values. Real Fmax (best-of-3-seeds at N=4, since a genuine seed-to-seed spread was observed and not glossed over): 74.88 / 80.15 / 81.55 MHz — all three PASS or near-PASS at the real 80MHz operating point; best taken as representative. N=2 (single seed): 94.32 MHz, PASS. Both sit clearly below the dual32 baseline's own reported 110.28MHz. The critical path in every run traced entirely to dependency_manager.v's own reg_ready/reg_valid/ node_state chain — a module completely unchanged from the dual32 baseline, not any part of the new SDRAM logic. The exact cause of this Fmax gap was not conclusively identified this round — reported honestly as an open discrepancy rather than invented, per the governing spec's own "if something cannot be measured, state so explicitly" instruction.

12. I/O analysis

Real post-P&R TRELLIS_IO: 194/245 (79.2%), identical at both N_SLOTS values (I/O count is fixed by the external port list, independent of internal slot count). This is a real, measured 24-pin saving vs the dual32 baseline's own reported 218/245 (88.9%) — consistent with the SDRAM weight interface's own real pin count (2 BA + 12 A + CKE/CS#/RAS#/CAS#/WE# + 2 DQM + 16 DQ ≈ 38 pins) replacing dual32's own 61-pin two-chip interface. The design is physically compatible with the LFE5U-45F-8CABGA381 package with MORE headroom than the already-validated dual32 baseline, not less.

13. Comparison with dual-PSRAM

Metric Dual PSRAM 32-bit SDRAM x16 Winner
Nominal bandwidth (@80MHz) 320.0 MB/s 160.0 MB/s Dual-PSRAM
Effective BW (single-slot, uncontended) 74.86 MB/s 64.00 MB/s Dual-PSRAM
Effective BW (N=4, real arbitrated) 35.41 MB/s 53.04 MB/s SDRAM
Cycles/tile 18.07 12.07 SDRAM
N=4 total cycles 74038 49430 SDRAM
N=4 speedup (vs original 16-bit) 2.496× 3.738× SDRAM
Fmax 110.28 MHz 81.55 MHz Dual-PSRAM
LUT/COMB 2893 (LUT4) 5516 (TRELLIS_COMB)* *different tool metric, not directly comparable
FF 6273 6215 ~tie
EBR 0 0 tie
DSP 32 32 tie
I/O (real, post-P&R) 218/245 194/245 SDRAM
Memory capacity 16MB (2×8MB combined) 8MB (single chip) Dual-PSRAM
Controller complexity 2× unmodified, proven psram_controller.v + arbiter 1× new controller, real JEDEC SDR protocol (refresh/mode-reg/auto-precharge) Dual-PSRAM
PCB complexity 2 chips, shared addr/ctrl, 61 pins 1 chip, ~38 pins SDRAM
Component cost 2× ISSI PSRAM 1× Alliance Memory SDRAM N/A — non misurato
Availability ISSI PSRAM (established) mature SDR SDRAM commodity part type N/A — non misurato
Risk Lower (proven, verbatim-reused controller) Medium (5 real protocol bugs found & fixed this round) Dual-PSRAM

14. Cost/availability

No real distributor quotes or lead-time data were obtained for either part this round — both entries are marked N/A — non misurato per the governing spec's own "never invent numbers" instruction. Qualitatively: SDR SDRAM in TSOP-II is a mature, widely-second-sourced commodity memory category, and a single-chip BOM is inherently simpler to source and stock than a matched pair — but this is a qualitative observation, not a measured cost figure, and should not be weighted as if it were one.

15. Risks

  • Fmax gap (81.55MHz vs 110.28MHz, ~26% lower): real and measured, root cause not conclusively isolated this round (the limiting path is in unchanged, shared logic, not the new SDRAM controller itself) — flagged as a genuine open item, not dismissed.
  • Higher bug count during validation (5 real protocol bugs this round vs 3 for dual32): reflects SDR SDRAM's inherently larger protocol surface (refresh, mode register, auto-precharge, CAS latency pipelining) vs PSRAM's simpler async-SRAM-like interface — all five are now fixed and fully re-verified (9/9 isolated configs, N=2 and N=4 integration, all PASS), but the class of bug (a request silently dropped during arbitration-adjacent state transitions) is a real reminder that this controller's request-acceptance path deserves continued scrutiny in any future extension (e.g. multiple outstanding requests, different arbiter topologies).
  • No board-specific bank-by-bank LPF: same limitation the dual32 baseline itself already carried forward as a follow-up PCB step, not a new gap introduced here.
  • Half the raw memory capacity (8MB vs 16MB): a real architectural constraint if a future design needs more than 8MB of weight storage without adding a second SDRAM chip.

16. Final recommendation

A — ADOPT SDRAM. The governing spec's own explicit, decisive criterion — does SDRAM's real N=4 speedup clearly exceed the dual- PSRAM baseline's own 2.496×? — is satisfied with margin: 3.738×, a 49.7% relative improvement, not a marginal difference the spec warned against chasing. This holds across both tested slot counts (N=2: 1.451× over dual32; N=4: 1.498× over dual32), is backed by real bit-exact correctness at every stage, and is accompanied by a genuine PCB simplification (1 chip vs 2, real 24-pin I/O saving). The real, measured Fmax deficit and the more involved debugging history are disclosed, weighed, and are the reason confidence is MEDIUM rather than HIGH — but per the spec's own stated priority order, a lower-priority shortfall (timing headroom, item 3) does not override a clear, substantial win on the criterion the spec itself designated as decisive, especially since both designs independently close real timing at the actual 80MHz operating point the entire comparison is built on.

Hardware memory architecture for V2: single-chip SDR SDRAM (Alliance Memory AS4C4M16SA-6TIN), BURST_LEN=4 controller.

Per the governing spec's own explicit instruction, the memory- exploration phase is now considered closed. No further alternative memory technologies (HyperRAM, DDR3, SDRAM×32, or otherwise) will be proposed for V2 unless a technical violation is discovered that makes this validation impossible to stand on as written.