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
9.6 KiB
NMS STEP14 — Weight Datapath Scaling & Activation Fabric Timing: Final Report
Full data: step14_weight_scaling.csv, step14_activation_timing.csv
(this dir). Architecture: docs/architecture/weight_datapath_scaling.md,
docs/architecture/activation_fabric_timing.md. Full narrative:
hardware/v2/logs/experiments.log (EXP-0029 through EXP-0033),
decisions.log (DEC-0026, DEC-0027, DEC-0028).
Critical comparison table
Real, measured (POST-P&R Fmax/resources; RTL SIMULATION bit-exact cycles, real V1 PSRAM chain unless noted). D-Stress workload (256 neurons, 16 tiles each) throughout.
| Configuration | N | Fmax (MHz) | Pass 80MHz | LUT4 | CCU2C | FF | DSP | Total cycles | Sustained MAC/cyc |
|---|---|---|---|---|---|---|---|---|---|
| Current NMS (pre-STEP13) | 1 | 160.18 | ✓ | — | — | 2281 | 8 | n/a | n/a |
| Current NMS | 2 | 93.10 | ✓ | 1948 | 266 | 3522 | 16 | 185645 | 0.1765 |
| Current NMS | 4 | 56.62 | ✗ | — | — | 6004 | 32 | 184764 | ~0.177 |
| Streaming NMS (STEP13) | 1 | 137.76 | ✓ | 1464 | 200 | 2245 | 8 | n/a | n/a |
| Streaming NMS | 2 | 95.25 | ✓ | 1908 | 362 | 3449 | 16 | 185398 | 0.1767 |
| Streaming NMS | 4 | 55.22 | ✗ | 2937 | 705 | 5877 | 32 | 184771 | 0.1773 |
| Streaming + wider weight path (IDEAL, MEM_DATA_WIDTH=64, not real-hardware-deployable) | standalone | n/a (I/O-oversubscribed, POST-SYNTH only) | — | 144 | 71 | 386 | 0 | n/a (1 cyc/tile ideal) | n/a |
| Streaming + activation timing fix (v3) | 1 | 138.85 | ✓ | 1431 | 206 | 2282 | 8 | n/a | n/a |
| Streaming + activation timing fix | 2 | 136.09 | ✓ | 1999 | 371 | 3507 | 16 | 185270 | 0.1769 |
| Streaming + activation timing fix | 4 | 106.81 | ✓ | 2776 | 705 | 5957 | 32 | 184771 | 0.1773 |
| Streaming + activation timing fix (= Combined architecture) | 8 | 52.25 | ✗ | 4653 | 1367 | 10855 | 64 | 184771 | 0.1773 |
The "Combined architecture" is the "streaming + activation timing fix" row — Part A's weight-width fix is not realizable on real hardware (see below), so there is nothing further to combine at the physical level this round.
Part A — Weight Datapath Scaling: summary
Built weight_prefetch_engine_wide.v (parameterized MEM_DATA_WIDTH)
and nms_memory_manager_stream_wide.v. Bit-exact at all 4 widths
(16/32/64/128, 9/9 tests each). Ideal-memory cycles/tile: 4, 2, 1,
1 — confirming 64-bit is the exact architectural point (matches
P_IN×DATA_WIDTH) that removes the weight-fetch bottleneck entirely
(100% of theoretical per-tile rate). 128-bit gives zero further
benefit. Critically: this cannot be realized on the current board.
The real V1 PSRAM is a fixed 16-bit physical chip; the already-existing
real weight_prefetch_engine.v already represents the "64-bit logical
via 16-bit physical" packing case, and its real measured rate (4
cycles/tile) proves logical width alone yields zero real benefit
without a matching physical bandwidth increase. See
weight_datapath_scaling.md for full reasoning.
Part B — Activation Fabric Timing: summary
Exact critical path traced from the real P&R report (not assumed):
resident_tag → max_n_tiles computation (line 92) → resident_count < max_n_tiles comparison (line 165) → pf_start/pf_addr, two
chained 16-bit comparisons in one combinational cone, 18.11 ns. Fixed
in two iterations: v2 (register once) reached 72.78 MHz (insufficient);
v3 (separate the per-slot tag-equality stage from the max-fold stage)
reached 106.81 MHz at N=4 (+93.4%), bit-exact, zero throughput
regression at N=2 (in fact N=2's own Fmax jumped to 136.09 MHz as a
bonus — the same chain was present there too, just under the 80 MHz
threshold already). N=8: DSP/LUT/FF all feasible, but Fmax still fails
(52.25 MHz) — the fold itself is still O(N_SLOTS)-deep; v3 shifted the
crossover point, a further log₂(N_SLOTS)-scaling fix would be needed
for N=8 (not undertaken, N=8 is exploratory only).
Roofline update
The EXP-0024 model T(k) = 17.544 + 167.854/k is superseded by a
decomposed model built from real, RTL-traced components (EXP-0033):
T(n_tiles) = T_startup_drain + n_tiles × T_weight [real hardware, N=1]
= 16 + n_tiles × 4 [cycles]
- T_control (memory-manager serialization): was 3/4 of the old floor's per-tile cost — fixed (STEP13), now ~0.
- T_weight (real 16-bit PSRAM bus): still 4 cycles/tile — a physical bus-width floor, proven (ideal) to reach 1 cycle/tile at 64 bits, but not realizable without a physical bandwidth increase.
- T_activation (Fmax only): fixed (Part B) — zero effect on cycle count, only on achievable clock frequency.
- T_startup_drain (~16 cycles/job): unchanged by any fix, a small, genuinely separate, already-minimal residual.
- T_external_memory (real port contention, N_SLOTS≥2): the true dominant real bottleneck — N=2/4/8 all produce statistically identical real cycle counts (185270/184771/184771) despite theoretical MAC/cycle scaling 16/32/64. Untouched by any fix in STEP13 or STEP14, since neither touches the physical port itself.
Does the new architecture remove the previous 11.674% asymptotic ceiling? No, not on real hardware today — the ceiling is numerically unchanged (still 11.674% at N=2), because its dominant cause (T_weight, physical bus width, ~64 of every 68.5 cycles/neuron) was never addressable by any RTL-scheduling fix; the fixes made in STEP13 (T_control) and STEP14 Part B (T_activation/Fmax) targeted smaller, genuinely separate components that were already minor relative to the bus-width floor. In principle, yes — both the control-plane ceiling (STEP13) and the weight-fetch-rate ceiling (STEP14 Part A, ideal) have already been shown to reach the architectural optimum (1 cycle/tile); only the physical PSRAM interface itself remains as the blocker, a hardware/board-level dependency outside this project's own RTL scope.
A DERIVED, hypothetical upper bound (NOT a real-hardware promise): if physical bandwidth reached 64 bits and N=2 slots had fully independent, uncontended ports (unrealistic for a single physical memory), utilization would reach 50% — a large improvement over 1.1%, but still short of the 90% target, and almost certainly optimistic once real port contention at 64-bit width is accounted for (not measurable — no such real hardware exists to test).
The twelve final questions, answered directly
- Is 16-bit weight delivery fundamentally insufficient for P_IN=8? Yes — costs 4× the achievable minimum (4 vs. 1 cycle/tile).
- Is 32-bit enough? No — still 2× the minimum.
- Is 64-bit the natural architectural point? Yes, exactly —
proven cycle-exact (
P_IN×DATA_WIDTH). - Does wider logical weight delivery actually improve real throughput? No, not on this board — requires a matching physical bandwidth increase; logical width alone is provably inert (DEC-0028).
- What is the exact activation-fill critical path?
resident_tag→max_n_tilesfold (line 92) →resident_countcomparison (line 165) →pf_start/pf_addr— two chained 16-bit comparisons, no register between, 18.11 ns total. Traced from the real P&R report, not assumed. - What is the minimum fix required for N=4 ≥80 MHz? Two pipeline stages: register the per-slot tag-equality/masking result, then separately register the max-fold result before its use — v3, 106.81 MHz.
- Does N=4 become genuinely useful after both fixes? Timing: yes (106.81 MHz, real margin). Throughput: no — real cycle count is statistically identical to N=2 (single shared PSRAM port saturated), so absolute throughput does not improve, only headroom for a future bandwidth increase does.
- Is N=8 timing/resource feasible? Resource: yes (DSP 89%, LUT/FF comfortable). Timing: no (52.25 MHz) — the max-fold's O(N_SLOTS) depth reappears at 2× the N=4 depth; a log₂(N_SLOTS)-scaling fix is required and not yet built.
- What external memory bandwidth is required after these fixes? Unchanged from EXP-0024's own quantification (~36-82× today's real bandwidth for 90/95/99% targets) — these fixes make the RTL ready to exploit that bandwidth if it existed; they do not create it.
- What internal SRAM/banking architecture should be designed next? None needed for weight/activation SRAM sizing itself (already adequate); the next design target is external — real PSRAM bus width/banking, and (separately) a log₂(N_SLOTS) activation-fold pipeline for N=8.
- Should
neural_processor.vremain unchanged? Yes — confirmed again this STEP: it was never implicated in either bottleneck. - What is the next experiment? Two independent, concrete, evidence-backed candidates: (a) real hardware feasibility study of a wider/banked external PSRAM interface (board-level, outside RTL scope); (b) a balanced-tree (log₂(N_SLOTS)-depth) redesign of the activation-fill max-computation specifically for N=8.
Final decision
Both parts closed with real, RTL-traced, bit-exact-verified evidence —
no assumption stood unverified. Part A establishes the precise
architectural requirement (64-bit) and proves it is currently
unrealizable (a hardware, not RTL, gap). Part B delivers a real,
adopted fix (nms_activation_fill_ctrl_v3.v) that achieves N=4's
Fmax criterion outright with zero throughput cost. Neither fix moves
the real N=2/4/8 D-Stress cycle count, because both targeted
components that were never the dominant term — the dominant term
(external memory bandwidth) remains exactly as EXP-0024 quantified it,
now with full, precise attribution rather than an unexplained "fixed
overhead."