fix: axi dma wrapper #2
@ -271,7 +271,7 @@ module axi_dma_wrapper #(
|
|||||||
// local read descriptor interface -> DMA flat input
|
// local read descriptor interface -> DMA flat input
|
||||||
axis_if_to_flat #(
|
axis_if_to_flat #(
|
||||||
.DATA_W (AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH),
|
.DATA_W (AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH),
|
||||||
.KEEP_W ('0),
|
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||||
.ID_W (AXIS_ID_WIDTH),
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
.DEST_W (AXIS_DEST_WIDTH),
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
.USER_W (AXIS_USER_WIDTH)
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
@ -282,7 +282,7 @@ module axi_dma_wrapper #(
|
|||||||
.m_axis_tstrb (),
|
.m_axis_tstrb (),
|
||||||
.m_axis_tlast (),
|
.m_axis_tlast (),
|
||||||
.m_axis_tid (dma_s_axis_read_desc_id),
|
.m_axis_tid (dma_s_axis_read_desc_id),
|
||||||
.m_axis_tdest (dma_s_axis_read_desc_tdest),
|
.m_axis_tdest (dma_s_axis_read_desc_dest),
|
||||||
.m_axis_tuser (dma_s_axis_read_desc_user),
|
.m_axis_tuser (dma_s_axis_read_desc_user),
|
||||||
.m_axis_tvalid (dma_s_axis_read_desc_valid),
|
.m_axis_tvalid (dma_s_axis_read_desc_valid),
|
||||||
.m_axis_tready (dma_s_axis_read_desc_ready)
|
.m_axis_tready (dma_s_axis_read_desc_ready)
|
||||||
@ -291,10 +291,10 @@ module axi_dma_wrapper #(
|
|||||||
// DMA read descriptor status flat output -> local status interface
|
// DMA read descriptor status flat output -> local status interface
|
||||||
axis_flat_to_if #(
|
axis_flat_to_if #(
|
||||||
.DATA_W (TAG_WIDTH + 4),
|
.DATA_W (TAG_WIDTH + 4),
|
||||||
.KEEP_W ('0),
|
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||||
.ID_W ('0),
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
.DEST_W ('0),
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
.USER_W ('0)
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
) i_read_desc_status_f2i(
|
) i_read_desc_status_f2i(
|
||||||
.s_axis_tdata ({dma_m_axis_read_desc_status_tag, dma_m_axis_read_desc_status_error}),
|
.s_axis_tdata ({dma_m_axis_read_desc_status_tag, dma_m_axis_read_desc_status_error}),
|
||||||
.s_axis_tkeep (),
|
.s_axis_tkeep (),
|
||||||
@ -311,7 +311,7 @@ module axi_dma_wrapper #(
|
|||||||
// local write descriptor interface -> DMA flat input
|
// local write descriptor interface -> DMA flat input
|
||||||
axis_if_to_flat #(
|
axis_if_to_flat #(
|
||||||
.DATA_W (AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH),
|
.DATA_W (AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH),
|
||||||
.KEEP_W ('0),
|
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||||
.ID_W (AXIS_ID_WIDTH),
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
.DEST_W (AXIS_DEST_WIDTH),
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
.USER_W (AXIS_USER_WIDTH)
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
@ -321,9 +321,9 @@ module axi_dma_wrapper #(
|
|||||||
.m_axis_tkeep (),
|
.m_axis_tkeep (),
|
||||||
.m_axis_tstrb (),
|
.m_axis_tstrb (),
|
||||||
.m_axis_tlast (),
|
.m_axis_tlast (),
|
||||||
.m_axis_tid (dma_s_axis_write_desc_id),
|
.m_axis_tid (),
|
||||||
.m_axis_tdest (dma_s_axis_write_desc_tdest),
|
.m_axis_tdest (),
|
||||||
.m_axis_tuser (dma_s_axis_write_desc_user),
|
.m_axis_tuser (),
|
||||||
.m_axis_tvalid (dma_s_axis_write_desc_valid),
|
.m_axis_tvalid (dma_s_axis_write_desc_valid),
|
||||||
.m_axis_tready (dma_s_axis_write_desc_ready)
|
.m_axis_tready (dma_s_axis_write_desc_ready)
|
||||||
);
|
);
|
||||||
@ -332,7 +332,7 @@ module axi_dma_wrapper #(
|
|||||||
// DMA write descriptor status flat output -> local status interface
|
// DMA write descriptor status flat output -> local status interface
|
||||||
axis_flat_to_if #(
|
axis_flat_to_if #(
|
||||||
.DATA_W (TAG_WIDTH + LEN_WIDTH + 4),
|
.DATA_W (TAG_WIDTH + LEN_WIDTH + 4),
|
||||||
.KEEP_W ('0),
|
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||||
.ID_W (AXIS_ID_WIDTH),
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
.DEST_W (AXIS_DEST_WIDTH),
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
.USER_W (AXIS_USER_WIDTH)
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
@ -448,6 +448,6 @@ module axi_dma_wrapper #(
|
|||||||
.m_axi (m_axi)
|
.m_axi (m_axi)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule : axi_dma_if_wrapper
|
endmodule : axi_dma_wrapper
|
||||||
|
|
||||||
`default_nettype wire
|
`default_nettype wire
|
||||||
|
|||||||
@ -44,8 +44,8 @@ VERILOG_SOURCES += $(FORENCICH_AXI_RTL_DIR)/axi_dma_rd.v
|
|||||||
VERILOG_SOURCES += $(FORENCICH_AXI_RTL_DIR)/axi_dma_wr.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_wrapper.sv
|
||||||
VERILOG_SOURCES += $(AXI_IF_RTL_DIR)/axi_dma_compat.sv
|
|
||||||
VERILOG_SOURCES += $(TB_DIR)/tb_axi_dma_axis_compat.sv
|
VERILOG_SOURCES += $(TB_DIR)/tb_axi_dma_axis_compat.sv
|
||||||
|
|
||||||
COMPILE_ARGS += -I$(AXI_IF_RTL_DIR)
|
COMPILE_ARGS += -I$(AXI_IF_RTL_DIR)
|
||||||
|
|||||||
@ -26,18 +26,14 @@ module tb_axi_dma_axis_compat #(
|
|||||||
parameter int unsigned ENABLE_SG = 0,
|
parameter int unsigned ENABLE_SG = 0,
|
||||||
parameter int unsigned ENABLE_UNALIGNED = 0,
|
parameter int unsigned ENABLE_UNALIGNED = 0,
|
||||||
|
|
||||||
parameter int unsigned READ_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH,
|
parameter int unsigned READ_DESC_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH,
|
||||||
parameter int unsigned WRITE_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH,
|
parameter int unsigned READ_DESC_DATA_WIDTH = ((READ_DESC_RAW_WIDTH + 7) / 8) * 8,
|
||||||
parameter int unsigned DESC_CMD_RAW_WIDTH = READ_DESC_WIDTH + WRITE_DESC_WIDTH,
|
parameter int unsigned WRITE_DESC_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH,
|
||||||
parameter int unsigned DESC_CMD_DATA_WIDTH = ((DESC_CMD_RAW_WIDTH + 7) / 8) * 8,
|
parameter int unsigned WRITE_DESC_DATA_WIDTH = ((WRITE_DESC_RAW_WIDTH + 7) / 8) * 8,
|
||||||
parameter int unsigned DESC_CMD_KEEP_WIDTH = DESC_CMD_DATA_WIDTH / 8,
|
parameter int unsigned READ_STATUS_RAW_WIDTH = TAG_WIDTH + 4,
|
||||||
|
parameter int unsigned READ_STATUS_DATA_WIDTH = ((READ_STATUS_RAW_WIDTH + 7) / 8) * 8,
|
||||||
parameter int unsigned READ_STATUS_WIDTH = TAG_WIDTH + 4,
|
parameter int unsigned WRITE_STATUS_RAW_WIDTH = LEN_WIDTH + TAG_WIDTH + 4,
|
||||||
parameter int unsigned WRITE_STATUS_WIDTH = LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4,
|
parameter int unsigned WRITE_STATUS_DATA_WIDTH = ((WRITE_STATUS_RAW_WIDTH + 7) / 8) * 8
|
||||||
parameter int unsigned DESC_STATUS_RAW_WIDTH = READ_STATUS_WIDTH + WRITE_STATUS_WIDTH,
|
|
||||||
parameter int unsigned DESC_STATUS_DATA_WIDTH = ((DESC_STATUS_RAW_WIDTH + 7) / 8) * 8,
|
|
||||||
parameter int unsigned DESC_STATUS_KEEP_WIDTH = DESC_STATUS_DATA_WIDTH / 8,
|
|
||||||
parameter int unsigned DESC_STATUS_USER_WIDTH = 2
|
|
||||||
)(
|
)(
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic rst,
|
input logic rst,
|
||||||
@ -46,27 +42,35 @@ module tb_axi_dma_axis_compat #(
|
|||||||
input logic write_enable,
|
input logic write_enable,
|
||||||
input logic write_abort,
|
input logic write_abort,
|
||||||
|
|
||||||
// Unified descriptor command AXIS, flat for cocotb
|
// Read descriptor AXIS input, flat for cocotb.
|
||||||
input logic [DESC_CMD_DATA_WIDTH-1:0] s_axis_desc_cmd_tdata,
|
// tdata layout: {addr, len, tag}; id/dest/user use AXIS sidebands.
|
||||||
input logic [DESC_CMD_KEEP_WIDTH-1:0] s_axis_desc_cmd_tkeep,
|
input logic [READ_DESC_DATA_WIDTH-1:0] s_axis_read_desc_tdata,
|
||||||
input logic [DESC_CMD_KEEP_WIDTH-1:0] s_axis_desc_cmd_tstrb,
|
input logic [AXIS_ID_WIDTH-1:0] s_axis_read_desc_tid,
|
||||||
input logic s_axis_desc_cmd_tlast,
|
input logic [AXIS_DEST_WIDTH-1:0] s_axis_read_desc_tdest,
|
||||||
input logic s_axis_desc_cmd_tid,
|
input logic [AXIS_USER_WIDTH-1:0] s_axis_read_desc_tuser,
|
||||||
input logic s_axis_desc_cmd_tdest,
|
input logic s_axis_read_desc_tvalid,
|
||||||
input logic s_axis_desc_cmd_tuser,
|
output logic s_axis_read_desc_tready,
|
||||||
input logic s_axis_desc_cmd_tvalid,
|
|
||||||
output logic s_axis_desc_cmd_tready,
|
|
||||||
|
|
||||||
// Unified descriptor status AXIS, flat for cocotb
|
// Read descriptor status AXIS output.
|
||||||
output logic [DESC_STATUS_DATA_WIDTH-1:0] m_axis_desc_status_tdata,
|
// tdata layout: {tag, error}.
|
||||||
output logic [DESC_STATUS_KEEP_WIDTH-1:0] m_axis_desc_status_tkeep,
|
output logic [READ_STATUS_DATA_WIDTH-1:0] m_axis_read_desc_status_tdata,
|
||||||
output logic [DESC_STATUS_KEEP_WIDTH-1:0] m_axis_desc_status_tstrb,
|
output logic m_axis_read_desc_status_tvalid,
|
||||||
output logic m_axis_desc_status_tlast,
|
input logic m_axis_read_desc_status_tready,
|
||||||
output logic m_axis_desc_status_tid,
|
|
||||||
output logic m_axis_desc_status_tdest,
|
// Write descriptor AXIS input.
|
||||||
output logic [DESC_STATUS_USER_WIDTH-1:0] m_axis_desc_status_tuser,
|
// tdata layout: {addr, len, tag}.
|
||||||
output logic m_axis_desc_status_tvalid,
|
input logic [WRITE_DESC_DATA_WIDTH-1:0] s_axis_write_desc_tdata,
|
||||||
input logic m_axis_desc_status_tready,
|
input logic s_axis_write_desc_tvalid,
|
||||||
|
output logic s_axis_write_desc_tready,
|
||||||
|
|
||||||
|
// Write descriptor status AXIS output.
|
||||||
|
// tdata layout: {len, tag, error}; id/dest/user use AXIS sidebands.
|
||||||
|
output logic [WRITE_STATUS_DATA_WIDTH-1:0] m_axis_write_desc_status_tdata,
|
||||||
|
output logic [AXIS_ID_WIDTH-1:0] m_axis_write_desc_status_tid,
|
||||||
|
output logic [AXIS_DEST_WIDTH-1:0] m_axis_write_desc_status_tdest,
|
||||||
|
output logic [AXIS_USER_WIDTH-1:0] m_axis_write_desc_status_tuser,
|
||||||
|
output logic m_axis_write_desc_status_tvalid,
|
||||||
|
input logic m_axis_write_desc_status_tready,
|
||||||
|
|
||||||
// Read data AXIS output
|
// Read data AXIS output
|
||||||
output logic [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata,
|
output logic [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata,
|
||||||
@ -144,23 +148,45 @@ module tb_axi_dma_axis_compat #(
|
|||||||
wire rstn = ~rst;
|
wire rstn = ~rst;
|
||||||
|
|
||||||
axis_if #(
|
axis_if #(
|
||||||
.DATA_W (DESC_CMD_DATA_WIDTH),
|
.DATA_W (READ_DESC_DATA_WIDTH),
|
||||||
.KEEP_W (DESC_CMD_KEEP_WIDTH),
|
.KEEP_W (READ_DESC_DATA_WIDTH / 8),
|
||||||
.ID_W (1),
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
.DEST_W (1),
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
.USER_W (1)
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
) desc_cmd_if (
|
) read_desc_if (
|
||||||
.aclk (clk),
|
.aclk (clk),
|
||||||
.aresetn (rstn)
|
.aresetn (rstn)
|
||||||
);
|
);
|
||||||
|
|
||||||
axis_if #(
|
axis_if #(
|
||||||
.DATA_W (DESC_STATUS_DATA_WIDTH),
|
.DATA_W (READ_STATUS_DATA_WIDTH),
|
||||||
.KEEP_W (DESC_STATUS_KEEP_WIDTH),
|
.KEEP_W (READ_STATUS_DATA_WIDTH / 8),
|
||||||
.ID_W (1),
|
.ID_W (1),
|
||||||
.DEST_W (1),
|
.DEST_W (1),
|
||||||
.USER_W (DESC_STATUS_USER_WIDTH)
|
.USER_W (1)
|
||||||
) desc_status_if (
|
) read_desc_status_if (
|
||||||
|
.aclk (clk),
|
||||||
|
.aresetn (rstn)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_if #(
|
||||||
|
.DATA_W (WRITE_DESC_DATA_WIDTH),
|
||||||
|
.KEEP_W (WRITE_DESC_DATA_WIDTH / 8),
|
||||||
|
.ID_W (1),
|
||||||
|
.DEST_W (1),
|
||||||
|
.USER_W (1)
|
||||||
|
) write_desc_if (
|
||||||
|
.aclk (clk),
|
||||||
|
.aresetn (rstn)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_if #(
|
||||||
|
.DATA_W (WRITE_STATUS_DATA_WIDTH),
|
||||||
|
.KEEP_W (WRITE_STATUS_DATA_WIDTH / 8),
|
||||||
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
|
) write_desc_status_if (
|
||||||
.aclk (clk),
|
.aclk (clk),
|
||||||
.aresetn (rstn)
|
.aresetn (rstn)
|
||||||
);
|
);
|
||||||
@ -198,41 +224,79 @@ module tb_axi_dma_axis_compat #(
|
|||||||
);
|
);
|
||||||
|
|
||||||
axis_flat_to_if #(
|
axis_flat_to_if #(
|
||||||
.DATA_W (DESC_CMD_DATA_WIDTH),
|
.DATA_W (READ_DESC_DATA_WIDTH),
|
||||||
.KEEP_W (DESC_CMD_KEEP_WIDTH),
|
.KEEP_W (READ_DESC_DATA_WIDTH / 8),
|
||||||
.ID_W (1),
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
.DEST_W (1),
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
.USER_W (1)
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
) u_desc_cmd_flat_to_if (
|
) u_read_desc_flat_to_if (
|
||||||
.s_axis_tdata (s_axis_desc_cmd_tdata),
|
.s_axis_tdata (s_axis_read_desc_tdata),
|
||||||
.s_axis_tkeep (s_axis_desc_cmd_tkeep),
|
.s_axis_tkeep ({(READ_DESC_DATA_WIDTH/8){1'b1}}),
|
||||||
.s_axis_tstrb (s_axis_desc_cmd_tstrb),
|
.s_axis_tstrb ({(READ_DESC_DATA_WIDTH/8){1'b1}}),
|
||||||
.s_axis_tlast (s_axis_desc_cmd_tlast),
|
.s_axis_tlast (1'b1),
|
||||||
.s_axis_tid (s_axis_desc_cmd_tid),
|
.s_axis_tid (s_axis_read_desc_tid),
|
||||||
.s_axis_tdest (s_axis_desc_cmd_tdest),
|
.s_axis_tdest (s_axis_read_desc_tdest),
|
||||||
.s_axis_tuser (s_axis_desc_cmd_tuser),
|
.s_axis_tuser (s_axis_read_desc_tuser),
|
||||||
.s_axis_tvalid (s_axis_desc_cmd_tvalid),
|
.s_axis_tvalid (s_axis_read_desc_tvalid),
|
||||||
.s_axis_tready (s_axis_desc_cmd_tready),
|
.s_axis_tready (s_axis_read_desc_tready),
|
||||||
.m_axis (desc_cmd_if)
|
.m_axis (read_desc_if)
|
||||||
);
|
);
|
||||||
|
|
||||||
axis_if_to_flat #(
|
axis_if_to_flat #(
|
||||||
.DATA_W (DESC_STATUS_DATA_WIDTH),
|
.DATA_W (READ_STATUS_DATA_WIDTH),
|
||||||
.KEEP_W (DESC_STATUS_KEEP_WIDTH),
|
.KEEP_W (READ_STATUS_DATA_WIDTH / 8),
|
||||||
.ID_W (1),
|
.ID_W (1),
|
||||||
.DEST_W (1),
|
.DEST_W (1),
|
||||||
.USER_W (DESC_STATUS_USER_WIDTH)
|
.USER_W (1)
|
||||||
) u_desc_status_if_to_flat (
|
) u_read_desc_status_if_to_flat (
|
||||||
.s_axis (desc_status_if),
|
.s_axis (read_desc_status_if),
|
||||||
.m_axis_tdata (m_axis_desc_status_tdata),
|
.m_axis_tdata (m_axis_read_desc_status_tdata),
|
||||||
.m_axis_tkeep (m_axis_desc_status_tkeep),
|
.m_axis_tkeep (),
|
||||||
.m_axis_tstrb (m_axis_desc_status_tstrb),
|
.m_axis_tstrb (),
|
||||||
.m_axis_tlast (m_axis_desc_status_tlast),
|
.m_axis_tlast (),
|
||||||
.m_axis_tid (m_axis_desc_status_tid),
|
.m_axis_tid (),
|
||||||
.m_axis_tdest (m_axis_desc_status_tdest),
|
.m_axis_tdest (),
|
||||||
.m_axis_tuser (m_axis_desc_status_tuser),
|
.m_axis_tuser (),
|
||||||
.m_axis_tvalid (m_axis_desc_status_tvalid),
|
.m_axis_tvalid (m_axis_read_desc_status_tvalid),
|
||||||
.m_axis_tready (m_axis_desc_status_tready)
|
.m_axis_tready (m_axis_read_desc_status_tready)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_flat_to_if #(
|
||||||
|
.DATA_W (WRITE_DESC_DATA_WIDTH),
|
||||||
|
.KEEP_W (WRITE_DESC_DATA_WIDTH / 8),
|
||||||
|
.ID_W (1),
|
||||||
|
.DEST_W (1),
|
||||||
|
.USER_W (1)
|
||||||
|
) u_write_desc_flat_to_if (
|
||||||
|
.s_axis_tdata (s_axis_write_desc_tdata),
|
||||||
|
.s_axis_tkeep ({(WRITE_DESC_DATA_WIDTH/8){1'b1}}),
|
||||||
|
.s_axis_tstrb ({(WRITE_DESC_DATA_WIDTH/8){1'b1}}),
|
||||||
|
.s_axis_tlast (1'b1),
|
||||||
|
.s_axis_tid (1'b0),
|
||||||
|
.s_axis_tdest (1'b0),
|
||||||
|
.s_axis_tuser (1'b0),
|
||||||
|
.s_axis_tvalid (s_axis_write_desc_tvalid),
|
||||||
|
.s_axis_tready (s_axis_write_desc_tready),
|
||||||
|
.m_axis (write_desc_if)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_if_to_flat #(
|
||||||
|
.DATA_W (WRITE_STATUS_DATA_WIDTH),
|
||||||
|
.KEEP_W (WRITE_STATUS_DATA_WIDTH / 8),
|
||||||
|
.ID_W (AXIS_ID_WIDTH),
|
||||||
|
.DEST_W (AXIS_DEST_WIDTH),
|
||||||
|
.USER_W (AXIS_USER_WIDTH)
|
||||||
|
) u_write_desc_status_if_to_flat (
|
||||||
|
.s_axis (write_desc_status_if),
|
||||||
|
.m_axis_tdata (m_axis_write_desc_status_tdata),
|
||||||
|
.m_axis_tkeep (),
|
||||||
|
.m_axis_tstrb (),
|
||||||
|
.m_axis_tlast (),
|
||||||
|
.m_axis_tid (m_axis_write_desc_status_tid),
|
||||||
|
.m_axis_tdest (m_axis_write_desc_status_tdest),
|
||||||
|
.m_axis_tuser (m_axis_write_desc_status_tuser),
|
||||||
|
.m_axis_tvalid (m_axis_write_desc_status_tvalid),
|
||||||
|
.m_axis_tready (m_axis_write_desc_status_tready)
|
||||||
);
|
);
|
||||||
|
|
||||||
axis_if_to_flat #(
|
axis_if_to_flat #(
|
||||||
@ -273,7 +337,7 @@ module tb_axi_dma_axis_compat #(
|
|||||||
.m_axis (write_data_if)
|
.m_axis (write_data_if)
|
||||||
);
|
);
|
||||||
|
|
||||||
axi_dma_axis_compat #(
|
axi_dma_wrapper #(
|
||||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||||
.AXI_STRB_WIDTH (AXI_STRB_WIDTH),
|
.AXI_STRB_WIDTH (AXI_STRB_WIDTH),
|
||||||
@ -293,21 +357,20 @@ module tb_axi_dma_axis_compat #(
|
|||||||
.LEN_WIDTH (LEN_WIDTH),
|
.LEN_WIDTH (LEN_WIDTH),
|
||||||
.TAG_WIDTH (TAG_WIDTH),
|
.TAG_WIDTH (TAG_WIDTH),
|
||||||
.ENABLE_SG (ENABLE_SG),
|
.ENABLE_SG (ENABLE_SG),
|
||||||
.ENABLE_UNALIGNED (ENABLE_UNALIGNED),
|
.ENABLE_UNALIGNED (ENABLE_UNALIGNED)
|
||||||
.DESC_CMD_DATA_WIDTH (DESC_CMD_DATA_WIDTH),
|
|
||||||
.DESC_STATUS_DATA_WIDTH (DESC_STATUS_DATA_WIDTH),
|
|
||||||
.DESC_STATUS_USER_WIDTH (DESC_STATUS_USER_WIDTH)
|
|
||||||
) u_dut (
|
) u_dut (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst (rst),
|
.rst (rst),
|
||||||
.s_axis_desc_cmd (desc_cmd_if),
|
.s_axis_read_desc (read_desc_if),
|
||||||
.m_axis_desc_status (desc_status_if),
|
.m_axis_read_desc_status (read_desc_status_if),
|
||||||
.m_axis_read_data (read_data_if),
|
.m_axis_read_data (read_data_if),
|
||||||
.s_axis_write_data (write_data_if),
|
.s_axis_write_desc (write_desc_if),
|
||||||
.m_axi (m_axi_if),
|
.m_axis_write_desc_status (write_desc_status_if),
|
||||||
.read_enable (read_enable),
|
.s_axis_write_data (write_data_if),
|
||||||
.write_enable (write_enable),
|
.m_axi (m_axi_if),
|
||||||
.write_abort (write_abort)
|
.read_enable (read_enable),
|
||||||
|
.write_enable (write_enable),
|
||||||
|
.write_abort (write_abort)
|
||||||
);
|
);
|
||||||
|
|
||||||
axi4_if_to_flat #(
|
axi4_if_to_flat #(
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import os
|
|||||||
|
|
||||||
import cocotb
|
import cocotb
|
||||||
from cocotb.clock import Clock
|
from cocotb.clock import Clock
|
||||||
from cocotb.triggers import RisingEdge, Combine
|
from cocotb.triggers import RisingEdge
|
||||||
|
|
||||||
from cocotbext.axi import AxiBus, AxiRam
|
from cocotbext.axi import AxiBus, AxiRam
|
||||||
from cocotbext.axi import AxiStreamBus, AxiStreamFrame, AxiStreamSource, AxiStreamSink
|
from cocotbext.axi import AxiStreamBus, AxiStreamFrame, AxiStreamSource, AxiStreamSink
|
||||||
@ -16,42 +16,33 @@ AXIS_ID_WIDTH = int(os.getenv("PARAM_AXIS_ID_WIDTH", "8"))
|
|||||||
AXIS_DEST_WIDTH = int(os.getenv("PARAM_AXIS_DEST_WIDTH", "8"))
|
AXIS_DEST_WIDTH = int(os.getenv("PARAM_AXIS_DEST_WIDTH", "8"))
|
||||||
AXIS_USER_WIDTH = int(os.getenv("PARAM_AXIS_USER_WIDTH", "1"))
|
AXIS_USER_WIDTH = int(os.getenv("PARAM_AXIS_USER_WIDTH", "1"))
|
||||||
|
|
||||||
READ_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH + \
|
READ_DESC_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH
|
||||||
AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH
|
READ_DESC_DATA_WIDTH = ((READ_DESC_RAW_WIDTH + 7) // 8) * 8
|
||||||
WRITE_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH
|
READ_DESC_BYTES = READ_DESC_DATA_WIDTH // 8
|
||||||
DESC_CMD_RAW_WIDTH = READ_DESC_WIDTH + WRITE_DESC_WIDTH
|
|
||||||
DESC_CMD_DATA_WIDTH = ((DESC_CMD_RAW_WIDTH + 7) // 8) * 8
|
|
||||||
DESC_CMD_BYTES = DESC_CMD_DATA_WIDTH // 8
|
|
||||||
|
|
||||||
READ_STATUS_WIDTH = TAG_WIDTH + 4
|
WRITE_DESC_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH
|
||||||
WRITE_STATUS_WIDTH = LEN_WIDTH + TAG_WIDTH + \
|
WRITE_DESC_DATA_WIDTH = ((WRITE_DESC_RAW_WIDTH + 7) // 8) * 8
|
||||||
AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4
|
WRITE_DESC_BYTES = WRITE_DESC_DATA_WIDTH // 8
|
||||||
DESC_STATUS_RAW_WIDTH = READ_STATUS_WIDTH + WRITE_STATUS_WIDTH
|
|
||||||
DESC_STATUS_DATA_WIDTH = ((DESC_STATUS_RAW_WIDTH + 7) // 8) * 8
|
|
||||||
DESC_STATUS_BYTES = DESC_STATUS_DATA_WIDTH // 8
|
|
||||||
|
|
||||||
RD_ADDR_LSB = 0
|
READ_STATUS_RAW_WIDTH = TAG_WIDTH + 4
|
||||||
RD_LEN_LSB = RD_ADDR_LSB + AXI_ADDR_WIDTH
|
READ_STATUS_DATA_WIDTH = ((READ_STATUS_RAW_WIDTH + 7) // 8) * 8
|
||||||
RD_TAG_LSB = RD_LEN_LSB + LEN_WIDTH
|
|
||||||
RD_ID_LSB = RD_TAG_LSB + TAG_WIDTH
|
|
||||||
RD_DEST_LSB = RD_ID_LSB + AXIS_ID_WIDTH
|
|
||||||
RD_USER_LSB = RD_DEST_LSB + AXIS_DEST_WIDTH
|
|
||||||
|
|
||||||
WR_BASE_LSB = READ_DESC_WIDTH
|
WRITE_STATUS_RAW_WIDTH = LEN_WIDTH + TAG_WIDTH + 4
|
||||||
WR_ADDR_LSB = WR_BASE_LSB
|
WRITE_STATUS_DATA_WIDTH = ((WRITE_STATUS_RAW_WIDTH + 7) // 8) * 8
|
||||||
WR_LEN_LSB = WR_ADDR_LSB + AXI_ADDR_WIDTH
|
|
||||||
WR_TAG_LSB = WR_LEN_LSB + LEN_WIDTH
|
|
||||||
|
|
||||||
RD_STS_TAG_LSB = 0
|
# axi_dma_wrapper maps descriptor tdata as {addr, len, tag}.
|
||||||
RD_STS_ERROR_LSB = RD_STS_TAG_LSB + TAG_WIDTH
|
DESC_TAG_LSB = 0
|
||||||
|
DESC_LEN_LSB = DESC_TAG_LSB + TAG_WIDTH
|
||||||
|
DESC_ADDR_LSB = DESC_LEN_LSB + LEN_WIDTH
|
||||||
|
|
||||||
WR_STS_BASE_LSB = READ_STATUS_WIDTH
|
# Read status tdata is {tag, error}.
|
||||||
WR_STS_LEN_LSB = WR_STS_BASE_LSB
|
READ_STATUS_ERROR_LSB = 0
|
||||||
WR_STS_TAG_LSB = WR_STS_LEN_LSB + LEN_WIDTH
|
READ_STATUS_TAG_LSB = READ_STATUS_ERROR_LSB + 4
|
||||||
WR_STS_ID_LSB = WR_STS_TAG_LSB + TAG_WIDTH
|
|
||||||
WR_STS_DEST_LSB = WR_STS_ID_LSB + AXIS_ID_WIDTH
|
# Write status tdata is {len, tag, error}.
|
||||||
WR_STS_USER_LSB = WR_STS_DEST_LSB + AXIS_DEST_WIDTH
|
WRITE_STATUS_ERROR_LSB = 0
|
||||||
WR_STS_ERROR_LSB = WR_STS_USER_LSB + AXIS_USER_WIDTH
|
WRITE_STATUS_TAG_LSB = WRITE_STATUS_ERROR_LSB + 4
|
||||||
|
WRITE_STATUS_LEN_LSB = WRITE_STATUS_TAG_LSB + TAG_WIDTH
|
||||||
|
|
||||||
|
|
||||||
def mask(width):
|
def mask(width):
|
||||||
@ -68,59 +59,60 @@ def get(value, lsb, width):
|
|||||||
return (int(value) >> lsb) & mask(width)
|
return (int(value) >> lsb) & mask(width)
|
||||||
|
|
||||||
|
|
||||||
def pack_desc_cmd(
|
def pack_read_desc(*, addr, length, tag, axis_id=0, dest=0, user=0):
|
||||||
*,
|
|
||||||
read_addr=0,
|
|
||||||
read_len=0,
|
|
||||||
read_tag=0,
|
|
||||||
read_id=0,
|
|
||||||
read_dest=0,
|
|
||||||
read_user=0,
|
|
||||||
write_addr=0,
|
|
||||||
write_len=0,
|
|
||||||
write_tag=0,
|
|
||||||
):
|
|
||||||
value = 0
|
value = 0
|
||||||
value = put(value, RD_ADDR_LSB, AXI_ADDR_WIDTH, read_addr)
|
value = put(value, DESC_TAG_LSB, TAG_WIDTH, tag)
|
||||||
value = put(value, RD_LEN_LSB, LEN_WIDTH, read_len)
|
value = put(value, DESC_LEN_LSB, LEN_WIDTH, length)
|
||||||
value = put(value, RD_TAG_LSB, TAG_WIDTH, read_tag)
|
value = put(value, DESC_ADDR_LSB, AXI_ADDR_WIDTH, addr)
|
||||||
value = put(value, RD_ID_LSB, AXIS_ID_WIDTH, read_id)
|
|
||||||
value = put(value, RD_DEST_LSB, AXIS_DEST_WIDTH, read_dest)
|
|
||||||
value = put(value, RD_USER_LSB, AXIS_USER_WIDTH, read_user)
|
|
||||||
|
|
||||||
value = put(value, WR_ADDR_LSB, AXI_ADDR_WIDTH, write_addr)
|
return AxiStreamFrame(
|
||||||
value = put(value, WR_LEN_LSB, LEN_WIDTH, write_len)
|
value.to_bytes(READ_DESC_BYTES, byteorder="little"),
|
||||||
value = put(value, WR_TAG_LSB, TAG_WIDTH, write_tag)
|
tid=axis_id,
|
||||||
|
tdest=dest,
|
||||||
|
tuser=user,
|
||||||
|
)
|
||||||
|
|
||||||
return value.to_bytes(DESC_CMD_BYTES, byteorder="little")
|
|
||||||
|
def pack_write_desc(*, addr, length, tag):
|
||||||
|
value = 0
|
||||||
|
value = put(value, DESC_TAG_LSB, TAG_WIDTH, tag)
|
||||||
|
value = put(value, DESC_LEN_LSB, LEN_WIDTH, length)
|
||||||
|
value = put(value, DESC_ADDR_LSB, AXI_ADDR_WIDTH, addr)
|
||||||
|
|
||||||
|
return AxiStreamFrame(
|
||||||
|
value.to_bytes(WRITE_DESC_BYTES, byteorder="little")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def frame_to_int(frame):
|
def frame_to_int(frame):
|
||||||
return int.from_bytes(bytes(frame.tdata), byteorder="little")
|
return int.from_bytes(bytes(frame.tdata), byteorder="little")
|
||||||
|
|
||||||
|
|
||||||
def frame_tuser(frame):
|
def frame_sideband(frame, name):
|
||||||
|
value = getattr(frame, name)
|
||||||
try:
|
try:
|
||||||
return int(frame.tuser)
|
return int(value)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return int(frame.tuser[0]) if frame.tuser else 0
|
return int(value[0]) if value else 0
|
||||||
|
|
||||||
|
|
||||||
def unpack_status(frame):
|
def unpack_read_status(frame):
|
||||||
value = frame_to_int(frame)
|
value = frame_to_int(frame)
|
||||||
tuser = frame_tuser(frame)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"read_valid": bool(tuser & 0x1),
|
"tag": get(value, READ_STATUS_TAG_LSB, TAG_WIDTH),
|
||||||
"write_valid": bool(tuser & 0x2),
|
"error": get(value, READ_STATUS_ERROR_LSB, 4),
|
||||||
"read_tag": get(value, RD_STS_TAG_LSB, TAG_WIDTH),
|
}
|
||||||
"read_error": get(value, RD_STS_ERROR_LSB, 4),
|
|
||||||
"write_len": get(value, WR_STS_LEN_LSB, LEN_WIDTH),
|
|
||||||
"write_tag": get(value, WR_STS_TAG_LSB, TAG_WIDTH),
|
def unpack_write_status(frame):
|
||||||
"write_id": get(value, WR_STS_ID_LSB, AXIS_ID_WIDTH),
|
value = frame_to_int(frame)
|
||||||
"write_dest": get(value, WR_STS_DEST_LSB, AXIS_DEST_WIDTH),
|
return {
|
||||||
"write_user": get(value, WR_STS_USER_LSB, AXIS_USER_WIDTH),
|
"len": get(value, WRITE_STATUS_LEN_LSB, LEN_WIDTH),
|
||||||
"write_error": get(value, WR_STS_ERROR_LSB, 4),
|
"tag": get(value, WRITE_STATUS_TAG_LSB, TAG_WIDTH),
|
||||||
|
"error": get(value, WRITE_STATUS_ERROR_LSB, 4),
|
||||||
|
"id": frame_sideband(frame, "tid"),
|
||||||
|
"dest": frame_sideband(frame, "tdest"),
|
||||||
|
"user": frame_sideband(frame, "tuser"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,24 +124,45 @@ class TB:
|
|||||||
|
|
||||||
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
|
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
|
||||||
|
|
||||||
self.desc_cmd_source = AxiStreamSource(
|
self.read_desc_source = AxiStreamSource(
|
||||||
AxiStreamBus.from_prefix(dut, "s_axis_desc_cmd"), dut.clk, dut.rst
|
AxiStreamBus.from_prefix(dut, "s_axis_read_desc"),
|
||||||
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
)
|
)
|
||||||
self.desc_status_sink = AxiStreamSink(
|
self.read_desc_status_sink = AxiStreamSink(
|
||||||
AxiStreamBus.from_prefix(
|
AxiStreamBus.from_prefix(dut, "m_axis_read_desc_status"),
|
||||||
dut, "m_axis_desc_status"), dut.clk, dut.rst
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.write_desc_source = AxiStreamSource(
|
||||||
|
AxiStreamBus.from_prefix(dut, "s_axis_write_desc"),
|
||||||
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
|
)
|
||||||
|
self.write_desc_status_sink = AxiStreamSink(
|
||||||
|
AxiStreamBus.from_prefix(dut, "m_axis_write_desc_status"),
|
||||||
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.read_data_sink = AxiStreamSink(
|
self.read_data_sink = AxiStreamSink(
|
||||||
AxiStreamBus.from_prefix(dut, "m_axis_read_data"), dut.clk, dut.rst
|
AxiStreamBus.from_prefix(dut, "m_axis_read_data"),
|
||||||
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
)
|
)
|
||||||
self.write_data_source = AxiStreamSource(
|
self.write_data_source = AxiStreamSource(
|
||||||
AxiStreamBus.from_prefix(
|
AxiStreamBus.from_prefix(dut, "s_axis_write_data"),
|
||||||
dut, "s_axis_write_data"), dut.clk, dut.rst
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.axi_ram = AxiRam(AxiBus.from_prefix(
|
self.axi_ram = AxiRam(
|
||||||
dut, "m_axi"), dut.clk, dut.rst, size=2**16)
|
AxiBus.from_prefix(dut, "m_axi"),
|
||||||
|
dut.clk,
|
||||||
|
dut.rst,
|
||||||
|
size=2**AXI_ADDR_WIDTH,
|
||||||
|
)
|
||||||
|
|
||||||
dut.read_enable.setimmediatevalue(0)
|
dut.read_enable.setimmediatevalue(0)
|
||||||
dut.write_enable.setimmediatevalue(0)
|
dut.write_enable.setimmediatevalue(0)
|
||||||
@ -166,8 +179,11 @@ class TB:
|
|||||||
await RisingEdge(self.dut.clk)
|
await RisingEdge(self.dut.clk)
|
||||||
await RisingEdge(self.dut.clk)
|
await RisingEdge(self.dut.clk)
|
||||||
|
|
||||||
async def send_desc_cmd(self, payload):
|
async def send_read_desc(self, **kwargs):
|
||||||
await self.desc_cmd_source.send(AxiStreamFrame(payload))
|
await self.read_desc_source.send(pack_read_desc(**kwargs))
|
||||||
|
|
||||||
|
async def send_write_desc(self, **kwargs):
|
||||||
|
await self.write_desc_source.send(pack_write_desc(**kwargs))
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
@ -184,28 +200,26 @@ async def test_axis_compat_write_path(dut):
|
|||||||
|
|
||||||
tb.axi_ram.write(addr - 16, b"\xaa" * (len(data) + 32))
|
tb.axi_ram.write(addr - 16, b"\xaa" * (len(data) + 32))
|
||||||
|
|
||||||
cmd = pack_desc_cmd(write_addr=addr, write_len=len(data), write_tag=tag)
|
desc_task = cocotb.start_soon(
|
||||||
|
tb.send_write_desc(addr=addr, length=len(data), tag=tag)
|
||||||
cmd_task = cocotb.start_soon(tb.send_desc_cmd(cmd))
|
)
|
||||||
data_task = cocotb.start_soon(
|
data_task = cocotb.start_soon(
|
||||||
tb.write_data_source.send(AxiStreamFrame(data, tid=tag))
|
tb.write_data_source.send(AxiStreamFrame(data, tid=tag))
|
||||||
)
|
)
|
||||||
|
|
||||||
await cmd_task
|
await desc_task
|
||||||
await data_task
|
await data_task
|
||||||
|
|
||||||
status_frame = await tb.desc_status_sink.recv()
|
status = unpack_write_status(await tb.write_desc_status_sink.recv())
|
||||||
status = unpack_status(status_frame)
|
|
||||||
|
|
||||||
assert not status["read_valid"]
|
assert status["tag"] == tag
|
||||||
assert status["write_valid"]
|
assert status["len"] == len(data)
|
||||||
assert status["write_tag"] == tag
|
assert status["id"] == tag
|
||||||
assert status["write_len"] == len(data)
|
assert status["error"] == 0
|
||||||
assert status["write_id"] == tag
|
|
||||||
assert status["write_error"] == 0
|
|
||||||
|
|
||||||
assert tb.axi_ram.read(addr - 8, len(data) +
|
assert tb.axi_ram.read(addr - 8, len(data) + 16) == (
|
||||||
16) == b"\xaa" * 8 + data + b"\xaa" * 8
|
b"\xaa" * 8 + data + b"\xaa" * 8
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
@ -222,32 +236,26 @@ async def test_axis_compat_read_path(dut):
|
|||||||
|
|
||||||
tb.axi_ram.write(addr, data)
|
tb.axi_ram.write(addr, data)
|
||||||
|
|
||||||
cmd = pack_desc_cmd(
|
await tb.send_read_desc(
|
||||||
read_addr=addr,
|
addr=addr,
|
||||||
read_len=len(data),
|
length=len(data),
|
||||||
read_tag=tag,
|
tag=tag,
|
||||||
read_id=tag,
|
axis_id=tag,
|
||||||
read_dest=0,
|
dest=0,
|
||||||
read_user=0,
|
user=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
await tb.send_desc_cmd(cmd)
|
|
||||||
|
|
||||||
data_frame = await tb.read_data_sink.recv()
|
data_frame = await tb.read_data_sink.recv()
|
||||||
assert bytes(data_frame.tdata) == data
|
assert bytes(data_frame.tdata) == data
|
||||||
assert int(data_frame.tid) == tag
|
assert frame_sideband(data_frame, "tid") == tag
|
||||||
|
|
||||||
status_frame = await tb.desc_status_sink.recv()
|
status = unpack_read_status(await tb.read_desc_status_sink.recv())
|
||||||
status = unpack_status(status_frame)
|
assert status["tag"] == tag
|
||||||
|
assert status["error"] == 0
|
||||||
assert status["read_valid"]
|
|
||||||
assert not status["write_valid"]
|
|
||||||
assert status["read_tag"] == tag
|
|
||||||
assert status["read_error"] == 0
|
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
async def test_axis_compat_read_and_write_same_command(dut):
|
async def test_axis_compat_read_and_write_independent_desc_ports(dut):
|
||||||
tb = TB(dut)
|
tb = TB(dut)
|
||||||
await tb.reset()
|
await tb.reset()
|
||||||
|
|
||||||
@ -264,51 +272,46 @@ async def test_axis_compat_read_and_write_same_command(dut):
|
|||||||
tb.axi_ram.write(read_addr, read_data)
|
tb.axi_ram.write(read_addr, read_data)
|
||||||
tb.axi_ram.write(write_addr - 8, b"\xaa" * (len(write_data) + 16))
|
tb.axi_ram.write(write_addr - 8, b"\xaa" * (len(write_data) + 16))
|
||||||
|
|
||||||
cmd = pack_desc_cmd(
|
read_desc_task = cocotb.start_soon(
|
||||||
read_addr=read_addr,
|
tb.send_read_desc(
|
||||||
read_len=len(read_data),
|
addr=read_addr,
|
||||||
read_tag=read_tag,
|
length=len(read_data),
|
||||||
read_id=read_tag,
|
tag=read_tag,
|
||||||
write_addr=write_addr,
|
axis_id=read_tag,
|
||||||
write_len=len(write_data),
|
dest=0,
|
||||||
write_tag=write_tag,
|
user=0,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
write_desc_task = cocotb.start_soon(
|
||||||
cmd_task = cocotb.start_soon(tb.send_desc_cmd(cmd))
|
tb.send_write_desc(
|
||||||
data_task = cocotb.start_soon(
|
addr=write_addr,
|
||||||
|
length=len(write_data),
|
||||||
|
tag=write_tag,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
write_data_task = cocotb.start_soon(
|
||||||
tb.write_data_source.send(AxiStreamFrame(write_data, tid=write_tag))
|
tb.write_data_source.send(AxiStreamFrame(write_data, tid=write_tag))
|
||||||
)
|
)
|
||||||
|
|
||||||
await cmd_task
|
await read_desc_task
|
||||||
await data_task
|
await write_desc_task
|
||||||
|
await write_data_task
|
||||||
|
|
||||||
data_frame = await tb.read_data_sink.recv()
|
data_frame = await tb.read_data_sink.recv()
|
||||||
assert bytes(data_frame.tdata) == read_data
|
assert bytes(data_frame.tdata) == read_data
|
||||||
assert int(data_frame.tid) == read_tag
|
assert frame_sideband(data_frame, "tid") == read_tag
|
||||||
|
|
||||||
# status might be in 2 beats, depending on timings
|
read_status = unpack_read_status(await tb.read_desc_status_sink.recv())
|
||||||
seen_read = False
|
write_status = unpack_write_status(await tb.write_desc_status_sink.recv())
|
||||||
seen_write = False
|
|
||||||
|
|
||||||
for _ in range(2):
|
assert read_status["tag"] == read_tag
|
||||||
status_frame = await tb.desc_status_sink.recv()
|
assert read_status["error"] == 0
|
||||||
status = unpack_status(status_frame)
|
|
||||||
|
|
||||||
if status["read_valid"]:
|
assert write_status["tag"] == write_tag
|
||||||
assert status["read_tag"] == read_tag
|
assert write_status["len"] == len(write_data)
|
||||||
assert status["read_error"] == 0
|
assert write_status["id"] == write_tag
|
||||||
seen_read = True
|
assert write_status["error"] == 0
|
||||||
|
|
||||||
if status["write_valid"]:
|
assert tb.axi_ram.read(write_addr - 8, len(write_data) + 16) == (
|
||||||
assert status["write_tag"] == write_tag
|
b"\xaa" * 8 + write_data + b"\xaa" * 8
|
||||||
assert status["write_len"] == len(write_data)
|
)
|
||||||
assert status["write_error"] == 0
|
|
||||||
seen_write = True
|
|
||||||
|
|
||||||
if seen_read and seen_write:
|
|
||||||
break
|
|
||||||
|
|
||||||
assert seen_read
|
|
||||||
assert seen_write
|
|
||||||
assert tb.axi_ram.read(write_addr - 8, len(write_data) +
|
|
||||||
16) == b"\xaa" * 8 + write_data + b"\xaa" * 8
|
|
||||||
|
|||||||
Reference in New Issue
Block a user