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>
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>
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>
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>