pluto_hdl_adi/library/axi_dmac/axi_dmac_regmap.v

326 lines
10 KiB
Verilog

// ***************************************************************************
// ***************************************************************************
// 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:
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
//
// 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