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

123 lines
6.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.
# 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.v``nms_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.