aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/fifo/axi_mux.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/fifo/axi_mux.v')
-rw-r--r--fpga/usrp3/lib/fifo/axi_mux.v110
1 files changed, 110 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/fifo/axi_mux.v b/fpga/usrp3/lib/fifo/axi_mux.v
new file mode 100644
index 000000000..72a771348
--- /dev/null
+++ b/fpga/usrp3/lib/fifo/axi_mux.v
@@ -0,0 +1,110 @@
+
+// Copyright 2016 Ettus Research
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+// axi_mux -- takes arbitrary number of AXI stream, merges them to 1 output channel
+// Round-robin if PRIO=0, priority if PRIO=1 (lower number ports get priority)
+// Bubble cycles are inserted after each packet
+
+module axi_mux
+ #(parameter PRIO=0,
+ parameter WIDTH=64,
+ parameter PRE_FIFO_SIZE=0,
+ parameter POST_FIFO_SIZE=0,
+ parameter SIZE=4)
+ (input clk, input reset, input clear,
+ input [(WIDTH*SIZE)-1:0] i_tdata, input [SIZE-1:0] i_tlast, input [SIZE-1:0] i_tvalid, output [SIZE-1:0] i_tready,
+ output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);
+
+ wire [WIDTH*SIZE-1:0] i_tdata_int;
+ wire [SIZE-1:0] i_tlast_int, i_tvalid_int, i_tready_int;
+
+ wire [WIDTH-1:0] o_tdata_int;
+ wire o_tlast_int, o_tvalid_int, o_tready_int;
+
+ reg [$clog2(SIZE)-1:0] st_port;
+ reg st_active;
+
+ genvar n;
+ generate
+ if (PRE_FIFO_SIZE == 0) begin
+ assign i_tdata_int = i_tdata;
+ assign i_tlast_int = i_tlast;
+ assign i_tvalid_int = i_tvalid;
+ assign i_tready = i_tready_int;
+ end else begin
+ for (n = 0; n < SIZE; n = n + 1) begin
+ axi_fifo #(.WIDTH(WIDTH+1), .SIZE(PRE_FIFO_SIZE)) axi_fifo (
+ .clk(clk), .reset(reset), .clear(clear),
+ .i_tdata({i_tlast[n],i_tdata[WIDTH*(n+1)-1:WIDTH*n]}), .i_tvalid(i_tvalid[n]), .i_tready(i_tready[n]),
+ .o_tdata({i_tlast_int[n],i_tdata_int[WIDTH*(n+1)-1:WIDTH*n]}), .o_tvalid(i_tvalid_int[n]), .o_tready(i_tready_int[n]),
+ .space(), .occupied());
+ end
+ end
+ endgenerate
+
+ always @(posedge clk)
+ if(reset)
+ begin
+ st_port <= 0;
+ st_active <= 1'b0;
+ end
+ else
+ if(st_active)
+ begin
+ if(o_tlast_int & o_tvalid_int & o_tready_int)
+ begin
+ st_active <= 1'b0;
+ if((PRIO != 0) | (st_port == (SIZE-1)))
+ st_port <= 0;
+ else
+ st_port <= st_port + 1;
+ end
+ end // if (st_active)
+ else
+ if(i_tvalid_int[st_port])
+ st_active <= 1'b1;
+ else
+ if(st_port == (SIZE-1))
+ st_port <= 0;
+ else
+ st_port <= st_port + 1;
+
+ genvar i;
+ generate
+ for(i=0;i<SIZE;i=i+1)
+ begin : gen1
+ assign i_tready_int[i] = st_active & o_tready_int & (st_port == i);
+ end
+ endgenerate
+
+ assign o_tvalid_int = st_active & i_tvalid_int[st_port];
+ assign o_tlast_int = i_tlast_int[st_port];
+
+ genvar j;
+ generate
+ for (j=0;j<WIDTH;j=j+1)
+ begin : gen2
+ assign o_tdata_int[j] = i_tdata_int[st_port*WIDTH+j];
+ end
+ endgenerate
+
+ generate
+ if(POST_FIFO_SIZE == 0)
+ begin
+ assign o_tdata = o_tdata_int;
+ assign o_tlast = o_tlast_int;
+ assign o_tvalid = o_tvalid_int;
+ assign o_tready_int = o_tready;
+ end
+ else
+ axi_fifo #(.WIDTH(WIDTH+1),.SIZE(POST_FIFO_SIZE)) axi_fifo
+ (.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());
+ endgenerate
+
+endmodule // axi__mux