diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/chdr_fifo_large.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/chdr_fifo_large.v | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/chdr_fifo_large.v b/fpga/usrp3/lib/rfnoc/chdr_fifo_large.v new file mode 100644 index 000000000..77e1f8a0b --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/chdr_fifo_large.v @@ -0,0 +1,94 @@ +// +// Copyright 2016 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +module chdr_fifo_large #( + parameter SIZE = 12, + parameter DEVICE = "7SERIES" +) ( + input clk, + input reset, + input clear, + + input [63:0] i_tdata, + input i_tlast, + input i_tvalid, + output i_tready, + + output [63:0] o_tdata, + output o_tlast, + output o_tvalid, + input o_tready +); + + localparam SIZE_THRESHOLD = ( + (DEVICE == "7SERIES") ? 14 : ( + (DEVICE == "VIRTEX6") ? 14 : ( + (DEVICE == "SPARTAN6") ? 12 : ( + 12 + )))); + + wire [63:0] i_tdata_pre; + wire i_tlast_pre, i_tvalid_pre, i_tready_pre; + + // SRL based FIFO to break timing paths to BRAM resources + axi_fifo_flop2 #(.WIDTH(65)) pre_fifo ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata({i_tlast, i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready), + .o_tdata({i_tlast_pre, i_tdata_pre}), .o_tvalid(i_tvalid_pre), .o_tready(i_tready_pre), + .space(), .occupied() + ); + + generate + if (SIZE <= SIZE_THRESHOLD) begin + wire [63:0] o_tdata_int; + wire o_tlast_int, o_tvalid_int, o_tready_int; + // Instantiate a single axi_fifo if size is not larger than threshold + axi_fifo #(.WIDTH(65), .SIZE(SIZE)) main_fifo ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata({i_tlast_pre, i_tdata_pre}), .i_tvalid(i_tvalid_pre), .i_tready(i_tready_pre), + .o_tdata({o_tlast_int, o_tdata_int}), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int), + .space(), .occupied() + ); + axi_fifo_flop2 #(.WIDTH(65)) fifo_flop2 ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata({o_tlast_int, o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int), + .o_tdata({o_tlast, o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready), + .space(), .occupied() + ); + end else begin + // Instantiate a cascade of axi_fifos if size is larger than threshold + localparam CDEPTH = 2**(SIZE - SIZE_THRESHOLD); //Cascade Depth + wire [63:0] c_tdata[CDEPTH:0], int_tdata[CDEPTH-1:0]; + wire c_tlast[CDEPTH:0], c_tvalid[CDEPTH:0], c_tready[CDEPTH:0]; + wire int_tlast[CDEPTH-1:0], int_tvalid[CDEPTH-1:0], int_tready[CDEPTH-1:0]; + + //Connect input to first cascade state + assign {c_tdata[0], c_tlast[0], c_tvalid[0]} = {i_tdata_pre, i_tlast_pre, i_tvalid_pre}; + assign i_tready_pre = c_tready[0]; + //Connect output to last cascade state + assign {o_tdata, o_tlast, o_tvalid} = {c_tdata[CDEPTH], c_tlast[CDEPTH], c_tvalid[CDEPTH]}; + assign c_tready[CDEPTH] = o_tready; + + genvar i; + for (i=0; i<CDEPTH; i=i+1) begin: fifo_stages + axi_fifo #(.WIDTH(65), .SIZE(SIZE_THRESHOLD)) main_fifo ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata({c_tlast[i], c_tdata[i]}), .i_tvalid(c_tvalid[i]), .i_tready(c_tready[i]), + .o_tdata({int_tlast[i], int_tdata[i]}), .o_tvalid(int_tvalid[i]), .o_tready(int_tready[i]), + .space(), .occupied() + ); + axi_fifo_flop2 #(.WIDTH(65)) fifo_flop2 ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata({int_tlast[i], int_tdata[i]}), .i_tvalid(int_tvalid[i]), .i_tready(int_tready[i]), + .o_tdata({c_tlast[i+1], c_tdata[i+1]}), .o_tvalid(c_tvalid[i+1]), .o_tready(c_tready[i+1]), + .space(), .occupied() + ); + end + end + endgenerate + +endmodule // axi_fifo_large |