feat: add AXI4 interconnect testbench and enhance existing tests

- Introduced a new testbench for the AXI4 interconnect () to validate fault classification for decode and access errors.
- Updated  and  to reflect changes in bus naming conventions.
- Enhanced  to include AXI4-Stream interface checks and validate stream data transfers.
- Modified  to integrate AXI4-Stream interfaces for improved DMA testing.
- Added new Python tests () to verify AXI4 to RIBP burst bridge functionality and interconnect fault classification.
- Updated existing tests to include AXI4 interfaces and ensure proper error handling and response validation.
- Adjusted memory map generation and test setups to accommodate new AXI4 interface requirements.
This commit is contained in:
maksyuki committed 2026-08-12 12:30:12 +08:00
1 parent 9314b5950f
commit de32aa2979
65 files changed
+4271 -649

No files matched your search

+263
View File
@@ -0,0 +1,263 @@
`timescale 1ns / 1ps
`include "axi4_define.svh"
module axi42ribp_burst_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic [31:0] memory [0:63];
logic [31:0] expected;
integer target_accesses = 0;
integer error_beats;
integer cycle_count = 0;
integer burst_cycles;
integer single_cycles;
axi4_if #(
.ADDR_WIDTH(32),
.DATA_WIDTH(32),
.ID_WIDTH (1),
.USER_WIDTH(1)
) axi4 (
.aclk (clk_i),
.aresetn(rst_n_i)
);
ribp_if ribp ();
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)
);
always_ff @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
ribp.ready <= 1'b0;
ribp.rdata <= '0;
target_accesses <= 0;
end else begin
ribp.ready <= ribp.valid && !ribp.ready;
if (ribp.valid && !ribp.ready) begin
target_accesses <= target_accesses + 1;
ribp.rdata <= memory[ribp.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];
end
end
end
end
end
assign ribp.resp_err = 1'b0;
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;
end
endtask
task automatic issue_write4(input logic [31:0] address);
begin
@(negedge clk_i);
axi4.awaddr = address;
axi4.awlen = 8'd3;
axi4.awvalid = 1'b1;
do @(posedge clk_i); while (!axi4.awready);
@(negedge clk_i);
axi4.awvalid = 1'b0;
for (int beat = 0; beat < 4; beat++) begin
axi4.wdata = 32'hA500_0000 + beat;
axi4.wstrb = 4'hF;
axi4.wlast = beat == 3;
axi4.wvalid = 1'b1;
do @(posedge clk_i); while (!axi4.wready);
@(negedge clk_i);
axi4.wvalid = 1'b0;
end
repeat (2) @(posedge clk_i);
axi4.bready = 1'b1;
do @(posedge clk_i); while (!axi4.bvalid);
if (axi4.bresp != `AXI4_RESP_OKAY) $fatal(1, "write burst returned an error");
@(negedge clk_i);
axi4.bready = 1'b0;
end
endtask
task automatic issue_read4(input logic [31:0] address);
begin
@(negedge clk_i);
axi4.araddr = address;
axi4.arlen = 8'd3;
axi4.arvalid = 1'b1;
do @(posedge clk_i); while (!axi4.arready);
@(negedge clk_i);
axi4.arvalid = 1'b0;
for (int beat = 0; beat < 4; beat++) begin
if (beat == 1) begin
repeat (3) @(posedge clk_i);
@(negedge clk_i);
end
axi4.rready = 1'b1;
do @(posedge clk_i); while (!axi4.rvalid);
expected = 32'hA500_0000 + beat;
if (axi4.rdata != expected || axi4.rresp != `AXI4_RESP_OKAY ||
axi4.rlast != (beat == 3)) begin
$fatal(1, "read beat %0d mismatch: data=%08x expected=%08x resp=%0d last=%0d", beat,
axi4.rdata, expected, axi4.rresp, axi4.rlast);
end
@(negedge clk_i);
axi4.rready = 1'b0;
end
end
endtask
task automatic issue_illegal_read(input logic [31:0] address);
integer accesses_before;
begin
accesses_before = target_accesses;
@(negedge clk_i);
axi4.araddr = address;
axi4.arlen = 8'd16;
axi4.arvalid = 1'b1;
do @(posedge clk_i); while (!axi4.arready);
@(negedge clk_i);
axi4.arvalid = 1'b0;
axi4.rready = 1'b1;
error_beats = 0;
while (error_beats < 17) begin
@(posedge clk_i);
if (axi4.rvalid) begin
if (axi4.rresp != `AXI4_RESP_SLAVE_ERROR || axi4.rlast != (error_beats == 16)) begin
$fatal(1, "illegal burst response mismatch");
end
error_beats = error_beats + 1;
end
end
@(negedge clk_i);
axi4.rready = 1'b0;
if (target_accesses != accesses_before) begin
$fatal(1, "illegal burst reached the RIBP target");
end
end
endtask
task automatic issue_early_last_write(input logic [31:0] address);
integer accesses_before;
begin
accesses_before = target_accesses;
@(negedge clk_i);
axi4.awaddr = address;
axi4.awlen = 8'd3;
axi4.awvalid = 1'b1;
do @(posedge clk_i); while (!axi4.awready);
@(negedge clk_i);
axi4.awvalid = 1'b0;
axi4.wdata = 32'hDEAD_BEEF;
axi4.wstrb = 4'hF;
axi4.wlast = 1'b1;
axi4.wvalid = 1'b1;
do @(posedge clk_i); while (!axi4.wready);
@(negedge clk_i);
axi4.wvalid = 1'b0;
axi4.bready = 1'b1;
do @(posedge clk_i); while (!axi4.bvalid);
if (axi4.bresp != `AXI4_RESP_SLAVE_ERROR) begin
$fatal(1, "early WLAST did not return SLVERR");
end
@(negedge clk_i);
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");
end
end
endtask
task automatic issue_read(input logic [31:0] address, input logic [7:0] length);
integer beat;
begin
@(negedge clk_i);
axi4.araddr = address;
axi4.arlen = length;
axi4.arvalid = 1'b1;
do @(posedge clk_i); while (!axi4.arready);
@(negedge clk_i);
axi4.arvalid = 1'b0;
axi4.rready = 1'b1;
beat = 0;
while (beat <= length) begin
@(posedge clk_i);
if (axi4.rvalid) begin
if (axi4.rresp != `AXI4_RESP_OKAY || axi4.rlast != (beat == length)) begin
$fatal(1, "performance read response mismatch");
end
beat = beat + 1;
end
end
@(negedge clk_i);
axi4.rready = 1'b0;
end
endtask
initial begin
init_axi4();
for (int index = 0; index < 64; index++) memory[index] = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
issue_write4(32'h0000_0040);
issue_read4(32'h0000_0040);
issue_illegal_read(32'h0000_0080);
issue_early_last_write(32'h0000_00C0);
burst_cycles = cycle_count;
issue_read(32'h0000_0000, 8'd15);
burst_cycles = cycle_count - burst_cycles;
single_cycles = cycle_count;
for (int index = 0; index < 16; index++) begin
issue_read(32'(index * 4), 8'd0);
end
single_cycles = cycle_count - single_cycles;
if ((burst_cycles * 5) > (single_cycles * 4)) begin
$fatal(1, "16-beat burst improvement is below 20%%: burst=%0d single=%0d", burst_cycles,
single_cycles);
end
if (target_accesses != 41) $fatal(1, "unexpected RIBP access count");
$display("AXI4 to RIBP burst bridge test passed");
$finish;
end
endmodule
+195
View File
@@ -0,0 +1,195 @@
`timescale 1ns / 1ps
`include "axi4_define.svh"
`include "rib_defs.svh"
module axi4_interconnect_tb;
localparam int NUM_MASTERS = 3;
localparam int NUM_TARGETS = 9;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic fault_valid_o;
logic [31:0] fault_addr_o;
logic [ 3:0] fault_wstrb_o;
logic fault_reserved_o;
logic fault_access_o;
logic [ 1:0] fault_master_o;
logic [ 2:0] fault_code_o;
logic user_bus_idle_o;
axi4_if #(
.ADDR_WIDTH(32),
.DATA_WIDTH(32),
.ID_WIDTH (1),
.USER_WIDTH(1)
) masters[NUM_MASTERS] (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_if #(
.ADDR_WIDTH(32),
.DATA_WIDTH(32),
.ID_WIDTH (1),
.USER_WIDTH(1)
) targets[NUM_TARGETS] (
.aclk (clk_i),
.aresetn(rst_n_i)
);
always #5 clk_i = ~clk_i;
axi4_interconnect #(
.NUM_MASTERS(NUM_MASTERS),
.NUM_TARGETS(NUM_TARGETS)
) u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.masters (masters),
.targets (targets),
.user_bus_enable_i(1'b1),
.user_bus_idle_o (user_bus_idle_o),
.perf_enable_i (1'b0),
.perf_clear_i (1'b0),
.fault_valid_o (fault_valid_o),
.fault_addr_o (fault_addr_o),
.fault_wstrb_o (fault_wstrb_o),
.fault_reserved_o (fault_reserved_o),
.fault_access_o (fault_access_o),
.fault_master_o (fault_master_o),
.fault_code_o (fault_code_o),
.perf_mgmt_wait_o (),
.perf_user_wait_o (),
.perf_dma_wait_o (),
.perf_ribp_wait_o (),
.perf_apb_wait_o (),
.perf_sdram_wait_o(),
.perf_psram_wait_o(),
.perf_flash_wait_o()
);
for (genvar target = 0; target < NUM_TARGETS; target++) begin : GEN_TARGETS
localparam logic [1:0] RESPONSE =
(target == 7) ? `AXI4_RESP_DECODE_ERROR :
(target == 8) ? `AXI4_RESP_SLAVE_ERROR : `AXI4_RESP_OKAY;
axi4_error_slave #(
.RESPONSE(RESPONSE)
) u_target (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.axi4 (targets[target])
);
end
`define INIT_MASTER(index) \
masters[index].awid = '0; \
masters[index].awaddr = '0; \
masters[index].awlen = '0; \
masters[index].awsize = `AXI4_BURST_SIZE_4BYTES; \
masters[index].awburst = `AXI4_BURST_TYPE_INCR; \
masters[index].awlock = `AXI4_LOCK_NORM; \
masters[index].awcache = `AXI4_CACHE_NO_BUF; \
masters[index].awprot = `AXI4_PROT_DATA; \
masters[index].awqos = `AXI4_QOS_NORMAL; \
masters[index].awregion = `AXI4_REGION_NORMAL; \
masters[index].awuser = '0; \
masters[index].awvalid = 1'b0; \
masters[index].wdata = '0; \
masters[index].wstrb = '0; \
masters[index].wlast = 1'b0; \
masters[index].wuser = '0; \
masters[index].wvalid = 1'b0; \
masters[index].bready = 1'b0; \
masters[index].arid = '0; \
masters[index].araddr = '0; \
masters[index].arlen = '0; \
masters[index].arsize = `AXI4_BURST_SIZE_4BYTES; \
masters[index].arburst = `AXI4_BURST_TYPE_INCR; \
masters[index].arlock = `AXI4_LOCK_NORM; \
masters[index].arcache = `AXI4_CACHE_NO_BUF; \
masters[index].arprot = `AXI4_PROT_DATA; \
masters[index].arqos = `AXI4_QOS_NORMAL; \
masters[index].arregion = `AXI4_REGION_NORMAL; \
masters[index].aruser = '0; \
masters[index].arvalid = 1'b0; \
masters[index].rready = 1'b0;
task automatic issue_mgmt_error_read(input logic [31:0] address, input logic [7:0] length,
input logic [1:0] response, input logic [2:0] fault_code);
integer beat;
begin
@(negedge clk_i);
masters[0].araddr = address;
masters[0].arlen = length;
masters[0].arvalid = 1'b1;
do @(posedge clk_i); while (!masters[0].arready);
@(negedge clk_i);
masters[0].arvalid = 1'b0;
masters[0].rready = 1'b1;
beat = 0;
while (beat <= length) begin
@(negedge clk_i);
if (masters[0].rvalid) begin
if ((masters[0].rresp != response) || (masters[0].rlast != (beat == int'(length)))) begin
$fatal(1, "management error response mismatch on beat %0d", beat);
end
if ((beat == int'(length)) &&
(!fault_valid_o || (fault_addr_o != address) || fault_access_o ||
(fault_master_o != 2'd0) || (fault_code_o != fault_code))) begin
$fatal(1, "management fault classification mismatch");
end
beat = beat + 1;
end
end
@(negedge clk_i);
masters[0].rready = 1'b0;
end
endtask
task automatic issue_denied_user_write(input logic [31:0] address);
begin
@(negedge clk_i);
masters[1].awaddr = address;
masters[1].awlen = 8'd0;
masters[1].awvalid = 1'b1;
do @(posedge clk_i); while (!masters[1].awready);
@(negedge clk_i);
masters[1].awvalid = 1'b0;
masters[1].wdata = 32'hA5A5_5A5A;
masters[1].wstrb = 4'hF;
masters[1].wlast = 1'b1;
masters[1].wvalid = 1'b1;
do @(posedge clk_i); while (!masters[1].wready);
@(negedge clk_i);
masters[1].wvalid = 1'b0;
while (!masters[1].bvalid) @(negedge clk_i);
masters[1].bready = 1'b1;
#1;
if ((masters[1].bresp != `AXI4_RESP_SLAVE_ERROR) || !fault_valid_o ||
!fault_access_o || (fault_addr_o != address) || (fault_wstrb_o != 4'hF) ||
(fault_master_o != 2'd1) || (fault_code_o != `RIB_RESP_PROTERR)) begin
$fatal(1, "user access fault classification mismatch");
end
@(negedge clk_i);
masters[1].bready = 1'b0;
end
endtask
initial begin
`INIT_MASTER(0)
`INIT_MASTER(1)
`INIT_MASTER(2)
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
issue_mgmt_error_read(32'hA000_0000, 8'd0, `AXI4_RESP_DECODE_ERROR, `RIB_RESP_DECERR);
issue_mgmt_error_read(32'h3000_0000, 8'd16, `AXI4_RESP_SLAVE_ERROR, `RIB_RESP_BURSTERR);
issue_denied_user_write(32'h1000_B000);
$display("AXI4 interconnect fault classification test passed");
$finish;
end
`undef INIT_MASTER
endmodule
+1 -1
View File
@@ -36,7 +36,7 @@ module bus_fault_tb;
assign apb_rib.rsp_beat = '0;
assign apb_rib.rsp_last = 1'b1;
bus u_bus (
rib_bus u_bus (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mgmt_ribp (mgmt_ribp),
+86 -10
View File
@@ -27,6 +27,10 @@ module dma_error_tb;
integer incr4_write_count = 0;
integer legacy_cycles;
integer burst_cycles;
integer stream_tx_count = 0;
integer stream_rx_count = 0;
logic stream_tx_ready = 1'b0;
logic stream_rx_valid = 1'b0;
logic [ 1:0] model_state_q = MODEL_IDLE;
logic [ 1:0] model_len_q = '0;
logic [ 1:0] model_beat_q = '0;
@@ -34,17 +38,59 @@ module dma_error_tb;
logic model_error_q = 1'b0;
dma_hw_trg_if hw_trg ();
rib_if rib ();
axi4_stream_if i2s_tx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if i2s_rx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if dvp_rx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
always #5 clk_i = ~clk_i;
assign rib.cmd_ready = model_state_q == MODEL_IDLE;
assign rib.w_ready = model_state_q == MODEL_WDATA;
assign rib.rsp_valid = model_state_q == MODEL_RESP;
assign rib.rdata = 32'hA5A5_5A5A + model_beat_q;
assign rib.resp_err = model_error_q;
assign rib.resp_code = model_error_q ? `RIB_RESP_DECERR : `RIB_RESP_OK;
assign rib.rsp_beat = model_beat_q;
assign rib.rsp_last = model_write_q || model_error_q || (model_beat_q == model_len_q);
assign rib.cmd_ready = model_state_q == MODEL_IDLE;
assign rib.w_ready = model_state_q == MODEL_WDATA;
assign rib.rsp_valid = model_state_q == MODEL_RESP;
assign rib.rdata = 32'hA5A5_5A5A + model_beat_q;
assign rib.resp_err = model_error_q;
assign rib.resp_code = model_error_q ? `RIB_RESP_DECERR : `RIB_RESP_OK;
assign rib.rsp_beat = model_beat_q;
assign rib.rsp_last = model_write_q || model_error_q || (model_beat_q == model_len_q);
assign i2s_tx_axis.tready = stream_tx_ready;
assign i2s_rx_axis.tdata = 32'h5100_0000 + stream_rx_count;
assign i2s_rx_axis.tkeep = '1;
assign i2s_rx_axis.tstrb = '1;
assign i2s_rx_axis.tlast = stream_rx_count == 1;
assign i2s_rx_axis.tid = '0;
assign i2s_rx_axis.tdest = '0;
assign i2s_rx_axis.tuser = '0;
assign i2s_rx_axis.tvalid = stream_rx_valid;
assign dvp_rx_axis.tdata = '0;
assign dvp_rx_axis.tkeep = '0;
assign dvp_rx_axis.tstrb = '0;
assign dvp_rx_axis.tlast = 1'b0;
assign dvp_rx_axis.tid = '0;
assign dvp_rx_axis.tdest = '0;
assign dvp_rx_axis.tuser = '0;
assign dvp_rx_axis.tvalid = 1'b0;
always @(posedge clk_i) begin
if (i2s_tx_axis.tvalid && i2s_tx_axis.tready) begin
if (i2s_tx_axis.tdata !== 32'hA5A5_5A5A) begin
$fatal(1, "I2S TX stream data mismatch");
end
stream_tx_count <= stream_tx_count + 1;
end
if (i2s_rx_axis.tvalid && i2s_rx_axis.tready) begin
stream_rx_count <= stream_rx_count + 1;
if (stream_rx_count == 1) stream_rx_valid <= 1'b0;
end
end
always @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
@@ -114,7 +160,10 @@ module dma_error_tb;
.error_addr_o(error_addr_o),
.fsm_o (fsm_o),
.hw_trg (hw_trg),
.rib (rib)
.rib (rib),
.i2s_tx_axis (i2s_tx_axis),
.i2s_rx_axis (i2s_rx_axis),
.dvp_rx_axis (dvp_rx_axis)
);
task automatic start_transfer;
@@ -193,7 +242,34 @@ module dma_error_tb;
$fatal(1, "DMA did not fall back to INCR1 for a register window");
end
$display("dma error and burst performance test passed");
mode_i = 4'd1;
srcaddr_i = 32'h3800_2000;
srcincr_i = 1'b1;
xferlen_i = 32'd2;
stream_tx_ready = 1'b0;
start_transfer();
repeat (3) @(posedge clk_i);
@(negedge clk_i);
stream_tx_ready = 1'b1;
wait (done_o);
@(negedge clk_i);
if (stream_tx_count != 2) begin
$fatal(1, "I2S TX stream transferred %0d words", stream_tx_count);
end
mode_i = 4'd2;
dstaddr_i = 32'h4000_2000;
dstincr_i = 1'b1;
xferlen_i = 32'd2;
stream_rx_valid = 1'b1;
start_transfer();
wait (done_o);
@(negedge clk_i);
if (stream_rx_count != 2) begin
$fatal(1, "I2S RX stream transferred %0d words", stream_rx_count);
end
$display("dma error, burst performance, and AXI4-Stream test passed");
$finish;
end
endmodule
+1 -1
View File
@@ -66,7 +66,7 @@ module rib_bus_tb;
assign apb_rib.rsp_beat = '0;
assign apb_rib.rsp_last = 1'b1;
bus u_bus (
rib_bus u_bus (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mgmt_ribp (mgmt_ribp),
+2 -2
View File
@@ -141,8 +141,8 @@ module ribp_topology_tb;
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_PSRAM_BASE, 4, 32'h4444_4444);
expect_route(`SOC_ADDR_FLASH_BASE, 9, 32'h9999_9999);
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;
+46 -14
View File
@@ -46,6 +46,18 @@ module ws2812_dma_tb;
rib_if dma_rib ();
ribp_if ws_ribp ();
ws2812_if ws2812 ();
axi4_stream_if i2s_tx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if i2s_rx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
axi4_stream_if dvp_rx_axis (
.aclk (clk_i),
.aresetn(rst_n_i)
);
always #5 clk_i = ~clk_i;
@@ -54,20 +66,37 @@ 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 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 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.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;
assign dma_rib.resp_code = `RIB_RESP_OK;
assign dma_rib.rsp_beat = 2'd0;
assign dma_rib.rsp_last = 1'b1;
assign dma_ws_valid = (bus_state_q == BUS_WRITE_DATA) && dma_rib.w_valid;
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.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;
assign dma_rib.resp_code = `RIB_RESP_OK;
assign dma_rib.rsp_beat = 2'd0;
assign dma_rib.rsp_last = 1'b1;
assign dma_ws_valid = (bus_state_q == BUS_WRITE_DATA) && dma_rib.w_valid;
assign i2s_tx_axis.tready = 1'b0;
assign i2s_rx_axis.tdata = '0;
assign i2s_rx_axis.tkeep = '0;
assign i2s_rx_axis.tstrb = '0;
assign i2s_rx_axis.tlast = 1'b0;
assign i2s_rx_axis.tid = '0;
assign i2s_rx_axis.tdest = '0;
assign i2s_rx_axis.tuser = '0;
assign i2s_rx_axis.tvalid = 1'b0;
assign dvp_rx_axis.tdata = '0;
assign dvp_rx_axis.tkeep = '0;
assign dvp_rx_axis.tstrb = '0;
assign dvp_rx_axis.tlast = 1'b0;
assign dvp_rx_axis.tid = '0;
assign dvp_rx_axis.tdest = '0;
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
@@ -142,7 +171,10 @@ module ws2812_dma_tb;
.error_addr_o(dma_error_addr),
.fsm_o (dma_fsm),
.hw_trg (hw_trg),
.rib (dma_rib)
.rib (dma_rib),
.i2s_tx_axis (i2s_tx_axis),
.i2s_rx_axis (i2s_rx_axis),
.dvp_rx_axis (dvp_rx_axis)
);
ribp_ws2812 #(
+113
View File
@@ -0,0 +1,113 @@
"""Directed tests for the active AXI4 fabric adapters."""
from __future__ import annotations
import os
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_axi42ribp_supports_bursts_backpressure_and_errors(tmp_path: Path) -> None:
verilator = shutil.which("verilator")
if verilator is None:
return
output = tmp_path / "axi42ribp_burst_tb"
ccache_tmp = tmp_path / "ccache"
ccache_tmp.mkdir()
subprocess.run(
[
verilator,
"--binary",
"--timing",
"-Wno-fatal",
"--top-module",
"axi42ribp_burst_tb",
"-I" + str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-I" + str(ROOT / "rtl/managed/clusterip/common/rtl/interface"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/mini/top/axi42ribp_burst.sv"),
str(ROOT / "tests/rtl/axi42ribp_burst_tb.sv"),
"-Mdir",
str(tmp_path / "obj"),
"-o",
str(output),
],
check=True,
text=True,
capture_output=True,
env={
**os.environ,
"CCACHE_DIR": str(ccache_tmp),
"CCACHE_TEMPDIR": str(ccache_tmp),
},
)
result = subprocess.run([output], check=True, text=True, capture_output=True)
assert "AXI4 to RIBP burst bridge test passed" in result.stdout
def test_axi4_interconnect_classifies_decode_protocol_and_access_errors(
tmp_path: Path,
) -> None:
verilator = shutil.which("verilator")
if verilator is None:
return
memory_map = tmp_path / "memory_map"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/address_map/generate_memory_map.py"),
"--map",
str(ROOT / "rtl/mini/address_map/memory_map.json"),
"--output-dir",
str(memory_map),
"--have-sram-if",
"NO",
],
check=True,
)
output = tmp_path / "axi4_interconnect_tb"
ccache_tmp = tmp_path / "ccache"
ccache_tmp.mkdir()
subprocess.run(
[
verilator,
"--binary",
"--timing",
"-Wno-fatal",
"--top-module",
"axi4_interconnect_tb",
"-I" + str(memory_map / "rtl"),
"-I" + str(ROOT / "rtl/mini/top"),
"-I" + str(ROOT / "rtl/managed/clusterip/common/rtl"),
"-I" + str(ROOT / "rtl/managed/clusterip/common/rtl/interface"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/stream/round_robin_arbiter.sv"),
str(ROOT / "rtl/mini/top/axi4_interconnect.sv"),
str(ROOT / "rtl/mini/top/axi4_error_slave.sv"),
str(ROOT / "tests/rtl/axi4_interconnect_tb.sv"),
"-Mdir",
str(tmp_path / "obj"),
"-o",
str(output),
],
check=True,
text=True,
capture_output=True,
env={
**os.environ,
"CCACHE_DIR": str(ccache_tmp),
"CCACHE_TEMPDIR": str(ccache_tmp),
},
)
result = subprocess.run([output], check=True, text=True, capture_output=True)
assert "AXI4 interconnect fault classification test passed" in result.stdout
+2 -1
View File
@@ -40,6 +40,7 @@ def test_dma_reports_bus_errors_and_transfers_exact_word_count(tmp_path: Path) -
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
f"+incdir+{ROOT / 'rtl/mini/top'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_stream_if.sv"),
str(ROOT / "rtl/mini/top/rib_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/fifo.sv"),
@@ -69,4 +70,4 @@ def test_dma_reports_bus_errors_and_transfers_exact_word_count(tmp_path: Path) -
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "dma error and burst performance test passed" in result.stdout
assert "dma error, burst performance, and AXI4-Stream test passed" in result.stdout
+1
View File
@@ -148,6 +148,7 @@ def test_bus_fault_responder_handles_reserved_and_unmapped_addresses(tmp_path: P
f"+incdir+{tmp_path / 'rtl'}",
f"+incdir+{tmp_path / 'user_extensions' / 'rtl'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ram_if.sv"),
str(ROOT / "rtl/mini/top/rib_if.sv"),
+1
View File
@@ -39,6 +39,7 @@ def test_bus_preserves_incr4_and_rejects_illegal_bursts(tmp_path: Path) -> None:
f"+incdir+{memory_map / 'rtl'}",
f"+incdir+{ROOT / 'rtl/mini/top'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ram_if.sv"),
str(ROOT / "rtl/mini/top/rib_if.sv"),
+1 -1
View File
@@ -737,7 +737,7 @@ def test_management_core_is_fixed_to_hazard3_with_debug() -> None:
assert "CORE_$(CORE)" not in makefile
assert "`ifdef CORE_" not in wrapper
assert "`ifdef HAVE_DEBUG" not in wrapper
assert "ahbl2ribp u_ahbl2ribp" in wrapper
assert "ahbl2axi4 u_ahbl2axi4" in wrapper
assert ".RESET_VECTOR (`SOC_CPU_RESET_ADDR)" in wrapper
assert ".DEBUG_SUPPORT (1)" in wrapper
+7 -7
View File
@@ -79,7 +79,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
assert "assign s_slv_sel_d[17] = u_i2c1_ribp_if.valid;" in routes
assert "assign s_slv_resp_err[17] = u_i2c1_ribp_if.resp_err;" in routes
assert "assign ribp.resp_err = |(s_slv_sel_q & s_slv_ready & s_slv_resp_err);" in routes
assert "assign s_xpi_region_sel[1] = (ribp.addr <= `SOC_ADDR_FLASH_END);" in routes
assert "SOC_ADDR_FLASH" not in routes
assert "assign u_sdio_ribp_if.valid = 1'b0;" in routes
assert gpio.count("// GPIO") == 64
assert "u_uart1_if" not in gpio
@@ -106,12 +106,12 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
assert "assign user_ip.paddr = s_addr_q;" in apb_routes
assert "({32{s_psel_q[7]}} & user_ip.prdata)" in apb_response
assert "localparam int NSLV = 8;" in apb_declarations
assert fabric.count("ribp_if u_") == 1
assert fabric.count("rib_if u_") == 4
assert ".mgmt_ribp(u_mgmt_ribp_if)" in bus_fabric
assert ".user_rib(u_user_rib_if)" in bus_fabric
assert ".apb_rib(u_apb_rib_if)" in bus_fabric
assert ".rib(u_rib_if)" in bus_fabric
assert fabric.count("axi4_if #(") == 5
assert ".mgmt_axi4(u_mgmt_axi4_if)" in bus_fabric
assert ".user_axi4(u_user_axi4_if)" in bus_fabric
assert ".dma_axi4(u_dma_axi4_if)" in bus_fabric
assert ".cfg_axi4(u_cfg_axi4_if)" in bus_fabric
assert ".apb_axi4(u_apb_axi4_if)" in bus_fabric
assert "`define SOC_IRQ_VECTOR_WIDTH 32" in irq_config
assert "`define SOC_USER_IRQ_MASK 32'h000E7BFC" in irq_config
assert "`define SOC_IRQ_RIBP_WIDTH 13" in irq_config
+1
View File
@@ -96,6 +96,7 @@ def test_ws2812_accepts_dma_fixed_destination_backpressure(tmp_path: Path) -> No
f"+incdir+{ROOT / 'rtl/mini/top'}",
f"+incdir+{serial}",
str(common / "interface/ribp_if.sv"),
str(common / "interface/axi4_stream_if.sv"),
str(ROOT / "rtl/mini/top/rib_if.sv"),
str(common / "utils/register.sv"),
str(common / "utils/fifo.sv"),