// retroDE_ps2 — tb_gs_texture_unit // // Verifies gs_texture_unit end-to-end against a stand-in VRAM: preload known // 32-bit texels, stream a sequence of (u,v) coords in, and check the sampled // color comes out aligned with out_valid and matches the preloaded texel at // the address the unit computed. Exercises the read-latency pipeline. `timescale 1ns/1ps module tb_gs_texture_unit; localparam logic [5:0] PSMCT32 = 6'h00; localparam int RD_LATENCY = 1; logic clk = 0, rst_n = 0; logic in_valid; logic [10:0] u, v; logic [31:0] tbp0_base_bytes; logic [13:0] tbw; logic [5:0] psm; logic tex_rd_en; logic [31:0] tex_rd_addr; logic [31:0] tex_rd_data; logic out_valid; logic [31:0] tex_color; int errors = 0; always #5 clk = ~clk; gs_texture_unit #(.RD_LATENCY(RD_LATENCY)) dut ( .clk(clk), .rst_n(rst_n), .in_valid(in_valid), .u(u), .v(v), .tbp0_base_bytes(tbp0_base_bytes), .tbw(tbw), .psm(psm), .tex_rd_en(tex_rd_en), .tex_rd_addr(tex_rd_addr), .tex_rd_data(tex_rd_data), .out_valid(out_valid), .tex_color(tex_color) ); // --- stand-in VRAM: byte-addressed, 32-bit word, registered 1-cycle read --- logic [31:0] mem [0:1023]; // 4 KiB window always_ff @(posedge clk) begin if (tex_rd_en) tex_rd_data <= mem[tex_rd_addr[31:2]]; // word index = byte addr >> 2 end // expected-color shadow, delayed to align with out_valid logic [31:0] exp_color_q; logic exp_valid_q; task automatic feed(input logic [10:0] uu, input logic [10:0] vv, input logic [31:0] expect_color); @(negedge clk); in_valid = 1'b1; u = uu; v = vv; exp_color_q = expect_color; exp_valid_q = 1'b1; @(posedge clk); // address presented; VRAM registers data #1; in_valid = 1'b0; // out_valid + tex_color valid RD_LATENCY cycles after this posedge endtask // checker: whenever out_valid, compare against the pipelined expectation logic [31:0] exp_pipe; logic expv_pipe; always_ff @(posedge clk) begin if (!rst_n) begin expv_pipe <= 0; exp_pipe <= 0; end else begin expv_pipe <= exp_valid_q; exp_pipe <= exp_color_q; exp_valid_q <= 1'b0; // one-shot per feed end end always_ff @(posedge clk) begin if (out_valid) begin if (tex_color !== exp_pipe) begin $display("FAIL: tex_color=%08x expected=%08x (addr=%0d)", tex_color, exp_pipe, tex_rd_addr); errors++; end else begin $display("ok : tex_color=%08x", tex_color); end end end initial begin // preload texels. tbw=1 -> 64 texels/row, base 0, PSMCT32 (4 B/texel) // texel (u,v) lives at word index v*64 + u. mem[2*64 + 3] = 32'hDEADBEEF; // (u=3, v=2) mem[0] = 32'h11223344; // (u=0, v=0) mem[1*64 + 5] = 32'hA5A5F00D; // (u=5, v=1) tbp0_base_bytes = 0; tbw = 1; psm = PSMCT32; in_valid = 0; u = 0; v = 0; repeat (3) @(posedge clk); rst_n = 1; @(negedge clk); feed(11'd3, 11'd2, 32'hDEADBEEF); feed(11'd0, 11'd0, 32'h11223344); feed(11'd5, 11'd1, 32'hA5A5F00D); repeat (4) @(posedge clk); if (errors == 0) $display("\nPASS tb_gs_texture_unit"); else $display("\nFAIL tb_gs_texture_unit (%0d errors)", errors); $finish; end endmodule