aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/fifo/axi_mux4.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/fifo/axi_mux4.v')
-rw-r--r--fpga/usrp3/lib/fifo/axi_mux4.v112
1 files changed, 112 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/fifo/axi_mux4.v b/fpga/usrp3/lib/fifo/axi_mux4.v
new file mode 100644
index 000000000..91bfe43a9
--- /dev/null
+++ b/fpga/usrp3/lib/fifo/axi_mux4.v
@@ -0,0 +1,112 @@
+
+// Copyright 2012 Ettus Research LLC
+// axi_mux -- takes 4 64-bit 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 in PRIO mode, or on wraparound in Round Robin mode
+
+module axi_mux4
+ #(parameter PRIO=0,
+ parameter WIDTH=64,
+ parameter BUFFER=0)
+ (input clk, input reset, input clear,
+ input [WIDTH-1:0] i0_tdata, input i0_tlast, input i0_tvalid, output i0_tready,
+ input [WIDTH-1:0] i1_tdata, input i1_tlast, input i1_tvalid, output i1_tready,
+ input [WIDTH-1:0] i2_tdata, input i2_tlast, input i2_tvalid, output i2_tready,
+ input [WIDTH-1:0] i3_tdata, input i3_tlast, input i3_tvalid, output i3_tready,
+ output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready);
+
+ wire [WIDTH-1:0] o_tdata_int;
+ wire o_tlast_int, o_tvalid_int, o_tready_int;
+
+ reg [3:0] mx_state;
+ localparam MX_IDLE = 4'b0000;
+ localparam MX_0 = 4'b0001;
+ localparam MX_1 = 4'b0010;
+ localparam MX_2 = 4'b0100;
+ localparam MX_3 = 4'b1000;
+
+ always @(posedge clk)
+ if(reset | clear)
+ mx_state <= MX_IDLE;
+ else
+ case (mx_state)
+ MX_IDLE :
+ if(i0_tvalid)
+ mx_state <= MX_0;
+ else if(i1_tvalid)
+ mx_state <= MX_1;
+ else if(i2_tvalid)
+ mx_state <= MX_2;
+ else if(i3_tvalid)
+ mx_state <= MX_3;
+
+ MX_0 :
+ if(o_tready_int & o_tvalid_int & o_tlast_int)
+ if(PRIO)
+ mx_state <= MX_IDLE;
+ else if(i1_tvalid)
+ mx_state <= MX_1;
+ else if(i2_tvalid)
+ mx_state <= MX_2;
+ else if(i3_tvalid)
+ mx_state <= MX_3;
+ else
+ mx_state <= MX_IDLE;
+
+ MX_1 :
+ if(o_tready_int & o_tvalid_int & o_tlast_int)
+ if(PRIO)
+ mx_state <= MX_IDLE;
+ else if(i2_tvalid)
+ mx_state <= MX_2;
+ else if(i3_tvalid)
+ mx_state <= MX_3;
+ else
+ mx_state <= MX_IDLE;
+
+ MX_2 :
+ if(o_tready_int & o_tvalid_int & o_tlast_int)
+ if(PRIO)
+ mx_state <= MX_IDLE;
+ else if(i3_tvalid)
+ mx_state <= MX_3;
+ else
+ mx_state <= MX_IDLE;
+
+ MX_3 :
+ if(o_tready_int & o_tvalid_int & o_tlast_int)
+ if(PRIO)
+ mx_state <= MX_IDLE;
+ else
+ mx_state <= MX_IDLE;
+
+ default :
+ mx_state <= MX_IDLE;
+ endcase // case (mx_state)
+
+ assign {i3_tready, i2_tready, i1_tready, i0_tready} = mx_state & {4{o_tready_int}};
+
+ assign o_tvalid_int = |(mx_state & ({i3_tvalid, i2_tvalid, i1_tvalid, i0_tvalid}));
+
+ assign {o_tlast_int, o_tdata_int} = mx_state[3] ? {i3_tlast, i3_tdata} :
+ mx_state[2] ? {i2_tlast, i2_tdata} :
+ mx_state[1] ? {i1_tlast, i1_tdata} :
+ {i0_tlast, i0_tdata};
+
+ generate
+ if(BUFFER == 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_short #(.WIDTH(WIDTH+1)) axi_fifo_short
+ (.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__mux4