Ch440 review fixes: 93-bit per-bank test coverage + soften M20K claims [READY FOR REVIEW]

Per Codex review of 471c1af:
1. tb_gs_async_fifo QUAD_WIDTH4 variant now runs at the PRODUCTION 93-bit width
   (exercising the odd 23/23/23/24 remainder split) and drives a DISTINCT NONZERO
   pattern into every width bank (seq XOR per-bank constants, bank2 inverted), with
   the scoreboard checking the FULL reconstructed word. A swapped/broken/zeroed
   upper bank now changes the word and trips the scoreboard. Depth-half crossing
   (DEPTH=8) + wrap/full coverage retained. mk() is generate-guarded so the 32-bit
   variants never elaborate the 93-bit selects.
2. Softened gs_async_fifo comments: 'same total M20K' -> EXPECTED-similar, pending
   synthesis (fact -> expectation).

No simulations or Quartus run. Awaiting review before any sim.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-21 10:28:31 -04:00
parent 471c1af9cd
commit 94d6293c43
2 changed files with 37 additions and 8 deletions
+5 -3
View File
@@ -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;
+32 -5
View File
@@ -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;