Ch443f: coherent Gray readiness CDC + qualified scanout underflow detector
Harden the LPDDR scanout underflow diagnostic (Codex direction). Keeps the Ch443e 4-buffer + lead-2 fix; adds no 5th buffer. RTL (gs_lpddr_scanout_lb): - Replace the raw-binary next_fetch readiness sync with a reset-aware GRAY code. next_fetch is monotonic between frames, so one Gray bit changes per increment; the 2-FF-synced + decoded nf_v is always a real prior frontier (monotone, burst-safe), never a torn multi-bit combination. (A plain toggle-per-change handshake dropped bursts when two increments landed in one sync window; that is why the earlier attempt under-read nf_v and false-tripped.) fs_edge_v overrides the lone multi-bit reset transient. - Qualify the underflow: only a miss persisting >= QUAL_CYCLES (4) sets sticky underflow. uf_pmax_q records the longest streak and uf_qual_q whether any qualified, so a host can distinguish a 1-cycle CDC lag from a real late row. - Atomic snapshot: scan_y/nf_v/pmax/causes/vphase/line_valid all latched the same video cycle on the first qualified miss. ABI: 0x120 adds [15:12]=live pmax (2-FF synced via scan_diag_pmax_i). 0x124 [29:20] now carries pmax-at-capture (was nf_s0). Bridge dst reg kept 10-bit. SDC: scanout diag bundle source count 37 -> 31 (nf_s0[10] -> pmax[4]); new async-in cut + max_skew/net_delay for the next_fetch Gray CDC; stage-0 cut for the live pmax sync. Tests: new tb_gs_scanout_cdc_qual (async-clock focused: no false event from the readiness transition or ordinary sync latency; sub-QUAL transient does not qualify; genuine late row qualifies with a self-consistent atomic snapshot; frame reset + mod-4 reuse re-arm the detector). tb_gs_scanout_diag updated for the pmax field. Tie off scan_diag_pmax_i (+ pre-existing clut_* gap from the fog baseline) in the four .* bridge/integration TBs. Regressions green: scanout (cdc_qual, binomial_lookahead, diag, restart, lpddr_scanout_lb x3), regbuf (r/aw/w), bridge + 3 pad integration TBs, and the f52 top-level golden FB (Z 0/307200, COLOR 0/245760 mismatch, drops=0). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1299,6 +1299,15 @@ tb_gs_scanout_diag: dirs
|
||||
@echo "=== run tb_gs_scanout_diag ==="
|
||||
@cd $(TRACE_DIR) && $(VVP) $(BUILD_DIR)/tb_gs_scanout_diag.vvp
|
||||
|
||||
tb_gs_scanout_cdc_qual: dirs
|
||||
@echo "=== build tb_gs_scanout_cdc_qual ==="
|
||||
$(IVERILOG) $(IVERILOG_FLGS) \
|
||||
-o $(BUILD_DIR)/tb_gs_scanout_cdc_qual.vvp \
|
||||
-s tb_gs_scanout_cdc_qual \
|
||||
$(RTL_SRCS) $(TB_ROOT)/gif_gs/tb_gs_scanout_cdc_qual.sv
|
||||
@echo "=== run tb_gs_scanout_cdc_qual ==="
|
||||
@cd $(TRACE_DIR) && $(VVP) $(BUILD_DIR)/tb_gs_scanout_cdc_qual.vvp
|
||||
|
||||
tb_gs_scanout_restart: dirs
|
||||
@echo "=== build tb_gs_scanout_restart ==="
|
||||
$(IVERILOG) $(IVERILOG_FLGS) \
|
||||
@@ -6321,6 +6330,7 @@ run: tb_top_psmct32_sh3_zs640b24_cap tb_top_psmct32_sh3_zint640b24
|
||||
|
||||
.PHONY: tb_top_psmct32_sh3_zs640c24c_cap tb_top_psmct32_sh3_zint640c24c sh3_zs640c24c_fixture sh3_zs640motionabc_bootlet
|
||||
run: tb_top_psmct32_sh3_zs640c24c_cap tb_top_psmct32_sh3_zint640c24c tb_gs_axi_w_regbuf tb_gs_axi_aw_regbuf tb_gs_axi_r_regbuf
|
||||
run: tb_gs_lpddr_scanout_lb tb_gs_scanout_binomial_lookahead tb_gs_scanout_diag tb_gs_scanout_restart tb_gs_scanout_cdc_qual
|
||||
|
||||
run: tb_ee_fetch tb_gs tb_intc tb_platform_video tb_bgcolor_via_dma tb_sif_mailbox \
|
||||
tb_sif_command_echo tb_sif_command_echo_rearm tb_sif_negative_path \
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
// ============================================================================
|
||||
// tb_gs_scanout_cdc_qual — Ch443f
|
||||
//
|
||||
// Focused async-clock test for the COHERENT + QUALIFIED underflow detector in
|
||||
// gs_lpddr_scanout_lb. It targets exactly the four properties Codex required of
|
||||
// the hardened diagnostic, using deliberately non-commensurate axi/video clocks
|
||||
// so the readiness (next_fetch) row-commit lands at every phase relative to the
|
||||
// video sampling edge:
|
||||
//
|
||||
// §A No false event from the binary transition + no false event from ordinary
|
||||
// synchronizer latency. A healthy phase-swept display commits many rows at
|
||||
// walking phases; the coherent nf_v handshake must never latch a value the
|
||||
// committed frontier never held (nf_v <= next_fetch, monotone), and NO
|
||||
// qualified underflow may assert (underflow==0, diag_valid==0, uf_qual==0)
|
||||
// even though the 2-FF sync lags next_fetch.
|
||||
//
|
||||
// §B1 A sub-QUAL miss (persistence 3 > the ~2-cycle sync latency, < QUAL=4) is
|
||||
// NOT a qualified event: underflow stays 0, diag_valid stays 0, but the
|
||||
// live uf_pmax records 3 so a host can SEE the transient. This is the
|
||||
// direct proof that ordinary synchronizer latency cannot fabricate an event.
|
||||
//
|
||||
// §B2 A genuinely late row (persistence >> QUAL) DOES produce a qualified event:
|
||||
// underflow==1, diag_valid==1, uf_qual==1, and the atomic snapshot is
|
||||
// self-consistent (diag_scan_y >= diag_nf_v, both frozen the same cycle,
|
||||
// diag_pmax >= QUAL).
|
||||
//
|
||||
// §C Frame reset + modulo-4 buffer reuse remain correct: frame_start clears the
|
||||
// detector (nf_v->VSTART, persistence/qual/valid=0) and a full healthy sweep
|
||||
// spanning > 4 source rows (all 4 rotating buffers reused) reproduces the
|
||||
// binomial 3x3 output exactly with no underflow.
|
||||
//
|
||||
// Vehicle: BINOMIAL_3X3_FILTER=1 (NBUF=4, lookahead active), stretch OFF so
|
||||
// scan_y == pixel_y and the fetch frontier can be positioned exactly. The
|
||||
// detector logic under test (coherent nf_v, persistence, qualification, atomic
|
||||
// capture) is stretch-agnostic; this isolates the CDC without stretch bookkeeping.
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module tb_gs_scanout_cdc_qual;
|
||||
localparam int SRC_W=32, N_ROWS=48, ROW_BEATS=4, STRIDE=SRC_W*4, VSTART=0;
|
||||
localparam int QUAL=4; // must match RTL QUAL_CYCLES
|
||||
|
||||
// Deliberately non-commensurate clocks: 6.0 ns vs 13.0 ns (ratio 13/6) so the
|
||||
// axi-domain next_fetch Gray commit crosses the video sampling edge at walking phases.
|
||||
logic axi_clk=0, video_clk=0, rst_n=0, enable=0;
|
||||
always #3 axi_clk = ~axi_clk; // 6.0 ns
|
||||
always #6.5 video_clk = ~video_clk; // 13.0 ns
|
||||
|
||||
logic frame_start=0, in_window=0;
|
||||
logic [11:0] pixel_x=0, pixel_y=0;
|
||||
wire [7:0] r,g,b;
|
||||
wire line_valid, underflow;
|
||||
wire [31:0] rd_errs;
|
||||
wire [29:0] araddr; wire [1:0] arburst; wire [6:0] arid;
|
||||
wire [7:0] arlen; wire [2:0] arsize; wire arvalid, rready;
|
||||
logic arready=0, rvalid=0, rlast=0;
|
||||
logic [255:0] rdata=0; logic [1:0] rresp=0;
|
||||
|
||||
logic [255:0] mem [0:N_ROWS*ROW_BEATS-1];
|
||||
initial begin
|
||||
for (int beat=0; beat<N_ROWS*ROW_BEATS; beat++) mem[beat]='0;
|
||||
for (int y=0; y<N_ROWS; y++)
|
||||
for (int x=0; x<SRC_W; x++)
|
||||
mem[y*ROW_BEATS + (x>>3)][(x&7)*32 +: 32] = {8'hff, 8'(8'h80+x+y), 8'(y), 8'(x)};
|
||||
end
|
||||
|
||||
gs_lpddr_scanout_lb #(
|
||||
.FB_BASE(30'd0), .STRIDE_BYTES(STRIDE), .ROW_BEATS(ROW_BEATS),
|
||||
.N_ROWS(N_ROWS), .PSMCT32(1'b1), .H_STRETCH_5_TO_4(1'b0),
|
||||
.V_SOURCE_START(VSTART), .V_STRETCH_15_TO_14(1'b0),
|
||||
.V_LINEAR_FILTER(1'b0), .H_LINEAR_FILTER(1'b0),
|
||||
.H_SOURCE_PIXELS(SRC_W), .BINOMIAL_3X3_FILTER(1'b1)
|
||||
) dut (
|
||||
.axi_clk(axi_clk), .axi_rst_n(rst_n), .enable(enable),
|
||||
.video_clk(video_clk), .frame_start(frame_start),
|
||||
.pixel_x(pixel_x), .pixel_y(pixel_y), .in_window(in_window),
|
||||
.r(r), .g(g), .b(b), .line_valid(line_valid), .underflow(underflow),
|
||||
.rd_errs(rd_errs), .araddr(araddr), .arburst(arburst), .arid(arid),
|
||||
.arlen(arlen), .arsize(arsize), .arvalid(arvalid), .arready(arready),
|
||||
.rdata(rdata), .rresp(rresp), .rlast(rlast), .rvalid(rvalid), .rready(rready)
|
||||
);
|
||||
|
||||
// ---- EMIF responder with TB-controlled starvation. starve=1 -> no AR accept,
|
||||
// no new R (fetch freezes -> next_fetch stops advancing). ----
|
||||
logic starve=0;
|
||||
localparam int LAT=3;
|
||||
typedef enum logic [1:0] {S_AR, S_WAIT, S_R} state_t;
|
||||
state_t state=S_AR;
|
||||
localparam int MEM_BEAT_BITS=$clog2(N_ROWS*ROW_BEATS);
|
||||
logic [MEM_BEAT_BITS-1:0] beat_q; int wait_c=0;
|
||||
always_ff @(posedge axi_clk) begin
|
||||
arready <= 1'b0;
|
||||
if (!rst_n) begin state<=S_AR; rvalid<=1'b0; rlast<=1'b0; wait_c<=0; end
|
||||
else case (state)
|
||||
S_AR: if (arvalid && !arready && !starve) begin
|
||||
beat_q<=araddr[MEM_BEAT_BITS+4:5]; arready<=1'b1; wait_c<=LAT; state<=S_WAIT;
|
||||
end
|
||||
S_WAIT: if (wait_c>0) wait_c<=wait_c-1;
|
||||
else begin rdata<=mem[beat_q]; rresp<=2'b00; rlast<=1'b1; rvalid<=1'b1; state<=S_R; end
|
||||
S_R: if (rready && rvalid) begin rvalid<=1'b0; rlast<=1'b0; state<=S_AR; end
|
||||
endcase
|
||||
end
|
||||
|
||||
// (pixel-exact binomial 3x3 reproduction across mod-4 wrap is owned by
|
||||
// tb_gs_scanout_binomial_lookahead; this TB isolates the readiness CDC +
|
||||
// qualification, so no per-pixel oracle is needed here.)
|
||||
|
||||
// ---- global invariants (video domain) ----
|
||||
int errors=0;
|
||||
logic expect_uf=0; // 0 while a qualified underflow is NOT permitted
|
||||
logic coh_en=0; // enable the nf_v coherence invariant (steady-state windows only)
|
||||
int commit_events=0; // # of next_fetch changes observed (phase-swept commits)
|
||||
logic [$clog2(N_ROWS):0] nf_prev=0; logic nf_seen=0;
|
||||
logic [$clog2(N_ROWS):0] fetch_prev=0;
|
||||
task automatic chk(input string label, input logic cond);
|
||||
if (!cond) begin $error("[cdc_qual] FAIL: %s", label); errors++; end
|
||||
else $display("[cdc_qual] ok : %s", label);
|
||||
endtask
|
||||
|
||||
// suppress the coherence invariant for a few cycles after a frame reset: the
|
||||
// Gray sync legitimately holds the (large, SAFE) pre-reset frontier for ~2 video
|
||||
// cycles after next_fetch drops to VSTART — that is the benign reset transient
|
||||
// fs_edge_v overrides, NOT a tear. Steady-state (guard expired) nf_v <= next_fetch
|
||||
// must hold; a real torn decode would surface there.
|
||||
int fs_guard=0;
|
||||
always @(posedge video_clk) if (rst_n && enable) begin
|
||||
if (dut.fs_edge_v) fs_guard <= 4; else if (fs_guard>0) fs_guard <= fs_guard-1;
|
||||
// coherence invariant (steady state): nf_v may never exceed the committed
|
||||
// frontier nor run below VSTART. A torn Gray decode would surface here.
|
||||
if (coh_en && !dut.fs_edge_v && fs_guard==0) begin
|
||||
if (dut.nf_v > dut.next_fetch) begin
|
||||
$error("[cdc_qual] FAIL: nf_v %0d > committed next_fetch %0d (incoherent latch)",
|
||||
dut.nf_v, dut.next_fetch); errors++;
|
||||
end
|
||||
if (dut.nf_v < ($clog2(N_ROWS)+1)'(VSTART)) begin
|
||||
$error("[cdc_qual] FAIL: nf_v %0d < VSTART", dut.nf_v); errors++;
|
||||
end
|
||||
end
|
||||
// qualified-underflow gate
|
||||
if (underflow && !expect_uf) begin
|
||||
$error("[cdc_qual] FAIL: qualified underflow asserted when not permitted (scan_y=%0d nf_v=%0d)",
|
||||
dut.scan_y, dut.nf_v); errors++;
|
||||
end
|
||||
// count committed-frontier changes (phase coverage)
|
||||
if (nf_seen && dut.next_fetch !== fetch_prev) commit_events++;
|
||||
fetch_prev <= dut.next_fetch; nf_prev <= dut.nf_v; nf_seen <= 1'b1;
|
||||
end
|
||||
|
||||
// ---- step display one source row, slowly enough that the modeled EMIF keeps
|
||||
// its lead-2 prefetch (fetch ~1 row / 6 axi cycles; display 1 row / 8 video
|
||||
// cycles -> fetch stays ahead). A row advance triggers exactly one commit. ----
|
||||
task automatic step_row(input int y);
|
||||
pixel_y = 12'(y); pixel_x = 12'd0; in_window = 1'b1;
|
||||
repeat (20) @(posedge video_clk);
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
// ---- reset / enable / prime ----
|
||||
repeat(8) @(posedge axi_clk); rst_n=1; enable=1;
|
||||
@(negedge video_clk); frame_start=1; repeat(3) @(posedge video_clk);
|
||||
@(negedge video_clk); frame_start=0;
|
||||
repeat(120) @(posedge axi_clk); // prime lead-2 buffers before any display
|
||||
|
||||
// ================= §A healthy phase-swept display =================
|
||||
expect_uf = 0; coh_en = 1; // steady-state coherence invariant active here
|
||||
for (int y=0; y<24; y++) step_row(y);
|
||||
@(negedge video_clk); in_window=0; repeat(10) @(posedge video_clk);
|
||||
coh_en = 0;
|
||||
chk("A: no qualified underflow across healthy phase sweep", !underflow);
|
||||
chk("A: diag_valid stays 0 (no real miss)", dut.diag_valid_q===1'b0);
|
||||
chk("A: uf_qual stays 0", dut.uf_qual_q===1'b0);
|
||||
chk("A: many frontier commits observed at swept phases (>=16)", commit_events>=16);
|
||||
$display("[cdc_qual] A: commit_events=%0d live_pmax=%0d", commit_events, dut.uf_pmax_q);
|
||||
|
||||
// ================= §B1 sub-QUAL transient must NOT qualify =================
|
||||
// fresh frame; advance healthily to row R, freeze fetch, jump display just
|
||||
// past the frozen frontier, hold for (QUAL-1) video cycles.
|
||||
in_window=0; pixel_y=0; @(negedge video_clk);
|
||||
frame_start=1; repeat(3) @(posedge video_clk);
|
||||
@(negedge video_clk); frame_start=0; repeat(120) @(posedge axi_clk);
|
||||
expect_uf = 0;
|
||||
for (int y=0; y<=18; y++) step_row(y);
|
||||
repeat(20) @(posedge axi_clk);
|
||||
begin
|
||||
int F3;
|
||||
starve = 1'b1; repeat(8) @(posedge video_clk); // freeze; drain in-flight + settle nf_v
|
||||
F3 = dut.next_fetch; // now-stable committed frontier
|
||||
pixel_y = 12'(F3); pixel_x = 12'd0; in_window = 1'b1; // scan_y == nf_v -> base miss
|
||||
repeat(QUAL-1) @(posedge video_clk); // persistence reaches 3 (< QUAL)
|
||||
chk("B1: sub-QUAL miss does NOT qualify (underflow==0)", !underflow);
|
||||
chk("B1: sub-QUAL miss leaves diag_valid==0", dut.diag_valid_q===1'b0);
|
||||
chk("B1: sub-QUAL miss leaves uf_qual==0", dut.uf_qual_q===1'b0);
|
||||
// a real transient was recorded (>0) but stayed below the qualification floor
|
||||
chk("B1: live pmax recorded a sub-QUAL transient (0<pmax<QUAL)",
|
||||
dut.uf_pmax_q>4'd0 && dut.uf_pmax_q<4'(QUAL));
|
||||
$display("[cdc_qual] B1: uf_pmax=%0d underflow=%0b (F3 frontier=%0d)",
|
||||
dut.uf_pmax_q, underflow, F3);
|
||||
starve = 1'b0; // relieve before it can qualify
|
||||
@(negedge video_clk); in_window=0; repeat(20) @(posedge video_clk);
|
||||
end
|
||||
|
||||
// ================= §B2 genuine late row MUST qualify =================
|
||||
in_window=0; pixel_y=0; @(negedge video_clk);
|
||||
frame_start=1; repeat(3) @(posedge video_clk);
|
||||
@(negedge video_clk); frame_start=0; repeat(120) @(posedge axi_clk);
|
||||
expect_uf = 1; // a qualified event is now the INTENDED outcome
|
||||
for (int y=0; y<=18; y++) step_row(y);
|
||||
repeat(20) @(posedge axi_clk);
|
||||
begin
|
||||
int F2;
|
||||
starve = 1'b1; repeat(8) @(posedge video_clk);
|
||||
F2 = dut.next_fetch;
|
||||
pixel_y = 12'(F2); pixel_x = 12'd0; in_window = 1'b1;
|
||||
repeat(10) @(posedge video_clk); // persistence >> QUAL
|
||||
chk("B2: genuine late row qualifies (underflow==1)", underflow===1'b1);
|
||||
chk("B2: genuine late row sets uf_qual==1", dut.uf_qual_q===1'b1);
|
||||
chk("B2: diag captured (diag_valid==1)", dut.diag_valid_q===1'b1);
|
||||
chk("B2: atomic snapshot self-consistent (scan_y >= nf_v)",
|
||||
dut.diag_scan_y_q >= dut.diag_nf_v_q);
|
||||
chk("B2: snapshot scan_y == frozen display row", dut.diag_scan_y_q===($clog2(N_ROWS)+1)'(F2));
|
||||
chk("B2: snapshot nf_v == frozen frontier", dut.diag_nf_v_q===($clog2(N_ROWS)+1)'(F2));
|
||||
chk("B2: captured pmax >= QUAL", dut.diag_pmax_q>=4'(QUAL));
|
||||
chk("B2: live pmax kept growing past capture", dut.uf_pmax_q>dut.diag_pmax_q);
|
||||
end
|
||||
|
||||
// ================= §C frame reset clears + mod-4 reuse correct =================
|
||||
starve = 1'b0;
|
||||
@(negedge video_clk); in_window=0; pixel_y=0; // disp_row->0 so fetch reloads rows 0..3
|
||||
@(negedge video_clk); frame_start=1; repeat(3) @(posedge video_clk);
|
||||
@(negedge video_clk); frame_start=0;
|
||||
chk("C: frame reset cleared diag_valid", dut.diag_valid_q===1'b0);
|
||||
chk("C: frame reset cleared uf_qual", dut.uf_qual_q===1'b0);
|
||||
chk("C: frame reset cleared underflow", underflow===1'b0);
|
||||
chk("C: frame reset realigned nf_v to VSTART", dut.nf_v===($clog2(N_ROWS)+1)'(VSTART));
|
||||
repeat(160) @(posedge axi_clk); // prime lead-2 buffers 0..3 before display (binomial needs r+1)
|
||||
|
||||
// Healthy display spanning 12 source rows (mod-4 rotation reused 3x) at the
|
||||
// proven step_row pace. This proves the DETECTOR re-arms correctly across a
|
||||
// frame reset and does NOT false-trip while the 4 buffers are recycled: no
|
||||
// qualified underflow, diag_valid stays 0, and the coherence invariant holds.
|
||||
// (Pixel-exact binomial 3x3 reproduction across the mod-4 wrap is owned by
|
||||
// tb_gs_scanout_binomial_lookahead; not re-litigated here.)
|
||||
expect_uf = 0; coh_en = 1;
|
||||
for (int y=0; y<12; y++) begin
|
||||
step_row(y);
|
||||
if (underflow) begin $error("[cdc_qual] C: false underflow at row %0d (nf_v=%0d next_fetch=%0d)",
|
||||
y, dut.nf_v, dut.next_fetch); errors++; end
|
||||
end
|
||||
@(negedge video_clk); in_window=0; repeat(10) @(posedge video_clk);
|
||||
chk("C: no qualified underflow across reset + mod-4 buffer reuse", !underflow);
|
||||
chk("C: uf_qual stayed 0 across reset+reuse", dut.uf_qual_q===1'b0);
|
||||
chk("C: diag_valid stayed 0 across reset+reuse", dut.diag_valid_q===1'b0);
|
||||
chk("C: live pmax stayed sub-QUAL across reset+reuse", dut.uf_pmax_q<4'(QUAL));
|
||||
|
||||
if (errors==0) $display("[tb_gs_scanout_cdc_qual] PASS");
|
||||
else $display("[tb_gs_scanout_cdc_qual] FAIL (errors=%0d)", errors);
|
||||
$finish;
|
||||
end
|
||||
initial begin #6_000_000; $display("[tb_gs_scanout_cdc_qual] TIMEOUT"); $finish; end
|
||||
endmodule
|
||||
@@ -229,7 +229,7 @@ module tb_gs_scanout_diag;
|
||||
chk("P1 line_valid=0", st[5]===1'b0);
|
||||
chk("P1 snap scan_y=0", fst[9:0]===10'd0);
|
||||
chk("P1 snap nf_v=0", fst[19:10]===10'd0);
|
||||
chk("P1 snap nf_s0=0", fst[29:20]===10'd0);
|
||||
chk("P1 snap pmax qualified (>=QUAL)", fst[29:20] >= 10'd4);
|
||||
|
||||
// snapshot stability: later misses on a different row must NOT overwrite the first snapshot
|
||||
@(posedge video_clk) begin pixel_y<=12'd2; end
|
||||
@@ -278,7 +278,7 @@ module tb_gs_scanout_diag;
|
||||
chk("P5 DUT-B captured", b_diag_valid===1'b1);
|
||||
chk("P5 scan_y=VSS(32)", b_diag_first[9:0]===10'd32); // NOT 0: source row 32
|
||||
chk("P5 nf_v=32", b_diag_first[19:10]===10'd32);
|
||||
chk("P5 nf_s0=32", b_diag_first[29:20]===10'd32);
|
||||
chk("P5 pmax qualified (>=QUAL)", b_diag_first[29:20] >= 10'd4);
|
||||
chk("P5 base=1", b_diag_stat[0]===1'b1);
|
||||
chk("P5 line_valid=0", b_diag_stat[2]===1'b0);
|
||||
// cause/phase packing: outputs must byte-map the internal capture regs
|
||||
@@ -288,7 +288,7 @@ module tb_gs_scanout_diag;
|
||||
chk("P5 pack vphase field", b_diag_stat[6:3] === dut_b.diag_vphase_q);
|
||||
chk("P5 pack scan_y field", b_diag_first[9:0] === 10'(dut_b.diag_scan_y_q));
|
||||
chk("P5 pack nf_v field", b_diag_first[19:10] === 10'(dut_b.diag_nf_v_q));
|
||||
chk("P5 pack nf_s0 field", b_diag_first[29:20] === 10'(dut_b.diag_nf_s0_q));
|
||||
chk("P5 pack pmax field", b_diag_first[29:20] === 10'(dut_b.diag_pmax_q));
|
||||
|
||||
// -------- coverage: the fs_edge-coincident-miss case was actually exercised --------
|
||||
chk("M1 coverage: fs_edge coincident with miss observed", cov_fsedge_miss===1'b1);
|
||||
|
||||
@@ -176,6 +176,11 @@ module tb_bridge_iop_pad_input;
|
||||
logic scan_diag_uf_i = 1'b0, scan_diag_rderr_nz_i = 1'b0, scan_diag_valid_i = 1'b0;
|
||||
logic [29:0] scan_diag_first_i = 30'd0;
|
||||
logic [6:0] scan_diag_stat_i = 7'd0;
|
||||
logic [3:0] scan_diag_pmax_i = 4'd0;
|
||||
// Pre-existing clut_stage/commit bridge outputs (fog-baseline ba74bbd); nets so .* binds.
|
||||
wire [7:0] clut_stage_waddr_o; wire [31:0] clut_stage_wdata_o; wire clut_stage_we_o;
|
||||
wire clut_commit_tgl_o; wire [31:0] clut_expected_crc_o;
|
||||
logic clut_busy_i = 1'b0, clut_done_tgl_i = 1'b0; logic [31:0] clut_crc_i = 32'd0;
|
||||
ps2_hps_bridge u_bridge (
|
||||
.clk (bclk),
|
||||
.reset_n (breset_n),
|
||||
|
||||
@@ -256,6 +256,11 @@ module tb_ee_pad_buffer_branch;
|
||||
logic scan_diag_uf_i = 1'b0, scan_diag_rderr_nz_i = 1'b0, scan_diag_valid_i = 1'b0;
|
||||
logic [29:0] scan_diag_first_i = 30'd0;
|
||||
logic [6:0] scan_diag_stat_i = 7'd0;
|
||||
logic [3:0] scan_diag_pmax_i = 4'd0;
|
||||
// Pre-existing clut_stage/commit bridge outputs (fog-baseline ba74bbd); nets so .* binds.
|
||||
wire [7:0] clut_stage_waddr_o; wire [31:0] clut_stage_wdata_o; wire clut_stage_we_o;
|
||||
wire clut_commit_tgl_o; wire [31:0] clut_expected_crc_o;
|
||||
logic clut_busy_i = 1'b0, clut_done_tgl_i = 1'b0; logic [31:0] clut_crc_i = 32'd0;
|
||||
ps2_hps_bridge u_bridge (
|
||||
.clk (bclk),
|
||||
.reset_n (breset_n),
|
||||
|
||||
@@ -207,6 +207,11 @@ module tb_pad_state_via_sif_to_ee;
|
||||
logic scan_diag_uf_i = 1'b0, scan_diag_rderr_nz_i = 1'b0, scan_diag_valid_i = 1'b0;
|
||||
logic [29:0] scan_diag_first_i = 30'd0;
|
||||
logic [6:0] scan_diag_stat_i = 7'd0;
|
||||
logic [3:0] scan_diag_pmax_i = 4'd0;
|
||||
// Pre-existing clut_stage/commit bridge outputs (fog-baseline ba74bbd); nets so .* binds.
|
||||
wire [7:0] clut_stage_waddr_o; wire [31:0] clut_stage_wdata_o; wire clut_stage_we_o;
|
||||
wire clut_commit_tgl_o; wire [31:0] clut_expected_crc_o;
|
||||
logic clut_busy_i = 1'b0, clut_done_tgl_i = 1'b0; logic [31:0] clut_crc_i = 32'd0;
|
||||
ps2_hps_bridge u_bridge (
|
||||
.clk (bclk),
|
||||
.reset_n (breset_n),
|
||||
|
||||
@@ -219,6 +219,7 @@ module tb_ps2_hps_bridge;
|
||||
logic scan_diag_uf_i = 1'b0, scan_diag_rderr_nz_i = 1'b0, scan_diag_valid_i = 1'b0;
|
||||
logic [29:0] scan_diag_first_i = 30'd0;
|
||||
logic [6:0] scan_diag_stat_i = 7'd0;
|
||||
logic [3:0] scan_diag_pmax_i = 4'd0;
|
||||
logic clear_done_i = 1'b0; // Ch357 — persistent-Z preclear ack (driven by the Ch357 status test)
|
||||
logic [31:0] frag_drops_i = 32'd0; // Ch357 — persistent-Z drop count (driven by the Ch357 status test)
|
||||
// Ch367 -- runtime CLUT staging ports (the data-bank CDC itself is
|
||||
|
||||
Reference in New Issue
Block a user