Fix signoff timing: remove dead bilinear clamp (comb loop) + relax gray skew 2.0->2.5ns

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>
This commit is contained in:
2026-07-20 20:03:42 -04:00
parent ba74bbd5aa
commit dd75d78491
2 changed files with 15 additions and 8 deletions
+6 -4
View File
@@ -671,10 +671,12 @@ module gs_texture_unit #(
prod = diff * $signed({1'b0, f});
shifted = prod >>> 4;
res = $signed({14'd0, a}) + shifted;
// defensive clamp 0..255 (in-range inputs keep res in range)
if (res < 0) lerp8 = 8'd0;
else if (res > 22'sd255) lerp8 = 8'd255;
else lerp8 = res[7:0];
// For 8-bit taps a,b and f in 0..15, res = a + floor((b-a)*f/16) always lands
// in [min(a,b),max(a,b)] subset [0,255] (worst cases a=255,b=0,f=15 -> 15;
// a=1,b=0,f=15 -> 0), so the old 0/255 clamp NEVER fired. Its comparators formed
// a 161-node combinational loop (Codex STA) that failed design-clock setup by 42 ps.
// Return the computed byte directly: functionally identical, breaks the loop.
lerp8 = res[7:0];
end
endfunction