From 3038edc09a2eb15762f2e58533f429489107520b Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Wed, 6 Mar 2024 02:38:24 -0600 Subject: rtl/wb2axip: add to version control --- rtl/wb2axip/axisgdma.v | 1120 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1120 insertions(+) create mode 100644 rtl/wb2axip/axisgdma.v (limited to 'rtl/wb2axip/axisgdma.v') diff --git a/rtl/wb2axip/axisgdma.v b/rtl/wb2axip/axisgdma.v new file mode 100644 index 0000000..dac2cbc --- /dev/null +++ b/rtl/wb2axip/axisgdma.v @@ -0,0 +1,1120 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: axisgdma.v +// {{{ +// Project: WB2AXIPSP: bus bridges and other odds and ends +// +// Purpose: Scripts an AXI DMA via in-memory tables: reads from the tables, +// commands the DMA. +// +// Registers: +// +// 0. Control +// 8b KEY +// 3'b PROT +// 4'b QOS +// 1b Abort: Either aborting or aborted +// 1b Err: Ended on an error +// 1b Busy +// 1b Interrupt Enable +// 1b Interrupt Set +// 1b Start +// 1. Reserved +// 2-3. First table entry address +// (Current) table entry address on read, if in progress +// (Optional) +// 4-5. Current read address +// 6-7. Current write address +// 1. Remaining amount to be written (this entry) +// +// Table entries (must be 32-bit aligned): +// If (address_width > 30) +// 64b: { 2'bflags, 62'b SOURCE ADDRESS (bytes) } +// 00: Continue after this to next +// 01: Skip this address +// 10: Jump to new address +// 11: Last item in chain +// 64b: { int_en, 1'b0, DESTINATION ADDRESS (bytes) } +// 32b LENGTH (in bytes) +// else +// 32b: { 2'bflags, 30'b SOURCE ADDRESS (bytes) } +// 32b: { int_en, 1'b0, 30'b DESTINATION ADDRESS (bytes) } +// 32b LENGTH (in bytes) +// +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// }}} +// Copyright (C) 2020-2024, Gisselquist Technology, LLC +// {{{ +// This file is part of the WB2AXIP project. +// +// The WB2AXIP project contains free software and gateware, licensed under the +// Apache License, Version 2.0 (the "License"). You may not use this project, +// or this file, except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// `define AXI3 +// }}} +module axisgdma #( + // {{{ + parameter C_AXI_ID_WIDTH = 1, + parameter C_AXI_ADDR_WIDTH = 32, + parameter C_AXI_DATA_WIDTH = 64, + // + localparam C_AXIL_ADDR_WIDTH = 4, + localparam C_AXIL_DATA_WIDTH = 32, + // + // OPT_UNALIGNED turns on support for unaligned addresses, + // whether source, destination, or length parameters. + parameter [0:0] OPT_UNALIGNED = 1'b1, + // + // OPT_WRAPMEM controls what happens if the transfer runs off + // of the end of memory. If set, the transfer will continue + // again from the beginning of memory. If clear, the transfer + // will be aborted with an error if either read or write + // address ever get this far. + parameter [0:0] OPT_WRAPMEM = 1'b1, + // + // LGMAXBURST controls the size of the maximum burst produced + // by this core. Specifically, its the log (based 2) of that + // maximum size. Hence, for AXI4, this size must be 8 + // (i.e. 2^8 or 256 beats) or less. For AXI3, the size must + // be 4 or less. Tests have verified performance for + // LGMAXBURST as low as 2. While I expect it to fail at + // LGMAXBURST=0, I haven't verified at what value this burst + // parameter is too small. +`ifdef AXI3 + parameter LGMAXBURST=4, // 16 beats max +`else + parameter LGMAXBURST=8, // 256 beats +`endif + // + // LGFIFO: This is the (log-based-2) size of the internal FIFO. + // Hence if LGFIFO=8, the internal FIFO will have 256 elements + // (words) in it. High throughput transfers are accomplished + // by first storing data into a FIFO, then once a full burst + // size is available bursting that data over the bus. In + // order to be able to keep receiving data while bursting it + // out, the FIFO size must be at least twice the size of the + // maximum burst size. Larger sizes are possible as well. + parameter LGFIFO = LGMAXBURST+1, // 512 element FIFO + // + // LGLEN: specifies the number of bits in the transfer length + // register. If a transfer cannot be specified in LGLEN bits, + // it won't happen. LGLEN must be less than or equal to the + // address width. + parameter LGLEN = C_AXI_ADDR_WIDTH, + // + // AXI uses ID's to transfer information. This core rather + // ignores them. Instead, it uses a constant ID for all + // transfers. The following two parameters control that ID. + parameter [C_AXI_ID_WIDTH-1:0] DMA_READ_ID = 0, + parameter [C_AXI_ID_WIDTH-1:0] DMA_WRITE_ID = 0, + parameter [C_AXI_ID_WIDTH-1:0] PF_READ_ID = DMA_READ_ID+1, + // + // The "ABORT_KEY" is a byte that, if written to the control + // word while the core is running, will cause the data transfer + // to be aborted. + parameter [7:0] ABORT_KEY = 8'h6d, + // + // OPT_LOWPOWER + parameter [0:0] OPT_LOWPOWER = 1'b0 + // }}} + ) ( + // {{{ + input wire S_AXI_ACLK, + input wire S_AXI_ARESETN, + // + // The AXI4-lite control interface + input wire S_AXIL_AWVALID, + output wire S_AXIL_AWREADY, + input wire [C_AXIL_ADDR_WIDTH-1:0] S_AXIL_AWADDR, + input wire [2:0] S_AXIL_AWPROT, + // + input wire S_AXIL_WVALID, + output wire S_AXIL_WREADY, + input wire [C_AXIL_DATA_WIDTH-1:0] S_AXIL_WDATA, + input wire [C_AXIL_DATA_WIDTH/8-1:0] S_AXIL_WSTRB, + // + output reg S_AXIL_BVALID, + input wire S_AXIL_BREADY, + output wire [1:0] S_AXIL_BRESP, + // + input wire S_AXIL_ARVALID, + output wire S_AXIL_ARREADY, + input wire [C_AXIL_ADDR_WIDTH-1:0] S_AXIL_ARADDR, + input wire [2:0] S_AXIL_ARPROT, + // + output reg S_AXIL_RVALID, + input wire S_AXIL_RREADY, + output reg [C_AXIL_DATA_WIDTH-1:0] S_AXIL_RDATA, + output wire [1:0] S_AXIL_RRESP, + // + // + // The AXI Master (DMA) interface + output wire M_AXI_AWVALID, + input wire M_AXI_AWREADY, + output wire [C_AXI_ID_WIDTH-1:0] M_AXI_AWID, + output wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR, +`ifdef AXI3 + output wire [3:0] M_AXI_AWLEN, +`else + output wire [7:0] M_AXI_AWLEN, +`endif + output wire [2:0] M_AXI_AWSIZE, + output wire [1:0] M_AXI_AWBURST, +`ifdef AXI3 + output wire [1:0] M_AXI_AWLOCK, +`else + output wire M_AXI_AWLOCK, +`endif + output wire [3:0] M_AXI_AWCACHE, + output wire [2:0] M_AXI_AWPROT, + output wire [3:0] M_AXI_AWQOS, + // + // + output wire M_AXI_WVALID, + input wire M_AXI_WREADY, +`ifdef AXI3 + output wire [C_AXI_ID_WIDTH-1:0] M_AXI_WID, +`endif + output wire [C_AXI_DATA_WIDTH-1:0] M_AXI_WDATA, + output wire [C_AXI_DATA_WIDTH/8-1:0] M_AXI_WSTRB, + output wire M_AXI_WLAST, + // + // + input wire M_AXI_BVALID, + output reg M_AXI_BREADY, + input wire [C_AXI_ID_WIDTH-1:0] M_AXI_BID, + input wire [1:0] M_AXI_BRESP, + // + // + output wire M_AXI_ARVALID, + input wire M_AXI_ARREADY, + output wire [C_AXI_ID_WIDTH-1:0] M_AXI_ARID, + output wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR, +`ifdef AXI3 + output wire [3:0] M_AXI_ARLEN, +`else + output wire [7:0] M_AXI_ARLEN, +`endif + output wire [2:0] M_AXI_ARSIZE, + output wire [1:0] M_AXI_ARBURST, +`ifdef AXI3 + output wire [1:0] M_AXI_ARLOCK, +`else + output wire M_AXI_ARLOCK, +`endif + output wire [3:0] M_AXI_ARCACHE, + output wire [2:0] M_AXI_ARPROT, + output wire [3:0] M_AXI_ARQOS, + // + input wire M_AXI_RVALID, + output wire M_AXI_RREADY, + input wire [C_AXI_ID_WIDTH-1:0] M_AXI_RID, + input wire [C_AXI_DATA_WIDTH-1:0] M_AXI_RDATA, + input wire M_AXI_RLAST, + input wire [1:0] M_AXI_RRESP, + // + output reg o_int + // }}} + ); + + // Local parameter definitions + // {{{ + // The number of beats in this maximum burst size is + // automatically determined from LGMAXBURST, and so its + // forced to be a power of two this way. + // localparam MAXBURST=(1< C_AXIL_DATA_WIDTH) begin + r_tbl_addr <= new_widetbl[C_AXI_ADDR_WIDTH-1:0]; + end + default: begin end + endcase + end else if (r_busy) + begin + r_tbl_addr <= tbl_addr; + end + // }}} + + // apply_wstrb function + // {{{ + function [C_AXIL_DATA_WIDTH-1:0] apply_wstrb; + input [C_AXIL_DATA_WIDTH-1:0] prior_data; + input [C_AXIL_DATA_WIDTH-1:0] new_data; + input [C_AXIL_DATA_WIDTH/8-1:0] wstrb; + + integer k; + for(k=0; k