Files
retroSoC/tests/rtl/gpio_tb.sv
T
maksyuki 6eedacd2f7 refactor: refactor tests to replace RIBP references with APB4 equivalents
- Updated test files to change instances of ribp_if to apb4_if in various test cases, ensuring consistency with the new APB4 interface.
- Modified assertions and checks in tests to reflect the new APB4 naming conventions, including changes in expected output and input files.
- Adjusted the test descriptions to accurately represent the APB4 functionality being tested, particularly in timer, UART, and GPIO tests.
- Ensured that all relevant paths and file names in the tests are updated to point to the new APB4 implementations, maintaining the integrity of the test suite.
2026-08-16 21:19:20 +08:00

177 lines
6.6 KiB
Systemverilog

`timescale 1ns / 1ps
`include "gpio_define.svh"
module gpio_tb;
localparam int PinNum = 4;
localparam logic [31:0] USER_BASE = 32'h1000_0000;
localparam logic [31:0] ADMIN_BASE = 32'h1001_4000;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
gpio_if #(PinNum) gpio ();
user_gpio_if #(PinNum) user_gpio ();
logic [31:0] read_data;
always #5 clk_i = ~clk_i;
apb4_gpio #(
.PinNum (PinNum),
.UserBaseAddr (USER_BASE),
.AdminBaseAddr(ADMIN_BASE),
.HasInputCmos (1'b1),
.HasPullUp (1'b1),
.HasPullDown (1'b1)
) dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.apb4 (apb4),
.gpio (gpio),
.user_gpio(user_gpio)
);
task automatic write_register(input logic [31:0] address, input logic [31:0] data,
input logic expected_error);
begin
@(negedge clk_i);
apb4.paddr = address;
apb4.pwdata = data;
apb4.pstrb = 4'hF;
apb4.pwrite = 1'b1;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
apb4.penable = 1'b1;
while (!apb4.pready) @(negedge clk_i);
if (apb4.pslverr !== expected_error) begin
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
end
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
task automatic read_register(input logic [31:0] address, output logic [31:0] data,
input logic expected_error);
begin
@(negedge clk_i);
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
apb4.penable = 1'b1;
while (!apb4.pready) @(negedge clk_i);
if (apb4.pslverr !== expected_error) begin
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
end
data = apb4.prdata;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
initial begin
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pprot = '0;
gpio.di_i = '0;
gpio.alt0_do_i = '0;
gpio.alt0_oe_i = '0;
gpio.alt1_do_i = '0;
gpio.alt1_oe_i = '0;
user_gpio.do_o = '0;
user_gpio.oe_o = '0;
repeat (3) @(posedge clk_i);
rst_n_i = 1'b1;
repeat (3) @(posedge clk_i);
read_register(ADMIN_BASE + `APB4_GPIO_CAPABILITY, read_data, 1'b0);
if (read_data !== 32'h007F_4204) $fatal(1, "capability register mismatch");
read_register(ADMIN_BASE + `APB4_GPIO_PAD_CAPABILITY, read_data, 1'b0);
if (read_data !== 32'h0000_0007) $fatal(1, "pad capability register mismatch");
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUTPUT_ENABLE, read_data, 1'b0);
if (read_data !== 32'd0) $fatal(1, "output enable reset value mismatch");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_SET, 32'h1, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OE_SET, 32'h1, 1'b0);
if ({gpio.oe_o[0], gpio.do_o[0]} !== 2'b11) $fatal(1, "software output failed");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_TOGGLE, 32'h1, 1'b0);
if (gpio.do_o[0] !== 1'b0) $fatal(1, "atomic output toggle failed");
read_register(ADMIN_BASE + 32'h2, read_data, 1'b1);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_USER_ACCESS_MASK, 32'h2, 1'b0);
write_register(USER_BASE + `APB4_GPIO_USER_OUT_SET, 32'h6, 1'b0);
read_register(USER_BASE + `APB4_GPIO_USER_DATA_OUT, read_data, 1'b0);
if (read_data !== 32'h2) $fatal(1, "user access mask did not isolate output data");
user_gpio.do_o[2] = 1'b1;
user_gpio.oe_o[2] = 1'b1;
@(negedge clk_i);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_USER_SELECT, 32'h4, 1'b0);
@(posedge clk_i);
#1;
if ({gpio.oe_o[2], gpio.do_o[2]} !== 2'b11) $fatal(1, "user output was not selected");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OE_SET, 32'h2, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OPEN_DRAIN, 32'h2, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_SET, 32'h2, 1'b0);
if ({gpio.oe_o[1], gpio.do_o[1]} !== 2'b00) $fatal(1, "open-drain release failed");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_CLEAR, 32'h2, 1'b0);
if ({gpio.oe_o[1], gpio.do_o[1]} !== 2'b10) $fatal(1, "open-drain low drive failed");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_PULL_UP, 32'h8, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_PULL_DOWN, 32'h8, 1'b1);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h1, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_ENABLE, 32'h1, 1'b0);
gpio.di_i[0] = 1'b1;
repeat (5) @(posedge clk_i);
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, read_data, 1'b0);
if ((read_data & 32'h1) == 0) $fatal(1, "rising edge interrupt was not latched");
if (!gpio.irq_o) $fatal(1, "combined GPIO interrupt was not asserted");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
if (gpio.irq_o) $fatal(1, "W1C did not clear the interrupt");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_TEST, 32'h1, 1'b0);
if (!gpio.irq_o) $fatal(1, "software interrupt test failed");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h9, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_HIGH_ENABLE, 32'h8, 1'b1);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_FILTER_DIV, 32'h0, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_FILTER_COUNT, 32'h4, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_FILTER_ENABLE, 32'h8, 1'b0);
gpio.di_i[3] = 1'b1;
@(posedge clk_i);
gpio.di_i[3] = 1'b0;
repeat (5) @(posedge clk_i);
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
if ((read_data & 32'h8) != 0) $fatal(1, "input filter accepted a short pulse");
gpio.di_i[3] = 1'b1;
repeat (8) @(posedge clk_i);
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
if ((read_data & 32'h8) == 0) $fatal(1, "input filter rejected a stable input");
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_CONFIG_LOCK, 32'h1, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OE_CLEAR, 32'h1, 1'b1);
if (gpio.oe_o[0] !== 1'b1) $fatal(1, "configuration lock did not protect OE");
$display("GPIO directed test passed");
$finish;
end
endmodule