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.
150 lines
4.3 KiB
Systemverilog
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
|