168 lines
5.1 KiB
Verilog
168 lines
5.1 KiB
Verilog
//
|
|
// 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
|