Files
thejayman77 ec82764bef Initial commit: retroDE_ps2 — first-of-its-kind PS2 GS FPGA core (DE25-Nano / Agilex 5)
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression
(272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps,
and all dump-derived textures/traces) is excluded via .gitignore and stays local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:10:50 -04:00

72 lines
2.6 KiB
Systemverilog

// retroDE_ps2 — tb_gs_tile_ram (Ch303)
//
// Focused TB for gs_tile_ram, the on-chip tile-local scratchpad RAM backing the
// tiled renderer's color + Z tiles. Proves:
// PROOF 1 — write/read round-trip across ALL 256 entries (1-cycle registered read).
// PROOF 2 — registered read latency is exactly 1 (data for raddr@N arrives @N+1).
// PROOF 3 — interleaved write-then-read (the renderer pattern: write a pixel,
// later read it back) returns the written value.
`timescale 1ns/1ps
module tb_gs_tile_ram;
localparam int ADDR_W = 8;
localparam int DATA_W = 32;
localparam int N = (1<<ADDR_W);
logic clk, rst_n;
initial clk = 1'b0;
always #5 clk = ~clk;
logic we;
logic [ADDR_W-1:0] waddr, raddr;
logic [DATA_W-1:0] wdata, rdata;
gs_tile_ram #(.ADDR_W(ADDR_W), .DATA_W(DATA_W)) dut (
.clk(clk), .rst_n(rst_n),
.we(we), .waddr(waddr), .wdata(wdata),
.raddr(raddr), .rdata(rdata)
);
function automatic logic [DATA_W-1:0] patt(input int a);
return 32'hC0DE_0000 ^ (a * 32'h0001_0103);
endfunction
int errors;
initial begin
errors = 0;
we=1'b0; waddr=0; wdata=0; raddr=0;
rst_n=1'b0; repeat(3) @(posedge clk); rst_n=1'b1; @(posedge clk);
// PROOF 1 — fill all entries.
for (int a=0; a<N; a++) begin
@(negedge clk); we=1'b1; waddr=a[ADDR_W-1:0]; wdata=patt(a);
end
@(negedge clk); we=1'b0;
// read all back (registered: present raddr, sample rdata next cycle).
for (int a=0; a<N; a++) begin
@(negedge clk); raddr=a[ADDR_W-1:0];
@(posedge clk); #1; // rdata now holds mem[raddr] (1-cyc latency)
if (rdata !== patt(a)) begin
if (errors<10) $error("[tile_ram] addr %0d got %08x exp %08x", a, rdata, patt(a));
errors++;
end
end
// PROOF 3 — write a fresh value then read it back through the latency.
@(negedge clk); we=1'b1; waddr=8'd42; wdata=32'hDEAD_BEEF;
@(negedge clk); we=1'b0; raddr=8'd42;
@(posedge clk); #1;
if (rdata !== 32'hDEAD_BEEF) begin $error("[tile_ram] RMW addr42 got %08x exp DEADBEEF", rdata); errors++; end
$display("[tb_gs_tile_ram] checked %0d entries, errors=%0d", N, errors);
if (errors==0) $display("[tb_gs_tile_ram] PASS");
else $display("[tb_gs_tile_ram] FAIL");
$finish;
end
initial begin #2000000; $error("[tb_gs_tile_ram] TIMEOUT"); $finish; end
endmodule : tb_gs_tile_ram