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.
253 lines
9.0 KiB
Systemverilog
253 lines
9.0 KiB
Systemverilog
`timescale 1ns / 1ps
|
|
|
|
`include "apb4_uart_define.svh"
|
|
|
|
module uart_tb;
|
|
logic clk_i = 1'b0;
|
|
logic rst_n_i = 1'b0;
|
|
logic dma_tx_stall;
|
|
logic dma_rx_stall;
|
|
apb4_if apb4 (
|
|
.pclk (clk_i),
|
|
.presetn(rst_n_i)
|
|
);
|
|
uart_if uart ();
|
|
|
|
always #5 clk_i = ~clk_i;
|
|
|
|
apb4_uart u_dut (
|
|
.clk_i (clk_i),
|
|
.rst_n_i (rst_n_i),
|
|
.dma_tx_stall_o(dma_tx_stall),
|
|
.dma_rx_stall_o(dma_rx_stall),
|
|
.apb4 (apb4),
|
|
.uart (uart)
|
|
);
|
|
|
|
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, input logic expected_error,
|
|
output logic [31:0] data);
|
|
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 write_ok(input logic [31:0] address, input logic [31:0] data);
|
|
begin
|
|
apb4_write(address, data, 4'hF, 1'b0);
|
|
end
|
|
endtask
|
|
|
|
task automatic configure_uart_flow(input logic [4:0] line_control, input logic [1:0] flow_control,
|
|
input logic [6:0] rts_assert_level,
|
|
input logic [6:0] rts_deassert_level,
|
|
input logic [3:0] control);
|
|
begin
|
|
write_ok(`APB4_UART_CTRL, 0);
|
|
repeat (4) @(posedge clk_i);
|
|
write_ok(`APB4_UART_FIFO_CTRL, 3);
|
|
write_ok(`APB4_UART_BAUD_INT, 16);
|
|
write_ok(`APB4_UART_BAUD_FRAC, 0);
|
|
write_ok(`APB4_UART_LINE_CTRL, line_control);
|
|
write_ok(`APB4_UART_RTS_WATERMARK, {9'd0, rts_deassert_level, 9'd0, rts_assert_level});
|
|
write_ok(`APB4_UART_FLOW_CTRL, flow_control);
|
|
write_ok(`APB4_UART_CTRL, control);
|
|
end
|
|
endtask
|
|
|
|
task automatic configure_uart(input logic [4:0] line_control, input logic [3:0] control);
|
|
begin
|
|
configure_uart_flow(line_control, 2'd0, 7'd32, 7'd48, control);
|
|
end
|
|
endtask
|
|
|
|
task automatic send_external_8n1(input logic [7:0] data, input logic bad_stop);
|
|
integer bit_index;
|
|
begin
|
|
uart.rx_i = 1'b0;
|
|
repeat (16) @(posedge clk_i);
|
|
for (bit_index = 0; bit_index < 8; bit_index = bit_index + 1) begin
|
|
uart.rx_i = data[bit_index];
|
|
repeat (16) @(posedge clk_i);
|
|
end
|
|
uart.rx_i = !bad_stop;
|
|
repeat (16) @(posedge clk_i);
|
|
uart.rx_i = 1'b1;
|
|
repeat (24) @(posedge clk_i);
|
|
end
|
|
endtask
|
|
|
|
initial begin
|
|
logic [31:0] value;
|
|
integer index;
|
|
|
|
apb4.psel = 1'b0;
|
|
apb4.paddr = '0;
|
|
apb4.pwdata = '0;
|
|
apb4.pstrb = '0;
|
|
uart.rx_i = 1'b1;
|
|
uart.cts_n_i = 1'b1;
|
|
repeat (4) @(posedge clk_i);
|
|
rst_n_i = 1'b1;
|
|
repeat (4) @(posedge clk_i);
|
|
|
|
if (uart.rts_n_o !== 1'b1) $fatal(1, "UART RTS_n was not released after reset");
|
|
apb4_read(`APB4_UART_IP_VERSION, 1'b0, value);
|
|
if (value != 32'h0003_0000) $fatal(1, "UART IP version mismatch");
|
|
apb4_read(`APB4_UART_CAPABILITY, 1'b0, value);
|
|
if (value != 32'h03FF_4040) $fatal(1, "UART capability mismatch");
|
|
apb4_read(32'h0000_0002, 1'b1, value);
|
|
apb4_read(`APB4_UART_RXDATA, 1'b1, value);
|
|
|
|
apb4_write(`APB4_UART_RTS_WATERMARK, 32'h0002_0002, 4'hF, 1'b1);
|
|
apb4_read(`APB4_UART_ERROR_STATUS, 1'b0, value);
|
|
if (!value[`UART_ERROR_CONFIG]) $fatal(1, "UART invalid RTS watermark was not reported");
|
|
write_ok(`APB4_UART_ERROR_STATUS, 7'h7F);
|
|
|
|
configure_uart_flow(5'd3, 2'b01, 7'd32, 7'd48, 4'b0111);
|
|
write_ok(`APB4_UART_TXDATA, 8'hA5);
|
|
repeat (220) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
|
if (value[11:0] != 12'h0A5) $fatal(1, "UART 8N1 loopback mismatch: %h", value);
|
|
|
|
configure_uart(5'd3, 4'b0001);
|
|
write_ok(`APB4_UART_TXDATA, 8'h5A);
|
|
repeat (24) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
|
if (!value[`UART_STATUS_TX_BUSY]) $fatal(1, "UART TX did not start before disable");
|
|
write_ok(`APB4_UART_CTRL, 0);
|
|
repeat (180) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
|
if (value[`UART_STATUS_TX_BUSY] || !value[`UART_STATUS_TX_EMPTY]) begin
|
|
$fatal(1, "UART TX did not finish its active frame after disable: %h", value);
|
|
end
|
|
|
|
write_ok(`APB4_UART_INTR_ENABLE, 7'h7F);
|
|
write_ok(`APB4_UART_INTR_TEST, 7'h20);
|
|
apb4_read(`APB4_UART_INTR_STATUS, 1'b0, value);
|
|
if (!value[`UART_INTR_BREAK] || !uart.irq_o) $fatal(1, "UART interrupt test failed");
|
|
write_ok(`APB4_UART_INTR_STATE, 7'h7F);
|
|
|
|
configure_uart_flow(5'd3, 2'b01, 7'd32, 7'd48, 4'b0001);
|
|
write_ok(`APB4_UART_INTR_ENABLE, 7'h40);
|
|
write_ok(`APB4_UART_TXDATA, 8'hC3);
|
|
write_ok(`APB4_UART_TXDATA, 8'h5C);
|
|
repeat (32) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
|
if (!value[`UART_STATUS_TX_FLOW_BLOCKED] || value[`UART_STATUS_TX_BUSY] ||
|
|
value[`UART_STATUS_CTS_ASSERTED]) begin
|
|
$fatal(1, "UART CTS did not block a new frame: %h", value);
|
|
end
|
|
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
|
if (value[6:0] != 7'd2) $fatal(1, "UART CTS-blocked FIFO count mismatch: %h", value);
|
|
|
|
uart.cts_n_i = 1'b0;
|
|
repeat (32) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
|
if (!value[`UART_STATUS_CTS_ASSERTED] || !value[`UART_STATUS_TX_BUSY]) begin
|
|
$fatal(1, "UART did not start after CTS assertion: %h", value);
|
|
end
|
|
uart.cts_n_i = 1'b1;
|
|
repeat (200) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
|
if (!value[`UART_STATUS_TX_FLOW_BLOCKED] || value[`UART_STATUS_TX_BUSY]) begin
|
|
$fatal(1, "UART CTS did not stop at the frame boundary: %h", value);
|
|
end
|
|
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
|
if (value[6:0] != 7'd1) $fatal(1, "UART frame-boundary FIFO count mismatch: %h", value);
|
|
apb4_read(`APB4_UART_INTR_STATUS, 1'b0, value);
|
|
if (!value[`UART_INTR_CTS_CHANGE] || !uart.irq_o) begin
|
|
$fatal(1, "UART CTS change interrupt failed: %h", value);
|
|
end
|
|
write_ok(`APB4_UART_INTR_STATE, 7'h7F);
|
|
uart.cts_n_i = 1'b0;
|
|
repeat (220) @(posedge clk_i);
|
|
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
|
if (value[6:0] != 7'd0) $fatal(1, "UART did not resume after CTS assertion: %h", value);
|
|
|
|
configure_uart(5'd3, 4'b0010);
|
|
fork
|
|
send_external_8n1(8'h3C, 1'b1);
|
|
join
|
|
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
|
if ((value[7:0] != 8'h3C) || !value[`UART_RXDATA_FRAME_ERROR]) begin
|
|
$fatal(1, "UART frame error was not retained: %h", value);
|
|
end
|
|
|
|
configure_uart_flow(5'd3, 2'b10, 7'd1, 7'd2, 4'b0010);
|
|
repeat (4) @(posedge clk_i);
|
|
if (uart.rts_n_o !== 1'b0) $fatal(1, "UART RTS_n was not asserted for an empty RX FIFO");
|
|
send_external_8n1(8'h12, 1'b0);
|
|
if (uart.rts_n_o !== 1'b0) $fatal(1, "UART RTS_n asserted state did not hold below watermark");
|
|
send_external_8n1(8'h34, 1'b0);
|
|
if (uart.rts_n_o !== 1'b1) $fatal(1, "UART RTS_n was not released at high watermark");
|
|
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
|
repeat (2) @(posedge clk_i);
|
|
if ((value[7:0] != 8'h12) || (uart.rts_n_o !== 1'b0)) begin
|
|
$fatal(1, "UART RTS hysteresis did not reassert below low watermark: %h", value);
|
|
end
|
|
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
|
if (value[7:0] != 8'h34) $fatal(1, "UART RTS test RX ordering mismatch: %h", value);
|
|
|
|
write_ok(`APB4_UART_CTRL, 0);
|
|
repeat (4) @(posedge clk_i);
|
|
write_ok(`APB4_UART_FIFO_CTRL, 3);
|
|
for (index = 0; index < 64; index = index + 1) begin
|
|
write_ok(`APB4_UART_TXDATA, index);
|
|
end
|
|
apb4_write(`APB4_UART_TXDATA, 32'h55, 4'hF, 1'b1);
|
|
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
|
if (value[6:0] != 7'd64) $fatal(1, "UART TX FIFO depth mismatch: %h", value);
|
|
|
|
write_ok(`APB4_UART_FIFO_CTRL, 3);
|
|
write_ok(`APB4_UART_DMA_CTRL, 3);
|
|
if (!dma_tx_stall || !dma_rx_stall) $fatal(1, "Disabled UART asserted a DMA request");
|
|
|
|
$display("UART register, FIFO, loopback, flow-control, interrupt, and DMA test passed");
|
|
$finish;
|
|
end
|
|
|
|
initial begin
|
|
repeat (20000) @(posedge clk_i);
|
|
$fatal(1, "UART test timeout");
|
|
end
|
|
|
|
endmodule
|