aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-01-23 16:10:22 -0800
committerMartin Braun <martin.braun@ettus.com>2020-01-28 09:35:36 -0800
commitbafa9d95453387814ef25e6b6256ba8db2df612f (patch)
tree39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v
parent3075b981503002df3115d5f1d0b97d2619ba30f2 (diff)
downloaduhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce the size of the repository. However, over the last half-decade, the split between the repositories has proven more burdensome than it has been helpful. By merging the FPGA code back, it will be possible to create atomic commits that touch both FPGA and UHD codebases. Continuous integration testing is also simplified by merging the repositories, because it was previously difficult to automatically derive the correct UHD branch when testing a feature branch on the FPGA repository. This commit also updates the license files and paths therein. We are therefore merging the repositories again. Future development for FPGA code will happen in the same repository as the UHD host code and MPM code. == Original Codebase and Rebasing == The original FPGA repository will be hosted for the foreseeable future at its original local location: https://github.com/EttusResearch/fpga/ It can be used for bisecting, reference, and a more detailed history. The final commit from said repository to be merged here is 05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as v4.0.0.0-pre-uhd-merge. If you have changes in the FPGA repository that you want to rebase onto the UHD repository, simply run the following commands: - Create a directory to store patches (this should be an empty directory): mkdir ~/patches - Now make sure that your FPGA codebase is based on the same state as the code that was merged: cd src/fpga # Or wherever your FPGA code is stored git rebase v4.0.0.0-pre-uhd-merge Note: The rebase command may look slightly different depending on what exactly you're trying to rebase. - Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge: git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches Note: Make sure that only patches are stored in your output directory. It should otherwise be empty. Make sure that you picked the correct range of commits, and only commits you wanted to rebase were exported as patch files. - Go to the UHD repository and apply the patches: cd src/uhd # Or wherever your UHD repository is stored git am --directory fpga ~/patches/* rm -rf ~/patches # This is for cleanup == Contributors == The following people have contributed mainly to these files (this list is not complete): Co-authored-by: Alex Williams <alex.williams@ni.com> Co-authored-by: Andrej Rode <andrej.rode@ettus.com> Co-authored-by: Ashish Chaudhari <ashish@ettus.com> Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Derek Kozel <derek.kozel@ettus.com> Co-authored-by: EJ Kreinar <ej@he360.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Ian Buckley <ian.buckley@gmail.com> Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Jon Kiser <jon.kiser@ni.com> Co-authored-by: Josh Blum <josh@joshknows.com> Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Matt Ettus <matt@ettus.com> Co-authored-by: Michael West <michael.west@ettus.com> Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com> Co-authored-by: Nick Foster <nick@ettus.com> Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Paul David <paul.david@ettus.com> Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com> Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com> Co-authored-by: Sylvain Munaut <tnt@246tNt.com> Co-authored-by: Trung Tran <trung.tran@ettus.com> Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com> Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v')
-rw-r--r--fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v1115
1 files changed, 1115 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v b/fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v
new file mode 100644
index 000000000..706d2cedc
--- /dev/null
+++ b/fpga/usrp3/lib/vivado_ipi/axi_dmac/request_arb.v
@@ -0,0 +1,1115 @@
+// ***************************************************************************
+// ***************************************************************************
+// Copyright 2013(c) Analog Devices, Inc.
+// Author: Lars-Peter Clausen <lars@metafoo.de>
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+// - Neither the name of Analog Devices, Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+// - The use of this software may or may not infringe the patent rights
+// of one or more patent holders. This license does not release you
+// from the requirement that you obtain separate licenses from these
+// patent holders to use this software.
+// - Use of the software either in source or binary form, must be run
+// on or directly connected to an Analog Devices Inc. component.
+//
+// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED.
+//
+// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
+// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// ***************************************************************************
+// ***************************************************************************
+
+module dmac_request_arb (
+ input req_aclk,
+ input req_aresetn,
+
+ input req_valid,
+ output req_ready,
+ input [31:BYTES_PER_BEAT_WIDTH_DEST] req_dest_address,
+ input [31:BYTES_PER_BEAT_WIDTH_SRC] req_src_address,
+ input [DMA_LENGTH_WIDTH-1:0] req_length,
+ input req_xlast,
+ input req_sync_transfer_start,
+
+ output reg eot,
+
+ input enable,
+ input pause,
+
+ // Master AXI interface
+ input m_dest_axi_aclk,
+ input m_dest_axi_aresetn,
+ input m_src_axi_aclk,
+ input m_src_axi_aresetn,
+
+ // Write address
+ output [31:0] m_axi_awaddr,
+ output [ 7:0] m_axi_awlen,
+ output [ 2:0] m_axi_awsize,
+ output [ 1:0] m_axi_awburst,
+ output [ 2:0] m_axi_awprot,
+ output [ 3:0] m_axi_awcache,
+ output m_axi_awvalid,
+ input m_axi_awready,
+
+ // Write data
+ output [DMA_DATA_WIDTH_DEST-1:0] m_axi_wdata,
+ output [(DMA_DATA_WIDTH_DEST/8)-1:0] m_axi_wstrb,
+ input m_axi_wready,
+ output m_axi_wvalid,
+ output m_axi_wlast,
+
+ // Write response
+ input m_axi_bvalid,
+ input [ 1:0] m_axi_bresp,
+ output m_axi_bready,
+
+ // Read address
+ input m_axi_arready,
+ output m_axi_arvalid,
+ output [31:0] m_axi_araddr,
+ output [ 7:0] m_axi_arlen,
+ output [ 2:0] m_axi_arsize,
+ output [ 1:0] m_axi_arburst,
+ output [ 2:0] m_axi_arprot,
+ output [ 3:0] m_axi_arcache,
+
+ // Read data and response
+ input [DMA_DATA_WIDTH_SRC-1:0] m_axi_rdata,
+ output m_axi_rready,
+ input m_axi_rvalid,
+ input [ 1:0] m_axi_rresp,
+
+ // Slave streaming AXI interface
+ input s_axis_aclk,
+ output s_axis_ready,
+ input s_axis_valid,
+ input [DMA_DATA_WIDTH_SRC-1:0] s_axis_data,
+ input [0:0] s_axis_user,
+ output s_axis_xfer_req,
+
+ // Master streaming AXI interface
+ input m_axis_aclk,
+ input m_axis_ready,
+ output m_axis_valid,
+ output [DMA_DATA_WIDTH_DEST-1:0] m_axis_data,
+ output m_axis_last,
+ output m_axis_xfer_req,
+
+ // Input FIFO interface
+ input fifo_wr_clk,
+ input fifo_wr_en,
+ input [DMA_DATA_WIDTH_SRC-1:0] fifo_wr_din,
+ output fifo_wr_overflow,
+ input fifo_wr_sync,
+ output fifo_wr_xfer_req,
+
+ // Input FIFO interface
+ input fifo_rd_clk,
+ input fifo_rd_en,
+ output fifo_rd_valid,
+ output [DMA_DATA_WIDTH_DEST-1:0] fifo_rd_dout,
+ output fifo_rd_underflow,
+ output fifo_rd_xfer_req,
+
+ output [ID_WIDTH-1:0] dbg_dest_request_id,
+ output [ID_WIDTH-1:0] dbg_dest_address_id,
+ output [ID_WIDTH-1:0] dbg_dest_data_id,
+ output [ID_WIDTH-1:0] dbg_dest_response_id,
+ output [ID_WIDTH-1:0] dbg_src_request_id,
+ output [ID_WIDTH-1:0] dbg_src_address_id,
+ output [ID_WIDTH-1:0] dbg_src_data_id,
+ output [ID_WIDTH-1:0] dbg_src_response_id,
+ output [7:0] dbg_status
+);
+
+parameter DMA_DATA_WIDTH_SRC = 64;
+parameter DMA_DATA_WIDTH_DEST = 64;
+parameter DMA_LENGTH_WIDTH = 24;
+
+parameter BYTES_PER_BEAT_WIDTH_DEST = $clog2(DMA_DATA_WIDTH_DEST/8);
+parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DMA_DATA_WIDTH_SRC/8);
+
+parameter DMA_TYPE_DEST = DMA_TYPE_MM_AXI;
+parameter DMA_TYPE_SRC = DMA_TYPE_FIFO;
+
+parameter ASYNC_CLK_REQ_SRC = 1;
+parameter ASYNC_CLK_SRC_DEST = 1;
+parameter ASYNC_CLK_DEST_REQ = 1;
+
+parameter AXI_SLICE_DEST = 0;
+parameter AXI_SLICE_SRC = 0;
+
+parameter MAX_BYTES_PER_BURST = 128;
+parameter FIFO_SIZE = 4;
+
+parameter ID_WIDTH = $clog2(FIFO_SIZE*2);
+
+localparam DMA_TYPE_MM_AXI = 0;
+localparam DMA_TYPE_STREAM_AXI = 1;
+localparam DMA_TYPE_FIFO = 2;
+
+localparam DMA_ADDRESS_WIDTH_DEST = 32 - BYTES_PER_BEAT_WIDTH_DEST;
+localparam DMA_ADDRESS_WIDTH_SRC = 32 - BYTES_PER_BEAT_WIDTH_SRC;
+
+localparam DMA_DATA_WIDTH = DMA_DATA_WIDTH_SRC < DMA_DATA_WIDTH_DEST ?
+ DMA_DATA_WIDTH_DEST : DMA_DATA_WIDTH_SRC;
+
+
+
+// Bytes per burst is the same for both dest and src, but bytes per beat may
+// differ, so beats per burst may also differ
+
+parameter BYTES_PER_BURST_WIDTH = $clog2(MAX_BYTES_PER_BURST);
+localparam BEATS_PER_BURST_WIDTH_SRC = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH_SRC;
+localparam BEATS_PER_BURST_WIDTH_DEST = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH_DEST;
+
+localparam BURSTS_PER_TRANSFER_WIDTH = DMA_LENGTH_WIDTH - BYTES_PER_BURST_WIDTH;
+
+reg [0:2**ID_WIDTH-1] eot_mem;
+wire request_eot;
+
+wire [ID_WIDTH-1:0] request_id;
+wire [ID_WIDTH-1:0] response_id;
+
+wire enabled_src;
+wire enabled_dest;
+wire sync_id;
+wire sync_id_ret_dest;
+wire sync_id_ret_src;
+
+wire dest_enable;
+wire dest_enabled;
+wire dest_pause;
+wire dest_sync_id;
+wire dest_sync_id_ret;
+wire src_enable;
+wire src_enabled;
+wire src_pause;
+wire src_sync_id;
+wire src_sync_id_ret;
+
+wire req_dest_valid;
+wire req_dest_ready;
+wire req_dest_empty;
+wire req_src_valid;
+wire req_src_ready;
+wire req_src_empty;
+
+wire dest_clk;
+wire dest_resetn;
+wire dest_req_valid;
+wire dest_req_ready;
+wire [DMA_ADDRESS_WIDTH_DEST-1:0] dest_req_address;
+wire [BEATS_PER_BURST_WIDTH_DEST-1:0] dest_req_last_burst_length;
+wire [BYTES_PER_BEAT_WIDTH_DEST-1:0] dest_req_last_beat_bytes;
+wire dest_req_xlast;
+
+wire dest_response_valid;
+wire dest_response_ready;
+wire dest_response_empty;
+wire [1:0] dest_response_resp;
+wire dest_response_resp_eot;
+
+wire [ID_WIDTH-1:0] dest_request_id;
+wire [ID_WIDTH-1:0] dest_response_id;
+
+wire dest_valid;
+wire dest_ready;
+wire [DMA_DATA_WIDTH_DEST-1:0] dest_data;
+wire dest_fifo_repacked_valid;
+wire dest_fifo_repacked_ready;
+wire [DMA_DATA_WIDTH_DEST-1:0] dest_fifo_repacked_data;
+wire dest_fifo_valid;
+wire dest_fifo_ready;
+wire [DMA_DATA_WIDTH-1:0] dest_fifo_data;
+
+wire src_clk;
+wire src_resetn;
+wire src_req_valid;
+wire src_req_ready;
+wire [DMA_ADDRESS_WIDTH_SRC-1:0] src_req_address;
+wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_req_last_burst_length;
+wire src_req_sync_transfer_start;
+
+wire src_response_valid;
+wire src_response_ready;
+wire src_response_empty;
+wire [1:0] src_response_resp;
+
+wire [ID_WIDTH-1:0] src_request_id;
+wire [ID_WIDTH-1:0] src_response_id;
+
+wire src_valid;
+wire src_ready;
+wire [DMA_DATA_WIDTH_SRC-1:0] src_data;
+wire src_fifo_valid;
+wire src_fifo_ready;
+wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data;
+wire src_fifo_repacked_valid;
+wire src_fifo_repacked_ready;
+wire [DMA_DATA_WIDTH-1:0] src_fifo_repacked_data;
+wire src_fifo_empty;
+
+wire fifo_empty;
+
+wire response_dest_valid;
+wire response_dest_ready = 1'b1;
+wire [1:0] response_dest_resp;
+wire response_dest_resp_eot;
+
+/* Unused for now
+wire response_src_valid;
+wire response_src_ready = 1'b1;
+wire [1:0] response_src_resp;
+*/
+
+assign dbg_dest_request_id = dest_request_id;
+assign dbg_dest_response_id = dest_response_id;
+assign dbg_src_request_id = src_request_id;
+assign dbg_src_response_id = src_response_id;
+
+assign sync_id = ~enabled_dest && ~enabled_src && request_id != response_id;
+
+reg enabled;
+reg do_enable;
+
+// Enable src and dest if we are in sync
+always @(posedge req_aclk)
+begin
+ if (req_aresetn == 1'b0) begin
+ do_enable <= 1'b0;
+ end else begin
+ if (enable) begin
+ // First make sure we are fully disabled
+ if (~sync_id_ret_dest && ~sync_id_ret_src &&
+ response_id == request_id && ~enabled_dest && ~enabled_src &&
+ req_dest_empty && req_src_empty && fifo_empty)
+ do_enable <= 1'b1;
+ end else begin
+ do_enable <= 1'b0;
+ end
+ end
+end
+
+// Flag enabled once both src and dest are enabled
+always @(posedge req_aclk)
+begin
+ if (req_aresetn == 1'b0) begin
+ enabled <= 1'b0;
+ end else begin
+ if (do_enable == 1'b0)
+ enabled <= 1'b0;
+ else if (enabled_dest && enabled_src)
+ enabled <= 1'b1;
+ end
+end
+
+assign dbg_status = {do_enable, enabled, enabled_dest, enabled_src, fifo_empty,
+ sync_id, sync_id_ret_dest, sync_id_ret_src};
+
+always @(posedge req_aclk)
+begin
+ eot_mem[request_id] <= request_eot;
+end
+
+always @(posedge req_aclk)
+begin
+ if (req_aresetn == 1'b0) begin
+ eot <= 1'b0;
+ end else begin
+ eot <= response_dest_valid & response_dest_ready & response_dest_resp_eot;
+ end
+end
+
+generate if (ASYNC_CLK_REQ_SRC) begin
+
+wire src_async_resetn_source;
+
+if (DMA_TYPE_SRC == DMA_TYPE_MM_AXI) begin
+assign src_async_resetn_source = m_src_axi_aresetn;
+end else begin
+assign src_async_resetn_source = req_aresetn;
+end
+
+reg [2:0] src_reset_shift = 3'b111;
+assign src_resetn = ~src_reset_shift[2];
+
+always @(negedge src_async_resetn_source or posedge src_clk) begin
+ if (src_async_resetn_source == 1'b0)
+ src_reset_shift <= 3'b111;
+ else
+ src_reset_shift <= {src_reset_shift[1:0], 1'b0};
+end
+
+end else begin
+assign src_resetn = req_aresetn;
+end endgenerate
+
+generate if (ASYNC_CLK_DEST_REQ) begin
+wire dest_async_resetn_source;
+
+if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin
+assign dest_async_resetn_source = m_dest_axi_aresetn;
+end else begin
+assign dest_async_resetn_source = req_aresetn;
+end
+
+reg [2:0] dest_reset_shift = 3'b111;
+assign dest_resetn = ~dest_reset_shift[2];
+
+always @(negedge dest_async_resetn_source or posedge dest_clk) begin
+ if (dest_async_resetn_source == 1'b0)
+ dest_reset_shift <= 3'b111;
+ else
+ dest_reset_shift <= {dest_reset_shift[1:0], 1'b0};
+end
+
+end else begin
+assign dest_resetn = req_aresetn;
+end endgenerate
+
+generate if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin
+
+assign dest_clk = m_dest_axi_aclk;
+
+wire [ID_WIDTH-1:0] dest_data_id;
+wire [ID_WIDTH-1:0] dest_address_id;
+wire dest_address_eot = eot_mem[dest_address_id];
+wire dest_data_eot = eot_mem[dest_data_id];
+wire dest_response_eot = eot_mem[dest_response_id];
+
+assign dbg_dest_address_id = dest_address_id;
+assign dbg_dest_data_id = dest_data_id;
+
+dmac_dest_mm_axi #(
+ .ID_WIDTH(ID_WIDTH),
+ .DMA_DATA_WIDTH(DMA_DATA_WIDTH_DEST),
+ .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST),
+ .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH_DEST)
+) i_dest_dma_mm (
+ .m_axi_aclk(m_dest_axi_aclk),
+ .m_axi_aresetn(dest_resetn),
+
+ .enable(dest_enable),
+ .enabled(dest_enabled),
+ .pause(dest_pause),
+
+ .req_valid(dest_req_valid),
+ .req_ready(dest_req_ready),
+ .req_address(dest_req_address),
+ .req_last_burst_length(dest_req_last_burst_length),
+ .req_last_beat_bytes(dest_req_last_beat_bytes),
+
+ .response_valid(dest_response_valid),
+ .response_ready(dest_response_ready),
+ .response_resp(dest_response_resp),
+ .response_resp_eot(dest_response_resp_eot),
+
+ .request_id(dest_request_id),
+ .response_id(dest_response_id),
+ .sync_id(dest_sync_id),
+ .sync_id_ret(dest_sync_id_ret),
+
+ .data_id(dest_data_id),
+ .address_id(dest_address_id),
+
+ .address_eot(dest_address_eot),
+ .data_eot(dest_data_eot),
+ .response_eot(dest_response_eot),
+
+ .fifo_valid(dest_valid),
+ .fifo_ready(dest_ready),
+ .fifo_data(dest_data),
+
+ .m_axi_awready(m_axi_awready),
+ .m_axi_awvalid(m_axi_awvalid),
+ .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_awprot(m_axi_awprot),
+ .m_axi_awcache(m_axi_awcache),
+ .m_axi_wready(m_axi_wready),
+ .m_axi_wvalid(m_axi_wvalid),
+ .m_axi_wdata(m_axi_wdata),
+ .m_axi_wstrb(m_axi_wstrb),
+ .m_axi_wlast(m_axi_wlast),
+
+ .m_axi_bvalid(m_axi_bvalid),
+ .m_axi_bresp(m_axi_bresp),
+ .m_axi_bready(m_axi_bready)
+);
+
+end else begin
+
+assign m_axi_awvalid = 1'b0;
+assign m_axi_awaddr = 'h00;
+assign m_axi_awlen = 'h00;
+assign m_axi_awsize = 'h00;
+assign m_axi_awburst = 'h00;
+assign m_axi_awprot = 'h00;
+assign m_axi_awcache = 'h00;
+
+assign m_axi_wvalid = 1'b0;
+assign m_axi_wdata = 'h00;
+assign m_axi_wstrb = 'h00;
+assign m_axi_wlast = 1'b0;
+
+assign m_axi_bready = 1'b0;
+
+end
+
+if (DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin
+
+assign dest_clk = m_axis_aclk;
+
+wire [ID_WIDTH-1:0] data_id;
+
+wire data_eot = eot_mem[data_id];
+wire response_eot = eot_mem[dest_response_id];
+
+assign dbg_dest_address_id = 'h00;
+assign dbg_dest_data_id = data_id;
+
+dmac_dest_axi_stream #(
+ .ID_WIDTH(ID_WIDTH),
+ .S_AXIS_DATA_WIDTH(DMA_DATA_WIDTH_DEST),
+ .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST)
+) i_dest_dma_stream (
+ .s_axis_aclk(m_axis_aclk),
+ .s_axis_aresetn(dest_resetn),
+
+ .enable(dest_enable),
+ .enabled(dest_enabled),
+
+ .req_valid(dest_req_valid),
+ .req_ready(dest_req_ready),
+ .req_last_burst_length(dest_req_last_burst_length),
+ .req_xlast(dest_req_xlast),
+
+ .response_valid(dest_response_valid),
+ .response_ready(dest_response_ready),
+ .response_resp(dest_response_resp),
+ .response_resp_eot(dest_response_resp_eot),
+
+ .request_id(dest_request_id),
+ .response_id(dest_response_id),
+ .data_id(data_id),
+ .sync_id(dest_sync_id),
+ .sync_id_ret(dest_sync_id_ret),
+ .xfer_req(m_axis_xfer_req),
+
+ .data_eot(data_eot),
+ .response_eot(response_eot),
+
+ .fifo_valid(dest_valid),
+ .fifo_ready(dest_ready),
+ .fifo_data(dest_data),
+
+ .m_axis_valid(m_axis_valid),
+ .m_axis_ready(m_axis_ready),
+ .m_axis_data(m_axis_data),
+ .m_axis_last(m_axis_last)
+);
+
+end else begin
+
+assign m_axis_valid = 1'b0;
+assign m_axis_last = 1'b0;
+assign m_axis_xfer_req = 1'b0;
+assign m_axis_data = 'h00;
+
+end
+
+if (DMA_TYPE_DEST == DMA_TYPE_FIFO) begin
+
+assign dest_clk = fifo_rd_clk;
+
+wire [ID_WIDTH-1:0] data_id;
+
+wire data_eot = eot_mem[data_id];
+wire response_eot = eot_mem[dest_response_id];
+
+assign dbg_dest_address_id = 'h00;
+assign dbg_dest_data_id = data_id;
+
+dmac_dest_fifo_inf #(
+ .ID_WIDTH(ID_WIDTH),
+ .DATA_WIDTH(DMA_DATA_WIDTH_DEST),
+ .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST)
+) i_dest_dma_fifo (
+ .clk(fifo_rd_clk),
+ .resetn(dest_resetn),
+
+ .enable(dest_enable),
+ .enabled(dest_enabled),
+
+ .req_valid(dest_req_valid),
+ .req_ready(dest_req_ready),
+ .req_last_burst_length(dest_req_last_burst_length),
+
+ .response_valid(dest_response_valid),
+ .response_ready(dest_response_ready),
+ .response_resp(dest_response_resp),
+ .response_resp_eot(dest_response_resp_eot),
+
+ .request_id(dest_request_id),
+ .response_id(dest_response_id),
+ .data_id(data_id),
+ .sync_id(dest_sync_id),
+ .sync_id_ret(dest_sync_id_ret),
+
+ .data_eot(data_eot),
+ .response_eot(response_eot),
+
+ .fifo_valid(dest_valid),
+ .fifo_ready(dest_ready),
+ .fifo_data(dest_data),
+
+ .en(fifo_rd_en),
+ .valid(fifo_rd_valid),
+ .dout(fifo_rd_dout),
+ .underflow(fifo_rd_underflow),
+ .xfer_req(fifo_rd_xfer_req)
+);
+
+end else begin
+
+assign fifo_rd_valid = 1'b0;
+assign fifo_rd_dout = 'h0;
+assign fifo_rd_underflow = 1'b0;
+assign fifo_rd_xfer_req = 1'b0;
+
+end endgenerate
+
+generate if (DMA_TYPE_SRC == DMA_TYPE_MM_AXI) begin
+
+assign src_clk = m_src_axi_aclk;
+
+wire [ID_WIDTH-1:0] src_data_id;
+wire [ID_WIDTH-1:0] src_address_id;
+wire src_address_eot = eot_mem[src_address_id];
+wire src_data_eot = eot_mem[src_data_id];
+
+assign dbg_src_address_id = src_address_id;
+assign dbg_src_data_id = src_data_id;
+
+dmac_src_mm_axi #(
+ .ID_WIDTH(ID_WIDTH),
+ .DMA_DATA_WIDTH(DMA_DATA_WIDTH_SRC),
+ .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_SRC),
+ .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH_SRC)
+) i_src_dma_mm (
+ .m_axi_aclk(m_src_axi_aclk),
+ .m_axi_aresetn(src_resetn),
+
+ .pause(src_pause),
+ .enable(src_enable),
+ .enabled(src_enabled),
+ .sync_id(src_sync_id),
+ .sync_id_ret(src_sync_id_ret),
+
+ .req_valid(src_req_valid),
+ .req_ready(src_req_ready),
+ .req_address(src_req_address),
+ .req_last_burst_length(src_req_last_burst_length),
+
+ .response_valid(src_response_valid),
+ .response_ready(src_response_ready),
+ .response_resp(src_response_resp),
+
+ .request_id(src_request_id),
+ .response_id(src_response_id),
+ .address_id(src_address_id),
+ .data_id(src_data_id),
+
+ .address_eot(src_address_eot),
+ .data_eot(src_data_eot),
+
+ .fifo_valid(src_valid),
+ .fifo_ready(src_ready),
+ .fifo_data(src_data),
+
+ .m_axi_arready(m_axi_arready),
+ .m_axi_arvalid(m_axi_arvalid),
+ .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_arprot(m_axi_arprot),
+ .m_axi_arcache(m_axi_arcache),
+
+ .m_axi_rready(m_axi_rready),
+ .m_axi_rvalid(m_axi_rvalid),
+ .m_axi_rdata(m_axi_rdata),
+ .m_axi_rresp(m_axi_rresp)
+);
+
+end else begin
+
+assign m_axi_arvalid = 1'b0;
+assign m_axi_araddr = 'h00;
+assign m_axi_arlen = 'h00;
+assign m_axi_arsize = 'h00;
+assign m_axi_arburst = 'h00;
+assign m_axi_arcache = 'h00;
+assign m_axi_arprot = 'h00;
+assign m_axi_rready = 1'b0;
+
+end
+
+if (DMA_TYPE_SRC == DMA_TYPE_STREAM_AXI) begin
+
+assign src_clk = s_axis_aclk;
+
+wire src_eot = eot_mem[src_response_id];
+
+assign dbg_src_address_id = 'h00;
+assign dbg_src_data_id = 'h00;
+
+/* TODO */
+assign src_response_valid = 1'b0;
+assign src_response_resp = 2'b0;
+
+dmac_src_axi_stream #(
+ .ID_WIDTH(ID_WIDTH),
+ .S_AXIS_DATA_WIDTH(DMA_DATA_WIDTH_SRC),
+ .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_SRC)
+) i_src_dma_stream (
+ .s_axis_aclk(s_axis_aclk),
+ .s_axis_aresetn(src_resetn),
+
+ .enable(src_enable),
+ .enabled(src_enabled),
+ .sync_id(src_sync_id),
+ .sync_id_ret(src_sync_id_ret),
+
+ .req_valid(src_req_valid),
+ .req_ready(src_req_ready),
+ .req_last_burst_length(src_req_last_burst_length),
+ .req_sync_transfer_start(src_req_sync_transfer_start),
+
+ .request_id(src_request_id),
+ .response_id(src_response_id),
+
+ .eot(src_eot),
+
+ .fifo_valid(src_valid),
+ .fifo_ready(src_ready),
+ .fifo_data(src_data),
+
+ .s_axis_valid(s_axis_valid),
+ .s_axis_ready(s_axis_ready),
+ .s_axis_data(s_axis_data),
+ .s_axis_user(s_axis_user),
+ .s_axis_xfer_req(s_axis_xfer_req)
+);
+
+end else begin
+
+assign s_axis_ready = 1'b0;
+assign s_axis_xfer_req = 1'b0;
+
+end
+
+if (DMA_TYPE_SRC == DMA_TYPE_FIFO) begin
+
+assign src_clk = fifo_wr_clk;
+
+wire src_eot = eot_mem[src_response_id];
+
+assign dbg_src_address_id = 'h00;
+assign dbg_src_data_id = 'h00;
+
+/* TODO */
+assign src_response_valid = 1'b0;
+assign src_response_resp = 2'b0;
+
+dmac_src_fifo_inf #(
+ .ID_WIDTH(ID_WIDTH),
+ .DATA_WIDTH(DMA_DATA_WIDTH_SRC),
+ .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_SRC)
+) i_src_dma_fifo (
+ .clk(fifo_wr_clk),
+ .resetn(src_resetn),
+
+ .enable(src_enable),
+ .enabled(src_enabled),
+ .sync_id(src_sync_id),
+ .sync_id_ret(src_sync_id_ret),
+
+ .req_valid(src_req_valid),
+ .req_ready(src_req_ready),
+ .req_last_burst_length(src_req_last_burst_length),
+ .req_sync_transfer_start(src_req_sync_transfer_start),
+
+ .request_id(src_request_id),
+ .response_id(src_response_id),
+
+ .eot(src_eot),
+
+ .fifo_valid(src_valid),
+ .fifo_ready(src_ready),
+ .fifo_data(src_data),
+
+ .en(fifo_wr_en),
+ .din(fifo_wr_din),
+ .overflow(fifo_wr_overflow),
+ .sync(fifo_wr_sync),
+ .xfer_req(fifo_wr_xfer_req)
+);
+
+end else begin
+
+assign fifo_wr_overflow = 1'b0;
+assign fifo_wr_xfer_req = 1'b0;
+
+end endgenerate
+
+sync_bits #(
+ .NUM_OF_BITS(ID_WIDTH),
+ .ASYNC_CLK(ASYNC_CLK_REQ_SRC)
+) i_sync_src_request_id (
+ .out_clk(src_clk),
+ .out_resetn(src_resetn),
+ .in(request_id),
+ .out(src_request_id)
+);
+
+sync_bits #(
+ .NUM_OF_BITS(ID_WIDTH),
+ .ASYNC_CLK(ASYNC_CLK_SRC_DEST)
+) i_sync_dest_request_id (
+ .out_clk(dest_clk),
+ .out_resetn(dest_resetn),
+ .in(src_response_id),
+ .out(dest_request_id)
+);
+
+sync_bits #(
+ .NUM_OF_BITS(ID_WIDTH),
+ .ASYNC_CLK(ASYNC_CLK_DEST_REQ)
+) i_sync_req_response_id (
+ .out_clk(req_aclk),
+ .out_resetn(req_aresetn),
+ .in(dest_response_id),
+ .out(response_id)
+);
+
+axi_register_slice #(
+ .DATA_WIDTH(DMA_DATA_WIDTH_SRC),
+ .FORWARD_REGISTERED(AXI_SLICE_SRC),
+ .BACKWARD_REGISTERED(AXI_SLICE_SRC)
+) i_src_slice (
+ .clk(src_clk),
+ .resetn(src_resetn),
+ .s_axi_valid(src_valid),
+ .s_axi_ready(src_ready),
+ .s_axi_data(src_data),
+ .m_axi_valid(src_fifo_valid),
+ .m_axi_ready(src_fifo_ready),
+ .m_axi_data(src_fifo_data)
+);
+
+util_axis_resize #(
+ .SLAVE_DATA_WIDTH(DMA_DATA_WIDTH_SRC),
+ .MASTER_DATA_WIDTH(DMA_DATA_WIDTH)
+) i_src_repack (
+ .clk(src_clk),
+ .resetn(src_resetn & src_enable),
+ .s_valid(src_fifo_valid),
+ .s_ready(src_fifo_ready),
+ .s_data(src_fifo_data),
+ .m_valid(src_fifo_repacked_valid),
+ .m_ready(src_fifo_repacked_ready),
+ .m_data(src_fifo_repacked_data)
+);
+
+util_axis_fifo #(
+ .DATA_WIDTH(DMA_DATA_WIDTH),
+ .ADDRESS_WIDTH($clog2(MAX_BYTES_PER_BURST / (DMA_DATA_WIDTH / 8) * FIFO_SIZE)),
+ .ASYNC_CLK(ASYNC_CLK_SRC_DEST)
+) i_fifo (
+ .s_axis_aclk(src_clk),
+ .s_axis_aresetn(src_resetn),
+ .s_axis_valid(src_fifo_repacked_valid),
+ .s_axis_ready(src_fifo_repacked_ready),
+ .s_axis_data(src_fifo_repacked_data),
+ .s_axis_empty(src_fifo_empty),
+ .s_axis_room(),
+
+ .m_axis_aclk(dest_clk),
+ .m_axis_aresetn(dest_resetn),
+ .m_axis_valid(dest_fifo_valid),
+ .m_axis_ready(dest_fifo_ready),
+ .m_axis_data(dest_fifo_data),
+ .m_axis_level()
+);
+
+util_axis_resize #(
+ .SLAVE_DATA_WIDTH(DMA_DATA_WIDTH),
+ .MASTER_DATA_WIDTH(DMA_DATA_WIDTH_DEST)
+) i_dest_repack (
+ .clk(dest_clk),
+ .resetn(dest_resetn & dest_enable),
+ .s_valid(dest_fifo_valid),
+ .s_ready(dest_fifo_ready),
+ .s_data(dest_fifo_data),
+ .m_valid(dest_fifo_repacked_valid),
+ .m_ready(dest_fifo_repacked_ready),
+ .m_data(dest_fifo_repacked_data)
+);
+
+wire _dest_valid;
+wire _dest_ready;
+wire [DMA_DATA_WIDTH_DEST-1:0] _dest_data;
+
+axi_register_slice #(
+ .DATA_WIDTH(DMA_DATA_WIDTH_DEST),
+ .FORWARD_REGISTERED(AXI_SLICE_DEST)
+) i_dest_slice2 (
+ .clk(dest_clk),
+ .resetn(dest_resetn),
+ .s_axi_valid(dest_fifo_repacked_valid),
+ .s_axi_ready(dest_fifo_repacked_ready),
+ .s_axi_data(dest_fifo_repacked_data),
+ .m_axi_valid(_dest_valid),
+ .m_axi_ready(_dest_ready),
+ .m_axi_data(_dest_data)
+);
+
+axi_register_slice #(
+ .DATA_WIDTH(DMA_DATA_WIDTH_DEST),
+ .FORWARD_REGISTERED(AXI_SLICE_DEST),
+ .BACKWARD_REGISTERED(AXI_SLICE_DEST)
+) i_dest_slice (
+ .clk(dest_clk),
+ .resetn(dest_resetn),
+ .s_axi_valid(_dest_valid),
+ .s_axi_ready(_dest_ready),
+ .s_axi_data(_dest_data),
+ .m_axi_valid(dest_valid),
+ .m_axi_ready(dest_ready),
+ .m_axi_data(dest_data)
+);
+
+
+// We do not accept any requests until all components are enabled
+reg _req_valid = 1'b0;
+wire _req_ready;
+
+always @(posedge req_aclk)
+begin
+ if (req_aresetn == 1'b0) begin
+ _req_valid <= 1'b0;
+ end else begin
+ if (_req_valid == 1'b1 && _req_ready == 1'b1) begin
+ _req_valid <= 1'b0;
+ end else if (req_valid == 1'b1 && enabled == 1'b1) begin
+ _req_valid <= 1'b1;
+ end
+ end
+end
+
+assign req_ready = _req_ready & _req_valid & enable;
+
+splitter #(
+ .NUM_M(3)
+) i_req_splitter (
+ .clk(req_aclk),
+ .resetn(req_aresetn),
+ .s_valid(_req_valid),
+ .s_ready(_req_ready),
+ .m_valid({
+ req_gen_valid,
+ req_dest_valid,
+ req_src_valid
+ }),
+ .m_ready({
+ req_gen_ready,
+ req_dest_ready,
+ req_src_ready
+ })
+);
+
+util_axis_fifo #(
+ .DATA_WIDTH(DMA_ADDRESS_WIDTH_DEST + BEATS_PER_BURST_WIDTH_DEST + BYTES_PER_BEAT_WIDTH_DEST + 1),
+ .ADDRESS_WIDTH(0),
+ .ASYNC_CLK(ASYNC_CLK_DEST_REQ)
+) i_dest_req_fifo (
+ .s_axis_aclk(req_aclk),
+ .s_axis_aresetn(req_aresetn),
+ .s_axis_valid(req_dest_valid),
+ .s_axis_ready(req_dest_ready),
+ .s_axis_empty(req_dest_empty),
+ .s_axis_data({
+ req_dest_address,
+ req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST],
+ req_length[BYTES_PER_BEAT_WIDTH_DEST-1:0],
+ req_xlast
+ }),
+ .s_axis_room(),
+
+ .m_axis_aclk(dest_clk),
+ .m_axis_aresetn(dest_resetn),
+ .m_axis_valid(dest_req_valid),
+ .m_axis_ready(dest_req_ready),
+ .m_axis_data({
+ dest_req_address,
+ dest_req_last_burst_length,
+ dest_req_last_beat_bytes,
+ dest_req_xlast
+ }),
+ .m_axis_level()
+);
+
+util_axis_fifo #(
+ .DATA_WIDTH(DMA_ADDRESS_WIDTH_SRC + BEATS_PER_BURST_WIDTH_SRC + 1),
+ .ADDRESS_WIDTH(0),
+ .ASYNC_CLK(ASYNC_CLK_REQ_SRC)
+) i_src_req_fifo (
+ .s_axis_aclk(req_aclk),
+ .s_axis_aresetn(req_aresetn),
+ .s_axis_valid(req_src_valid),
+ .s_axis_ready(req_src_ready),
+ .s_axis_empty(req_src_empty),
+ .s_axis_data({
+ req_src_address,
+ req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC],
+ req_sync_transfer_start
+ }),
+ .s_axis_room(),
+
+ .m_axis_aclk(src_clk),
+ .m_axis_aresetn(src_resetn),
+ .m_axis_valid(src_req_valid),
+ .m_axis_ready(src_req_ready),
+ .m_axis_data({
+ src_req_address,
+ src_req_last_burst_length,
+ src_req_sync_transfer_start
+ }),
+ .m_axis_level()
+);
+
+util_axis_fifo #(
+ .DATA_WIDTH(1),
+ .ADDRESS_WIDTH(0),
+ .ASYNC_CLK(ASYNC_CLK_DEST_REQ)
+) i_dest_response_fifo (
+ .s_axis_aclk(dest_clk),
+ .s_axis_aresetn(dest_resetn),
+ .s_axis_valid(dest_response_valid),
+ .s_axis_ready(dest_response_ready),
+ .s_axis_empty(dest_response_empty),
+ .s_axis_data(dest_response_resp_eot),
+ .s_axis_room(),
+
+ .m_axis_aclk(req_aclk),
+ .m_axis_aresetn(req_aresetn),
+ .m_axis_valid(response_dest_valid),
+ .m_axis_ready(response_dest_ready),
+ .m_axis_data(response_dest_resp_eot),
+ .m_axis_level()
+);
+
+/* Unused for now
+util_axis_fifo #(
+ .DATA_WIDTH(2),
+ .ADDRESS_WIDTH(0),
+ .ASYNC_CLK(ASYNC_CLK_REQ_SRC)
+) i_src_response_fifo (
+ .s_axis_aclk(src_clk),
+ .s_axis_aresetn(src_resetn),
+ .s_axis_valid(src_response_valid),
+ .s_axis_ready(src_response_ready),
+ .s_axis_empty(src_response_empty),
+ .s_axis_data(src_response_resp),
+ .m_axis_aclk(req_aclk),
+ .m_axis_aresetn(req_aresetn),
+ .m_axis_valid(response_src_valid),
+ .m_axis_ready(response_src_ready),
+ .m_axis_data(response_src_resp)
+);*/
+assign src_response_empty = 1'b1;
+assign src_response_ready = 1'b1;
+
+dmac_request_generator #(
+ .ID_WIDTH(ID_WIDTH),
+ .BURSTS_PER_TRANSFER_WIDTH(BURSTS_PER_TRANSFER_WIDTH)
+) i_req_gen (
+ .req_aclk(req_aclk),
+ .req_aresetn(req_aresetn),
+
+ .request_id(request_id),
+ .response_id(response_id),
+
+ .req_valid(req_gen_valid),
+ .req_ready(req_gen_ready),
+ .req_burst_count(req_length[DMA_LENGTH_WIDTH-1:BYTES_PER_BURST_WIDTH]),
+
+ .enable(do_enable),
+ .pause(pause),
+
+ .eot(request_eot)
+);
+
+sync_bits #(
+ .NUM_OF_BITS(3),
+ .ASYNC_CLK(ASYNC_CLK_DEST_REQ)
+) i_sync_control_dest (
+ .out_clk(dest_clk),
+ .out_resetn(dest_resetn),
+ .in({do_enable, pause, sync_id}),
+ .out({dest_enable, dest_pause, dest_sync_id})
+);
+
+sync_bits #(
+ .NUM_OF_BITS(2),
+ .ASYNC_CLK(ASYNC_CLK_DEST_REQ)
+) i_sync_status_dest (
+ .out_clk(req_aclk),
+ .out_resetn(req_aresetn),
+ .in({dest_enabled | ~dest_response_empty, dest_sync_id_ret}),
+ .out({enabled_dest, sync_id_ret_dest})
+);
+
+sync_bits #(
+ .NUM_OF_BITS(3),
+ .ASYNC_CLK(ASYNC_CLK_REQ_SRC)
+) i_sync_control_src (
+ .out_clk(src_clk),
+ .out_resetn(src_resetn),
+ .in({do_enable, pause, sync_id}),
+ .out({src_enable, src_pause, src_sync_id})
+);
+
+sync_bits #(
+ .NUM_OF_BITS(3),
+ .ASYNC_CLK(ASYNC_CLK_REQ_SRC)
+) i_sync_status_src (
+ .out_clk(req_aclk),
+ .out_resetn(req_aresetn),
+ .in({src_enabled | ~src_response_empty, src_sync_id_ret, src_fifo_empty}),
+ .out({enabled_src, sync_id_ret_src, fifo_empty})
+);
+
+endmodule