Ch442 review fixes: fs_edge parity, dest snap_valid, sync attrs + SDC
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>
This commit is contained in:
@@ -798,7 +798,11 @@ module gs_lpddr_scanout_lb #(
|
||||
// above) as combinational wires so the capture can name WHICH sub-cause fired. These
|
||||
// wires and the registers below drive ONLY the diag_* outputs — never the fetch FSM,
|
||||
// the pixel path, arbitration, or underflow_v. The existing latch block is untouched.
|
||||
wire uf_in_range = enable && in_window && (scan_y < ($clog2(N_ROWS)+1)'(N_ROWS));
|
||||
// NOTE the `!fs_edge_v` term: the sticky latch gives frame-start CLEAR priority
|
||||
// (`if (!enable || fs_edge_v) ... else if (predicate)`), so on an fs_edge_v cycle it
|
||||
// never sets. Mirror that exactly here or the diagnostic could capture a frame-start
|
||||
// coincident miss the real latch suppresses.
|
||||
wire uf_in_range = enable && !fs_edge_v && in_window && (scan_y < ($clog2(N_ROWS)+1)'(N_ROWS));
|
||||
wire uf_base_cond = uf_in_range && (scan_y >= nf_v);
|
||||
wire uf_look_cond = uf_in_range &&
|
||||
(BINOMIAL_3X3_FILTER ||
|
||||
@@ -814,9 +818,11 @@ module gs_lpddr_scanout_lb #(
|
||||
// so it names the first failure of the whole enabled session. The bundled snapshot
|
||||
// ({nf_s0,nf_v,scan_y} + cause/line_valid/vphase) stays stable while diag_valid is high,
|
||||
// so the bridge can transfer it coherently with a single synchronized valid.
|
||||
logic diag_valid_q, diag_base_q, diag_look_q, diag_lv_q;
|
||||
logic [3:0] diag_vphase_q;
|
||||
logic [$clog2(N_ROWS):0] diag_scan_y_q, diag_nf_v_q, diag_nf_s0_q;
|
||||
// (* preserve *): keep these capture regs as named keepers so the SDC bundled-data
|
||||
// hold-false/max-skew/net-delay constraint can bind to them (they must not be merged).
|
||||
(* preserve *) logic diag_valid_q, diag_base_q, diag_look_q, diag_lv_q;
|
||||
(* preserve *) logic [3:0] diag_vphase_q;
|
||||
(* preserve *) logic [$clog2(N_ROWS):0] diag_scan_y_q, diag_nf_v_q, diag_nf_s0_q;
|
||||
always_ff @(posedge video_clk) begin
|
||||
line_valid_vsync <= {line_valid_vsync[0], line_valid};
|
||||
if (!enable) begin
|
||||
|
||||
@@ -651,11 +651,19 @@ module ps2_hps_bridge (
|
||||
assign lpddr_video_src_o = lpddr_video_src_q;
|
||||
assign lpddr_scanout_lb_o = lpddr_scanout_lb_q;
|
||||
// Ch442 A+B diagnostic — independently synced live flags + bundled-data snapshot capture.
|
||||
logic [1:0] scan_diag_uf_sync, scan_diag_rderr_sync;
|
||||
// Forced-synchronizer + dont_merge/preserve on each async chain so Quartus identifies the
|
||||
// synchronizers (MTBF) and never retimes/merges them; the SDC cuts the async into stage 0.
|
||||
(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION FORCED", dont_merge, preserve *)
|
||||
logic [1:0] scan_diag_uf_sync;
|
||||
(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION FORCED", dont_merge, preserve *)
|
||||
logic [1:0] scan_diag_rderr_sync;
|
||||
(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION FORCED", dont_merge, preserve *)
|
||||
logic [2:0] scan_diag_valid_sync; // 3-deep so the RISING synced edge latches the snapshot
|
||||
logic scan_diag_base_q, scan_diag_look_q, scan_diag_lv_q;
|
||||
logic [3:0] scan_diag_vphase_q;
|
||||
logic [9:0] scan_diag_scan_y_q, scan_diag_nf_v_q, scan_diag_nf_s0_q;
|
||||
logic scan_diag_snap_valid_q; // DEST valid: set WITH payload capture, cleared on synced source-valid deassert
|
||||
// (* preserve *): keep the bundle dest regs as named keepers for the SDC bundled-data constraint.
|
||||
(* preserve *) logic scan_diag_base_q, scan_diag_look_q, scan_diag_lv_q;
|
||||
(* preserve *) logic [3:0] scan_diag_vphase_q;
|
||||
(* preserve *) logic [9:0] scan_diag_scan_y_q, scan_diag_nf_v_q, scan_diag_nf_s0_q;
|
||||
// Ch322 — LPDDR write-probe + texture-cache fill registers + return-path CDC.
|
||||
logic [31:0] lpddr_wr_addr_q; // "next write" pointer (auto-increments)
|
||||
logic [31:0] lpddr_wr_addr_present_q;// the address that goes WITH the current data word
|
||||
@@ -948,7 +956,7 @@ module ps2_hps_bridge (
|
||||
// [3]cause_base(scan_y>=nf_v) [4]cause_lookahead [5]line_valid [11:8]filter vphase.
|
||||
3'h0: reg_read = {20'd0, scan_diag_vphase_q, 2'd0,
|
||||
scan_diag_lv_q, scan_diag_look_q, scan_diag_base_q,
|
||||
scan_diag_rderr_sync[1], scan_diag_uf_sync[1], scan_diag_valid_sync[1]};
|
||||
scan_diag_rderr_sync[1], scan_diag_uf_sync[1], scan_diag_snap_valid_q};
|
||||
// 0x124 SCAN_DIAG_FIRST: [9:0]scan_y [19:10]nf_v [29:20]nf_s0.
|
||||
3'h1: reg_read = {2'd0, scan_diag_nf_s0_q, scan_diag_nf_v_q, scan_diag_scan_y_q};
|
||||
default: reg_read = 32'd0;
|
||||
@@ -1115,6 +1123,7 @@ module ps2_hps_bridge (
|
||||
scan_diag_uf_sync <= 2'b00;
|
||||
scan_diag_rderr_sync <= 2'b00;
|
||||
scan_diag_valid_sync <= 3'b000;
|
||||
scan_diag_snap_valid_q<= 1'b0;
|
||||
scan_diag_base_q <= 1'b0;
|
||||
scan_diag_look_q <= 1'b0;
|
||||
scan_diag_lv_q <= 1'b0;
|
||||
@@ -1169,6 +1178,9 @@ module ps2_hps_bridge (
|
||||
scan_diag_look_q <= scan_diag_stat_i[1];
|
||||
scan_diag_lv_q <= scan_diag_stat_i[2];
|
||||
scan_diag_vphase_q <= scan_diag_stat_i[6:3];
|
||||
scan_diag_snap_valid_q <= 1'b1; // valid asserts ON the payload-capture edge, never before
|
||||
end else if (!scan_diag_valid_sync[1]) begin
|
||||
scan_diag_snap_valid_q <= 1'b0; // clear once the synced source valid has deasserted (!enable)
|
||||
end
|
||||
// Ch322 — texture-fill / write-probe status sync (emif_clk -> clk).
|
||||
tex_fill_done_sync <= {tex_fill_done_sync[0], tex_fill_done_i};
|
||||
|
||||
Reference in New Issue
Block a user