ec82764bef
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>
175 lines
6.0 KiB
Systemverilog
175 lines
6.0 KiB
Systemverilog
// retroDE_ps2 — tb_gs_stub
|
|
//
|
|
// Milestone A slice: verifies gs_stub's BGCOLOR latch, non-BGCOLOR
|
|
// privileged-register logging, stable-state holding, and trace emission.
|
|
// Does not instantiate platform_video_stub (covered separately where a full
|
|
// Milestone A test is warranted).
|
|
//
|
|
// Plan ref: docs/stub_module_plan.md (Initial testbench plan).
|
|
|
|
`timescale 1ns/1ps
|
|
|
|
module tb_gs_stub;
|
|
|
|
logic clk;
|
|
logic rst_n;
|
|
|
|
initial clk = 1'b0;
|
|
always #5 clk = ~clk;
|
|
|
|
// ------------------------------------------------------------------
|
|
// DUT and trace sink
|
|
// ------------------------------------------------------------------
|
|
|
|
logic reg_wr_en;
|
|
logic [15:0] reg_wr_addr;
|
|
logic [63:0] reg_wr_data;
|
|
|
|
logic [7:0] bg_r, bg_g, bg_b;
|
|
|
|
logic ev_valid;
|
|
trace_pkg::subsys_e ev_subsys;
|
|
trace_pkg::event_e ev_event;
|
|
logic [63:0] ev_arg0, ev_arg1, ev_arg2, ev_arg3;
|
|
logic [31:0] ev_flags;
|
|
|
|
gs_stub u_gs (
|
|
.clk(clk), .rst_n(rst_n),
|
|
.reg_wr_en(reg_wr_en), .reg_wr_addr(reg_wr_addr), .reg_wr_data(reg_wr_data),
|
|
.gif_reg_wr_en(1'b0), .gif_reg_num(8'd0), .gif_reg_data(64'd0),
|
|
.prim_q(), .rgbaq_q(), .xyz2_q(), .xyzf2_q(), .frame_1_q(), .zbuf_1_q(),
|
|
.prim_complete(), .prim_complete_count(),
|
|
.prim_v0_q(), .prim_v1_q(), .prim_v2_q(),
|
|
.prim_color_q(),
|
|
.prim_color_v0_q(), .prim_color_v1_q(), .prim_color_v2_q(),
|
|
.prim_v0_decoded_q(), .prim_v1_decoded_q(), .prim_v2_decoded_q(),
|
|
.prim_v0_color_decoded_q(), .prim_v1_color_decoded_q(), .prim_v2_color_decoded_q(),
|
|
.pixel_emit(), .pixel_emit_count(),
|
|
.pixel_x_q(), .pixel_y_q(),
|
|
.pixel_color_q(),
|
|
.pixel_fbp_q(), .pixel_fbw_q(), .pixel_psm_q(),
|
|
.pixel_fb_addr_q(),
|
|
.raster_pixel_emit(), .raster_pixel_emit_count(),
|
|
.raster_pixel_x_q(), .raster_pixel_y_q(),
|
|
.raster_pixel_color_q(),
|
|
.raster_pixel_fb_addr_q(),
|
|
.raster_active(), .raster_overflow(),
|
|
.raster_degenerate(),
|
|
.bg_r(bg_r), .bg_g(bg_g), .bg_b(bg_b),
|
|
.ev_valid(ev_valid), .ev_subsys(ev_subsys), .ev_event(ev_event),
|
|
.ev_arg0(ev_arg0), .ev_arg1(ev_arg1),
|
|
.ev_arg2(ev_arg2), .ev_arg3(ev_arg3),
|
|
.ev_flags(ev_flags)
|
|
);
|
|
|
|
trace_sink_stub #(.FILENAME("gs.trace"), .SINK_LABEL("gs")) u_trace_gs (
|
|
.clk(clk), .rst_n(rst_n),
|
|
.ev_valid(ev_valid), .ev_subsys(ev_subsys), .ev_event(ev_event),
|
|
.ev_arg0(ev_arg0), .ev_arg1(ev_arg1),
|
|
.ev_arg2(ev_arg2), .ev_arg3(ev_arg3),
|
|
.ev_flags(ev_flags)
|
|
);
|
|
|
|
// ------------------------------------------------------------------
|
|
// Checkers
|
|
// ------------------------------------------------------------------
|
|
|
|
int bgcolor_events;
|
|
int mode_events;
|
|
int errors;
|
|
|
|
initial begin
|
|
bgcolor_events = 0;
|
|
mode_events = 0;
|
|
errors = 0;
|
|
end
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (rst_n && ev_valid) begin
|
|
if (ev_event == trace_pkg::EV_BGCOLOR) bgcolor_events <= bgcolor_events + 1;
|
|
if (ev_event == trace_pkg::EV_MODE) mode_events <= mode_events + 1;
|
|
end
|
|
end
|
|
|
|
task automatic write_reg(input logic [15:0] offset, input logic [63:0] data);
|
|
@(negedge clk);
|
|
reg_wr_en = 1'b1;
|
|
reg_wr_addr = offset;
|
|
reg_wr_data = data;
|
|
@(negedge clk);
|
|
reg_wr_en = 1'b0;
|
|
reg_wr_addr = 16'd0;
|
|
reg_wr_data = 64'd0;
|
|
endtask
|
|
|
|
task automatic expect_bg(input logic [7:0] r, input logic [7:0] g, input logic [7:0] b,
|
|
input string label);
|
|
if (bg_r !== r || bg_g !== g || bg_b !== b) begin
|
|
$error("[tb_gs_stub] %s: bg=(%02h,%02h,%02h) expected=(%02h,%02h,%02h)",
|
|
label, bg_r, bg_g, bg_b, r, g, b);
|
|
errors = errors + 1;
|
|
end
|
|
endtask
|
|
|
|
// ------------------------------------------------------------------
|
|
// Stimulus
|
|
// ------------------------------------------------------------------
|
|
|
|
initial begin
|
|
rst_n = 1'b0;
|
|
reg_wr_en = 1'b0;
|
|
reg_wr_addr = 16'd0;
|
|
reg_wr_data = 64'd0;
|
|
|
|
repeat (4) @(posedge clk);
|
|
rst_n = 1'b1;
|
|
repeat (2) @(posedge clk);
|
|
|
|
// Default reset value should be mid-grey.
|
|
expect_bg(8'h40, 8'h40, 8'h40, "post-reset default");
|
|
|
|
// Write BGCOLOR = (R=0xAA, G=0xBB, B=0xCC).
|
|
write_reg(16'h00E0, 64'h0000_0000_00AA_BBCC);
|
|
repeat (2) @(posedge clk);
|
|
expect_bg(8'hAA, 8'hBB, 8'hCC, "after BGCOLOR write");
|
|
|
|
// Stable-state: color should hold for many cycles without additional writes.
|
|
repeat (20) @(posedge clk);
|
|
expect_bg(8'hAA, 8'hBB, 8'hCC, "stable hold");
|
|
|
|
// Write to a non-BGCOLOR privileged register (PMODE at offset 0x000) —
|
|
// should log EV_MODE but leave BGCOLOR untouched.
|
|
write_reg(16'h0000, 64'h0000_0000_0000_0001);
|
|
repeat (2) @(posedge clk);
|
|
expect_bg(8'hAA, 8'hBB, 8'hCC, "after PMODE write");
|
|
|
|
// Overwrite BGCOLOR with a second value.
|
|
write_reg(16'h00E0, 64'h0000_0000_0011_2233);
|
|
repeat (2) @(posedge clk);
|
|
expect_bg(8'h11, 8'h22, 8'h33, "after second BGCOLOR write");
|
|
|
|
// ------------------------------------------------------------------
|
|
$display("[tb_gs_stub] bgcolor_events=%0d mode_events=%0d errors=%0d",
|
|
bgcolor_events, mode_events, errors);
|
|
|
|
if (bgcolor_events < 2)
|
|
$error("[tb_gs_stub] expected at least 2 BGCOLOR events, got %0d", bgcolor_events);
|
|
if (mode_events < 1)
|
|
$error("[tb_gs_stub] expected at least 1 MODE event, got %0d", mode_events);
|
|
|
|
if (errors == 0 && bgcolor_events >= 2 && mode_events >= 1)
|
|
$display("[tb_gs_stub] PASS");
|
|
else
|
|
$display("[tb_gs_stub] FAIL");
|
|
|
|
$finish;
|
|
end
|
|
|
|
initial begin
|
|
#100000;
|
|
$error("[tb_gs_stub] timeout");
|
|
$finish;
|
|
end
|
|
|
|
endmodule : tb_gs_stub
|