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:
2026-06-29 20:10:50 -04:00
commit ec82764bef
2462 changed files with 2174303 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
// 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