docs: Phase 7 placement-seed sweep + hardware design document

Phase 7 (docs/FPGA-NeuralNetwork-Engine.md): re-ran nextpnr-ecp5 on
the already-synthesized Phase 5 spi_neuron_top netlists (top.json
reused, only placement re-seeded) at --seed 1/2/3 for both P8 and P2.
Both land in a tight band regardless of seed (P8: 39.5-40.6 MHz,
2.6% spread; P2: 42.5-45.0 MHz, 5.8% spread) -- confirms the Phase 5
timing shortfall is a real structural bottleneck, not placement
noise, unlike the much smaller same-tier benchmark design (<2%
utilization, huge placer freedom, genuinely noisy). Corrected the
earlier "pipeline the saturate stage" candidate fix, which targeted
Phase 4's critical path and not the one Phase 5's logic actually
shifted to; block RAM for x_mem/w_mem remains the leading candidate,
not yet implemented.

New docs/FPGA-Neural-Hardware-Design.md: draft hardware design doc
for a board carrying the project's actual target device
(LFE5U-45F-8BG381C) plus the parallel PSRAM rtl/psram_controller.v
is written for. Covers: why not the basic-ecp5-pcb reference board
(wrong package/speed grade, no RAM), a real I/O pin budget from
Lattice's own CABGA381 pinout table, a researched PSRAM part
(ISSI IS66WVE4M16EBLL-70BLI -- 70ns access matches the controller's
timing assumption exactly, with a note on the byte/word address
shift in int8_memory_access.v so the chip's top address line is
correctly left as spare headroom, not a wiring error), clock
(16 MHz, no PLL exists yet so CLK_FREQ_MHZ must match whatever
oscillator is fitted), power/config reusing the reference board's
proven circuitry and errata (config-SPI pin can't double as the
application SPI interface), and a BOM/open-items list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
This commit is contained in:
2026-09-02 20:54:52 +02:00
co-authored by Claude Sonnet 5
parent a918c3f1e9
commit f6edc01613
2 changed files with 300 additions and 17 deletions
+44 -17
View File
@@ -919,24 +919,51 @@ neither Phase 4's nor Phase 5's single P2/P8 runs establish that.
**Candidate directions (not implemented, need a decision before
touching the validated core further):**
**Placement-seed sweep (2026-09-02) — resolved: it's structural, not
noise.** Re-ran `nextpnr-ecp5` on the already-synthesized Phase 5
netlists (`top.json` reused, only placement re-seeded — no re-synth)
at `--seed 1/2/3` for both P8 and P2:
| Build | seed (default) | seed 1 | seed 2 | seed 3 | spread |
|---|---|---|---|---|---|
| P8 | 40.57 MHz | 39.70 MHz | 39.54 MHz | 40.00 MHz | 1.03 MHz (2.6%) |
| P2 | 42.54 MHz | 42.82 MHz | 42.72 MHz | 45.01 MHz | 2.47 MHz (5.8%) |
Both builds land in a tight band regardless of seed — nothing close
to the P2/P4/P8 same-tier benchmark's own non-monotonic swings (that
benchmark's design uses <2% of the device, so its placer has enormous
freedom; `spi_neuron_top`'s fuller design does not). **This confirms
a real structural bottleneck, not a lucky/unlucky placement** — a
seed sweep or floorplan constraint will not close a ~2x gap to
80 MHz by itself; an RTL change is needed.
**Candidate directions (not implemented, need a decision before
touching the validated core further):**
- Move `x_mem`/`w_mem` onto `DP16KD` block RAM (0% used) instead of
LUT fabric — likely the highest-leverage single change, since it
is directly implicated in the Phase 5 critical path and currently
wastes a free, purpose-built resource.
- Add a pipeline register between the final MAC accumulation and the
activation/saturate stage in `neuron_parallel.v`, trading +1 cycle
of per-neuron latency (negligible next to the existing
N_INPUTS/PARALLEL group-count cycles) for a shorter combinational
path. No existing testbench hardcodes an exact cycle count for
neuron completion (`wait(done)`/polling patterns throughout), so
this should be low regression-risk — but it is still a change to
the explicitly "validated, don't touch" datapath (`mac8`/`mac_unit`
/`neuron_parallel`), so deserves an explicit go-ahead rather than
being done opportunistically.
- A `nextpnr` seed/effort sweep to check how much of the shortfall is
placement variance (see P4's own 75.01/76.41 MHz two-number report
in the same run, or P2/P4/P8's non-monotonic Fmax in the
same-tier benchmark) vs. a structural bottleneck.
LUT fabric — the leading candidate. The critical path runs through
what looks like `w_mem`'s *write*-address decode (`neuron_memory`
loads one byte per cycle into a variable index during
`STATE_READ_X`/`STATE_READ_W`, which needs a full-width mux/demux
in LUT fabric to steer that byte to the right register) feeding
forward into the accumulator's input path — not the arithmetic
itself. A block-RAM read/write port replaces that scattered
LUT-based decode with a single hard macro. This is a genuine
redesign, not a drop-in swap: `x_bus`/`w_bus` are currently
exposed to `neuron_parallel` as one fully-parallel N_INPUTS-wide
combinational bus (built by unrolling every `x_mem`/`w_mem`
element every cycle); block RAM has a registered, address-in/
data-out-next-cycle read port, so `neuron_parallel`'s group
processing would need to become RAM-latency-aware instead of
assuming the whole bus is already valid. Real potential upside,
real design effort — needs a go-ahead, not something to do
opportunistically.
- A pipeline register between MAC accumulation and the
activation/saturate stage (this session's original guess) does
**not** target the actual Phase 5 bottleneck — that finding was
Phase 4's critical path (the saturation comparator), and the path
moved once Phase 5's logic was wired in (see above). Keeping this
noted for Phase 4-only builds; not a fix for the current problem.
## Phase 8 — Optional Hardware Training