// 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