aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/control/axi_crossbar.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/control/axi_crossbar.v')
-rw-r--r--fpga/usrp3/lib/control/axi_crossbar.v167
1 files changed, 167 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/axi_crossbar.v b/fpga/usrp3/lib/control/axi_crossbar.v
new file mode 100644
index 000000000..a408f69f0
--- /dev/null
+++ b/fpga/usrp3/lib/control/axi_crossbar.v
@@ -0,0 +1,167 @@
+//
+// Copyright 2012 Ettus Research LLC
+//
+
+
+`define LOG2(N) (\
+ N < 2 ? 0 : \
+ N < 4 ? 1 : \
+ N < 8 ? 2 : \
+ N < 16 ? 3 : \
+ N < 32 ? 4 : \
+ N < 64 ? 5 : \
+ N < 128 ? 6 : \
+ N < 256 ? 7 : \
+ N < 512 ? 8 : \
+ N < 1024 ? 9 : \
+ 10)
+
+module axi_crossbar
+ #(
+ parameter FIFO_WIDTH = 64, // AXI4-STREAM data bus width
+ parameter DST_WIDTH = 16, // Width of DST field we are routing on.
+ parameter NUM_INPUTS = 2, // number of input AXI4-STREAM buses
+ parameter NUM_OUTPUTS = 2 // number of output AXI4-STREAM buses
+ )
+ (
+ input clk,
+ input reset,
+ input clear,
+ input [7:0] local_addr,
+ // Inputs
+ input [(FIFO_WIDTH*NUM_INPUTS)-1:0] i_tdata,
+ input [NUM_INPUTS-1:0] i_tvalid,
+ input [NUM_INPUTS-1:0] i_tlast,
+ output [NUM_INPUTS-1:0] i_tready,
+ input [NUM_INPUTS-1:0] pkt_present,
+ // Setting Bus
+ input set_stb,
+ input [15:0] set_addr,
+ input [31:0] set_data,
+ // Output
+ output [(FIFO_WIDTH*NUM_OUTPUTS)-1:0] o_tdata,
+ output [NUM_OUTPUTS-1:0] o_tvalid,
+ output [NUM_OUTPUTS-1:0] o_tlast,
+ input [NUM_OUTPUTS-1:0] o_tready,
+ // readback bus
+ input rb_rd_stb,
+ input [`LOG2(NUM_OUTPUTS)+`LOG2(NUM_INPUTS)-1:0] rb_addr,
+ output [31:0] rb_data
+ );
+
+ genvar m,n;
+
+ wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_valid_in;
+ wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_ack_in;
+ wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_valid_out;
+ wire [(NUM_INPUTS*NUM_OUTPUTS)-1:0] forward_ack_out;
+
+ wire [NUM_INPUTS-1:0] i_tready_slave [0:NUM_OUTPUTS-1];
+
+ //
+ // Instantiate an axi_slave_mux for every slave/output of the Crossbar switch.
+ // Each axi_slave_mux contains logic to maux and resolve arbitration
+ // for this particular slave/output.
+ //
+
+ generate
+ for (m = 0; m < NUM_OUTPUTS; m = m + 1) begin: instantiate_slave_mux
+
+ wire [NUM_INPUTS-1:0] i_tready_tmp;
+
+ axi_slave_mux
+ #(
+ .FIFO_WIDTH(FIFO_WIDTH), // AXI4-STREAM data bus width
+ .DST_WIDTH(DST_WIDTH), // Width of DST field we are routing on.
+ .NUM_INPUTS(NUM_INPUTS) // number of input AXI buses
+ ) axi_slave_mux_i
+ (
+ .clk(clk),
+ .reset(reset),
+ .clear(clear),
+ // Inputs
+ .i_tdata(i_tdata),
+ .i_tvalid(i_tvalid),
+ .i_tlast(i_tlast),
+ .i_tready(i_tready_tmp),
+ // Forwarding flags (One from each Input/Master)
+ .forward_valid(forward_valid_in[(m+1)*NUM_INPUTS-1:m*NUM_INPUTS]),
+ .forward_ack(forward_ack_out[(m+1)*NUM_INPUTS-1:m*NUM_INPUTS]),
+ // Output
+ .o_tdata(o_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH]),
+ .o_tvalid(o_tvalid[m]),
+ .o_tlast(o_tlast[m]),
+ .o_tready(o_tready[m])
+ );
+
+ if (m==0)
+ assign i_tready_slave[0] = i_tready_tmp;
+ else
+ assign i_tready_slave[m] = i_tready_tmp | i_tready_slave[m-1] ;
+
+ end // block: instantiate_slave_mux
+ endgenerate
+
+ assign i_tready = i_tready_slave[NUM_OUTPUTS-1];
+
+ //
+ // Permute the forwarding flag buses
+ //
+
+ generate
+ for (m = 0; m < NUM_OUTPUTS; m = m + 1) begin: permute_outer
+ for (n = 0; n < NUM_INPUTS; n = n + 1) begin: permute_inner
+ assign forward_valid_in[n*NUM_OUTPUTS+m] = forward_valid_out[n+m*NUM_INPUTS];
+ assign forward_ack_in[n+m*NUM_INPUTS] = forward_ack_out[n*NUM_OUTPUTS+m];
+ end
+ end
+
+ endgenerate
+
+
+ //
+ // Instantiate an axi_forwarding_cam for every Input/Master of the Crossbar switch.
+ // Each contains a TCAM like lookup that allocates an egress port.
+ //
+
+ wire [31:0] rb_data_mux[0:NUM_INPUTS-1];
+
+ generate
+ for (m = 0; m < NUM_INPUTS; m = m + 1) begin: instantiate_cam
+ axi_forwarding_cam
+ #(
+ .BASE(0),
+ .WIDTH(FIFO_WIDTH), // Bit width of FIFO word.
+ .NUM_OUTPUTS(NUM_OUTPUTS)
+ ) axi_forwarding_cam_i
+ (
+ .clk(clk),
+ .reset(reset),
+ .clear(clear),
+ // Monitored FIFO signals
+ .o_tdata(i_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH]),
+ .o_tvalid(i_tvalid[m]),
+ .o_tready(i_tready[m]),
+ .o_tlast(i_tlast[m]),
+ .pkt_present(pkt_present[m]),
+ // Configuration
+ .local_addr(local_addr),
+ // Setting Bus
+ .set_stb(set_stb),
+ .set_addr(set_addr),
+ .set_data(set_data),
+ // Header signals
+ .forward_valid(forward_valid_out[(m+1)*NUM_OUTPUTS-1:m*NUM_OUTPUTS]),
+ .forward_ack(forward_ack_in[(m+1)*NUM_OUTPUTS-1:m*NUM_OUTPUTS]),
+ // Readback bus
+ .rb_rd_stb(rb_rd_strobe && (rb_addr[`LOG2(NUM_OUTPUTS)+`LOG2(NUM_INPUTS)-1:`LOG2(NUM_OUTPUTS)] == m)),
+ .rb_addr(rb_addr[`LOG2(NUM_OUTPUTS)-1:0]),
+ .rb_data(rb_data_mux[m])
+ );
+ end // block: instantiate_fifo_header
+ endgenerate
+
+ assign rb_data = rb_data_mux[rb_addr[`LOG2(NUM_OUTPUTS)+`LOG2(NUM_INPUTS)-1:`LOG2(NUM_OUTPUTS)]];
+
+
+endmodule // axi_crossbar