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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user