mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
- 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.
177 lines
6.6 KiB
Systemverilog
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
|