Open Twistix opened 1 year ago
Odd, the integration tests definitely test the module in a similar configuration: https://github.com/alexforencich/verilog-axi/blob/master/tb/axil_interconnect/test_axil_interconnect.py#L215-L216 . Well, S_COUNT 4, M_COUNT 1 is definitely tested, although M_ADDR_WIDTH I think is set to 24 instead of 32. I did just test this configuration on my end, and it seems to work fine. Can you perhaps post your whole testbench or a waveform dump or something that I can take a look at? Only thing I can think of maybe is some sort of X-propagation issue or something in the simulator. Does it make any difference if you explicitly specify the widths, M_BASE_ADDR = 32'd0, M_ADDR_WIDTH = 32'd32?
M_BASE_ADDR and M_ADDR_WIDTH control the address decoding for the various downstream components. Effectively, M_BASE_ADDR defines the mask of which bits are used for routing, and M_BASE_ADDR provides the addresses. All regions for all downstream components need to have non-overlapping assignments so that requests can be routed appropriately. If you set M_BASE_ADDR to 0, then there is a routine that will compute base addresses automatically based on M_ADDR_WIDTH. In your case with M_COUNT and M_REGIONS set to 1 and M_ADDR_WIDTH = ADDR_WIDTH, this is basically a degenerate case where there is no address decoding - no routing needs to be done, and all of the address bits get passed through to the single downstream device.
Hi, Thank you for your feedback.
I tested by setting 32'd32 and 32'd24 for M_ADDR_WIDTH but without success either.
Here is the wrapper I made for axil_interconnect :
`timescale 1ns / 1ps
module axi_interconnect_ip #(
parameter AXI_DATA_WIDTH = 32,
parameter AXI_ADDR_WIDTH = 32
)
(
// Clock and reset
input clk,
input rst,
// AXI Slave in 0
input [AXI_ADDR_WIDTH-1:0] S00_AXI_awaddr,
input [2:0] S00_AXI_awprot,
input S00_AXI_awvalid,
output S00_AXI_awready,
input [AXI_DATA_WIDTH-1:0] S00_AXI_wdata,
input [AXI_DATA_WIDTH/8-1:0] S00_AXI_wstrb,
input S00_AXI_wvalid,
output S00_AXI_wready,
output [1:0] S00_AXI_bresp,
output S00_AXI_bvalid,
input S00_AXI_bready,
input [AXI_ADDR_WIDTH-1:0] S00_AXI_araddr,
input [2:0] S00_AXI_arprot,
input S00_AXI_arvalid,
output S00_AXI_arready,
output [AXI_DATA_WIDTH-1:0] S00_AXI_rdata,
output [1:0] S00_AXI_rresp,
output S00_AXI_rvalid,
input S00_AXI_rready,
// AXI Slave in 1
input [AXI_ADDR_WIDTH-1:0] S01_AXI_awaddr,
input [2:0] S01_AXI_awprot,
input S01_AXI_awvalid,
output S01_AXI_awready,
input [AXI_DATA_WIDTH-1:0] S01_AXI_wdata,
input [AXI_DATA_WIDTH/8-1:0] S01_AXI_wstrb,
input S01_AXI_wvalid,
output S01_AXI_wready,
output [1:0] S01_AXI_bresp,
output S01_AXI_bvalid,
input S01_AXI_bready,
input [AXI_ADDR_WIDTH-1:0] S01_AXI_araddr,
input [2:0] S01_AXI_arprot,
input S01_AXI_arvalid,
output S01_AXI_arready,
output [AXI_DATA_WIDTH-1:0] S01_AXI_rdata,
output [1:0] S01_AXI_rresp,
output S01_AXI_rvalid,
input S01_AXI_rready,
// AXI Master out
output [AXI_ADDR_WIDTH-1:0] M_AXI_awaddr,
output [2:0] M_AXI_awprot,
output M_AXI_awvalid,
input M_AXI_awready,
output [AXI_DATA_WIDTH-1:0] M_AXI_wdata,
output [AXI_DATA_WIDTH/8-1:0] M_AXI_wstrb,
output M_AXI_wvalid,
input M_AXI_wready,
input [1:0] M_AXI_bresp,
input M_AXI_bvalid,
output M_AXI_bready,
output [AXI_ADDR_WIDTH-1:0] M_AXI_araddr,
output [2:0] M_AXI_arprot,
output M_AXI_arvalid,
input M_AXI_arready,
input [AXI_DATA_WIDTH-1:0] M_AXI_rdata,
input [1:0] M_AXI_rresp,
input M_AXI_rvalid,
output M_AXI_rready
);
axil_interconnect #(
.S_COUNT(2),
.M_COUNT(1),
.DATA_WIDTH(AXI_DATA_WIDTH),
.ADDR_WIDTH(AXI_ADDR_WIDTH),
.M_BASE_ADDR(32'd0),
.M_ADDR_WIDTH(32'd32)
)
axil_interconnect_inst (
.clk (clk),
.rst (rst),
.s_axil_awaddr ({S01_AXI_awaddr,S00_AXI_awaddr}),
.s_axil_awprot ({S01_AXI_awprot,S00_AXI_awprot}),
.s_axil_awvalid ({S01_AXI_awvalid,S00_AXI_awvalid}),
.s_axil_awready ({S01_AXI_awready,S00_AXI_awready}),
.s_axil_wdata ({S01_AXI_wdata,S00_AXI_wdata}),
.s_axil_wstrb ({S01_AXI_wstrb,S00_AXI_wstrb}),
.s_axil_wvalid ({S01_AXI_wvalid,S00_AXI_wvalid}),
.s_axil_wready ({S01_AXI_wready,S00_AXI_wready}),
.s_axil_bresp ({S01_AXI_bresp,S00_AXI_bresp}),
.s_axil_bvalid ({S01_AXI_bvalid,S00_AXI_bvalid}),
.s_axil_bready ({S01_AXI_bready,S00_AXI_bready}),
.s_axil_araddr ({S01_AXI_araddr,S00_AXI_araddr}),
.s_axil_arprot ({S01_AXI_arprot,S00_AXI_arprot}),
.s_axil_arvalid ({S01_AXI_arvalid,S00_AXI_arvalid}),
.s_axil_arready ({S01_AXI_arready,S00_AXI_arready}),
.s_axil_rdata ({S01_AXI_rdata,S00_AXI_rdata}),
.s_axil_rresp ({S01_AXI_rresp,S00_AXI_rresp}),
.s_axil_rvalid ({S01_AXI_rvalid,S00_AXI_rvalid}),
.s_axil_rready ({S01_AXI_rready,S00_AXI_rready}),
.m_axil_awaddr (M_AXI_awaddr),
.m_axil_awprot (M_AXI_awprot),
.m_axil_awvalid (M_AXI_awvalid),
.m_axil_awready (M_AXI_awready),
.m_axil_wdata (M_AXI_wdata),
.m_axil_wstrb (M_AXI_wstrb),
.m_axil_wvalid (M_AXI_wvalid),
.m_axil_wready (M_AXI_wready),
.m_axil_bresp (M_AXI_bresp),
.m_axil_bvalid (M_AXI_bvalid),
.m_axil_bready (M_AXI_bready),
.m_axil_araddr (M_AXI_araddr),
.m_axil_arprot (M_AXI_arprot),
.m_axil_arvalid (M_AXI_arvalid),
.m_axil_arready (M_AXI_arready),
.m_axil_rdata (M_AXI_rdata),
.m_axil_rresp (M_AXI_rresp),
.m_axil_rvalid (M_AXI_rvalid),
.m_axil_rready (M_AXI_rready)
);
endmodule
And here is the CocoTB test bench:
import cocotb
from cocotb.triggers import RisingEdge, FallingEdge
from cocotb.clock import Clock
from cocotbext.axi import AxiLiteBus, AxiLiteMaster, AxiLiteRam
# Test routine
@cocotb.test()
async def test_axi_interconnect(dut):
# DUT ports
clk = dut.clk
rst = dut.rst
# AXI Lite Bus
master0 = AxiLiteMaster(AxiLiteBus.from_prefix(dut, "S00_AXI"), clk, rst)
ram0 = AxiLiteRam(AxiLiteBus.from_prefix(dut, "M_AXI"), clk, rst, size=2**32)
# Clock Generation
cocotb.start_soon(Clock(clk, period=10, units="ns").start())
# Reseting the DUT
rst.value = 1
for i in range(5):
await FallingEdge(clk)
rst.value = 0
await FallingEdge(clk)
# Testing the DUT
await master0.write(0x2, b'test')
In the waveform I get, it seems that the slave inputs of the interconnect never pass awready to 1, so maybe that's why the master connected to the input waits forever when writing?
Hi Mr Forencich,
First of all, thank you very much for all your work on this repository and for publishing this.
I'm currently trying tu use your axil_interconnect IP in a N to 1 configuration, in order to connect several Masters outputs to a single Slave input.
However, I have a problem using this module. I tried to do a test-bench with Cocotb with the following setup for the axil_interconnect component :
In the Cocotb test-bench I then defined 2 AxiLiteMaster connected to the 2 input ports and an AxiLiteRam on the output bus. But during the execution of the test, it blocks when writing on the input ports.
I guess I'm setting up the parameters wrong, I'm having trouble understanding the purpose of M_BASE_ADDR and M_ADDR_WIDTH. Could you please give me some advice on how to get the AXI Lite interconnect to work in an N to 1 configuration?
Thanks in advance :)