Files
retroDE_ps2/docs/ch420_request_fifo_read_address_prefit.md
T
thejayman77 ba74bbd5aa Snapshot: fog implementation + fidelity tooling baseline (pre bilinear-clamp fix)
Per-vertex GS fog end-to-end (gs_stub emit incl. persp_emit5, gs_prim_list_feeder
XYZ2->XYZF2 on PRIM.FGE, gs_make_sh3_scheduler_fixture.py F/FGE packing), new fog
TBs, fidelity attribution tooling. Functional baseline before removing the dead
bilinear lerp8 clamps (Codex: 161-node comb loop -> -0.042ns setup fail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 19:56:46 -04:00

3.4 KiB

Ch420 — request FIFO dedicated read-address stage (prefit)

Trigger

Ch419 removed both intended timing families and reduced setup from -0.388 ns / -7.218 ns to -0.115 ns / -1.150 ns. Its completed fit exposed one uniform remaining family: request FIFO rbin[6] directly driving the wide banked RAM's portbaddr[6] network.

This is not a new functional cone and not a reason to reroll placement. The paths have zero logic levels, fan-out 713, and spend 2.892 ns of 3.192 ns in one interconnect route.

Structural cut

Registered-read mode in gs_async_fifo now has a dedicated RAM-facing raddr_q stage, marked dont_merge, preserve so it cannot collapse back into the binary CDC pointer.

raddr_q captures rbin_nxt while the synchronous RAM reads the prior raddr_q. Before each edge, raddr_q equals the current head address, so the returned entry and accepted-pop latency are unchanged for isolated and back-to-back reads. The added boundary only separates pointer/empty logic from the physical address fan-out and gives the fitter a placeable/duplicable RAM- local launch register.

The stage intentionally has no reset or clock enable. The FIFO remains empty for multiple read clocks while the write pointer crosses its two synchronizer flops, so the address has settled to zero before any legal pop. Avoiding reset and enable prevents recreating the prior high-fanout RAM-control failures.

Prefit verification

  • async FIFO randomized CDC test: 3,284 writes and reads exact, no duplicate or drop;
  • Z/color emit: 1,500 fragments across three epochs exact, including directed ZTST=ALWAYS;
  • concurrent scanout/reload/probe: 16,384 pixels exact;
  • full 283-epoch production-control replay: PASS;
  • 1,177,489 fragments fed, 984,845 passed Z, zero drops/errors;
  • final Z mismatch 0 / 307,200 and color mismatch 0 / 235,963;
  • framebuffer SHA-256 remains exactly a88f1f6c926dd0db2b72ae2873c399e7dc5666f8003190184c34d360b13a5f44;
  • relevant git diff --check: PASS.

Owner fit gate

Ready for one owner-controlled Quartus 26.1 GUI compile. Acceptance requires:

  • the direct rbin -> request RAM portbaddr family is absent, not merely exchanged for an equally long rbin -> raddr_q or raddr_q -> portbaddr family;
  • setup, hold, recovery, removal, and minimum pulse all close;
  • request FIFO RAM inference and the 336 / 358 RAM-block budget remain intact.

Do not deploy the RBF until this report is clean. After timing acceptance, run the already-staged Ch419 283-epoch board scene and require exact equality with the production framebuffer hash above.

Owner fit result — 2026-07-18 11:59

The fitter preserved raddr_q, and the direct rbin -> portbaddr family is absent from the violated paths. Setup did not close:

  • WNS -0.273 ns, TNS -1.613 ns;
  • hold 0.000 ns; all other timing checks clean;
  • 38,227 ALMs and 336 / 358 RAM blocks.

The ten reported violations are the next request boundary, not either half of the new address stage. They launch at the request RAM output and terminate at the two packet-type validity registers:

u_zc_emit|u_req|mem...portbdataout
  -> req_stage_frag_valid / req_stage_marker_valid

The worst path is 3.443 ns, with the RAM output uTco accounting for 1.396 ns and three downstream decode/routing levels accounting for the rest. Ch421 removes packet contents from stage-occupancy control and captures the complete packet across one explicit boundary.