rtl: add axiS dma wrapper & tests
This commit is contained in:
345
axi/rtl/axi_dma_compat.sv
Normal file
345
axi/rtl/axi_dma_compat.sv
Normal file
@ -0,0 +1,345 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Compatibility wrapper over axi_dma_if_wrapper.
|
||||
//
|
||||
// Uses 4 axis_if channels for statuses and descs
|
||||
//
|
||||
// payload packing is LSB-first and one descriptor/status occupies one AXIS beat.
|
||||
// tkeep/tstrb/tlast/id/dest/user on descriptor inputs are ignored.
|
||||
// status outputs drive tkeep/tstrb to all ones, tlast to 1, and id/dest/user to 0.
|
||||
//
|
||||
// !!!!!: the original alexforencich axi_dma status outputs have
|
||||
// no ready/backpressure signal. This wrapper adds a oneentry holding register
|
||||
// for each status axis output, but if a downstream is not ready long enough for a
|
||||
// second status to arrive while the first one is still pending, the core cannot
|
||||
// be backpressured. In normal use keep status sinks ready, or add an external
|
||||
// FIFO if long stalls are possible.
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module axi_dma_axis_compat #(
|
||||
parameter int unsigned AXI_DATA_WIDTH = 32,
|
||||
parameter int unsigned AXI_ADDR_WIDTH = 16,
|
||||
parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXI_ID_WIDTH = 8,
|
||||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_MAX_BURST_LEN = 16,
|
||||
|
||||
parameter int unsigned AXIS_DATA_WIDTH = AXI_DATA_WIDTH,
|
||||
parameter int unsigned AXIS_KEEP_ENABLE = AXIS_DATA_WIDTH > 8,
|
||||
parameter int unsigned AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXIS_LAST_ENABLE = 1,
|
||||
parameter int unsigned AXIS_ID_ENABLE = 1,
|
||||
parameter int unsigned AXIS_ID_WIDTH = 8,
|
||||
parameter int unsigned AXIS_DEST_ENABLE = 0,
|
||||
parameter int unsigned AXIS_DEST_WIDTH = 8,
|
||||
parameter int unsigned AXIS_USER_ENABLE = 1,
|
||||
parameter int unsigned AXIS_USER_WIDTH = 1,
|
||||
|
||||
parameter int unsigned LEN_WIDTH = 20,
|
||||
parameter int unsigned TAG_WIDTH = 8,
|
||||
parameter int unsigned ENABLE_SG = 0,
|
||||
parameter int unsigned ENABLE_UNALIGNED = 0,
|
||||
|
||||
// Payload widths for descriptor/status AXIS streams.
|
||||
parameter int unsigned READ_DESC_PAYLOAD_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH,
|
||||
parameter int unsigned READ_DESC_AXIS_DATA_WIDTH = ((READ_DESC_PAYLOAD_WIDTH + 7) / 8) * 8,
|
||||
parameter int unsigned READ_DESC_STATUS_PAYLOAD_WIDTH = TAG_WIDTH + 4,
|
||||
parameter int unsigned READ_DESC_STATUS_AXIS_DATA_WIDTH = ((READ_DESC_STATUS_PAYLOAD_WIDTH + 7) / 8) * 8,
|
||||
parameter int unsigned WRITE_DESC_PAYLOAD_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH,
|
||||
parameter int unsigned WRITE_DESC_AXIS_DATA_WIDTH = ((WRITE_DESC_PAYLOAD_WIDTH + 7) / 8) * 8,
|
||||
parameter int unsigned WRITE_DESC_STATUS_PAYLOAD_WIDTH = LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4,
|
||||
parameter int unsigned WRITE_DESC_STATUS_AXIS_DATA_WIDTH = ((WRITE_DESC_STATUS_PAYLOAD_WIDTH + 7) / 8) * 8
|
||||
)(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
/*
|
||||
* AXI read descriptor input, encoded as one AXIS beat.
|
||||
* tdata layout, LSB first:
|
||||
* addr | len | tag | id | dest | user
|
||||
*/
|
||||
axis_if.slave s_axis_read_desc,
|
||||
|
||||
/*
|
||||
* AXI read descriptor status output, encoded as one AXIS beat.
|
||||
* tdata layout, LSB first:
|
||||
* tag | error
|
||||
*/
|
||||
axis_if.master m_axis_read_desc_status,
|
||||
|
||||
/*
|
||||
* AXI stream read data output.
|
||||
*/
|
||||
axis_if.master m_axis_read_data,
|
||||
|
||||
/*
|
||||
* AXI write descriptor input, encoded as one AXIS beat.
|
||||
* tdata layout, LSB first:
|
||||
* addr | len | tag
|
||||
*/
|
||||
axis_if.slave s_axis_write_desc,
|
||||
|
||||
/*
|
||||
* AXI write descriptor status output, encoded as one AXIS beat.
|
||||
* tdata layout, LSB first:
|
||||
* len | tag | id | dest | user | error
|
||||
*/
|
||||
axis_if.master m_axis_write_desc_status,
|
||||
|
||||
/*
|
||||
* AXI stream write data input.
|
||||
*/
|
||||
axis_if.slave s_axis_write_data,
|
||||
|
||||
/*
|
||||
* AXI memory master interface.
|
||||
*/
|
||||
axi4_if.master m_axi,
|
||||
|
||||
/*
|
||||
* Configuration.
|
||||
*/
|
||||
input logic read_enable,
|
||||
input logic write_enable,
|
||||
input logic write_abort
|
||||
);
|
||||
|
||||
localparam int unsigned RD_ADDR_LSB = 0;
|
||||
localparam int unsigned RD_LEN_LSB = RD_ADDR_LSB + AXI_ADDR_WIDTH;
|
||||
localparam int unsigned RD_TAG_LSB = RD_LEN_LSB + LEN_WIDTH;
|
||||
localparam int unsigned RD_ID_LSB = RD_TAG_LSB + TAG_WIDTH;
|
||||
localparam int unsigned RD_DEST_LSB = RD_ID_LSB + AXIS_ID_WIDTH;
|
||||
localparam int unsigned RD_USER_LSB = RD_DEST_LSB + AXIS_DEST_WIDTH;
|
||||
|
||||
localparam int unsigned RDS_TAG_LSB = 0;
|
||||
localparam int unsigned RDS_ERROR_LSB = RDS_TAG_LSB + TAG_WIDTH;
|
||||
|
||||
localparam int unsigned WD_ADDR_LSB = 0;
|
||||
localparam int unsigned WD_LEN_LSB = WD_ADDR_LSB + AXI_ADDR_WIDTH;
|
||||
localparam int unsigned WD_TAG_LSB = WD_LEN_LSB + LEN_WIDTH;
|
||||
|
||||
localparam int unsigned WDS_LEN_LSB = 0;
|
||||
localparam int unsigned WDS_TAG_LSB = WDS_LEN_LSB + LEN_WIDTH;
|
||||
localparam int unsigned WDS_ID_LSB = WDS_TAG_LSB + TAG_WIDTH;
|
||||
localparam int unsigned WDS_DEST_LSB = WDS_ID_LSB + AXIS_ID_WIDTH;
|
||||
localparam int unsigned WDS_USER_LSB = WDS_DEST_LSB + AXIS_DEST_WIDTH;
|
||||
localparam int unsigned WDS_ERROR_LSB = WDS_USER_LSB + AXIS_USER_WIDTH;
|
||||
|
||||
localparam int unsigned READ_DESC_AXIS_KEEP_WIDTH = READ_DESC_AXIS_DATA_WIDTH / 8;
|
||||
localparam int unsigned READ_DESC_STATUS_AXIS_KEEP_WIDTH = READ_DESC_STATUS_AXIS_DATA_WIDTH / 8;
|
||||
localparam int unsigned WRITE_DESC_AXIS_KEEP_WIDTH = WRITE_DESC_AXIS_DATA_WIDTH / 8;
|
||||
localparam int unsigned WRITE_DESC_STATUS_AXIS_KEEP_WIDTH = WRITE_DESC_STATUS_AXIS_DATA_WIDTH / 8;
|
||||
|
||||
logic rstn;
|
||||
assign rstn = ~rst;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Internal DMA-specific descriptor/status interfaces expected by
|
||||
// axi_dma_if_wrapper.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
axi_dma_read_desc_if #(
|
||||
.ADDR_W (AXI_ADDR_WIDTH),
|
||||
.LEN_W (LEN_WIDTH),
|
||||
.TAG_W (TAG_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) read_desc_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axi_dma_read_desc_status_if #(
|
||||
.TAG_W (TAG_WIDTH)
|
||||
) read_desc_status_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axi_dma_write_desc_if #(
|
||||
.ADDR_W (AXI_ADDR_WIDTH),
|
||||
.LEN_W (LEN_WIDTH),
|
||||
.TAG_W (TAG_WIDTH)
|
||||
) write_desc_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axi_dma_write_desc_status_if #(
|
||||
.LEN_W (LEN_WIDTH),
|
||||
.TAG_W (TAG_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) write_desc_status_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// AXIS read descriptor input -> DMA-specific read descriptor interface.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
assign read_desc_if.req.addr = s_axis_read_desc.req.t.data[RD_ADDR_LSB +: AXI_ADDR_WIDTH];
|
||||
assign read_desc_if.req.len = s_axis_read_desc.req.t.data[RD_LEN_LSB +: LEN_WIDTH];
|
||||
assign read_desc_if.req.tag = s_axis_read_desc.req.t.data[RD_TAG_LSB +: TAG_WIDTH];
|
||||
assign read_desc_if.req.id = s_axis_read_desc.req.t.data[RD_ID_LSB +: AXIS_ID_WIDTH];
|
||||
assign read_desc_if.req.dest = s_axis_read_desc.req.t.data[RD_DEST_LSB +: AXIS_DEST_WIDTH];
|
||||
assign read_desc_if.req.user = s_axis_read_desc.req.t.data[RD_USER_LSB +: AXIS_USER_WIDTH];
|
||||
assign read_desc_if.req.valid = s_axis_read_desc.req.t.valid;
|
||||
assign s_axis_read_desc.resp.ready = read_desc_if.resp.ready;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// AXIS write descriptor input -> DMA-specific write descriptor interface.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
assign write_desc_if.req.addr = s_axis_write_desc.req.t.data[WD_ADDR_LSB +: AXI_ADDR_WIDTH];
|
||||
assign write_desc_if.req.len = s_axis_write_desc.req.t.data[WD_LEN_LSB +: LEN_WIDTH];
|
||||
assign write_desc_if.req.tag = s_axis_write_desc.req.t.data[WD_TAG_LSB +: TAG_WIDTH];
|
||||
assign write_desc_if.req.valid = s_axis_write_desc.req.t.valid;
|
||||
assign s_axis_write_desc.resp.ready = write_desc_if.resp.ready;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// DMA-specific read status -> AXIS read status output.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
logic [READ_DESC_STATUS_AXIS_DATA_WIDTH-1:0] read_status_payload;
|
||||
logic [READ_DESC_STATUS_AXIS_DATA_WIDTH-1:0] read_status_data_q;
|
||||
logic read_status_valid_q;
|
||||
|
||||
always_comb begin
|
||||
read_status_payload = '0;
|
||||
read_status_payload[RDS_TAG_LSB +: TAG_WIDTH] = read_desc_status_if.req.tag;
|
||||
read_status_payload[RDS_ERROR_LSB +: 4] = read_desc_status_if.req.error;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
read_status_valid_q <= 1'b0;
|
||||
read_status_data_q <= '0;
|
||||
end else begin
|
||||
if (!read_status_valid_q || m_axis_read_desc_status.resp.ready) begin
|
||||
read_status_valid_q <= read_desc_status_if.req.valid;
|
||||
if (read_desc_status_if.req.valid) begin
|
||||
read_status_data_q <= read_status_payload;
|
||||
end else begin
|
||||
read_status_data_q <= '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
m_axis_read_desc_status.req.t.data = '0;
|
||||
m_axis_read_desc_status.req.t.keep = '0;
|
||||
m_axis_read_desc_status.req.t.strb = '0;
|
||||
m_axis_read_desc_status.req.t.last = read_status_valid_q;
|
||||
m_axis_read_desc_status.req.t.id = '0;
|
||||
m_axis_read_desc_status.req.t.dest = '0;
|
||||
m_axis_read_desc_status.req.t.user = '0;
|
||||
m_axis_read_desc_status.req.t.valid = read_status_valid_q;
|
||||
|
||||
m_axis_read_desc_status.req.t.data[READ_DESC_STATUS_AXIS_DATA_WIDTH-1:0] = read_status_data_q;
|
||||
m_axis_read_desc_status.req.t.keep[READ_DESC_STATUS_AXIS_KEEP_WIDTH-1:0] = {READ_DESC_STATUS_AXIS_KEEP_WIDTH{read_status_valid_q}};
|
||||
m_axis_read_desc_status.req.t.strb[READ_DESC_STATUS_AXIS_KEEP_WIDTH-1:0] = {READ_DESC_STATUS_AXIS_KEEP_WIDTH{read_status_valid_q}};
|
||||
end
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// DMA-specific write status -> AXIS write status output.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
logic [WRITE_DESC_STATUS_AXIS_DATA_WIDTH-1:0] write_status_payload;
|
||||
logic [WRITE_DESC_STATUS_AXIS_DATA_WIDTH-1:0] write_status_data_q;
|
||||
logic write_status_valid_q;
|
||||
|
||||
always_comb begin
|
||||
write_status_payload = '0;
|
||||
write_status_payload[WDS_LEN_LSB +: LEN_WIDTH] = write_desc_status_if.req.len;
|
||||
write_status_payload[WDS_TAG_LSB +: TAG_WIDTH] = write_desc_status_if.req.tag;
|
||||
write_status_payload[WDS_ID_LSB +: AXIS_ID_WIDTH] = write_desc_status_if.req.id;
|
||||
write_status_payload[WDS_DEST_LSB +: AXIS_DEST_WIDTH] = write_desc_status_if.req.dest;
|
||||
write_status_payload[WDS_USER_LSB +: AXIS_USER_WIDTH] = write_desc_status_if.req.user;
|
||||
write_status_payload[WDS_ERROR_LSB +: 4] = write_desc_status_if.req.error;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
write_status_valid_q <= 1'b0;
|
||||
write_status_data_q <= '0;
|
||||
end else begin
|
||||
if (!write_status_valid_q || m_axis_write_desc_status.resp.ready) begin
|
||||
write_status_valid_q <= write_desc_status_if.req.valid;
|
||||
if (write_desc_status_if.req.valid) begin
|
||||
write_status_data_q <= write_status_payload;
|
||||
end else begin
|
||||
write_status_data_q <= '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
m_axis_write_desc_status.req.t.data = '0;
|
||||
m_axis_write_desc_status.req.t.keep = '0;
|
||||
m_axis_write_desc_status.req.t.strb = '0;
|
||||
m_axis_write_desc_status.req.t.last = write_status_valid_q;
|
||||
m_axis_write_desc_status.req.t.id = '0;
|
||||
m_axis_write_desc_status.req.t.dest = '0;
|
||||
m_axis_write_desc_status.req.t.user = '0;
|
||||
m_axis_write_desc_status.req.t.valid = write_status_valid_q;
|
||||
|
||||
m_axis_write_desc_status.req.t.data[WRITE_DESC_STATUS_AXIS_DATA_WIDTH-1:0] = write_status_data_q;
|
||||
m_axis_write_desc_status.req.t.keep[WRITE_DESC_STATUS_AXIS_KEEP_WIDTH-1:0] = {WRITE_DESC_STATUS_AXIS_KEEP_WIDTH{write_status_valid_q}};
|
||||
m_axis_write_desc_status.req.t.strb[WRITE_DESC_STATUS_AXIS_KEEP_WIDTH-1:0] = {WRITE_DESC_STATUS_AXIS_KEEP_WIDTH{write_status_valid_q}};
|
||||
end
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Lower-level wrapper: DMA-specific descriptor/status interfaces inside,
|
||||
// ordinary AXIS data and AXI memory interfaces unchanged.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
axi_dma_if_wrapper #(
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH (AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_USER_WIDTH (AXI_USER_WIDTH),
|
||||
.AXI_MAX_BURST_LEN (AXI_MAX_BURST_LEN),
|
||||
.AXIS_DATA_WIDTH (AXIS_DATA_WIDTH),
|
||||
.AXIS_KEEP_ENABLE (AXIS_KEEP_ENABLE),
|
||||
.AXIS_KEEP_WIDTH (AXIS_KEEP_WIDTH),
|
||||
.AXIS_LAST_ENABLE (AXIS_LAST_ENABLE),
|
||||
.AXIS_ID_ENABLE (AXIS_ID_ENABLE),
|
||||
.AXIS_ID_WIDTH (AXIS_ID_WIDTH),
|
||||
.AXIS_DEST_ENABLE (AXIS_DEST_ENABLE),
|
||||
.AXIS_DEST_WIDTH (AXIS_DEST_WIDTH),
|
||||
.AXIS_USER_ENABLE (AXIS_USER_ENABLE),
|
||||
.AXIS_USER_WIDTH (AXIS_USER_WIDTH),
|
||||
.LEN_WIDTH (LEN_WIDTH),
|
||||
.TAG_WIDTH (TAG_WIDTH),
|
||||
.ENABLE_SG (ENABLE_SG),
|
||||
.ENABLE_UNALIGNED (ENABLE_UNALIGNED)
|
||||
) u_axi_dma_if_wrapper (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.s_axis_read_desc (read_desc_if),
|
||||
.m_axis_read_desc_status (read_desc_status_if),
|
||||
.m_axis_read_data (m_axis_read_data),
|
||||
|
||||
.s_axis_write_desc (write_desc_if),
|
||||
.m_axis_write_desc_status (write_desc_status_if),
|
||||
.s_axis_write_data (s_axis_write_data),
|
||||
|
||||
.m_axi (m_axi),
|
||||
|
||||
.read_enable (read_enable),
|
||||
.write_enable (write_enable),
|
||||
.write_abort (write_abort)
|
||||
);
|
||||
|
||||
endmodule : axi_dma_axis_compat
|
||||
|
||||
`default_nettype wire
|
||||
84
axi/tb/axi_dma_axis_compat/Makefile
Normal file
84
axi/tb/axi_dma_axis_compat/Makefile
Normal file
@ -0,0 +1,84 @@
|
||||
# Simple cocotb makefile for tb_axi_dma_axis_compat
|
||||
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
SIM ?= verilator
|
||||
|
||||
PWD := $(shell pwd)
|
||||
PROJECT_ROOT ?= $(abspath $(PWD)/../../..)
|
||||
|
||||
AXI_IF_RTL_DIR ?= $(PROJECT_ROOT)/axi/rtl
|
||||
FORENCICH_AXI_RTL_DIR ?= $(PROJECT_ROOT)/external/verilog-axi/rtl
|
||||
TB_DIR ?= $(PWD)
|
||||
|
||||
TOPLEVEL = tb_axi_dma_axis_compat
|
||||
MODULE = test_axi_dma_axis_compat
|
||||
|
||||
export PYTHONPATH := $(TB_DIR):$(PYTHONPATH)
|
||||
|
||||
|
||||
AXI_DATA_WIDTH ?= 32
|
||||
AXI_ADDR_WIDTH ?= 16
|
||||
AXI_ID_WIDTH ?= 8
|
||||
AXI_USER_WIDTH ?= 1
|
||||
AXI_MAX_BURST_LEN ?= 16
|
||||
ENABLE_UNALIGNED ?= 0
|
||||
|
||||
AXI_STRB_WIDTH := $(shell expr $(AXI_DATA_WIDTH) / 8)
|
||||
AXIS_DATA_WIDTH ?= $(AXI_DATA_WIDTH)
|
||||
AXIS_KEEP_WIDTH := $(shell expr $(AXIS_DATA_WIDTH) / 8)
|
||||
AXIS_KEEP_ENABLE := $(shell [ $(AXIS_DATA_WIDTH) -gt 8 ] && echo 1 || echo 0)
|
||||
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi_pkg.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi_if.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axis_if.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi4_flat_to_if.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi4_if_to_flat.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axis_flat_to_if.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axis_if_to_flat.sv
|
||||
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi_dma_desc_if.sv
|
||||
|
||||
VERILOG_SOURCES += $(FORENCICH_AXI_RTL_DIR)/axi_dma.v
|
||||
VERILOG_SOURCES += $(FORENCICH_AXI_RTL_DIR)/axi_dma_rd.v
|
||||
VERILOG_SOURCES += $(FORENCICH_AXI_RTL_DIR)/axi_dma_wr.v
|
||||
|
||||
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi_dma_if_wrapper.sv
|
||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi_dma_compat.sv
|
||||
VERILOG_SOURCES += $(TB_DIR)/tb_axi_dma_axis_compat.sv
|
||||
|
||||
COMPILE_ARGS += -I$(AXI_IF_RTL_DIR)
|
||||
|
||||
COMPILE_ARGS += -I$(FORENCICH_AXI_RTL_DIR)
|
||||
# took this from forencich to silence 100+ warnings
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH -Wno-CASEINCOMPLETE
|
||||
ifeq ($(SIM),verilator)
|
||||
EXTRA_ARGS += --trace
|
||||
EXTRA_ARGS += --trace-structs
|
||||
EXTRA_ARGS += -GAXI_DATA_WIDTH=$(AXI_DATA_WIDTH)
|
||||
EXTRA_ARGS += -GAXI_ADDR_WIDTH=$(AXI_ADDR_WIDTH)
|
||||
EXTRA_ARGS += -GAXI_STRB_WIDTH=$(AXI_STRB_WIDTH)
|
||||
EXTRA_ARGS += -GAXI_ID_WIDTH=$(AXI_ID_WIDTH)
|
||||
EXTRA_ARGS += -GAXI_USER_WIDTH=$(AXI_USER_WIDTH)
|
||||
EXTRA_ARGS += -GAXI_MAX_BURST_LEN=$(AXI_MAX_BURST_LEN)
|
||||
EXTRA_ARGS += -GAXIS_DATA_WIDTH=$(AXIS_DATA_WIDTH)
|
||||
EXTRA_ARGS += -GAXIS_KEEP_ENABLE=$(AXIS_KEEP_ENABLE)
|
||||
EXTRA_ARGS += -GAXIS_KEEP_WIDTH=$(AXIS_KEEP_WIDTH)
|
||||
EXTRA_ARGS += -GAXIS_LAST_ENABLE=1
|
||||
EXTRA_ARGS += -GAXIS_ID_ENABLE=1
|
||||
EXTRA_ARGS += -GAXIS_ID_WIDTH=8
|
||||
EXTRA_ARGS += -GAXIS_DEST_ENABLE=0
|
||||
EXTRA_ARGS += -GAXIS_DEST_WIDTH=8
|
||||
EXTRA_ARGS += -GAXIS_USER_ENABLE=1
|
||||
EXTRA_ARGS += -GAXIS_USER_WIDTH=1
|
||||
EXTRA_ARGS += -GLEN_WIDTH=20
|
||||
EXTRA_ARGS += -GTAG_WIDTH=8
|
||||
EXTRA_ARGS += -GENABLE_SG=0
|
||||
EXTRA_ARGS += -GENABLE_UNALIGNED=$(ENABLE_UNALIGNED)
|
||||
endif
|
||||
|
||||
export PARAM_AXI_DATA_WIDTH=$(AXI_DATA_WIDTH)
|
||||
export PARAM_ENABLE_UNALIGNED=$(ENABLE_UNALIGNED)
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
477
axi/tb/axi_dma_axis_compat/tb_axi_dma_axis_compat.sv
Normal file
477
axi/tb/axi_dma_axis_compat/tb_axi_dma_axis_compat.sv
Normal file
@ -0,0 +1,477 @@
|
||||
// another wrapper...
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module tb_axi_dma_axis_compat #(
|
||||
parameter int unsigned AXI_DATA_WIDTH = 32,
|
||||
parameter int unsigned AXI_ADDR_WIDTH = 16,
|
||||
parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXI_ID_WIDTH = 8,
|
||||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_MAX_BURST_LEN = 16,
|
||||
|
||||
parameter int unsigned AXIS_DATA_WIDTH = AXI_DATA_WIDTH,
|
||||
parameter int unsigned AXIS_KEEP_ENABLE = AXIS_DATA_WIDTH > 8,
|
||||
parameter int unsigned AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXIS_LAST_ENABLE = 1,
|
||||
parameter int unsigned AXIS_ID_ENABLE = 1,
|
||||
parameter int unsigned AXIS_ID_WIDTH = 8,
|
||||
parameter int unsigned AXIS_DEST_ENABLE = 0,
|
||||
parameter int unsigned AXIS_DEST_WIDTH = 8,
|
||||
parameter int unsigned AXIS_USER_ENABLE = 1,
|
||||
parameter int unsigned AXIS_USER_WIDTH = 1,
|
||||
|
||||
parameter int unsigned LEN_WIDTH = 20,
|
||||
parameter int unsigned TAG_WIDTH = 8,
|
||||
parameter int unsigned ENABLE_SG = 0,
|
||||
parameter int unsigned ENABLE_UNALIGNED = 0
|
||||
)();
|
||||
|
||||
// cocotb drives these directly
|
||||
logic clk;
|
||||
logic rst;
|
||||
logic rstn;
|
||||
|
||||
assign rstn = ~rst;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Descriptor/status payload widths and tdata layouts.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
localparam int unsigned READ_DESC_PAYLOAD_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH;
|
||||
localparam int unsigned READ_DESC_AXIS_DATA_WIDTH = ((READ_DESC_PAYLOAD_WIDTH + 7) / 8) * 8;
|
||||
localparam int unsigned READ_DESC_AXIS_KEEP_WIDTH = READ_DESC_AXIS_DATA_WIDTH / 8;
|
||||
|
||||
localparam int unsigned READ_DESC_STATUS_PAYLOAD_WIDTH = TAG_WIDTH + 4;
|
||||
localparam int unsigned READ_DESC_STATUS_AXIS_DATA_WIDTH = ((READ_DESC_STATUS_PAYLOAD_WIDTH + 7) / 8) * 8;
|
||||
localparam int unsigned READ_DESC_STATUS_AXIS_KEEP_WIDTH = READ_DESC_STATUS_AXIS_DATA_WIDTH / 8;
|
||||
|
||||
localparam int unsigned WRITE_DESC_PAYLOAD_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH;
|
||||
localparam int unsigned WRITE_DESC_AXIS_DATA_WIDTH = ((WRITE_DESC_PAYLOAD_WIDTH + 7) / 8) * 8;
|
||||
localparam int unsigned WRITE_DESC_AXIS_KEEP_WIDTH = WRITE_DESC_AXIS_DATA_WIDTH / 8;
|
||||
|
||||
localparam int unsigned WRITE_DESC_STATUS_PAYLOAD_WIDTH = LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4;
|
||||
localparam int unsigned WRITE_DESC_STATUS_AXIS_DATA_WIDTH = ((WRITE_DESC_STATUS_PAYLOAD_WIDTH + 7) / 8) * 8;
|
||||
localparam int unsigned WRITE_DESC_STATUS_AXIS_KEEP_WIDTH = WRITE_DESC_STATUS_AXIS_DATA_WIDTH / 8;
|
||||
|
||||
localparam int unsigned RD_ADDR_LSB = 0;
|
||||
localparam int unsigned RD_LEN_LSB = RD_ADDR_LSB + AXI_ADDR_WIDTH;
|
||||
localparam int unsigned RD_TAG_LSB = RD_LEN_LSB + LEN_WIDTH;
|
||||
localparam int unsigned RD_ID_LSB = RD_TAG_LSB + TAG_WIDTH;
|
||||
localparam int unsigned RD_DEST_LSB = RD_ID_LSB + AXIS_ID_WIDTH;
|
||||
localparam int unsigned RD_USER_LSB = RD_DEST_LSB + AXIS_DEST_WIDTH;
|
||||
|
||||
localparam int unsigned RDS_TAG_LSB = 0;
|
||||
localparam int unsigned RDS_ERROR_LSB = RDS_TAG_LSB + TAG_WIDTH;
|
||||
|
||||
localparam int unsigned WD_ADDR_LSB = 0;
|
||||
localparam int unsigned WD_LEN_LSB = WD_ADDR_LSB + AXI_ADDR_WIDTH;
|
||||
localparam int unsigned WD_TAG_LSB = WD_LEN_LSB + LEN_WIDTH;
|
||||
|
||||
localparam int unsigned WDS_LEN_LSB = 0;
|
||||
localparam int unsigned WDS_TAG_LSB = WDS_LEN_LSB + LEN_WIDTH;
|
||||
localparam int unsigned WDS_ID_LSB = WDS_TAG_LSB + TAG_WIDTH;
|
||||
localparam int unsigned WDS_DEST_LSB = WDS_ID_LSB + AXIS_ID_WIDTH;
|
||||
localparam int unsigned WDS_USER_LSB = WDS_DEST_LSB + AXIS_DEST_WIDTH;
|
||||
localparam int unsigned WDS_ERROR_LSB = WDS_USER_LSB + AXIS_USER_WIDTH;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Flat descriptor/status ports visible to cocotb.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
logic [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_addr;
|
||||
logic [LEN_WIDTH-1:0] s_axis_read_desc_len;
|
||||
logic [TAG_WIDTH-1:0] s_axis_read_desc_tag;
|
||||
logic [AXIS_ID_WIDTH-1:0] s_axis_read_desc_id;
|
||||
logic [AXIS_DEST_WIDTH-1:0] s_axis_read_desc_dest;
|
||||
logic [AXIS_USER_WIDTH-1:0] s_axis_read_desc_user;
|
||||
logic s_axis_read_desc_valid;
|
||||
logic s_axis_read_desc_ready;
|
||||
|
||||
logic [TAG_WIDTH-1:0] m_axis_read_desc_status_tag;
|
||||
logic [3:0] m_axis_read_desc_status_error;
|
||||
logic m_axis_read_desc_status_valid;
|
||||
|
||||
logic [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_addr;
|
||||
logic [LEN_WIDTH-1:0] s_axis_write_desc_len;
|
||||
logic [TAG_WIDTH-1:0] s_axis_write_desc_tag;
|
||||
logic s_axis_write_desc_valid;
|
||||
logic s_axis_write_desc_ready;
|
||||
|
||||
logic [LEN_WIDTH-1:0] m_axis_write_desc_status_len;
|
||||
logic [TAG_WIDTH-1:0] m_axis_write_desc_status_tag;
|
||||
logic [AXIS_ID_WIDTH-1:0] m_axis_write_desc_status_id;
|
||||
logic [AXIS_DEST_WIDTH-1:0] m_axis_write_desc_status_dest;
|
||||
logic [AXIS_USER_WIDTH-1:0] m_axis_write_desc_status_user;
|
||||
logic [3:0] m_axis_write_desc_status_error;
|
||||
logic m_axis_write_desc_status_valid;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Flat AXIS data ports visible to cocotb.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
logic [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata;
|
||||
logic [AXIS_KEEP_WIDTH-1:0] m_axis_read_data_tkeep;
|
||||
logic [AXIS_KEEP_WIDTH-1:0] m_axis_read_data_tstrb;
|
||||
logic m_axis_read_data_tvalid;
|
||||
logic m_axis_read_data_tready;
|
||||
logic m_axis_read_data_tlast;
|
||||
logic [AXIS_ID_WIDTH-1:0] m_axis_read_data_tid;
|
||||
logic [AXIS_DEST_WIDTH-1:0] m_axis_read_data_tdest;
|
||||
logic [AXIS_USER_WIDTH-1:0] m_axis_read_data_tuser;
|
||||
|
||||
logic [AXIS_DATA_WIDTH-1:0] s_axis_write_data_tdata;
|
||||
logic [AXIS_KEEP_WIDTH-1:0] s_axis_write_data_tkeep;
|
||||
logic [AXIS_KEEP_WIDTH-1:0] s_axis_write_data_tstrb;
|
||||
logic s_axis_write_data_tvalid;
|
||||
logic s_axis_write_data_tready;
|
||||
logic s_axis_write_data_tlast;
|
||||
logic [AXIS_ID_WIDTH-1:0] s_axis_write_data_tid;
|
||||
logic [AXIS_DEST_WIDTH-1:0] s_axis_write_data_tdest;
|
||||
logic [AXIS_USER_WIDTH-1:0] s_axis_write_data_tuser;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Flat AXI memory master ports visible to cocotb AxiRam.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
logic [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
logic [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
logic [7:0] m_axi_awlen;
|
||||
logic [2:0] m_axi_awsize;
|
||||
logic [1:0] m_axi_awburst;
|
||||
logic m_axi_awlock;
|
||||
logic [3:0] m_axi_awcache;
|
||||
logic [2:0] m_axi_awprot;
|
||||
logic [3:0] m_axi_awqos;
|
||||
logic [3:0] m_axi_awregion;
|
||||
logic [AXI_USER_WIDTH-1:0] m_axi_awuser;
|
||||
logic m_axi_awvalid;
|
||||
logic m_axi_awready;
|
||||
|
||||
logic [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
logic [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
logic m_axi_wlast;
|
||||
logic [AXI_USER_WIDTH-1:0] m_axi_wuser;
|
||||
logic m_axi_wvalid;
|
||||
logic m_axi_wready;
|
||||
|
||||
logic [AXI_ID_WIDTH-1:0] m_axi_bid;
|
||||
logic [1:0] m_axi_bresp;
|
||||
logic [AXI_USER_WIDTH-1:0] m_axi_buser;
|
||||
logic m_axi_bvalid;
|
||||
logic m_axi_bready;
|
||||
|
||||
logic [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
logic [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
logic [7:0] m_axi_arlen;
|
||||
logic [2:0] m_axi_arsize;
|
||||
logic [1:0] m_axi_arburst;
|
||||
logic m_axi_arlock;
|
||||
logic [3:0] m_axi_arcache;
|
||||
logic [2:0] m_axi_arprot;
|
||||
logic [3:0] m_axi_arqos;
|
||||
logic [3:0] m_axi_arregion;
|
||||
logic [AXI_USER_WIDTH-1:0] m_axi_aruser;
|
||||
logic m_axi_arvalid;
|
||||
logic m_axi_arready;
|
||||
|
||||
logic [AXI_ID_WIDTH-1:0] m_axi_rid;
|
||||
logic [AXI_DATA_WIDTH-1:0] m_axi_rdata;
|
||||
logic [1:0] m_axi_rresp;
|
||||
logic m_axi_rlast;
|
||||
logic [AXI_USER_WIDTH-1:0] m_axi_ruser;
|
||||
logic m_axi_rvalid;
|
||||
logic m_axi_rready;
|
||||
|
||||
// Configuration visible to cocotb
|
||||
logic read_enable;
|
||||
logic write_enable;
|
||||
logic write_abort;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Local interface instances.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
axis_if #(
|
||||
.DATA_W (READ_DESC_AXIS_DATA_WIDTH),
|
||||
.KEEP_W (READ_DESC_AXIS_KEEP_WIDTH),
|
||||
.ID_W (1),
|
||||
.DEST_W (1),
|
||||
.USER_W (1)
|
||||
) s_axis_read_desc_axis_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W (READ_DESC_STATUS_AXIS_DATA_WIDTH),
|
||||
.KEEP_W (READ_DESC_STATUS_AXIS_KEEP_WIDTH),
|
||||
.ID_W (1),
|
||||
.DEST_W (1),
|
||||
.USER_W (1)
|
||||
) m_axis_read_desc_status_axis_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W (WRITE_DESC_AXIS_DATA_WIDTH),
|
||||
.KEEP_W (WRITE_DESC_AXIS_KEEP_WIDTH),
|
||||
.ID_W (1),
|
||||
.DEST_W (1),
|
||||
.USER_W (1)
|
||||
) s_axis_write_desc_axis_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W (WRITE_DESC_STATUS_AXIS_DATA_WIDTH),
|
||||
.KEEP_W (WRITE_DESC_STATUS_AXIS_KEEP_WIDTH),
|
||||
.ID_W (1),
|
||||
.DEST_W (1),
|
||||
.USER_W (1)
|
||||
) m_axis_write_desc_status_axis_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W (AXIS_DATA_WIDTH),
|
||||
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) m_axis_read_data_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W (AXIS_DATA_WIDTH),
|
||||
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) s_axis_write_data_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_W (AXI_ADDR_WIDTH),
|
||||
.DATA_W (AXI_DATA_WIDTH),
|
||||
.ID_W (AXI_ID_WIDTH),
|
||||
.USER_W (AXI_USER_WIDTH)
|
||||
) m_axi_if (
|
||||
.aclk (clk),
|
||||
.aresetn (rstn)
|
||||
);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Flat descriptor/status <-> AXIS descriptor/status packing.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
always_comb begin
|
||||
s_axis_read_desc_axis_if.req.t.data = '0;
|
||||
s_axis_read_desc_axis_if.req.t.keep = {READ_DESC_AXIS_KEEP_WIDTH{s_axis_read_desc_valid}};
|
||||
s_axis_read_desc_axis_if.req.t.strb = {READ_DESC_AXIS_KEEP_WIDTH{s_axis_read_desc_valid}};
|
||||
s_axis_read_desc_axis_if.req.t.last = s_axis_read_desc_valid;
|
||||
s_axis_read_desc_axis_if.req.t.id = '0;
|
||||
s_axis_read_desc_axis_if.req.t.dest = '0;
|
||||
s_axis_read_desc_axis_if.req.t.user = '0;
|
||||
s_axis_read_desc_axis_if.req.t.valid = s_axis_read_desc_valid;
|
||||
|
||||
s_axis_read_desc_axis_if.req.t.data[RD_ADDR_LSB +: AXI_ADDR_WIDTH] = s_axis_read_desc_addr;
|
||||
s_axis_read_desc_axis_if.req.t.data[RD_LEN_LSB +: LEN_WIDTH] = s_axis_read_desc_len;
|
||||
s_axis_read_desc_axis_if.req.t.data[RD_TAG_LSB +: TAG_WIDTH] = s_axis_read_desc_tag;
|
||||
s_axis_read_desc_axis_if.req.t.data[RD_ID_LSB +: AXIS_ID_WIDTH] = s_axis_read_desc_id;
|
||||
s_axis_read_desc_axis_if.req.t.data[RD_DEST_LSB +: AXIS_DEST_WIDTH] = s_axis_read_desc_dest;
|
||||
s_axis_read_desc_axis_if.req.t.data[RD_USER_LSB +: AXIS_USER_WIDTH] = s_axis_read_desc_user;
|
||||
end
|
||||
|
||||
assign s_axis_read_desc_ready = s_axis_read_desc_axis_if.resp.ready;
|
||||
|
||||
always_comb begin
|
||||
m_axis_read_desc_status_tag = m_axis_read_desc_status_axis_if.req.t.data[RDS_TAG_LSB +: TAG_WIDTH];
|
||||
m_axis_read_desc_status_error = m_axis_read_desc_status_axis_if.req.t.data[RDS_ERROR_LSB +: 4];
|
||||
m_axis_read_desc_status_valid = m_axis_read_desc_status_axis_if.req.t.valid;
|
||||
end
|
||||
|
||||
assign m_axis_read_desc_status_axis_if.resp.ready = 1'b1;
|
||||
|
||||
always_comb begin
|
||||
s_axis_write_desc_axis_if.req.t.data = '0;
|
||||
s_axis_write_desc_axis_if.req.t.keep = {WRITE_DESC_AXIS_KEEP_WIDTH{s_axis_write_desc_valid}};
|
||||
s_axis_write_desc_axis_if.req.t.strb = {WRITE_DESC_AXIS_KEEP_WIDTH{s_axis_write_desc_valid}};
|
||||
s_axis_write_desc_axis_if.req.t.last = s_axis_write_desc_valid;
|
||||
s_axis_write_desc_axis_if.req.t.id = '0;
|
||||
s_axis_write_desc_axis_if.req.t.dest = '0;
|
||||
s_axis_write_desc_axis_if.req.t.user = '0;
|
||||
s_axis_write_desc_axis_if.req.t.valid = s_axis_write_desc_valid;
|
||||
|
||||
s_axis_write_desc_axis_if.req.t.data[WD_ADDR_LSB +: AXI_ADDR_WIDTH] = s_axis_write_desc_addr;
|
||||
s_axis_write_desc_axis_if.req.t.data[WD_LEN_LSB +: LEN_WIDTH] = s_axis_write_desc_len;
|
||||
s_axis_write_desc_axis_if.req.t.data[WD_TAG_LSB +: TAG_WIDTH] = s_axis_write_desc_tag;
|
||||
end
|
||||
|
||||
assign s_axis_write_desc_ready = s_axis_write_desc_axis_if.resp.ready;
|
||||
|
||||
always_comb begin
|
||||
m_axis_write_desc_status_len = m_axis_write_desc_status_axis_if.req.t.data[WDS_LEN_LSB +: LEN_WIDTH];
|
||||
m_axis_write_desc_status_tag = m_axis_write_desc_status_axis_if.req.t.data[WDS_TAG_LSB +: TAG_WIDTH];
|
||||
m_axis_write_desc_status_id = m_axis_write_desc_status_axis_if.req.t.data[WDS_ID_LSB +: AXIS_ID_WIDTH];
|
||||
m_axis_write_desc_status_dest = m_axis_write_desc_status_axis_if.req.t.data[WDS_DEST_LSB +: AXIS_DEST_WIDTH];
|
||||
m_axis_write_desc_status_user = m_axis_write_desc_status_axis_if.req.t.data[WDS_USER_LSB +: AXIS_USER_WIDTH];
|
||||
m_axis_write_desc_status_error = m_axis_write_desc_status_axis_if.req.t.data[WDS_ERROR_LSB +: 4];
|
||||
m_axis_write_desc_status_valid = m_axis_write_desc_status_axis_if.req.t.valid;
|
||||
end
|
||||
|
||||
assign m_axis_write_desc_status_axis_if.resp.ready = 1'b1;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Flat write stream -> interface.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
axis_flat_to_if #(
|
||||
.DATA_W (AXIS_DATA_WIDTH),
|
||||
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) u_s_axis_write_data_flat_to_if (
|
||||
.s_axis_tdata (s_axis_write_data_tdata),
|
||||
.s_axis_tkeep (s_axis_write_data_tkeep),
|
||||
.s_axis_tstrb (s_axis_write_data_tstrb),
|
||||
.s_axis_tlast (s_axis_write_data_tlast),
|
||||
.s_axis_tid (s_axis_write_data_tid),
|
||||
.s_axis_tdest (s_axis_write_data_tdest),
|
||||
.s_axis_tuser (s_axis_write_data_tuser),
|
||||
.s_axis_tvalid (s_axis_write_data_tvalid),
|
||||
.s_axis_tready (s_axis_write_data_tready),
|
||||
.m_axis (s_axis_write_data_if)
|
||||
);
|
||||
|
||||
// Wrapper read stream interface -> flat stream.
|
||||
axis_if_to_flat #(
|
||||
.DATA_W (AXIS_DATA_WIDTH),
|
||||
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) u_m_axis_read_data_if_to_flat (
|
||||
.s_axis (m_axis_read_data_if),
|
||||
.m_axis_tdata (m_axis_read_data_tdata),
|
||||
.m_axis_tkeep (m_axis_read_data_tkeep),
|
||||
.m_axis_tstrb (m_axis_read_data_tstrb),
|
||||
.m_axis_tlast (m_axis_read_data_tlast),
|
||||
.m_axis_tid (m_axis_read_data_tid),
|
||||
.m_axis_tdest (m_axis_read_data_tdest),
|
||||
.m_axis_tuser (m_axis_read_data_tuser),
|
||||
.m_axis_tvalid (m_axis_read_data_tvalid),
|
||||
.m_axis_tready (m_axis_read_data_tready)
|
||||
);
|
||||
|
||||
// Wrapper AXI interface -> flat AXI memory bus.
|
||||
axi4_if_to_flat #(
|
||||
.ADDR_W (AXI_ADDR_WIDTH),
|
||||
.DATA_W (AXI_DATA_WIDTH),
|
||||
.ID_W (AXI_ID_WIDTH),
|
||||
.USER_W (AXI_USER_WIDTH)
|
||||
) u_m_axi_if_to_flat (
|
||||
.s_axi (m_axi_if),
|
||||
|
||||
.m_axi_awid (m_axi_awid),
|
||||
.m_axi_awaddr (m_axi_awaddr),
|
||||
.m_axi_awlen (m_axi_awlen),
|
||||
.m_axi_awsize (m_axi_awsize),
|
||||
.m_axi_awburst (m_axi_awburst),
|
||||
.m_axi_awlock (m_axi_awlock),
|
||||
.m_axi_awcache (m_axi_awcache),
|
||||
.m_axi_awprot (m_axi_awprot),
|
||||
.m_axi_awqos (m_axi_awqos),
|
||||
.m_axi_awregion (m_axi_awregion),
|
||||
.m_axi_awuser (m_axi_awuser),
|
||||
.m_axi_awvalid (m_axi_awvalid),
|
||||
.m_axi_awready (m_axi_awready),
|
||||
|
||||
.m_axi_wdata (m_axi_wdata),
|
||||
.m_axi_wstrb (m_axi_wstrb),
|
||||
.m_axi_wlast (m_axi_wlast),
|
||||
.m_axi_wuser (m_axi_wuser),
|
||||
.m_axi_wvalid (m_axi_wvalid),
|
||||
.m_axi_wready (m_axi_wready),
|
||||
|
||||
.m_axi_bid (m_axi_bid),
|
||||
.m_axi_bresp (m_axi_bresp),
|
||||
.m_axi_buser (m_axi_buser),
|
||||
.m_axi_bvalid (m_axi_bvalid),
|
||||
.m_axi_bready (m_axi_bready),
|
||||
|
||||
.m_axi_arid (m_axi_arid),
|
||||
.m_axi_araddr (m_axi_araddr),
|
||||
.m_axi_arlen (m_axi_arlen),
|
||||
.m_axi_arsize (m_axi_arsize),
|
||||
.m_axi_arburst (m_axi_arburst),
|
||||
.m_axi_arlock (m_axi_arlock),
|
||||
.m_axi_arcache (m_axi_arcache),
|
||||
.m_axi_arprot (m_axi_arprot),
|
||||
.m_axi_arqos (m_axi_arqos),
|
||||
.m_axi_arregion (m_axi_arregion),
|
||||
.m_axi_aruser (m_axi_aruser),
|
||||
.m_axi_arvalid (m_axi_arvalid),
|
||||
.m_axi_arready (m_axi_arready),
|
||||
|
||||
.m_axi_rid (m_axi_rid),
|
||||
.m_axi_rdata (m_axi_rdata),
|
||||
.m_axi_rresp (m_axi_rresp),
|
||||
.m_axi_rlast (m_axi_rlast),
|
||||
.m_axi_ruser (m_axi_ruser),
|
||||
.m_axi_rvalid (m_axi_rvalid),
|
||||
.m_axi_rready (m_axi_rready)
|
||||
);
|
||||
|
||||
axi_dma_axis_compat #(
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH (AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_USER_WIDTH (AXI_USER_WIDTH),
|
||||
.AXI_MAX_BURST_LEN (AXI_MAX_BURST_LEN),
|
||||
.AXIS_DATA_WIDTH (AXIS_DATA_WIDTH),
|
||||
.AXIS_KEEP_ENABLE (AXIS_KEEP_ENABLE),
|
||||
.AXIS_KEEP_WIDTH (AXIS_KEEP_WIDTH),
|
||||
.AXIS_LAST_ENABLE (AXIS_LAST_ENABLE),
|
||||
.AXIS_ID_ENABLE (AXIS_ID_ENABLE),
|
||||
.AXIS_ID_WIDTH (AXIS_ID_WIDTH),
|
||||
.AXIS_DEST_ENABLE (AXIS_DEST_ENABLE),
|
||||
.AXIS_DEST_WIDTH (AXIS_DEST_WIDTH),
|
||||
.AXIS_USER_ENABLE (AXIS_USER_ENABLE),
|
||||
.AXIS_USER_WIDTH (AXIS_USER_WIDTH),
|
||||
.LEN_WIDTH (LEN_WIDTH),
|
||||
.TAG_WIDTH (TAG_WIDTH),
|
||||
.ENABLE_SG (ENABLE_SG),
|
||||
.ENABLE_UNALIGNED (ENABLE_UNALIGNED)
|
||||
) u_dut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.s_axis_read_desc (s_axis_read_desc_axis_if),
|
||||
.m_axis_read_desc_status (m_axis_read_desc_status_axis_if),
|
||||
|
||||
.m_axis_read_data (m_axis_read_data_if),
|
||||
|
||||
.s_axis_write_desc (s_axis_write_desc_axis_if),
|
||||
.m_axis_write_desc_status (m_axis_write_desc_status_axis_if),
|
||||
|
||||
.s_axis_write_data (s_axis_write_data_if),
|
||||
.m_axi (m_axi_if),
|
||||
|
||||
.read_enable (read_enable),
|
||||
.write_enable (write_enable),
|
||||
.write_abort (write_abort)
|
||||
);
|
||||
|
||||
endmodule : tb_axi_dma_axis_compat
|
||||
|
||||
`default_nettype wire
|
||||
362
axi/tb/axi_dma_axis_compat/test_axi_dma_axis_compat.py
Normal file
362
axi/tb/axi_dma_axis_compat/test_axi_dma_axis_compat.py
Normal file
@ -0,0 +1,362 @@
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb
|
||||
|
||||
try:
|
||||
import pytest
|
||||
except ImportError: # pytest is only needed for the optional cocotb-test entrypoint
|
||||
pytest = None
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.axi import AxiBus, AxiRam
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamFrame, AxiStreamSource, AxiStreamSink
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
|
||||
DescBus, DescTransaction, DescSource, DescSink, DescMonitor = define_stream(
|
||||
"Desc",
|
||||
signals=["addr", "len", "tag", "valid", "ready"],
|
||||
optional_signals=["id", "dest", "user"],
|
||||
)
|
||||
|
||||
DescStatusBus, DescStatusTransaction, DescStatusSource, DescStatusSink, DescStatusMonitor = define_stream(
|
||||
"DescStatus",
|
||||
signals=["tag", "error", "valid"],
|
||||
optional_signals=["len", "id", "dest", "user"],
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
self.log = logging.getLogger("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
|
||||
|
||||
# Cocotb still uses the original flat Forencich descriptor/status prefixes;
|
||||
# the SV top packs/unpacks these into ordinary axis_if streams.
|
||||
self.read_desc_source = DescSource(
|
||||
DescBus.from_prefix(dut, "s_axis_read_desc"), dut.clk, dut.rst
|
||||
)
|
||||
self.read_desc_status_sink = DescStatusSink(
|
||||
DescStatusBus.from_prefix(
|
||||
dut, "m_axis_read_desc_status"), dut.clk, dut.rst
|
||||
)
|
||||
self.write_desc_source = DescSource(
|
||||
DescBus.from_prefix(dut, "s_axis_write_desc"), dut.clk, dut.rst
|
||||
)
|
||||
self.write_desc_status_sink = DescStatusSink(
|
||||
DescStatusBus.from_prefix(
|
||||
dut, "m_axis_write_desc_status"), dut.clk, dut.rst
|
||||
)
|
||||
|
||||
# Data streams are flat from cocotb's point of view, but the SV top
|
||||
# sends them through axis_flat_to_if/axis_if_to_flat before/after DUT.
|
||||
self.read_data_sink = AxiStreamSink(
|
||||
AxiStreamBus.from_prefix(dut, "m_axis_read_data"), dut.clk, dut.rst
|
||||
)
|
||||
self.write_data_source = AxiStreamSource(
|
||||
AxiStreamBus.from_prefix(
|
||||
dut, "s_axis_write_data"), dut.clk, dut.rst
|
||||
)
|
||||
|
||||
# AXI memory model. The SV top routes this through the axi4_if adapters.
|
||||
self.axi_ram = AxiRam(AxiBus.from_prefix(
|
||||
dut, "m_axi"), dut.clk, dut.rst, size=2**16)
|
||||
|
||||
dut.read_enable.setimmediatevalue(0)
|
||||
dut.write_enable.setimmediatevalue(0)
|
||||
dut.write_abort.setimmediatevalue(0)
|
||||
|
||||
def set_idle_generator(self, generator=None):
|
||||
if generator:
|
||||
self.write_desc_source.set_pause_generator(generator())
|
||||
self.write_data_source.set_pause_generator(generator())
|
||||
self.read_desc_source.set_pause_generator(generator())
|
||||
self.axi_ram.write_if.b_channel.set_pause_generator(generator())
|
||||
self.axi_ram.read_if.r_channel.set_pause_generator(generator())
|
||||
|
||||
def set_backpressure_generator(self, generator=None):
|
||||
if generator:
|
||||
self.read_data_sink.set_pause_generator(generator())
|
||||
self.axi_ram.write_if.aw_channel.set_pause_generator(generator())
|
||||
self.axi_ram.write_if.w_channel.set_pause_generator(generator())
|
||||
self.axi_ram.read_if.ar_channel.set_pause_generator(generator())
|
||||
|
||||
async def cycle_reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
await RisingEdge(self.dut.clk)
|
||||
await RisingEdge(self.dut.clk)
|
||||
self.dut.rst.value = 1
|
||||
await RisingEdge(self.dut.clk)
|
||||
await RisingEdge(self.dut.clk)
|
||||
self.dut.rst.value = 0
|
||||
await RisingEdge(self.dut.clk)
|
||||
await RisingEdge(self.dut.clk)
|
||||
|
||||
|
||||
async def run_test_write(dut, data_in=None, idle_inserter=None, backpressure_inserter=None):
|
||||
"""DMA write path stress test adapted from Forencich's axi_dma test."""
|
||||
tb = TB(dut)
|
||||
|
||||
byte_lanes = tb.axi_ram.write_if.byte_lanes
|
||||
step_size = 1 if int(
|
||||
os.getenv("PARAM_ENABLE_UNALIGNED", "0")) else byte_lanes
|
||||
tag_count = 2 ** len(tb.write_desc_source.bus.tag)
|
||||
cur_tag = 1
|
||||
|
||||
await tb.cycle_reset()
|
||||
|
||||
tb.set_idle_generator(idle_inserter)
|
||||
tb.set_backpressure_generator(backpressure_inserter)
|
||||
|
||||
dut.write_enable.value = 1
|
||||
|
||||
for length in list(range(1, byte_lanes * 4 + 1)) + [128]:
|
||||
offsets = list(range(0, byte_lanes * 2, step_size))
|
||||
offsets += list(range(4096 - byte_lanes * 2, 4096, step_size))
|
||||
|
||||
for offset in offsets:
|
||||
for diff in [-8, -2, -1, 0, 1, 2, 8]:
|
||||
if length + diff < 1:
|
||||
continue
|
||||
|
||||
tb.log.info("write: length=%d offset=%d diff=%d",
|
||||
length, offset, diff)
|
||||
|
||||
addr = offset + 0x1000
|
||||
expected_data = bytearray([x % 256 for x in range(length)])
|
||||
stream_data = bytearray(
|
||||
[x % 256 for x in range(length + diff)])
|
||||
|
||||
tb.axi_ram.write(addr - 128, b"\xaa" *
|
||||
(len(expected_data) + 256))
|
||||
|
||||
await tb.write_desc_source.send(
|
||||
DescTransaction(addr=addr, len=len(
|
||||
expected_data), tag=cur_tag)
|
||||
)
|
||||
await tb.write_data_source.send(AxiStreamFrame(stream_data, tid=cur_tag))
|
||||
|
||||
status = await tb.write_desc_status_sink.recv()
|
||||
tb.log.info("write status: %s", status)
|
||||
|
||||
transferred_len = min(len(expected_data), len(stream_data))
|
||||
|
||||
assert int(status.len) == transferred_len
|
||||
assert int(status.tag) == cur_tag
|
||||
assert int(status.id) == cur_tag
|
||||
assert int(status.error) == 0
|
||||
|
||||
tb.log.debug(
|
||||
"%s",
|
||||
tb.axi_ram.hexdump_str(
|
||||
(addr & ~0xF) - 16,
|
||||
(((addr & 0xF) + length - 1) & ~0xF) + 48,
|
||||
),
|
||||
)
|
||||
|
||||
if len(expected_data) <= len(stream_data):
|
||||
assert tb.axi_ram.read(addr - 8, len(expected_data) + 16) == (
|
||||
b"\xaa" * 8 + expected_data + b"\xaa" * 8
|
||||
)
|
||||
else:
|
||||
assert tb.axi_ram.read(addr - 8, len(stream_data) + 16) == (
|
||||
b"\xaa" * 8 + stream_data + b"\xaa" * 8
|
||||
)
|
||||
|
||||
cur_tag = (cur_tag + 1) % tag_count
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
async def run_test_read(dut, data_in=None, idle_inserter=None, backpressure_inserter=None):
|
||||
"""DMA read path stress test adapted from Forencich's axi_dma test."""
|
||||
tb = TB(dut)
|
||||
|
||||
byte_lanes = tb.axi_ram.read_if.byte_lanes
|
||||
step_size = 1 if int(
|
||||
os.getenv("PARAM_ENABLE_UNALIGNED", "0")) else byte_lanes
|
||||
tag_count = 2 ** len(tb.read_desc_source.bus.tag)
|
||||
cur_tag = 1
|
||||
|
||||
await tb.cycle_reset()
|
||||
|
||||
tb.set_idle_generator(idle_inserter)
|
||||
tb.set_backpressure_generator(backpressure_inserter)
|
||||
|
||||
dut.read_enable.value = 1
|
||||
|
||||
for length in list(range(1, byte_lanes * 4 + 1)) + [128]:
|
||||
offsets = list(range(0, byte_lanes * 2, step_size))
|
||||
offsets += list(range(4096 - byte_lanes * 2, 4096, step_size))
|
||||
|
||||
for offset in offsets:
|
||||
tb.log.info("read: length=%d offset=%d", length, offset)
|
||||
|
||||
addr = offset + 0x1000
|
||||
test_data = bytearray([x % 256 for x in range(length)])
|
||||
|
||||
tb.axi_ram.write(addr - 128, b"\xaa" * (len(test_data) + 256))
|
||||
tb.axi_ram.write(addr, test_data)
|
||||
|
||||
tb.log.debug(
|
||||
"%s",
|
||||
tb.axi_ram.hexdump_str(
|
||||
(addr & ~0xF) - 16,
|
||||
(((addr & 0xF) + length - 1) & ~0xF) + 48,
|
||||
),
|
||||
)
|
||||
|
||||
await tb.read_desc_source.send(
|
||||
DescTransaction(addr=addr, len=len(
|
||||
test_data), tag=cur_tag, id=cur_tag)
|
||||
)
|
||||
|
||||
status = await tb.read_desc_status_sink.recv()
|
||||
read_data = await tb.read_data_sink.recv()
|
||||
|
||||
tb.log.info("read status: %s", status)
|
||||
tb.log.info("read data: %s", read_data)
|
||||
|
||||
assert int(status.tag) == cur_tag
|
||||
assert int(status.error) == 0
|
||||
assert read_data.tdata == test_data
|
||||
assert int(read_data.tid) == cur_tag
|
||||
|
||||
cur_tag = (cur_tag + 1) % tag_count
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
def cycle_pause():
|
||||
return itertools.cycle([1, 1, 1, 0])
|
||||
|
||||
|
||||
# When imported by cocotb inside a simulator, generate the actual cocotb tests.
|
||||
if cocotb.SIM_NAME:
|
||||
for test in [run_test_write, run_test_read]:
|
||||
factory = TestFactory(test)
|
||||
factory.add_option("idle_inserter", [None, cycle_pause])
|
||||
factory.add_option("backpressure_inserter", [None, cycle_pause])
|
||||
factory.generate_tests()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Optional pytest entrypoint via cocotb-test.
|
||||
# Run from this directory with: pytest -q test_axi_dma_axis_compat.py
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _sanitize_node_name(name):
|
||||
return name.replace("[", "-").replace("]", "").replace("/", "_")
|
||||
|
||||
|
||||
if pytest is not None:
|
||||
@pytest.mark.parametrize("axi_data_width", [8, 16, 32])
|
||||
@pytest.mark.parametrize("unaligned", [0, 1])
|
||||
def test_axi_dma_axis_compat_pytest(request, axi_data_width, unaligned):
|
||||
import cocotb_test.simulator
|
||||
|
||||
tests_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
project_root = os.path.abspath(os.path.join(tests_dir, "..", ".."))
|
||||
|
||||
axi_if_rtl_dir = os.environ.get(
|
||||
"AXI_IF_RTL_DIR", os.path.join(project_root, "rtl", "axi")
|
||||
)
|
||||
dma_if_rtl_dir = os.environ.get(
|
||||
"DMA_IF_RTL_DIR", os.path.join(project_root, "rtl", "dma")
|
||||
)
|
||||
wrapper_rtl_dir = os.environ.get(
|
||||
"WRAPPER_RTL_DIR", os.path.join(project_root, "rtl", "wrappers")
|
||||
)
|
||||
forencich_rtl_dir = os.environ.get(
|
||||
"FORENCICH_AXI_RTL_DIR",
|
||||
os.path.join(project_root, "external", "verilog-axi", "rtl"),
|
||||
)
|
||||
|
||||
dut = "tb_axi_dma_axis_compat"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
parameters = {
|
||||
"AXI_DATA_WIDTH": axi_data_width,
|
||||
"AXI_ADDR_WIDTH": 16,
|
||||
"AXI_ID_WIDTH": 8,
|
||||
"AXI_USER_WIDTH": 1,
|
||||
"AXI_MAX_BURST_LEN": 16,
|
||||
"AXIS_ID_ENABLE": 1,
|
||||
"AXIS_ID_WIDTH": 8,
|
||||
"AXIS_DEST_ENABLE": 0,
|
||||
"AXIS_DEST_WIDTH": 8,
|
||||
"AXIS_USER_ENABLE": 1,
|
||||
"AXIS_USER_WIDTH": 1,
|
||||
"LEN_WIDTH": 20,
|
||||
"TAG_WIDTH": 8,
|
||||
"ENABLE_SG": 0,
|
||||
"ENABLE_UNALIGNED": unaligned,
|
||||
}
|
||||
|
||||
parameters["AXI_STRB_WIDTH"] = parameters["AXI_DATA_WIDTH"] // 8
|
||||
parameters["AXIS_DATA_WIDTH"] = parameters["AXI_DATA_WIDTH"]
|
||||
parameters["AXIS_KEEP_ENABLE"] = int(parameters["AXIS_DATA_WIDTH"] > 8)
|
||||
parameters["AXIS_KEEP_WIDTH"] = parameters["AXIS_DATA_WIDTH"] // 8
|
||||
parameters["AXIS_LAST_ENABLE"] = 1
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(axi_if_rtl_dir, "axi_pkg.sv"),
|
||||
os.path.join(axi_if_rtl_dir, "axi_if.sv"),
|
||||
os.path.join(axi_if_rtl_dir, "axis_if.sv"),
|
||||
os.path.join(axi_if_rtl_dir, "axi4_flat_to_if.sv"),
|
||||
os.path.join(axi_if_rtl_dir, "axi4_if_to_flat.sv"),
|
||||
os.path.join(axi_if_rtl_dir, "axis_flat_to_if.sv"),
|
||||
os.path.join(axi_if_rtl_dir, "axis_if_to_flat.sv"),
|
||||
os.path.join(dma_if_rtl_dir, "axi_dma_desc_if.sv"),
|
||||
os.path.join(dma_if_rtl_dir, "axi_dma_read_desc_flat_to_if.sv"),
|
||||
os.path.join(dma_if_rtl_dir, "axi_dma_read_desc_if_to_flat.sv"),
|
||||
os.path.join(dma_if_rtl_dir,
|
||||
"axi_dma_read_desc_status_flat_to_if.sv"),
|
||||
os.path.join(dma_if_rtl_dir,
|
||||
"axi_dma_read_desc_status_if_to_flat.sv"),
|
||||
os.path.join(dma_if_rtl_dir, "axi_dma_write_desc_flat_to_if.sv"),
|
||||
os.path.join(dma_if_rtl_dir, "axi_dma_write_desc_if_to_flat.sv"),
|
||||
os.path.join(dma_if_rtl_dir,
|
||||
"axi_dma_write_desc_status_flat_to_if.sv"),
|
||||
os.path.join(dma_if_rtl_dir,
|
||||
"axi_dma_write_desc_status_if_to_flat.sv"),
|
||||
os.path.join(forencich_rtl_dir, "axi_dma.v"),
|
||||
os.path.join(forencich_rtl_dir, "axi_dma_rd.v"),
|
||||
os.path.join(forencich_rtl_dir, "axi_dma_wr.v"),
|
||||
os.path.join(wrapper_rtl_dir, "axi_dma_if_wrapper.sv"),
|
||||
os.path.join(wrapper_rtl_dir, "axi_dma_axis_compat.sv"),
|
||||
os.path.join(tests_dir, "tb_axi_dma_axis_compat.sv"),
|
||||
]
|
||||
|
||||
extra_env = {f"PARAM_{k}": str(v) for k, v in parameters.items()}
|
||||
sim_build = os.path.join(
|
||||
tests_dir, "sim_build", _sanitize_node_name(request.node.name))
|
||||
|
||||
extra_args = []
|
||||
if os.getenv("SIM", "verilator") == "verilator":
|
||||
extra_args += ["--trace-structs"]
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
includes=[axi_if_rtl_dir, dma_if_rtl_dir,
|
||||
wrapper_rtl_dir, forencich_rtl_dir],
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
waves=bool(int(os.getenv("WAVES", "0"))),
|
||||
extra_args=extra_args,
|
||||
)
|
||||
Reference in New Issue
Block a user