Codex review containment/observability fixes (no behavior change, no redesign):
- scanout_lb: add !fs_edge_v to the diagnostic predicate so capture
matches the underflow latch's frame-start CLEAR priority exactly
(no capture on an fs_edge cycle the real latch suppresses).
- bridge: expose a destination snap_valid_q as 0x120[0] — set ON the
payload-capture edge, cleared on synced source-valid deassert — so
valid never leads the bundle by a cycle (was the middle sync stage).
- bridge: forced-synchronizer (SYNCHRONIZER_IDENTIFICATION FORCED) +
dont_merge/preserve on the underflow/read-error/valid chains;
preserve on the bundle capture regs (both domains).
- SDC: stage-0 async cuts on the three sync[0] inputs + the 37-bit
stable bundle hold-false-path + 2ns max_skew + 2ns net_delay, with
fail-closed src==37 / dst!=0 count checks (tile_ram_cdc idiom).
- tb_gs_scanout_diag: +fs_edge-suppression monitor (with coverage that
the coincidence is exercised), +valid-ordering monitor, +snapshot
stability after later misses, +production DUT (V_SOURCE_START=32,
stretch, linear) proving cold-start scan_y=32, +cause/phase packing.
32/32 checks pass.
- doc: production cold start is source row 32 (not 0), base+lookahead
may both assert, and one snapshot narrows but does not prove
starvation vs next_fetch CDC-lag.
Sim set all PASS: focused TB, tb_ps2_hps_bridge, scanout_lb
{binomial,hstretch,psm32_256}, complete f52 replay (FB byte-identical
Z 0/307200, COLOR 0/245760). No Quartus, board, push, or scanout
behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Read-only diagnostic to disambiguate the three causes folded into
LPDDR_STATUS[5]. bit5 (0x02C) semantics are UNCHANGED.
- gs_lpddr_scanout_lb: register a live (rd_errs!=0) flag in the emif
domain (the raw counter never crosses), and capture the FIRST raw
underflow of each video-source-enabled session as a bundled-data
snapshot (scan_y/nf_v/nf_s0 + base-vs-lookahead cause + line_valid +
vphase), held stable until !enable. The existing sticky underflow_v
latch, fetch FSM, pixel path and arbitration are untouched.
- ps2_hps_bridge: independently 2-FF sync the two split live flags;
latch the snapshot on the rising synced-valid edge (coherent bundled
data). New read-only regs 0x120 SCAN_DIAG_STATUS / 0x124
SCAN_DIAG_FIRST (window addr[37:5]==9); 0x118/0x11C reserved slots
untouched.
- top: drive 5 diag nets per scanout arm like scan_err_w; bit5 assign
unchanged.
- tb_gs_scanout_diag (new): provokes AXI RRESP error, cold-start row-0
starvation, first-failure capture + coherent bridge readback, and
clear-via-video-source-disable (17/17 checks).
- Tie off the new bridge inputs in the four .*-instantiating TBs.
Sim set all PASS: focused TB, tb_ps2_hps_bridge, scanout_lb
{binomial,hstretch,psm32_256}, and the complete f52 replay (FB
byte-identical: Z 0/307200, COLOR 0/245760; sum32=0xaad0b94d).
No fix / gray-code / persistence-filter / scanout checksum. No Quartus,
no board, no push.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Preserve the Ch441 timing/renderer board-validation evidence and the
Codex-directed follow-up:
- FB reconciliation: the Ch437 A/B dump's 8-word first-beat delta was a
non-reproducible one-time transient; 3x render+dump and 8x pure-probe
re-reads all return golden d0047677 (words 0-7 correct). Memory integrity
confirmed deterministic. (fb_reconciliation.md)
- Structural audit + A-D diagnostic proposal for LPDDR_STATUS[5]: bit5 ORs
sticky CDC-synced underflow with AXI read-errors; dump path (arid=1) is
separate from scanout/HDMI (arid=3). Instrumentation proposal only, not
implemented. (scanout_status_bit5_proposal.md)
- Raw board logs, status samples, RBF hashes, A/B FB dump, board PNG.
No RTL edits, no compile, no builds.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per Codex review of dd7ca4f (testbench only, RTL unchanged):
1. Stall check now requires d_wvalid to REMAIN asserted (catches a deassert) and
compares the COMPLETE {d_wdata,d_wstrb,d_wlast} against the held beat, not just
d_wdata.
2. Added saw_full_and_ready coverage flag (set on dut.full && d_wready) and a final
check that FAILS if the distinguishing no-bypass case was never observed.
No RTL change, no simulations, no Quartus.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cuts the lone remaining EMIF setup fail (-0.016 ns, -0.259 skew): the combinational
EMIF gen_p2c_ff -> wr_arb s2_wready -> gs_lpddr_z_rmw next-state (st, endpoint
labelled S_FILL_R via the shared encoded state register).
New gs_axi_w_regbuf: fully-registered one-entry W buffer (Option B per Codex).
- u_wready = !full ONLY (registered occupancy) -> EMIF WREADY never reaches the Z
FSM combinationally. NOT a fall-through skid (no !full-OR-d_wready term).
- Buffers WDATA/WSTRB/WLAST; downstream held stable until accepted; exactly-once.
- AW/B untouched; arbiter bready_q unchanged (still arms on real EMIF W handshake).
- z_rmw may enter B-wait once the beat is buffered -- safe: EMIF cannot return B
until the buffered beat reaches it. Single-beat writes -> the 1-beat/2-cycle
buffer rate is far above the Z write rate (no new FIFO pressure).
Wired in zc_emit between u_z W output (zi_*) and the z_w* ports. New file in sim
Makefile RTL_SRCS + synth QSF (both). Focused tb_gs_axi_w_regbuf: exactly-once/order/
payload scoreboard + no-combinational-bypass check (u_wready===!full incl. full &&
d_wready) + downstream-stable check; standalone target + in make run. Texture-cache
+0.016 paths NOT touched. No simulations or Quartus run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per Codex review of 471c1af:
1. tb_gs_async_fifo QUAD_WIDTH4 variant now runs at the PRODUCTION 93-bit width
(exercising the odd 23/23/23/24 remainder split) and drives a DISTINCT NONZERO
pattern into every width bank (seq XOR per-bank constants, bank2 inverted), with
the scoreboard checking the FULL reconstructed word. A swapped/broken/zeroed
upper bank now changes the word and trips the scoreboard. Depth-half crossing
(DEPTH=8) + wrap/full coverage retained. mk() is generate-guarded so the 32-bit
variants never elaborate the 93-bit selects.
2. Softened gs_async_fifo comments: 'same total M20K' -> EXPECTED-similar, pending
synthesis (fact -> expectation).
No simulations or Quartus run. Awaiting review before any sim.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Candidate 2 from the accepted structural proposal. Adds a QUAD_WIDTH4_READ
generate branch to gs_async_fifo: like QUADRANT_READ (2 depth x 2 width) but
splits the payload into FOUR width banks, so each preserved read-address launch
register drives ~half the M20K load (targets the 310MHz raddr_hi1_q->mem_hi1
setup family, WNS -0.103). Keeps QUADRANT_READ's proven 2:1 depth OUTPUT selector
unchanged (no new/deeper mux, per the doc's warning). Depth (8192), one-cycle
read latency, ordering, CDC, capacity, and interface are identical.
zc_emit u_req switched QUADRANT_READ->QUAD_WIDTH4_READ. New default-off param
leaves the other two gs_async_fifo instances byte-identical. TB gains a
TEST_QUAD_WIDTH4 variant + standalone Makefile target tb_gs_async_fifo_quad_width4.
NO simulations or Quartus run (per authorization). Awaiting review before any sim.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
My REQ_DEPTH=1024 reduction was wrong: I sized it off a 478 peak from a SMALL
scene. The documented full-f52 replay peak is 6,115 (adjacent frame 3,610; even
2,048 clips) — ch439_timing_convergence_prefit.md. The raster cannot backpressure,
so an undersized FIFO SILENTLY DROPS Z-requests -> corrupt frame. The -0.074 fit
was on an invalid (drop-prone) config. Restore 8,192 as the correctness baseline.
The real timing fix is a registered/skid AR-handshake boundary (arbiter s2_arready
combinational -> texcache F_AR), NOT FIFO shrinking. Packaging that for Codex review.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 8K request FIFO was 8x oversized (measured peak ~478; Codex's TB uses 1024).
Its read address routed to 8 spread M20K blocks -> 310MHz EMIF setup miss (-0.103,
MAX_FANOUT can't help: Quartus refuses to duplicate RAM-address regs, Warning 22471).
Shrinking to 1024 (2 blocks): 26.1 fit shows that path GONE, design clk +0.631->+5.693,
RAM 309/358 (86%) -> 277/358 (77%). New worst is a DIFFERENT, skew-dominated EMIF->
texcache-FSM path at -0.074 (TNS -2.032 -> -0.164).
SAFETY GATE before board load: confirm the full zsrt139f52 scene never bursts >1024
Z-requests in flight (peak I have is 478 from a smaller scene). Bump to 2048 if unsure.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fit data: AGGRESSIVE AREA gives design clk +0.631 / EMIF -0.103; global BALANCED
flipped it to EMIF +0.084 / design clk -6.119 (vert_count->texcache swung 6.7ns).
AGGRESSIVE AREA is far closer to closing, so keep it and fix the one 310MHz EMIF
miss surgically: MAX_FANOUT 3 on u_zc_emit|u_req|raddr_hi1_q forces the register
duplication Quartus asked for (TMC-20551) without the global placement disruption.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After the fog prune the design clock closed (+0.631ns) but a 310MHz EMIF path
missed by 103ps: the Z-req FIFO read-address register u_zc_emit|u_req|raddr_hi1_q[4]
fans out to 6 spread M20K blocks. Quartus flagged TMC-20551 (needs more register
duplication), which AGGRESSIVE AREA mode was suppressing. That mode is a leftover
from the resolved LAB-overflow era; utilization has headroom (ALM 85%, DSP 45%,
RAM unaffected by opt mode). BALANCED lets the fitter duplicate the address
register to close the path. QSF-only, no RTL change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fog blend's tex_color*F multiply landed on the texture->color critical path
(u_texcache RAM -> u_tex|tex_color -> mult_126 -> raster_pixel_color_q, 46ns,
-6.165ns setup). Fog is a proven no-op for the current board scene (96.5% F=255),
so pay zero for it here.
FOG_ENABLE (default 1, byte-identical fog) added to gs_stub; each fog mux gated
(FOG_ENABLE && ras_fge) so FOG_ENABLE=0 constant-folds the entire fog cone away
(multiply, FOGCOL adders, s2_fog_f/persp_fog_f5 interp). Threaded through
top_psmct32_raster_demo_bram; set FOG_ENABLE(1'b0) on the active GS_SH3_LPDDR_FB
board arm (elsif at :1086, the one the QSF profile compiles). Fog stays default-on
everywhere else.
Verified: FOG_ENABLE=1 fog TBs unchanged PASS; FOG_ENABLE=0 (new tb_gs_fog_disabled
+ board scene TB) emits raw color = pre-fog datapath; board elaborates clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two fixes for the failing STA (Codex-reviewed):
1. gs_texture_unit lerp8: remove the dead 0/255 clamp. For 8-bit taps and f in
0..15, a+floor((b-a)*f/16) is always in [0,255], so the clamp never fired -
but its comparators formed a 161-node combinational loop that failed
design-clock setup by 42 ps (tap[0][11] -> tex_cache_sel_q). Functionally
identical (tb_gs_texture_bilinear + texture TBs bit-identical PASS).
2. SDC: relax the u_zc_emit gray-code CDC max_skew 2.0 -> 2.5 ns. Post-fog
placement pushed actual skew to 2.010 ns (fails 2.0 by ~10 ps). Real ceiling
is the 3.225 ns EMIF period (one gray bit in flight); 2.5 clears the miss and
stays well under it. Documented relax of a conservative round number.
Acceptance (owner fit): no comb-loop warning, no tap->tex_cache_sel_q path,
all setup + max_skew slacks >= 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression
(272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps,
and all dump-derived textures/traces) is excluded via .gitignore and stays local.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>