diff --git a/rtl/gif_gs/gs_async_fifo.sv b/rtl/gif_gs/gs_async_fifo.sv index 5e566bc..70396de 100644 --- a/rtl/gif_gs/gs_async_fifo.sv +++ b/rtl/gif_gs/gs_async_fifo.sv @@ -31,8 +31,9 @@ module gs_async_fifo #( parameter bit QUADRANT_READ = 1'b0, // Ch440: two depth banks x FOUR width banks (eight physical RAMs). Like // QUADRANT_READ but splits the payload into four width banks instead of two, - // halving each preserved read-address register's M20K load AGAIN at the same - // total M20K, while KEEPING QUADRANT_READ's 2:1 depth output selector (no + // halving each preserved read-address register's M20K load AGAIN (total M20K + // is EXPECTED to stay ~the same, pending synthesis), while KEEPING + // QUADRANT_READ's 2:1 depth output selector (no // new/deeper output mux). Depth, one-cycle read latency, ordering, capacity, // and interface behaviour are identical to QUADRANT_READ. parameter bit QUAD_WIDTH4_READ = 1'b0 @@ -174,7 +175,8 @@ module gs_async_fifo #( if (QUAD_WIDTH4_READ) begin : g_quad_width4_storage // Ch440: 2 depth banks x 4 width banks = eight RAMs. Each read-address // register drives only a HALF_DEPTH x ~(WIDTH/4) RAM -> roughly half the - // M20K load of QUADRANT_READ's hi/lo banks, at the SAME total M20K. The + // M20K load of QUADRANT_READ's hi/lo banks, at an EXPECTED-similar total + // M20K (pending synthesis confirmation). The // depth-half selection stays a 2:1 OUTPUT mux, byte-for-byte the selector // QUADRANT_READ already uses -- no new/deeper output mux is introduced. localparam int W4B0 = WIDTH/4; diff --git a/sim/tb/gif_gs/tb_gs_async_fifo.sv b/sim/tb/gif_gs/tb_gs_async_fifo.sv index 614ae61..273afce 100644 --- a/sim/tb/gif_gs/tb_gs_async_fifo.sv +++ b/sim/tb/gif_gs/tb_gs_async_fifo.sv @@ -14,7 +14,10 @@ module tb_gs_async_fifo #( parameter bit TEST_QUAD_WIDTH4 = 1'b0, // Ch440: 2 depth x 4 width banks parameter bit TEST_REGISTERED = TEST_BANKED || TEST_QUADRANT || TEST_QUAD_WIDTH4 ); - localparam int WIDTH = 32; + // Ch440: the 4-width-bank variant runs at the PRODUCTION 93-bit width so the + // odd 23/23/23/24 remainder split and every width bank are exercised; the + // other variants keep the legacy 32-bit width. + localparam int WIDTH = TEST_QUAD_WIDTH4 ? 93 : 32; localparam int DEPTH = 8; // Production request-FIFO corner: 40 MHz raster producer into the @@ -54,8 +57,32 @@ module tb_gs_async_fifo #( else registered_pending <= TEST_REGISTERED && dut_rd; end - logic [WIDTH-1:0] wr_seq, rd_seq; // next value to write / next value expected to read - assign wdata = wr_seq; + logic [WIDTH-1:0] wr_seq, rd_seq; // sequence counter to write / next expected to read + logic [WIDTH-1:0] wr_pat, rd_pat; // payload for wr_seq / expected reconstruction for rd_seq + + // Ch440: payload generator. For the 4-width-bank variant, spread a DISTINCT + // NONZERO pattern into each of the four 23/23/23/24 banks (sequence counter + // XORed with per-bank constants, one bank inverted) so that a swapped, broken, + // or zeroed upper bank changes the reconstructed word and is caught by the + // full-word scoreboard. Other variants keep the plain incrementing payload. + // Generate-guarded so the 32-bit variants never elaborate the 93-bit selects. + generate + if (TEST_QUAD_WIDTH4) begin : g_payload + function automatic logic [WIDTH-1:0] mk(input logic [WIDTH-1:0] s); + mk = '0; + mk[22:0] = s[22:0] ^ 23'h2AAAAA; // bank0 + mk[45:23] = s[22:0] ^ 23'h555555; // bank1 (distinct const) + mk[68:46] = ~s[22:0] ^ 23'h0F0F0F; // bank2 (inverted) + mk[92:69] = {s[7:0], s[15:8], 8'hA5} ^ 24'hC33C5A; // bank3 (24-bit remainder) + endfunction + assign wr_pat = mk(wr_seq); + assign rd_pat = mk(rd_seq); + end else begin : g_payload + assign wr_pat = wr_seq; + assign rd_pat = rd_seq; + end + endgenerate + assign wdata = wr_pat; int errors; initial errors=0; int sb_err; // scoreboard-only error counter (reset + written solely by the reader always_ff) @@ -70,8 +97,8 @@ module tb_gs_async_fifo #( always_ff @(posedge rclk or negedge rrst_n) begin if (!rrst_n) begin rd_seq <= '0; sb_err <= 0; end else if (TEST_REGISTERED ? registered_pending : dut_rd) begin - if (rdata !== rd_seq) begin - if (sb_err < 20) $error("[afifo] out-of-order/dup/drop: got %0d expected %0d", rdata, rd_seq); + if (rdata !== rd_pat) begin + if (sb_err < 20) $error("[afifo] out-of-order/dup/drop/bank: got %h expected %h (seq %0d)", rdata, rd_pat, rd_seq); sb_err <= sb_err + 1; end rd_seq <= rd_seq + 1;