Files
FPGA-Neural/docs/architecture/neural_processor_batch.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

6.6 KiB
Raw Blame History

NMS Continuous Tile Stream — Memory Manager Redesign (STEP13)

Status: implemented, bit-exact verified, synthesized. Adopted as the new reference NMS memory-manager configuration (DEC-0025). Full data: hardware/v2/nms/reports/batch_processor_{sweep.csv,summary.md}. Full narrative: hardware/v2/logs/experiments.log (EXP-0025 through EXP-0028), decisions.log (DEC-0024, DEC-0025).

Why this file is not neural_processor_batch.v

The governing brief for this STEP asked for a "batch/continuous neuron execution model" — multiple neurons processed per dispatch, or a continuous neuron stream — to amortize the ~68.5-cycles/neuron non-memory floor found in EXP-0024. Before writing any RTL, Step 1 required tracing the actual RTL to find exactly where those cycles go, rather than assuming.

That trace (EXP-0025, an isolated testbench with neural_processor.v

  • nms_memory_manager_pf.v driven with zero real memory latency anywhere) found: 93.4% of the floor is explained by a 4-cycles/tile serialization bug inside the memory manager's own ST_RUN state, not by per-job dispatch overhead (only 6.6%). ST_RUN implements operand delivery as a strictly sequential chain — read_issued → read_ready → present → consumed — with zero overlap between consecutive tiles, even though:
  • the local activation/weight SRAMs (nms_activation_replicated.v, nms_weight_packed.v) have only a 1-cycle rd_en-to-data latency;
  • neural_processor.v's own operand_ready is held continuously high through the whole tile-loading phase — its datapath is explicitly designed (per its own header comment) to accept a new tile every cycle while previous tiles drain through the adder tree/accumulator.

Neither side of this interface requires 4 cycles/tile. It is purely an artifact of the memory manager's own un-pipelined FSM. The fix is therefore a continuous per-tile streaming redesign of the memory manager, not a neuron-batching scheme — hence nms_memory_manager_stream.v, not neural_processor_batch.v. neural_processor.v itself required no modification.

Design: nms_memory_manager_stream.v

Drop-in replacement for nms_memory_manager_pf.v (identical external interface, same weight_prefetch_engine.v instance, same outer job FSM ST_IDLE/ST_WAIT_RESULT/ST_WRITE_RES/ST_DONE). Only ST_RUN's internal operand-delivery logic differs:

  • rd_ptr — the read-issue pointer (which tile's SRAM read has been, or is about to be, issued), independent of and normally one tile ahead of tile_idx (the consumption pointer, i.e. how many tiles neural_processor.v has actually accepted).
  • A 1-deep skid buffer (buf_valid/buf_input/buf_weight/ buf_last) holds one tile's fully-read SRAM data, presented to NP as operand_valid/input_data/weight_data/tile_last.
  • Every cycle: if a read issued last cycle is landing now (1-cycle SRAM latency), it's captured into the skid buffer; independently, a new read is issued for rd_ptr whenever legal (in bounds, weight + activation ready) and the buffer will not overflow (empty, or being drained this same cycle).

Since operand_ready stays high throughout the tile-loading phase, the skid buffer drains every cycle it's full, so a new read can be issued every cycle too — sustained ~1 cycle/tile, down from 4.

tile_idx (the consumption pointer) is still what feeds weight_prefetch_engine.v's own consumed_count port — its external contract is unchanged; only the local SRAM read-issue pointer (rd_ptr) is new, and it can run up to one tile ahead of tile_idx (the skid buffer's own depth).

Verification chain (all real, none assumed)

  1. EXP-0025: isolated zero-latency trace of the old design — established the 4-cycles/tile floor and its 93.4% share of EXP-0024's real measured floor.
  2. EXP-0026: same isolated trace against the new design — the fix works exactly as designed (confirmed cycle-by-cycle), but total cycles barely move (81→80), because it immediately hits a second, previously-masked bottleneck: weight_prefetch_engine.v's own word-fetch rate is also exactly 4 cycles/tile (P_IN=8 bytes ÷ 16-bit bus = 4 word-transactions, 1 cycle/word minimum even at zero real latency) — a bus-width ceiling, structurally different from an FSM-serialization ceiling, that happens to coincide numerically today.
  3. EXP-0027: a direct control experiment — a scratch variant with weight-fetch bypassed (always-ready) isolates the new design's own ceiling: a clean 1 cycle/tile (100% of neural_processor.v's theoretical per-tile rate), vs. the old design's hard 4-cycles/tile cap under the identical bypass. This is the direct proof that the fix removes a real, 4× architectural ceiling — it was just masked by a coincidentally-equal second bottleneck.
  4. EXP-0028: full real-system integration (nms_dataflow_core_stream.vnms_neural_multiprocessor_stream.v, real V1 PSRAM chain) — bit-exact PASS, 256/256 neurons, D-Stress workload identical to EXP-0022/0024. Real cycle count: 185270 vs. 185398 (_pf baseline), -0.07% — confirms the "masked, zero net benefit today" prediction exactly. Real synthesis + P&R: N=1 Fmax=142.92 MHz (+3.7% vs. baseline), N=2 Fmax=92.57 MHz (-2.8%, still comfortably above 80 MHz), resource cost within ±6%. N=4: 55.22 MHz, FAILS 80 MHz — but for the pre-existing, already-documented nms_activation_fill_ctrl.v priority-scan regression (EXP-0022), unrelated to and unaffected by this fix.

Outcome and adoption

Outcome B (helps, but another bottleneck appears — see DEC-0025 and batch_processor_summary.md for the full nine-question final decision). nms_memory_manager_stream.v is adopted as the new reference configuration: it is a strict improvement (bit-exact, resource-neutral, no measured downside) and is required groundwork for any future PSRAM bandwidth increase to actually translate into a throughput gain — without it, a wider/faster memory would immediately hit the old FSM's 4-cycles/tile ceiling and realize only 25% of its potential benefit. The original nms_memory_manager.v and nms_memory_manager_pf.v remain preserved, unmodified, for A/B/C reference. Neuron-batching (the brief's original Model B/C) was not pursued — evidence showed it addresses only 6.6% of the real floor and would deliver no measurable benefit today for the identical reason (weight-fetch-rate-bound). N=4/N=8 viability remains blocked by two independent issues neither addressed by this STEP: external PSRAM bandwidth, and the activation fill controller's own Fmax regression — both flagged as future work.