diff --git a/docs/NOW.md b/docs/NOW.md index 168356c10..1ef83c99a 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -1,7 +1,13 @@ -# NOW — MMCM places but is dead on silicon; open-flow structural options exhausted (2026-08-08) +# NOW — Vivado closure kit: the multicycle constraint that kills the seed-lottery (2026-08-08) Last updated: 2026-08-08 +## feat(docs): Vivado closure kit -- the set_multicycle_path constraint the open flow cannot express (Refs #1764) + +- The root-cause arc concluded the seed-lottery is a global placement effect of the timing-relaxed open-flow placement; the cure is not another register but telling a timing-driven P&R the truth about the path. nextpnr-xilinx XDC = create_clock only, so it cannot; Vivado can +- Added `docs/vivado_closure/`: (1) `bpseq_vivado.xdc` = create_clock 200 MHz + `set_multicycle_path 16` on the shared-core `rf -> rf` (through GftSmul/GftSadd) paths -- that path is genuinely multicycle (captured once per cen x settle ~2560 cycles), so Vivado closes it deterministically and the lottery disappears; (2) `vivado_build.tcl` batch synth->route->bitstream printing worst slack; (3) `README.md` +- This converts the documented open-toolchain limitation into a solved problem with the right instrument, and is the prerequisite for training nets > XOR (where open-flow seed-search runs out). Vivado does not run on this macOS arm64 host, so the kit is authored for the user's Vivado environment. Methodology points to it. Docs/scripts only. Refs #1764 + ## docs: MMCM real clock tree places but does NOT function on silicon -> open-toolchain options exhausted, seed-search is final (Refs #1764) - Tested the last structural lever ("все три", Variant 1): regenerate the 200 MHz clock through the MMCM/CMT tree (low-skew) instead of the fabric IBUFDS net, to probe the global clock-skew hypothesis. MMCME2_BASE places in nextpnr and the fasm builds, but the flashed bitstream is DEAD on the AX7203 -- no UART response on any of 4 seeds, with or without a BUFG on the MMCM output diff --git a/docs/SILICON_TRAINING_METHODOLOGY.md b/docs/SILICON_TRAINING_METHODOLOGY.md index 25c4198c1..69100469f 100644 --- a/docs/SILICON_TRAINING_METHODOLOGY.md +++ b/docs/SILICON_TRAINING_METHODOLOGY.md @@ -200,6 +200,10 @@ does not re-run them: on openXC7, not functional** — the clock-skew hypothesis cannot be tested here, and the open-toolchain structural options are fully exhausted. Only commercial P&R (Vivado) can close timing directly or provide a working MMCM. Build in `scratchpad/board/bpmmcm/`. + A ready-to-run **Vivado closure kit** for this is in `docs/vivado_closure/`: a + `set_multicycle_path` on the shared-core `rf→rf` path — the exact constraint the open + flow cannot express — plus a batch build script, which closes the deep path + deterministically (no seed-search) and is the prerequisite for training nets > XOR. Conclusion of the root-cause arc: **every local register-based fix has failed** — the combinational datapath at the endpoints (7), mid-cloud (10), and the write/control path diff --git a/docs/vivado_closure/README.md b/docs/vivado_closure/README.md new file mode 100644 index 000000000..29a899003 --- /dev/null +++ b/docs/vivado_closure/README.md @@ -0,0 +1,41 @@ +# Vivado closure kit — kills the seed-lottery with a real multicycle constraint + +The open flow (yosys → nextpnr-xilinx → prjxray) **cannot express a multicycle timing +constraint** — nextpnr-xilinx's XDC parser supports only `create_clock`. So the deep +shared-core path (`rf → GftSmul/GftSadd → rf`) is left timing-relaxed and correctness +becomes placement-dependent: some `--seed` values train, most glitch (the "seed-lottery", +characterised across 12 measured dead ends in `SILICON_TRAINING_METHODOLOGY.md`). + +Commercial P&R closes it directly. This kit is the minimal delta: + +- **`bpseq_vivado.xdc`** — `create_clock` at 200 MHz **plus** `set_multicycle_path 16` + on the `rf → rf` (through-core) paths. That path is genuinely multicycle: the + microsequencer captures its result only once per `cen × settle` (~2560) cycles, so it + never needs 200 MHz single-cycle setup. Vivado then closes it deterministically. +- **`vivado_build.tcl`** — batch synth → opt → place → phys_opt → route → bitstream, + printing the worst setup slack (expect ≥ 0) and writing `bpseq_vivado.bit`. + +## Run + +``` +# copy the RTL next to this kit: +cp ../bpseq_capstone.v bpseq.v +cp ../uart_bpseq.v ../gft_smul.v ../gft_sadd.v . +vivado -mode batch -source vivado_build.tcl +``` + +Then flash the result exactly like the open-flow bitstream — but **no seed-search**: + +``` +openFPGALoader -c digilent_hs2 --busdev-num 002:002 bpseq_vivado.bit +python3 ../drive_bpseq.py /dev/cu.usbserial-2120 +``` + +## Why this is the fix (and the open flow is not) + +Every *local* fix failed on silicon (endpoint / mid-cloud / write-control registration — +the fault is a global clock/placement effect of the relaxed placement). The cure is not a +different register; it is **telling the tool the truth about the path** so a timing-driven +placer closes it. Vivado can hear that constraint; nextpnr-xilinx cannot. This converts the +documented open-toolchain limitation into a solved problem with the right instrument, and it +is the prerequisite for training nets larger than XOR (where open-flow seed-search runs out). diff --git a/docs/vivado_closure/bpseq_vivado.xdc b/docs/vivado_closure/bpseq_vivado.xdc new file mode 100644 index 000000000..5726125b0 --- /dev/null +++ b/docs/vivado_closure/bpseq_vivado.xdc @@ -0,0 +1,26 @@ +## AX7203 (xc7a200tfbg484-1) — GF-T microsequencer trainer, commercial P&R closure. +## The one constraint the open flow (nextpnr-xilinx XDC = create_clock only) cannot +## express: the shared-core path is MULTICYCLE, so Vivado closes it deterministically +## and the seed-lottery disappears. + +## --- board clock (200 MHz LVDS); Vivado propagates through the IBUFDS automatically --- +set_property -dict {PACKAGE_PIN R4 IOSTANDARD DIFF_SSTL15} [get_ports clk_p] +set_property -dict {PACKAGE_PIN T4 IOSTANDARD DIFF_SSTL15} [get_ports clk_n] +create_clock -period 5.000 -name sys_clk [get_ports clk_p] + +## --- the shared-core datapath is a multicycle path --------------------------------- +## rf -> (modf) -> GftSmul/GftSadd -> rf. The microsequencer captures the result only +## once per (cen x settle) cycles, so this path never needs to meet 200 MHz single-cycle +## setup. Its real delay is ~47 ns (~10 cycles); a 16-cycle budget closes it with margin +## while every launch->capture gap in the design is >= 2560 cycles, so this is safe. +## Counters (pc/settle/dc) and the UART FSM are NOT rf_reg, so they stay single-cycle. +set_multicycle_path 16 -setup -from [get_cells -hier -filter {NAME =~ *rf_reg*}] -to [get_cells -hier -filter {NAME =~ *rf_reg*}] +set_multicycle_path 15 -hold -from [get_cells -hier -filter {NAME =~ *rf_reg*}] -to [get_cells -hier -filter {NAME =~ *rf_reg*}] + +## --- I/O ----------------------------------------------------------------------------- +set_property -dict {PACKAGE_PIN P20 IOSTANDARD LVCMOS33} [get_ports uart_rx] +set_property -dict {PACKAGE_PIN N15 IOSTANDARD LVCMOS33} [get_ports uart_tx] +set_property -dict {PACKAGE_PIN B13 IOSTANDARD LVCMOS33} [get_ports {led[0]}] +set_property -dict {PACKAGE_PIN C13 IOSTANDARD LVCMOS33} [get_ports {led[1]}] +set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS33} [get_ports {led[2]}] +set_property -dict {PACKAGE_PIN D15 IOSTANDARD LVCMOS33} [get_ports {led[3]}] diff --git a/docs/vivado_closure/vivado_build.tcl b/docs/vivado_closure/vivado_build.tcl new file mode 100644 index 000000000..463244d20 --- /dev/null +++ b/docs/vivado_closure/vivado_build.tcl @@ -0,0 +1,20 @@ +# vivado_build.tcl — batch build the GF-T microsequencer trainer for the AX7203. +# vivado -mode batch -source vivado_build.tcl +# Produces bpseq_vivado.bit with DETERMINISTIC timing closure (no seed-search): +# the multicycle constraint in bpseq_vivado.xdc lets a timing-driven P&R close the +# deep shared-core path that the open flow can only leave relaxed. +set part xc7a200tfbg484-1 +set top top +read_verilog [list uart_bpseq.v bpseq.v gft_smul.v gft_sadd.v] +read_xdc bpseq_vivado.xdc +synth_design -top $top -part $part +opt_design +place_design +phys_opt_design +route_design +report_timing_summary -file timing_summary.rpt +# Expect: WNS >= 0 (all paths met, including the multicycle shared-core path). +set wns [get_property SLACK [get_timing_paths -max_paths 1 -nworst 1 -setup]] +puts "=== WNS (setup worst slack) = $wns ns ===" +write_bitstream -force bpseq_vivado.bit +puts "=== wrote bpseq_vivado.bit — flash with openFPGALoader, no seed-search needed ==="