Compare commits

4 Commits

8 changed files with 305 additions and 344 deletions

View File

@ -1,37 +1,64 @@
package dma_axil_reg_map_pkg; package dma_axil_reg_map_pkg;
localparam int unsigned DMA_AXIL_REG_MAP_N_REGS = 4; localparam int unsigned DMA_AXIL_REG_MAP_N_REGS = 6;
localparam int unsigned DMA_WRITE_DESC_CONTROL_REG = 0;
localparam int unsigned DMA_WRITE_DESC_ADDR_REG = 1;
localparam int unsigned DMA_WRITE_DESC_LEN_REG = 2;
localparam int unsigned DMA_READ_DESC_CONTROL_REG = 3;
localparam int unsigned DMA_READ_DESC_ADDR_REG = 4;
localparam int unsigned DMA_READ_DESC_LEN_REG = 5;
localparam logic [2:0] REG_BIT_RSVD = 3'd0; localparam logic [2:0] REG_BIT_RSVD = 3'd0;
localparam logic [2:0] REG_BIT_RO = 3'd1; localparam logic [2:0] REG_BIT_RO = 3'd1;
localparam logic [2:0] REG_BIT_RW = 3'd2; localparam logic [2:0] REG_BIT_RW = 3'd2;
localparam logic [2:0] REG_BIT_W1S = 3'd3; localparam logic [2:0] REG_BIT_W1S = 3'd3;
localparam logic [2:0] REG_BIT_W1C = 3'd4;
localparam DMA_WRITE_DESC_CONTROL_REG = 0; typedef logic [DMA_AXIL_REG_MAP_N_REGS-1:0][31:0][2:0] reg_mode_map_t;
localparam DMA_WRITE_DESC_ADDR_REG = 1;
localparam DMA_WRITE_DESC_LEN_REG = 2;
localparam DMA_READ_DESC_CONTROL_REG = 3;
localparam DMA_READ_DESC_ADDR_REG = 4;
localparam DMA_READ_DESC_LEN_REG = 5;
localparam logic [DMA_AXIL_REG_MAP_N_REGS-1:0][31:0][2:0] DMA_AXIL_REG_MAP_REG_MODE = '{ function automatic reg_mode_map_t make_dma_reg_mode();
reg_mode_map_t mode;
'{REG_BIT_RO, REG_BIT_W1S, default: REG_BIT_RSVD}, mode = '0;
'{32{REG_BIT_RW}, default: REG_BIT_RSVD},
'{32{REG_BIT_RW}, default: REG_BIT_RSVD},
'{REG_BIT_RO, REG_BIT_W1S, default: REG_BIT_RSVD},
'{32{REG_BIT_RW}, default: REG_BIT_RSVD},
'{32{REG_BIT_RW}, default: REG_BIT_RSVD}
};
localparam logic [DMA_AXIL_REG_MAP_N_REGS-1:0][31:0] DMA_AXIL_REG_MAP_REG_RST = '{ // По умолчанию всё reserved
32'h0000_0000, for (int reg_idx = 0; reg_idx < DMA_AXIL_REG_MAP_N_REGS; reg_idx++) begin
32'h0000_0000, for (int bit_idx = 0; bit_idx < 32; bit_idx++) begin
32'h0000_0000, mode[reg_idx][bit_idx] = REG_BIT_RSVD;
32'h0000_0000, end
32'h0000_0000, end
32'h0000_0000
}; // WRITE CONTROL
mode[DMA_WRITE_DESC_CONTROL_REG][0] = REG_BIT_RO;
mode[DMA_WRITE_DESC_CONTROL_REG][1] = REG_BIT_W1S;
// WRITE ADDR
for (int bit_idx = 0; bit_idx < 32; bit_idx++) begin
mode[DMA_WRITE_DESC_ADDR_REG][bit_idx] = REG_BIT_RW;
end
// WRITE LEN
for (int bit_idx = 0; bit_idx < 32; bit_idx++) begin
mode[DMA_WRITE_DESC_LEN_REG][bit_idx] = REG_BIT_RW;
end
// READ CONTROL
mode[DMA_READ_DESC_CONTROL_REG][0] = REG_BIT_RO;
mode[DMA_READ_DESC_CONTROL_REG][1] = REG_BIT_W1S;
// READ ADDR
for (int bit_idx = 0; bit_idx < 32; bit_idx++) begin
mode[DMA_READ_DESC_ADDR_REG][bit_idx] = REG_BIT_RW;
end
// READ LEN
for (int bit_idx = 0; bit_idx < 32; bit_idx++) begin
mode[DMA_READ_DESC_LEN_REG][bit_idx] = REG_BIT_RW;
end
return mode;
endfunction
localparam reg_mode_map_t DMA_AXIL_REG_MAP_REG_MODE = make_dma_reg_mode();
endpackage endpackage

View File

@ -2,7 +2,7 @@ module axi_crossbar_wrapper #(
parameter int SLAVE_QTY = 3, parameter int SLAVE_QTY = 3,
parameter int MASTER_QTY = 3, parameter int MASTER_QTY = 3,
parameter int ADDR_WIDTH = 32, parameter int ADDR_WIDTH = 32,
parameter int DATA_WIDTH = 32 parameter int DATA_WIDTH = 32,
parameter int STRB_WIDTH = (DATA_WIDTH/8) parameter int STRB_WIDTH = (DATA_WIDTH/8)
)( )(
input wire clk, input wire clk,

View File

@ -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 (AXIS_KEEP_WIDTH), .KEEP_W ('0),
.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_dest), .m_axis_tdest (dma_s_axis_read_desc_tdest),
.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 (AXIS_KEEP_WIDTH), .KEEP_W ('0),
.ID_W (AXIS_ID_WIDTH), .ID_W ('0),
.DEST_W (AXIS_DEST_WIDTH), .DEST_W ('0),
.USER_W (AXIS_USER_WIDTH) .USER_W ('0)
) 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 (AXIS_KEEP_WIDTH), .KEEP_W ('0),
.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 (), .m_axis_tid (dma_s_axis_write_desc_id),
.m_axis_tdest (), .m_axis_tdest (dma_s_axis_write_desc_tdest),
.m_axis_tuser (), .m_axis_tuser (dma_s_axis_write_desc_user),
.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 (AXIS_KEEP_WIDTH), .KEEP_W ('0),
.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_wrapper endmodule : axi_dma_if_wrapper
`default_nettype wire `default_nettype wire

View File

@ -13,7 +13,7 @@ interface axi4_if #(
typedef logic [DATA_W/8-1:0] strb_t; typedef logic [DATA_W/8-1:0] strb_t;
typedef logic [ID_W-1:0] id_t; typedef logic [ID_W-1:0] id_t;
typedef logic [USER_W-1:0] user_t; typedef logic [USER_W-1:0] user_t;
`AXI4_TYPEDEF_ALL(axi, addr_t, data_t, strb_t, id_t, user_t) `AXI4_TYPEDEF_ALL(axi, addr_t, data_t, strb_t, id_t, user_t);
axi_req_t req; axi_req_t req;
axi_resp_t resp; axi_resp_t resp;
modport master (input aclk, aresetn, output req, input resp); modport master (input aclk, aresetn, output req, input resp);
@ -34,7 +34,7 @@ interface axi4l_if #(
typedef logic [DATA_W-1:0] data_t; typedef logic [DATA_W-1:0] data_t;
typedef logic [DATA_W/8-1:0] strb_t; typedef logic [DATA_W/8-1:0] strb_t;
typedef logic [USER_W-1:0] user_t; typedef logic [USER_W-1:0] user_t;
`AXI4L_TYPEDEF_ALL(axil, addr_t, data_t, strb_t, user_t) `AXI4L_TYPEDEF_ALL(axil, addr_t, data_t, strb_t, user_t);
axil_req_t req; axil_req_t req;
axil_resp_t resp; axil_resp_t resp;
modport master (input aclk, aresetn, output req, input resp); modport master (input aclk, aresetn, output req, input resp);

View File

@ -1,6 +1,6 @@
module axil_cdc_wrapper #( module axil_cdc_wrapper #(
parameter int ADDR_WIDTH = 32 parameter int ADDR_WIDTH = 32,
parameter int DATA_WIDTH = 32, parameter int DATA_WIDTH = 32
)( )(
input wire s_clk, input wire s_clk,
input wire s_rst, input wire s_rst,
@ -83,8 +83,8 @@ module axil_cdc_wrapper #(
); );
axil_cdc #( axil_cdc #(
.ADDR_WIDTH (ADDR_WIDTH) .ADDR_WIDTH (ADDR_WIDTH),
.DATA_WIDTH (DATA_WIDTH), .DATA_WIDTH (DATA_WIDTH)
) i_axil_cdc ( ) i_axil_cdc (
.s_clk (s_clk), .s_clk (s_clk),
.s_rst (s_rst), .s_rst (s_rst),

View File

@ -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_wrapper.sv 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 VERILOG_SOURCES += $(TB_DIR)/tb_axi_dma_axis_compat.sv
COMPILE_ARGS += -I$(AXI_IF_RTL_DIR) COMPILE_ARGS += -I$(AXI_IF_RTL_DIR)

View File

@ -26,14 +26,18 @@ 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_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH, 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_DATA_WIDTH = ((READ_DESC_RAW_WIDTH + 7) / 8) * 8, parameter int unsigned WRITE_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH,
parameter int unsigned WRITE_DESC_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH, parameter int unsigned DESC_CMD_RAW_WIDTH = READ_DESC_WIDTH + WRITE_DESC_WIDTH,
parameter int unsigned WRITE_DESC_DATA_WIDTH = ((WRITE_DESC_RAW_WIDTH + 7) / 8) * 8, parameter int unsigned DESC_CMD_DATA_WIDTH = ((DESC_CMD_RAW_WIDTH + 7) / 8) * 8,
parameter int unsigned READ_STATUS_RAW_WIDTH = TAG_WIDTH + 4, parameter int unsigned DESC_CMD_KEEP_WIDTH = DESC_CMD_DATA_WIDTH / 8,
parameter int unsigned READ_STATUS_DATA_WIDTH = ((READ_STATUS_RAW_WIDTH + 7) / 8) * 8,
parameter int unsigned WRITE_STATUS_RAW_WIDTH = LEN_WIDTH + TAG_WIDTH + 4, parameter int unsigned READ_STATUS_WIDTH = TAG_WIDTH + 4,
parameter int unsigned WRITE_STATUS_DATA_WIDTH = ((WRITE_STATUS_RAW_WIDTH + 7) / 8) * 8 parameter int unsigned WRITE_STATUS_WIDTH = LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4,
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,
@ -42,35 +46,27 @@ module tb_axi_dma_axis_compat #(
input logic write_enable, input logic write_enable,
input logic write_abort, input logic write_abort,
// Read descriptor AXIS input, flat for cocotb. // Unified descriptor command AXIS, flat for cocotb
// tdata layout: {addr, len, tag}; id/dest/user use AXIS sidebands. input logic [DESC_CMD_DATA_WIDTH-1:0] s_axis_desc_cmd_tdata,
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_tkeep,
input logic [AXIS_ID_WIDTH-1:0] s_axis_read_desc_tid, input logic [DESC_CMD_KEEP_WIDTH-1:0] s_axis_desc_cmd_tstrb,
input logic [AXIS_DEST_WIDTH-1:0] s_axis_read_desc_tdest, input logic s_axis_desc_cmd_tlast,
input logic [AXIS_USER_WIDTH-1:0] s_axis_read_desc_tuser, input logic s_axis_desc_cmd_tid,
input logic s_axis_read_desc_tvalid, input logic s_axis_desc_cmd_tdest,
output logic s_axis_read_desc_tready, input logic s_axis_desc_cmd_tuser,
input logic s_axis_desc_cmd_tvalid,
output logic s_axis_desc_cmd_tready,
// Read descriptor status AXIS output. // Unified descriptor status AXIS, flat for cocotb
// tdata layout: {tag, error}. output logic [DESC_STATUS_DATA_WIDTH-1:0] m_axis_desc_status_tdata,
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_tkeep,
output logic m_axis_read_desc_status_tvalid, output logic [DESC_STATUS_KEEP_WIDTH-1:0] m_axis_desc_status_tstrb,
input logic m_axis_read_desc_status_tready, output logic m_axis_desc_status_tlast,
output logic m_axis_desc_status_tid,
// Write descriptor AXIS input. output logic m_axis_desc_status_tdest,
// tdata layout: {addr, len, tag}. output logic [DESC_STATUS_USER_WIDTH-1:0] m_axis_desc_status_tuser,
input logic [WRITE_DESC_DATA_WIDTH-1:0] s_axis_write_desc_tdata, output logic m_axis_desc_status_tvalid,
input logic s_axis_write_desc_tvalid, input logic m_axis_desc_status_tready,
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,
@ -148,45 +144,23 @@ module tb_axi_dma_axis_compat #(
wire rstn = ~rst; wire rstn = ~rst;
axis_if #( axis_if #(
.DATA_W (READ_DESC_DATA_WIDTH), .DATA_W (DESC_CMD_DATA_WIDTH),
.KEEP_W (READ_DESC_DATA_WIDTH / 8), .KEEP_W (DESC_CMD_KEEP_WIDTH),
.ID_W (AXIS_ID_WIDTH),
.DEST_W (AXIS_DEST_WIDTH),
.USER_W (AXIS_USER_WIDTH)
) read_desc_if (
.aclk (clk),
.aresetn (rstn)
);
axis_if #(
.DATA_W (READ_STATUS_DATA_WIDTH),
.KEEP_W (READ_STATUS_DATA_WIDTH / 8),
.ID_W (1), .ID_W (1),
.DEST_W (1), .DEST_W (1),
.USER_W (1) .USER_W (1)
) read_desc_status_if ( ) desc_cmd_if (
.aclk (clk), .aclk (clk),
.aresetn (rstn) .aresetn (rstn)
); );
axis_if #( axis_if #(
.DATA_W (WRITE_DESC_DATA_WIDTH), .DATA_W (DESC_STATUS_DATA_WIDTH),
.KEEP_W (WRITE_DESC_DATA_WIDTH / 8), .KEEP_W (DESC_STATUS_KEEP_WIDTH),
.ID_W (1), .ID_W (1),
.DEST_W (1), .DEST_W (1),
.USER_W (1) .USER_W (DESC_STATUS_USER_WIDTH)
) write_desc_if ( ) desc_status_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)
); );
@ -224,79 +198,41 @@ module tb_axi_dma_axis_compat #(
); );
axis_flat_to_if #( axis_flat_to_if #(
.DATA_W (READ_DESC_DATA_WIDTH), .DATA_W (DESC_CMD_DATA_WIDTH),
.KEEP_W (READ_DESC_DATA_WIDTH / 8), .KEEP_W (DESC_CMD_KEEP_WIDTH),
.ID_W (AXIS_ID_WIDTH),
.DEST_W (AXIS_DEST_WIDTH),
.USER_W (AXIS_USER_WIDTH)
) u_read_desc_flat_to_if (
.s_axis_tdata (s_axis_read_desc_tdata),
.s_axis_tkeep ({(READ_DESC_DATA_WIDTH/8){1'b1}}),
.s_axis_tstrb ({(READ_DESC_DATA_WIDTH/8){1'b1}}),
.s_axis_tlast (1'b1),
.s_axis_tid (s_axis_read_desc_tid),
.s_axis_tdest (s_axis_read_desc_tdest),
.s_axis_tuser (s_axis_read_desc_tuser),
.s_axis_tvalid (s_axis_read_desc_tvalid),
.s_axis_tready (s_axis_read_desc_tready),
.m_axis (read_desc_if)
);
axis_if_to_flat #(
.DATA_W (READ_STATUS_DATA_WIDTH),
.KEEP_W (READ_STATUS_DATA_WIDTH / 8),
.ID_W (1), .ID_W (1),
.DEST_W (1), .DEST_W (1),
.USER_W (1) .USER_W (1)
) u_read_desc_status_if_to_flat ( ) u_desc_cmd_flat_to_if (
.s_axis (read_desc_status_if), .s_axis_tdata (s_axis_desc_cmd_tdata),
.m_axis_tdata (m_axis_read_desc_status_tdata), .s_axis_tkeep (s_axis_desc_cmd_tkeep),
.m_axis_tkeep (), .s_axis_tstrb (s_axis_desc_cmd_tstrb),
.m_axis_tstrb (), .s_axis_tlast (s_axis_desc_cmd_tlast),
.m_axis_tlast (), .s_axis_tid (s_axis_desc_cmd_tid),
.m_axis_tid (), .s_axis_tdest (s_axis_desc_cmd_tdest),
.m_axis_tdest (), .s_axis_tuser (s_axis_desc_cmd_tuser),
.m_axis_tuser (), .s_axis_tvalid (s_axis_desc_cmd_tvalid),
.m_axis_tvalid (m_axis_read_desc_status_tvalid), .s_axis_tready (s_axis_desc_cmd_tready),
.m_axis_tready (m_axis_read_desc_status_tready) .m_axis (desc_cmd_if)
);
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 #( axis_if_to_flat #(
.DATA_W (WRITE_STATUS_DATA_WIDTH), .DATA_W (DESC_STATUS_DATA_WIDTH),
.KEEP_W (WRITE_STATUS_DATA_WIDTH / 8), .KEEP_W (DESC_STATUS_KEEP_WIDTH),
.ID_W (AXIS_ID_WIDTH), .ID_W (1),
.DEST_W (AXIS_DEST_WIDTH), .DEST_W (1),
.USER_W (AXIS_USER_WIDTH) .USER_W (DESC_STATUS_USER_WIDTH)
) u_write_desc_status_if_to_flat ( ) u_desc_status_if_to_flat (
.s_axis (write_desc_status_if), .s_axis (desc_status_if),
.m_axis_tdata (m_axis_write_desc_status_tdata), .m_axis_tdata (m_axis_desc_status_tdata),
.m_axis_tkeep (), .m_axis_tkeep (m_axis_desc_status_tkeep),
.m_axis_tstrb (), .m_axis_tstrb (m_axis_desc_status_tstrb),
.m_axis_tlast (), .m_axis_tlast (m_axis_desc_status_tlast),
.m_axis_tid (m_axis_write_desc_status_tid), .m_axis_tid (m_axis_desc_status_tid),
.m_axis_tdest (m_axis_write_desc_status_tdest), .m_axis_tdest (m_axis_desc_status_tdest),
.m_axis_tuser (m_axis_write_desc_status_tuser), .m_axis_tuser (m_axis_desc_status_tuser),
.m_axis_tvalid (m_axis_write_desc_status_tvalid), .m_axis_tvalid (m_axis_desc_status_tvalid),
.m_axis_tready (m_axis_write_desc_status_tready) .m_axis_tready (m_axis_desc_status_tready)
); );
axis_if_to_flat #( axis_if_to_flat #(
@ -337,7 +273,7 @@ module tb_axi_dma_axis_compat #(
.m_axis (write_data_if) .m_axis (write_data_if)
); );
axi_dma_wrapper #( axi_dma_axis_compat #(
.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),
@ -357,20 +293,21 @@ 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_read_desc (read_desc_if), .s_axis_desc_cmd (desc_cmd_if),
.m_axis_read_desc_status (read_desc_status_if), .m_axis_desc_status (desc_status_if),
.m_axis_read_data (read_data_if), .m_axis_read_data (read_data_if),
.s_axis_write_desc (write_desc_if), .s_axis_write_data (write_data_if),
.m_axis_write_desc_status (write_desc_status_if), .m_axi (m_axi_if),
.s_axis_write_data (write_data_if), .read_enable (read_enable),
.m_axi (m_axi_if), .write_enable (write_enable),
.read_enable (read_enable), .write_abort (write_abort)
.write_enable (write_enable),
.write_abort (write_abort)
); );
axi4_if_to_flat #( axi4_if_to_flat #(

View File

@ -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 from cocotb.triggers import RisingEdge, Combine
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,33 +16,42 @@ 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_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH READ_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH + \
READ_DESC_DATA_WIDTH = ((READ_DESC_RAW_WIDTH + 7) // 8) * 8 AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH
READ_DESC_BYTES = READ_DESC_DATA_WIDTH // 8 WRITE_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH
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
WRITE_DESC_RAW_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH READ_STATUS_WIDTH = TAG_WIDTH + 4
WRITE_DESC_DATA_WIDTH = ((WRITE_DESC_RAW_WIDTH + 7) // 8) * 8 WRITE_STATUS_WIDTH = LEN_WIDTH + TAG_WIDTH + \
WRITE_DESC_BYTES = WRITE_DESC_DATA_WIDTH // 8 AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4
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
READ_STATUS_RAW_WIDTH = TAG_WIDTH + 4 RD_ADDR_LSB = 0
READ_STATUS_DATA_WIDTH = ((READ_STATUS_RAW_WIDTH + 7) // 8) * 8 RD_LEN_LSB = RD_ADDR_LSB + AXI_ADDR_WIDTH
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
WRITE_STATUS_RAW_WIDTH = LEN_WIDTH + TAG_WIDTH + 4 WR_BASE_LSB = READ_DESC_WIDTH
WRITE_STATUS_DATA_WIDTH = ((WRITE_STATUS_RAW_WIDTH + 7) // 8) * 8 WR_ADDR_LSB = WR_BASE_LSB
WR_LEN_LSB = WR_ADDR_LSB + AXI_ADDR_WIDTH
WR_TAG_LSB = WR_LEN_LSB + LEN_WIDTH
# axi_dma_wrapper maps descriptor tdata as {addr, len, tag}. RD_STS_TAG_LSB = 0
DESC_TAG_LSB = 0 RD_STS_ERROR_LSB = RD_STS_TAG_LSB + TAG_WIDTH
DESC_LEN_LSB = DESC_TAG_LSB + TAG_WIDTH
DESC_ADDR_LSB = DESC_LEN_LSB + LEN_WIDTH
# Read status tdata is {tag, error}. WR_STS_BASE_LSB = READ_STATUS_WIDTH
READ_STATUS_ERROR_LSB = 0 WR_STS_LEN_LSB = WR_STS_BASE_LSB
READ_STATUS_TAG_LSB = READ_STATUS_ERROR_LSB + 4 WR_STS_TAG_LSB = WR_STS_LEN_LSB + LEN_WIDTH
WR_STS_ID_LSB = WR_STS_TAG_LSB + TAG_WIDTH
# Write status tdata is {len, tag, error}. WR_STS_DEST_LSB = WR_STS_ID_LSB + AXIS_ID_WIDTH
WRITE_STATUS_ERROR_LSB = 0 WR_STS_USER_LSB = WR_STS_DEST_LSB + AXIS_DEST_WIDTH
WRITE_STATUS_TAG_LSB = WRITE_STATUS_ERROR_LSB + 4 WR_STS_ERROR_LSB = WR_STS_USER_LSB + AXIS_USER_WIDTH
WRITE_STATUS_LEN_LSB = WRITE_STATUS_TAG_LSB + TAG_WIDTH
def mask(width): def mask(width):
@ -59,60 +68,59 @@ def get(value, lsb, width):
return (int(value) >> lsb) & mask(width) return (int(value) >> lsb) & mask(width)
def pack_read_desc(*, addr, length, tag, axis_id=0, dest=0, user=0): def pack_desc_cmd(
*,
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, DESC_TAG_LSB, TAG_WIDTH, tag) value = put(value, RD_ADDR_LSB, AXI_ADDR_WIDTH, read_addr)
value = put(value, DESC_LEN_LSB, LEN_WIDTH, length) value = put(value, RD_LEN_LSB, LEN_WIDTH, read_len)
value = put(value, DESC_ADDR_LSB, AXI_ADDR_WIDTH, addr) value = put(value, RD_TAG_LSB, TAG_WIDTH, read_tag)
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)
return AxiStreamFrame( value = put(value, WR_ADDR_LSB, AXI_ADDR_WIDTH, write_addr)
value.to_bytes(READ_DESC_BYTES, byteorder="little"), value = put(value, WR_LEN_LSB, LEN_WIDTH, write_len)
tid=axis_id, value = put(value, WR_TAG_LSB, TAG_WIDTH, write_tag)
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_sideband(frame, name): def frame_tuser(frame):
value = getattr(frame, name)
try: try:
return int(value) return int(frame.tuser)
except TypeError: except TypeError:
return int(value[0]) if value else 0 return int(frame.tuser[0]) if frame.tuser else 0
def unpack_read_status(frame): def unpack_status(frame):
value = frame_to_int(frame) value = frame_to_int(frame)
return { tuser = frame_tuser(frame)
"tag": get(value, READ_STATUS_TAG_LSB, TAG_WIDTH),
"error": get(value, READ_STATUS_ERROR_LSB, 4),
}
def unpack_write_status(frame):
value = frame_to_int(frame)
return { return {
"len": get(value, WRITE_STATUS_LEN_LSB, LEN_WIDTH), "read_valid": bool(tuser & 0x1),
"tag": get(value, WRITE_STATUS_TAG_LSB, TAG_WIDTH), "write_valid": bool(tuser & 0x2),
"error": get(value, WRITE_STATUS_ERROR_LSB, 4), "read_tag": get(value, RD_STS_TAG_LSB, TAG_WIDTH),
"id": frame_sideband(frame, "tid"), "read_error": get(value, RD_STS_ERROR_LSB, 4),
"dest": frame_sideband(frame, "tdest"), "write_len": get(value, WR_STS_LEN_LSB, LEN_WIDTH),
"user": frame_sideband(frame, "tuser"), "write_tag": get(value, WR_STS_TAG_LSB, TAG_WIDTH),
"write_id": get(value, WR_STS_ID_LSB, AXIS_ID_WIDTH),
"write_dest": get(value, WR_STS_DEST_LSB, AXIS_DEST_WIDTH),
"write_user": get(value, WR_STS_USER_LSB, AXIS_USER_WIDTH),
"write_error": get(value, WR_STS_ERROR_LSB, 4),
} }
@ -124,45 +132,24 @@ class TB:
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
self.read_desc_source = AxiStreamSource( self.desc_cmd_source = AxiStreamSource(
AxiStreamBus.from_prefix(dut, "s_axis_read_desc"), AxiStreamBus.from_prefix(dut, "s_axis_desc_cmd"), dut.clk, dut.rst
dut.clk,
dut.rst,
) )
self.read_desc_status_sink = AxiStreamSink( self.desc_status_sink = AxiStreamSink(
AxiStreamBus.from_prefix(dut, "m_axis_read_desc_status"), AxiStreamBus.from_prefix(
dut.clk, dut, "m_axis_desc_status"), dut.clk, dut.rst
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"), AxiStreamBus.from_prefix(dut, "m_axis_read_data"), dut.clk, dut.rst
dut.clk,
dut.rst,
) )
self.write_data_source = AxiStreamSource( self.write_data_source = AxiStreamSource(
AxiStreamBus.from_prefix(dut, "s_axis_write_data"), AxiStreamBus.from_prefix(
dut.clk, dut, "s_axis_write_data"), dut.clk, dut.rst
dut.rst,
) )
self.axi_ram = AxiRam( self.axi_ram = AxiRam(AxiBus.from_prefix(
AxiBus.from_prefix(dut, "m_axi"), dut, "m_axi"), dut.clk, dut.rst, size=2**16)
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)
@ -179,11 +166,8 @@ 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_read_desc(self, **kwargs): async def send_desc_cmd(self, payload):
await self.read_desc_source.send(pack_read_desc(**kwargs)) await self.desc_cmd_source.send(AxiStreamFrame(payload))
async def send_write_desc(self, **kwargs):
await self.write_desc_source.send(pack_write_desc(**kwargs))
@cocotb.test() @cocotb.test()
@ -200,26 +184,28 @@ 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))
desc_task = cocotb.start_soon( cmd = pack_desc_cmd(write_addr=addr, write_len=len(data), write_tag=tag)
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 desc_task await cmd_task
await data_task await data_task
status = unpack_write_status(await tb.write_desc_status_sink.recv()) status_frame = await tb.desc_status_sink.recv()
status = unpack_status(status_frame)
assert status["tag"] == tag assert not status["read_valid"]
assert status["len"] == len(data) assert status["write_valid"]
assert status["id"] == tag assert status["write_tag"] == tag
assert status["error"] == 0 assert status["write_len"] == len(data)
assert status["write_id"] == tag
assert status["write_error"] == 0
assert tb.axi_ram.read(addr - 8, len(data) + 16) == ( assert tb.axi_ram.read(addr - 8, len(data) +
b"\xaa" * 8 + data + b"\xaa" * 8 16) == b"\xaa" * 8 + data + b"\xaa" * 8
)
@cocotb.test() @cocotb.test()
@ -236,26 +222,32 @@ async def test_axis_compat_read_path(dut):
tb.axi_ram.write(addr, data) tb.axi_ram.write(addr, data)
await tb.send_read_desc( cmd = pack_desc_cmd(
addr=addr, read_addr=addr,
length=len(data), read_len=len(data),
tag=tag, read_tag=tag,
axis_id=tag, read_id=tag,
dest=0, read_dest=0,
user=0, read_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 frame_sideband(data_frame, "tid") == tag assert int(data_frame.tid) == tag
status = unpack_read_status(await tb.read_desc_status_sink.recv()) status_frame = await tb.desc_status_sink.recv()
assert status["tag"] == tag status = unpack_status(status_frame)
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_independent_desc_ports(dut): async def test_axis_compat_read_and_write_same_command(dut):
tb = TB(dut) tb = TB(dut)
await tb.reset() await tb.reset()
@ -272,46 +264,51 @@ async def test_axis_compat_read_and_write_independent_desc_ports(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))
read_desc_task = cocotb.start_soon( cmd = pack_desc_cmd(
tb.send_read_desc( read_addr=read_addr,
addr=read_addr, read_len=len(read_data),
length=len(read_data), read_tag=read_tag,
tag=read_tag, read_id=read_tag,
axis_id=read_tag, write_addr=write_addr,
dest=0, write_len=len(write_data),
user=0, write_tag=write_tag,
)
) )
write_desc_task = cocotb.start_soon(
tb.send_write_desc( cmd_task = cocotb.start_soon(tb.send_desc_cmd(cmd))
addr=write_addr, data_task = cocotb.start_soon(
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 read_desc_task await cmd_task
await write_desc_task await data_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 frame_sideband(data_frame, "tid") == read_tag assert int(data_frame.tid) == read_tag
read_status = unpack_read_status(await tb.read_desc_status_sink.recv()) # status might be in 2 beats, depending on timings
write_status = unpack_write_status(await tb.write_desc_status_sink.recv()) seen_read = False
seen_write = False
assert read_status["tag"] == read_tag for _ in range(2):
assert read_status["error"] == 0 status_frame = await tb.desc_status_sink.recv()
status = unpack_status(status_frame)
assert write_status["tag"] == write_tag if status["read_valid"]:
assert write_status["len"] == len(write_data) assert status["read_tag"] == read_tag
assert write_status["id"] == write_tag assert status["read_error"] == 0
assert write_status["error"] == 0 seen_read = True
assert tb.axi_ram.read(write_addr - 8, len(write_data) + 16) == ( if status["write_valid"]:
b"\xaa" * 8 + write_data + b"\xaa" * 8 assert status["write_tag"] == write_tag
) 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