From a2e330d193e49f3b0afad93c24fed05c0a3bada8 Mon Sep 17 00:00:00 2001 From: Phil Date: Tue, 9 Jun 2026 18:06:14 +0300 Subject: [PATCH] rtl: add dma simple wrapper --- axi/rtl/axi_dma_if_wrapper.sv | 384 ++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 axi/rtl/axi_dma_if_wrapper.sv diff --git a/axi/rtl/axi_dma_if_wrapper.sv b/axi/rtl/axi_dma_if_wrapper.sv new file mode 100644 index 0000000..f2d9057 --- /dev/null +++ b/axi/rtl/axi_dma_if_wrapper.sv @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: MIT +// +// Thin SystemVerilog interface wrapper around alexforencich/verilog-axi axi_dma.v. +// +// Policy used here: +// * AXI memory master is exposed as axi4_if.master. +// * AXI-Stream read/write data paths are exposed as axis_if master/slave. +// * Descriptor and status channels remain flat because they are DMA-specific +// command/status streams, not generic AXI-Stream data interfaces. + +`default_nettype none + +module axi_dma_if_wrapper #( + 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 +)( + input logic clk, + input logic rst, + + /* + * AXI read descriptor input, kept flat intentionally. + */ + input logic [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_addr, + input logic [LEN_WIDTH-1:0] s_axis_read_desc_len, + input logic [TAG_WIDTH-1:0] s_axis_read_desc_tag, + input logic [AXIS_ID_WIDTH-1:0] s_axis_read_desc_id, + input logic [AXIS_DEST_WIDTH-1:0] s_axis_read_desc_dest, + input logic [AXIS_USER_WIDTH-1:0] s_axis_read_desc_user, + input logic s_axis_read_desc_valid, + output logic s_axis_read_desc_ready, + + /* + * AXI read descriptor status output, kept flat intentionally. + */ + output logic [TAG_WIDTH-1:0] m_axis_read_desc_status_tag, + output logic [3:0] m_axis_read_desc_status_error, + output logic m_axis_read_desc_status_valid, + + /* + * AXI stream read data output. + */ + axis_if.master m_axis_read_data, + + /* + * AXI write descriptor input, kept flat intentionally. + */ + input logic [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_addr, + input logic [LEN_WIDTH-1:0] s_axis_write_desc_len, + input logic [TAG_WIDTH-1:0] s_axis_write_desc_tag, + input logic s_axis_write_desc_valid, + output logic s_axis_write_desc_ready, + + /* + * AXI write descriptor status output, kept flat intentionally. + */ + output logic [LEN_WIDTH-1:0] m_axis_write_desc_status_len, + output logic [TAG_WIDTH-1:0] m_axis_write_desc_status_tag, + output logic [AXIS_ID_WIDTH-1:0] m_axis_write_desc_status_id, + output logic [AXIS_DEST_WIDTH-1:0] m_axis_write_desc_status_dest, + output logic [AXIS_USER_WIDTH-1:0] m_axis_write_desc_status_user, + output logic [3:0] m_axis_write_desc_status_error, + output logic m_axis_write_desc_status_valid, + + /* + * 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 +); + + // -------------------------------------------------------------------------- + // Flat wires connected to original alexforencich axi_dma.v + // -------------------------------------------------------------------------- + + logic [AXIS_DATA_WIDTH-1:0] dma_m_axis_read_data_tdata; + logic [AXIS_KEEP_WIDTH-1:0] dma_m_axis_read_data_tkeep; + logic dma_m_axis_read_data_tvalid; + logic dma_m_axis_read_data_tready; + logic dma_m_axis_read_data_tlast; + logic [AXIS_ID_WIDTH-1:0] dma_m_axis_read_data_tid; + logic [AXIS_DEST_WIDTH-1:0] dma_m_axis_read_data_tdest; + logic [AXIS_USER_WIDTH-1:0] dma_m_axis_read_data_tuser; + + logic [AXIS_DATA_WIDTH-1:0] dma_s_axis_write_data_tdata; + logic [AXIS_KEEP_WIDTH-1:0] dma_s_axis_write_data_tkeep; + logic [AXIS_KEEP_WIDTH-1:0] unused_s_axis_write_data_tstrb; + logic dma_s_axis_write_data_tvalid; + logic dma_s_axis_write_data_tready; + logic dma_s_axis_write_data_tlast; + logic [AXIS_ID_WIDTH-1:0] dma_s_axis_write_data_tid; + logic [AXIS_DEST_WIDTH-1:0] dma_s_axis_write_data_tdest; + logic [AXIS_USER_WIDTH-1:0] dma_s_axis_write_data_tuser; + + logic [AXI_ID_WIDTH-1:0] dma_m_axi_awid; + logic [AXI_ADDR_WIDTH-1:0] dma_m_axi_awaddr; + logic [7:0] dma_m_axi_awlen; + logic [2:0] dma_m_axi_awsize; + logic [1:0] dma_m_axi_awburst; + logic dma_m_axi_awlock; + logic [3:0] dma_m_axi_awcache; + logic [2:0] dma_m_axi_awprot; + logic dma_m_axi_awvalid; + logic dma_m_axi_awready; + + logic [AXI_DATA_WIDTH-1:0] dma_m_axi_wdata; + logic [AXI_STRB_WIDTH-1:0] dma_m_axi_wstrb; + logic dma_m_axi_wlast; + logic dma_m_axi_wvalid; + logic dma_m_axi_wready; + + logic [AXI_ID_WIDTH-1:0] dma_m_axi_bid; + logic [1:0] dma_m_axi_bresp; + logic dma_m_axi_bvalid; + logic dma_m_axi_bready; + + logic [AXI_ID_WIDTH-1:0] dma_m_axi_arid; + logic [AXI_ADDR_WIDTH-1:0] dma_m_axi_araddr; + logic [7:0] dma_m_axi_arlen; + logic [2:0] dma_m_axi_arsize; + logic [1:0] dma_m_axi_arburst; + logic dma_m_axi_arlock; + logic [3:0] dma_m_axi_arcache; + logic [2:0] dma_m_axi_arprot; + logic dma_m_axi_arvalid; + logic dma_m_axi_arready; + + logic [AXI_ID_WIDTH-1:0] dma_m_axi_rid; + logic [AXI_DATA_WIDTH-1:0] dma_m_axi_rdata; + logic [1:0] dma_m_axi_rresp; + logic dma_m_axi_rlast; + logic dma_m_axi_rvalid; + logic dma_m_axi_rready; + + logic [AXI_USER_WIDTH-1:0] unused_m_axi_buser; + logic [AXI_USER_WIDTH-1:0] unused_m_axi_ruser; + + // Original DMA: flat ports only. + axi_dma #( + .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_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 ( + .clk (clk), + .rst (rst), + + .s_axis_read_desc_addr (s_axis_read_desc_addr), + .s_axis_read_desc_len (s_axis_read_desc_len), + .s_axis_read_desc_tag (s_axis_read_desc_tag), + .s_axis_read_desc_id (s_axis_read_desc_id), + .s_axis_read_desc_dest (s_axis_read_desc_dest), + .s_axis_read_desc_user (s_axis_read_desc_user), + .s_axis_read_desc_valid (s_axis_read_desc_valid), + .s_axis_read_desc_ready (s_axis_read_desc_ready), + + .m_axis_read_desc_status_tag (m_axis_read_desc_status_tag), + .m_axis_read_desc_status_error (m_axis_read_desc_status_error), + .m_axis_read_desc_status_valid (m_axis_read_desc_status_valid), + + .m_axis_read_data_tdata (dma_m_axis_read_data_tdata), + .m_axis_read_data_tkeep (dma_m_axis_read_data_tkeep), + .m_axis_read_data_tvalid (dma_m_axis_read_data_tvalid), + .m_axis_read_data_tready (dma_m_axis_read_data_tready), + .m_axis_read_data_tlast (dma_m_axis_read_data_tlast), + .m_axis_read_data_tid (dma_m_axis_read_data_tid), + .m_axis_read_data_tdest (dma_m_axis_read_data_tdest), + .m_axis_read_data_tuser (dma_m_axis_read_data_tuser), + + .s_axis_write_desc_addr (s_axis_write_desc_addr), + .s_axis_write_desc_len (s_axis_write_desc_len), + .s_axis_write_desc_tag (s_axis_write_desc_tag), + .s_axis_write_desc_valid (s_axis_write_desc_valid), + .s_axis_write_desc_ready (s_axis_write_desc_ready), + + .m_axis_write_desc_status_len (m_axis_write_desc_status_len), + .m_axis_write_desc_status_tag (m_axis_write_desc_status_tag), + .m_axis_write_desc_status_id (m_axis_write_desc_status_id), + .m_axis_write_desc_status_dest (m_axis_write_desc_status_dest), + .m_axis_write_desc_status_user (m_axis_write_desc_status_user), + .m_axis_write_desc_status_error (m_axis_write_desc_status_error), + .m_axis_write_desc_status_valid (m_axis_write_desc_status_valid), + + .s_axis_write_data_tdata (dma_s_axis_write_data_tdata), + .s_axis_write_data_tkeep (dma_s_axis_write_data_tkeep), + .s_axis_write_data_tvalid (dma_s_axis_write_data_tvalid), + .s_axis_write_data_tready (dma_s_axis_write_data_tready), + .s_axis_write_data_tlast (dma_s_axis_write_data_tlast), + .s_axis_write_data_tid (dma_s_axis_write_data_tid), + .s_axis_write_data_tdest (dma_s_axis_write_data_tdest), + .s_axis_write_data_tuser (dma_s_axis_write_data_tuser), + + .m_axi_awid (dma_m_axi_awid), + .m_axi_awaddr (dma_m_axi_awaddr), + .m_axi_awlen (dma_m_axi_awlen), + .m_axi_awsize (dma_m_axi_awsize), + .m_axi_awburst (dma_m_axi_awburst), + .m_axi_awlock (dma_m_axi_awlock), + .m_axi_awcache (dma_m_axi_awcache), + .m_axi_awprot (dma_m_axi_awprot), + .m_axi_awvalid (dma_m_axi_awvalid), + .m_axi_awready (dma_m_axi_awready), + + .m_axi_wdata (dma_m_axi_wdata), + .m_axi_wstrb (dma_m_axi_wstrb), + .m_axi_wlast (dma_m_axi_wlast), + .m_axi_wvalid (dma_m_axi_wvalid), + .m_axi_wready (dma_m_axi_wready), + + .m_axi_bid (dma_m_axi_bid), + .m_axi_bresp (dma_m_axi_bresp), + .m_axi_bvalid (dma_m_axi_bvalid), + .m_axi_bready (dma_m_axi_bready), + + .m_axi_arid (dma_m_axi_arid), + .m_axi_araddr (dma_m_axi_araddr), + .m_axi_arlen (dma_m_axi_arlen), + .m_axi_arsize (dma_m_axi_arsize), + .m_axi_arburst (dma_m_axi_arburst), + .m_axi_arlock (dma_m_axi_arlock), + .m_axi_arcache (dma_m_axi_arcache), + .m_axi_arprot (dma_m_axi_arprot), + .m_axi_arvalid (dma_m_axi_arvalid), + .m_axi_arready (dma_m_axi_arready), + + .m_axi_rid (dma_m_axi_rid), + .m_axi_rdata (dma_m_axi_rdata), + .m_axi_rresp (dma_m_axi_rresp), + .m_axi_rlast (dma_m_axi_rlast), + .m_axi_rvalid (dma_m_axi_rvalid), + .m_axi_rready (dma_m_axi_rready), + + .read_enable (read_enable), + .write_enable (write_enable), + .write_abort (write_abort) + ); + + // DMA read data flat output -> local axis_if.master + 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_m_axis_read_data_flat_to_if ( + .s_axis_tdata (dma_m_axis_read_data_tdata), + .s_axis_tkeep (dma_m_axis_read_data_tkeep), + .s_axis_tstrb (dma_m_axis_read_data_tkeep), // axi_dma has no tstrb; mirror tkeep + .s_axis_tlast (dma_m_axis_read_data_tlast), + .s_axis_tid (dma_m_axis_read_data_tid), + .s_axis_tdest (dma_m_axis_read_data_tdest), + .s_axis_tuser (dma_m_axis_read_data_tuser), + .s_axis_tvalid (dma_m_axis_read_data_tvalid), + .s_axis_tready (dma_m_axis_read_data_tready), + .m_axis (m_axis_read_data) + ); + + // local axis_if.slave -> DMA write data flat input + 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_s_axis_write_data_if_to_flat ( + .s_axis (s_axis_write_data), + .m_axis_tdata (dma_s_axis_write_data_tdata), + .m_axis_tkeep (dma_s_axis_write_data_tkeep), + .m_axis_tstrb (unused_s_axis_write_data_tstrb), + .m_axis_tlast (dma_s_axis_write_data_tlast), + .m_axis_tid (dma_s_axis_write_data_tid), + .m_axis_tdest (dma_s_axis_write_data_tdest), + .m_axis_tuser (dma_s_axis_write_data_tuser), + .m_axis_tvalid(dma_s_axis_write_data_tvalid), + .m_axis_tready(dma_s_axis_write_data_tready) + ); + + // DMA AXI master flat output -> local axi4_if.master + axi4_flat_to_if #( + .ADDR_W (AXI_ADDR_WIDTH), + .DATA_W (AXI_DATA_WIDTH), + .ID_W (AXI_ID_WIDTH), + .USER_W (AXI_USER_WIDTH) + ) u_m_axi_flat_to_if ( + .s_axi_awid (dma_m_axi_awid), + .s_axi_awaddr (dma_m_axi_awaddr), + .s_axi_awlen (dma_m_axi_awlen), + .s_axi_awsize (dma_m_axi_awsize), + .s_axi_awburst (dma_m_axi_awburst), + .s_axi_awlock (dma_m_axi_awlock), + .s_axi_awcache (dma_m_axi_awcache), + .s_axi_awprot (dma_m_axi_awprot), + .s_axi_awqos (4'd0), + .s_axi_awregion (4'd0), + .s_axi_awuser ({AXI_USER_WIDTH{1'b0}}), + .s_axi_awvalid (dma_m_axi_awvalid), + .s_axi_awready (dma_m_axi_awready), + + .s_axi_wdata (dma_m_axi_wdata), + .s_axi_wstrb (dma_m_axi_wstrb), + .s_axi_wlast (dma_m_axi_wlast), + .s_axi_wuser ({AXI_USER_WIDTH{1'b0}}), + .s_axi_wvalid (dma_m_axi_wvalid), + .s_axi_wready (dma_m_axi_wready), + + .s_axi_bid (dma_m_axi_bid), + .s_axi_bresp (dma_m_axi_bresp), + .s_axi_buser (unused_m_axi_buser), + .s_axi_bvalid (dma_m_axi_bvalid), + .s_axi_bready (dma_m_axi_bready), + + .s_axi_arid (dma_m_axi_arid), + .s_axi_araddr (dma_m_axi_araddr), + .s_axi_arlen (dma_m_axi_arlen), + .s_axi_arsize (dma_m_axi_arsize), + .s_axi_arburst (dma_m_axi_arburst), + .s_axi_arlock (dma_m_axi_arlock), + .s_axi_arcache (dma_m_axi_arcache), + .s_axi_arprot (dma_m_axi_arprot), + .s_axi_arqos (4'd0), + .s_axi_arregion (4'd0), + .s_axi_aruser ({AXI_USER_WIDTH{1'b0}}), + .s_axi_arvalid (dma_m_axi_arvalid), + .s_axi_arready (dma_m_axi_arready), + + .s_axi_rid (dma_m_axi_rid), + .s_axi_rdata (dma_m_axi_rdata), + .s_axi_rresp (dma_m_axi_rresp), + .s_axi_rlast (dma_m_axi_rlast), + .s_axi_ruser (unused_m_axi_ruser), + .s_axi_rvalid (dma_m_axi_rvalid), + .s_axi_rready (dma_m_axi_rready), + + .m_axi (m_axi) + ); + +endmodule : axi_dma_if_wrapper + +`default_nettype wire