diff --git a/library/axi_dmac/2d_transfer.v b/library/axi_dmac/2d_transfer.v new file mode 100644 index 000000000..b8a3e67f1 --- /dev/null +++ b/library/axi_dmac/2d_transfer.v @@ -0,0 +1,141 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_2d_transfer ( + input req_aclk, + input req_aresetn, + + input req_valid, + output reg req_ready, + + input [31:C_ADDR_ALIGN_BITS] req_dest_address, + input [31:C_ADDR_ALIGN_BITS] req_src_address, + input [C_DMA_LENGTH_WIDTH-1:0] req_x_length, + input [C_DMA_LENGTH_WIDTH-1:0] req_y_length, + input [C_DMA_LENGTH_WIDTH-1:0] req_dest_stride, + input [C_DMA_LENGTH_WIDTH-1:0] req_src_stride, + input req_sync_transfer_start, + output reg req_eot, + + output reg out_req_valid, + input out_req_ready, + output [31:C_ADDR_ALIGN_BITS] out_req_dest_address, + output [31:C_ADDR_ALIGN_BITS] out_req_src_address, + output [C_DMA_LENGTH_WIDTH-1:0] out_req_length, + output reg out_req_sync_transfer_start, + input out_eot +); + +parameter C_DMA_LENGTH_WIDTH = 24; +parameter C_ADDR_ALIGN_BITS = 3; + +reg [31:C_ADDR_ALIGN_BITS] dest_address; +reg [31:C_ADDR_ALIGN_BITS] src_address; +reg [C_DMA_LENGTH_WIDTH-1:0] x_length; +reg [C_DMA_LENGTH_WIDTH-1:0] y_length; +reg [C_DMA_LENGTH_WIDTH-1:0] dest_stride; +reg [C_DMA_LENGTH_WIDTH-1:0] src_stride; + +reg [1:0] req_id; +reg [1:0] eot_id; +reg [3:0] last_req; + +assign out_req_dest_address = dest_address; +assign out_req_src_address = src_address; +assign out_req_length = x_length; + +always @(posedge req_aclk) +begin + if (req_aresetn == 1'b0) begin + req_id <= 2'b0; + eot_id <= 2'b0; + req_eot <= 1'b0; + end else begin + if (out_req_valid && out_req_ready) begin + req_id <= req_id + 1'b1; + last_req[req_id] <= y_length == 0; + end + req_eot <= 1'b0; + if (out_eot) begin + eot_id <= eot_id + 1'b1; + req_eot <= last_req[eot_id]; + end + end +end + +always @(posedge req_aclk) +begin + if (req_aresetn == 1'b0) begin + dest_address <= 'h00; + src_address <= 'h00; + x_length <= 'h00; + y_length <= 'h00; + dest_stride <= 'h00; + src_stride <= 'h00; + req_ready <= 1'b1; + out_req_valid <= 1'b0; + out_req_sync_transfer_start <= 1'b0; + end else begin + if (req_ready) begin + if (req_valid) begin + dest_address <= req_dest_address; + src_address <= req_src_address; + x_length <= req_x_length; + y_length <= req_y_length; + dest_stride <= req_dest_stride; + src_stride <= req_src_stride; + out_req_sync_transfer_start <= req_sync_transfer_start; + req_ready <= 1'b0; + out_req_valid <= 1'b1; + end + end else begin + if (out_req_valid && out_req_ready) begin + dest_address <= dest_address + dest_stride[C_DMA_LENGTH_WIDTH-1:C_ADDR_ALIGN_BITS]; + src_address <= src_address + src_stride[C_DMA_LENGTH_WIDTH-1:C_ADDR_ALIGN_BITS]; + y_length <= y_length - 1'b1; + out_req_sync_transfer_start <= 1'b0; + if (y_length == 0) begin + out_req_valid <= 1'b0; + req_ready <= 1'b1; + end + end + end + end +end + +endmodule diff --git a/library/axi_dmac/address_generator.v b/library/axi_dmac/address_generator.v new file mode 100644 index 000000000..7be066f80 --- /dev/null +++ b/library/axi_dmac/address_generator.v @@ -0,0 +1,135 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// +// 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_address_generator ( + input clk, + input resetn, + + input req_valid, + output reg req_ready, + input [31:C_ADDR_ALIGN_BITS] req_address, + input [3:0] req_last_burst_length, + + output reg [C_ID_WIDTH-1:0] id, + input [C_ID_WIDTH-1:0] wait_id, + input sync_id, + + input eot, + + input enable, + input pause, + output reg enabled, + + input addr_ready, + output reg addr_valid, + output [31:0] addr, + output [ 7:0] len, + output [ 2:0] size, + output [ 1:0] burst, + output [ 2:0] prot, + output [ 3:0] cache +); + +parameter C_ID_WIDTH = 3; +parameter C_ADDR_ALIGN_BITS = 3; +parameter C_BURST_ALIGN_BITS = 7; +parameter C_DMA_LENGTH_WIDTH = 24; +localparam MAX_BURST_SIZE_BEATS = 2**(C_BURST_ALIGN_BITS-C_ADDR_ALIGN_BITS); + +`include "inc_id.h" + +assign burst = 2'b01; +assign prot = 3'b000; +assign cache = 4'b0011; +assign len = eot ? req_last_burst_length : MAX_BURST_SIZE_BEATS - 1; +assign size = 3'b011; + +reg [31-C_ADDR_ALIGN_BITS:0] address = 'h00; +reg [C_BURST_ALIGN_BITS-C_ADDR_ALIGN_BITS-1:0] last_burst_len = 'h00; +assign addr = {address, {C_ADDR_ALIGN_BITS{1'b0}}}; + +// If we already asserted addr_valid we have to wait until it is accepted before +// we can disable the address generator. +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else begin + if (enable) + enabled <= 1'b1; + else if (~addr_valid) + enabled <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + address <= 'h00; + last_burst_len <= 'h00; + req_ready <= 1'b1; + addr_valid <= 1'b0; + end else begin + if (~enabled) begin + req_ready <= 1'b1; + end else if (req_ready) begin + if (req_valid && enable) begin + address <= req_address; + req_ready <= 1'b0; + end + end else begin + if (addr_valid && addr_ready) begin + address <= address + MAX_BURST_SIZE_BEATS; + addr_valid <= 1'b0; + if (eot) + req_ready <= 1'b1; + end else if (id != wait_id) begin + addr_valid <= 1'b1; + end + end + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <='h0; + end else begin + if ((addr_valid && addr_ready) || + (sync_id && id != wait_id)) + id <= inc_id(id); + end +end + +endmodule diff --git a/library/axi_dmac/axi_dmac.v b/library/axi_dmac/axi_dmac.v new file mode 100644 index 000000000..f12b48456 --- /dev/null +++ b/library/axi_dmac/axi_dmac.v @@ -0,0 +1,538 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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 axi_dmac ( + // Slave AXI interface + input s_axi_aclk, + input s_axi_aresetn, + + input s_axi_awvalid, + input [31:0] s_axi_awaddr, + output s_axi_awready, + input s_axi_wvalid, + input [31:0] s_axi_wdata, + input [ 3:0] s_axi_wstrb, + output s_axi_wready, + output s_axi_bvalid, + output [ 1:0] s_axi_bresp, + input s_axi_bready, + input s_axi_arvalid, + input [31:0] s_axi_araddr, + output s_axi_arready, + output s_axi_rvalid, + input s_axi_rready, + output [ 1:0] s_axi_rresp, + output [31:0] s_axi_rdata, + + // Interrupt + output reg irq, + + // 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_dest_axi_awaddr, + output [ 7:0] m_dest_axi_awlen, + output [ 2:0] m_dest_axi_awsize, + output [ 1:0] m_dest_axi_awburst, + output [ 2:0] m_dest_axi_awprot, + output [ 3:0] m_dest_axi_awcache, + output m_dest_axi_awvalid, + input m_dest_axi_awready, + + // Write data + output [C_M_DEST_AXI_DATA_WIDTH-1:0] m_dest_axi_wdata, + output [(C_M_DEST_AXI_DATA_WIDTH/8)-1:0] m_dest_axi_wstrb, + input m_dest_axi_wready, + output m_dest_axi_wvalid, + output m_dest_axi_wlast, + + // Write response + input m_dest_axi_bvalid, + input [ 1:0] m_dest_axi_bresp, + output m_dest_axi_bready, + + // Read address + input m_src_axi_arready, + output m_src_axi_arvalid, + output [31:0] m_src_axi_araddr, + output [ 7:0] m_src_axi_arlen, + output [ 2:0] m_src_axi_arsize, + output [ 1:0] m_src_axi_arburst, + output [ 2:0] m_src_axi_arprot, + output [ 3:0] m_src_axi_arcache, + + // Read data and response + input [C_M_DEST_AXI_DATA_WIDTH-1:0] m_src_axi_rdata, + output m_src_axi_rready, + input m_src_axi_rvalid, + input [ 1:0] m_src_axi_rresp, + + // Slave streaming AXI interface + input s_axis_aclk, + output s_axis_ready, + input s_axis_valid, + input [C_M_DEST_AXI_DATA_WIDTH-1:0] s_axis_data, + input [0:0] s_axis_user, + + // Master streaming AXI interface + input m_axis_aclk, + input m_axis_ready, + output m_axis_valid, + output [C_M_DEST_AXI_DATA_WIDTH-1:0] m_axis_data, + + // Input FIFO interface + input fifo_wr_clk, + input fifo_wr_en, + input [C_M_DEST_AXI_DATA_WIDTH-1:0] fifo_wr_din, + output fifo_wr_overflow, + input fifo_wr_sync, + + // Input FIFO interface + input fifo_rd_clk, + input fifo_rd_en, + output fifo_rd_valid, + output [C_M_DEST_AXI_DATA_WIDTH-1:0] fifo_rd_dout, + output fifo_rd_underflow +); + +parameter PCORE_ID = 0; + +parameter C_BASEADDR = 32'hffffffff; +parameter C_HIGHADDR = 32'h00000000; +parameter C_M_DEST_AXI_DATA_WIDTH = 64; +parameter C_ADDR_ALIGN_BITS = 3; +parameter C_DMA_LENGTH_WIDTH = 24; +parameter C_2D_TRANSFER = 0; + +parameter C_CLKS_ASYNC_REQ_SRC = 1; +parameter C_CLKS_ASYNC_SRC_DEST = 1; +parameter C_CLKS_ASYNC_DEST_REQ = 1; + +parameter C_AXI_SLICE_DEST = 0; +parameter C_AXI_SLICE_SRC = 0; +parameter C_SYNC_TRANSFER_START = 0; +parameter C_CYCLIC = 0; + +parameter C_DMA_TYPE_DEST = 0; +parameter C_DMA_TYPE_SRC = 0; + +localparam DMA_TYPE_AXI_MM = 0; +localparam DMA_TYPE_AXI_STREAM = 1; +localparam DMA_TYPE_FIFO = 2; + +localparam PCORE_VERSION = 'h00040061; +localparam DMA_ADDR_WIDTH = 32 - C_ADDR_ALIGN_BITS; + +localparam HAS_DEST_ADDR = C_DMA_TYPE_DEST == DMA_TYPE_AXI_MM; +localparam HAS_SRC_ADDR = C_DMA_TYPE_SRC == DMA_TYPE_AXI_MM; + +// Register interface signals +reg [31:0] up_rdata = 'd0; +wire up_wr; +wire up_sel; +wire [31:0] up_wdata; +wire [13:0] up_addr; +wire up_write; + +// Scratch register +reg [31:0] up_scratch = 'h00; + +// Control bits +reg up_enable = 'h00; +reg up_pause = 'h00; + +// Start and end of transfer +wire up_eot; // Asserted for one cycle when a transfer has been completed +wire up_sot; // Asserted for one cycle when a transfer has been queued + +// Interupt handling +reg [1:0] up_irq_mask = 'h3; +reg [1:0] up_irq_source = 'h0; +wire [1:0] up_irq_pending; +wire [1:0] up_irq_trigger; +wire [1:0] up_irq_source_clear; + +// DMA transfer signals +reg up_dma_req_valid = 1'b0; +wire up_dma_req_ready; + +reg [1:0] up_transfer_id; +reg [1:0] up_transfer_id_eot; +reg [3:0] up_transfer_done_bitmap; + +reg [31:C_ADDR_ALIGN_BITS] up_dma_dest_address = 'h00; +reg [31:C_ADDR_ALIGN_BITS] up_dma_src_address = 'h00; +reg [C_DMA_LENGTH_WIDTH-1:0] up_dma_x_length = 'h00; +reg [C_DMA_LENGTH_WIDTH-1:0] up_dma_y_length = 'h00; +reg [C_DMA_LENGTH_WIDTH-1:0] up_dma_src_stride = 'h00; +reg [C_DMA_LENGTH_WIDTH-1:0] up_dma_dest_stride = 'h00; +wire up_dma_sync_transfer_start = C_SYNC_TRANSFER_START ? 1'b1 : 1'b0; + +// ID signals from the DMAC, just for debugging +wire [2:0] dest_request_id; +wire [2:0] dest_data_id; +wire [2:0] dest_address_id; +wire [2:0] dest_response_id; +wire [2:0] src_request_id; +wire [2:0] src_data_id; +wire [2:0] src_address_id; +wire [2:0] src_response_id; +wire [7:0] dbg_status; + +up_axi #( + .PCORE_BASEADDR (C_BASEADDR), + .PCORE_HIGHADDR (C_HIGHADDR) +) i_up_axi ( + .up_rstn(s_axi_aresetn), + .up_clk(s_axi_aclk), + .up_axi_awvalid(s_axi_awvalid), + .up_axi_awaddr(s_axi_awaddr), + .up_axi_awready(s_axi_awready), + .up_axi_wvalid(s_axi_wvalid), + .up_axi_wdata(s_axi_wdata), + .up_axi_wstrb(s_axi_wstrb), + .up_axi_wready(s_axi_wready), + .up_axi_bvalid(s_axi_bvalid), + .up_axi_bresp(s_axi_bresp), + .up_axi_bready(s_axi_bready), + .up_axi_arvalid(s_axi_arvalid), + .up_axi_araddr(s_axi_araddr), + .up_axi_arready(s_axi_arready), + .up_axi_rvalid(s_axi_rvalid), + .up_axi_rresp(s_axi_rresp), + .up_axi_rdata(s_axi_rdata), + .up_axi_rready(s_axi_rready), + .up_wr(up_wr), + .up_sel(up_sel), + .up_addr(up_addr), + .up_wdata(up_wdata), + .up_rdata(up_rdata), + .up_ack(up_sel) +); + +// IRQ handling +assign up_irq_pending = ~up_irq_mask & up_irq_source; +assign up_irq_trigger = {up_eot, up_sot}; +assign up_irq_source_clear = (up_write == 1'b1 && up_addr[11:0] == 12'h021) ? up_wdata[1:0] : 0; + +always @(posedge s_axi_aclk) +begin + if (s_axi_aresetn == 1'b0) + irq <= 1'b0; + else + irq <= |up_irq_pending; +end + +always @(posedge s_axi_aclk) +begin + if (s_axi_aresetn == 1'b0) begin + up_irq_source <= 2'b00; + end else begin + up_irq_source <= up_irq_trigger | (up_irq_source & ~up_irq_source_clear); + end +end + +// Register Interface +assign up_write = up_wr & up_sel; + +always @(posedge s_axi_aclk) +begin + if (s_axi_aresetn == 1'b0) begin + up_enable <= 'h00; + up_pause <= 'h00; + up_dma_src_address <= 'h00; + up_dma_dest_address <= 'h00; + up_dma_y_length <= 'h00; + up_dma_x_length <= 'h00; + up_dma_dest_stride <= 'h00; + up_dma_src_stride <= 'h00; + up_irq_mask <= 3'b11; + up_dma_req_valid <= 1'b0; + up_scratch <= 'h00; + end else begin + if (up_enable == 1'b1) begin + if (up_write && up_addr[11:0] == 12'h102) begin + up_dma_req_valid <= up_dma_req_valid | up_wdata[0]; + end else if (up_sot) begin + up_dma_req_valid <= 1'b0; + end + end else begin + up_dma_req_valid <= 1'b0; + end + + if (up_write) begin + case (up_addr[11:0]) + 12'h002: up_scratch <= up_wdata; + 12'h020: up_irq_mask <= up_wdata; + 12'h100: {up_pause, up_enable} <= up_wdata[1:0]; + 12'h104: up_dma_dest_address <= up_wdata[31:C_ADDR_ALIGN_BITS]; + 12'h105: up_dma_src_address <= up_wdata[31:C_ADDR_ALIGN_BITS]; + 12'h106: up_dma_x_length <= up_wdata[C_DMA_LENGTH_WIDTH-1:0]; + 12'h107: up_dma_y_length <= up_wdata[C_DMA_LENGTH_WIDTH-1:0]; + 12'h108: up_dma_dest_stride <= up_wdata[C_DMA_LENGTH_WIDTH-1:0]; + 12'h109: up_dma_src_stride <= up_wdata[C_DMA_LENGTH_WIDTH-1:0]; + endcase + end + end +end + +always @(posedge s_axi_aclk) +begin + if (s_axi_aresetn == 1'b0) begin + up_rdata <= 'h00; + end else begin + case (up_addr[11:0]) + 12'h000: up_rdata <= PCORE_VERSION; + 12'h001: up_rdata <= PCORE_ID; + 12'h002: up_rdata <= up_scratch; + 12'h020: up_rdata <= up_irq_mask; + 12'h021: up_rdata <= up_irq_pending; + 12'h022: up_rdata <= up_irq_source; + 12'h100: up_rdata <= {up_pause, up_enable}; + 12'h101: up_rdata <= up_transfer_id; + 12'h102: up_rdata <= up_dma_req_valid; + 12'h103: up_rdata <= 'h00; // Flags + 12'h104: up_rdata <= HAS_DEST_ADDR ? {up_dma_dest_address,{C_ADDR_ALIGN_BITS{1'b0}}} : 'h00; + 12'h105: up_rdata <= HAS_SRC_ADDR ? {up_dma_src_address,{C_ADDR_ALIGN_BITS{1'b0}}} : 'h00; + 12'h106: up_rdata <= up_dma_x_length; + 12'h107: up_rdata <= C_2D_TRANSFER ? up_dma_y_length : 'h00; + 12'h108: up_rdata <= C_2D_TRANSFER ? up_dma_dest_stride : 'h00; + 12'h109: up_rdata <= C_2D_TRANSFER ? up_dma_src_stride : 'h00; + 12'h10a: up_rdata <= up_transfer_done_bitmap; + 12'h10b: up_rdata <= up_transfer_id_eot; + 12'h10c: up_rdata <= 'h00; // Status + 12'h10d: up_rdata <= m_dest_axi_awaddr; //HAS_DEST_ADDR ? 'h00 : 'h00; // Current dest address + 12'h10e: up_rdata <= m_src_axi_araddr; //HAS_SRC_ADDR ? 'h00 : 'h00; // Current src address + 12'h10f: up_rdata <= {src_response_id, 1'b0, src_data_id, 1'b0, src_address_id, 1'b0, src_request_id, + 1'b0, dest_response_id, 1'b0, dest_data_id, 1'b0, dest_address_id, 1'b0, dest_request_id}; + 12'h110: up_rdata <= {dbg_status}; + default: up_rdata <= 'h00; + endcase + end +end + +// Request ID and Request done bitmap handling +always @(posedge s_axi_aclk) +begin + if (s_axi_aresetn == 1'b0 || up_enable == 1'b0) begin + up_transfer_id <= 'h0; + up_transfer_id_eot <= 'h0; + up_transfer_done_bitmap <= 'h0; + end begin + if (up_dma_req_valid == 1'b1 && up_dma_req_ready == 1'b1) begin + up_transfer_id <= up_transfer_id + 1'b1; + up_transfer_done_bitmap[up_transfer_id] <= 1'b0; + end + if (up_eot == 1'b1) begin + up_transfer_done_bitmap[up_transfer_id_eot] <= 1'b1; + up_transfer_id_eot <= up_transfer_id_eot + 1'b1; + end + end +end + +wire dma_req_valid; +wire dma_req_ready; +wire [31:C_ADDR_ALIGN_BITS] dma_req_dest_address; +wire [31:C_ADDR_ALIGN_BITS] dma_req_src_address; +wire [C_DMA_LENGTH_WIDTH-1:0] dma_req_length; +wire dma_req_eot; +wire dma_req_sync_transfer_start; +wire up_req_eot; + +assign up_sot = C_CYCLIC ? 1'b0 : up_dma_req_valid & up_dma_req_ready; +assign up_eot = C_CYCLIC ? 1'b0 : up_req_eot; + + +generate if (C_2D_TRANSFER == 1) begin + +dmac_2d_transfer #( + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS) +) i_2d_transfer ( + .req_aclk(s_axi_aclk), + .req_aresetn(s_axi_aresetn), + + .req_eot(up_req_eot), + + .req_valid(up_dma_req_valid), + .req_ready(up_dma_req_ready), + .req_dest_address(up_dma_dest_address), + .req_src_address(up_dma_src_address), + .req_x_length(up_dma_x_length), + .req_y_length(up_dma_y_length), + .req_dest_stride(up_dma_dest_stride), + .req_src_stride(up_dma_src_stride), + .req_sync_transfer_start(up_dma_sync_transfer_start), + + .out_req_valid(dma_req_valid), + .out_req_ready(dma_req_ready), + .out_req_dest_address(dma_req_dest_address), + .out_req_src_address(dma_req_src_address), + .out_req_length(dma_req_length), + .out_req_sync_transfer_start(dma_req_sync_transfer_start), + .out_eot(dma_req_eot) +); + +end else begin + +assign dma_req_valid = up_dma_req_valid; +assign up_dma_req_ready = dma_req_ready; +assign dma_req_dest_address = up_dma_dest_address; +assign dma_req_src_address = up_dma_src_address; +assign dma_req_length = up_dma_x_length; +assign dma_req_sync_transfer_start = up_dma_sync_transfer_start; +assign up_req_eot = dma_req_eot; + +end endgenerate + +dmac_request_arb #( + .C_ID_WIDTH(3), + .C_M_AXI_DATA_WIDTH(C_M_DEST_AXI_DATA_WIDTH), + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS), + .C_DMA_TYPE_DEST(C_DMA_TYPE_DEST), + .C_DMA_TYPE_SRC(C_DMA_TYPE_SRC), + .C_CLKS_ASYNC_REQ_SRC(C_CLKS_ASYNC_REQ_SRC), + .C_CLKS_ASYNC_SRC_DEST(C_CLKS_ASYNC_SRC_DEST), + .C_CLKS_ASYNC_DEST_REQ(C_CLKS_ASYNC_DEST_REQ), + .C_AXI_SLICE_DEST(C_AXI_SLICE_DEST), + .C_AXI_SLICE_SRC(C_AXI_SLICE_SRC) +) i_request_arb ( + .req_aclk(s_axi_aclk), + .req_aresetn(s_axi_aresetn), + + .enable(up_enable), + .pause(up_pause), + + .req_valid(dma_req_valid), + .req_ready(dma_req_ready), + .req_dest_address(dma_req_dest_address), + .req_src_address(dma_req_src_address), + .req_length(dma_req_length), + .req_sync_transfer_start(dma_req_sync_transfer_start), + + .eot(dma_req_eot), + + + .m_dest_axi_aclk(m_dest_axi_aclk), + .m_dest_axi_aresetn(m_dest_axi_aresetn), + .m_src_axi_aclk(m_src_axi_aclk), + .m_src_axi_aresetn(m_src_axi_aresetn), + + + .m_axi_awaddr(m_dest_axi_awaddr), + .m_axi_awlen(m_dest_axi_awlen), + .m_axi_awsize(m_dest_axi_awsize), + .m_axi_awburst(m_dest_axi_awburst), + .m_axi_awprot(m_dest_axi_awprot), + .m_axi_awcache(m_dest_axi_awcache), + .m_axi_awvalid(m_dest_axi_awvalid), + .m_axi_awready(m_dest_axi_awready), + + + .m_axi_wdata(m_dest_axi_wdata), + .m_axi_wstrb(m_dest_axi_wstrb), + .m_axi_wready(m_dest_axi_wready), + .m_axi_wvalid(m_dest_axi_wvalid), + .m_axi_wlast(m_dest_axi_wlast), + + + .m_axi_bvalid(m_dest_axi_bvalid), + .m_axi_bresp(m_dest_axi_bresp), + .m_axi_bready(m_dest_axi_bready), + + + .m_axi_arready(m_src_axi_arready), + .m_axi_arvalid(m_src_axi_arvalid), + .m_axi_araddr(m_src_axi_araddr), + .m_axi_arlen(m_src_axi_arlen), + .m_axi_arsize(m_src_axi_arsize), + .m_axi_arburst(m_src_axi_arburst), + .m_axi_arprot(m_src_axi_arprot), + .m_axi_arcache(m_src_axi_arcache), + + + .m_axi_rdata(m_src_axi_rdata), + .m_axi_rready(m_src_axi_rready), + .m_axi_rvalid(m_src_axi_rvalid), + .m_axi_rresp(m_src_axi_rresp), + + + .s_axis_aclk(s_axis_aclk), + .s_axis_ready(s_axis_ready), + .s_axis_valid(s_axis_valid), + .s_axis_data(s_axis_data), + .s_axis_user(s_axis_user), + + + .m_axis_aclk(m_axis_aclk), + .m_axis_ready(m_axis_ready), + .m_axis_valid(m_axis_valid), + .m_axis_data(m_axis_data), + + + .fifo_wr_clk(fifo_wr_clk), + .fifo_wr_en(fifo_wr_en), + .fifo_wr_din(fifo_wr_din), + .fifo_wr_overflow(fifo_wr_overflow), + .fifo_wr_sync(fifo_wr_sync), + + + .fifo_rd_clk(fifo_rd_clk), + .fifo_rd_en(fifo_rd_en), + .fifo_rd_valid(fifo_rd_valid), + .fifo_rd_dout(fifo_rd_dout), + .fifo_rd_underflow(fifo_rd_underflow), + + // DBG + .dbg_dest_request_id(dest_request_id), + .dbg_dest_address_id(dest_address_id), + .dbg_dest_data_id(dest_data_id), + .dbg_dest_response_id(dest_response_id), + .dbg_src_request_id(src_request_id), + .dbg_src_address_id(src_address_id), + .dbg_src_data_id(src_data_id), + .dbg_src_response_id(src_response_id), + .dbg_status(dbg_status) +); + +endmodule diff --git a/library/axi_dmac/axi_dmac_ip.tcl b/library/axi_dmac/axi_dmac_ip.tcl new file mode 100644 index 000000000..f39f4f1a3 --- /dev/null +++ b/library/axi_dmac/axi_dmac_ip.tcl @@ -0,0 +1,63 @@ +# ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create axi_dmac +adi_ip_files axi_dmac [list \ + "$ad_hdl_dir/library/common/sync_bits.v" \ + "$ad_hdl_dir/library/common/sync_gray.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/axi_fifo/axi_fifo.v" \ + "$ad_hdl_dir/library/axi_fifo/address_gray.v" \ + "$ad_hdl_dir/library/axi_fifo/address_gray_pipelined.v" \ + "address_generator.v" \ + "data_mover.v" \ + "request_arb.v" \ + "request_generator.v" \ + "response_handler.v" \ + "axi_register_slice.v" \ + "2d_transfer.v" \ + "dest_axi_mm.v" \ + "dest_axi_stream.v" \ + "dest_fifo_inf.v" \ + "src_axi_mm.v" \ + "src_axi_stream.v" \ + "src_fifo_inf.v" \ + "splitter.v" \ + "response_generator.v" \ + "axi_dmac.v" ] + +adi_ip_properties axi_dmac + +set_property physical_name {s_axi_aclk} [ipx::get_port_map CLK \ + [ipx::get_bus_interface s_axi_signal_clock [ipx::current_core]]] + +adi_add_bus "s_axis" "axis" "slave" \ + [list {"s_axis_aclk" "ACLK"} \ + {"s_axis_ready" "TREADY"} \ + {"s_axis_valid" "VALID"} \ + {"s_axis_data" "TDATA"} \ + {"s_axis_user" "TUSER"} ] + +adi_add_bus "m_axis" "axis" "master" \ + [list {"m_axis_aclk" "ACLK"} \ + {"m_axis_ready" "TREADY"} \ + {"m_axis_valid" "VALID"} \ + {"m_axis_data" "TDATA"} ] + +adi_set_bus_dependency "m_src_axi" "m_src_axi" \ + "(spirit:decode(id('MODELPARAM_VALUE.C_DMA_TYPE_SRC')) = 0)" +adi_set_bus_dependency "m_dest_axi" "m_dest_axi" \ + "(spirit:decode(id('MODELPARAM_VALUE.C_DMA_TYPE_DEST')) = 0)" +adi_set_bus_dependency "s_axis" "s_axis" \ + "(spirit:decode(id('MODELPARAM_VALUE.C_DMA_TYPE_SRC')) = 1)" +adi_set_bus_dependency "m_axis" "m_axis" \ + "(spirit:decode(id('MODELPARAM_VALUE.C_DMA_TYPE_DEST')) = 1)" +adi_set_ports_dependency "fifo_wr" \ + "(spirit:decode(id('MODELPARAM_VALUE.C_DMA_TYPE_SRC')) = 2)" +adi_set_ports_dependency "fifo_rd" \ + "(spirit:decode(id('MODELPARAM_VALUE.C_DMA_TYPE_DEST')) = 2)" + +ipx::save_core [ipx::current_core] + diff --git a/library/axi_dmac/axi_register_slice.v b/library/axi_dmac/axi_register_slice.v new file mode 100644 index 000000000..7cf5d7b22 --- /dev/null +++ b/library/axi_dmac/axi_register_slice.v @@ -0,0 +1,133 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// +// 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 axi_register_slice ( + input clk, + input resetn, + + input s_axi_valid, + output s_axi_ready, + input [DATA_WIDTH-1:0] s_axi_data, + + output m_axi_valid, + input m_axi_ready, + output [DATA_WIDTH-1:0] m_axi_data +); + +parameter DATA_WIDTH = 32; + +parameter FORWARD_REGISTERED = 0; +parameter BACKWARD_REGISTERED = 0; + +/* + s_axi_data -> bwd_data -> fwd_data(1) -> m_axi_data + s_axi_valid -> bwd_valid -> fwd_valid(1) -> m_axi_valid + s_axi_ready <- bwd_ready(2) <- fwd_ready <- m_axi_ready + + (1) FORWARD_REGISTERED inserts a set of FF before m_axi_data and m_axi_valid + (2) BACKWARD_REGISTERED insters a FF before s_axi_ready +*/ + +wire [DATA_WIDTH-1:0] bwd_data_s; +wire bwd_valid_s; +wire bwd_ready_s; +wire [DATA_WIDTH-1:0] fwd_data_s; +wire fwd_valid_s; +wire fwd_ready_s; + +generate if (FORWARD_REGISTERED == 1) begin + +reg fwd_valid; +reg [DATA_WIDTH-1:0] fwd_data; + +assign fwd_ready_s = ~fwd_valid | m_axi_ready; +assign fwd_valid_s = fwd_valid; +assign fwd_data_s = fwd_data; + +always @(posedge clk) begin + if (resetn == 1'b0) begin + fwd_valid <= 1'b0; + end else begin + if (~fwd_valid | m_axi_ready) + fwd_data <= bwd_data_s; + if (bwd_valid_s) + fwd_valid <= 1'b1; + else if (m_axi_ready) + fwd_valid <= 1'b0; + end +end + +end else begin +assign fwd_data_s = bwd_data_s; +assign fwd_valid_s = bwd_valid_s; +assign fwd_ready_s = m_axi_ready; +end +endgenerate + +generate if (BACKWARD_REGISTERED == 1) begin + +reg bwd_ready; +reg [DATA_WIDTH-1:0] bwd_data; + +assign bwd_valid_s = ~bwd_ready | s_axi_valid; +assign bwd_data_s = bwd_ready ? s_axi_data : bwd_data; +assign bwd_ready_s = bwd_ready; + +always @(posedge clk) begin + if (resetn == 1'b0) begin + bwd_ready <= 1'b1; + end else begin + if (bwd_ready) + bwd_data <= s_axi_data; + if (fwd_ready_s) + bwd_ready <= 1'b1; + else if (s_axi_valid) + bwd_ready <= 1'b0; + end +end + +end else begin +assign bwd_valid_s = s_axi_valid; +assign bwd_data_s = s_axi_data; +assign bwd_ready_s = fwd_ready_s; +end endgenerate + +assign m_axi_data = fwd_data_s; +assign m_axi_valid = fwd_valid_s; +assign s_axi_ready = bwd_ready_s; + +endmodule diff --git a/library/axi_dmac/data_mover.v b/library/axi_dmac/data_mover.v new file mode 100644 index 000000000..e72568f6a --- /dev/null +++ b/library/axi_dmac/data_mover.v @@ -0,0 +1,150 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_data_mover ( + input clk, + input resetn, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + input sync_id, + input eot, + + input enable, + output reg enabled, + + output s_axi_ready, + input s_axi_valid, + input [C_DATA_WIDTH-1:0] s_axi_data, + + input m_axi_ready, + output m_axi_valid, + output [C_DATA_WIDTH-1:0] m_axi_data, + output m_axi_last, + + input req_valid, + output reg req_ready, + input [3:0] req_last_burst_length +); + +parameter C_ID_WIDTH = 3; +parameter C_DATA_WIDTH = 64; +parameter C_DISABLE_WAIT_FOR_ID = 1; + +`include "inc_id.h" + +reg [3:0] last_burst_length; +reg [C_ID_WIDTH-1:0] id = 'h00; +reg [C_ID_WIDTH-1:0] id_next; +reg [3:0] beat_counter = 'h00; +wire [3:0] beat_counter_next; +wire last; +reg pending_burst; + +assign response_id = id; + +assign beat_counter_next = s_axi_ready && s_axi_valid ? beat_counter + 1'b1 : beat_counter; +assign last = beat_counter == (eot ? last_burst_length : 4'hf); + +assign s_axi_ready = m_axi_ready & pending_burst & ~req_ready; +assign m_axi_valid = s_axi_valid & pending_burst & ~req_ready; +assign m_axi_data = s_axi_data; +assign m_axi_last = last; + +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else begin + if (enable) begin + enabled <= 1'b1; + end else begin + if (C_DISABLE_WAIT_FOR_ID == 0) begin + // We are not allowed to just deassert valid, so wait until the + // current beat has been accepted + if (~s_axi_valid || m_axi_ready) + enabled <= 1'b0; + end else begin + // For memory mapped AXI busses we have to complete all pending + // burst requests before we can disable the data mover. + if (response_id == request_id) + enabled <= 1'b0; + end + end + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + beat_counter <= 'h0; + req_ready <= 1'b1; + end else begin + if (~enabled) begin + req_ready <= 1'b1; + end else if (req_ready) begin + if (req_valid && enabled) begin + last_burst_length <= req_last_burst_length; + req_ready <= 1'b0; + beat_counter <= 'h0; + end + end else if (s_axi_ready && s_axi_valid) begin + if (last && eot) + req_ready <= 1'b1; + beat_counter <= beat_counter + 1'b1; + end + end +end + +always @(*) +begin + if ((s_axi_ready && s_axi_valid && last) || + (sync_id && id != request_id)) + id_next <= inc_id(id); + else + id_next <= id; +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else begin + id <= id_next; + pending_burst <= id_next != request_id; + end +end + +endmodule diff --git a/library/axi_dmac/dest_axi_mm.v b/library/axi_dmac/dest_axi_mm.v new file mode 100644 index 000000000..d823a53a4 --- /dev/null +++ b/library/axi_dmac/dest_axi_mm.v @@ -0,0 +1,232 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_dest_mm_axi ( + input m_axi_aclk, + input m_axi_aresetn, + + input req_valid, + output req_ready, + input [31:C_ADDR_ALIGN_BITS] req_address, + input [3:0] req_last_burst_length, + input [2:0] req_last_beat_bytes, + + input enable, + output enabled, + input pause, + input sync_id, + output sync_id_ret, + + output response_valid, + input response_ready, + output [1:0] response_resp, + output response_resp_eot, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + + output [C_ID_WIDTH-1:0] data_id, + output [C_ID_WIDTH-1:0] address_id, + input data_eot, + input address_eot, + input response_eot, + + input fifo_valid, + output fifo_ready, + input [C_M_AXI_DATA_WIDTH-1:0] fifo_data, + + // Write address + input m_axi_awready, + output m_axi_awvalid, + 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, + + // Write data + output [C_M_AXI_DATA_WIDTH-1:0] m_axi_wdata, + output [(C_M_AXI_DATA_WIDTH/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 +); + +parameter C_ID_WIDTH = 3; +parameter C_M_AXI_DATA_WIDTH = 64; +parameter C_ADDR_ALIGN_BITS = 3; +parameter C_DMA_LENGTH_WIDTH = 24; + +wire [C_ID_WIDTH-1:0] data_id; +wire [C_ID_WIDTH-1:0] address_id; + +reg [(C_M_AXI_DATA_WIDTH/8)-1:0] wstrb; + +wire address_req_valid; +wire address_req_ready; +wire data_req_valid; +wire data_req_ready; + +wire address_enabled; +wire data_enabled; +assign sync_id_ret = sync_id; + +splitter #( + .C_NUM_M(2) +) i_req_splitter ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + .s_valid(req_valid), + .s_ready(req_ready), + .m_valid({ + address_req_valid, + data_req_valid + }), + .m_ready({ + address_req_ready, + data_req_ready + }) +); + +dmac_address_generator #( + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS), + .C_ID_WIDTH(C_ID_WIDTH) +) i_addr_gen ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + + .enable(enable), + .enabled(address_enabled), + .pause(pause), + + .id(address_id), + .wait_id(request_id), + .sync_id(sync_id), + + .req_valid(address_req_valid), + .req_ready(address_req_ready), + .req_address(req_address), + .req_last_burst_length(req_last_burst_length), + + .eot(address_eot), + + .addr_ready(m_axi_awready), + .addr_valid(m_axi_awvalid), + .addr(m_axi_awaddr), + .len(m_axi_awlen), + .size(m_axi_awsize), + .burst(m_axi_awburst), + .prot(m_axi_awprot), + .cache(m_axi_awcache) +); + +wire _fifo_ready; + +dmac_data_mover # ( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_M_AXI_DATA_WIDTH) +) i_data_mover ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + + .enable(address_enabled), + .enabled(data_enabled), + + .request_id(address_id), + .response_id(data_id), + .sync_id(sync_id), + .eot(data_eot), + + .req_valid(data_req_valid), + .req_ready(data_req_ready), + .req_last_burst_length(req_last_burst_length), + + .s_axi_valid(fifo_valid), + .s_axi_ready(_fifo_ready), + .s_axi_data(fifo_data), + .m_axi_valid(m_axi_wvalid), + .m_axi_ready(m_axi_wready), + .m_axi_data(m_axi_wdata), + .m_axi_last(m_axi_wlast) +); + +assign fifo_ready = _fifo_ready | ~enabled; + +always @(*) +begin + if (data_eot & m_axi_wlast) begin + wstrb <= (1 << (req_last_beat_bytes + 1)) - 1; + end else begin + wstrb <= 8'b11111111; + end +end + +assign m_axi_wstrb = wstrb; + +dmac_response_handler #( + .C_ID_WIDTH(C_ID_WIDTH) +) i_response_handler ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + .bvalid(m_axi_bvalid), + .bready(m_axi_bready), + .bresp(m_axi_bresp), + + .enable(data_enabled), + .enabled(enabled), + + .id(response_id), + .wait_id(data_id), + .sync_id(sync_id), + + .eot(response_eot), + + .resp_valid(response_valid), + .resp_ready(response_ready), + .resp_resp(response_resp), + .resp_eot(response_resp_eot) +); + +endmodule diff --git a/library/axi_dmac/dest_axi_stream.v b/library/axi_dmac/dest_axi_stream.v new file mode 100644 index 000000000..5101cef40 --- /dev/null +++ b/library/axi_dmac/dest_axi_stream.v @@ -0,0 +1,137 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_dest_axi_stream ( + input s_axis_aclk, + input s_axis_aresetn, + + input enable, + output enabled, + input sync_id, + output sync_id_ret, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + output [C_ID_WIDTH-1:0] data_id, + input data_eot, + input response_eot, + + input m_axis_ready, + output m_axis_valid, + output [C_S_AXIS_DATA_WIDTH-1:0] m_axis_data, + + output fifo_ready, + input fifo_valid, + input [C_S_AXIS_DATA_WIDTH-1:0] fifo_data, + + input req_valid, + output req_ready, + input [3:0] req_last_burst_length, + + output response_valid, + input response_ready, + output response_resp_eot, + output [1:0] response_resp +); + +parameter C_ID_WIDTH = 3; +parameter C_S_AXIS_DATA_WIDTH = 64; +parameter C_LENGTH_WIDTH = 24; + +assign sync_id_ret = sync_id; +wire data_enabled; +wire [C_ID_WIDTH-1:0] data_id; +wire _fifo_ready; + +// We are not allowed to just de-assert valid, but if the streaming target does +// not accept any samples anymore we'd lock up the DMA core. So retain the last +// beat when disabled until it is accepted. But if in the meantime the DMA core +// is re-enabled and new data becomes available overwrite the old. + +dmac_data_mover # ( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_S_AXIS_DATA_WIDTH), + .C_DISABLE_WAIT_FOR_ID(0) +) i_data_mover ( + .clk(s_axis_aclk), + .resetn(s_axis_aresetn), + + .enable(enable), + .enabled(data_enabled), + .sync_id(sync_id), + + .request_id(request_id), + .response_id(data_id), + .eot(data_eot), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_last_burst_length(req_last_burst_length), + + .m_axi_ready(m_axis_ready), + .m_axi_valid(m_axis_valid), + .m_axi_data(m_axis_data), + .s_axi_ready(_fifo_ready), + .s_axi_valid(fifo_valid), + .s_axi_data(fifo_data) +); + +dmac_response_generator # ( + .C_ID_WIDTH(C_ID_WIDTH) +) i_response_generator ( + .clk(s_axis_aclk), + .resetn(s_axis_aresetn), + + .enable(data_enabled), + .enabled(enabled), + .sync_id(sync_id), + + .request_id(data_id), + .response_id(response_id), + + .eot(response_eot), + + .resp_valid(response_valid), + .resp_ready(response_ready), + .resp_eot(response_resp_eot), + .resp_resp(response_resp) +); + +assign fifo_ready = _fifo_ready | ~enabled; + +endmodule diff --git a/library/axi_dmac/dest_fifo_inf.v b/library/axi_dmac/dest_fifo_inf.v new file mode 100644 index 000000000..59fba2aac --- /dev/null +++ b/library/axi_dmac/dest_fifo_inf.v @@ -0,0 +1,155 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_dest_fifo_inf ( + input clk, + input resetn, + + input enable, + output enabled, + input sync_id, + output sync_id_ret, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + output [C_ID_WIDTH-1:0] data_id, + input data_eot, + input response_eot, + + input en, + output [C_DATA_WIDTH-1:0] dout, + output reg valid, + output reg underflow, + + output fifo_ready, + input fifo_valid, + input [C_DATA_WIDTH-1:0] fifo_data, + + input req_valid, + output req_ready, + input [3:0] req_last_burst_length, + + output response_valid, + input response_ready, + output response_resp_eot, + output [1:0] response_resp +); + +parameter C_ID_WIDTH = 3; +parameter C_DATA_WIDTH = 64; +parameter C_LENGTH_WIDTH = 24; + +assign sync_id_ret = sync_id; +wire data_enabled; +wire [C_ID_WIDTH-1:0] data_id; + +wire _fifo_ready; +assign fifo_ready = _fifo_ready | ~enabled; + +reg data_ready; +wire data_valid; + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + data_ready <= 1'b1; + underflow <= 1'b0; + valid <= 1'b0; + end else begin + if (enable == 1'b1) begin + valid <= data_valid & en; + data_ready <= en & data_valid; + underflow <= en & ~data_valid; + end else begin + valid <= 1'b0; + data_ready <= 1'b1; + underflow <= en; + end + end +end + +dmac_data_mover # ( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_DATA_WIDTH), + .C_DISABLE_WAIT_FOR_ID(0) +) i_data_mover ( + .clk(clk), + .resetn(resetn), + + .enable(enable), + .enabled(data_enabled), + .sync_id(sync_id), + + .request_id(request_id), + .response_id(data_id), + .eot(data_eot), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_last_burst_length(req_last_burst_length), + + .s_axi_ready(_fifo_ready), + .s_axi_valid(fifo_valid), + .s_axi_data(fifo_data), + .m_axi_ready(data_ready), + .m_axi_valid(data_valid), + .m_axi_data(dout) +); + +dmac_response_generator # ( + .C_ID_WIDTH(C_ID_WIDTH) +) i_response_generator ( + .clk(clk), + .resetn(resetn), + + .enable(data_enabled), + .enabled(enabled), + .sync_id(sync_id), + + .request_id(data_id), + .response_id(response_id), + + .eot(response_eot), + + .resp_valid(response_valid), + .resp_ready(response_ready), + .resp_eot(response_resp_eot), + .resp_resp(response_resp) +); + +endmodule diff --git a/library/axi_dmac/inc_id.h b/library/axi_dmac/inc_id.h new file mode 100644 index 000000000..03ad51cc6 --- /dev/null +++ b/library/axi_dmac/inc_id.h @@ -0,0 +1,67 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// +// 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. +// *************************************************************************** +// *************************************************************************** + +function [C_ID_WIDTH-1:0] g2b; + input [C_ID_WIDTH-1:0] g; + reg [C_ID_WIDTH-1:0] b; + integer i; + begin + b[C_ID_WIDTH-1] = g[C_ID_WIDTH-1]; + for (i = C_ID_WIDTH - 2; i >= 0; i = i - 1) + b[i] = b[i + 1] ^ g[i]; + g2b = b; + end +endfunction + +function [C_ID_WIDTH-1:0] b2g; + input [C_ID_WIDTH-1:0] b; + reg [C_ID_WIDTH-1:0] g; + integer i; + begin + g[C_ID_WIDTH-1] = b[C_ID_WIDTH-1]; + for (i = C_ID_WIDTH - 2; i >= 0; i = i -1) + g[i] = b[i + 1] ^ b[i]; + b2g = g; + end +endfunction + +function [C_ID_WIDTH:0] inc_id; +input [C_ID_WIDTH:0] id; +begin + inc_id = b2g(g2b(id) + 1); +end +endfunction diff --git a/library/axi_dmac/request_arb.v b/library/axi_dmac/request_arb.v new file mode 100644 index 000000000..f24c888a5 --- /dev/null +++ b/library/axi_dmac/request_arb.v @@ -0,0 +1,934 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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:C_ADDR_ALIGN_BITS] req_dest_address, + input [31:C_ADDR_ALIGN_BITS] req_src_address, + input [C_DMA_LENGTH_WIDTH-1:0] req_length, + 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 [C_M_AXI_DATA_WIDTH-1:0] m_axi_wdata, + output [(C_M_AXI_DATA_WIDTH/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 [C_M_AXI_DATA_WIDTH-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 [C_M_AXI_DATA_WIDTH-1:0] s_axis_data, + input [0:0] s_axis_user, + + // Master streaming AXI interface + input m_axis_aclk, + input m_axis_ready, + output m_axis_valid, + output [C_M_AXI_DATA_WIDTH-1:0] m_axis_data, + + // Input FIFO interface + input fifo_wr_clk, + input fifo_wr_en, + input [C_M_AXI_DATA_WIDTH-1:0] fifo_wr_din, + output fifo_wr_overflow, + input fifo_wr_sync, + + // Input FIFO interface + input fifo_rd_clk, + input fifo_rd_en, + output fifo_rd_valid, + output [C_M_AXI_DATA_WIDTH-1:0] fifo_rd_dout, + output fifo_rd_underflow, + + output [C_ID_WIDTH-1:0] dbg_dest_request_id, + output [C_ID_WIDTH-1:0] dbg_dest_address_id, + output [C_ID_WIDTH-1:0] dbg_dest_data_id, + output [C_ID_WIDTH-1:0] dbg_dest_response_id, + output [C_ID_WIDTH-1:0] dbg_src_request_id, + output [C_ID_WIDTH-1:0] dbg_src_address_id, + output [C_ID_WIDTH-1:0] dbg_src_data_id, + output [C_ID_WIDTH-1:0] dbg_src_response_id, + output [7:0] dbg_status +); + +parameter C_ID_WIDTH = 3; +parameter C_M_AXI_DATA_WIDTH = 64; +parameter C_DMA_LENGTH_WIDTH = 24; +parameter C_ADDR_ALIGN_BITS = 3; + +parameter C_DMA_TYPE_DEST = DMA_TYPE_MM_AXI; +parameter C_DMA_TYPE_SRC = DMA_TYPE_FIFO; + +parameter C_CLKS_ASYNC_REQ_SRC = 1; +parameter C_CLKS_ASYNC_SRC_DEST = 1; +parameter C_CLKS_ASYNC_DEST_REQ = 1; + +parameter C_AXI_SLICE_DEST = 0; +parameter C_AXI_SLICE_SRC = 0; + +localparam DMA_TYPE_MM_AXI = 0; +localparam DMA_TYPE_STREAM_AXI = 1; +localparam DMA_TYPE_FIFO = 2; + +localparam DMA_ADDR_WIDTH = 32 - C_ADDR_ALIGN_BITS; + +reg eot_mem_src[0:2**C_ID_WIDTH-1]; +reg eot_mem_dest[0:2**C_ID_WIDTH-1]; +wire request_eot; + +wire [C_ID_WIDTH-1:0] request_id; +wire [C_ID_WIDTH-1:0] response_id; + +wire [C_DMA_LENGTH_WIDTH-7:0] req_burst_count = req_length[C_DMA_LENGTH_WIDTH-1:7]; +wire [3:0] req_last_burst_length = req_length[6:3]; +wire [2:0] req_last_beat_bytes = req_length[2:0]; + +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_ADDR_WIDTH-1:0] dest_req_address; +wire [3:0] dest_req_last_burst_length; +wire [2:0] dest_req_last_beat_bytes; + +wire dest_response_valid; +wire dest_response_ready; +wire dest_response_empty; +wire [1:0] dest_response_resp; +wire dest_response_resp_eot; + +wire [C_ID_WIDTH-1:0] dest_request_id; +wire [C_ID_WIDTH-1:0] dest_response_id; + +wire dest_valid; +wire dest_ready; +wire [C_M_AXI_DATA_WIDTH-1:0] dest_data; +wire dest_fifo_valid; +wire dest_fifo_ready; +wire [C_M_AXI_DATA_WIDTH-1:0] dest_fifo_data; + +wire src_clk; +wire src_resetn; +wire src_req_valid; +wire src_req_ready; +wire [DMA_ADDR_WIDTH-1:0] src_req_address; +wire [3:0] src_req_last_burst_length; +wire [2:0] src_req_last_beat_bytes; +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 [C_ID_WIDTH-1:0] src_request_id; +wire [C_ID_WIDTH-1:0] src_response_id; + +wire src_valid; +wire src_ready; +wire [C_M_AXI_DATA_WIDTH-1:0] src_data; +wire src_fifo_valid; +wire src_fifo_ready; +wire [C_M_AXI_DATA_WIDTH-1:0] src_fifo_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; + +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_src[request_id] <= request_eot; + eot_mem_dest[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 reset for reset-less interfaces +generate if (C_DMA_TYPE_SRC == DMA_TYPE_STREAM_AXI || C_DMA_TYPE_SRC == DMA_TYPE_FIFO) begin + +reg [2:0] src_resetn_shift = 3'b0; +assign src_resetn = src_resetn_shift[2]; + +always @(negedge req_aresetn or posedge src_clk) begin + if (~req_aresetn) + src_resetn_shift <= 3'b000; + else + src_resetn_shift <= {src_resetn_shift[1:0], 1'b1}; +end + +end endgenerate + +generate if (C_DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI || C_DMA_TYPE_DEST == DMA_TYPE_FIFO) begin + +reg [2:0] dest_resetn_shift = 3'b0; +assign dest_resetn = dest_resetn_shift[2]; + +always @(negedge req_aresetn or posedge dest_clk) begin + if (~req_aresetn) + dest_resetn_shift <= 3'b000; + else + dest_resetn_shift <= {dest_resetn_shift[1:0], 1'b1}; +end + +end endgenerate + + +generate if (C_DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin + +assign dest_clk = m_dest_axi_aclk; +assign dest_resetn = m_dest_axi_aresetn; + +wire [C_ID_WIDTH-1:0] dest_data_id; +wire [C_ID_WIDTH-1:0] dest_address_id; +wire dest_address_eot = eot_mem_dest[dest_address_id]; +wire dest_data_eot = eot_mem_dest[dest_data_id]; +wire dest_response_eot = eot_mem_dest[dest_response_id]; + +assign dbg_dest_address_id = dest_address_id; +assign dbg_dest_data_id = dest_data_id; + +dmac_dest_mm_axi #( + .C_ID_WIDTH(C_ID_WIDTH), + .C_M_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS), + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH) +) i_dest_dma_mm ( + .m_axi_aclk(m_dest_axi_aclk), + .m_axi_aresetn(m_dest_axi_aresetn), + + .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 if (C_DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin + + +assign dest_clk = m_axis_aclk; + +wire [C_ID_WIDTH-1:0] data_id; + +wire data_eot = eot_mem_dest[data_id]; +wire response_eot = eot_mem_dest[dest_response_id]; + +assign dbg_dest_address_id = dest_request_id; +assign dbg_dest_data_id = data_id; + +dmac_dest_axi_stream #( + .C_ID_WIDTH(C_ID_WIDTH), + .C_S_AXIS_DATA_WIDTH(C_M_AXI_DATA_WIDTH) +) 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), + + .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), + + .m_axis_valid(m_axis_valid), + .m_axis_ready(m_axis_ready), + .m_axis_data(m_axis_data) +); + +end else /* if (C_DMA_TYPE_DEST == DMA_TYPE_FIFO) */ begin + +assign dest_clk = fifo_rd_clk; + +wire [C_ID_WIDTH-1:0] data_id; + +wire data_eot = eot_mem_dest[data_id]; +wire response_eot = eot_mem_dest[dest_response_id]; + +dmac_dest_fifo_inf #( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_M_AXI_DATA_WIDTH) +) 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) +); + +end endgenerate + +generate if (C_DMA_TYPE_SRC == DMA_TYPE_MM_AXI) begin + +assign src_clk = m_src_axi_aclk; +assign src_resetn = m_src_axi_aresetn; + +wire [C_ID_WIDTH-1:0] src_data_id; +wire [C_ID_WIDTH-1:0] src_address_id; +wire src_address_eot = eot_mem_src[src_address_id]; +wire src_data_eot = eot_mem_src[src_data_id]; + +assign dbg_src_address_id = src_address_id; +assign dbg_src_data_id = src_data_id; + +dmac_src_mm_axi #( + .C_ID_WIDTH(C_ID_WIDTH), + .C_M_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS), + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH) +) i_src_dma_mm ( + .m_axi_aclk(m_src_axi_aclk), + .m_axi_aresetn(m_src_axi_aresetn), + + .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), + .req_last_beat_bytes(src_req_last_beat_bytes), + + .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 if (C_DMA_TYPE_SRC == DMA_TYPE_STREAM_AXI) begin + +assign src_clk = s_axis_aclk; + +wire src_eot = eot_mem_src[src_response_id]; + +dmac_src_axi_stream #( + .C_ID_WIDTH(C_ID_WIDTH), + .C_S_AXIS_DATA_WIDTH(C_M_AXI_DATA_WIDTH) +) 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) +); + +end else /* if (C_DMA_TYPE_SRC == DMA_TYPE_FIFO) */ begin + +assign src_clk = fifo_wr_clk; + +wire src_eot = eot_mem_src[src_response_id]; + +dmac_src_fifo_inf #( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_M_AXI_DATA_WIDTH) +) 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) +); + +end endgenerate + +sync_bits #( + .NUM_BITS(C_ID_WIDTH), + .CLK_ASYNC(C_CLKS_ASYNC_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_BITS(C_ID_WIDTH), + .CLK_ASYNC(C_CLKS_ASYNC_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_BITS(C_ID_WIDTH), + .CLK_ASYNC(C_CLKS_ASYNC_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(C_M_AXI_DATA_WIDTH), + .FORWARD_REGISTERED(C_AXI_SLICE_SRC), + .BACKWARD_REGISTERED(C_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) +); + +axi_fifo #( + .C_DATA_WIDTH(C_M_AXI_DATA_WIDTH), + .C_ADDRESS_WIDTH(6), + .C_CLKS_ASYNC(C_CLKS_ASYNC_SRC_DEST) +) i_fifo ( + .s_axis_aclk(src_clk), + .s_axis_aresetn(src_resetn), + .s_axis_valid(src_fifo_valid), + .s_axis_ready(src_fifo_ready), + .s_axis_data(src_fifo_data), + .s_axis_empty(src_fifo_empty), + + .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) +); + +wire _dest_valid; +wire _dest_ready; +wire [C_M_AXI_DATA_WIDTH-1:0] _dest_data; + +axi_register_slice #( + .DATA_WIDTH(C_M_AXI_DATA_WIDTH), + .FORWARD_REGISTERED(C_AXI_SLICE_DEST) +) i_dest_slice2 ( + .clk(dest_clk), + .resetn(dest_resetn), + .s_axi_valid(dest_fifo_valid), + .s_axi_ready(dest_fifo_ready), + .s_axi_data(dest_fifo_data), + .m_axi_valid(_dest_valid), + .m_axi_ready(_dest_ready), + .m_axi_data(_dest_data) +); + +axi_register_slice #( + .DATA_WIDTH(C_M_AXI_DATA_WIDTH), + .FORWARD_REGISTERED(C_AXI_SLICE_DEST), + .BACKWARD_REGISTERED(C_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 +wire _req_ready; +assign req_ready = _req_ready & enabled; + +splitter #( + .C_NUM_M(3) +) i_req_splitter ( + .clk(req_aclk), + .resetn(req_aresetn), + .s_valid(req_valid & enabled), + .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 + }) +); + +axi_fifo #( + .C_DATA_WIDTH(DMA_ADDR_WIDTH + 4 + 3), + .C_ADDRESS_WIDTH(0), + .C_CLKS_ASYNC(C_CLKS_ASYNC_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_last_burst_length, + req_last_beat_bytes + }), + .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 + }) +); + +axi_fifo #( + .C_DATA_WIDTH(DMA_ADDR_WIDTH + 4 + 3 + 1), + .C_ADDRESS_WIDTH(0), + .C_CLKS_ASYNC(C_CLKS_ASYNC_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_last_burst_length, + req_last_beat_bytes, + req_sync_transfer_start + }), + .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_last_beat_bytes, + src_req_sync_transfer_start + }) +); + +axi_fifo #( + .C_DATA_WIDTH(3), + .C_ADDRESS_WIDTH(0), + .C_CLKS_ASYNC(C_CLKS_ASYNC_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, + dest_response_resp_eot + }), + .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, + response_dest_resp_eot + }) +); + +axi_fifo #( + .C_DATA_WIDTH(2), + .C_ADDRESS_WIDTH(0), + .C_CLKS_ASYNC(C_CLKS_ASYNC_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) +); + +dmac_request_generator #( + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS), + .C_ID_WIDTH(C_ID_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_burst_count), + + .enable(enable), + .pause(pause), + + .eot(request_eot) +); + +sync_bits #( + .NUM_BITS(3), + .CLK_ASYNC(C_CLKS_ASYNC_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_BITS(2), + .CLK_ASYNC(C_CLKS_ASYNC_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_BITS(3), + .CLK_ASYNC(C_CLKS_ASYNC_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_BITS(3), + .CLK_ASYNC(C_CLKS_ASYNC_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 diff --git a/library/axi_dmac/request_generator.v b/library/axi_dmac/request_generator.v new file mode 100644 index 000000000..014c55bb6 --- /dev/null +++ b/library/axi_dmac/request_generator.v @@ -0,0 +1,99 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_generator ( + input req_aclk, + input req_aresetn, + + output [C_ID_WIDTH-1:0] request_id, + input [C_ID_WIDTH-1:0] response_id, + + input req_valid, + output reg req_ready, + input [BURST_COUNT_WIDTH:0] req_burst_count, + + input enable, + input pause, + + output eot +); + +parameter C_ID_WIDTH = 3; +parameter C_ADDR_ALIGN_BITS = 3; +parameter C_BURST_ALIGN_BITS = 7; +parameter C_DMA_LENGTH_WIDTH = 24; +localparam BURST_COUNT_WIDTH = C_DMA_LENGTH_WIDTH - C_BURST_ALIGN_BITS; + +`include "inc_id.h" + +/* + * Here we only need to count the number of bursts, which means we can ignore + * the lower bits of the byte count. The last last burst may not contain the + * maximum number of bytes, but the address_generator and data_mover will take + * care that only the requested ammount of bytes is transfered. + */ + +reg [BURST_COUNT_WIDTH-1:0] burst_count = 'h00; +reg [C_ID_WIDTH-1:0] id; +wire [C_ID_WIDTH-1:0] id_next = inc_id(id); + +assign eot = burst_count == 'h00; +assign request_id = id; + +always @(posedge req_aclk) +begin + if (req_aresetn == 1'b0) begin + burst_count <= 'h00; + id <= 'h0; + req_ready <= 1'b1; + end else begin + if (req_ready) begin + if (req_valid && enable) begin + burst_count <= req_burst_count; + req_ready <= 1'b0; + end + end else if (response_id != id_next && ~pause) begin + if (eot) + req_ready <= 1'b1; + burst_count <= burst_count - 1'b1; + id <= id_next; + end + end +end + +endmodule diff --git a/library/axi_dmac/resp.h b/library/axi_dmac/resp.h new file mode 100644 index 000000000..a3a738357 --- /dev/null +++ b/library/axi_dmac/resp.h @@ -0,0 +1,4 @@ +localparam RESP_OKAY = 2'b00; +localparam RESP_EXOKAY = 2'b01; +localparam RESP_SLVERR = 2'b10; +localparam RESP_DECERR = 2'b11; diff --git a/library/axi_dmac/response_generator.v b/library/axi_dmac/response_generator.v new file mode 100644 index 000000000..546ab60c0 --- /dev/null +++ b/library/axi_dmac/response_generator.v @@ -0,0 +1,90 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_response_generator ( + input clk, + input resetn, + + input enable, + output reg enabled, + + input [C_ID_WIDTH-1:0] request_id, + output reg [C_ID_WIDTH-1:0] response_id, + input sync_id, + + input eot, + + output resp_valid, + input resp_ready, + output resp_eot, + output [1:0] resp_resp +); + +parameter C_ID_WIDTH = 3; + +`include "inc_id.h" +`include "resp.h" + +assign resp_resp = RESP_OKAY; +assign resp_eot = eot; + +assign resp_valid = request_id != response_id; + +// We have to wait for all responses before we can disable the response handler +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else begin + if (enable) + enabled <= 1'b1; + else if (request_id == response_id) + enabled <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + response_id <= 'h0; + end else begin + if ((resp_valid && resp_ready) || + (sync_id && response_id != request_id)) + response_id <= inc_id(response_id); + end +end + +endmodule diff --git a/library/axi_dmac/response_handler.v b/library/axi_dmac/response_handler.v new file mode 100644 index 000000000..f93386b2f --- /dev/null +++ b/library/axi_dmac/response_handler.v @@ -0,0 +1,97 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_response_handler ( + input clk, + input resetn, + + input bvalid, + output bready, + input [1:0] bresp, + + output reg [C_ID_WIDTH-1:0] id, + input [C_ID_WIDTH-1:0] wait_id, + input sync_id, + + input enable, + output reg enabled, + + input eot, + + output resp_valid, + input resp_ready, + output resp_eot, + output [1:0] resp_resp +); + +parameter C_ID_WIDTH = 3; + +`include "resp.h" +`include "inc_id.h" + +assign resp_resp = bresp; +assign resp_eot = eot; + +wire active = id != wait_id && enabled; + +assign bready = active && resp_ready; +assign resp_valid = active && bvalid; + +// We have to wait for all responses before we can disable the response handler +always @(posedge clk) begin + if (resetn == 1'b0) begin + enabled <= 1'b0; + end else begin + if (enable) + enabled <= 1'b1; + else if (wait_id == id) + enabled <= 1'b0; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else begin + if ((bready && bvalid) || + (sync_id && id != wait_id)) + id <= inc_id(id); + end +end + +endmodule diff --git a/library/axi_dmac/splitter.v b/library/axi_dmac/splitter.v new file mode 100644 index 000000000..2487d43ea --- /dev/null +++ b/library/axi_dmac/splitter.v @@ -0,0 +1,69 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// +// 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 splitter ( + input clk, + input resetn, + + input s_valid, + output s_ready, + + output [C_NUM_M-1:0] m_valid, + input [C_NUM_M-1:0] m_ready +); + +parameter C_NUM_M = 2; + +reg [C_NUM_M-1:0] acked; + +assign s_ready = &(m_ready | acked); +assign m_valid = s_valid ? ~acked : {C_NUM_M{1'b0}}; + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + acked <= {C_NUM_M{1'b0}}; + end else begin + if (s_valid & s_ready) + acked <= {C_NUM_M{1'b0}}; + else + acked <= acked | (m_ready & m_valid); + end +end + +endmodule diff --git a/library/axi_dmac/src_axi_mm.v b/library/axi_dmac/src_axi_mm.v new file mode 100644 index 000000000..9f33f8834 --- /dev/null +++ b/library/axi_dmac/src_axi_mm.v @@ -0,0 +1,192 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_src_mm_axi ( + input m_axi_aclk, + input m_axi_aresetn, + + input req_valid, + output req_ready, + input [31:C_ADDR_ALIGN_BITS] req_address, + input [3:0] req_last_burst_length, + input [2:0] req_last_beat_bytes, + + input enable, + output enabled, + input pause, + input sync_id, + output sync_id_ret, + + output response_valid, + input response_ready, + output [1:0] response_resp, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + + output [C_ID_WIDTH-1:0] data_id, + output [C_ID_WIDTH-1:0] address_id, + input data_eot, + input address_eot, + + output fifo_valid, + input fifo_ready, + output [C_M_AXI_DATA_WIDTH-1:0] fifo_data, + + // 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 [C_M_AXI_DATA_WIDTH-1:0] m_axi_rdata, + output m_axi_rready, + input m_axi_rvalid, + input [ 1:0] m_axi_rresp +); + +parameter C_ID_WIDTH = 3; +parameter C_M_AXI_DATA_WIDTH = 64; +parameter C_ADDR_ALIGN_BITS = 3; +parameter C_DMA_LENGTH_WIDTH = 24; + +wire [C_ID_WIDTH-1:0] data_id; +wire [C_ID_WIDTH-1:0] address_id; + +wire address_enabled; + +wire address_req_valid; +wire address_req_ready; +wire data_req_valid; +wire data_req_ready; + +assign sync_id_ret = sync_id; +assign response_id = data_id; + +splitter #( + .C_NUM_M(2) +) i_req_splitter ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + .s_valid(req_valid), + .s_ready(req_ready), + .m_valid({ + address_req_valid, + data_req_valid + }), + .m_ready({ + address_req_ready, + data_req_ready + }) +); + +dmac_address_generator #( + .C_DMA_LENGTH_WIDTH(C_DMA_LENGTH_WIDTH), + .C_ADDR_ALIGN_BITS(C_ADDR_ALIGN_BITS), + .C_ID_WIDTH(C_ID_WIDTH) +) i_addr_gen ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + + .enable(enable), + .enabled(address_enabled), + .sync_id(sync_id), + + .id(address_id), + .wait_id(request_id), + + .req_valid(address_req_valid), + .req_ready(address_req_ready), + .req_address(req_address), + .req_last_burst_length(req_last_burst_length), + + .eot(address_eot), + + .addr_ready(m_axi_arready), + .addr_valid(m_axi_arvalid), + .addr(m_axi_araddr), + .len(m_axi_arlen), + .size(m_axi_arsize), + .burst(m_axi_arburst), + .prot(m_axi_arprot), + .cache(m_axi_arcache) +); + +dmac_data_mover # ( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_M_AXI_DATA_WIDTH) +) i_data_mover ( + .clk(m_axi_aclk), + .resetn(m_axi_aresetn), + + .enable(address_enabled), + .enabled(enabled), + .sync_id(sync_id), + + .request_id(address_id), + .response_id(data_id), + .eot(data_eot), + + .req_valid(data_req_valid), + .req_ready(data_req_ready), + .req_last_burst_length(req_last_burst_length), + + .s_axi_valid(m_axi_rvalid), + .s_axi_ready(m_axi_rready), + .s_axi_data(m_axi_rdata), + .m_axi_valid(fifo_valid), + .m_axi_ready(fifo_ready), + .m_axi_data(fifo_data) +); + +reg [1:0] rresp; + +always @(posedge m_axi_aclk) +begin + if (m_axi_rvalid && m_axi_rready) begin + if (m_axi_rresp != 2'b0) + rresp <= m_axi_rresp; + end +end + +endmodule diff --git a/library/axi_dmac/src_axi_stream.v b/library/axi_dmac/src_axi_stream.v new file mode 100644 index 000000000..23a982510 --- /dev/null +++ b/library/axi_dmac/src_axi_stream.v @@ -0,0 +1,118 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_src_axi_stream ( + input s_axis_aclk, + input s_axis_aresetn, + + input enable, + output enabled, + input sync_id, + output sync_id_ret, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + input eot, + + output s_axis_ready, + input s_axis_valid, + input [C_S_AXIS_DATA_WIDTH-1:0] s_axis_data, + input [0:0] s_axis_user, + + input fifo_ready, + output fifo_valid, + output [C_S_AXIS_DATA_WIDTH-1:0] fifo_data, + + input req_valid, + output req_ready, + input [3:0] req_last_burst_length, + input req_sync_transfer_start +); + +parameter C_ID_WIDTH = 3; +parameter C_S_AXIS_DATA_WIDTH = 64; +parameter C_LENGTH_WIDTH = 24; + +reg needs_sync = 1'b0; +wire sync = s_axis_user[0]; +wire has_sync = ~needs_sync | sync; +wire sync_valid = s_axis_valid & has_sync; +assign sync_id_ret = sync_id; + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + needs_sync <= 1'b0; + end else begin + if (s_axis_valid && s_axis_ready && sync) begin + needs_sync <= 1'b0; + end else if (req_valid && req_ready) begin + needs_sync <= req_sync_transfer_start; + end + end +end + +dmac_data_mover # ( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_S_AXIS_DATA_WIDTH), + .C_DISABLE_WAIT_FOR_ID(0) +) i_data_mover ( + .clk(s_axis_aclk), + .resetn(s_axis_aresetn), + + .enable(enable), + .enabled(enabled), + .sync_id(sync_id), + + .request_id(request_id), + .response_id(response_id), + .eot(eot), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_last_burst_length(req_last_burst_length), + + .s_axi_ready(s_axis_ready), + .s_axi_valid(sync_valid), + .s_axi_data(s_axis_data), + .m_axi_ready(fifo_ready), + .m_axi_valid(fifo_valid), + .m_axi_data(fifo_data) +); + +endmodule diff --git a/library/axi_dmac/src_fifo_inf.v b/library/axi_dmac/src_fifo_inf.v new file mode 100644 index 000000000..f526815c7 --- /dev/null +++ b/library/axi_dmac/src_fifo_inf.v @@ -0,0 +1,146 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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_src_fifo_inf ( + input clk, + input resetn, + + input enable, + output enabled, + input sync_id, + output sync_id_ret, + + input [C_ID_WIDTH-1:0] request_id, + output [C_ID_WIDTH-1:0] response_id, + input eot, + + input en, + input [C_DATA_WIDTH-1:0] din, + output reg overflow, + input sync, + + input fifo_ready, + output fifo_valid, + output [C_DATA_WIDTH-1:0] fifo_data, + + input req_valid, + output req_ready, + input [3:0] req_last_burst_length, + input req_sync_transfer_start +); + +parameter C_ID_WIDTH = 3; +parameter C_DATA_WIDTH = 64; +parameter C_LENGTH_WIDTH = 24; + +reg valid = 1'b0; +wire ready; +reg [C_DATA_WIDTH-1:0] buffer = 'h00; +reg buffer_sync = 1'b0; + +reg needs_sync = 1'b0; +wire has_sync = ~needs_sync | buffer_sync; +wire sync_valid = valid & has_sync; + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + needs_sync <= 1'b0; + end else begin + if (ready && valid && buffer_sync) begin + needs_sync <= 1'b0; + end else if (req_valid && req_ready) begin + needs_sync <= req_sync_transfer_start; + end + end +end + +always @(posedge clk) +begin + if (resetn == 1'b0) begin + valid <= 1'b0; + overflow <= 1'b0; + end else begin + if (enable) begin + if (en) begin + buffer <= din; + buffer_sync <= sync; + valid <= 1'b1; + end else if (ready) begin + valid <= 1'b0; + end + overflow <= en & valid & ~ready; + end else begin + if (ready) + valid <= 1'b0; + overflow <= en; + end + end +end + +assign sync_id_ret = sync_id; + +dmac_data_mover # ( + .C_ID_WIDTH(C_ID_WIDTH), + .C_DATA_WIDTH(C_DATA_WIDTH), + .C_DISABLE_WAIT_FOR_ID(0) +) i_data_mover ( + .clk(clk), + .resetn(resetn), + + .enable(enable), + .enabled(enabled), + .sync_id(sync_id), + + .request_id(request_id), + .response_id(response_id), + .eot(eot), + + .req_valid(req_valid), + .req_ready(req_ready), + .req_last_burst_length(req_last_burst_length), + + .s_axi_ready(ready), + .s_axi_valid(sync_valid), + .s_axi_data(buffer), + .m_axi_ready(fifo_ready), + .m_axi_valid(fifo_valid), + .m_axi_data(fifo_data) +); + +endmodule diff --git a/library/axi_fifo/address_gray.v b/library/axi_fifo/address_gray.v new file mode 100644 index 000000000..da26227de --- /dev/null +++ b/library/axi_fifo/address_gray.v @@ -0,0 +1,156 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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 fifo_address_gray ( + input m_axis_aclk, + input m_axis_aresetn, + input m_axis_ready, + output reg m_axis_valid, + output [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next, + + input s_axis_aclk, + input s_axis_aresetn, + output reg s_axis_ready, + input s_axis_valid, + output reg s_axis_empty, + output [C_ADDRESS_WIDTH-1:0] s_axis_waddr +); + +parameter C_ADDRESS_WIDTH = 4; + +reg [C_ADDRESS_WIDTH:0] _s_axis_waddr = 'h00; +reg [C_ADDRESS_WIDTH:0] _s_axis_waddr_next; + +reg [C_ADDRESS_WIDTH:0] _m_axis_raddr = 'h00; +reg [C_ADDRESS_WIDTH:0] _m_axis_raddr_next; + +reg [C_ADDRESS_WIDTH:0] s_axis_waddr_gray = 'h00; +wire [C_ADDRESS_WIDTH:0] s_axis_waddr_gray_next; +wire [C_ADDRESS_WIDTH:0] s_axis_raddr_gray; + +reg [C_ADDRESS_WIDTH:0] m_axis_raddr_gray = 'h00; +wire [C_ADDRESS_WIDTH:0] m_axis_raddr_gray_next; +wire [C_ADDRESS_WIDTH:0] m_axis_waddr_gray; + +assign s_axis_waddr = _s_axis_waddr[C_ADDRESS_WIDTH-1:0]; +assign m_axis_raddr_next = _m_axis_raddr_next[C_ADDRESS_WIDTH-1:0]; + +always @(*) +begin + if (s_axis_ready && s_axis_valid) + _s_axis_waddr_next <= _s_axis_waddr + 1; + else + _s_axis_waddr_next <= _s_axis_waddr; +end + +assign s_axis_waddr_gray_next = _s_axis_waddr_next ^ _s_axis_waddr_next[C_ADDRESS_WIDTH:1]; + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + _s_axis_waddr <= 'h00; + s_axis_waddr_gray <= 'h00; + end else begin + _s_axis_waddr <= _s_axis_waddr_next; + s_axis_waddr_gray <= s_axis_waddr_gray_next; + end +end + +always @(*) +begin + if (m_axis_ready && m_axis_valid) + _m_axis_raddr_next <= _m_axis_raddr + 1; + else + _m_axis_raddr_next <= _m_axis_raddr; +end + +assign m_axis_raddr_gray_next = _m_axis_raddr_next ^ _m_axis_raddr_next[C_ADDRESS_WIDTH:1]; + +always @(posedge m_axis_aclk) +begin + if (m_axis_aresetn == 1'b0) begin + _m_axis_raddr <= 'h00; + m_axis_raddr_gray <= 'h00; + end else begin + _m_axis_raddr <= _m_axis_raddr_next; + m_axis_raddr_gray <= m_axis_raddr_gray_next; + end +end + +sync_bits #( + .NUM_BITS(C_ADDRESS_WIDTH + 1) +) i_waddr_sync ( + .out_clk(m_axis_aclk), + .out_resetn(m_axis_aresetn), + .in(s_axis_waddr_gray), + .out(m_axis_waddr_gray) +); + +sync_bits #( + .NUM_BITS(C_ADDRESS_WIDTH + 1) +) i_raddr_sync ( + .out_clk(s_axis_aclk), + .out_resetn(s_axis_aresetn), + .in(m_axis_raddr_gray), + .out(s_axis_raddr_gray) +); + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + s_axis_ready <= 1'b1; + s_axis_empty <= 1'b1; + end else begin + s_axis_ready <= (s_axis_raddr_gray[C_ADDRESS_WIDTH] == s_axis_waddr_gray_next[C_ADDRESS_WIDTH] || + s_axis_raddr_gray[C_ADDRESS_WIDTH-1] == s_axis_waddr_gray_next[C_ADDRESS_WIDTH-1] || + s_axis_raddr_gray[C_ADDRESS_WIDTH-2:0] != s_axis_waddr_gray_next[C_ADDRESS_WIDTH-2:0]); + s_axis_empty <= s_axis_raddr_gray == s_axis_waddr_gray_next; + end +end + +always @(posedge m_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) + m_axis_valid <= 1'b0; + else begin + m_axis_valid <= m_axis_waddr_gray != m_axis_raddr_gray_next; + end +end + +endmodule + diff --git a/library/axi_fifo/address_gray_pipelined.v b/library/axi_fifo/address_gray_pipelined.v new file mode 100644 index 000000000..62b5072c7 --- /dev/null +++ b/library/axi_fifo/address_gray_pipelined.v @@ -0,0 +1,147 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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 fifo_address_gray_pipelined ( + input m_axis_aclk, + input m_axis_aresetn, + input m_axis_ready, + output reg m_axis_valid, + output [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next, + output [C_ADDRESS_WIDTH-1:0] m_axis_raddr, + + input s_axis_aclk, + input s_axis_aresetn, + output reg s_axis_ready, + input s_axis_valid, + output reg s_axis_empty, + output [C_ADDRESS_WIDTH-1:0] s_axis_waddr +); + +parameter C_ADDRESS_WIDTH = 4; + +reg [C_ADDRESS_WIDTH:0] _s_axis_waddr = 'h00; +reg [C_ADDRESS_WIDTH:0] _s_axis_waddr_next; +wire [C_ADDRESS_WIDTH:0] _s_axis_raddr; + +reg [C_ADDRESS_WIDTH:0] _m_axis_raddr = 'h00; +reg [C_ADDRESS_WIDTH:0] _m_axis_raddr_next; +wire [C_ADDRESS_WIDTH:0] _m_axis_waddr; + +assign s_axis_waddr = _s_axis_waddr[C_ADDRESS_WIDTH-1:0]; +assign m_axis_raddr_next = _m_axis_raddr_next[C_ADDRESS_WIDTH-1:0]; +assign m_axis_raddr = _m_axis_raddr[C_ADDRESS_WIDTH-1:0]; + +always @(*) +begin + if (s_axis_ready && s_axis_valid) + _s_axis_waddr_next <= _s_axis_waddr + 1; + else + _s_axis_waddr_next <= _s_axis_waddr; +end + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + _s_axis_waddr <= 'h00; + end else begin + _s_axis_waddr <= _s_axis_waddr_next; + end +end + +always @(*) +begin + if (m_axis_ready && m_axis_valid) + _m_axis_raddr_next <= _m_axis_raddr + 1; + else + _m_axis_raddr_next <= _m_axis_raddr; +end + +always @(posedge m_axis_aclk) +begin + if (m_axis_aresetn == 1'b0) begin + _m_axis_raddr <= 'h00; + end else begin + _m_axis_raddr <= _m_axis_raddr_next; + end +end + +sync_gray #( + .DATA_WIDTH(C_ADDRESS_WIDTH + 1) +) i_waddr_sync ( + .in_clk(s_axis_aclk), + .in_resetn(s_axis_aresetn), + .out_clk(m_axis_aclk), + .out_resetn(m_axis_aresetn), + .in_count(_s_axis_waddr), + .out_count(_m_axis_waddr) +); + +sync_gray #( + .DATA_WIDTH(C_ADDRESS_WIDTH + 1) +) i_raddr_sync ( + .in_clk(m_axis_aclk), + .in_resetn(m_axis_aresetn), + .out_clk(s_axis_aclk), + .out_resetn(s_axis_aresetn), + .in_count(_m_axis_raddr), + .out_count(_s_axis_raddr) +); + +always @(posedge s_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) begin + s_axis_ready <= 1'b1; + s_axis_empty <= 1'b1; + end else begin + s_axis_ready <= (_s_axis_raddr[C_ADDRESS_WIDTH] == _s_axis_waddr_next[C_ADDRESS_WIDTH] || + _s_axis_raddr[C_ADDRESS_WIDTH-1:0] != _s_axis_waddr_next[C_ADDRESS_WIDTH-1:0]); + s_axis_empty <= _s_axis_raddr == _s_axis_waddr_next; + end +end + +always @(posedge m_axis_aclk) +begin + if (s_axis_aresetn == 1'b0) + m_axis_valid <= 1'b0; + else begin + m_axis_valid <= _m_axis_waddr != _m_axis_raddr_next; + end +end + +endmodule + diff --git a/library/axi_fifo/axi_fifo.v b/library/axi_fifo/axi_fifo.v new file mode 100644 index 000000000..4c8a6bab3 --- /dev/null +++ b/library/axi_fifo/axi_fifo.v @@ -0,0 +1,192 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2013(c) Analog Devices, Inc. +// Author: Lars-Peter Clausen +// +// 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 axi_fifo ( + input m_axis_aclk, + input m_axis_aresetn, + input m_axis_ready, + output m_axis_valid, + output [C_DATA_WIDTH-1:0] m_axis_data, + + input s_axis_aclk, + input s_axis_aresetn, + output s_axis_ready, + input s_axis_valid, + input [C_DATA_WIDTH-1:0] s_axis_data, + output s_axis_empty +); + +parameter C_DATA_WIDTH = 64; +parameter C_CLKS_ASYNC = 1; +parameter C_ADDRESS_WIDTH = 4; + +generate if (C_ADDRESS_WIDTH == 0) begin + +reg [C_DATA_WIDTH-1:0] ram; +reg s_axis_waddr = 1'b0; +reg m_axis_raddr = 1'b0; + +wire m_axis_waddr; +wire s_axis_raddr; + +sync_bits #( + .NUM_BITS(1), + .CLK_ASYNC(C_CLKS_ASYNC) +) i_waddr_sync ( + .out_clk(m_axis_aclk), + .out_resetn(s_axis_aresetn), + .in(s_axis_waddr), + .out(m_axis_waddr) +); + +sync_bits #( + .NUM_BITS(1), + .CLK_ASYNC(C_CLKS_ASYNC) +) i_raddr_sync ( + .out_clk(s_axis_aclk), + .out_resetn(m_axis_aresetn), + .in(m_axis_raddr), + .out(s_axis_raddr) +); + +assign m_axis_valid = m_axis_raddr != m_axis_waddr; +assign s_axis_ready = s_axis_raddr == s_axis_waddr; +assign s_axis_empty = s_axis_raddr == s_axis_waddr; + +always @(posedge s_axis_aclk) begin + if (s_axis_aresetn == 1'b0) begin + s_axis_waddr <= 1'b0; + end else begin + if (s_axis_ready & s_axis_valid) begin + s_axis_waddr <= s_axis_waddr + 1'b1; + ram <= s_axis_data; + end + end +end + +always @(posedge m_axis_aclk) begin + if (m_axis_aresetn == 1'b0) begin + m_axis_raddr <= 1'b0; + end else begin + if (m_axis_valid & m_axis_ready) + m_axis_raddr <= m_axis_raddr + 1'b1; + end +end + +assign m_axis_data = ram; + +end else begin + +reg [C_DATA_WIDTH-1:0] ram[0:2**C_ADDRESS_WIDTH-1]; + +wire [C_ADDRESS_WIDTH-1:0] s_axis_waddr; +wire [C_ADDRESS_WIDTH-1:0] m_axis_raddr; +wire _m_axis_ready; +wire _m_axis_valid; + +if (C_CLKS_ASYNC == 1) begin + +fifo_address_gray_pipelined #( + .C_ADDRESS_WIDTH(C_ADDRESS_WIDTH) +) i_address_gray ( + .m_axis_aclk(m_axis_aclk), + .m_axis_aresetn(m_axis_aresetn), + + .m_axis_ready(_m_axis_ready), + .m_axis_valid(_m_axis_valid), + .m_axis_raddr(m_axis_raddr), + + .s_axis_aclk(s_axis_aclk), + .s_axis_aresetn(s_axis_aresetn), + .s_axis_ready(s_axis_ready), + .s_axis_valid(s_axis_valid), + .s_axis_empty(s_axis_empty), + .s_axis_waddr(s_axis_waddr) +); + +end else begin + +fifo_address_sync #( + .C_ADDRESS_WIDTH(C_ADDRESS_WIDTH) +) i_address_sync ( + .clk(m_axis_aclk), + .resetn(m_axis_aresetn), + + .m_axis_ready(_m_axis_ready), + .m_axis_valid(_m_axis_valid), + .m_axis_raddr(m_axis_raddr), + + .s_axis_ready(s_axis_ready), + .s_axis_valid(s_axis_valid), + .s_axis_empty(s_axis_empty), + .s_axis_waddr(s_axis_waddr) +); + +end + +always @(posedge s_axis_aclk) begin + if (s_axis_ready) + ram[s_axis_waddr] <= s_axis_data; +end + +reg [C_DATA_WIDTH-1:0] data; +reg valid; + +always @(posedge m_axis_aclk) begin + if (m_axis_aresetn == 1'b0) begin + valid <= 1'b0; + end else begin + if (_m_axis_valid) + valid <= 1'b1; + else if (m_axis_ready) + valid <= 1'b0; + end +end + +always @(posedge m_axis_aclk) begin + if ((~valid || m_axis_ready) && _m_axis_valid) + data <= ram[m_axis_raddr]; +end + +assign _m_axis_ready = ~valid || m_axis_ready; +assign m_axis_data = data; +assign m_axis_valid = valid; + +end endgenerate + +endmodule diff --git a/library/misc/daq1_spi.v b/library/misc/daq1_spi.v new file mode 100644 index 000000000..c89add83e --- /dev/null +++ b/library/misc/daq1_spi.v @@ -0,0 +1,111 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011(c) Analog Devices, Inc. +// +// 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. +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module daq1_spi ( + + spi_csn, + spi_clk, + spi_mosi, + spi_miso, + + spi_sdio); + + // 4 wire + + input [ 2:0] spi_csn; + input spi_clk; + input spi_mosi; + output spi_miso; + + // 3 wire + + inout spi_sdio; + + // internal registers + + reg [ 5:0] spi_count = 'd0; + reg spi_rd_wr_n = 'd0; + reg spi_enable = 'd0; + + // internal signals + + wire spi_csn_s; + wire spi_enable_s; + + // check on rising edge and change on falling edge + + assign spi_csn_s = & spi_csn; + assign spi_enable_s = spi_enable & ~spi_csn_s; + + always @(posedge spi_clk) begin + if (spi_csn_s == 1'b1) begin + spi_count <= 6'd0; + spi_rd_wr_n <= 1'd0; + end else begin + spi_count <= spi_count + 1'b1; + if (spi_count == 6'd0) begin + spi_rd_wr_n <= spi_mosi; + end + end + end + + always @(negedge spi_clk) begin + if (spi_csn_s == 1'b1) begin + spi_enable <= 1'b0; + end else begin + if (((spi_count == 6'd16) && (spi_csn[2] == 1'b0)) || + ((spi_count == 6'd8) && (spi_csn[1] == 1'b0)) || + ((spi_count == 6'd16) && (spi_csn[0] == 1'b0))) begin + spi_enable <= spi_rd_wr_n; + end + end + end + + // io butter + + IOBUF i_iobuf_sdio ( + .T (spi_enable_s), + .I (spi_mosi), + .O (spi_miso), + .IO (spi_sdio)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/library/misc/daq2_spi.v b/library/misc/daq2_spi.v new file mode 100644 index 000000000..eb3e7d91e --- /dev/null +++ b/library/misc/daq2_spi.v @@ -0,0 +1,109 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011(c) Analog Devices, Inc. +// +// 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. +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module daq2_spi ( + + spi_csn, + spi_clk, + spi_mosi, + spi_miso, + + spi_sdio); + + // 4 wire + + input [ 2:0] spi_csn; + input spi_clk; + input spi_mosi; + output spi_miso; + + // 3 wire + + inout spi_sdio; + + // internal registers + + reg [ 5:0] spi_count = 'd0; + reg spi_rd_wr_n = 'd0; + reg spi_enable = 'd0; + + // internal signals + + wire spi_csn_s; + wire spi_enable_s; + + // check on rising edge and change on falling edge + + assign spi_csn_s = & spi_csn; + assign spi_enable_s = spi_enable & ~spi_csn_s; + + always @(posedge spi_clk or posedge spi_csn_s) begin + if (spi_csn_s == 1'b1) begin + spi_count <= 6'd0; + spi_rd_wr_n <= 1'd0; + end else begin + spi_count <= spi_count + 1'b1; + if (spi_count == 6'd0) begin + spi_rd_wr_n <= spi_mosi; + end + end + end + + always @(negedge spi_clk or posedge spi_csn_s) begin + if (spi_csn_s == 1'b1) begin + spi_enable <= 1'b0; + end else begin + if (spi_count == 6'd16) begin + spi_enable <= spi_rd_wr_n; + end + end + end + + // io butter + + IOBUF i_iobuf_sdio ( + .T (spi_enable_s), + .I (spi_mosi), + .O (spi_miso), + .IO (spi_sdio)); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/library/misc/usdrx1_spi.v b/library/misc/usdrx1_spi.v new file mode 100644 index 000000000..552a9536c --- /dev/null +++ b/library/misc/usdrx1_spi.v @@ -0,0 +1,141 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011(c) Analog Devices, Inc. +// +// 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. +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module usdrx1_spi ( + + spi_fout_csn, + spi_afe_csn, + spi_clk_csn, + spi_clk, + spi_mosi, + spi_miso, + + spi_fout_sdio, + spi_afe_sdio, + spi_clk_sdio); + + // 4 wire + + input [ 5:0] spi_fout_csn; + input [ 3:0] spi_afe_csn; + input spi_clk_csn; + input spi_clk; + input spi_mosi; + output spi_miso; + + // 3 wire + + inout spi_fout_sdio; + inout spi_afe_sdio; + input spi_clk_sdio; + + // internal registers + + reg [ 5:0] spi_count = 'd0; + reg spi_rd_wr_n = 'd0; + reg spi_enable = 'd0; + + // internal signals + + wire [ 2:0] spi_csn_3_s; + wire spi_csn_s; + wire spi_enable_s; + wire spi_fout_miso_s; + wire spi_afe_miso_s; + wire spi_clk_miso_s; + + // check on rising edge and change on falling edge + + assign spi_csn_3_s[2] = & spi_fout_csn; + assign spi_csn_3_s[1] = & spi_afe_csn; + assign spi_csn_3_s[0] = spi_clk_csn; + assign spi_csn_s = & spi_csn_3_s; + assign spi_enable_s = spi_enable & ~spi_csn_s; + + always @(posedge spi_clk) begin + if (spi_csn_s == 1'b1) begin + spi_count <= 6'd0; + spi_rd_wr_n <= 1'd0; + end else begin + spi_count <= spi_count + 1'b1; + if (spi_count == 6'd0) begin + spi_rd_wr_n <= spi_mosi; + end + end + end + + always @(negedge spi_clk) begin + if (spi_csn_s == 1'b1) begin + spi_enable <= 1'b0; + end else begin + if (((spi_count == 6'd16) && (spi_csn_3_s[1] == 1'b0)) || + ((spi_count == 6'd16) && (spi_csn_3_s[0] == 1'b0))) begin + spi_enable <= spi_rd_wr_n; + end + end + end + + assign spi_miso = ((spi_fout_miso_s & ~spi_csn_3_s[2]) | + (spi_afe_miso_s & ~spi_csn_3_s[1]) | + (spi_clk_miso_s & ~spi_csn_3_s[0])); + + // io buffers + + IOBUF i_iobuf_fout_sdio ( + .T (spi_enable_s), + .I (spi_mosi), + .O (spi_fout_miso_s), + .IO (spi_fout_sdio)); + + IOBUF i_iobuf_afe_sdio ( + .T (spi_enable_s), + .I (spi_mosi), + .O (spi_afe_miso_s), + .IO (spi_afe_sdio)); + + IOBUF i_iobuf_clk_sdio ( + .T (spi_enable_s), + .I (spi_mosi), + .O (spi_clk_miso_s), + .IO (spi_clk_sdio)); + +endmodule + +// *************************************************************************** +// ***************************************************************************