Files
retroSoC/tests/rtl/clint_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

150 lines
4.3 KiB
Systemverilog

`timescale 1ns / 1ps
module clint_tb;
logic clk_i = 1'b0;
logic ref_clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic tick_i = 1'b0;
logic timebase_tick;
logic [31:0] value;
integer timebase_tick_count = 0;
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
clint_if #(.HartNum(2)) clint ();
always #5 clk_i = ~clk_i;
always #2 ref_clk_i = ~ref_clk_i;
always @(posedge clk_i) begin
if (timebase_tick) timebase_tick_count <= timebase_tick_count + 1;
end
clint_timebase #(
.RefClkHz (4),
.TimebaseHz(1)
) u_timebase (
.ref_clk_i (ref_clk_i),
.ref_rst_n_i(rst_n_i),
.sys_clk_i (clk_i),
.sys_rst_n_i(rst_n_i),
.tick_o (timebase_tick)
);
apb4_clint #(
.HartNum(2)
) u_dut (
.clk_i,
.rst_n_i,
.timebase_tick_i(tick_i),
.apb4,
.clint
);
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
input logic [3:0] strobe, input logic expected_error);
begin
@(negedge clk_i);
apb4.paddr = address;
apb4.pwdata = data;
apb4.pstrb = strobe;
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 apb4_read(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
task automatic pulse_tick;
begin
@(negedge clk_i);
tick_i = 1'b1;
@(negedge clk_i);
tick_i = 1'b0;
end
endtask
initial begin
apb4.psel = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
apb4_read(32'h0000_0000, value, 1'b0);
if (value != 32'd0 || clint.software_irq_o != 2'b00) begin
$fatal(1, "MSIP reset state is invalid");
end
apb4_read(32'h0000_4000, value, 1'b0);
if (value != 32'hFFFF_FFFF) $fatal(1, "MTIMECMP low reset state is invalid");
apb4_read(32'h0000_4004, value, 1'b0);
if (value != 32'hFFFF_FFFF || clint.timer_irq_o != 2'b00) begin
$fatal(1, "MTIMECMP high reset state is invalid");
end
apb4_write(32'h0000_0004, 32'h0000_0001, 4'h1, 1'b0);
if (clint.software_irq_o != 2'b10) $fatal(1, "hart 1 MSIP did not assert");
apb4_write(32'h0000_0004, 32'h0000_0000, 4'h1, 1'b0);
if (clint.software_irq_o != 2'b00) $fatal(1, "hart 1 MSIP did not clear");
apb4_write(32'h0000_BFFC, 32'd0, 4'hF, 1'b0);
apb4_write(32'h0000_BFF8, 32'd10, 4'hF, 1'b0);
apb4_read(32'h0000_BFF8, value, 1'b0);
if (value != 32'd10) $fatal(1, "MTIME write/read failed: %h", value);
apb4_write(32'h0000_4004, 32'd0, 4'hF, 1'b0);
apb4_write(32'h0000_4000, 32'd12, 4'hF, 1'b0);
pulse_tick();
pulse_tick();
repeat (2) @(posedge clk_i);
if (clint.timer_irq_o[0] != 1'b1) $fatal(1, "hart 0 timer IRQ did not assert");
if (clint.timer_irq_o[1] != 1'b0) $fatal(1, "hart 1 timer IRQ asserted unexpectedly");
apb4_write(32'h0000_4001, 32'd0, 4'hF, 1'b1);
apb4_read(32'h0000_0010, value, 1'b1);
if (value != 32'd0) $fatal(1, "invalid read did not return zero");
repeat (20) @(posedge clk_i);
if (timebase_tick_count < 2) begin
$fatal(1, "reference-clock timebase did not produce synchronized ticks");
end
$display("CLINT standard map, multi-hart, IRQ, error, and timebase test passed");
$finish;
end
endmodule