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.
This commit is contained in:
maksyuki committed 2026-08-16 21:19:20 +08:00
1 parent 06e2b9c4de
commit 6eedacd2f7
153 files changed
+5566 -3744

No files matched your search

+61
View File
@@ -0,0 +1,61 @@
// Shared APB4 master helpers for unit tests.
// The including module must provide clk_i and an apb4_if instance.
`ifndef APB4_BFM_IF
`define APB4_BFM_IF apb4
`endif
task automatic apb4_idle();
begin
`APB4_BFM_IF.psel = 1'b0;
`APB4_BFM_IF.penable = 1'b0;
`APB4_BFM_IF.pwrite = 1'b0;
`APB4_BFM_IF.paddr = '0;
`APB4_BFM_IF.pwdata = '0;
`APB4_BFM_IF.pstrb = '0;
`APB4_BFM_IF.pprot = '0;
end
endtask
task automatic apb4_xfer(input logic [31:0] address, input logic write, input logic [31:0] wdata,
input logic [3:0] strobe, input logic expected_error,
output logic [31:0] rdata);
begin
@(negedge clk_i);
`APB4_BFM_IF.paddr = address;
`APB4_BFM_IF.pwdata = wdata;
`APB4_BFM_IF.pstrb = write ? strobe : 4'h0;
`APB4_BFM_IF.pwrite = write;
`APB4_BFM_IF.pprot = '0;
`APB4_BFM_IF.psel = 1'b1;
`APB4_BFM_IF.penable = 1'b0;
@(negedge clk_i);
`APB4_BFM_IF.penable = 1'b1;
while (!`APB4_BFM_IF.pready) begin
@(negedge clk_i);
end
if (`APB4_BFM_IF.pslverr !== expected_error) begin
$fatal(1, "APB4 %s %h error=%b expected=%b", write ? "write" : "read", address,
`APB4_BFM_IF.pslverr, expected_error);
end
rdata = `APB4_BFM_IF.prdata;
`APB4_BFM_IF.psel = 1'b0;
`APB4_BFM_IF.penable = 1'b0;
`APB4_BFM_IF.pwrite = 1'b0;
`APB4_BFM_IF.pstrb = '0;
end
endtask
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
input logic [3:0] strobe, input logic expected_error);
logic [31:0] unused_rdata;
begin
apb4_xfer(address, 1'b1, data, strobe, expected_error, unused_rdata);
end
endtask
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
output logic [31:0] data);
begin
apb4_xfer(address, 1'b0, 32'd0, 4'h0, expected_error, data);
end
endtask
+47
View File
@@ -0,0 +1,47 @@
`timescale 1ns / 1ps
`include "mmap_define.svh"
module apb4_topology_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b1;
logic [31:0] s_decode_addr = 32'd0;
`include "apb4_periph_declarations.svh"
`include "apb4_periph_select_routes.svh"
always #5 clk_i = ~clk_i;
task automatic expect_select(input logic [31:0] address, input integer slot);
begin
s_decode_addr = address;
#1;
if (s_psel_comb !== (18'd1 << slot)) begin
$fatal(1, "unexpected APB4 target slot for %h: got %b", address, s_psel_comb);
end
end
endtask
task automatic expect_disabled(input logic [31:0] address);
begin
s_decode_addr = address;
#1;
if (s_psel_comb !== '0) begin
$fatal(1, "disabled APB4 target accepted %h: got %b", address, s_psel_comb);
end
end
endtask
initial begin
expect_select(`SOC_ADDR_APB4_GPIO_BASE, 1);
expect_select(`SOC_ADDR_APB4_GPIO_ADMIN_BASE, 1);
expect_select(`SOC_ADDR_APB4_PSRAM_BASE, 4);
expect_select(`SOC_ADDR_APB4_XPI_BASE, 9);
expect_select(`SOC_ADDR_APB4_SDRAM_BASE, 13);
expect_select(`SOC_ADDR_APB4_I2C1_BASE, 17);
expect_disabled(`SOC_ADDR_APB4_SDIO_BASE);
expect_disabled(`SOC_ADDR_APB4_OPIPSRAM_BASE);
$display("SoC topology APB4 routing test passed");
$finish;
end
endmodule
+1 -1
View File
@@ -62,7 +62,7 @@ module axi4_interconnect_tb;
.perf_mgmt_wait_o (),
.perf_user_wait_o (),
.perf_dma_wait_o (),
.perf_ribp_wait_o (),
.perf_apb4_wait_o (),
.perf_apb_wait_o (),
.perf_sdram_wait_o(),
.perf_psram_wait_o(),
@@ -2,7 +2,7 @@
`include "axi4_define.svh"
module axi42ribp_burst_tb;
module axi4_word_bridge_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic [31:0] memory [0:63];
@@ -22,39 +22,51 @@ module axi42ribp_burst_tb;
.aclk (clk_i),
.aresetn(rst_n_i)
);
ribp_if ribp ();
logic req_valid;
logic req_ready;
logic [31:0] req_addr;
logic [31:0] req_wdata;
logic [ 3:0] req_wstrb;
logic [31:0] req_rdata;
logic req_resp_err;
always #5 clk_i = ~clk_i;
always @(posedge clk_i) cycle_count <= cycle_count + 1;
axi42ribp_burst u_dut (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.axi4 (axi4),
.ribp (ribp)
axi4_word_bridge u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.axi4 (axi4),
.req_valid_o (req_valid),
.req_ready_i (req_ready),
.req_addr_o (req_addr),
.req_wdata_o (req_wdata),
.req_wstrb_o (req_wstrb),
.req_rdata_i (req_rdata),
.req_resp_err_i(req_resp_err)
);
always_ff @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
ribp.ready <= 1'b0;
ribp.rdata <= '0;
req_ready <= 1'b0;
req_rdata <= '0;
target_accesses <= 0;
end else begin
ribp.ready <= ribp.valid && !ribp.ready;
if (ribp.valid && !ribp.ready) begin
req_ready <= req_valid && !req_ready;
if (req_valid && !req_ready) begin
target_accesses <= target_accesses + 1;
ribp.rdata <= memory[ribp.addr[7:2]];
req_rdata <= memory[req_addr[7:2]];
for (int lane = 0; lane < 4; lane++) begin
if (ribp.wstrb[lane]) begin
memory[ribp.addr[7:2]][lane*8+:8] <= ribp.wdata[lane*8+:8];
if (req_wstrb[lane]) begin
memory[req_addr[7:2]][lane*8+:8] <= req_wdata[lane*8+:8];
end
end
end
end
end
assign ribp.resp_err = 1'b0;
assign req_resp_err = 1'b0;
task automatic init_axi4;
begin
@@ -172,7 +184,7 @@ module axi42ribp_burst_tb;
@(negedge clk_i);
axi4.rready = 1'b0;
if (target_accesses != accesses_before) begin
$fatal(1, "illegal burst reached the RIBP target");
$fatal(1, "illegal burst reached the word target");
end
end
endtask
@@ -204,7 +216,7 @@ module axi42ribp_burst_tb;
axi4.bready = 1'b0;
axi4.wlast = 1'b0;
if (target_accesses != accesses_before + 1) begin
$fatal(1, "early WLAST must commit exactly one RIBP beat");
$fatal(1, "early WLAST must commit exactly one word beat");
end
end
endtask
@@ -299,8 +311,8 @@ module axi42ribp_burst_tb;
$fatal(1, "16-beat burst improvement is below 20%%: burst=%0d single=%0d", burst_cycles,
single_cycles);
end
if (target_accesses != 49) $fatal(1, "unexpected RIBP access count");
$display("AXI4 to RIBP burst bridge test passed");
if (target_accesses != 49) $fatal(1, "unexpected word access count");
$display("AXI4 word bridge test passed");
$finish;
end
endmodule
+29 -14
View File
@@ -11,7 +11,7 @@ module bus_fault_tb;
logic [ 1:0] fault_master_o;
logic [ 2:0] fault_code_o;
logic user_bus_idle_o;
ribp_if mgmt_ribp ();
rib_if mgmt_rib ();
rib_if user_rib ();
rib_if dma_rib ();
rib_if rib ();
@@ -39,7 +39,7 @@ module bus_fault_tb;
rib_bus u_bus (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mgmt_ribp (mgmt_ribp),
.mgmt_rib (mgmt_rib),
.user_rib (user_rib),
.dma_rib (dma_rib),
.user_bus_enable_i(1'b1),
@@ -61,22 +61,32 @@ module bus_fault_tb;
input logic reserved, input logic [2:0] expected_code);
begin
@(negedge clk_i);
mgmt_ribp.addr = address;
mgmt_ribp.wdata = 32'hA5A5_5A5A;
mgmt_ribp.wstrb = write_strobes;
mgmt_ribp.valid = 1'b1;
mgmt_rib.cmd_addr = address;
mgmt_rib.cmd_write = |write_strobes;
mgmt_rib.cmd_len = `RIB_LEN_INCR1;
mgmt_rib.cmd_valid = 1'b1;
while (!mgmt_rib.cmd_ready) @(posedge clk_i);
@(negedge clk_i);
mgmt_rib.cmd_valid = 1'b0;
if (|write_strobes) begin
mgmt_rib.wdata = 32'hA5A5_5A5A;
mgmt_rib.wstrb = write_strobes;
mgmt_rib.wlast = 1'b1;
mgmt_rib.w_valid = 1'b1;
while (!mgmt_rib.w_ready) @(posedge clk_i);
@(negedge clk_i);
mgmt_rib.w_valid = 1'b0;
end
while (!fault_valid_o) @(posedge clk_i);
if (fault_addr_o !== address || fault_wstrb_o !== write_strobes ||
fault_reserved_o !== reserved || fault_access_o || fault_code_o !== expected_code ||
rib.cmd_valid || apb_rib.cmd_valid) begin
$fatal(1, "unexpected fault response for address %h", address);
end
while (!mgmt_ribp.ready) @(posedge clk_i);
if (mgmt_ribp.rdata !== 32'd0 || !mgmt_ribp.resp_err) begin
while (!mgmt_rib.rsp_valid) @(posedge clk_i);
if (mgmt_rib.rdata !== 32'd0 || !mgmt_rib.resp_err) begin
$fatal(1, "fault response data must be zero");
end
@(negedge clk_i);
mgmt_ribp.valid = 1'b0;
while (fault_valid_o) @(posedge clk_i);
end
endtask
@@ -113,10 +123,15 @@ module bus_fault_tb;
endtask
initial begin
mgmt_ribp.valid = 1'b0;
mgmt_ribp.addr = '0;
mgmt_ribp.wdata = '0;
mgmt_ribp.wstrb = '0;
mgmt_rib.cmd_valid = 1'b0;
mgmt_rib.cmd_addr = '0;
mgmt_rib.cmd_write = 1'b0;
mgmt_rib.cmd_len = `RIB_LEN_INCR1;
mgmt_rib.w_valid = 1'b0;
mgmt_rib.wdata = '0;
mgmt_rib.wstrb = '0;
mgmt_rib.wlast = 1'b0;
mgmt_rib.rsp_ready = 1'b1;
user_rib.cmd_valid = 1'b0;
user_rib.cmd_addr = '0;
user_rib.cmd_write = 1'b0;
+53 -39
View File
@@ -8,7 +8,10 @@ module clint_tb;
logic timebase_tick;
logic [31:0] value;
integer timebase_tick_count = 0;
ribp_if ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
clint_if #(.HartNum(2)) clint ();
always #5 clk_i = ~clk_i;
@@ -29,47 +32,58 @@ module clint_tb;
.tick_o (timebase_tick)
);
ribp_clint #(
apb4_clint #(
.HartNum(2)
) u_dut (
.clk_i,
.rst_n_i,
.timebase_tick_i(tick_i),
.ribp,
.apb4,
.clint
);
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
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);
ribp.valid = 1'b1;
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = strobe;
do @(negedge clk_i); while (!ribp.ready);
if (ribp.resp_err !== expected_error) begin
$fatal(1, "write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
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
ribp.valid = 1'b0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
task automatic ribp_read(input logic [31:0] address, output logic [31:0] data,
task automatic apb4_read(input logic [31:0] address, output logic [31:0] data,
input logic expected_error);
begin
@(negedge clk_i);
ribp.valid = 1'b1;
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
do @(negedge clk_i); while (!ribp.ready);
data = ribp.rdata;
if (ribp.resp_err !== expected_error) begin
$fatal(1, "read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
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
ribp.valid = 1'b0;
data = apb4.prdata;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
@@ -83,45 +97,45 @@ module clint_tb;
endtask
initial begin
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
ribp_read(32'h0000_0000, value, 1'b0);
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
ribp_read(32'h0000_4000, value, 1'b0);
apb4_read(32'h0000_4000, value, 1'b0);
if (value != 32'hFFFF_FFFF) $fatal(1, "MTIMECMP low reset state is invalid");
ribp_read(32'h0000_4004, value, 1'b0);
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
ribp_write(32'h0000_0004, 32'h0000_0001, 4'h1, 1'b0);
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");
ribp_write(32'h0000_0004, 32'h0000_0000, 4'h1, 1'b0);
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");
ribp_write(32'h0000_BFFC, 32'd0, 4'hF, 1'b0);
ribp_write(32'h0000_BFF8, 32'd10, 4'hF, 1'b0);
ribp_read(32'h0000_BFF8, value, 1'b0);
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);
ribp_write(32'h0000_4004, 32'd0, 4'hF, 1'b0);
ribp_write(32'h0000_4000, 32'd12, 4'hF, 1'b0);
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");
ribp_write(32'h0000_4001, 32'd0, 4'hF, 1'b1);
ribp_read(32'h0000_0010, value, 1'b1);
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);
+38 -25
View File
@@ -7,9 +7,12 @@ module dvp_tb;
logic href_i = 1'b0;
logic vsync_i = 1'b0;
logic [ 7:0] dat_i = 8'd0;
logic [31:0] ribp_rdata;
logic [31:0] apb4_rdata;
logic irq_o;
ribp_if ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
axi4_stream_if #(
.DATA_WIDTH(32),
.ID_WIDTH (1),
@@ -32,7 +35,7 @@ module dvp_tb;
axi4s_dvp u_dut (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.ribp (ribp),
.apb4 (apb4),
.rx_axis(axis),
.dvp (dvp),
.irq_o (irq_o)
@@ -41,27 +44,37 @@ module dvp_tb;
task automatic write(input logic [31:0] address, input logic [31:0] data);
begin
@(negedge clk_i);
ribp.valid = 1'b1;
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = 4'hf;
do @(negedge clk_i); while (!ribp.ready);
if (ribp.resp_err) $fatal(1, "unexpected write error at %h", address);
ribp.valid = 1'b0;
ribp.wstrb = '0;
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);
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
task automatic read(input logic [31:0] address, output logic [31:0] data);
begin
@(negedge clk_i);
ribp.valid = 1'b1;
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
do @(negedge clk_i); while (!ribp.ready);
data = ribp.rdata;
ribp.valid = 1'b0;
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);
data = apb4.prdata;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
@@ -106,16 +119,16 @@ module dvp_tb;
end
end
initial begin
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
read(32'h0000_00f8, value);
if (value != 32'h0002_0000) $fatal(1, "bad DVP version %h", value);
read(32'h0000_0100, value);
if (!ribp.resp_err) $fatal(1, "invalid DVP access was accepted");
if (!apb4.pslverr) $fatal(1, "invalid DVP access was accepted");
write(32'h0000_0018, {16'd2, 16'd4});
write(32'h0000_000c, 32'd1);
write(32'h0000_0000, 32'd3);
@@ -127,8 +140,8 @@ module dvp_tb;
check_frame(1, 3, 2);
write(32'h0000_0048, 32'h0000_0004);
read(32'h0000_003c, value);
if (ribp.resp_err) $fatal(1, "DVP interrupt read failed");
$display("RIBP DVP capture test passed");
if (apb4.pslverr) $fatal(1, "DVP interrupt read failed");
$display("APB4 DVP capture test passed");
$finish;
end
endmodule
+73 -71
View File
@@ -9,14 +9,17 @@ module gpio_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
ribp_if ribp ();
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;
ribp_gpio #(
apb4_gpio #(
.PinNum (PinNum),
.UserBaseAddr (USER_BASE),
.AdminBaseAddr(ADMIN_BASE),
@@ -26,7 +29,7 @@ module gpio_tb;
) dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.ribp (ribp),
.apb4 (apb4),
.gpio (gpio),
.user_gpio(user_gpio)
);
@@ -35,19 +38,22 @@ module gpio_tb;
input logic expected_error);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = 4'hF;
ribp.valid = 1'b1;
@(posedge clk_i);
#1;
if (!ribp.ready || (ribp.resp_err !== expected_error)) begin
$fatal(1, "write response mismatch at %08x", address);
end
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);
ribp.valid = 1'b0;
@(posedge clk_i);
#1;
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
@@ -55,28 +61,32 @@ module gpio_tb;
input logic expected_error);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
ribp.valid = 1'b1;
@(posedge clk_i);
#1;
if (!ribp.ready || (ribp.resp_err !== expected_error)) begin
$fatal(1, "read response mismatch at %08x", address);
end
data = ribp.rdata;
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
ribp.valid = 1'b0;
@(posedge clk_i);
#1;
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
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
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;
@@ -89,83 +99,75 @@ module gpio_tb;
rst_n_i = 1'b1;
repeat (3) @(posedge clk_i);
read_register(ADMIN_BASE + `RIBP_GPIO_CAPABILITY, read_data, 1'b0);
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 + `RIBP_GPIO_PAD_CAPABILITY, read_data, 1'b0);
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 + `RIBP_GPIO_ADMIN_OUTPUT_ENABLE, read_data, 1'b0);
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 + `RIBP_GPIO_ADMIN_OUT_SET, 32'h1, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OE_SET, 32'h1, 1'b0);
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 + `RIBP_GPIO_ADMIN_OUT_TOGGLE, 32'h1, 1'b0);
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 + `RIBP_GPIO_ADMIN_USER_ACCESS_MASK, 32'h2, 1'b0);
write_register(USER_BASE + `RIBP_GPIO_USER_OUT_SET, 32'h6, 1'b0);
read_register(USER_BASE + `RIBP_GPIO_USER_DATA_OUT, read_data, 1'b0);
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);
ribp.addr = ADMIN_BASE + `RIBP_GPIO_ADMIN_USER_SELECT;
ribp.wdata = 32'h4;
ribp.wstrb = 4'hF;
ribp.valid = 1'b1;
@(posedge clk_i);
#1;
if (gpio.oe_o[2] !== 1'b0) $fatal(1, "user handoff did not force high impedance");
@(negedge clk_i);
ribp.valid = 1'b0;
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 + `RIBP_GPIO_ADMIN_OE_SET, 32'h2, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OPEN_DRAIN, 32'h2, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OUT_SET, 32'h2, 1'b0);
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 + `RIBP_GPIO_ADMIN_OUT_CLEAR, 32'h2, 1'b0);
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 + `RIBP_GPIO_ADMIN_PULL_UP, 32'h8, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_PULL_DOWN, 32'h8, 1'b1);
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 + `RIBP_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h1, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_ENABLE, 32'h1, 1'b0);
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 + `RIBP_GPIO_ADMIN_INTR_STATE, read_data, 1'b0);
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 + `RIBP_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
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 + `RIBP_GPIO_ADMIN_INTR_TEST, 32'h1, 1'b0);
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 + `RIBP_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h9, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_HIGH_ENABLE, 32'h8, 1'b1);
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 + `RIBP_GPIO_ADMIN_FILTER_DIV, 32'h0, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_FILTER_COUNT, 32'h4, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_FILTER_ENABLE, 32'h8, 1'b0);
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 + `RIBP_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
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 + `RIBP_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
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 + `RIBP_GPIO_ADMIN_CONFIG_LOCK, 32'h1, 1'b0);
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OE_CLEAR, 32'h1, 1'b1);
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");
+82 -73
View File
@@ -1,6 +1,6 @@
`timescale 1ns / 1ps
`include "ribp_i2c_define.svh"
`include "apb4_i2c_define.svh"
module i2c_tb;
logic clk_i = 1'b0;
@@ -11,7 +11,10 @@ module i2c_tb;
logic slave_sda_low = 1'b0;
logic scl_line;
logic sda_line;
ribp_if ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
i2c_if i2c ();
always #5 clk_i = ~clk_i;
@@ -21,54 +24,57 @@ module i2c_tb;
assign i2c.scl_i = scl_line;
assign i2c.sda_i = sda_line;
ribp_i2c u_dut (
apb4_i2c 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),
.ribp (ribp),
.apb4 (apb4),
.i2c (i2c)
);
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
input logic expected_error);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = 4'hF;
ribp.valid = 1'b1;
while (!ribp.ready) begin
@(posedge clk_i);
#1;
end
if (ribp.resp_err !== expected_error) begin
$fatal(1, "I2C write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
end
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);
ribp.valid = 1'b0;
ribp.wstrb = '0;
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 ribp_read(input logic [31:0] address, input logic expected_error,
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
output logic [31:0] data);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
ribp.valid = 1'b1;
while (!ribp.ready) begin
@(posedge clk_i);
#1;
end
if (ribp.resp_err !== expected_error) begin
$fatal(1, "I2C read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
end
data = ribp.rdata;
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
ribp.valid = 1'b0;
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
@@ -124,26 +130,26 @@ module i2c_tb;
begin
value = '0;
for (attempts = 0; attempts < 4000; attempts = attempts + 1) begin
ribp_read(`RIBP_I2C_INTR_STATE, 1'b0, value);
apb4_read(`APB4_I2C_INTR_STATE, 1'b0, value);
if (value[`I2C_INTR_DONE]) begin
attempts = 4000;
end
end
if (!value[`I2C_INTR_DONE]) begin
ribp_read(`RIBP_I2C_ERROR_STATUS, 1'b0, error_value);
ribp_read(`RIBP_I2C_STATUS, 1'b0, status_value);
apb4_read(`APB4_I2C_ERROR_STATUS, 1'b0, error_value);
apb4_read(`APB4_I2C_STATUS, 1'b0, status_value);
$fatal(1, "I2C transaction did not complete: error=%h status=%h fsm=%0d", error_value,
status_value, u_dut.u_i2c_core.s_fsm_q);
end
ribp_write(`RIBP_I2C_INTR_STATE, 32'hFF, 1'b0);
apb4_write(`APB4_I2C_INTR_STATE, 32'hFF, 1'b0);
end
endtask
task automatic clear_state;
begin
ribp_write(`RIBP_I2C_ERROR_STATUS, 32'h7FF, 1'b0);
ribp_write(`RIBP_I2C_INTR_STATE, 32'hFF, 1'b0);
ribp_write(`RIBP_I2C_COMMAND, 32'hC, 1'b0);
apb4_write(`APB4_I2C_ERROR_STATUS, 32'h7FF, 1'b0);
apb4_write(`APB4_I2C_INTR_STATE, 32'hFF, 1'b0);
apb4_write(`APB4_I2C_COMMAND, 32'hC, 1'b0);
end
endtask
@@ -153,30 +159,33 @@ module i2c_tb;
logic nack;
integer pulse_count;
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pprot = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
repeat (4) @(posedge clk_i);
ribp_read(`RIBP_I2C_IP_VERSION, 1'b0, value);
apb4_read(`APB4_I2C_IP_VERSION, 1'b0, value);
if (value != 32'h0002_0000) $fatal(1, "I2C version mismatch");
ribp_read(`RIBP_I2C_CAPABILITY, 1'b0, value);
apb4_read(`APB4_I2C_CAPABILITY, 1'b0, value);
if (value != 32'h007F_1010) $fatal(1, "I2C capability mismatch: %h", value);
ribp_read(32'h2, 1'b1, value);
apb4_read(32'h2, 1'b1, value);
ribp_write(`RIBP_I2C_SCL_TIMING, 32'h0008_0008, 1'b0);
ribp_write(`RIBP_I2C_START_TIMING, 32'h0002_0002, 1'b0);
ribp_write(`RIBP_I2C_DATA_TIMING, 32'h0001_0000, 1'b0);
ribp_write(`RIBP_I2C_STOP_TIMING, 32'h0002_0002, 1'b0);
ribp_write(`RIBP_I2C_FILTER, 0, 1'b0);
ribp_write(`RIBP_I2C_STRETCH_TIMEOUT, 200, 1'b0);
ribp_write(`RIBP_I2C_BUS_IDLE_TIMEOUT, 200, 1'b0);
ribp_write(`RIBP_I2C_COMMAND_TIMEOUT, 2000, 1'b0);
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h50, 1'b0);
ribp_write(`RIBP_I2C_CTRL, 1, 1'b0);
apb4_write(`APB4_I2C_SCL_TIMING, 32'h0008_0008, 1'b0);
apb4_write(`APB4_I2C_START_TIMING, 32'h0002_0002, 1'b0);
apb4_write(`APB4_I2C_DATA_TIMING, 32'h0001_0000, 1'b0);
apb4_write(`APB4_I2C_STOP_TIMING, 32'h0002_0002, 1'b0);
apb4_write(`APB4_I2C_FILTER, 0, 1'b0);
apb4_write(`APB4_I2C_STRETCH_TIMEOUT, 200, 1'b0);
apb4_write(`APB4_I2C_BUS_IDLE_TIMEOUT, 200, 1'b0);
apb4_write(`APB4_I2C_COMMAND_TIMEOUT, 2000, 1'b0);
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h50, 1'b0);
apb4_write(`APB4_I2C_CTRL, 1, 1'b0);
fork
begin
@@ -187,13 +196,13 @@ module i2c_tb;
if (byte_value != 8'hA5) $fatal(1, "write data mismatch: %h", byte_value);
end
begin
ribp_write(`RIBP_I2C_DATA_CMD, 32'h4A5, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'h4A5, 1'b0);
wait_done();
end
join
clear_state();
ribp_write(`RIBP_I2C_TARGET_ADDR, 32'h0000_06AA, 1'b0);
apb4_write(`APB4_I2C_TARGET_ADDR, 32'h0000_06AA, 1'b0);
fork
begin
wait_start();
@@ -208,15 +217,15 @@ module i2c_tb;
if (!nack) $fatal(1, "final 10-bit read byte was not NACKed");
end
begin
ribp_write(`RIBP_I2C_DATA_CMD, 32'hD00, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'hD00, 1'b0);
wait_done();
ribp_read(`RIBP_I2C_RXDATA, 1'b0, value);
apb4_read(`APB4_I2C_RXDATA, 1'b0, value);
if (value[7:0] != 8'hC3) $fatal(1, "10-bit read data mismatch: %h", value);
end
join
clear_state();
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h50, 1'b0);
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h50, 1'b0);
fork
begin
wait_start();
@@ -231,10 +240,10 @@ module i2c_tb;
if (!nack) $fatal(1, "final read byte was not NACKed");
end
begin
ribp_write(`RIBP_I2C_DATA_CMD, 32'h012, 1'b0);
ribp_write(`RIBP_I2C_DATA_CMD, 32'hF00, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'h012, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'hF00, 1'b0);
wait_done();
ribp_read(`RIBP_I2C_RXDATA, 1'b0, value);
apb4_read(`APB4_I2C_RXDATA, 1'b0, value);
if (value[7:0] != 8'h5A) $fatal(1, "read data mismatch: %h", value);
end
join
@@ -247,20 +256,20 @@ module i2c_tb;
receive_byte(byte_value, 0);
end
begin
ribp_write(`RIBP_I2C_DATA_CMD, 32'h45C, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'h45C, 1'b0);
wait_done();
end
join
clear_state();
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h51, 1'b0);
ribp_write(`RIBP_I2C_DATA_CMD, 32'h455, 1'b0);
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h51, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'h455, 1'b0);
repeat (300) @(posedge clk_i);
ribp_read(`RIBP_I2C_ERROR_STATUS, 1'b0, value);
apb4_read(`APB4_I2C_ERROR_STATUS, 1'b0, value);
if (!value[`I2C_ERROR_ADDR_NACK]) $fatal(1, "address NACK was not reported");
clear_state();
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h7F, 1'b0);
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h7F, 1'b0);
fork
begin
wait_start();
@@ -271,11 +280,11 @@ module i2c_tb;
slave_sda_low = 1'b0;
end
begin
ribp_write(`RIBP_I2C_DATA_CMD, 32'h400, 1'b0);
apb4_write(`APB4_I2C_DATA_CMD, 32'h400, 1'b0);
end
join
repeat (20) @(posedge clk_i);
ribp_read(`RIBP_I2C_ERROR_STATUS, 1'b0, value);
apb4_read(`APB4_I2C_ERROR_STATUS, 1'b0, value);
if (!value[`I2C_ERROR_ARB_LOST]) $fatal(1, "arbitration loss was not reported");
clear_state();
@@ -290,11 +299,11 @@ module i2c_tb;
slave_sda_low = 1'b0;
end
begin
ribp_write(`RIBP_I2C_COMMAND, 32'h2, 1'b0);
apb4_write(`APB4_I2C_COMMAND, 32'h2, 1'b0);
end
join
repeat (80) @(posedge clk_i);
ribp_read(`RIBP_I2C_INTR_STATE, 1'b0, value);
apb4_read(`APB4_I2C_INTR_STATE, 1'b0, value);
if (!value[`I2C_INTR_RECOVERY_DONE] || (pulse_count != 9)) begin
$fatal(1, "bus recovery failed: intr=%h pulses=%0d", value, pulse_count);
end
+41 -24
View File
@@ -10,13 +10,16 @@ module pll_ctrl_tb;
logic [31:0] fault_addr_i = '0;
logic [ 3:0] fault_wstrb_i = '0;
logic fault_reserved_i = 1'b0;
ribp_if rib ();
sysctrl_if sysctrl ();
pll_ctrl_if pll_ctrl ();
logic sys_clk_o;
logic sys_rst_n_o;
logic aud_rst_n_o;
logic sys_clkdiv4_o;
apb4_if apb4 (
.pclk (sys_clk_o),
.presetn(sys_rst_n_o)
);
sysctrl_if sysctrl ();
pll_ctrl_if pll_ctrl ();
logic [31:0] read_data;
time edge_start;
time edge_end;
@@ -41,14 +44,14 @@ module pll_ctrl_tb;
.timebase_tick_o()
);
ribp_sysctrl u_sysctrl (
apb4_sysctrl u_sysctrl (
.clk_i (sys_clk_o),
.rst_n_i (sys_rst_n_o),
.fault_valid_i (fault_valid_i),
.fault_addr_i (fault_addr_i),
.fault_wstrb_i (fault_wstrb_i),
.fault_reserved_i(fault_reserved_i),
.ribp (rib),
.apb4 (apb4),
.sysctrl (sysctrl),
.pll_ctrl (pll_ctrl)
);
@@ -56,29 +59,43 @@ module pll_ctrl_tb;
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
begin
@(negedge sys_clk_o);
rib.addr = address;
rib.wdata = '0;
rib.wstrb = '0;
rib.valid = 1'b1;
while (!rib.ready) @(posedge sys_clk_o);
data = rib.rdata;
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge sys_clk_o);
rib.valid = 1'b0;
while (rib.ready) @(posedge sys_clk_o);
apb4.penable = 1'b1;
while (!apb4.pready) @(negedge sys_clk_o);
if (apb4.pslverr !== 1'b0) begin
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
end
data = apb4.prdata;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
task automatic write_register(input logic [31:0] address, input logic [31:0] data);
begin
@(negedge sys_clk_o);
rib.addr = address;
rib.wdata = data;
rib.wstrb = 4'hF;
rib.valid = 1'b1;
while (!rib.ready) @(posedge sys_clk_o);
apb4.paddr = address;
apb4.pwdata = data;
apb4.pstrb = 4'hF;
apb4.pwrite = 1'b1;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge sys_clk_o);
rib.valid = 1'b0;
while (rib.ready) @(posedge sys_clk_o);
apb4.penable = 1'b1;
while (!apb4.pready) @(negedge sys_clk_o);
if (apb4.pslverr !== 1'b0) begin
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
end
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
@@ -101,10 +118,10 @@ module pll_ctrl_tb;
endtask
initial begin
rib.valid = 1'b0;
rib.addr = '0;
rib.wdata = '0;
rib.wstrb = '0;
apb4.psel = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
sysctrl.user_bus_idle_i = 1'b1;
sysctrl.fault_access_i = 1'b0;
sysctrl.fault_master_i = '0;
+68 -56
View File
@@ -17,7 +17,10 @@ module psram_tb;
logic [ 1:0] held_resp;
logic held_last;
ribp_if cfg_ribp ();
apb4_if cfg_apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
axi4_if #(
.ADDR_WIDTH(32),
.DATA_WIDTH(32),
@@ -38,10 +41,10 @@ module psram_tb;
end
assign psram.io_di_i = psram_sio;
ribp_psram u_dut (
apb4_psram u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.cfg_ribp(cfg_ribp),
.cfg_apb4(cfg_apb4),
.mem_axi4(mem_axi4),
.psram (psram)
);
@@ -131,39 +134,48 @@ module psram_tb;
end
endtask
task automatic ribp_write(input logic [31:0] offset, input logic [31:0] data,
task automatic apb4_write(input logic [31:0] offset, input logic [31:0] data,
input logic [3:0] strobe, input logic expected_error);
begin
@(negedge clk_i);
cfg_ribp.addr = offset;
cfg_ribp.wdata = data;
cfg_ribp.wstrb = strobe;
cfg_ribp.valid = 1'b1;
do @(negedge clk_i); while (!cfg_ribp.ready);
if (cfg_ribp.resp_err != expected_error) begin
$fatal(1, "RIBP write response mismatch at %08x", offset);
end
cfg_ribp.valid = 1'b0;
cfg_ribp.wstrb = '0;
cfg_apb4.paddr = offset;
cfg_apb4.pwdata = data;
cfg_apb4.pstrb = strobe;
cfg_apb4.pwrite = 1'b1;
cfg_apb4.psel = 1'b1;
cfg_apb4.penable = 1'b0;
@(negedge clk_i);
cfg_apb4.penable = 1'b1;
while (!cfg_apb4.pready) @(negedge clk_i);
if (cfg_apb4.pslverr !== expected_error) begin
$fatal(1, "write %h error=%b expected=%b", offset, cfg_apb4.pslverr, expected_error);
end
cfg_apb4.psel = 1'b0;
cfg_apb4.penable = 1'b0;
cfg_apb4.pwrite = 1'b0;
cfg_apb4.pstrb = '0;
end
endtask
task automatic ribp_read(input logic [31:0] offset, input logic expected_error,
task automatic apb4_read(input logic [31:0] offset, input logic expected_error,
output logic [31:0] data);
begin
@(negedge clk_i);
cfg_ribp.addr = offset;
cfg_ribp.wdata = '0;
cfg_ribp.wstrb = '0;
cfg_ribp.valid = 1'b1;
do @(negedge clk_i); while (!cfg_ribp.ready);
if (cfg_ribp.resp_err != expected_error) begin
$fatal(1, "RIBP read response mismatch at %08x", offset);
end
data = cfg_ribp.rdata;
cfg_ribp.valid = 1'b0;
cfg_apb4.paddr = offset;
cfg_apb4.pwdata = '0;
cfg_apb4.pstrb = '0;
cfg_apb4.pwrite = 1'b0;
cfg_apb4.psel = 1'b1;
cfg_apb4.penable = 1'b0;
@(negedge clk_i);
cfg_apb4.penable = 1'b1;
while (!cfg_apb4.pready) @(negedge clk_i);
if (cfg_apb4.pslverr !== expected_error) begin
$fatal(1, "read %h error=%b expected=%b", offset, cfg_apb4.pslverr, expected_error);
end
data = cfg_apb4.prdata;
cfg_apb4.psel = 1'b0;
cfg_apb4.penable = 1'b0;
end
endtask
@@ -172,7 +184,7 @@ module psram_tb;
reg_data = '0;
for (int poll = 0; poll < 200; poll++) begin
repeat (20) @(posedge clk_i);
ribp_read(`RIBP_PSRAM_INTR_STATE, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_INTR_STATE, 1'b0, reg_data);
if (reg_data[`PSRAM_INTR_INIT_DONE]) return;
end
$fatal(1, "PSRAM initialization timed out");
@@ -184,7 +196,7 @@ module psram_tb;
reg_data = '0;
for (int poll = 0; poll < 100; poll++) begin
repeat (10) @(posedge clk_i);
ribp_read(`RIBP_PSRAM_INTR_STATE, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_INTR_STATE, 1'b0, reg_data);
if (reg_data[`PSRAM_INTR_INDIRECT_DONE]) return;
end
$fatal(1, "PSRAM indirect command timed out");
@@ -343,39 +355,39 @@ module psram_tb;
endtask
initial begin
cfg_ribp.valid = 1'b0;
cfg_ribp.addr = '0;
cfg_ribp.wdata = '0;
cfg_ribp.wstrb = '0;
cfg_apb4.psel = 1'b0;
cfg_apb4.paddr = '0;
cfg_apb4.pwdata = '0;
cfg_apb4.pstrb = '0;
init_axi4();
repeat (5) @(posedge clk_i);
rst_n_i = 1'b1;
$display("PSRAM_TB_STAGE register_setup");
ribp_write(`RIBP_PSRAM_POWERUP_CYCLES, 32'd1, 4'hF, 1'b0);
ribp_write(`RIBP_PSRAM_CS_HIGH_CYCLES, 32'd2, 4'hF, 1'b0);
ribp_write(`RIBP_PSRAM_CS_HOLD_CYCLES, 32'd3, 4'hF, 1'b0);
ribp_write(`RIBP_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
ribp_write(`RIBP_PSRAM_ACCESS_TIMEOUT_CYCLES, 32'd1024, 4'hF, 1'b0);
ribp_write(`RIBP_PSRAM_PERF_CTRL, 32'd1, 4'h1, 1'b0);
ribp_write(`RIBP_PSRAM_STATUS, 32'd1, 4'h1, 1'b1);
ribp_read(32'h0000_0002, 1'b1, reg_data);
ribp_read(32'h0000_00B0, 1'b1, reg_data);
ribp_write(`RIBP_PSRAM_COMMAND, 32'h0000_0003, 4'h1, 1'b1);
apb4_write(`APB4_PSRAM_POWERUP_CYCLES, 32'd1, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_CS_HIGH_CYCLES, 32'd2, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_CS_HOLD_CYCLES, 32'd3, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_ACCESS_TIMEOUT_CYCLES, 32'd1024, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_PERF_CTRL, 32'd1, 4'h1, 1'b0);
apb4_write(`APB4_PSRAM_STATUS, 32'd1, 4'h1, 1'b1);
apb4_read(32'h0000_0002, 1'b1, reg_data);
apb4_read(32'h0000_00B0, 1'b1, reg_data);
apb4_write(`APB4_PSRAM_COMMAND, 32'h0000_0003, 4'h1, 1'b1);
$display("PSRAM_TB_STAGE initialization");
ribp_write(`RIBP_PSRAM_COMMAND, 32'h0000_0001, 4'h1, 1'b0);
apb4_write(`APB4_PSRAM_COMMAND, 32'h0000_0001, 4'h1, 1'b0);
wait_for_init();
ribp_read(`RIBP_PSRAM_CHIP_PRESENT, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP_PRESENT, 1'b0, reg_data);
if (reg_data[3:0] != 4'b1011) $fatal(1, "unexpected present mask");
ribp_read(`RIBP_PSRAM_CHIP_READY, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP_READY, 1'b0, reg_data);
if (reg_data[3:0] != 4'b1011) $fatal(1, "unexpected ready mask");
ribp_read(`RIBP_PSRAM_CHIP_ERROR, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP_ERROR, 1'b0, reg_data);
if (reg_data[3:0] != 4'b0100) $fatal(1, "missing-device error not isolated");
ribp_read(`RIBP_PSRAM_CHIP0_ID_LO, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP0_ID_LO, 1'b0, reg_data);
if (reg_data != 32'h0026_5D0D) $fatal(1, "chip ID mismatch");
ribp_read(`RIBP_PSRAM_CHIP_MODE, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP_MODE, 1'b0, reg_data);
if (reg_data[3:0] != 4'b1011) $fatal(1, "QPI mode mask mismatch");
$display("PSRAM_TB_STAGE basic_axi");
@@ -407,28 +419,28 @@ module psram_tb;
if (read_data != 32'hC001_CAFE) $fatal(1, "healthy chip after missing device failed");
$display("PSRAM_TB_STAGE indirect");
ribp_write(`RIBP_PSRAM_INTR_STATE, 32'hF, 4'h1, 1'b0);
ribp_write(`RIBP_PSRAM_INDIRECT_CTRL, 32'h8000_0009, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_INTR_STATE, 32'hF, 4'h1, 1'b0);
apb4_write(`APB4_PSRAM_INDIRECT_CTRL, 32'h8000_0009, 4'hF, 1'b0);
wait_for_indirect();
ribp_read(`RIBP_PSRAM_CHIP_MODE, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP_MODE, 1'b0, reg_data);
if (!reg_data[4]) $fatal(1, "wrap32 mode did not update");
$display("PSRAM_TB_STAGE timeout");
ribp_write(`RIBP_PSRAM_CS_MAX_LOW_CYCLES, 32'd20, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_CS_MAX_LOW_CYCLES, 32'd20, 4'hF, 1'b0);
axi_read_single(PsramBase + 32'h0080_0800, `AXI4_BURST_SIZE_4BYTES, `AXI4_RESP_SLAVE_ERROR,
read_data);
ribp_read(`RIBP_PSRAM_CHIP_READY, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_CHIP_READY, 1'b0, reg_data);
if (reg_data[3:0] != 4'b1001) $fatal(1, "timeout fault was not isolated");
ribp_write(`RIBP_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
apb4_write(`APB4_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
axi_read_single(PsramBase + 32'h0180_0300, `AXI4_BURST_SIZE_4BYTES, `AXI4_RESP_OKAY, read_data);
if (read_data != 32'hC001_CAFE) $fatal(1, "healthy chip failed after timeout");
$display("PSRAM_TB_STAGE counters");
ribp_read(`RIBP_PSRAM_PERF_READ_BYTES, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_PERF_READ_BYTES, 1'b0, reg_data);
if (reg_data == 32'd0) $fatal(1, "read performance counter did not advance");
ribp_read(`RIBP_PSRAM_PERF_WRITE_BYTES, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_PERF_WRITE_BYTES, 1'b0, reg_data);
if (reg_data == 32'd0) $fatal(1, "write performance counter did not advance");
ribp_read(`RIBP_PSRAM_PERF_COMMANDS, 1'b0, reg_data);
apb4_read(`APB4_PSRAM_PERF_COMMANDS, 1'b0, reg_data);
if (reg_data == 32'd0) $fatal(1, "command performance counter did not advance");
$display("PSRAM controller integration test passed");
+12 -7
View File
@@ -16,7 +16,7 @@ module rib_bus_tb;
logic fault_valid_o;
logic [2:0] fault_code_o;
logic user_bus_idle_o;
ribp_if mgmt_ribp ();
rib_if mgmt_rib ();
rib_if user_rib ();
rib_if dma_rib ();
rib_if rib ();
@@ -69,7 +69,7 @@ module rib_bus_tb;
rib_bus u_bus (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mgmt_ribp (mgmt_ribp),
.mgmt_rib (mgmt_rib),
.user_rib (user_rib),
.dma_rib (dma_rib),
.user_bus_enable_i(1'b1),
@@ -88,7 +88,7 @@ module rib_bus_tb;
.perf_mgmt_wait_o (),
.perf_user_wait_o (),
.perf_dma_wait_o (),
.perf_ribp_wait_o (),
.perf_apb4_wait_o (),
.perf_apb_wait_o (),
.perf_sdram_wait_o(),
.perf_psram_wait_o(),
@@ -135,10 +135,15 @@ module rib_bus_tb;
endtask
initial begin
mgmt_ribp.valid = 1'b0;
mgmt_ribp.addr = '0;
mgmt_ribp.wdata = '0;
mgmt_ribp.wstrb = '0;
mgmt_rib.cmd_valid = 1'b0;
mgmt_rib.cmd_addr = '0;
mgmt_rib.cmd_write = 1'b0;
mgmt_rib.cmd_len = `RIB_LEN_INCR1;
mgmt_rib.w_valid = 1'b0;
mgmt_rib.wdata = '0;
mgmt_rib.wstrb = '0;
mgmt_rib.wlast = 1'b0;
mgmt_rib.rsp_ready = 1'b1;
user_rib.cmd_valid = 1'b0;
user_rib.cmd_addr = '0;
user_rib.cmd_write = 1'b0;
-156
View File
@@ -1,156 +0,0 @@
`timescale 1ns / 1ps
`include "mmap_define.svh"
module ribp_topology_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
ribp_if ribp ();
ribp_if sdram_cfg_ribp ();
`include "ribp_interfaces.svh"
`include "ribp_routes.svh"
always #5 clk_i = ~clk_i;
task automatic expect_route(input logic [31:0] address, input integer slot,
input logic [31:0] expected_rdata);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.valid = 1'b1;
#1;
if (s_slv_sel_d !== (18'd1 << slot)) begin
$fatal(1, "unexpected target slot for %h", address);
end
@(posedge clk_i);
#1;
if (!ribp.ready || ribp.rdata !== expected_rdata) begin
$fatal(1, "unexpected response for %h", address);
end
@(negedge clk_i);
ribp.valid = 1'b0;
@(posedge clk_i);
end
endtask
task automatic expect_disabled(input logic [31:0] address);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.valid = 1'b1;
#1;
if (s_slv_sel_d !== '0) begin
$fatal(1, "disabled target accepted %h", address);
end
@(posedge clk_i);
#1;
if (ribp.ready || ribp.rdata !== 32'd0) begin
$fatal(1, "disabled target responded to %h", address);
end
@(negedge clk_i);
ribp.valid = 1'b0;
@(posedge clk_i);
end
endtask
task automatic expect_error_route(input logic [31:0] address, input integer slot);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.valid = 1'b1;
#1;
if (s_slv_sel_d !== (18'd1 << slot)) begin
$fatal(1, "unexpected error target slot for %h", address);
end
@(posedge clk_i);
#1;
if (!ribp.ready || !ribp.resp_err) begin
$fatal(1, "error response was not propagated for %h", address);
end
@(negedge clk_i);
ribp.valid = 1'b0;
@(posedge clk_i);
end
endtask
initial begin
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
u_uart_ribp_if.ready = 1'b1;
u_gpio_ribp_if.ready = 1'b1;
u_tim0_ribp_if.ready = 1'b1;
u_tim1_ribp_if.ready = 1'b1;
u_psram_ribp_if.ready = 1'b1;
u_spisd_ribp_if.ready = 1'b1;
u_i2c0_ribp_if.ready = 1'b1;
u_i2s_ribp_if.ready = 1'b1;
u_ws2812_ribp_if.ready = 1'b1;
u_xpi_ribp_if.ready = 1'b1;
u_dma_ribp_if.ready = 1'b1;
u_sysctrl_ribp_if.ready = 1'b1;
u_clint_ribp_if.ready = 1'b1;
sdram_cfg_ribp.ready = 1'b1;
u_dvp_ribp_if.ready = 1'b1;
u_sdio_ribp_if.ready = 1'b1;
u_opipsram_ribp_if.ready = 1'b1;
u_i2c1_ribp_if.ready = 1'b1;
u_uart_ribp_if.rdata = 32'h0000_0000;
u_gpio_ribp_if.rdata = 32'h1111_1111;
u_tim0_ribp_if.rdata = 32'h2222_2222;
u_tim1_ribp_if.rdata = 32'h3333_3333;
u_psram_ribp_if.rdata = 32'h4444_4444;
u_spisd_ribp_if.rdata = 32'h5555_5555;
u_i2c0_ribp_if.rdata = 32'h6666_6666;
u_i2s_ribp_if.rdata = 32'h7777_7777;
u_ws2812_ribp_if.rdata = 32'h8888_8888;
u_xpi_ribp_if.rdata = 32'h9999_9999;
u_dma_ribp_if.rdata = 32'hAAAA_AAAA;
u_sysctrl_ribp_if.rdata = 32'hBBBB_BBBB;
u_clint_ribp_if.rdata = 32'hCCCC_CCCC;
sdram_cfg_ribp.rdata = 32'hDDDD_DDDD;
u_dvp_ribp_if.rdata = 32'hEEEE_EEEE;
u_sdio_ribp_if.rdata = 32'hF0F0_F0F0;
u_opipsram_ribp_if.rdata = 32'h0F0F_0F0F;
u_i2c1_ribp_if.rdata = 32'h1234_5678;
u_uart_ribp_if.resp_err = 1'b0;
u_gpio_ribp_if.resp_err = 1'b0;
u_tim0_ribp_if.resp_err = 1'b0;
u_tim1_ribp_if.resp_err = 1'b0;
u_psram_ribp_if.resp_err = 1'b0;
u_spisd_ribp_if.resp_err = 1'b0;
u_i2c0_ribp_if.resp_err = 1'b0;
u_i2s_ribp_if.resp_err = 1'b0;
u_ws2812_ribp_if.resp_err = 1'b0;
u_xpi_ribp_if.resp_err = 1'b0;
u_dma_ribp_if.resp_err = 1'b0;
u_sysctrl_ribp_if.resp_err = 1'b0;
u_clint_ribp_if.resp_err = 1'b0;
sdram_cfg_ribp.resp_err = 1'b0;
u_dvp_ribp_if.resp_err = 1'b0;
u_sdio_ribp_if.resp_err = 1'b0;
u_opipsram_ribp_if.resp_err = 1'b0;
u_i2c1_ribp_if.resp_err = 1'b0;
repeat (2) @(posedge clk_i);
rst_n_i = 1'b1;
expect_route(`SOC_ADDR_RIBP_GPIO_BASE, 1, 32'h1111_1111);
expect_route(`SOC_ADDR_RIBP_GPIO_ADMIN_BASE, 1, 32'h1111_1111);
expect_route(`SOC_ADDR_RIBP_PSRAM_BASE, 4, 32'h4444_4444);
expect_route(`SOC_ADDR_RIBP_XPI_BASE, 9, 32'h9999_9999);
expect_route(`SOC_ADDR_RIBP_I2C1_BASE, 17, 32'h1234_5678);
expect_disabled(`SOC_ADDR_RIBP_SDIO_BASE);
u_gpio_ribp_if.resp_err = 1'b1;
expect_error_route(`SOC_ADDR_RIBP_GPIO_BASE, 1);
u_gpio_ribp_if.resp_err = 1'b0;
$display("SoC topology RIBP routing test passed");
$finish;
end
endmodule
+40 -37
View File
@@ -14,7 +14,10 @@ module sdram_data_tb;
.aclk (clk_i),
.aresetn(rst_n_i)
);
ribp_if cfg_ribp ();
apb4_if cfg_apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
sdram_if sdram ();
always #5 clk_i = ~clk_i;
@@ -26,7 +29,7 @@ module sdram_data_tb;
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.axi4 (axi4),
.cfg_ribp(cfg_ribp),
.cfg_apb4(cfg_apb4),
.sdram (sdram)
);
@@ -60,41 +63,41 @@ module sdram_data_tb;
task automatic init_axi4;
begin
axi4.awid = '0;
axi4.awaddr = '0;
axi4.awlen = '0;
axi4.awsize = `AXI4_BURST_SIZE_4BYTES;
axi4.awburst = `AXI4_BURST_TYPE_INCR;
axi4.awlock = `AXI4_LOCK_NORM;
axi4.awcache = `AXI4_CACHE_NO_BUF;
axi4.awprot = `AXI4_PROT_DATA;
axi4.awqos = `AXI4_QOS_NORMAL;
axi4.awregion = `AXI4_REGION_NORMAL;
axi4.awuser = '0;
axi4.awvalid = 1'b0;
axi4.wdata = '0;
axi4.wstrb = '0;
axi4.wlast = 1'b0;
axi4.wuser = '0;
axi4.wvalid = 1'b0;
axi4.bready = 1'b0;
axi4.arid = '0;
axi4.araddr = '0;
axi4.arlen = '0;
axi4.arsize = `AXI4_BURST_SIZE_4BYTES;
axi4.arburst = `AXI4_BURST_TYPE_INCR;
axi4.arlock = `AXI4_LOCK_NORM;
axi4.arcache = `AXI4_CACHE_NO_BUF;
axi4.arprot = `AXI4_PROT_DATA;
axi4.arqos = `AXI4_QOS_NORMAL;
axi4.arregion = `AXI4_REGION_NORMAL;
axi4.aruser = '0;
axi4.arvalid = 1'b0;
axi4.rready = 1'b0;
cfg_ribp.valid = 1'b0;
cfg_ribp.addr = '0;
cfg_ribp.wdata = '0;
cfg_ribp.wstrb = '0;
axi4.awid = '0;
axi4.awaddr = '0;
axi4.awlen = '0;
axi4.awsize = `AXI4_BURST_SIZE_4BYTES;
axi4.awburst = `AXI4_BURST_TYPE_INCR;
axi4.awlock = `AXI4_LOCK_NORM;
axi4.awcache = `AXI4_CACHE_NO_BUF;
axi4.awprot = `AXI4_PROT_DATA;
axi4.awqos = `AXI4_QOS_NORMAL;
axi4.awregion = `AXI4_REGION_NORMAL;
axi4.awuser = '0;
axi4.awvalid = 1'b0;
axi4.wdata = '0;
axi4.wstrb = '0;
axi4.wlast = 1'b0;
axi4.wuser = '0;
axi4.wvalid = 1'b0;
axi4.bready = 1'b0;
axi4.arid = '0;
axi4.araddr = '0;
axi4.arlen = '0;
axi4.arsize = `AXI4_BURST_SIZE_4BYTES;
axi4.arburst = `AXI4_BURST_TYPE_INCR;
axi4.arlock = `AXI4_LOCK_NORM;
axi4.arcache = `AXI4_CACHE_NO_BUF;
axi4.arprot = `AXI4_PROT_DATA;
axi4.arqos = `AXI4_QOS_NORMAL;
axi4.arregion = `AXI4_REGION_NORMAL;
axi4.aruser = '0;
axi4.arvalid = 1'b0;
axi4.rready = 1'b0;
cfg_apb4.psel = 1'b0;
cfg_apb4.paddr = '0;
cfg_apb4.pwdata = '0;
cfg_apb4.pstrb = '0;
end
endtask
+8 -8
View File
@@ -4,7 +4,7 @@
module soc_irq_topology_tb;
logic [`SOC_IRQ_VECTOR_WIDTH-1:0] s_irq;
logic [ `SOC_IRQ_RIBP_WIDTH-1:0] s_ribp_irq;
logic [ `SOC_IRQ_APB4_WIDTH-1:0] s_apb4_irq;
logic [ `SOC_IRQ_APB_WIDTH-1:0] s_apb_irq;
`include "soc_irq_wiring.svh"
@@ -19,20 +19,20 @@ module soc_irq_topology_tb;
endtask
initial begin
s_ribp_irq = '0;
s_apb4_irq = '0;
s_apb_irq = '0;
expect_irq('0);
for (int bit_index = 0; bit_index < 10; bit_index++) begin
s_ribp_irq = '0;
s_ribp_irq[bit_index] = 1'b1;
s_apb4_irq = '0;
s_apb4_irq[bit_index] = 1'b1;
s_apb_irq = '0;
expect_irq(32'd1 << bit_index);
end
for (int bit_index = 10; bit_index < `SOC_IRQ_RIBP_WIDTH; bit_index++) begin
s_ribp_irq = '0;
s_ribp_irq[bit_index] = 1'b1;
for (int bit_index = 10; bit_index < `SOC_IRQ_APB4_WIDTH; bit_index++) begin
s_apb4_irq = '0;
s_apb4_irq[bit_index] = 1'b1;
case (bit_index)
13: expect_irq(32'd1 << 15);
default: expect_irq(32'd1 << (bit_index + 7));
@@ -40,7 +40,7 @@ module soc_irq_topology_tb;
end
for (int bit_index = 0; bit_index < `SOC_IRQ_APB_WIDTH; bit_index++) begin
s_ribp_irq = '0;
s_apb4_irq = '0;
s_apb_irq = '0;
s_apb_irq[bit_index] = 1'b1;
case (bit_index)
+40 -23
View File
@@ -7,20 +7,23 @@ module sysctrl_tb;
logic [31:0] fault_addr_i = '0;
logic [ 3:0] fault_wstrb_i = '0;
logic fault_reserved_i = 1'b0;
ribp_if rib ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
sysctrl_if sysctrl ();
pll_ctrl_if pll_ctrl ();
always #5 clk_i = ~clk_i;
ribp_sysctrl u_sysctrl (
apb4_sysctrl u_sysctrl (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.fault_valid_i (fault_valid_i),
.fault_addr_i (fault_addr_i),
.fault_wstrb_i (fault_wstrb_i),
.fault_reserved_i(fault_reserved_i),
.ribp (rib),
.apb4 (apb4),
.sysctrl (sysctrl),
.pll_ctrl (pll_ctrl)
);
@@ -28,38 +31,52 @@ module sysctrl_tb;
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
begin
@(negedge clk_i);
rib.addr = address;
rib.wdata = '0;
rib.wstrb = '0;
rib.valid = 1'b1;
while (!rib.ready) @(posedge clk_i);
data = rib.rdata;
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
rib.valid = 1'b0;
while (rib.ready) @(posedge clk_i);
apb4.penable = 1'b1;
while (!apb4.pready) @(negedge clk_i);
if (apb4.pslverr !== 1'b0) begin
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
end
data = apb4.prdata;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
task automatic write_register(input logic [31:0] address, input logic [31:0] data);
begin
@(negedge clk_i);
rib.addr = address;
rib.wdata = data;
rib.wstrb = 4'hF;
rib.valid = 1'b1;
while (!rib.ready) @(posedge 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);
rib.valid = 1'b0;
while (rib.ready) @(posedge clk_i);
apb4.penable = 1'b1;
while (!apb4.pready) @(negedge clk_i);
if (apb4.pslverr !== 1'b0) begin
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
end
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
logic [31:0] read_data;
initial begin
rib.valid = 1'b0;
rib.addr = '0;
rib.wdata = '0;
rib.wstrb = '0;
apb4.psel = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
sysctrl.user_bus_idle_i = 1'b1;
sysctrl.fault_access_i = 1'b0;
sysctrl.fault_master_i = '0;
@@ -67,7 +84,7 @@ module sysctrl_tb;
sysctrl.perf_mgmt_wait_i = 64'd11;
sysctrl.perf_user_wait_i = 64'd12;
sysctrl.perf_dma_wait_i = 64'd13;
sysctrl.perf_ribp_wait_i = 64'd14;
sysctrl.perf_apb4_wait_i = 64'd14;
sysctrl.perf_apb_wait_i = 64'd15;
sysctrl.perf_sdram_wait_i = 64'd16;
sysctrl.perf_psram_wait_i = 64'd17;
+91 -74
View File
@@ -12,49 +12,63 @@ module timer_tb;
logic rst_n_i = 1'b0;
logic debug_halted_i = 1'b0;
logic irq_o;
ribp_if ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
always #5 clk_i = ~clk_i;
ribp_timer u_dut (
apb4_timer u_dut (
.clk_i,
.rst_n_i,
.debug_halted_i,
.ribp,
.apb4,
.irq_o
);
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
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);
ribp.valid = 1'b1;
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = strobe;
do @(negedge clk_i); while (!ribp.ready);
if (ribp.resp_err !== expected_error) begin
$fatal(1, "write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
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
ribp.valid = 1'b0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
task automatic ribp_read(input logic [31:0] address, output logic [31:0] data,
task automatic apb4_read(input logic [31:0] address, output logic [31:0] data,
input logic expected_error);
begin
@(negedge clk_i);
ribp.valid = 1'b1;
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
do @(negedge clk_i); while (!ribp.ready);
data = ribp.rdata;
if (ribp.resp_err !== expected_error) begin
$fatal(1, "read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
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
ribp.valid = 1'b0;
data = apb4.prdata;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
@@ -65,7 +79,7 @@ module timer_tb;
status = '1;
cycles = 0;
while ((status[0] != 1'b0) && (cycles < 64)) begin
ribp_read(32'h0000_001C, status, 1'b0);
apb4_read(32'h0000_001C, status, 1'b0);
cycles++;
end
if (status[0] != 1'b0) $fatal(1, "timer did not enter inactive state");
@@ -78,98 +92,101 @@ module timer_tb;
logic [31:0] intr_state;
initial begin
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pprot = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
ribp_read(32'h0000_00F8, value, 1'b0);
apb4_read(32'h0000_00F8, value, 1'b0);
if (value != 32'h0002_0000) $fatal(1, "unexpected timer version %h", value);
ribp_read(32'h0000_00FC, value, 1'b0);
apb4_read(32'h0000_00FC, value, 1'b0);
if (value != 32'h00F2_1020) $fatal(1, "unexpected timer capability %h", value);
ribp_read(32'h0000_0100, value, 1'b1);
apb4_read(32'h0000_0100, value, 1'b1);
if (value != 32'd0) $fatal(1, "invalid read did not return zero");
ribp_read(32'h0000_0002, value, 1'b1);
ribp_write(32'h0000_0008, 32'h1234_5678, 4'hF, 1'b1);
ribp_read(32'h0000_002C, value, 1'b1);
ribp_write(32'h0000_0000, 32'h0000_0006, 4'hF, 1'b1);
apb4_read(32'h0000_0002, value, 1'b1);
apb4_write(32'h0000_0008, 32'h1234_5678, 4'hF, 1'b1);
apb4_read(32'h0000_002C, value, 1'b1);
apb4_write(32'h0000_0000, 32'h0000_0006, 4'hF, 1'b1);
// Free-running mode wraps naturally and stops without changing its value.
ribp_write(32'h0000_0000, CTRL_ENABLE, 4'hF, 1'b0);
apb4_write(32'h0000_0000, CTRL_ENABLE, 4'hF, 1'b0);
repeat (6) @(posedge clk_i);
ribp_read(32'h0000_0008, value, 1'b0);
apb4_read(32'h0000_0008, value, 1'b0);
if (value == 32'd0) $fatal(1, "free-running timer did not advance");
ribp_write(32'h0000_0000, 32'd0, 4'hF, 1'b0);
apb4_write(32'h0000_0000, 32'd0, 4'hF, 1'b0);
// Up-counting periodic mode with both compare channels.
ribp_write(32'h0000_0010, 32'd1, 4'hF, 1'b0);
ribp_write(32'h0000_0014, 32'd1, 4'hF, 1'b0);
ribp_write(32'h0000_0018, 32'd2, 4'hF, 1'b0);
ribp_write(32'h0000_0004, 32'd3, 4'hF, 1'b0);
ribp_write(32'h0000_0024, 32'h0000_0007, 4'hF, 1'b0);
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
ribp_write(32'h0000_0010, 32'd0, 4'hF, 1'b1);
apb4_write(32'h0000_0010, 32'd1, 4'hF, 1'b0);
apb4_write(32'h0000_0014, 32'd1, 4'hF, 1'b0);
apb4_write(32'h0000_0018, 32'd2, 4'hF, 1'b0);
apb4_write(32'h0000_0004, 32'd3, 4'hF, 1'b0);
apb4_write(32'h0000_0024, 32'h0000_0007, 4'hF, 1'b0);
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
apb4_write(32'h0000_0010, 32'd0, 4'hF, 1'b1);
repeat (12) @(posedge clk_i);
ribp_read(32'h0000_0020, intr_state, 1'b0);
apb4_read(32'h0000_0020, intr_state, 1'b0);
if (intr_state[2:0] != 3'b111 || !irq_o) begin
$fatal(1, "periodic compare/timeout state invalid: %h irq=%b", intr_state, irq_o);
end
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
ribp_write(32'h0000_0000, CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
apb4_write(32'h0000_0000, CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
// Down-counting one-shot stops at zero and leaves a sticky timeout.
ribp_write(32'h0000_0004, 32'd2, 4'hF, 1'b0);
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_ONE_SHOT | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
apb4_write(32'h0000_0004, 32'd2, 4'hF, 1'b0);
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_ONE_SHOT | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
wait_inactive();
ribp_read(32'h0000_0008, value, 1'b0);
ribp_read(32'h0000_0020, intr_state, 1'b0);
apb4_read(32'h0000_0008, value, 1'b0);
apb4_read(32'h0000_0020, intr_state, 1'b0);
if (value != 32'd0 || !intr_state[0]) begin
$fatal(1, "one-shot completion invalid value=%h state=%h", value, intr_state);
end
// Background load updates the next down-counting period without an immediate reload.
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
ribp_write(32'h0000_0004, 32'd5, 4'hF, 1'b0);
ribp_write(32'h0000_0010, 32'd3, 4'hF, 1'b0);
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
ribp_read(32'h0000_0008, value, 1'b0);
ribp_write(32'h0000_000C, 32'd1, 4'hF, 1'b0);
ribp_read(32'h0000_0008, frozen_value, 1'b0);
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
apb4_write(32'h0000_0004, 32'd5, 4'hF, 1'b0);
apb4_write(32'h0000_0010, 32'd3, 4'hF, 1'b0);
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
apb4_read(32'h0000_0008, value, 1'b0);
apb4_write(32'h0000_000C, 32'd1, 4'hF, 1'b0);
apb4_read(32'h0000_0008, frozen_value, 1'b0);
if (frozen_value == 32'd1) $fatal(1, "BGLOAD changed the live counter immediately");
repeat (32) @(posedge clk_i);
ribp_read(32'h0000_0008, value, 1'b0);
apb4_read(32'h0000_0008, value, 1'b0);
if (value > 32'd1) $fatal(1, "BGLOAD was not used by the next period: %h", value);
ribp_write(32'h0000_0000, CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
apb4_write(32'h0000_0000, CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
// Debug freeze stops both prescaler and counter while keeping RIBP readable.
ribp_write(32'h0000_0004, 32'd20, 4'hF, 1'b0);
ribp_write(32'h0000_0010, 32'd0, 4'hF, 1'b0);
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DEBUG_FREEZE, 4'hF, 1'b0);
// Debug freeze stops both prescaler and counter while keeping APB4 readable.
apb4_write(32'h0000_0004, 32'd20, 4'hF, 1'b0);
apb4_write(32'h0000_0010, 32'd0, 4'hF, 1'b0);
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DEBUG_FREEZE, 4'hF, 1'b0);
debug_halted_i = 1'b1;
repeat (2) @(posedge clk_i);
ribp_read(32'h0000_0008, frozen_value, 1'b0);
apb4_read(32'h0000_0008, frozen_value, 1'b0);
repeat (8) @(posedge clk_i);
ribp_read(32'h0000_0008, value, 1'b0);
ribp_read(32'h0000_001C, status, 1'b0);
apb4_read(32'h0000_0008, value, 1'b0);
apb4_read(32'h0000_001C, status, 1'b0);
if (value != frozen_value || status[1:0] != 2'b11) begin
$fatal(1, "debug freeze invalid before=%h after=%h status=%h", frozen_value, value, status);
end
debug_halted_i = 1'b0;
repeat (4) @(posedge clk_i);
ribp_read(32'h0000_0008, value, 1'b0);
apb4_read(32'h0000_0008, value, 1'b0);
if (value == frozen_value) $fatal(1, "timer did not resume after debug halt");
// Software interrupt test and W1C clear.
ribp_write(32'h0000_002C, 32'h0000_0006, 4'h1, 1'b0);
ribp_read(32'h0000_0020, intr_state, 1'b0);
apb4_write(32'h0000_002C, 32'h0000_0006, 4'h1, 1'b0);
apb4_read(32'h0000_0020, intr_state, 1'b0);
if ((intr_state[2:1] != 2'b11) || !irq_o) $fatal(1, "interrupt test failed");
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
$display("RIBP Timer register, mode, interrupt, and error test passed");
$display("APB4 Timer register, mode, interrupt, and error test passed");
$finish;
end
endmodule
+89 -83
View File
@@ -1,71 +1,77 @@
`timescale 1ns / 1ps
`include "ribp_uart_define.svh"
`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;
ribp_if ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
uart_if uart ();
always #5 clk_i = ~clk_i;
ribp_uart u_dut (
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),
.ribp (ribp),
.apb4 (apb4),
.uart (uart)
);
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
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);
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = strobe;
ribp.valid = 1'b1;
while (!ribp.ready) begin
@(posedge clk_i);
#1;
end
if (ribp.resp_err !== expected_error) begin
$fatal(1, "UART write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
end
apb4.paddr = address;
apb4.pwdata = data;
apb4.pstrb = strobe;
apb4.pwrite = 1'b1;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
ribp.valid = 1'b0;
ribp.wstrb = '0;
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 ribp_read(input logic [31:0] address, input logic expected_error,
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
output logic [31:0] data);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
ribp.valid = 1'b1;
while (!ribp.ready) begin
@(posedge clk_i);
#1;
end
if (ribp.resp_err !== expected_error) begin
$fatal(1, "UART read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
end
data = ribp.rdata;
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
ribp.valid = 1'b0;
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
ribp_write(address, data, 4'hF, 1'b0);
apb4_write(address, data, 4'hF, 1'b0);
end
endtask
@@ -74,15 +80,15 @@ module uart_tb;
input logic [6:0] rts_deassert_level,
input logic [3:0] control);
begin
write_ok(`RIBP_UART_CTRL, 0);
write_ok(`APB4_UART_CTRL, 0);
repeat (4) @(posedge clk_i);
write_ok(`RIBP_UART_FIFO_CTRL, 3);
write_ok(`RIBP_UART_BAUD_INT, 16);
write_ok(`RIBP_UART_BAUD_FRAC, 0);
write_ok(`RIBP_UART_LINE_CTRL, line_control);
write_ok(`RIBP_UART_RTS_WATERMARK, {9'd0, rts_deassert_level, 9'd0, rts_assert_level});
write_ok(`RIBP_UART_FLOW_CTRL, flow_control);
write_ok(`RIBP_UART_CTRL, control);
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
@@ -112,10 +118,10 @@ module uart_tb;
logic [31:0] value;
integer index;
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
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);
@@ -123,84 +129,84 @@ module uart_tb;
repeat (4) @(posedge clk_i);
if (uart.rts_n_o !== 1'b1) $fatal(1, "UART RTS_n was not released after reset");
ribp_read(`RIBP_UART_IP_VERSION, 1'b0, value);
apb4_read(`APB4_UART_IP_VERSION, 1'b0, value);
if (value != 32'h0003_0000) $fatal(1, "UART IP version mismatch");
ribp_read(`RIBP_UART_CAPABILITY, 1'b0, value);
apb4_read(`APB4_UART_CAPABILITY, 1'b0, value);
if (value != 32'h03FF_4040) $fatal(1, "UART capability mismatch");
ribp_read(32'h0000_0002, 1'b1, value);
ribp_read(`RIBP_UART_RXDATA, 1'b1, value);
apb4_read(32'h0000_0002, 1'b1, value);
apb4_read(`APB4_UART_RXDATA, 1'b1, value);
ribp_write(`RIBP_UART_RTS_WATERMARK, 32'h0002_0002, 4'hF, 1'b1);
ribp_read(`RIBP_UART_ERROR_STATUS, 1'b0, 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(`RIBP_UART_ERROR_STATUS, 7'h7F);
write_ok(`APB4_UART_ERROR_STATUS, 7'h7F);
configure_uart_flow(5'd3, 2'b01, 7'd32, 7'd48, 4'b0111);
write_ok(`RIBP_UART_TXDATA, 8'hA5);
write_ok(`APB4_UART_TXDATA, 8'hA5);
repeat (220) @(posedge clk_i);
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
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(`RIBP_UART_TXDATA, 8'h5A);
write_ok(`APB4_UART_TXDATA, 8'h5A);
repeat (24) @(posedge clk_i);
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
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(`RIBP_UART_CTRL, 0);
write_ok(`APB4_UART_CTRL, 0);
repeat (180) @(posedge clk_i);
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
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(`RIBP_UART_INTR_ENABLE, 7'h7F);
write_ok(`RIBP_UART_INTR_TEST, 7'h20);
ribp_read(`RIBP_UART_INTR_STATUS, 1'b0, value);
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(`RIBP_UART_INTR_STATE, 7'h7F);
write_ok(`APB4_UART_INTR_STATE, 7'h7F);
configure_uart_flow(5'd3, 2'b01, 7'd32, 7'd48, 4'b0001);
write_ok(`RIBP_UART_INTR_ENABLE, 7'h40);
write_ok(`RIBP_UART_TXDATA, 8'hC3);
write_ok(`RIBP_UART_TXDATA, 8'h5C);
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);
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
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
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
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);
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
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);
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
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
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
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);
ribp_read(`RIBP_UART_INTR_STATUS, 1'b0, 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(`RIBP_UART_INTR_STATE, 7'h7F);
write_ok(`APB4_UART_INTR_STATE, 7'h7F);
uart.cts_n_i = 1'b0;
repeat (220) @(posedge clk_i);
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
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
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
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
@@ -212,26 +218,26 @@ module uart_tb;
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");
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
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
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
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(`RIBP_UART_CTRL, 0);
write_ok(`APB4_UART_CTRL, 0);
repeat (4) @(posedge clk_i);
write_ok(`RIBP_UART_FIFO_CTRL, 3);
write_ok(`APB4_UART_FIFO_CTRL, 3);
for (index = 0; index < 64; index = index + 1) begin
write_ok(`RIBP_UART_TXDATA, index);
write_ok(`APB4_UART_TXDATA, index);
end
ribp_write(`RIBP_UART_TXDATA, 32'h55, 4'hF, 1'b1);
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
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(`RIBP_UART_FIFO_CTRL, 3);
write_ok(`RIBP_UART_DMA_CTRL, 3);
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");
+48 -31
View File
@@ -27,10 +27,12 @@ module ws2812_dma_tb;
logic [31:0] dma_error_addr;
logic [ 1:0] dma_fsm;
logic host_active = 1'b1;
logic host_valid = 1'b0;
logic host_psel = 1'b0;
logic host_penable = 1'b0;
logic [31:0] host_addr = '0;
logic [31:0] host_wdata = '0;
logic [ 3:0] host_wstrb = '0;
logic dma_penable = 1'b0;
logic dma_ws_valid;
bus_state_t bus_state_q = BUS_IDLE;
logic [31:0] bus_addr_q = '0;
@@ -44,7 +46,10 @@ module ws2812_dma_tb;
dma_hw_trg_if hw_trg ();
rib_if dma_rib ();
ribp_if ws_ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
ws2812_if ws2812 ();
axi4_stream_if i2s_tx_axis (
.aclk (clk_i),
@@ -66,13 +71,16 @@ module ws2812_dma_tb;
$fatal(1, "WS2812 DMA integration test timeout");
end
assign ws_ribp.valid = host_active ? host_valid : dma_ws_valid;
assign ws_ribp.addr = host_active ? host_addr : bus_addr_q;
assign ws_ribp.wdata = host_active ? host_wdata : dma_rib.wdata;
assign ws_ribp.wstrb = host_active ? host_wstrb : dma_rib.wstrb;
assign apb4.psel = host_active ? host_psel : dma_ws_valid;
assign apb4.penable = host_active ? host_penable : dma_penable;
assign apb4.pwrite = 1'b1;
assign apb4.paddr = host_active ? host_addr : bus_addr_q;
assign apb4.pwdata = host_active ? host_wdata : dma_rib.wdata;
assign apb4.pstrb = host_active ? host_wstrb : dma_rib.wstrb;
assign apb4.pprot = '0;
assign dma_rib.cmd_ready = bus_state_q == BUS_IDLE;
assign dma_rib.w_ready = (bus_state_q == BUS_WRITE_DATA) && ws_ribp.ready;
assign dma_rib.w_ready = (bus_state_q == BUS_WRITE_DATA) && dma_penable && apb4.pready;
assign dma_rib.rsp_valid = (bus_state_q == BUS_READ_RESP) || (bus_state_q == BUS_WRITE_RESP);
assign dma_rib.rdata = pixels[bus_addr_q[4:2]];
assign dma_rib.resp_err = 1'b0;
@@ -98,6 +106,18 @@ module ws2812_dma_tb;
assign dvp_rx_axis.tuser = '0;
assign dvp_rx_axis.tvalid = 1'b0;
always_ff @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
dma_penable <= 1'b0;
end else if (!dma_ws_valid) begin
dma_penable <= 1'b0;
end else if (!dma_penable) begin
dma_penable <= 1'b1;
end else if (apb4.pready) begin
dma_penable <= 1'b0;
end
end
always_ff @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
bus_state_q <= BUS_IDLE;
@@ -177,32 +197,29 @@ module ws2812_dma_tb;
.dvp_rx_axis (dvp_rx_axis)
);
ribp_ws2812 #(
apb4_ws2812 #(
.TxFifoDepth(4)
) u_ws2812 (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.ribp (ws_ribp),
.apb4 (apb4),
.ws2812 (ws2812)
);
task automatic host_write(input logic [31:0] address, input logic [31:0] data);
begin
@(negedge clk_i);
host_addr = address;
host_wdata = data;
host_wstrb = 4'hF;
host_valid = 1'b1;
while (!ws_ribp.ready) begin
@(posedge clk_i);
#1;
end
if (ws_ribp.resp_err) begin
$fatal(1, "host write %h failed", address);
end
host_addr = address;
host_wdata = data;
host_wstrb = 4'hF;
host_psel = 1'b1;
host_penable = 1'b0;
@(negedge clk_i);
host_valid = 1'b0;
host_wstrb = '0;
host_penable = 1'b1;
while (!apb4.pready) @(negedge clk_i);
if (apb4.pslverr) $fatal(1, "WS2812 write %h unexpected error", address);
host_psel = 1'b0;
host_penable = 1'b0;
end
endtask
@@ -258,15 +275,15 @@ module ws2812_dma_tb;
repeat (3) @(posedge clk_i);
rst_n_i = 1'b1;
host_write(`RIBP_WS2812_BIT_CYCLES, BIT_CYCLES);
host_write(`RIBP_WS2812_T0H_CYCLES, T0H_CYCLES);
host_write(`RIBP_WS2812_T1H_CYCLES, T1H_CYCLES);
host_write(`RIBP_WS2812_RESET_CYCLES, RESET_CYCLES);
host_write(`RIBP_WS2812_FIFO_WATERMARK, 3);
host_write(`RIBP_WS2812_INTR_ENABLE, 1);
host_write(`RIBP_WS2812_TXDATA, pixels[0]);
host_write(`RIBP_WS2812_FRAME_WORDS, 6);
host_write(`RIBP_WS2812_CTRL, 1);
host_write(`APB4_WS2812_BIT_CYCLES, BIT_CYCLES);
host_write(`APB4_WS2812_T0H_CYCLES, T0H_CYCLES);
host_write(`APB4_WS2812_T1H_CYCLES, T1H_CYCLES);
host_write(`APB4_WS2812_RESET_CYCLES, RESET_CYCLES);
host_write(`APB4_WS2812_FIFO_WATERMARK, 3);
host_write(`APB4_WS2812_INTR_ENABLE, 1);
host_write(`APB4_WS2812_TXDATA, pixels[0]);
host_write(`APB4_WS2812_FRAME_WORDS, 6);
host_write(`APB4_WS2812_CTRL, 1);
host_active = 1'b0;
@(negedge clk_i);
+92 -84
View File
@@ -11,7 +11,10 @@ module ws2812_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
ribp_if ribp ();
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
ws2812_if ws2812 ();
logic monitor_enable = 1'b0;
@@ -31,67 +34,72 @@ module ws2812_tb;
initial begin
repeat (10000) @(posedge clk_i);
$fatal(1, "WS2812 test timeout at stage %0d state=%0d valid=%b ready=%b", test_stage,
u_dut.u_ws2812_core.s_state_q, ribp.valid, ribp.ready);
u_dut.u_ws2812_core.s_state_q, apb4.psel, apb4.pready);
end
ribp_ws2812 #(
apb4_ws2812 #(
.TxFifoDepth(FIFO_DEPTH)
) u_dut (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.ribp (ribp),
.apb4 (apb4),
.ws2812 (ws2812)
);
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
input logic [3:0] strobe, input logic expected_error,
output integer wait_cycles);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = data;
ribp.wstrb = strobe;
ribp.valid = 1'b1;
wait_cycles = 0;
while (!ribp.ready) begin
@(posedge clk_i);
#1;
@(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) begin
@(negedge clk_i);
wait_cycles = wait_cycles + 1;
end
if (ribp.resp_err !== expected_error) begin
$fatal(1, "write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
if (apb4.pslverr !== expected_error) begin
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
end
@(negedge clk_i);
ribp.valid = 1'b0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
task automatic ribp_read(input logic [31:0] address, input logic expected_error,
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
output logic [31:0] data);
begin
@(negedge clk_i);
ribp.addr = address;
ribp.wdata = '0;
ribp.wstrb = '0;
ribp.valid = 1'b1;
while (!ribp.ready) begin
@(posedge clk_i);
#1;
end
if (ribp.resp_err !== expected_error) begin
$fatal(1, "read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
end
data = ribp.rdata;
apb4.paddr = address;
apb4.pwdata = '0;
apb4.pstrb = '0;
apb4.pwrite = 1'b0;
apb4.psel = 1'b1;
apb4.penable = 1'b0;
@(negedge clk_i);
ribp.valid = 1'b0;
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);
integer ignored_wait;
begin
ribp_write(address, data, 4'hF, 1'b0, ignored_wait);
apb4_write(address, data, 4'hF, 1'b0, ignored_wait);
end
endtask
@@ -100,19 +108,19 @@ module ws2812_tb;
begin
status = 32'h1;
while (status[`WS2812_STATUS_BUSY]) begin
ribp_read(`RIBP_WS2812_STATUS, 1'b0, status);
apb4_read(`APB4_WS2812_STATUS, 1'b0, status);
end
end
endtask
task automatic configure_timing;
begin
write_ok(`RIBP_WS2812_BIT_CYCLES, BIT_CYCLES);
write_ok(`RIBP_WS2812_T0H_CYCLES, T0H_CYCLES);
write_ok(`RIBP_WS2812_T1H_CYCLES, T1H_CYCLES);
write_ok(`RIBP_WS2812_RESET_CYCLES, RESET_CYCLES);
write_ok(`RIBP_WS2812_FIFO_WATERMARK, 3);
write_ok(`RIBP_WS2812_INTR_ENABLE, 4'hF);
write_ok(`APB4_WS2812_BIT_CYCLES, BIT_CYCLES);
write_ok(`APB4_WS2812_T0H_CYCLES, T0H_CYCLES);
write_ok(`APB4_WS2812_T1H_CYCLES, T1H_CYCLES);
write_ok(`APB4_WS2812_RESET_CYCLES, RESET_CYCLES);
write_ok(`APB4_WS2812_FIFO_WATERMARK, 3);
write_ok(`APB4_WS2812_INTR_ENABLE, 4'hF);
end
endtask
@@ -176,50 +184,50 @@ module ws2812_tb;
logic [31:0] value;
integer wait_cycles;
ribp.valid = 1'b0;
ribp.addr = '0;
ribp.wdata = '0;
ribp.wstrb = '0;
apb4.psel = 1'b0;
apb4.paddr = '0;
apb4.pwdata = '0;
apb4.pstrb = '0;
repeat (3) @(posedge clk_i);
rst_n_i = 1'b1;
test_stage = 1;
ribp_read(`RIBP_WS2812_IP_INFO, 1'b0, value);
apb4_read(`APB4_WS2812_IP_INFO, 1'b0, value);
if (value !== 32'h1804_0100) begin
$fatal(1, "unexpected IP_INFO %h", value);
end
ribp_read(`RIBP_WS2812_STATUS, 1'b0, value);
apb4_read(`APB4_WS2812_STATUS, 1'b0, value);
if (value[`WS2812_STATUS_CONFIG_VALID] || !value[`WS2812_STATUS_FIFO_EMPTY]) begin
$fatal(1, "unexpected reset status %h", value);
end
ribp_read(`RIBP_WS2812_CTRL, 1'b1, value);
ribp_write(8'h02, 32'd1, 4'hF, 1'b1, wait_cycles);
ribp_read(32'h00000100, 1'b1, value);
ribp_write(`RIBP_WS2812_TXDATA, 24'h112233, 4'h7, 1'b1, wait_cycles);
write_ok(`RIBP_WS2812_TXDATA, 24'h112233);
write_ok(`RIBP_WS2812_FRAME_WORDS, 1);
ribp_write(`RIBP_WS2812_CTRL, 32'h1, 4'hF, 1'b1, wait_cycles);
ribp_read(`RIBP_WS2812_ERROR_STATUS, 1'b0, value);
apb4_read(`APB4_WS2812_CTRL, 1'b1, value);
apb4_write(8'h02, 32'd1, 4'hF, 1'b1, wait_cycles);
apb4_read(32'h00000100, 1'b1, value);
apb4_write(`APB4_WS2812_TXDATA, 24'h112233, 4'h7, 1'b1, wait_cycles);
write_ok(`APB4_WS2812_TXDATA, 24'h112233);
write_ok(`APB4_WS2812_FRAME_WORDS, 1);
apb4_write(`APB4_WS2812_CTRL, 32'h1, 4'hF, 1'b1, wait_cycles);
apb4_read(`APB4_WS2812_ERROR_STATUS, 1'b0, value);
if (!value[`WS2812_ERROR_CONFIG]) begin
$fatal(1, "invalid timing did not set CONFIG error");
end
write_ok(`RIBP_WS2812_ERROR_STATUS, 32'h7);
write_ok(`RIBP_WS2812_CTRL, 32'h4);
write_ok(`APB4_WS2812_ERROR_STATUS, 32'h7);
write_ok(`APB4_WS2812_CTRL, 32'h4);
configure_timing();
ribp_read(`RIBP_WS2812_STATUS, 1'b0, value);
apb4_read(`APB4_WS2812_STATUS, 1'b0, value);
if (!value[`WS2812_STATUS_CONFIG_VALID]) begin
$fatal(1, "legal timing was not accepted");
end
test_stage = 2;
for (integer index = 0; index < FIFO_DEPTH; index = index + 1) begin
write_ok(`RIBP_WS2812_TXDATA, index);
write_ok(`APB4_WS2812_TXDATA, index);
end
ribp_write(`RIBP_WS2812_TXDATA, 32'h55, 4'hF, 1'b1, wait_cycles);
write_ok(`RIBP_WS2812_CTRL, 32'h4);
write_ok(`RIBP_WS2812_ERROR_STATUS, 32'h7);
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
apb4_write(`APB4_WS2812_TXDATA, 32'h55, 4'hF, 1'b1, wait_cycles);
write_ok(`APB4_WS2812_CTRL, 32'h4);
write_ok(`APB4_WS2812_ERROR_STATUS, 32'h7);
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
test_stage = 3;
expected_pixels[0] = 24'h800001;
@@ -229,68 +237,68 @@ module ws2812_tb;
expected_pixels[4] = 24'hFFFFFF;
expected_pixels[5] = 24'h000000;
for (integer index = 0; index < FIFO_DEPTH; index = index + 1) begin
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[index]);
write_ok(`APB4_WS2812_TXDATA, expected_pixels[index]);
end
write_ok(`RIBP_WS2812_FRAME_WORDS, 6);
write_ok(`APB4_WS2812_FRAME_WORDS, 6);
begin_monitor(6);
write_ok(`RIBP_WS2812_CTRL, 32'h1);
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[4]);
ribp_write(`RIBP_WS2812_TXDATA, expected_pixels[5], 4'hF, 1'b0, wait_cycles);
write_ok(`APB4_WS2812_CTRL, 32'h1);
write_ok(`APB4_WS2812_TXDATA, expected_pixels[4]);
apb4_write(`APB4_WS2812_TXDATA, expected_pixels[5], 4'hF, 1'b0, wait_cycles);
if (wait_cycles < (BIT_CYCLES * 20)) begin
$fatal(1, "full FIFO write was not backpressured: %0d cycles", wait_cycles);
end
wait_until_idle();
end_monitor(1'b1);
ribp_read(`RIBP_WS2812_INTR_STATE, 1'b0, value);
apb4_read(`APB4_WS2812_INTR_STATE, 1'b0, value);
if ((value & 32'h3) != 32'h3 || !ws2812.irq_o) begin
$fatal(1, "done/low-watermark interrupt missing: %h", value);
end
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
if (ws2812.irq_o) begin
$fatal(1, "IRQ did not clear");
end
test_stage = 4;
expected_pixels[0] = 24'h123456;
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[0]);
write_ok(`RIBP_WS2812_FRAME_WORDS, 2);
write_ok(`APB4_WS2812_TXDATA, expected_pixels[0]);
write_ok(`APB4_WS2812_FRAME_WORDS, 2);
begin_monitor(1);
write_ok(`RIBP_WS2812_CTRL, 32'h1);
write_ok(`APB4_WS2812_CTRL, 32'h1);
wait_until_idle();
end_monitor(1'b1);
ribp_read(`RIBP_WS2812_ERROR_STATUS, 1'b0, value);
apb4_read(`APB4_WS2812_ERROR_STATUS, 1'b0, value);
if (!value[`WS2812_ERROR_UNDERFLOW]) begin
$fatal(1, "underflow was not reported");
end
ribp_read(`RIBP_WS2812_FIFO_LEVEL, 1'b0, value);
apb4_read(`APB4_WS2812_FIFO_LEVEL, 1'b0, value);
if (value != 0) begin
$fatal(1, "underflow did not flush FIFO");
end
write_ok(`RIBP_WS2812_ERROR_STATUS, 32'h7);
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
write_ok(`APB4_WS2812_ERROR_STATUS, 32'h7);
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
test_stage = 5;
expected_pixels[0] = 24'hABCDEF;
expected_pixels[1] = 24'h765432;
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[0]);
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[1]);
write_ok(`RIBP_WS2812_FRAME_WORDS, 2);
write_ok(`APB4_WS2812_TXDATA, expected_pixels[0]);
write_ok(`APB4_WS2812_TXDATA, expected_pixels[1]);
write_ok(`APB4_WS2812_FRAME_WORDS, 2);
begin_monitor(2);
write_ok(`RIBP_WS2812_CTRL, 32'h1);
write_ok(`APB4_WS2812_CTRL, 32'h1);
repeat (8) @(posedge clk_i);
write_ok(`RIBP_WS2812_CTRL, 32'h2);
write_ok(`APB4_WS2812_CTRL, 32'h2);
wait_until_idle();
end_monitor(1'b0);
ribp_read(`RIBP_WS2812_INTR_STATE, 1'b0, value);
apb4_read(`APB4_WS2812_INTR_STATE, 1'b0, value);
if (!value[`WS2812_INTR_ABORTED]) begin
$fatal(1, "abort completion was not reported");
end
write_ok(`RIBP_WS2812_INTR_TEST, 32'h1);
write_ok(`APB4_WS2812_INTR_TEST, 32'h1);
if (!ws2812.irq_o) begin
$fatal(1, "interrupt test did not assert IRQ");
end
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
$display("WS2812 register, waveform, streaming, and error test passed");
$finish;