Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/NOW.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# NOW — docs: seed-lottery marginality is placement-level, Heisenbug-confirmed (2026-08-08)
# NOW — docs: a slower clock is not the fix; pipelining is (2026-08-08)

Last updated: 2026-08-08

## docs: a slower clock cannot fix the seed-lottery — pipelining the shared core is the only structural fix (Refs #1764)

- Investigated the "just run the deep path on a slower clock" remedy and ruled it out on TWO independent grounds. (a) NOT buildable on openXC7: a fabric-counter divided clock needs a clock buffer, and nextpnr-xilinx cannot place one driven from fabric — both `BUFG` and `BUFR` fed by a divider bit fail with "Unable to find legal placement" (7-series clock-buffer inputs come from clock-capable pins / the CMT, not general routing). Only an MMCM/PLL could make a real divided clock
- (b) Even if buildable, it would not help: a divided clock with the same microcode `settle` gives the SAME real settle window (~µs) as the working `/N` clock-enable, and more settle does not cure the glitch — silicon behaviour is non-monotonic in settle (`/128` glitched worse than `/64`, cycle 93). The fault is a placement HAZARD, not a settle shortage
- Also re-confirmed: `create_clock` on the differential `clk_p` port does not propagate through `IBUFDS`; the internal clock net defaults to a loose 12 MHz target and always "passes", so `--timing-allow-fail` was effectively a no-op. Constraining `[get_nets clk]` tighter reports the true fmax (~21 MHz) but does not change the silicon hazard
- CONCLUSION (re-prioritises the roadmap): the one viable structural fix is to PIPELINE the shared `GftSmul`/`GftSadd` (a spec-level `on_clock` pipelined multiply/add) so each microcode step reads a registered value and the deep combinational hazard is broken. This is the prerequisite for on-silicon training beyond XOR (seed-search runs out at 62 steps). Documented in `docs/SILICON_TRAINING_METHODOLOGY.md` "Honest limits". Docs only. Refs #1764

## docs: record that seed-lottery marginality is a PLACEMENT property, not a register bug (Refs #1764)

- Ran the last diagnostic for the on-silicon seed-lottery: on-chip observability. Widened the UART result dump from 4B (y) to 12B `{z1, z0, y}` so a glitching seed would reveal WHICH register diverges first (hidden pre-activations vs output). The instrumented design output ALL-ZERO on every seed tried — adding the probe re-placed the shared core past its (unconstrained) timing edge
Expand Down
25 changes: 24 additions & 1 deletion docs/SILICON_TRAINING_METHODOLOGY.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,30 @@ no Docker, native macOS arm64.
core past its (unconstrained) timing edge. This is a genuine Heisenbug: the deep path is
marginal enough that instrumenting it *moves* the result, which is itself the evidence
that the fault lives in the timing/placement of the whole path, not in one microcode
step. The fix is a real timing constraint (commercial P&R), not a code change.
step.
- **A slower clock is NOT the fix — on two independent grounds.** The intuitive remedy
("just run the deep path at a slower clock so it settles") fails twice on this flow.
*(a) It is not buildable.* A fabric-counter divided clock needs a clock buffer, and
nextpnr-xilinx cannot place one driven from fabric: both `BUFG` and `BUFR` fed by a
divider bit fail with *"Unable to find legal placement"* (a 7-series clock buffer input
comes from a clock-capable pin or the CMT, not general routing). Only an MMCM/PLL could
synthesize a real divided clock. *(b) Even if it built, it would not help.* A divided
clock with the same microcode `settle` count delivers the **same real settle window**
(~µs) as the working `/N` clock-enable — no new mechanism. And more settle does not cure
the glitch: the on-silicon behaviour is **non-monotonic in settle** (a `/128` enable
glitched *worse* than `/64`), so the fault is a placement **hazard**, not a shortage of
settle time. Note too that `create_clock` on the differential `clk_p` port does **not**
propagate through the `IBUFDS`; the internal clock net defaults to a loose 12 MHz target
and always "passes", so `--timing-allow-fail` was effectively a no-op — the path was
never actually being closed, just loosely met. Constraining the internal net tighter
reports the true fmax (~21 MHz) but does not change the silicon hazard.
- **Therefore the one viable structural fix is to PIPELINE the shared core** — register
the intermediate stages of `GftSmul`/`GftSadd` (a spec-level `on_clock` pipelined
multiply/add) so every microcode step reads a clean, registered value and the deep
combinational hazard is broken, letting nextpnr close each short stage at the real
200 MHz. This is a code/spec change, not a clock or constraint change. It is the
prerequisite for training nets larger than XOR on this open flow (where seed-search
runs out — a 62-step net does not stabilise in any seed).

## Reproducibility

Expand Down
Loading