3416b8d3cfd909a226ab5b2c29a38dc73ffffe9e
86
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3416b8d3cf |
exp: fix pulse-race hang in tb_layer_reuse_vs_zero_reuse.v (EXP-0058 follow-up); real remaining bug still open, 7.16x NOT yet re-verified
Same class of testbench-vs-DUT scheduling race documented in EXP-0058 (tb_layer_prefetch_ctrl.v, tb_neural_processor_layer_reuse.v) was also present here on ctrl_req/fill_done/consume_done: clearing a one-cycle pulse on the very next @(posedge clk) let the clear land in the same active-region pass as the edge the DUT needed to sample it at, so the pulse could be silently missed. Confirmed via direct state tracing: sdram_controller_openrow.v sat in S_IDLE with busy=0 forever after the first burst, never latching req_pending for the second -- this is why the file hung indefinitely rather than completing. Fixed with the same #1-before-clear hardening as the other files. Honesty note: fixing this hang exposed a SECOND, still-unfixed bug in prefetch_layer's own fill_addr sequencing (real data-correctness failures once the run actually completes, not just a hang) -- so EXP-0057's own headline "7.16x real measured speedup" number is NOT re-verified by this commit and should not be treated as confirmed. Not pursued further -- see decisions.log for why (project paused). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC |
||
|
|
80c89fa10d |
exp: real end-to-end weight-reuse integration with neural_processor.v (EXP-0058)
New tb_neural_processor_layer_reuse.v wires the real SDRAM controller, layer_prefetch_ctrl.v and layer_weight_buffer.v into a real neural_processor.v compute engine: one resident filter is fetched once and reused across 8 independent jobs per layer, verified bit-exact against an independent golden dot-product model (32/32 PASS). Also found and fixed a real testbench-vs-DUT scheduling race present in tb_layer_prefetch_ctrl.v (and hardened in the new file): clearing a one-cycle control pulse on the very next clock edge lands the clear in the same active-region pass as the edge a receiving module's own synchronous logic reads it at, so the pulse can be silently missed depending on implementation-defined process ordering. This had been silently preventing tb_layer_prefetch_ctrl.v's own claimed 8192/8192 result from ever actually being observed; fixed by holding the pulse past the edge with a real time delay before clearing, and the 8192/8192 result is now genuinely reproducible (5/5 consecutive runs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC |
||
|
|
ca94083366 |
prod: promote EXP-0056 fixes into production RTL (dependency_manager.v, nms_activation_fill_ctrl_v3.v)
Per explicit instruction: when a bug/fix found in an experimental fork
also applies to the production file it was forked from, apply it
there too, not just in the fork.
dependency_manager.v: swaps in priority_encoder_lsb.v for the
first_ready_idx scan (was: serial O(N_NODES) for-loop). Bit-exact
equivalent, correctness-neutral by construction.
nms_activation_fill_ctrl_v3.v: adds the missing N_SLOTS==16 balanced
max-tree case (was: silently falling back to the slow flat scan for
any N_SLOTS not in {1,2,4,8}) -- this was the real cause of N_SLOTS=16
failing timing closure (23-24MHz vs 64MHz target), fixed to 71.01MHz
PASS in the experimental fork.
Verified on the REAL, unmodified production top (fpga_neural_v2_top.v,
N_SLOTS=4 default): tb_dependency_manager.v 4/4 PASS, board smoke test
11/11 PASS, D-Stress N=4 total_cycles=49927 (bit-exact, IDENTICAL to
the pre-fix baseline -- zero functional regression, as expected from a
pure combinational-depth change). Real nextpnr-ecp5 P&R (LFE5U-45F,
seed 1): 97.36MHz, PASS at 64MHz -- BETTER margin than the pre-fix
baseline's own 76.80-88.25MHz seed range, not just neutral.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
|
||
|
|
49b25f6eb6 |
exp: layer_prefetch_ctrl.v, real synthesizable RTL for layer-weight-reuse prefetch, fixes a real address-truncation bug (EXP-0057b)
Built the real FSM version of EXP-0057's own task-based prefetch pattern (bulk-sequential layer fetch via sdram_controller_openrow.v into layer_weight_buffer.v), so it's an actual instantiable module, not just a simulation convenience. Found and fixed a real bug in the process: cur_fill_addr's own address arithmetic bit-sliced BYTES_PER_BURST down to too few bits (BYTES_PER_BURST[BIDXW-1:0]), silently truncating 16 to 0 -- every burst's bytes landed at fill offset 0-15 instead of their real position, overwriting each other (only each layer's last burst survived). Root cause: misapplied a widening idiom used safely elsewhere in this codebase to a case where the target width was actually too small. Found via a standalone control-flow debug test first, then tracing data once control-flow was cleared. Verified: 8192/8192 bit-exact, 0 errors (was 512/8192 before the fix) through the real controller + SDRAM model, 16 layers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC |
||
|
|
1ce78dff6e |
exp: N=16 timing closure fixed (EXP-0056), weight-reuse gives real 7.16x memory speedup without DDR3 (EXP-0057)
EXP-0056: N_SLOTS=16 failed timing on LFE5U-85F (23-24MHz vs 64MHz
target). First hypothesis (dependency_manager.v's serial ready-scan)
was wrong but real -- built and verified priority_encoder_lsb.v (a
generic recursive tree encoder) and dependency_manager_fast.v, bit-
exact equivalent to the original, but integrated it made no real
difference (24.26MHz). The real cause, found from nextpnr's own
critical-path report: nms_activation_fill_ctrl_v3.v's balanced max-
tree was only ever extended to N_SLOTS in {1,2,4,8}, silently falling
back to the original slow scan for 16. Added the missing case
(nms_activation_fill_ctrl_v3_n16.v), verified isolated (10017/10017)
and functionally (D-Stress N=16 still 256/256 bit-exact). Real result:
71.01MHz, PASS at 64MHz (single seed so far).
EXP-0057: built layer_weight_buffer.v, a double-buffered per-layer
weight scratchpad (fill one buffer in the background from SDRAM while
compute reads many times from the other -- weight-stationary reuse,
as opposed to D-Stress's own deliberately zero-reuse pattern). Wired
to the real sdram_controller_openrow.v + sdram_model.v, no new
hardware. For the same 32768 bytes of useful data: zero-reuse costs
27048 real cycles, reuse costs 3777 -- 7.16x real measured speedup on
the SAME SDR SDRAM, no DDR3, no clock change. This is the answer to
whether DDR3 is necessary for a workload class that actually has
reuse (e.g. conv-style face recognition, unlike D-Stress) -- it isn't,
at least not for this reason.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
|
||
|
|
fce8ff2d66 |
exp: fork real board top (fpga_neural_v2_top_openrow.v) with open-row SDRAM backend, verified functionally identical
SPI+board-level smoke test: 11/11 PASS, matching the unmodified production top exactly. 8-seed nextpnr-ecp5 P&R sweep (N=4, real v2_board_top.lpf pins, 64MHz target): 8/8 PASS on both, open-row variant has BETTER margin than baseline (worst 83.34 vs 76.80 MHz, mean 90.40 vs 82.53 MHz) -- not just no regression, a real improvement. Not yet promoted over the production fpga_neural_v2_top.v (that swap is still pending an explicit go-ahead); this commit only adds the verified fork + its own smoke test, additive only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC |
||
|
|
ee5a68f6e6 |
exp: SDRAM CDC bridge + open-row policy (EXP-0053/54/55) -- open-row is a real ~5% D-Stress win, CDC bridge measured net-negative once integrated
EXP-0053: sdram_cdc_bridge.v decouples the SDRAM clock (115.2MHz, real value derived from the board's own existing PLL VCO=576MHz, verified via ecppll) from the 64MHz compute domain. Isolated: 137/137 tests, 0 errors, but real measured speedup is only 1.095x (not the naive 1.8x clock-ratio estimate) -- the CDC handshake's own synchronizer round-trip is a fixed per-transaction tax. EXP-0054: sdram_controller_openrow.v implements the page-hit/ keep-row-open optimization sdram_controller.v's own header had always deferred. weight_prefetch_engine_wide.v's real production traffic is strictly sequential per job and mostly stays within one SDRAM row -- closing/reopening it every tile (today's fixed auto-precharge policy) wastes tRP+tRCD for no reason. Isolated: 154/154 tests, 0 errors, 0 protocol violations (including the new refresh-while-row-open hazard, fixed via an explicit precharge-before-refresh path). Real measured speedup on the actual sequential access pattern: 1.141x. EXP-0055: composed both, then integrated into the real D-Stress benchmark (N=4/N=8, 256/256 bit-exact in every config). Result: open-row ALONE gives a real, consistent ~5% cycle-count improvement (47445/47468 vs baseline 49927/49909). CDC alone is a real ~8% REGRESSION. Combined is still a ~4% regression -- the CDC's fixed tax is paid on every transaction regardless of row-hit, and real D-Stress traffic interleaves weight-fetch/activation-result access far more than the isolated same-row test exercised, so open-row's real saving doesn't offset it. Decision: do not adopt the CDC approach; open-row alone is the disclosed, real win worth considering for production next, pending an explicit go-ahead (not applied to the real board top in this commit -- all additive, existing production RTL untouched). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC |
||
|
|
03b5cbc25b |
exp: bank-interleaved SDRAM pipelining works in isolation, ~0.3% gain integrated (EXP-0052)
Follow-up to EXP-0051: built sdram_controller_pipelined.v, remapping addr->bank to low-order bits (today's weight region always maps to bank 0) and adding a shadow-slot ACTIVATE lookahead so a different-bank request can start its tRCD wait during the current transaction's tail. Phase A (isolated tb_sdram_controller_pipelined.v, 38/38 bit-exact, independently re-verified this session): mechanism works, saves exactly 2 cycles (tRCD) per different-bank back-to-back pair, matching the theoretical ceiling derived before measuring (CAS_LATENCY+BURST_LEN are serial on the shared data bus regardless of bank, so more than tRCD/tRP was never on the table). Phase B (integration, tb_nms_dstress_sdram_pipelined.v, independently rebuilt/rerun): N=4 49760 cycles (-0.33% vs baseline), N=8 49755 (-0.31%) -- both 256/256 bit-exact. Root cause of the gap: the W port's request/ready protocol is one-at-a-time, so a second, different-bank request is essentially never already pending while the first is still in flight, so the mechanism rarely triggers in the real system even though it's correct when directly stimulated. Not integrated into production; kept as additive reference for a possible future arbiter/backend pipelined-dispatch rewrite (out of scope here, larger and riskier). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHENedK76onD2Vtc2CMjej |
||
|
|
cc5db09f61 |
exp: dual-bank SDRAM sim shows W/AR split gives only ~9% cycle gain, not thrashing removal (EXP-0051)
Forked nms_neural_multiprocessor_sdram_unified.v + its D-Stress testbench into a dual-bank variant (two independent sdram_unified_backend.v instances, one for weight-fetch, one for activation+result) to test the Fase-3 memory-bound hypothesis ahead of Phase 2. Simulation-only: the real board (v2_board_top.lpf) still wires exactly one physical chip, per STEP19's governing single-SDRAM mandate. Result is honest but not the hoped-for one: splitting by traffic class only cuts D-Stress cycles ~8-10% (N=4: 49927->45724, N=8: 49909->44980), because the AR (activation+result) path was already lightly loaded (~12% busy) even alone. The real ceiling is the weight-fetch channel itself, which stays ~77-78% busy even with its own dedicated bank and zero cross-traffic. Full writeup in experiments.log EXP-0051, including the refined next-step options this suggests instead of a straight 2-bank board revision. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHENedK76onD2Vtc2CMjej |
||
|
|
19ef54aea8 |
docs+synth: Phase 0 complete - N=8 baseline + toolchain discrepancy closed
N=8 baseline (EXP-0050, real fpga_neural_v2_top + v2_board_top.lpf, fresh 8-seed sweep): 8/8 PASS at 64MHz, worst 80.97MHz, mean 84.62MHz. DSP 64/72 (88.9%) confirms real N_SLOTS=8. This directly contradicts the brief's own premise (N8 expected to collapse to ~31MHz) and the project's historical numbers (3-5/8 pass, worst ~55-67MHz) despite bit-identical RTL. Investigated and closed the same discrepancy already flagged for N=4: logs/experiments.log:2563 explicitly tags historical Fmax numbers as measured on "Yosys 0.68+"; this session's toolchain is Yosys 0.69+59, a nightly dated the same day as the session -- a confirmed ~59-commit version gap. Critical-path inspection on both N=4 and N=8 confirms the underlying RTL congestion the project diagnosed is real and still present (same bottleneck locations as previously documented) -- the newer toolchain just places it well enough to still clear 64MHz. Decision: this session's numbers are adopted as the operative baseline for Phase 1+ (see timing.log for the full writeup). Also found, not yet applied: slot_mem_arbiter.v/slot_mem_arbiter_wide.v both still have the runtime-indexed-crossbar anti-pattern already fixed in neural_director.v, sitting right on the arbiter<->backend boundary the brief names -- a concrete Phase 1 candidate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
685a4d6cfe |
docs+synth: Phase 0 baseline (N_SLOTS=4, real board top), fix stale LPF freq
New brief (N=8 timing closure, LFE5U-85F retarget, 4/8/16 x 1/2-bank SDRAM sweep). Phase 0: no RTL changes, only measure the current baseline. ERR-0030: constraints/v2_unified.lpf's FREQUENCY PORT "clk" was still 80MHz, a leftover from the STEP19 freeze, never updated to the project's real 64MHz target -- fixed (LPF only, zero RTL/datapath effect). ERR-0031 (bigger one): the first two synthesis attempts targeted nms_neural_multiprocessor_sdram_unified.v, which is NOT the real board-level top -- it's an obsolete wrapper only exercised by one testbench now. The real target is fpga_neural_v2_top.v (adds the real PLL, reset_sync, spi_host_bridge, and a second arbitration level), which is what actually goes through synthesis+P&R for hardware. Re-targeted correctly, matched against constraints/v2_board_top.lpf (all 17 ports real-ball-assigned). An N_SLOTS=8 P&R attempt against the WRONG (wrapper) target ran for 2h42m without converging on a single seed; discarded rather than trusted. N_SLOTS=8 baseline deferred by explicit user request until N_SLOTS=4 is fully understood -- re-attempt against the correct fpga_neural_v2_top target with an agreed time budget. Result (EXP-0049, fresh 8-seed nextpnr-ecp5 P&R, real pins): N_SLOTS=4 8/8 PASS at 64MHz, worst-seed 81.20MHz, mean 91.05MHz. Higher than DEC-0042's historical worst/best (64.55/77.21MHz) despite identical RTL -- disclosed, unresolved (leading hypothesis: nextpnr-ecp5 build/version difference), adopted as the operative baseline for this session's toolchain going forward. Full writeup in errors.log/timing.log/ experiments.log (EXP-0049). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
8b8ca239ca |
docs: consolidate all V2 datasheets into one current, complete document
The repository had accumulated multiple, contradictory "current state" documents for V2 hardware: an old V1 IT/EN datasheet copy nested inside hardware/v2/docs/datasheet/, a stray untracked duplicate at repo root (docs/DatasheetLatex/), and a second, much older documentation track (hardware/v2/docs/*.md: PRE_PCB_VERIFICATION.md, PRE_PCB_CLOSURE_4POINT.md, MEMORY_UPGRADE_64MB_N8.md, and 10 more) describing an earlier PSRAM/ N_SLOTS<=2 milestone alongside the real, current SDRAM/N_SLOTS=4 board. The LaTeX datasheet's own front matter (features/pinout cover pages) and chapter 9 (benchmarks) were themselves still describing that obsolete architecture, contradicting the real, current chapters 5/7/10 elsewhere in the same document. This commit: - Flattens hardware/v2/docs/datasheet/files/docs/datasheet/v2-en/* up to hardware/v2/docs/datasheet/ (was 4 levels of redundant nesting). - Removes the old V1 IT/EN LaTeX copies and the stray root-level duplicate entirely (recoverable from git history, not from disk). - Preserves the real component reference PDFs (ECP5 eval board, ISSI PSRAM, programming cables) under datasheet/references/. - Removes 13 superseded hardware/v2/docs/*.md status documents after folding every real, unique fact they contained into the datasheet: SPI max verified clock (12MHz, exact 12.8MHz CDC edge), SDRAM directed boundary test (21/21 PASS), 16MHz oscillator MPN (ECS-3225MV-160-BN-TR), and the real FPGA<->SDRAM ball mapping cross-check. - Rewrites the datasheet's own front matter, ch.4 (parameters), ch.8 (top-level module -- was documenting the wrong, non-physical top entirely), and ch.9 (benchmarks) to describe the current, real SDRAM/ N_SLOTS=4 production board, while keeping the real PSRAM-era chapters as clearly-labeled history rather than deleting correctly-measured work. - Fixes a title-page tikzpicture that was clipped off the page edge (pre-existing, unrelated to this change) by scaling it to fit. Net: 85 files changed, -8814/+498 lines. hardware/v2/docs/ now contains exactly one current datasheet plus FIRST_POWER_ON.md (a bring-up runbook, not a duplicate spec). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
1efd63912f |
docs: polish V2 datasheet to professional third-person English
Removed session-log/conversational register leftover from the
interactive drafting process ("the user's own suggestion", "user
confirmed", "user-authored schematic", "user-requested optimizations",
etc.) and replaced with neutral, factual engineering-document
phrasing. No technical content changed -- attribution language only.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
|
||
|
|
d4792beed7 |
docs: embed real KiCad schematic export in V2 datasheet, verify BOM from source
Exported the schematic (kicad-cli sch export pdf) and BOM (kicad-cli sch export bom) directly from the real KiCad source instead of relying on pasted screenshots/CSVs, then updated ch.10 accordingly: - New "Real KiCad schematic capture" section embeds the two live sheets (FPGA, UnusedBank) as vector figures pulled straight from the project file, plus a note on the three sheet files not reachable from the root hierarchy. - Boot-flash net-name mismatch finding confirmed resolved: FPGA_SPI_* labels now match exactly on both the flash chip and the ECP5's dedicated MSPI pins. - FPGA grade fix (8BG381I -> 8BG381C) now verified directly in the source file's Value field, not just as a stated intent. Real package geometry added: 0.8mm pitch, 20x20 array, 17x17x1.76mm body. - New minor finding: U2's footprint library folder is still named ..._8BG381I even though the Value field is corrected -- not board-affecting (identical physical footprint across grades), but flagged for a future rename. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
7eb02ba4bd |
docs: resolve FPGA grade to commercial (8BG381C), correct temp range data
User confirmed LFE5U-45F-8BG381C (commercial) is the intended part, matching every other reference in this project. Also corrects this chapter's own earlier temperature figures: commercial grade is real TJ 0 to +85C, industrial is TJ -40 to +100C (an earlier draft of this section had the industrial range wrong at -40/+85C). Same "-8" speed grade in both -- the letter suffix only changes the characterized temperature range. KiCad library still needs the part number itself corrected from ...381I to ...381C. Compiled clean (47 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
22e226a087 |
docs: resolve the +1V1 label mystery and close remaining schematic open items
User confirmed TLV62568 (U1) outputs 1.1V, explaining the +1V1 label found near the VCCAUX ferrite (L2) during the schematic review: it belongs to U1's own real output net, merely nearby on the page layout, not routed through the ferrite. VCCAUX remains 2.5V as required by the real Lattice datasheet. All three schematic "open items" from the earlier review are now resolved: TLV62568 EN (R3=499k, confirmed via BOM), the +1V1 label (false alarm, explained above), and the JTAG pull-up array (confirmed 8 discrete 0402 parts via BOM, not a bussed package -- no polarity limitation). Only the boot-flash net-name typo (FGPA/FPGA + SCLK/CLK) remains as a real, open schematic fix, and the FPGA grade discrepancy (8BG381I vs 8BG381C) remains to be confirmed. Compiled clean (47 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
1e36853072 |
docs: clear CAS#/WE# false alarm, resolve TLV73325 EN wiring
User confirmed the real schematic has SDRAM CAS#=F7/WE#=F9 -- matches this chapter exactly. The earlier review's "appear swapped" finding was a misread of the schematic image, not a real error; moved from "real findings" to a cleared checked-item note. TLV73325's EN pin resolved: direct wire to +3.3V (VIN), always-enabled -- no soft-start timing requirement like TLV62568's own R3 pull-up (a plain LDO, no sequencing note in TI's own datasheet), and no dynamic enable/disable control exists elsewhere in this design. Remaining real, open finding: the boot-flash net-name mismatch (FGPA/FPGA typo + SCLK/CLK) still needs a schematic fix. Compiled clean (47 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
e2956d0377 |
docs: add real BOM, flag FPGA grade discrepancy (8BG381I vs 8BG381C)
Real KiCad-exported BOM added to the hardware chapter, cross-checked against every component value this chapter already specifies -- most match exactly (R1/R2 feedback divider, L1/L2, ferrite part number, all three real ICs). One real discrepancy found: U2 is captured as LFE5U-45F-8BG381I (industrial grade) while every other reference in this project uses the C (commercial) grade part -- flagged, not resolved, needs explicit confirmation. Also resolves three earlier open items from the schematic review: R3=499k confirms TLV62568's EN is populated; R5-R12 being 8 discrete 0402 resistors (not a multi-resistor array) confirms the JTAG pull-up/down polarity concern doesn't apply; U5 confirms the previously-missing 16MHz oscillator is now present. Compiled clean (47 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
4cbbe5a29d |
docs: real KiCad schematic review + reserved PCB module section
Adds a dated review section recording today's actual schematic check against every real ball assignment in this chapter: confirmed-correct items, two real findings needing correction (boot-flash net-name mismatch FGPA/FPGA typo + SCLK/CLK label mismatch that would leave the flash electrically disconnected from the ECP5's config engine; SDRAM CAS#/WE# appearing swapped vs. the verified F7/F9 assignment), and open items not resolvable from the schematic image alone (regulator EN pins, a stray +1V1 label near the VCCAUX ferrite, JTAG pull-up/down array polarity). Also reserves a "PCB module form factor" section (castellated-edge SMD module, ~50x25mm) for the future physical layout. Compiled clean (46 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
44be4a7d81 |
docs: reflect flash #1 removal and the N=4 8/8 timing recovery
Datasheet and pinouts.md updated to the current, real state after today's session: flash #1 was implemented then removed (user's own MHz-over-persistence priority call), the clock-closure table now shows the post-revert, post-DEC-0042 numbers (N_SLOTS=4 @ 64MHz 8/8, worst 64.55MHz/best 72.37MHz; N_SLOTS=8 deferred by explicit user request), and the FPGA_DATA_READY any_pending formula is updated to the real counter-based implementation (credited to the user's own diagnosis) that fixed the last failing N=4 seed. Compiled clean (45 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
481b5d223f |
perf: fix N=4@64MHz 7/8->8/8 by removing any_pending fan-out (user's idea)
Real critical-path trace after the flash #1 revert showed a NEW bottleneck (neural_director.job_out_slot -> dependency_manager. node_resolved/node_state, 76-84% routing) distinct from every prior fix this session -- already a flat, parallel 64-way compare, not a serial chain, so the established restructuring fix class doesn't apply. Root cause: any_pending (added for FPGA_DATA_READY) reads node_state[0:N_NODES-1] combinationally every cycle, adding real fan-out onto the same congested signal. User's own suggestion: replace the combinational scan with a synchronous up/down counter. pending_count +1 on registration acceptance, -1 on dispatch acceptance; any_pending = (pending_count != 0) -- mathematically identical (DEC-0008: nodes never reclaimed mid-run) but reads one small register instead of scanning a 16-wide array every cycle. Verified: D-Stress N=4 bit-exact (49927 cycles, data_ready PASS). Fresh 8-seed P&R: N_SLOTS=4 @ 64MHz now 8/8 PASS (was 7/8 after the flash revert), worst seed1 64.55MHz, best seed0 72.37MHz. See decisions.log DEC-0042. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
ee708775c7 |
Revert "feat: integrate flash #1 (neural-network data) RTL into V2 top-level"
This reverts commit
|
||
|
|
59901a4905 |
feat: integrate flash #1 (neural-network data) RTL into V2 top-level
Closes the flash #1 RTL gap flagged in DEC-0041: real, unmodified V1 subsystem (flash_slot_manager.v/flash_copy_engine.v/spi_flash_master.v/ crc32.v) now instantiated in fpga_neural_v2_top.v, bridged to the AR memory bus via a new flash_mem_adapter.v (byte<->word, matches nms_memory_manager_stream_wide.v's own real masking convention), and commandable over SPI via a new spi_host_bridge.v opcode (OP_FLASH_CMD, 0x30) using the same byte-counting idiom as OP_WRITE_JOB. Real balls now in the LPF: flash_sclk=B2, flash_mosi=E2, flash_miso=F2, flash_cs_n=F3. New tb_flash_integration_smoke.v: real SPI-triggered OP_FLASH_READ_BLOCK verified bit-exact (64/64 bytes) against a real V1 flash_model.v instance, through the new adapter and the widened (2->3 port) host-arb arbiter; WRITE_JOB regression confirms the new 3rd port doesn't disturb existing traffic. Full existing regression re-run clean: D-Stress N=4/ N=8 (bit-exact + data_ready PASS), board-level smoke test (11/11), isolated spi_host_bridge test (18/18). Honest, disclosed finding: a full 8-seed P&R re-verification shows N_SLOTS=4 @ 64MHz regressed from 8/8 to 3/8 PASS (worst 60.18MHz). Root cause traced via the real critical-path report: the SAME pre-existing arbiter-to-sdram-backend bottleneck already documented all session, made worse by flash's added die-area placement pressure -- not a new path through the flash logic itself. N_SLOTS=8 essentially unchanged (6/8, was 5/8). See decisions.log DEC-0042 for full detail and open decision points. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
b4f33388a9 |
fix: add missing sdram_clk output port -- real chip never had a clock pin
Found while helping verify the user's own schematic: clk_sys (the PLL- generated 64MHz system clock) was purely internal to fpga_neural_v2_top.v -- never reached a physical output pin. The real external SDRAM chip cannot function without its own CLK input driven from the board; this was missing from every prior P&R run this session, none of which ever routed a real clock to the SDRAM interface. Added `sdram_clk` output port (driven directly by clk_sys), assigned to J4 (bank 6, GR_PCLK6_0 -- a real clock-capable ball, confirmed free via Trellis iodb.json). Verified via real synthesis (0 errors) and nextpnr-ecp5 place&route: the pad-forwarded clock merges with the existing internal clock net (as expected, both are the same clk_sys signal), achieving 66.61 MHz post-route -- PASS at the 64 MHz target (the pre-route estimate of 49.73 MHz was a placement-only pessimistic number, superseded by the real post-route result). Smoke test re-verified (tb_fpga_neural_v2_top_smoke.v, 11/11 PASS). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
abaaf21f56 |
docs: datasheet addendum for two-flash programming architecture + FPGA_DATA_READY
Adds a real, dated section to ch.10 (Hardware and board) covering the two-independent-flash architecture (neural-network data vs. boot bitstream), the ESP32<->ECP5 JTAG-only link, and the real CABGA381 ball assignments (JTAG/PROGRAMN/INITN/DONE/CFG[2:0]/MSPI dedicated pins), matching decisions.log DEC-0041. Also closes ch.7's (Host interface) own long-standing "still needed" list: the physical transport (spi_host_bridge.v) and the completion- notification path (FPGA_DATA_READY) it used to flag as missing are both now real -- described with the same system-idle-detector formula implemented in the RTL. Compiled clean (44 pages, 0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
7d6311bce3 |
feat: two-flash programming architecture, FPGA_DATA_READY, real JTAG/config pinout
Establishes the real ESP32<->ECP5 programming architecture: flash #1 (neural-network data, existing V1 subsystem, ball reserved not yet wired into V2) stays separate from flash #2 (boot bitstream, MSPI auto-boot, CFG[2:0]=[0,1,0]); ESP32 talks JTAG only (bit-banged, no hardware JTAG-master peripheral on S3/C6), updating flash #2 through the ECP5's own internal sysCONFIG-to-SPI bridge, never driving the flash pins directly -- zero bus contention, confirmed against the real Lattice hardware checklist and sysCONFIG user guide. Adds real, verified ball assignments (official Lattice CABGA381 CSV + Project Trellis iodb.json) for JTAG, PROGRAMN/INITN/DONE, CFG[2:0], and the MSPI dedicated pins -- all written to docs/pinouts.md. Implements FPGA_DATA_READY as real RTL: a system-idle detector (dependency_manager's any_pending OR neural_director's !queue_empty OR any active slot), sticky on the busy->idle edge, self-clearing on new work -- not a per-neuron completion pulse, which was confirmed too fine-grained. Bit-exact regression re-verified at N_SLOTS=4 and 8 (zero cycle-count change), new explicit data_ready assertion check added to the D-Stress testbench (PASS both configs), and a fresh Yosys+nextpnr-ecp5 placement check (0 errors, data_ready placed at G3). Also fixes a real, independently-found bug while editing an adjacent file: nms_neural_multiprocessor_sdram_unified.v's own sdram_a port was still [11:0] (12 bits), stale from before the 64MB/13-bit memory upgrade. Not exercised by the real board-level top (which wires SDRAM directly, bypassing this wrapper) but WAS silently truncating A12 in every D-Stress simulation this session, including today's earlier ERR-0029 verification runs. Assessed impact: all D-Stress test addresses used this session decode to rows under 4096 (bit 12 never actually needed), so no false-positive PASS is believed to have resulted -- but the full 64MB space was never actually exercised through this wrapper. Fixed; re-verified bit-exact with identical cycle counts. See decisions.log DEC-0041 for full detail. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
81a9619214 |
chore: remove root-level V1 duplicates, superseded by hardware/v1/ freeze
hardware/v1/ was created (
|
||
|
|
e1cefd13db |
docs: remove hardware/v2/docs/DatasheetLatex, superseded by datasheet/
Replaced by the just-versioned hardware/v2/docs/datasheet/ (the project's real, maintained IT+EN LaTeX datasheet, now including the 2026-09-07 SDRAM upgrade addendum). DatasheetLatex/ was a separate, differently-structured, stale LaTeX document living in the same location -- removed to avoid two competing datasheets under hardware/v2/docs. hardware/v1/docs/DatasheetLatex/ is untouched (V1 scope, not part of this request). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
ff49d3c75d |
docs: bring datasheet/ into the main repo under hardware/v2/docs
Was a separate, untracked directory (DataSheet/) outside the repo. Renamed to lowercase and moved in as hardware/v2/docs/datasheet/, with its own .gitignore for LaTeX build byproducts (compiled PDFs stay tracked, .aux/.log/.toc/etc do not). Now versioned and shares this repo's own remote instead of living untracked on disk. Content: IT+EN LaTeX chapter sources, reference manufacturer PDFs, and compiled datasheet PDFs including the 2026-09-07 SDRAM upgrade addendum (AS4C32M16SB-7BIN part/pinout/timing) in the v2-en chapters. Note: hardware/v2/docs/DatasheetLatex/ (and the v1 sibling) is a separate, already-tracked, differently-structured LaTeX document that predates this move -- left untouched, not merged, since its chapter set and content differ and merging was not requested. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
f14224d0cd |
fix: ERR-0029 sdram_unified_backend weight-cache hit-index critical path
Replace the serial "last-match-wins" priority-scan hit-index encoder with a flat one-hot compare + single-level priority encode, breaking the serially-dependent PFUMX/OFX cascade real P&R showed dominating the N_SLOTS=8 @ 64MHz critical path (55.84MHz worst, 4/8 seeds PASS). Real nextpnr-ecp5 re-verification (32-run matrix, 4 configs x 8 seeds): N_SLOTS=8 @ 64MHz improves to 5/8 PASS (worst 60.12MHz, up from 55.84MHz). N_SLOTS=4 @ 64MHz stays 8/8 PASS but with reduced worst-case margin (WNS +0.605ns, down from +2.143ns) as the critical path relocates to a different, previously-second-worst path in the same module -- a real, disclosed trade-off, not hidden. 80MHz remains NO-GO at both processor counts (re-confirmed on the fixed RTL). Bit-exact, zero functional regression: isolated tb_sdram_unified_backend.v (40/40) and full D-Stress N=4/N=8 (both 256/256 neurons bit-exact vs golden model). See errors.log ERR-0029 and decisions.log DEC-0040 for full root-cause writeup and MEMORY_UPGRADE_64MB_N8.md section 10 for the complete measured data set and AS4C32M16SB-7BIN pinout tables. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
a20f1ecd73 |
docs: memory upgrade writeup (MEMORY_UPGRADE_64MB_N8.md) + supersede stale SDRAM docs
Adds the consolidated, authoritative record for the 64MB memory upgrade and N_SLOTS=8 investigation (real datasheet family comparison, RTL changes, both timing fixes with real P&R data, honest N=8 clock- closure status, real DigiKey availability for the frozen part). Marks HARDWARE_FREEZE.md/MEMORY_ARCHITECTURE.md/PRE_PCB_VERIFICATION.md/ PRE_PCB_CLOSURE_4POINT.md's own SDRAM-specific sections as superseded (they describe the previous 8MB AS4C4M16SA-6TIN part) with pointers to the new document, rather than rewriting each individually. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
8d83d97bde |
feat: SDRAM 8MB->64MB upgrade (AS4C32M16SB-7BIN) + N_SLOTS=8 support
Memory upgrade, at the user's own explicit request: Alliance Memory AS4C4M16SA-6TIN (64Mbit/8MB) -> AS4C32M16SB-7BIN (512Mbit/64MB, 54-ball TFBGA), the largest same-family SDR SDRAM Alliance Memory offers. Real-datasheet-driven (whole AS4C4M16SA/AS4C8M16SA/AS4C16M16SA/ AS4C32M16SA family investigated): 13 row bits (was 12, one new FPGA pin sdram_a[12]/ball F1), 10 column bits (was 8), real -7-grade AC timing (tRCD/tRP improved to 15ns, tREFI halved to 7.8us for the doubled row count). sdram_controller.v and sdram_model.v gained real ROW_BITS/COL_BITS/BANK_BITS parameters (was hardcoded 12/8/2). ADDR_WIDTH widened 23->26 bits across the live instantiation tree. This required a real SPI protocol change (spi_host_bridge.v): a 26-bit byte address no longer fits in 3 bytes -- every address field widened 3->4 bytes (WRITE_JOB 15->18 payload bytes, WRITE_MEM/READ_MEM header 5->6 bytes). Found and fixed two real timing regressions via nextpnr-ecp5 P&R (not assumed): neural_director.v's own runtime-indexed demux write (ERR-0027, was silently synthesizing an extra MULT18X18D) and nms_activation_fill_ctrl_v3.v's own linear N_SLOTS-wide max-scan (ERR-0028, became dominant at N_SLOTS=8) -- both replaced with constant-indexed/tree-based equivalents, bit-exact same behavior, confirmed via full D-Stress N=2/4/8 regression (identical cycle counts). N_SLOTS=4 now fully closes timing at 64MHz (8/8 seeds); N_SLOTS=8 significantly improved but not yet fully reliable (5/8 seeds) -- honestly disclosed, not claimed complete. Full regression re-verified: sdram_controller (461/461, 18 configs), tb_sdram_boundary (21/21), D-Stress N=2/4/8 (bit-exact), spi_host_bridge (18/18), board-level SPI smoke test (11/11), unified backend (40/40). See hardware/v2/docs/MEMORY_UPGRADE_64MB_N8.md for the full investigation, and errors.log/decisions.log (ERR-0027, ERR-0028, DEC-0039) for the complete root-cause writeups. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
9b5d1055b8 |
feat: neural_sim Python golden functional reference simulator
Adds tools/neural_sim/, a NumPy-based reference implementation of the FPGA-Neural V2 numeric model (INT8 in/weight, 32-bit wraparound accumulation, ReLU+saturate out), derived directly from hardware/v2/rtl/neural_processor.v (not assumed) and reusing tools/validation/mac_oracle.py's own pre-existing, hand-verified two's-complement primitives rather than duplicating them. Provides: neuron/layer/network models, a logical memory model of the real V2 SDRAM map (weights/activations/results), deterministic test-vector generators (simple/signed/extremes/zero/random/D-Stress 256x128) with JSON golden-vector export, an FPGA-vs-Python bit-exact comparison utility, four example networks, a CLI (`python -m tools.neural_sim ...`), and a 96-test pytest suite (all passing) covering signed-arithmetic edge cases (including a direct 32-bit wraparound proof), scalar-vs-vectorized neuron cross-checks, layer/memory/vector/comparison tests. This is a golden functional reference (bit-exact numeric result), explicitly NOT a cycle-accurate FPGA simulator -- see tools/neural_sim/README.md for the full scope statement. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
c4763aab10 |
test: directed SDRAM boundary verification + SPI frequency sweep
PRE-PCB CLOSURE Point 1: adds tb_sdram_boundary.v, a directed (not randomized) regression covering address 0/1/last/last-1, an explicit row-boundary crossing, all 3 inter-bank boundary crossings, the real V2 memory-map region boundaries (weights/activations/results), and every DQM byte-mask combination with explicit read-after-write. 21/21 PASS at both 64MHz and 166MHz, zero bugs found. PRE-PCB CLOSURE Point 2: adds tb_spi_freq_sweep.v, a reproducible SPI bit-rate sweep against the real fpga_neural_v2_top (osc_clk driven at the real 64MHz clk_sys rate via the SIM PLL bypass). Found and fixed a race in the new test harness itself (a fixed-time wait before reading a WRITE_MEM/READ_MEM response, too short whenever a periodic AUTO REFRESH delayed the backend) -- not a spi_host_bridge.v defect, confirmed against tb_spi_host_bridge.v's own isolated regression. Determined the real, deterministic CDC margin: the synchronizer requires >=5 system-clock cycles per SPI bit (exactly 64MHz/5 = 12.8MHz); recommends SPI_MAX_VERIFIED=12MHz with real margin below that hard edge. Full writeup: hardware/v2/docs/PRE_PCB_CLOSURE_4POINT.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
eb0b0f9170 |
docs: PRE-PCB VERIFICATION FREEZE report + config flash freeze
Adds hardware/v2/docs/PRE_PCB_VERIFICATION.md as the single authoritative pre-schematic verification record: RTL/ERR-0025/ regression re-verification, clock/reset, synthesis/P&R re-audit, setup/hold timing status, the real SDRAM datasheet-parameter audit table (Alliance Memory AS4C4M16SA-6TIN Table 17), SPI host bridge protocol documentation, FPGA power/pinout tables, first-board bring-up and benchmark status, and cross-domain consistency audit. Freezes the FPGA configuration flash: Winbond W25Q32JVSSIQ (32Mbit, SOIC-8, 2.7-3.6V, standard SPI, ECP5 Master-SPI-boot compatible) -- this was the one section-11 item the governing mandate required not be left OPEN. Marks CHIP_READINESS.md/OPEN_ITEMS.md/PINOUT.md/CLOCK_ARCHITECTURE.md/ POWER_ARCHITECTURE.md/SCHEMATIC_READINESS.md as superseded (they predate the SPI host bridge, PLL, and this session's SDRAM datasheet audit) with pointers to the new consolidated document, rather than rewriting each individually. Updates the V2 LaTeX datasheet's status/roadmap chapter to reflect the SDRAM datasheet audit and configuration-flash decisions, rebuilds the PDF (clean compile, 16 pages). Classification: PRE-PCB VERIFIED. Schematic and PCB implementation remain user-owned and not started. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
8890b0abc2 |
fix: ERR-0026 SDRAM tMRD datasheet-unit mismatch at 64MHz
Real Alliance Memory AS4C4M16SA-6TIN datasheet (Rev 5.0, Table 17) specifies tMRD as a fixed 2-tCK cycle count, not an ns value. sdram_controller.v modeled it via ns_to_cycles(12), which rounded to 2 cycles by coincidence at every previously-tested frequency (100/133/166MHz) but rounds to only 1 cycle at the real 64MHz board target -- an under-provisioned one-time init sequence. Fixed by hardcoding T_MRD=2, matching how CAS_LATENCY is already modeled. Verified zero regression: full 9-config legacy sweep + a new dedicated 64MHz config (461/461 PASS each), N=2/N=4 D-Stress (identical cycle counts), board-level smoke test (11/11 PASS). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
d6376e8f2a |
V2 final synthesis/P&R sign-off + LaTeX datasheet port (NOT SILICON READY)
Real synthesis and place-and-route of the actual final board-level
top (fpga_neural_v2_top.v -- SPI bridge, real EHXPLLL, reset_sync,
compute+memory core), against a real, fully ball-assigned LPF. Also
ports the V2 datasheet to LaTeX using V1's own preamble/macros/
typography, and records a real (non-ESP32, honestly labeled) software
reference comparison.
Synthesis (Yosys, real run): 0 CHECK-pass problems, 38 unique warnings
(43 total), all matching this project's own previously-reviewed benign
set (neural_processor.v's known genvar multi-driver artifact, small-
array-to-register unrolling, the real SDRAM DQ tristate bus) -- no new
warnings from the SPI bridge, PLL, or reset synchronizer.
TRELLIS_FF=6322, TRELLIS_COMB=7084, MULT18X18D=32, EHXPLLL=1 (real PLL
confirmed present), DP16KD=0 (all small SRAMs -> distributed RAM).
Place-and-route (nextpnr-ecp5, real runs, 8 seeds, new
v2_board_top.lpf with all 44 top-level signals ball-assigned from the
official Lattice pinout CSV -- no placeholders): 8/8 PASS at 64MHz.
Worst 68.51MHz (seed 4), best 74.17MHz (seed 7), mean 71.16MHz. Zero
unrouted nets, zero placement/routing errors, TRELLIS_IO=44/245 (17%).
Critical path alternates between dependency_manager's own priority
encoder and sdram_unified_backend's own weight-cache hit-index logic,
matching this project's own prior documented timing investigations --
not a new defect.
New: hardware/v2/constraints/v2_board_top.lpf (final LPF, supersedes
v2_unified.lpf for the board-level top), hardware/v2/reports/
step_final_{synthesis,pnr_worst_seed4,timing}.* (raw evidence),
hardware/v2/docs/DatasheetLatex/ (V2 datasheet, real LaTeX build,
16 pages, visually inspected, ported from hardware/v1/docs/
DatasheetLatex/'s own preamble and macros).
Real, honestly-labeled software baseline: the D-Stress arithmetic
(256 neurons x 128 INT8 MACs) compiled and run on THIS development
machine (Apple M4, arm64, NOT an embedded target, NOT ESP32) --
1.28us/inference, included in the datasheet with an explicit
disclosure that no physical ESP32 hardware was available for a real
embedded-target comparison.
Remaining, disclosed, NOT-yet-closed items (this commit does NOT
claim silicon readiness): real KiCad schematic + ERC, PCB layout,
sourced BOM, real power current-budget estimate, SDRAM-datasheet-
parameter cross-check, configuration-flash selection, and (necessarily)
physical fabrication/bring-up. See hardware/v2/docs/DatasheetLatex/
chapters/08-status-roadmap.tex for the complete, itemized checklist.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
|
||
|
|
68f3c5e403 |
fix(v2): resolve ERR-0025 Part B - SRAM read timing bug in weight/activation memory
Root-causes and fixes the real, disclosed defect left open at the end of the previous STEP20 commit: the board-level SPI host interface produced wrong compute results when jobs were dispatched with realistic (widely time-separated) pacing, even though job registration itself was already confirmed correct at the dependency_manager handshake. Root cause: nms_weight_packed.v and nms_activation_replicated.v both used a REGISTERED SRAM read (rd_data_reg <= mem[addr], one full clock of latency), but nms_memory_manager_stream_wide.v's own read-ahead pipeline (its `rd_pending` bit) is designed around a COMBINATIONAL read -- a request issued this cycle produces data already valid to capture the very next cycle. A busy, multi-tile job (e.g. the STEP19 D-Stress regression, 16 tiles/neuron) never exposes the mismatch, since its own weight/activation prefetch always runs far enough ahead that any given tile has been sitting stable in the SRAM for many cycles by the time it's actually consumed. An uncontested single-tile job has zero such margin: its one tile's read fires on the exact edge the data nominally becomes ready, landing squarely on the missing cycle and permanently latching stale/zero data. Fixed by making both SRAMs' reads combinational, with an explicit same-cycle fill/read address-match bypass for the one hazard a plain combinational read alone would still miss. No FSM, arbiter, or SDRAM controller logic was touched. Verified (Verilator, per this project's own standing DEC-0004 protocol): - tb_fpga_neural_v2_top_smoke.v: 11/11 PASS -- single job, back-to-back jobs, a realistic ~85us-gap job pair, and a parametric sweep of inter-job gaps (100ns/5000ns/50000ns). - STEP19 D-Stress N=2: 49788 cycles, 256/256 bit-exact -- identical cycle count to before this fix (zero regression). - STEP19 D-Stress N=4: 49771 cycles, 256/256 bit-exact -- identical cycle count to before this fix (zero regression). - tb_sdram_unified_backend.v (40/40) and tb_spi_host_bridge.v (18/18) reconfirmed unaffected. The physical SPI host interface is now verified correct end-to-end. Real synthesis/P&R of the board-level top (fpga_neural_v2_top.v) is the deliberate next step, not yet performed this round. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
18bf038ed5 | v1 datasheet latex source | ||
|
|
43abf28b5b |
V2.1.0-dev: SPI host bridge + clock/reset architecture (NOT release-ready)
STEP20 work toward the V2 hardware release gate. Adds real new RTL
implementing the three pieces the previous freeze (V2.0.0) explicitly
left open, plus real, disclosed verification findings. Does NOT
declare hardware release complete -- see below.
New RTL:
- spi_host_bridge.v: real SPI slave protocol engine (WRITE_JOB/
WRITE_MEM/READ_MEM/STATUS/RESET opcodes), replacing the 110-pin
reg_* testbench bus as the intended physical host interface.
Isolated regression 18/18 PASS (tb_spi_host_bridge.v); two real
MISO-timing bugs found and fixed during its own development (see
the module's header for the root-cause writeup).
- ecp5_pll_sys_clk.v: real, tool-generated (Project Trellis ecppll)
EHXPLLL wrapper, 16MHz oscillator -> 64MHz system clock, with a
declared (not fabricated) simulation-only PLL bypass.
- reset_sync.v: standard async-assert/sync-deassert reset bridge
gating on external POR and PLL lock.
- fpga_neural_v2_top.v: board-level top wiring the above around the
STEP19 compute+memory design's own already-frozen submodules
(zero modification to neural_processor.v, dependency_manager.v,
sdram_unified_backend.v, or any other previously-frozen file).
Real findings from this step's own re-verification (both logged in
full in hardware/v2/logs/errors.log):
- ERR-0024: the current Icarus Verilog v13.0 install (updated since
the last freeze) gives WRONG bit-exact results for the
already-committed STEP19 regression. Cross-checked against
Verilator per this project's own standing protocol (DEC-0004) --
the STEP19 baseline (single SDRAM, N=2/N=4, raw reg_* interface) IS
bit-exact correct, reconfirmed today, matching the historical cycle
counts exactly. Two provably-zero-behavior-change declaration-order
fixes were required just to get the current toolchain to elaborate
the already-shipped STEP19 files at all.
- ERR-0025: a real SPI-bridge protocol race (fixed) plus a SEPARATE,
real, UNRESOLVED defect -- two jobs dispatched through the real SPI
path with realistic pacing produce wrong compute results, even
though job registration itself is confirmed correct at the
handshake. Root cause not yet isolated. Committed as a known-failing
regression (tb_fpga_neural_v2_top_smoke.v) documenting the gap
honestly rather than hiding it.
Given ERR-0025 Part B is real and unresolved, synthesis/P&R of the new
board-level top was deliberately not attempted this round, and V2
hardware release is NOT declared complete. See decisions.log DEC-0036
and hardware/v2/docs/{CHIP_READINESS,OPEN_ITEMS}.md for the full,
itemized status.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
|
||
|
|
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 |
||
|
|
5c9ec618d3 |
docs: publish refreshed V1 datasheet (EN/IT, Rev A1)
Adds the updated professional-template V1 datasheet PDFs to the tracked repo, matching the datasheet's own filename convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
63cac6a7e5 |
perf(v2): shared activation cache - further 1.66-2.00x real speedup (DEC-0016)
Implements optimization #2 from the final benchmark campaign's own recommendation, on top of DEC-0015's word-level burst rewrite: a new shared activation_cache.v module fetches a given activation (X) vector from PSRAM once instead of once per neuron sharing it - the exact redundant traffic pattern the dense-layer workloads in this project's benchmark suite exhibit. Each memory_manager's own prefetch_engine now fetches WEIGHTS only; the activation half is requested from the shared cache instead (single-tag, tile-granular, N_SLOTS request ports, its own real word-level PSRAM backend via a new dedicated arbiter port). dataflow_core.v/slot_mem_arbiter.v/neural_multiprocessor.v widened to N_SLOTS+1 ports to arbitrate the cache's traffic alongside each slot's weight traffic. Two real bugs found and fixed during implementation (ERR-0010): a target-bank/pending-bank race in memory_manager.v's activation-cache wiring (the same bug class ERR-0006 already fixed once for pf_target_bank - a later handoff's queued request can overwrite which bank an earlier, still-in-flight request's ack applies to), and a repeat of ERR-0009's N_SLOTS=1 zero-width replication bug in activation_cache.v itself. Real, measured results: the full final-benchmark campaign (24/24 workload/config combinations) re-verified bit-exact. D-Stress cycles fall a further 1.66-2.00x on top of DEC-0015 (~4x combined vs the original byte-level baseline). But the cache's real Fmax cost is much steeper than DEC-0015's own: N_SLOTS=2 (the recommended default, DEC-0014) drops from 133.58 to 87.72 MHz (-34%, margin over 80MHz shrinks from +67% to +9.7%), and N_SLOTS=4 drops to 65.01 MHz - now FAILING the 80MHz target it previously passed. Combined real wall-clock speedup vs the original baseline: N=1 3.86x, N=2 2.45x (both real net wins); N=4 is a real regression once its own now-failing Fmax is honestly used, though N=4 was never the recommended configuration. N_SLOTS=2 remains the recommended default (DEC-0014 unaffected) with a thinner but still real Fmax margin. Cache hit-detection pipelining is flagged as concrete follow-up work if N_SLOTS>2 is ever needed with the cache active - not attempted this round. Logged: simulation/synthesis/timing/benchmark/decisions (DEC-0016)/ experiments (EXP-0016)/errors (ERR-0010)/development.log, ROADMAP.md updated. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
e4a5540b6e |
perf(v2): word-level burst reads - 2.24-2.37x real wall-clock speedup (DEC-0015)
Implements optimization #1 from the final benchmark campaign's own recommendation: exploit psram_controller.v's already-implemented page-mode support (confirmed present by direct inspection) by fetching multiple bytes per real backend transaction instead of one at a time. Root cause addressed: int8_memory_access.v (the byte-level backend prefetch_engine.v originally sat on) already converts every 8-bit logical request into a full 16-bit PSRAM word access internally (mem_addr <= addr >> 1), discarding half of every word it already paid for. prefetch_engine.v/memory_manager.v now speak memory_interface.v's own 16-bit word protocol directly, bypassing int8_memory_access.v entirely - which remains untouched, still frozen V1 (§1/§34); V2 simply reuses the lower layer of the same frozen chain instead of the byte-splitting layer on top of it, the same "reuse what fits" precedent slot_mem_arbiter.v already set. slot_mem_arbiter.v and neural_multiprocessor.v widened to match (lb_n/ub_n added, master port wired directly to memory_interface.v). Real, measured results: M4's own single-job testbench shows 49-56% fewer cycles (166->84, 446->204, 728->322, all still bit-exact). The full final-benchmark campaign (24/24 workload/config combinations) re-verified bit-exact with D-Stress's real wall-clock time (cycles / real POST-P&R Fmax) improving 2.24-2.37x across every N_SLOTS tested, against a small real Fmax cost (unchanged at N=1, -6.2% at N=2, -1.2% at N=4). tb_neural_multiprocessor.v (M8) and tb_benchmark_suite.v (final campaign) needed zero changes - both treat neural_multiprocessor.v as a black box. Only tb_memory_manager.v (M4, rewired to skip int8_memory_access.v) and tb_dataflow_core.v (M7, behavioral model widened to word-level) needed updates. The "real parallel scaling is flat beyond N_SLOTS=2" finding (DEC-0014) still holds - this optimization made the shared PSRAM port more efficient per transaction, not multi-ported - so N_SLOTS=2 remains the recommended default. Logged: simulation/synthesis/timing/benchmark/decisions (DEC-0015)/ experiments (EXP-0015)/development.log. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
3cdaeaee35 |
test(v2): final benchmark campaign - real end-to-end characterization (EXP-0014)
Post-M10, user-requested final benchmark campaign: 6 realistic workloads (16-256 independent neurons in a shared-input dense-layer shape, a random-seeded 2-layer network with real cross-node PSRAM forwarding, and a 6-node 2-hop dependency diamond) x 4 concurrency levels (N_SLOTS=1/2/4/8) through the real, full neural_multiprocessor system (real V1 PSRAM chain, real slot_mem_arbiter). 24/24 runs PASS bit-exact against a software golden model (11,520 individual neuron/ node checks, zero mismatches). Three real bugs found and fixed during the campaign itself (ERR-0009): 1. neural_director.v (M5) had a real RTL bug at N_SLOTS=1 ($clog2(1)=0 makes a replication expression illegal) - never caught because M5-M10 only ever tested N_SLOTS=2/4/8. Fixed with a width-agnostic '0 literal; M5's own testbench re-verified unaffected. 2/3. Two testbench sizing bugs in tb_benchmark_suite.v itself (psram_model DEPTH too small for the Large workload's address range; N_NODES too small for the Stress workload's node-id range, causing a real deadlock via node-id wraparound colliding with an already-DISPATCHED node - a real, honest consequence of DEC-0008's own "no node-slot reclamation" design choice). Headline finding: real parallel scaling is essentially flat beyond N_SLOTS=2 - the single shared PSRAM port saturates at ~91% utilization regardless of slot count, so memory-bound workloads gain only 1.05-1.06x real speedup from N=1 to N=8. Once real POST-P&R Fmax degradation is also factored in, N_SLOTS=4 is measurably 21% SLOWER in real wall-clock time than N_SLOTS=1 for the largest workload tested. N_SLOTS=2 is recommended as the default (DEC-0014, superseding DEC-0012's resource-only "N_SLOTS=8 ceiling" framing for general use). Full 21-section report (every number classified THEORETICAL/ SIMULATED/POST-P&R MEASURED/DERIVED, per the user's own methodology requirements): hardware/v2/docs/benchmarks/ final-benchmark.md Logged: simulation/synthesis/timing/benchmark/decisions (DEC-0014)/ experiments (EXP-0014)/errors (ERR-0009)/development.log, ROADMAP.md updated. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
91bbbe2fe5 |
feat(v2): M10 Optimization - data-driven findings, completes the V2 roadmap
Final milestone of docs/v2-description.md's §33 roadmap, scoped exactly to its own mandate: optimize only on data already gathered in M1-M9, across the pipeline/P_IN/processor-count/scheduling/memory axes - no speculative new features. Three concrete, data-driven results: 1. N_SLOTS=8 (numero processor axis): real synthesis + nextpnr-ecp5 P&R for dataflow_core at N_SLOTS=8, extending M7's N_SLOTS=2/4 sweep to the real DSP ceiling DEC-0005 predicted. 92.63 MHz POST-P&R, PASS at 80MHz, DSP 64/72 (88.9%). DEC-0012 recommends N_SLOTS=8 as the practical ceiling for P_IN=8 on the LFE5U-45F-8BG381. 2. ACC_WIDTH 24 vs 32 (pipeline axis): a real 6-seed nextpnr-ecp5 placement sweep (reusing already-synthesized netlists, no new synthesis needed) resolves EXP-0002's single-seed inconclusiveness. ACC_WIDTH=24 wins on both mean Fmax (+6.2%, 180.71 vs 170.12 MHz) and seed-to-seed variance (~3.4x tighter), on top of its already-known resource advantage. DEC-0013 recommends ACC_WIDTH=24 as the new default. 3. Stall %/utilization (scheduling/memory axes): testbench-only cycle counters added to tb_neural_multiprocessor.v (no RTL touched) close DEC-0011's deferred measurement gap with real data - shared PSRAM port 81.7% utilized, slot 0 95.2%, slot 1 65.2%, no conclusive evidence of harmful fixed-priority starvation at this scale. The 10-milestone V2 roadmap (docs/v2-description.md §33) is now complete end-to-end: real Verilator simulation, real Yosys synthesis, real nextpnr-ecp5 place & route for every milestone, fully logged (EXP-0001..EXP-0013, DEC-0001..DEC-0013, ERR-0001..ERR-0008) with no invented results (§30) and V1 kept frozen and untouched throughout (§1/§34). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
84794a3d25 |
docs(v2): M9 full benchmark - V1 vs V2 comparison table (§32)
Consolidates real, already-measured data from hardware/v1/ (frozen, pre-certified) and V2's own M1-M8 logs into the §32-mandated comparison table, on an apples-to-apples basis: both full systems (V1's spi_neuron_top post_fix_verify vs V2's neural_multiprocessor N_SLOTS=2), both PARALLEL=8/P_IN=8, both using the real unmodified V1 PSRAM backend. Headline, all real measurements: V2 full-system Fmax 142.45 MHz POST-P&R (PASS at 80MHz) vs V1's 68.65 MHz (FAIL at 80MHz); 166 vs 209 real simulated cycles for one neuron's 8-input dot product through the same real PSRAM chain (2.6x wall-clock speedup); peak MAC/cycle 16 (N_SLOTS=2 concurrent slots, real contention already demonstrated in EXP-0009) vs V1's 8 (single sequential core); lower LUT/FF despite V2 already including full dependency-graph scheduling that V1 has none of. 9 of the table's 12 rows carry real sourced numbers; stall %/memory utilization/processor utilization are reported as NOT MEASURED rather than approximated (DEC-0011) - a real number needs dedicated cycle-accounting instrumentation neither system has had built for it yet, and approximating from partial data would violate §30's "no invented results" rule. Deferred to M10, which needs exactly this data to decide what to optimize. No new RTL this milestone - pure data consolidation, logged as EXP-0010. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
6cff2c8a7c |
feat(v2): M8 PSRAM integration - real V1 backend shared across concurrent slots
neural_multiprocessor.v wraps dataflow_core.v (M7, unmodified) around the real, unmodified V1 PSRAM backend chain (int8_memory_access -> memory_interface -> psram_controller), funneling N_SLOTS independent Memory Backend Interface ports through a new generic N-port arbiter (slot_mem_arbiter.v) inspired by (not copied from) V1's own mem_arbiter.v. Real concurrent-slot simulation immediately surfaced a genuine bug (ERR-0008): memory_manager/prefetch_engine's byte-level backend protocol is fire-and-forget (a single-cycle mem_req pulse with no accept handshake) - correct for M4's direct 1:1 connection, but a naive arbiter silently drops a pulse arriving while the shared bus is owned by another slot, hanging that slot forever. Fixed with a per-port pending-request latch, the same "queue, don't drop" idiom already used by memory_manager's own pf_pending register (ERR-0006). Verified (Verilator): 4/4 PASS with 2 slots genuinely contending for one real PSRAM port (444 cycles). No regression on M4's own testbench. Real synthesis + nextpnr-ecp5 P&R (no harness needed - real PSRAM pins keep the top-level at 157 pins): 0 problems, Fmax 142.45 MHz, PASS at 80MHz. Arbitration policy is fixed lowest-index priority, not fairness- balanced (DEC-0010) - consistent with every other "simplest correct policy first" scheduling choice in this roadmap, revisited only if M9's real measurement shows starvation matters. Logged: simulation/synthesis/timing/benchmark/decisions (DEC-0010)/ experiments (EXP-0009)/errors (ERR-0008)/development.log, ROADMAP.md updated. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
77baa8fc16 |
feat(v2): M7 Dataflow Core - full M1-M6 integration, wake-up loop closed end-to-end
dataflow_core.v integrates dependency_manager (M6) -> neural_director (M5) -> N_SLOTS x (memory_manager (M4) + neural_processor (M1)) for the first time. A slot's completion (via neural_director's new slot_node_id tracking, an additive port) feeds back as a producer_done event to dependency_manager, waking up any node that depended on it - closing the dataflow loop without external glue. Verified end-to-end (Verilator) on a 3-node DAG: two independent nodes plus a third depending on both, confirmed to dispatch only after both genuinely complete via real neural_processor computation. 4/4 PASS. Real synthesis + nextpnr-ecp5 P&R via a synthesis-only timing harness (bare per-slot backend ports exceed the LFE5U-45F's TRELLIS_IO budget, same pattern as ERR-0005): N_SLOTS=2 -> 165.15 MHz, N_SLOTS=4 -> 133.19 MHz, both PASS at 80MHz, 0 synthesis problems. Scope explicitly deferred to M8 (DEC-0009): M3's BRAM buffers not wired in yet, per-slot Memory Backend Interface ports not arbitrated to one shared PSRAM master yet - both need real measured data before committing to a design, not guessed at here. Logged: simulation/synthesis/timing/benchmark/decisions (DEC-0009)/ experiments (EXP-0008)/errors (ERR-0007, a Yosys chparam-ordering build quirk, not an RTL bug)/development.log, ROADMAP.md updated. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v |
||
|
|
8af16d3a12 |
feat(v2): M6 Dependency Manager, multi-dependency wake-up
Implements M6: dependency_manager.v tracks a table of node
descriptors (node_id/state/required_dependencies/resolved_
dependencies/producer_ids -- §10's exact field list), incrementing a
waiting node's resolved count whenever one of its listed producers
completes, transitioning it to READY once resolved==required, and
dispatching ready nodes to the Neural Director (M5) one at a time via
a backpressure-safe valid/ready interface.
Verified with Verilator on a small hand-built DAG: node0/node1 have no
dependencies (dispatch immediately); node2 depends on BOTH node0 AND
node1 ("dipendenze multiple") and stays WAITING until both complete,
confirmed via an explicit negative check after only one resolves;
node3 depends on node0 ALONE, demonstrating a single producer
("node0") satisfying two different consumers' dependencies
("risultati condivisi... piu' consumer") -- node3 fully, node2
partially. 4/4 tests pass.
Scope for this milestone (decisions.log DEC-0008): dependency
COUNTING/readiness only, no direct producer-to-consumer value
forwarding (§11 frames that as a "quando possibile" optimization, not
a correctness requirement -- deferred until real bandwidth
measurements justify it) and no node-slot reclamation after dispatch
(not exercised by any scenario built so far).
Real synthesis: 0 CHECK problems, 763 LUT4/474 FF/0 DSP/0 CCU2C. Real
place&route (module fits the TRELLIS_IO budget as a bare top-level
this time, no harness needed): Fmax 155.30 MHz, PASS at 80MHz.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
|