diff options
Diffstat (limited to 'fpga/usrp3/lib/control/axi_crossbar.v')
-rw-r--r-- | fpga/usrp3/lib/control/axi_crossbar.v | 167 |
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 |