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>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// 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
|
||||
Reference in New Issue
Block a user