// *************************************************************************** // *************************************************************************** // Copyright (C) 2014-2023 Analog Devices, Inc. All rights reserved. // // In this HDL repository, there are many different and unique modules, consisting // of various HDL (Verilog or VHDL) components. The individual modules are // developed independently, and may be accompanied by separate and unique license // terms. // // The user should read each of these license terms, and understand the // freedoms and responsibilities that he or she has by using this source/core. // // This core is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. // // Redistribution and use of source or resulting binaries, with or without modification // of this file, are permitted under one of the following two license terms: // // 1. The GNU General Public License version 2 as published by the // Free Software Foundation, which can be found in the top level directory // of this repository (LICENSE_GPL2), and also online at: // // // OR // // 2. An ADI specific BSD license, which can be found in the top level directory // of this repository (LICENSE_ADIBSD), and also on-line at: // https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD // This will allow to generate bit files and not release the source code, // as long as it attaches to an ADI device. // // *************************************************************************** // *************************************************************************** `timescale 1ns/100ps module axi_dmac_regmap #( parameter ID = 0, parameter DISABLE_DEBUG_REGISTERS = 0, parameter BYTES_PER_BEAT_WIDTH_DEST = 1, parameter BYTES_PER_BEAT_WIDTH_SRC = 1, parameter BYTES_PER_BEAT_WIDTH_SG = 1, parameter BYTES_PER_BURST_WIDTH = 7, parameter DMA_TYPE_DEST = 0, parameter DMA_TYPE_SRC = 2, parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_LENGTH_WIDTH = 24, parameter DMA_LENGTH_ALIGN = 3, parameter DMA_CYCLIC = 0, parameter HAS_DEST_ADDR = 1, parameter HAS_SRC_ADDR = 1, parameter DMA_2D_TRANSFER = 0, parameter DMA_SG_TRANSFER = 0, parameter SYNC_TRANSFER_START = 0, parameter CACHE_COHERENT_DEST = 0 ) ( // Slave AXI interface input s_axi_aclk, input s_axi_aresetn, input s_axi_awvalid, output s_axi_awready, input [10:0] s_axi_awaddr, input [2:0] s_axi_awprot, input s_axi_wvalid, output s_axi_wready, input [31:0] s_axi_wdata, input [3:0] s_axi_wstrb, output s_axi_bvalid, input s_axi_bready, output [1:0] s_axi_bresp, input s_axi_arvalid, output s_axi_arready, input [10:0] s_axi_araddr, input [2:0] s_axi_arprot, output s_axi_rvalid, input s_axi_rready, output [1:0] s_axi_rresp, output [31:0] s_axi_rdata, // Interrupt output reg irq, // Control interface output reg ctrl_enable = 1'b0, output reg ctrl_pause = 1'b0, output reg ctrl_hwdesc = 1'b0, // DMA request interface output request_valid, input request_ready, output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] request_dest_address, output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] request_src_address, output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SG] request_sg_address, output [DMA_LENGTH_WIDTH-1:0] request_x_length, output [DMA_LENGTH_WIDTH-1:0] request_y_length, output [DMA_LENGTH_WIDTH-1:0] request_dest_stride, output [DMA_LENGTH_WIDTH-1:0] request_src_stride, output request_sync_transfer_start, output request_last, // DMA response interface input response_eot, input [31:0] response_sg_desc_id, input [BYTES_PER_BURST_WIDTH-1:0] response_measured_burst_length, input response_partial, input response_valid, output response_ready, // Debug interface input [DMA_AXI_ADDR_WIDTH-1:0] dbg_src_addr, input [DMA_AXI_ADDR_WIDTH-1:0] dbg_dest_addr, input [11:0] dbg_status, input [31:0] dbg_ids0, input [31:0] dbg_ids1 ); localparam PCORE_VERSION = 'h00040561; localparam HAS_ADDR_HIGH = DMA_AXI_ADDR_WIDTH > 32; localparam ADDR_LOW_MSB = HAS_ADDR_HIGH ? 31 : DMA_AXI_ADDR_WIDTH-1; // Register interface signals reg [31:0] up_rdata = 32'h00; reg up_wack = 1'b0; reg up_rack = 1'b0; wire up_wreq; wire up_rreq; wire [31:0] up_wdata; wire [8:0] up_waddr; wire [8:0] up_raddr; wire [31:0] up_rdata_request; // Scratch register reg [31:0] up_scratch = 32'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 = 2'h3; reg [1:0] up_irq_source = 2'h0; wire [1:0] up_irq_pending; wire [1:0] up_irq_trigger; wire [1:0] up_irq_source_clear; // 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_wreq == 1'b1 && up_waddr == 9'h021) ? up_wdata[1:0] : 2'b00; always @(posedge s_axi_aclk) begin if (s_axi_aresetn == 1'b0) begin irq <= 1'b0; end else begin irq <= |up_irq_pending; end 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 always @(posedge s_axi_aclk) begin if (s_axi_aresetn == 1'b0) begin ctrl_enable <= 1'b0; ctrl_pause <= 1'b0; ctrl_hwdesc <= 1'b0; up_irq_mask <= 2'b11; up_scratch <= 32'h00; up_wack <= 1'b0; end else begin up_wack <= up_wreq; if (up_wreq == 1'b1) begin case (up_waddr) 9'h002: begin up_scratch <= up_wdata; end 9'h020: begin up_irq_mask <= up_wdata[1:0]; end 9'h100: begin ctrl_hwdesc <= up_wdata[2] & DMA_SG_TRANSFER; ctrl_pause <= up_wdata[1]; ctrl_enable <= up_wdata[0]; end endcase end end end always @(posedge s_axi_aclk) begin if (s_axi_aresetn == 1'b0) begin up_rack <= 'd0; end else begin up_rack <= up_rreq; end end always @(posedge s_axi_aclk) begin if (up_rreq == 1'b1) begin case (up_raddr) 9'h000: up_rdata <= PCORE_VERSION; 9'h001: up_rdata <= ID; 9'h002: up_rdata <= up_scratch; 9'h003: up_rdata <= 32'h444d4143; // "DMAC" 9'h004: up_rdata <= {8'b0, 4'b0,BYTES_PER_BURST_WIDTH[3:0], 2'b0,DMA_TYPE_SRC[1:0],BYTES_PER_BEAT_WIDTH_SRC[3:0], 2'b0,DMA_TYPE_DEST[1:0],BYTES_PER_BEAT_WIDTH_DEST[3:0]}; 9'h005: up_rdata <= {31'd0, CACHE_COHERENT_DEST}; 9'h020: up_rdata <= up_irq_mask; 9'h021: up_rdata <= up_irq_pending; 9'h022: up_rdata <= up_irq_source; 9'h100: up_rdata <= {ctrl_hwdesc, ctrl_pause, ctrl_enable}; 9'h10d: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_dest_addr[ADDR_LOW_MSB:0]; 9'h10e: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_src_addr[ADDR_LOW_MSB:0]; 9'h10f: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_status; 9'h110: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_ids0; 9'h111: up_rdata <= DISABLE_DEBUG_REGISTERS ? 32'h00 : dbg_ids1; 9'h126: up_rdata <= (HAS_ADDR_HIGH && !DISABLE_DEBUG_REGISTERS) ? dbg_dest_addr[DMA_AXI_ADDR_WIDTH-1:32] : 32'h00; 9'h127: up_rdata <= (HAS_ADDR_HIGH && !DISABLE_DEBUG_REGISTERS) ? dbg_src_addr[DMA_AXI_ADDR_WIDTH-1:32] : 32'h00; default: up_rdata <= up_rdata_request; endcase end end axi_dmac_regmap_request #( .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), .BYTES_PER_BEAT_WIDTH_SG(BYTES_PER_BEAT_WIDTH_SG), .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), .DMA_CYCLIC(DMA_CYCLIC), .HAS_DEST_ADDR(HAS_DEST_ADDR), .HAS_SRC_ADDR(HAS_SRC_ADDR), .DMA_2D_TRANSFER(DMA_2D_TRANSFER), .DMA_SG_TRANSFER(DMA_SG_TRANSFER), .SYNC_TRANSFER_START(SYNC_TRANSFER_START) ) i_regmap_request ( .clk(s_axi_aclk), .reset(~s_axi_aresetn), .up_sot(up_sot), .up_eot(up_eot), .up_wreq(up_wreq), .up_rreq(up_rreq), .up_waddr(up_waddr), .up_wdata(up_wdata), .up_raddr(up_raddr), .up_rdata(up_rdata_request), .ctrl_enable(ctrl_enable), .ctrl_hwdesc(ctrl_hwdesc), .request_valid(request_valid), .request_ready(request_ready), .request_dest_address(request_dest_address), .request_src_address(request_src_address), .request_sg_address(request_sg_address), .request_x_length(request_x_length), .request_y_length(request_y_length), .request_dest_stride(request_dest_stride), .request_src_stride(request_src_stride), .request_sync_transfer_start(request_sync_transfer_start), .request_last(request_last), .response_eot(response_eot), .response_sg_desc_id(response_sg_desc_id), .response_measured_burst_length(response_measured_burst_length), .response_partial(response_partial), .response_valid(response_valid), .response_ready(response_ready)); up_axi #( .AXI_ADDRESS_WIDTH (11) ) 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_wreq(up_wreq), .up_waddr(up_waddr), .up_wdata(up_wdata), .up_wack(up_wack), .up_rreq(up_rreq), .up_raddr(up_raddr), .up_rdata(up_rdata), .up_rack(up_rack)); endmodule