docs: consolidate N=16 to N=8's own level of rigor (EXP-0098) -- whole family real and closed

N=2 re-verified with the same shared pipelined neural_processor_packed.v
(EXP-0097's fix): real functional xsim 8/8 PASS (identical completion
time to the pre-fix baseline), real full P&R WNS=+0.389ns (up from
+0.099962ns), 0 failing endpoints, 16 DSP48E1 -- no regression.

Real, consolidated family state, all sharing the same pipelined core:
  N=2:  WNS=+0.389ns, 16 DSP48E1,  8/8 functional PASS
  N=8:  WNS=+0.108ns, 64 DSP48E1,  16/16 functional PASS
  N=16: WNS=+0.269ns, 128 DSP48E1, 32/32 functional PASS

Updated the project's own primary real docs (docs/PHYSICAL_REALIZATION.md
S3, docs/ARCHITECTURE_ANALYSIS.md S5.6) to the same depth EXP-0096 gave
N=8 alone -- not just the docs/latex/ deliverables. Clear two-track
framing throughout: the physically fabricated board still uses N=8's
original, unmodified core (WNS=0.000ns exact); this consolidated,
improved family lives on the isolated n16-timing-closure branch,
pending a real hardware decision on whether/when to adopt it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
2026-09-22 01:15:15 +02:00
co-authored by Claude Sonnet 5
parent cc6cfe168e
commit 0303aacb9f
3 changed files with 198 additions and 57 deletions
+84 -20
View File
@@ -1,15 +1,16 @@
# FPGA-Neural V3 — Architecture Analysis: Timing, Bottlenecks, and Recommended Interventions
Scope: the current, real, P&R-verified V3 design (`hardware/v3/`, branch
`v3-artix7`), updated through EXP-0095/0096 (N=8 hybrid systolic, real,
closed timing — the current, definitive real deployment target, chosen
by the user after a real, measured N=4/8/16 timing curve). The current
real, trustworthy *timing* signoff is now EXP-0095/0096
(`n8_system_ddr3_top.v`, 32-bit DDR3, 155.039MHz, WNS 0.000ns, 8 real
parallel PEs), replacing EXP-0088's own N=2 pointer (which itself
replaced EXP-0086's, which replaced EXP-0083's 16-bit-era one). See §5.6
for the full real story, including N=16's own real RTL (functionally
verified but NOT timing-closed, kept as documented future work). Every
`v3-artix7` for the physically-fabricated board; branch
`n16-timing-closure` for the real, consolidated follow-up below),
updated through EXP-0097/0098 (a real MAC-pipeline fix that closes
timing for the WHOLE real family — N=2/N=8/N=16 — not just N=8). The
board **currently in physical fabrication** uses N=8's own original,
unmodified EXP-0095/0096 signoff (`n8_system_ddr3_top.v`, 32-bit DDR3,
155.039MHz, WNS=0.000ns exact, 8 real parallel PEs). Separately, on an
isolated real branch, EXP-0097/0098 found that one shared-core fix
closes N=16 too (WNS=+0.269ns) and improves N=2 (+0.389ns) and N=8
(+0.108ns) as well — see §5.6 for the full real story. Every
number in this document is either
directly measured (real simulation trace, real P&R report) or a calculation
built from directly-measured building blocks — the two are labeled
@@ -664,7 +665,7 @@ specifically to document where/how it breaks rather than to succeed):
---
### 5.6 [N=8 IS THE REAL, DEFINITIVE DEPLOYMENT TARGET — `n8_system_ddr3_top.v`, EXP-0089…0096] Hybrid systolic scaling: up to 4 groups × 4-PE weight-stationary chains
### 5.6 [WHOLE FAMILY CLOSED — N=2/N=8/N=16, EXP-0089…0098] Hybrid systolic scaling: up to 4 groups × 4-PE weight-stationary chains
Captured from a 2026-09-20 brainstorming session as a purely exploratory
idea; the same day, per the user's own explicit reprioritization, the real
@@ -857,16 +858,79 @@ lanes exercised exactly once): **real functional xsim, 16/16 PASS, 0
errors** — closes the real, disclosed functional-verification gap
this section previously flagged for N=8 specifically.
**Current real status: N=8 (`n8_system_ddr3_top.v`) is BOTH
functionally verified AND timing-closed under its own permanent real
name — the definitive deployment target.** N=2 (`n2_system_ddr3_top.v`,
EXP-0088) remains documented as a real, valid, simpler fallback. N=16
(`n16_system_ddr3_top.v`) remains real, functionally-verified RTL, not
abandoned, just not timing-closed and not the current target. Real,
disclosed caveat carried forward: N=8's WNS=0.000ns is an exact-zero
margin — any future RTL change touching this top-level or its
dependents needs a fresh real P&R (same `Explore`/`ExtraNetDelay_high`/
`AggressiveExplore` directive stack) before trusting timing again.
**Current real status (physical board): N=8 (`n8_system_ddr3_top.v`)
is BOTH functionally verified AND timing-closed under its own
permanent real name — the configuration currently in physical
fabrication.** N=2 (`n2_system_ddr3_top.v`, EXP-0088) remains
documented as a real, valid, simpler fallback. Real, disclosed caveat:
N=8's original WNS=0.000ns is an exact-zero margin — any future RTL
change touching this top-level or its dependents needs a fresh real
P&R before trusting timing again. **This exact-zero margin is what
motivated EXP-0097/0098 below.**
#### 5.6.1 [DONE, EXP-0097/0098] The whole family closes: a real MAC-pipeline fix, branch `n16-timing-closure`
**Context**: N=16's own real, traced remaining bottleneck (after the
hierarchical arbiter + P&R directive tuning already closed most of the
gap, WNS 0.913ns → 0.338ns, EXP-0094) was inside `neural_processor_
packed.v`'s own DSP48E1 MAC datapath — a pre-existing, N=2-era design
(unchanged since EXP-0059) with an already razor-thin real margin
(+0.099962ns) that N=16's own higher real die congestion eroded past
zero, and that N=8's own real signoff (§5.6, EXP-0095/0096) closed at
an exact zero with no slack to spare.
**Real root cause** (traced to the exact register-to-register hop, not
guessed): the critical path ran from a DSP48E1's own (Vivado-auto-
retimed) product register, straight through the real carry-heavy
INT8-unpack logic (`pb_comb`'s own shift + conditional +1
carry-propagate add, CARRY4-dominated), into `proda1`/`prodb1` in a
SINGLE real cycle.
**Real fix**: split the original single pipeline stage into two real
stages — Stage 1a registers the RAW DSP48E1 product with zero logic in
between (a real, explicit register boundary immediately after the
multiply); Stage 1b does the carry-heavy unpack FROM the already-
registered value (unchanged real math, now one real cycle later). Real,
deliberate consequence: end-to-end per-tile latency grows by exactly
ONE real clock cycle; throughput is unaffected (real valid/ready
handshaking throughout, no fixed-latency assumption anywhere
downstream).
**Real bug found and fixed in the testbench first** (not an RTL bug):
`tb_neural_processor_packed.v`'s own comparison logic required all
three cores (2 real reference `neural_processor.v` instances + the
DUT) to assert `result_valid` simultaneously — correct only when all
three share the exact same real pipeline depth, no longer true once
the DUT is deliberately one real cycle deeper. Fixed by latching each
core's own result independently the cycle its own `result_valid`
first pulses, then comparing the three LATCHED values.
**Real, consolidated result — EVERY real top-level this project has,
same shared pipelined core, real functional xsim + real, full P&R**:
| Target | Real WNS | Real DSP48E1 | Real functional test |
|---|---|---|---|
| N=2 (`n2_system_ddr3_top.v`) | +0.389ns (up from +0.099962ns) | 16 (6.67%) | 8/8 PASS |
| N=8 (`n8_system_ddr3_top.v`) | +0.108ns (up from 0.000ns exact) | 64 (26.7%) | 16/16 PASS |
| N=16 (`n16_system_ddr3_top.v`) | **+0.269ns** (up from 0.338ns FAILED) | 128 (53.3%) | 32/32 PASS |
A real margin-hunt attempt for even more N=16 headroom (alternate P&R
directives) gave a WORSE real result (+0.168ns vs. the original
+0.269ns) — confirms real P&R run-to-run variance, not a further
systematic gain available without touching more RTL (the new N=16
worst path, after this fix, moved to `neural_director_grouped.v`'s own
queue update logic, still real route-dominated — not pursued further,
current margin already comfortable).
**Decision**: this fix is a pure, unconditional real improvement
across the whole real family — no regression anywhere, real margin
improves at every N, N=16 goes from real FAILING to real CLOSED. It is
**not yet applied to the physically fabricated board** (which uses the
original, unmodified N=8 core) — adopting it (and/or moving to N=16)
for a future board revision is a real, open hardware decision, not an
RTL blocker. A real Vivado incremental-synthesis quirk was also found
and fixed along the way (a parameter binding silently carried forward
from an earlier `-generic` run despite `reset_run` — see CLAUDE.md).
**The problem it targets**: plain N=16 independent cores (§5.5's own
"documentary, expected to break" framing) means 16 independent DDR3
+65 -37
View File
@@ -165,25 +165,39 @@ these from an ESP32 doing real JTAG bit-banging (TAP state machine, IR/DR
shifting) rather than a bench programmer — that firmware is separate,
software-side work, not covered here.
## 3. Real timing signoff (EXP-0095/0096, the current, definitive target — N=8 hybrid systolic, `n8_system_ddr3_top.v`, CLOSED)
## 3. Real timing signoff — N=8 in physical fabrication; N=2/N=8/N=16 all real, closed on branch `n16-timing-closure` (EXP-0095…0098)
**This is the real, definitive deployment target as of 2026-09-21**
(the user's own explicit decision, after a real, measured N=4/8/16
timing curve found N=8 to be the largest real configuration that
closes timing cleanly — see `docs/ARCHITECTURE_ANALYSIS.md` §5.6 for
the full real story). Top-level RTL: `hardware/v3/rtl/
n8_system_ddr3_top.v` — 2 groups × 4 PEs, shared-weight-broadcast
systolic architecture (`systolic_group.v`/`packed_pe.v`,
`neural_director_grouped.v`, `sdram_arbiter_hier.v`'s own real
hierarchical 2-level arbiter), same real DDR3/SPI/flash bridge as
every other real V3 top-level. Real in-context Vivado place-and-route
(not out-of-context, not estimated):
**Real, current, two-track status (2026-09-22)**: the **physical board
currently being fabricated** uses **N=8** (`hardware/v3/rtl/
n8_system_ddr3_top.v`, unmodified, EXP-0095/0096 signoff below) — this
was the real, definitive decision made on 2026-09-21 after a real,
measured N=4/8/16 timing curve found N=8 the largest configuration
that closed cleanly at the time. Separately, on an isolated real
development branch (`n16-timing-closure`, does NOT affect the board
already in fabrication), a real fix (EXP-0097 — an extra real pipeline
stage in `neural_processor_packed.v`'s own MAC datapath, see
`docs/ARCHITECTURE_ANALYSIS.md` §5.6) has since **closed real timing
for N=16 too, and improved N=2's and N=8's own margins** — the whole
real product family (N=2/N=8/N=16) now closes with positive margin
under that fix. Whether/when to adopt this fix for a future board
revision (potentially N=16) is a real, open hardware decision, not an
RTL blocker — see `docs/ARCHITECTURE_ANALYSIS.md` §5.6 for the full
story.
### 3.0 N=8, in physical fabrication (`n8_system_ddr3_top.v`, EXP-0095/0096, unmodified core)
Top-level RTL: `hardware/v3/rtl/n8_system_ddr3_top.v` — 2 groups × 4
PEs, shared-weight-broadcast systolic architecture
(`systolic_group.v`/`packed_pe.v`, `neural_director_grouped.v`,
`sdram_arbiter_hier.v`'s own real hierarchical 2-level arbiter), same
real DDR3/SPI/flash bridge as every other real V3 top-level. Real
in-context Vivado place-and-route (not out-of-context, not estimated):
| Metric | Value |
|---|---|
| DDR3 PHY clock (sys_clk_p/n) | **310.078 MHz** (3.225ns period) |
| Compute domain clock (ui_clk/clk_pll_i, PLL-derived 2:1 from sys_clk) | **155.039 MHz** |
| WNS (setup slack) | **0.000 ns** — real, closed, 0 failing setup endpoints (EXP-0095/0096). Re-verify with a fresh P&R after ANY further logic addition — this margin is exactly zero, no slack to spare. |
| WNS (setup slack) | **0.000 ns** — real, closed, 0 failing setup endpoints (EXP-0095/0096). This is the exact RTL physically being fabricated. |
| WHS (hold slack) | +0.017 ns |
| Failing endpoints | 0 of 63212 (setup), 0 of 63209 (hold) |
| LUTs used | 12535 / 63400 (19.77%) |
@@ -200,20 +214,31 @@ real, closed, but with zero slack. Re-run a real P&R (same
ExtraNetDelay_high` / `phys_opt_design -directive AggressiveExplore` /
`route_design -directive AggressiveExplore` directive stack used to
reach this result, EXP-0094/0095) after ANY further RTL change before
trusting timing again — do not assume it still holds.
trusting timing again — do not assume it still holds. This zero-margin
result is exactly why EXP-0097's own pipeline fix (below) was pursued.
**Superseded, real predecessor signoff (N=2, flat architecture,
`n2_system_ddr3_top.v`, EXP-0088)** — kept below for reference; still
a real, valid, simpler fallback target if N=8's zero-margin closure
ever proves too fragile in practice:
### 3.0.1 The real, consolidated family — EXP-0097/0098, branch `n16-timing-closure` (not yet on the fabricated board)
| Metric | Value |
|---|---|
| WNS (setup slack) | +0.099962 ns |
| WHS (hold slack) | +0.036275 ns |
| LUTs used | 6642 / 63400 (10.48%) |
| DSP48E1 used | 16 / 240 (6.67%) — 8 per compute core × 2 cores |
| Real parallelism | 2 real parallel processing elements |
A single real fix (`neural_processor_packed.v`, an extra real pipeline
stage in the packed-MAC datapath — full real root-cause story in
`docs/ARCHITECTURE_ANALYSIS.md` §5.6) applies identically to every
real top-level in the family (it's the SAME shared compute core). Real
functional xsim + real, full P&R, every real configuration this
project has a dedicated top-level for:
| Target | Top-level | Real WNS | Real DSP48E1 | Real functional test |
|---|---|---|---|---|
| N=2 | `n2_system_ddr3_top.v` | **+0.389 ns** (up from +0.100ns) | 16/240 (6.67%) | 8/8 PASS |
| N=8 | `n8_system_ddr3_top.v` | **+0.108 ns** (up from 0.000ns exact) | 64/240 (26.7%) | 16/16 PASS |
| N=16 | `n16_system_ddr3_top.v` | **+0.269 ns** (up from 0.338ns FAILED) | 128/240 (53.3%) | 32/32 PASS |
**Real, honest takeaway**: this fix is a pure, unconditional
improvement across the whole real family — no regression found
anywhere, real margin improves at every N, and N=16 goes from real
FAILING to real CLOSED. It is not yet applied to the physically
fabricated board (which uses the original, unmodified N=8 core,
§3.0) — that board's own real signoff (WNS=0.000ns) remains accurate
for the hardware actually being built.
Signoff history (every real change, in-context P&R):
@@ -230,7 +255,10 @@ Signoff history (every real change, in-context P&R):
| 0088 (+result-writeback engine, `result_writeback.v`) | N=2 | +0.100 (CLOSED) | 6642 | 16 |
| 0093 (hybrid systolic, flat 21-way arbiter) | N=16 | -0.913 (FAILED) | 19751 | 128 |
| 0094 (+hierarchical 2-level arbiter, +P&R directive tuning) | N=16 | -0.338 (still FAILED) | 19936 | 128 |
| 0095/0096 (`n8_system_ddr3_top.v`, hybrid systolic) | **N=8** | **0.000 (CLOSED)** | 12535 | 64 |
| 0095/0096 (`n8_system_ddr3_top.v`, hybrid systolic**in physical fabrication**) | **N=8** | **0.000 (CLOSED)** | 12535 | 64 |
| 0097/0098 (+MAC pipeline fix, branch `n16-timing-closure`) | N=2 | +0.389 (CLOSED) | 6645 | 16 |
| 0097/0098 (+MAC pipeline fix, branch `n16-timing-closure`) | N=8 | +0.108 (CLOSED) | 12536 | 64 |
| 0097/0098 (+MAC pipeline fix, branch `n16-timing-closure`) | **N=16** | **+0.269 (CLOSED)** | 19903 | 128 |
### 3.1 Real 32-bit DDR3 widening — functionally verified AND timing CLOSED (EXP-0084 → EXP-0086)
@@ -397,17 +425,17 @@ when it actually fires, instead of polling every loop iteration.
## 7. Known-open items (honestly disclosed, not hidden)
- Scaling past N=2 compute cores: **RESOLVED, real N=8 is now the
definitive deployment target** (§3, EXP-0095/0096, `n8_system_ddr3_
top.v`, a real hybrid systolic shared-weight-broadcast architecture,
2 groups × 4 PEs, WNS=0.000ns CLOSED). Real N=4/8/16 P&R curve
measured: N=4 0.005ns (2 failing endpoints, essentially at the
edge), N=8 **0.000ns (CLOSED)**, N=16 0.338ns (still failing even
after a real hierarchical-arbiter fix + P&R directive tuning, EXP-
0093/0094) — see `docs/ARCHITECTURE_ANALYSIS.md` §5.6 for the full
real story. N=16 remains real, functionally verified RTL
(`n16_system_ddr3_top.v`), just not yet timing-closed; not the
current real deployment target.
- Scaling past N=2 compute cores: **RESOLVED, N=8 is the configuration
in physical fabrication** (§3.0, EXP-0095/0096, `n8_system_ddr3_
top.v`, WNS=0.000ns CLOSED). **UPDATE (EXP-0097/0098)**: a real MAC-
pipeline fix, developed on an isolated branch (`n16-timing-closure`,
does not affect the board in fabrication), closes real timing for
N=16 too (WNS=+0.269ns) and improves N=2's and N=8's own margins
(+0.389ns, +0.108ns respectively) — see §3.0.1 and
`docs/ARCHITECTURE_ANALYSIS.md` §5.6 for the full real story. N=16
is no longer blocked by a real timing problem; whether to adopt it
for a future board revision is now a real hardware decision, not an
RTL one.
- `sys_rst` has only a *tentative* real pin (G13, bank 15, EXP-0084 —
chosen just to unblock real P&R, not a final board decision) — assign
its real, permanent location once the rest of the board layout (reset
+49
View File
@@ -6962,3 +6962,52 @@ N=8 design, unaffected), and/or (2) actually build the NEXT physical
board as N=16 instead of N=8, given N=16 is now real, functionally
verified, AND timing-closed with a real, comfortable margin -- a real,
consequential hardware decision, not an RTL one.
EXP-0098 -- consolidating N=16 to the same real rigor as N=8: N=2
re-verified too (the pipelined MAC core is SHARED across the whole
real family), full real family state now closed at every N
(2026-09-22, user's own explicit direction: "consolidare N=16 come
faccio con N=8")
CONTEXT: EXP-0097 verified the pipelined `neural_processor_packed.v`
against N=8 and N=16, but never against N=2 -- a real, disclosed gap,
since N=2 (`n2_system_ddr3_top.v`) is the SAME shared core and remains
this project's own documented real fallback signoff (EXP-0088).
Consolidating N=16 to N=8's own level of rigor means confirming the
WHOLE real family, not just the two configurations directly asked
about.
REAL RESULT: functional xsim (`tb_n2_system_ddr3.v`, real DDR3 model):
**8/8 PASS, 0 errors**, `$finish` at the EXACT SAME real completion
time as the pre-fix baseline (101204.9335ns) -- zero observable
end-to-end effect at this scale, same as N=16's own real finding.
Real, full P&R (`n2_system_ddr3_top.v`, real XC7A100T-CSG324-2, same
directive stack): **WNS=+0.389ns (up from the original real
+0.099962ns), WHS=+0.017ns, 0 failing endpoints, 16 DSP48E1 (6.67%),
6645 LUTs (10.48%)** -- a real, substantial margin improvement, no
regression.
REAL, CONSOLIDATED FAMILY STATE (branch `n16-timing-closure`, all
three real top-levels sharing the SAME pipelined `neural_processor_
packed.v`, all real, functionally verified AND timing-closed):
N=2 (`n2_system_ddr3_top.v`): WNS=+0.389ns, 16 DSP48E1, 8/8 functional PASS
N=8 (`n8_system_ddr3_top.v`): WNS=+0.108ns, 64 DSP48E1, 16/16 functional PASS
N=16 (`n16_system_ddr3_top.v`): WNS=+0.269ns, 128 DSP48E1, 32/32 functional PASS
DECISION: the real MAC-pipeline fix (EXP-0097) is a pure, unconditional
improvement across the entire real product family -- every real
configuration this project has ever built a dedicated top-level for
now closes with real, comfortable, positive margin, not just N=16. No
real regression found anywhere. This is now a real, trustworthy,
fully-consolidated state for this branch, at the same level of rigor
EXP-0096 established for N=8 alone.
next_action: update the project's own primary real docs
(`docs/PHYSICAL_REALIZATION.md` §3, `docs/ARCHITECTURE_ANALYSIS.md`
§5.6 and its own top-of-document pointer) on this branch to reflect
this consolidated real family state -- not yet done, the LaTeX
deliverables (`docs/latex/*.tex`) were updated first per the user's
own more immediate request, but the markdown docs are this project's
own real, authoritative source of truth per CLAUDE.md's own "Read
first" section and deserve the same update.