Files
b210-k7-fpga/lib/axi/axi_dma_fifo.v
T
+18 6b67702ad7 Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce
the size of the repository. However, over the last half-decade, the
split between the repositories has proven more burdensome than it has
been helpful. By merging the FPGA code back, it will be possible to
create atomic commits that touch both FPGA and UHD codebases. Continuous
integration testing is also simplified by merging the repositories,
because it was previously difficult to automatically derive the correct
UHD branch when testing a feature branch on the FPGA repository.

This commit also updates the license files and paths therein.

We are therefore merging the repositories again. Future development for
FPGA code will happen in the same repository as the UHD host code and
MPM code.

== Original Codebase and Rebasing ==

The original FPGA repository will be hosted for the foreseeable future
at its original local location: https://github.com/EttusResearch/fpga/

It can be used for bisecting, reference, and a more detailed history.

The final commit from said repository to be merged here is
05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as
v4.0.0.0-pre-uhd-merge.

If you have changes in the FPGA repository that you want to rebase onto
the UHD repository, simply run the following commands:

- Create a directory to store patches (this should be an empty
  directory):

    mkdir ~/patches

- Now make sure that your FPGA codebase is based on the same state as
  the code that was merged:

    cd src/fpga # Or wherever your FPGA code is stored
    git rebase v4.0.0.0-pre-uhd-merge

  Note: The rebase command may look slightly different depending on what
  exactly you're trying to rebase.

- Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge:

    git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches

  Note: Make sure that only patches are stored in your output directory.
  It should otherwise be empty. Make sure that you picked the correct
  range of commits, and only commits you wanted to rebase were exported
  as patch files.

- Go to the UHD repository and apply the patches:

    cd src/uhd # Or wherever your UHD repository is stored
    git am --directory fpga ~/patches/*
    rm -rf ~/patches # This is for cleanup

== Contributors ==

The following people have contributed mainly to these files (this list
is not complete):

Co-authored-by: Alex Williams <alex.williams@ni.com>
Co-authored-by: Andrej Rode <andrej.rode@ettus.com>
Co-authored-by: Ashish Chaudhari <ashish@ettus.com>
Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Derek Kozel <derek.kozel@ettus.com>
Co-authored-by: EJ Kreinar <ej@he360.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Ian Buckley <ian.buckley@gmail.com>
Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Jon Kiser <jon.kiser@ni.com>
Co-authored-by: Josh Blum <josh@joshknows.com>
Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Matt Ettus <matt@ettus.com>
Co-authored-by: Michael West <michael.west@ettus.com>
Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com>
Co-authored-by: Nick Foster <nick@ettus.com>
Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Paul David <paul.david@ettus.com>
Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com>
Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com>
Co-authored-by: Sylvain Munaut <tnt@246tNt.com>
Co-authored-by: Trung Tran <trung.tran@ettus.com>
Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>


Original-commit: bafa9d95453387814ef25e6b6256ba8db2df612f
2020-01-28 09:35:36 -08:00

1074 lines
43 KiB
Verilog

//
// Copyright 2015 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
//
// There are various obligations put on this code not present in regular BRAM based FIFO's
//
// 1) Bursts are way more efficient, use local small FIFO's to interact with DRAM
// 2) Never cross a 4KByte address boundary within a single transaction, this is an AXI4 rule.
// 3) 2^SIZE must be greater than 4KB so that the 4KByte page protection also deals with FIFO wrap corner case.
//
module axi_dma_fifo
#(
parameter SIMULATION = 0, // Shorten flush counter for simulation
parameter DEFAULT_BASE = 30'h00000000,
parameter DEFAULT_MASK = 30'hFF000000,
parameter DEFAULT_TIMEOUT = 12'd256,
parameter BUS_CLK_RATE = 32'd166666666, // Frequency in Hz of bus_clk
parameter SR_BASE = 0, // Base address for settings registers
parameter EXT_BIST = 0, // If 1 then instantiate extended BIST with dynamic SID, delays and BW counters
parameter MAX_PKT_LEN = 12 // Log2 of maximum packet length
) (
input bus_clk,
input bus_reset,
input dram_clk,
input dram_reset,
//
// AXI Write address channel
//
output [0 : 0] m_axi_awid, // Write address ID. This signal is the identification tag for the write address signals
output [31 : 0] m_axi_awaddr, // Write address. The write address gives the address of the first transfer in a write burst
output [7 : 0] m_axi_awlen, // Burst length. The burst length gives the exact number of transfers in a burst.
output [2 : 0] m_axi_awsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_awburst, // Burst type. The burst type and the size information, determine how the address is calculated
output [0 : 0] m_axi_awlock, // Lock type. Provides additional information about the atomic characteristics of the transfer.
output [3 : 0] m_axi_awcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_awprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_awqos, // Quality of Service, QoS. The QoS identifier sent for each write transaction
output [3 : 0] m_axi_awregion, // Region identifier. Permits a single physical interface on a slave to be re-used.
output [0 : 0] m_axi_awuser, // User signal. Optional User-defined signal in the write address channel.
output m_axi_awvalid, // Write address valid. This signal indicates that the channel is signaling valid write addr
input m_axi_awready, // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
output [63 : 0] m_axi_wdata, // Write data
output [7 : 0] m_axi_wstrb, // Write strobes. This signal indicates which byte lanes hold valid data.
output m_axi_wlast, // Write last. This signal indicates the last transfer in a write burst
output [0 : 0] m_axi_wuser, // User signal. Optional User-defined signal in the write data channel.
output m_axi_wvalid, // Write valid. This signal indicates that valid write data and strobes are available.
input m_axi_wready, // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
input [0 : 0] m_axi_bid, // Response ID tag. This signal is the ID tag of the write response.
input [1 : 0] m_axi_bresp, // Write response. This signal indicates the status of the write transaction.
input [0 : 0] m_axi_buser, // User signal. Optional User-defined signal in the write response channel.
input m_axi_bvalid, // Write response valid. This signal indicates that the channel is signaling a valid response
output m_axi_bready, // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
output [0 : 0] m_axi_arid, // Read address ID. This signal is the identification tag for the read address group of signals
output [31 : 0] m_axi_araddr, // Read address. The read address gives the address of the first transfer in a read burst
output [7 : 0] m_axi_arlen, // Burst length. This signal indicates the exact number of transfers in a burst.
output [2 : 0] m_axi_arsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_arburst, // Burst type. The burst type and the size information determine how the address for each transfer
output [0 : 0] m_axi_arlock, // Lock type. This signal provides additional information about the atomic characteristics
output [3 : 0] m_axi_arcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_arprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_arqos, // Quality of Service, QoS. QoS identifier sent for each read transaction.
output [3 : 0] m_axi_arregion, // Region identifier. Permits a single physical interface on a slave to be re-used
output [0 : 0] m_axi_aruser, // User signal. Optional User-defined signal in the read address channel.
output m_axi_arvalid, // Read address valid. This signal indicates that the channel is signaling valid read addr
input m_axi_arready, // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
input [0 : 0] m_axi_rid, // Read ID tag. This signal is the identification tag for the read data group of signals
input [63 : 0] m_axi_rdata, // Read data.
input [1 : 0] m_axi_rresp, // Read response. This signal indicates the status of the read transfer
input m_axi_rlast, // Read last. This signal indicates the last transfer in a read burst.
input [0 : 0] m_axi_ruser, // User signal. Optional User-defined signal in the read data channel.
input m_axi_rvalid, // Read valid. This signal indicates that the channel is signaling the required read data.
output m_axi_rready, // Read ready. This signal indicates that the master can accept the read data and response
//
// CHDR friendly AXI stream input
//
input [63:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
//
// CHDR friendly AXI Stream output
//
output [63:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready,
//
// Settings and Readback
//
input set_stb,
input [7:0] set_addr,
input [31:0] set_data,
output reg [31:0] rb_data,
//
// Debug Bus
//
output [197:0] debug
);
//
// We are only solving for width 64bits here, since it's our standard CHDR quanta
//
localparam DWIDTH = 64;
localparam AWIDTH = 30; //Can address 1GiB of memory
//
// Settings and Readback
//
wire [2:0] rb_addr;
wire clear_bclk, flush_bclk;
wire supress_enable_bclk;
wire [15:0] supress_threshold_bclk;
wire [11:0] timeout_bclk;
wire [AWIDTH-1:0] fifo_base_addr_bclk;
wire [AWIDTH-1:0] fifo_addr_mask_bclk;
wire [0:0] ctrl_reserved;
wire [31:0] rb_fifo_status;
wire [3:0] rb_bist_status;
wire [95:0] rb_bist_bw_ratio;
reg [31:0] out_pkt_count = 32'd0;
localparam RB_FIFO_STATUS = 3'd0;
localparam RB_BIST_STATUS = 3'd1;
localparam RB_BIST_XFER_CNT = 3'd2;
localparam RB_BIST_CYC_CNT = 3'd3;
localparam RB_BUS_CLK_RATE = 3'd4;
localparam RB_OUT_PKT_CNT = 3'd5;
// SETTING: Readback Address Register
// Fields:
// - [2:0] : Address for readback register
// - 0 = RB_FIFO_STATUS
// - 1 = RB_BIST_STATUS
// - 2 = RB_BIST_XFER_CNT
// - 3 = RB_BIST_CYC_CNT
// - 4 = RB_BUS_CLK_RATE
// - rest reserved
setting_reg #(.my_addr(SR_BASE + 0), .awidth(8), .width(3), .at_reset(3'b000)) sr_readback
(.clk(bus_clk), .rst(bus_reset),
.strobe(set_stb), .addr(set_addr), .in(set_data),
.out(rb_addr), .changed());
// SETTING: FIFO Control Register
// Fields:
// - [0] : Clear FIFO and discard stored data
// - [1] : Enable read suppression to prioritize writes
// - [2] : Flush all packets from the FIFO
// - [3] : Reserved
// - [15:4] : Timeout (in memory clock beats) for issuing smaller than optimal bursts
// - [31:16] : Read suppression threshold in number of words
setting_reg #(.my_addr(SR_BASE + 1), .awidth(8), .width(32), .at_reset({16'h0, DEFAULT_TIMEOUT[11:0], 1'b0, 1'b0, 1'b0, 1'b1})) sr_fifo_ctrl
(.clk(bus_clk), .rst(bus_reset),
.strobe(set_stb), .addr(set_addr), .in(set_data),
.out({supress_threshold_bclk, timeout_bclk, ctrl_reserved, flush_bclk, supress_enable_bclk, clear_bclk}), .changed());
// SETTING: Base Address for FIFO in memory space
// Fields:
// - [29:0] : Base address
setting_reg #(.my_addr(SR_BASE + 2), .awidth(8), .width(AWIDTH), .at_reset(DEFAULT_BASE)) sr_fifo_base_addr
(.clk(bus_clk), .rst(bus_reset),
.strobe(set_stb), .addr(set_addr), .in(set_data),
.out(fifo_base_addr_bclk), .changed());
// SETTING: Address Mask for FIFO in memory space. The mask is ANDed with the base address to define
// a unique address for this FIFO. A zero in the mask signifies that the DRAM FIFO can
// utilize the address bit internally for maintaining FIFO data
// Fields:
// - [29:0] : Address mask
setting_reg #(.my_addr(SR_BASE + 3), .awidth(8), .width(AWIDTH), .at_reset(DEFAULT_MASK)) sr_fifo_addr_mask
(.clk(bus_clk), .rst(bus_reset),
.strobe(set_stb), .addr(set_addr), .in(set_data),
.out(fifo_addr_mask_bclk), .changed());
always @(*) begin
case(rb_addr)
RB_FIFO_STATUS: rb_data = rb_fifo_status;
RB_BIST_STATUS: rb_data = {(EXT_BIST?1'b1:1'b0), 27'h0, rb_bist_status};
RB_BIST_XFER_CNT: rb_data = rb_bist_bw_ratio[79:48];
RB_BIST_CYC_CNT: rb_data = rb_bist_bw_ratio[31:0];
RB_BUS_CLK_RATE: rb_data = BUS_CLK_RATE;
RB_OUT_PKT_CNT: rb_data = out_pkt_count;
default: rb_data = 32'h0;
endcase
end
//
// Synchronize settings register values to dram_clk
//
wire clear;
synchronizer #(.INITIAL_VAL(1'b1)) clear_sync_inst (.clk(dram_clk), .rst(1'b0), .in(clear_bclk), .out(clear));
wire set_suppress_en;
wire [15:0] set_supress_threshold;
wire [11:0] set_timeout;
wire [AWIDTH-1:0] set_fifo_base_addr, set_fifo_addr_mask, set_fifo_addr_mask_bar;
wire [(72-AWIDTH-29-1):0] set_sync_discard0;
wire [(72-(2*AWIDTH)-1):0] set_sync_discard1;
fifo_short_2clk set_sync_fifo0(
.rst(bus_reset),
.wr_clk(bus_clk), .din({{(72-AWIDTH-29){1'b0}}, timeout_bclk, supress_enable_bclk, supress_threshold_bclk, fifo_base_addr_bclk}),
.wr_en(1'b1), .full(), .wr_data_count(),
.rd_clk(dram_clk), .dout({set_sync_discard0, set_timeout, set_suppress_en, set_supress_threshold, set_fifo_base_addr}),
.rd_en(1'b1), .empty(), .rd_data_count()
);
fifo_short_2clk set_sync_fifo1(
.rst(bus_reset),
.wr_clk(bus_clk), .din({{(72-(2*AWIDTH)){1'b0}}, ~fifo_addr_mask_bclk, fifo_addr_mask_bclk}),
.wr_en(1'b1), .full(), .wr_data_count(),
.rd_clk(dram_clk), .dout({set_sync_discard1, set_fifo_addr_mask_bar, set_fifo_addr_mask}),
.rd_en(1'b1), .empty(), .rd_data_count()
);
//
// Input side declarations
//
localparam [2:0] INPUT_IDLE = 0;
localparam [2:0] INPUT1 = 1;
localparam [2:0] INPUT2 = 2;
localparam [2:0] INPUT3 = 3;
localparam [2:0] INPUT4 = 4;
localparam [2:0] INPUT5 = 5;
localparam [2:0] INPUT6 = 6;
reg [2:0] input_state;
reg input_timeout_triggered;
reg input_timeout_reset;
reg [8:0] input_timeout_count;
reg [AWIDTH-1:0] write_addr;
reg write_ctrl_valid;
wire write_ctrl_ready;
reg [7:0] write_count = 8'd0;
reg [8:0] write_count_plus_one = 9'd1; // Maintain a +1 version to break critical timing paths
reg update_write;
//
// Output side declarations
//
localparam [2:0] OUTPUT_IDLE = 0;
localparam [2:0] OUTPUT1 = 1;
localparam [2:0] OUTPUT2 = 2;
localparam [2:0] OUTPUT3 = 3;
localparam [2:0] OUTPUT4 = 4;
localparam [2:0] OUTPUT5 = 5;
localparam [2:0] OUTPUT6 = 6;
reg [2:0] output_state;
reg output_timeout_triggered;
reg output_timeout_reset;
reg [8:0] output_timeout_count;
reg [AWIDTH-1:0] read_addr;
reg read_ctrl_valid;
wire read_ctrl_ready;
reg [7:0] read_count = 8'd0;
reg [8:0] read_count_plus_one = 9'd1; // Maintain a +1 version to break critical timing paths
reg update_read;
// Track main FIFO active size.
reg [AWIDTH-3:0] space, occupied, occupied_minus_one; // Maintain a -1 version to break critical timing paths
reg [AWIDTH-3:0] input_page_boundry, output_page_boundry; // Cache in a register to break critical timing paths
// Assign FIFO status bits
wire [71:0] status_out_bclk;
fifo_short_2clk status_fifo_2clk(
.rst(dram_reset),
.wr_clk(dram_clk), .din({{(72-(AWIDTH-2)){1'b0}}, occupied}),
.wr_en(1'b1), .full(), .wr_data_count(),
.rd_clk(bus_clk), .dout(status_out_bclk),
.rd_en(1'b1), .empty(), .rd_data_count()
);
assign rb_fifo_status[31] = 1'b1; //DRAM FIFO signature (validates existence of DRAM FIFO)
assign rb_fifo_status[30:27] = {o_tvalid, o_tready, i_tvalid, i_tready}; //Ready valid flags
assign rb_fifo_status[26:0] = status_out_bclk[26:0]; //FIFO fullness count in 64bit words (max 27 bits = 1GiB)
///////////////////////////////////////////////////////////////////////////////
// Inline BIST for production testing
//
wire i_tready_int;
wire [DWIDTH-1:0] i_tdata_fifo;
wire i_tvalid_fifo, i_tready_fifo, i_tlast_fifo;
wire [DWIDTH-1:0] i_tdata_bist;
wire i_tvalid_bist, i_tready_bist, i_tlast_bist;
wire [DWIDTH-1:0] o_tdata_int;
wire o_tvalid_int, o_tready_int, o_tlast_int;
wire [DWIDTH-1:0] o_tdata_fifo;
wire o_tvalid_fifo, o_tready_fifo, o_tlast_fifo;
wire [DWIDTH-1:0] o_tdata_bist;
wire o_tvalid_bist, o_tready_bist, o_tlast_bist;
wire [DWIDTH-1:0] o_tdata_gate;
wire o_tvalid_gate, o_tready_gate, o_tlast_gate;
axi_mux4 #(.PRIO(1), .WIDTH(DWIDTH), .BUFFER(1)) axi_mux (
.clk(bus_clk), .reset(bus_reset), .clear(clear_bclk),
.i0_tdata(i_tdata), .i0_tlast(i_tlast), .i0_tvalid(i_tvalid), .i0_tready(i_tready_int),
.i1_tdata(i_tdata_bist), .i1_tlast(i_tlast_bist), .i1_tvalid(i_tvalid_bist), .i1_tready(i_tready_bist),
.i2_tdata({DWIDTH{1'b0}}), .i2_tlast(1'b0), .i2_tvalid(1'b0), .i2_tready(),
.i3_tdata({DWIDTH{1'b0}}), .i3_tlast(1'b0), .i3_tvalid(1'b0), .i3_tready(),
.o_tdata(i_tdata_fifo), .o_tlast(i_tlast_fifo), .o_tvalid(i_tvalid_fifo), .o_tready(i_tready_fifo)
);
assign i_tready = i_tready_int & (~clear_bclk);
wire bist_running, bist_done;
wire [1:0] bist_error;
axi_chdr_test_pattern #(
.DELAY_MODE(EXT_BIST ? "DYNAMIC" : "STATIC"),
.SID_MODE(EXT_BIST ? "DYNAMIC" : "STATIC"),
.BW_COUNTER(EXT_BIST ? 1 : 0),
.SR_BASE(SR_BASE + 4)
) axi_chdr_test_pattern_i (
.clk(bus_clk), .reset(bus_reset | clear_bclk),
.i_tdata(i_tdata_bist), .i_tlast(i_tlast_bist), .i_tvalid(i_tvalid_bist), .i_tready(i_tready_bist),
.o_tdata(o_tdata_bist), .o_tlast(o_tlast_bist), .o_tvalid(o_tvalid_bist), .o_tready(o_tready_bist),
.set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
.running(bist_running), .done(bist_done), .error(bist_error), .status_vtr(), .bw_ratio(rb_bist_bw_ratio)
);
assign rb_bist_status = {bist_error, bist_done, bist_running};
axi_demux4 #(.ACTIVE_CHAN(4'b0011), .WIDTH(DWIDTH)) axi_demux(
.clk(bus_clk), .reset(bus_reset), .clear(clear_bclk),
.header(), .dest({1'b0, bist_running}),
.i_tdata(o_tdata_fifo), .i_tlast(o_tlast_fifo), .i_tvalid(o_tvalid_fifo), .i_tready(o_tready_fifo),
.o0_tdata(o_tdata_gate), .o0_tlast(o_tlast_gate), .o0_tvalid(o_tvalid_gate), .o0_tready(o_tready_gate),
.o1_tdata(o_tdata_bist), .o1_tlast(o_tlast_bist), .o1_tvalid(o_tvalid_bist), .o1_tready(o_tready_bist),
.o2_tdata(), .o2_tlast(), .o2_tvalid(), .o2_tready(1'b0),
.o3_tdata(), .o3_tlast(), .o3_tvalid(), .o3_tready(1'b0)
);
//Insert package gate before output to absorb any intra-packet bubble cycles
axi_packet_gate #(.WIDTH(DWIDTH), .SIZE(MAX_PKT_LEN)) out_pkt_gate (
.clk(bus_clk), .reset(bus_reset), .clear(clear_bclk),
.i_tdata(o_tdata_gate), .i_tlast(o_tlast_gate), .i_tvalid(o_tvalid_gate), .i_tready(o_tready_gate),
.i_terror(1'b0),
.o_tdata(o_tdata_int), .o_tlast(o_tlast_int), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int)
);
axis_packet_flush #(
.WIDTH(DWIDTH), .FLUSH_PARTIAL_PKTS(0), .TIMEOUT_W(1), .PIPELINE("NONE")
) flusher_i (
.clk(bus_clk), .reset(bus_reset),
.enable(clear_bclk | flush_bclk), .timeout(1'b0), .flushing(), .done(),
.s_axis_tdata(o_tdata_int), .s_axis_tlast(o_tlast_int),
.s_axis_tvalid(o_tvalid_int), .s_axis_tready(o_tready_int),
.m_axis_tdata(o_tdata), .m_axis_tlast(o_tlast),
.m_axis_tvalid(o_tvalid), .m_axis_tready(o_tready)
);
always @(posedge bus_clk) begin
if (bus_reset) begin
out_pkt_count <= 32'd0;
end else if (o_tlast_int & o_tvalid_int & o_tready_int) begin
out_pkt_count <= out_pkt_count + 32'd1;
end
end
//
// Buffer input in FIFO's. Embeded tlast signal using ESCape code.
//
wire [DWIDTH-1:0] i_tdata_i0;
wire i_tvalid_i0, i_tready_i0, i_tlast_i0;
wire [DWIDTH-1:0] i_tdata_i1;
wire i_tvalid_i1, i_tready_i1, i_tlast_i1;
wire [DWIDTH-1:0] i_tdata_i2;
wire i_tvalid_i2, i_tready_i2;
wire [DWIDTH-1:0] i_tdata_i3;
wire i_tvalid_i3, i_tready_i3;
wire [DWIDTH-1:0] i_tdata_input;
wire i_tvalid_input, i_tready_input;
wire [15:0] space_input, occupied_input;
reg [15:0] space_input_reg;
reg supress_reads;
///////////////////////////////////////////////////////////////////////////////
wire write_in, read_in, empty_in, full_in;
assign i_tready_fifo = ~full_in;
assign write_in = i_tvalid_fifo & i_tready_fifo;
assign i_tvalid_i0 = ~empty_in;
assign read_in = i_tvalid_i0 & i_tready_i0;
wire [6:0] discard_i0;
fifo_short_2clk fifo_short_2clk_i0 (
.rst(bus_reset),
.wr_clk(bus_clk),
.din({7'h0,i_tlast_fifo,i_tdata_fifo}), // input [71 : 0] din
.wr_en(write_in), // input wr_en
.full(full_in), // output full
.wr_data_count(), // output [9 : 0] wr_data_count
.rd_clk(dram_clk), // input rd_clk
.dout({discard_i0,i_tlast_i0,i_tdata_i0}), // output [71 : 0] dout
.rd_en(read_in), // input rd_en
.empty(empty_in), // output empty
.rd_data_count() // output [9 : 0] rd_data_count
);
axi_fifo_flop2 #(.WIDTH(DWIDTH+1)) input_pipe_i0
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata({i_tlast_i0, i_tdata_i0}),
.i_tvalid(i_tvalid_i0),
.i_tready(i_tready_i0),
//
.o_tdata({i_tlast_i1, i_tdata_i1}),
.o_tvalid(i_tvalid_i1),
.o_tready(i_tready_i1)
);
axi_embed_tlast #(.WIDTH(DWIDTH), .ADD_CHECKSUM(0)) axi_embed_tlast_i (
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(i_tdata_i1),
.i_tlast(i_tlast_i1),
.i_tvalid(i_tvalid_i1),
.i_tready(i_tready_i1),
//
.o_tdata(i_tdata_i2),
.o_tvalid(i_tvalid_i2),
.o_tready(i_tready_i2)
);
axi_fifo_flop2 #(.WIDTH(DWIDTH)) input_pipe_i1 (
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(i_tdata_i2),
.i_tvalid(i_tvalid_i2),
.i_tready(i_tready_i2),
//
.o_tdata(i_tdata_i3),
.o_tvalid(i_tvalid_i3),
.o_tready(i_tready_i3)
);
axi_fifo #(.WIDTH(DWIDTH),.SIZE(10)) fifo_i1 (
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(i_tdata_i3),
.i_tvalid(i_tvalid_i3),
.i_tready(i_tready_i3),
//
.o_tdata(i_tdata_input),
.o_tvalid(i_tvalid_input),
.o_tready(i_tready_input),
//
.space(space_input),
.occupied(occupied_input)
);
//
// Monitor occupied_input to deduce when DRAM FIFO is running short of bandwidth and there is a danger of backpressure
// passing upstream of the DRAM FIFO.
// In this situation supress read requests to the DRAM FIFO so that more bandwidth is available to writes.
//
always @(posedge dram_clk)
begin
space_input_reg <= space_input;
if ((space_input_reg < set_supress_threshold[15:0]) && set_suppress_en)
supress_reads <= 1'b1;
else
supress_reads <= 1'b0;
end
//
// Buffer output in 32entry FIFO's. Extract embeded tlast signal.
//
wire [DWIDTH-1:0] o_tdata_output;
wire o_tvalid_output, o_tready_output;
wire [15:0] space_output, occupied_output;
wire [DWIDTH-1:0] o_tdata_i0;
wire o_tvalid_i0, o_tready_i0;
wire [DWIDTH-1:0] o_tdata_i1;
wire o_tvalid_i1, o_tready_i1;
wire [DWIDTH-1:0] o_tdata_i2;
wire o_tvalid_i2, o_tready_i2;
wire [DWIDTH-1:0] o_tdata_i3;
wire o_tvalid_i3, o_tready_i3;
wire [DWIDTH-1:0] o_tdata_i4;
wire o_tvalid_i4, o_tready_i4, o_tlast_i4;
wire [DWIDTH-1:0] o_tdata_i5;
wire o_tvalid_i5, o_tready_i5, o_tlast_i5;
wire checksum_error;
axi_fifo #(.WIDTH(DWIDTH),.SIZE(10)) fifo_i2 (
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_output),
.i_tvalid(o_tvalid_output),
.i_tready(o_tready_output),
//
.o_tdata(o_tdata_i0),
.o_tvalid(o_tvalid_i0),
.o_tready(o_tready_i0),
//
.space(space_output),
.occupied(occupied_output)
);
// Place FLops straight after SRAM read access for timing.
axi_fifo_flop2 #(.WIDTH(DWIDTH)) output_pipe_i0
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i0),
.i_tvalid(o_tvalid_i0),
.i_tready(o_tready_i0),
//
.o_tdata(o_tdata_i1),
.o_tvalid(o_tvalid_i1),
.o_tready(o_tready_i1 && ~supress_reads)
);
// Read suppression logic
// The CL part of this exists between these
// axi_flops
axi_fifo_flop2 #(.WIDTH(DWIDTH)) output_pipe_i1
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i1),
.i_tvalid(o_tvalid_i1 && ~supress_reads),
.i_tready(o_tready_i1),
//
.o_tdata(o_tdata_i2),
.o_tvalid(o_tvalid_i2),
.o_tready(o_tready_i2)
);
// Pipeline flop before tlast extraction logic
axi_fifo_flop2 #(.WIDTH(DWIDTH)) output_pipe_i2
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i2),
.i_tvalid(o_tvalid_i2),
.i_tready(o_tready_i2),
//
.o_tdata(o_tdata_i3),
.o_tvalid(o_tvalid_i3),
.o_tready(o_tready_i3)
);
axi_extract_tlast #(.WIDTH(DWIDTH), .VALIDATE_CHECKSUM(0)) axi_extract_tlast_i (
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata(o_tdata_i3),
.i_tvalid(o_tvalid_i3),
.i_tready(o_tready_i3),
//
.o_tdata(o_tdata_i4),
.o_tlast(o_tlast_i4),
.o_tvalid(o_tvalid_i4),
.o_tready(o_tready_i4),
//
.checksum_error()
);
// Pipeline flop after tlast extraction logic
axi_fifo_flop2 #(.WIDTH(DWIDTH+1)) output_pipe_i3
(
.clk(dram_clk),
.reset(dram_reset),
.clear(clear),
//
.i_tdata({o_tlast_i4,o_tdata_i4}),
.i_tvalid(o_tvalid_i4),
.i_tready(o_tready_i4),
//
.o_tdata({o_tlast_i5,o_tdata_i5}),
.o_tvalid(o_tvalid_i5),
.o_tready(o_tready_i5)
);
wire write_out, read_out, empty_out, full_out;
assign o_tready_i5 = ~full_out;
assign write_out = o_tvalid_i5 & o_tready_i5;
assign o_tvalid_fifo = ~empty_out;
assign read_out = o_tvalid_fifo & o_tready_fifo;
wire [6:0] discard_i1;
fifo_short_2clk fifo_short_2clk_i1 (
.rst(dram_reset),
.wr_clk(dram_clk),
.din({7'h0,o_tlast_i5,o_tdata_i5}), // input [71 : 0] din
.wr_en(write_out), // input wr_en
.full(full_out), // output full
.wr_data_count(), // output [9 : 0] wr_data_count
.rd_clk(bus_clk), // input rd_clk
.dout({discard_i1,o_tlast_fifo,o_tdata_fifo}), // output [71 : 0] dout
.rd_en(read_out), // input rd_en
.empty(empty_out), // output empty
.rd_data_count() // output [9 : 0] rd_data_count
);
//
// Simple input timeout counter for now.
// Timeout count only increments when there is some data waiting to be written.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
input_timeout_count <= 9'd0;
input_timeout_triggered <= 1'b0;
end else if (input_timeout_reset) begin
input_timeout_count <= 9'd0;
input_timeout_triggered <= 1'b0;
end else if (input_timeout_count == set_timeout[8:0]) begin
input_timeout_triggered <= 1'b1;
end else if (input_state == INPUT_IDLE) begin
input_timeout_count <= input_timeout_count + ((occupied_input != 16'd0) ? 9'd1 : 9'd0);
end
//
// Wait for 16 entries in input FIFO to trigger DRAM write burst.
// Timeout can also trigger burst so fragments of data are not left to rot in the input FIFO.
// Also if enough data is present in the input FIFO to complete a burst upto the edge
// of a 4KByte page then immediately start the burst.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
input_state <= INPUT_IDLE;
write_addr <= set_fifo_base_addr & set_fifo_addr_mask;
input_timeout_reset <= 1'b0;
write_ctrl_valid <= 1'b0;
write_count <= 8'd0;
write_count_plus_one <= 9'd1;
update_write <= 1'b0;
end else
case (input_state)
//
// INPUT_IDLE.
// To start an input transfer to DRAM need:
// 1) Space in the DRAM FIFO
// and either
// 2) 256 entrys in the input FIFO
// or
// 3) Timeout waiting for more data.
//
INPUT_IDLE: begin
write_ctrl_valid <= 1'b0;
update_write <= 1'b0;
if (space[AWIDTH-3:8] != 'd0) begin // (space > 255): Space in the DRAM FIFO
if (occupied_input[15:8] != 'd0) begin // (occupied_input > 255): 256 or more entries in input FIFO
input_state <= INPUT1;
input_timeout_reset <= 1'b1;
// Calculate number of entries remaining until next 4KB page boundry is crossed minus 1.
// Note, units of calculation are 64bit wide words. Address is always 64bit alligned.
input_page_boundry <= {write_addr[AWIDTH-1:12],9'h1ff} - write_addr[AWIDTH-1:3];
end else if (input_timeout_triggered) begin // input FIFO timeout waiting for new data.
input_state <= INPUT2;
input_timeout_reset <= 1'b1;
// Calculate number of entries remaining until next 4KB page boundry is crossed minus 1.
// Note, units of calculation are 64bit wide words. Address is always 64bit alligned.
input_page_boundry <= {write_addr[AWIDTH-1:12],9'h1ff} - write_addr[AWIDTH-1:3];
end else begin
input_timeout_reset <= 1'b0;
input_state <= INPUT_IDLE;
end
end else begin
input_timeout_reset <= 1'b0;
input_state <= INPUT_IDLE;
end
end
//
// INPUT1.
// Caused by input FIFO reaching 256 entries.
// Request write burst of lesser of:
// 1) Entrys until page boundry crossed
// 2) 256.
//
INPUT1: begin
// Replicated write logic to break a read timing critical path for write_count
write_count <= (input_page_boundry[11:8] == 4'd0) ? input_page_boundry[7:0] : 8'd255;
write_count_plus_one <= (input_page_boundry[11:8] == 4'd0) ? ({1'b0,input_page_boundry[7:0]} + 9'd1) : 9'd256;
write_ctrl_valid <= 1'b1;
if (write_ctrl_ready)
input_state <= INPUT4; // Pre-emptive ACK
else
input_state <= INPUT3; // Wait for ACK
end
//
// INPUT2.
// Caused by timeout of input FIFO. (occupied_input was implicitly less than 256 last cycle)
// Request write burst of lesser of:
// 1) Entries until page boundry crossed
// 2) Entries in input FIFO
//
INPUT2: begin
// Replicated write logic to break a read timing critical path for write_count
write_count <= (input_page_boundry < ({3'h0,occupied_input[8:0]} - 12'd1)) ? input_page_boundry[7:0] : (occupied_input[8:0] - 9'd1);
write_count_plus_one <= (input_page_boundry < ({3'h0,occupied_input[8:0]} - 12'd1)) ? ({1'b0,input_page_boundry[7:0]} + 9'd1) : occupied_input[8:0];
write_ctrl_valid <= 1'b1;
if (write_ctrl_ready)
input_state <= INPUT4; // Pre-emptive ACK
else
input_state <= INPUT3; // Wait for ACK
end
//
// INPUT3.
// Wait in this state for AXI4_DMA engine to accept transaction.
//
INPUT3: begin
if (write_ctrl_ready) begin
write_ctrl_valid <= 1'b0;
input_state <= INPUT4; // ACK
end else begin
write_ctrl_valid <= 1'b1;
input_state <= INPUT3; // Wait for ACK
end
end
//
// INPUT4.
// Wait here until write_ctrl_ready_deasserts.
// This is important as the next time it asserts we know that a write response was receieved.
INPUT4: begin
write_ctrl_valid <= 1'b0;
if (!write_ctrl_ready)
input_state <= INPUT5; // Move on
else
input_state <= INPUT4; // Wait for deassert
end
//
// INPUT5.
// Transaction has been accepted by AXI4 DMA engine. Now we wait for the re-assertion
// of write_ctrl_ready which signals that the AXI4 DMA engine has receieved a response
// for the whole write transaction and we assume that this means it is commited to DRAM.
// We are now free to update write_addr pointer and go back to idle state.
//
INPUT5: begin
write_ctrl_valid <= 1'b0;
if (write_ctrl_ready) begin
write_addr <= ((write_addr + (write_count_plus_one << 3)) & set_fifo_addr_mask_bar) | (write_addr & set_fifo_addr_mask);
input_state <= INPUT6;
update_write <= 1'b1;
end else begin
input_state <= INPUT5;
end
end
//
// INPUT6:
// Need to let space update before looking if there's more to do.
//
INPUT6: begin
input_state <= INPUT_IDLE;
update_write <= 1'b0;
end
default:
input_state <= INPUT_IDLE;
endcase // case(input_state)
//
// Simple output timeout counter for now
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
output_timeout_count <= 9'd0;
output_timeout_triggered <= 1'b0;
end else if (output_timeout_reset) begin
output_timeout_count <= 9'd0;
output_timeout_triggered <= 1'b0;
end else if (output_timeout_count == set_timeout[8:0]) begin
output_timeout_triggered <= 1'b1;
end else if (output_state == OUTPUT_IDLE) begin
output_timeout_count <= output_timeout_count + ((occupied != 'd0) ? 9'd1 : 9'd0);
end
//
// Wait for 64 entries in main FIFO to trigger DRAM read burst.
// Timeout can also trigger burst so fragments of data are not left to rot in the main FIFO.
// Also if enough data is present in the main FIFO to complete a burst upto the edge
// of a 4KByte page then immediately start the burst.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
output_state <= OUTPUT_IDLE;
read_addr <= set_fifo_base_addr & set_fifo_addr_mask;
output_timeout_reset <= 1'b0;
read_ctrl_valid <= 1'b0;
read_count <= 8'd0;
read_count_plus_one <= 9'd1;
update_read <= 1'b0;
end else
case (output_state)
//
// OUTPUT_IDLE.
// To start an output tranfer from DRAM
// 1) Space in the small output FIFO
// and either
// 2) 256 entrys in the DRAM FIFO
// or
// 3) Timeout waiting for more data.
//
OUTPUT_IDLE: begin
read_ctrl_valid <= 1'b0;
update_read <= 1'b0;
if (space_output[15:8] != 'd0) begin // (space_output > 255): Space in the output FIFO.
if (occupied[AWIDTH-3:8] != 'd0) begin // (occupied > 255): 64 or more entrys in main FIFO
output_state <= OUTPUT1;
output_timeout_reset <= 1'b1;
// Calculate number of entries remaining until next 4KB page boundry is crossed minus 1.
// Note, units of calculation are 64bit wide words. Address is always 64bit alligned.
output_page_boundry <= {read_addr[AWIDTH-1:12],9'h1ff} - read_addr[AWIDTH-1:3];
end else if (output_timeout_triggered) begin // output FIFO timeout waiting for new data.
output_state <= OUTPUT2;
output_timeout_reset <= 1'b1;
// Calculate number of entries remaining until next 4KB page boundry is crossed minus 1.
// Note, units of calculation are 64bit wide words. Address is always 64bit alligned.
output_page_boundry <= {read_addr[AWIDTH-1:12],9'h1ff} - read_addr[AWIDTH-1:3];
end else begin
output_timeout_reset <= 1'b0;
output_state <= OUTPUT_IDLE;
end
end else begin
output_timeout_reset <= 1'b0;
output_state <= OUTPUT_IDLE;
end
end // case: OUTPUT_IDLE
//
// OUTPUT1.
// Caused by main FIFO reaching 256 entries.
// Request read burst of lesser of lesser of:
// 1) Entrys until page boundry crossed
// 2) 256.
//
OUTPUT1: begin
// Replicated write logic to break a read timing critical path for read_count
read_count <= (output_page_boundry[11:8] == 4'd0) ? output_page_boundry[7:0] : 8'd255;
read_count_plus_one <= (output_page_boundry[11:8] == 4'd0) ? ({1'b0,output_page_boundry[7:0]} + 9'd1) : 9'd256;
read_ctrl_valid <= 1'b1;
if (read_ctrl_ready)
output_state <= OUTPUT4; // Pre-emptive ACK
else
output_state <= OUTPUT3; // Wait for ACK
end
//
// OUTPUT2.
// Caused by timeout of main FIFO
// Request read burst of lesser of:
// 1) Entries until page boundry crossed
// 2) Entries in main FIFO
//
OUTPUT2: begin
// Replicated write logic to break a read timing critical path for read_count
read_count <= (output_page_boundry < occupied_minus_one) ? output_page_boundry[7:0] : occupied_minus_one[7:0];
read_count_plus_one <= (output_page_boundry < occupied_minus_one) ? ({1'b0,output_page_boundry[7:0]} + 9'd1) : {1'b0, occupied[7:0]};
read_ctrl_valid <= 1'b1;
if (read_ctrl_ready)
output_state <= OUTPUT4; // Pre-emptive ACK
else
output_state <= OUTPUT3; // Wait for ACK
end
//
// OUTPUT3.
// Wait in this state for AXI4_DMA engine to accept transaction.
//
OUTPUT3: begin
if (read_ctrl_ready) begin
read_ctrl_valid <= 1'b0;
output_state <= OUTPUT4; // ACK
end else begin
read_ctrl_valid <= 1'b1;
output_state <= OUTPUT3; // Wait for ACK
end
end
//
// OUTPUT4.
// Wait here unitl read_ctrl_ready_deasserts.
// This is important as the next time it asserts we know that a read response was receieved.
OUTPUT4: begin
read_ctrl_valid <= 1'b0;
if (!read_ctrl_ready)
output_state <= OUTPUT5; // Move on
else
output_state <= OUTPUT4; // Wait for deassert
end
//
// OUTPUT5.
// Transaction has been accepted by AXI4 DMA engine. Now we wait for the re-assertion
// of read_ctrl_ready which signals that the AXI4 DMA engine has receieved a last signal and good response
// for the whole read transaction.
// We are now free to update read_addr pointer and go back to idle state.
//
OUTPUT5: begin
read_ctrl_valid <= 1'b0;
if (read_ctrl_ready) begin
read_addr <= ((read_addr + (read_count_plus_one << 3)) & set_fifo_addr_mask_bar) | (read_addr & set_fifo_addr_mask);
output_state <= OUTPUT6;
update_read <= 1'b1;
end else begin
output_state <= OUTPUT5;
end
end // case: OUTPUT5
//
// OUTPUT6.
// Need to get occupied value updated before checking if there's more to do.
//
OUTPUT6: begin
update_read <= 1'b0;
output_state <= OUTPUT_IDLE;
end
default:
output_state <= OUTPUT_IDLE;
endcase // case(output_state)
//
// Count number of used entries in main DRAM FIFO.
// Note that this is expressed in units of 64bit wide words.
//
always @(posedge dram_clk)
if (dram_reset | clear) begin
occupied <= 'd0;
occupied_minus_one <= {(AWIDTH-2){1'b1}};
end else begin
occupied <= occupied + (update_write ? write_count_plus_one : 9'd0) - (update_read ? read_count_plus_one : 9'd0);
occupied_minus_one <= occupied_minus_one + (update_write ? write_count_plus_one : 9'd0) - (update_read ? read_count_plus_one : 9'd0);
end
always @(posedge dram_clk)
if (dram_reset | clear)
space <= set_fifo_addr_mask_bar[AWIDTH-1:3] & ~('d63); // Subtract 64 from space to make allowance for read/write reordering in DRAM controller
else
space <= space - (update_write ? write_count_plus_one : 9'd0) + (update_read ? read_count_plus_one : 9'd0);
//
// Instamce of axi_dma_master
//
axi_dma_master axi_dma_master_i
(
.aclk(dram_clk), // input aclk
.areset(dram_reset | clear), // input aresetn
// Write control
.m_axi_awid(m_axi_awid), // input [0 : 0] m_axi_awid
.m_axi_awaddr(m_axi_awaddr), // input [31 : 0] m_axi_awaddr
.m_axi_awlen(m_axi_awlen), // input [7 : 0] m_axi_awlen
.m_axi_awsize(m_axi_awsize), // input [2 : 0] m_axi_awsize
.m_axi_awburst(m_axi_awburst), // input [1 : 0] m_axi_awburst
.m_axi_awvalid(m_axi_awvalid), // input m_axi_awvalid
.m_axi_awready(m_axi_awready), // output m_axi_awready
.m_axi_awlock(m_axi_awlock),
.m_axi_awcache(m_axi_awcache),
.m_axi_awprot(m_axi_awprot),
.m_axi_awqos(m_axi_awqos),
.m_axi_awregion(m_axi_awregion),
.m_axi_awuser(m_axi_awuser),
// Write Data
.m_axi_wdata(m_axi_wdata), // input [63 : 0] m_axi_wdata
.m_axi_wstrb(m_axi_wstrb), // input [7 : 0] m_axi_wstrb
.m_axi_wlast(m_axi_wlast), // input m_axi_wlast
.m_axi_wvalid(m_axi_wvalid), // input m_axi_wvalid
.m_axi_wready(m_axi_wready), // output m_axi_wready
.m_axi_wuser(m_axi_wuser),
// Write Response
.m_axi_bid(m_axi_bid), // output [0 : 0] m_axi_bid
.m_axi_bresp(m_axi_bresp), // output [1 : 0] m_axi_bresp
.m_axi_bvalid(m_axi_bvalid), // output m_axi_bvalid
.m_axi_bready(m_axi_bready), // input m_axi_bready
.m_axi_buser(m_axi_buser),
// Read Control
.m_axi_arid(m_axi_arid), // input [0 : 0] m_axi_arid
.m_axi_araddr(m_axi_araddr), // input [31 : 0] m_axi_araddr
.m_axi_arlen(m_axi_arlen), // input [7 : 0] m_axi_arlen
.m_axi_arsize(m_axi_arsize), // input [2 : 0] m_axi_arsize
.m_axi_arburst(m_axi_arburst), // input [1 : 0] m_axi_arburst
.m_axi_arvalid(m_axi_arvalid), // input m_axi_arvalid
.m_axi_arready(m_axi_arready), // output m_axi_arready
.m_axi_arlock(m_axi_arlock),
.m_axi_arcache(m_axi_arcache),
.m_axi_arprot(m_axi_arprot),
.m_axi_arqos(m_axi_arqos),
.m_axi_arregion(m_axi_arregion),
.m_axi_aruser(m_axi_aruser),
// Read Data
.m_axi_rid(m_axi_rid), // output [0 : 0] m_axi_rid
.m_axi_rdata(m_axi_rdata), // output [63 : 0] m_axi_rdata
.m_axi_rresp(m_axi_rresp), // output [1 : 0] m_axi_rresp
.m_axi_rlast(m_axi_rlast), // output m_axi_rlast
.m_axi_rvalid(m_axi_rvalid), // output m_axi_rvalid
.m_axi_rready(m_axi_rready), // input m_axi_rready
.m_axi_ruser(m_axi_ruser),
//
// DMA interface for Write transaction
//
.write_addr({{(32-AWIDTH){1'b0}}, write_addr}), // Byte address for start of write transaction (should be 64bit alligned)
.write_count(write_count), // Count of 64bit words to write.
.write_ctrl_valid(write_ctrl_valid),
.write_ctrl_ready(write_ctrl_ready),
.write_data(i_tdata_input),
.write_data_valid(i_tvalid_input),
.write_data_ready(i_tready_input),
//
// DMA interface for Read
//
.read_addr({{(32-AWIDTH){1'b0}}, read_addr}), // Byte address for start of read transaction (should be 64bit alligned)
.read_count(read_count), // Count of 64bit words to read.
.read_ctrl_valid(read_ctrl_valid),
.read_ctrl_ready(read_ctrl_ready),
.read_data(o_tdata_output),
.read_data_valid(o_tvalid_output),
.read_data_ready(o_tready_output),
//
// Debug
//
.debug()
);
//ila_axi_dma_fifo inst_ila (
// .clk(ce_clk), // input wire clk
// .probe0(rb_bist_status), // input wire [3:0] probe0 channel 0
// .probe1(), // input wire [3:0] probe0 channel 0
//);
endmodule // axi_dma_fifo