1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
//
// Copyright 2021 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: chdr_xb_routing_table
//
// Description:
//
// A routing table for the CHDR crossbar. This table is designed to be shared
// between all ports. It has an AXI-Stream lookup interface and two
// simplified ctrlport configuration interfaces, one for crossbar (XB) ports
// and the other for external configuration.
//
// To insert an entry into the routing table, write the desired output port
// number to the EPID address. That is, put the EPID for a route into the
// req_addr field and the corresponding output port number on the req_data
// field.
//
// Parameters:
//
// SIZE : The number entries to support in the routing table.
// NPORTS : The number of output crossbar ports.
// EXT_INS_PORT_EN : Set to 1 to enable the external configuration interface.
//
`default_nettype none
module chdr_xb_routing_table #(
parameter SIZE = 6,
parameter NPORTS = 4,
parameter EXT_INS_PORT_EN = 1
) (
// Clocks and resets
input wire clk,
input wire reset,
// Insertion Interface (for XB ports)
input wire [ NPORTS-1:0] port_req_wr,
input wire [ (16*NPORTS)-1:0] port_req_addr,
input wire [ (32*NPORTS)-1:0] port_req_data,
output wire [ NPORTS-1:0] port_resp_ack,
// Insertion Interface (External)
input wire ext_req_wr,
input wire [ 15:0] ext_req_addr,
input wire [ 31:0] ext_req_data,
output wire ext_resp_ack,
// Find Interface
input wire [ (16*NPORTS)-1:0] axis_find_tdata,
input wire [ NPORTS-1:0] axis_find_tvalid,
output wire [ NPORTS-1:0] axis_find_tready,
// Result Interface (for Find)
output wire [($clog2(NPORTS)*NPORTS)-1:0] axis_result_tdata,
output wire [ NPORTS-1:0] axis_result_tkeep,
output wire [ NPORTS-1:0] axis_result_tvalid,
input wire [ NPORTS-1:0] axis_result_tready
);
localparam NPORTS_W = $clog2(NPORTS);
localparam CFG_W = NPORTS_W + 16;
localparam CFG_PORTS = NPORTS + EXT_INS_PORT_EN;
//---------------------------------------------------------------------------
// CAM-based lookup table
//---------------------------------------------------------------------------
wire [ 15:0] insert_tdest;
wire [NPORTS_W-1:0] insert_tdata;
wire insert_tvalid;
wire insert_tready;
axis_muxed_kv_map #(
.KEY_WIDTH(16 ),
.VAL_WIDTH(NPORTS_W),
.SIZE (SIZE ),
.NUM_PORTS(NPORTS )
) kv_map_i (
.clk (clk ),
.reset (reset ),
.axis_insert_tdata (insert_tdata ),
.axis_insert_tdest (insert_tdest ),
.axis_insert_tvalid(insert_tvalid ),
.axis_insert_tready(insert_tready ),
.axis_find_tdata (axis_find_tdata ),
.axis_find_tvalid (axis_find_tvalid ),
.axis_find_tready (axis_find_tready ),
.axis_result_tdata (axis_result_tdata ),
.axis_result_tkeep (axis_result_tkeep ),
.axis_result_tvalid(axis_result_tvalid),
.axis_result_tready(axis_result_tready)
);
//---------------------------------------------------------------------------
// Logic to convert from CtrlPort to AXI-Stream
//---------------------------------------------------------------------------
wire ins_req_wr [0:CFG_PORTS-1];
wire [ 15:0] ins_req_addr[0:CFG_PORTS-1];
wire [NPORTS_W-1:0] ins_req_data[0:CFG_PORTS-1];
wire ins_resp_ack[0:CFG_PORTS-1];
reg [(CFG_PORTS*CFG_W)-1:0] cfg_tdata;
reg [ CFG_PORTS-1:0] cfg_tvalid = {CFG_PORTS{1'b0}};
wire [ CFG_PORTS-1:0] cfg_tready;
genvar i;
generate for (i = 0; i < CFG_PORTS; i=i+1) begin : gen_cfg_ports
assign ins_req_wr[i] = (i < NPORTS) ? port_req_wr[i] : ext_req_wr;
assign ins_req_addr[i] = (i < NPORTS) ? port_req_addr[i*16 +: 16] : ext_req_addr;
assign ins_req_data[i] = (i < NPORTS) ? port_req_data[i*32 +: NPORTS_W] : ext_req_data[NPORTS_W-1:0];
if (i < NPORTS) begin : gen_port_resp
assign port_resp_ack[i] = ins_resp_ack[i];
end else begin : gen_ext_resp
assign ext_resp_ack = ins_resp_ack[i];
end
always @(posedge clk) begin : cfg_regs
if (reset) begin
cfg_tvalid[i] <= 1'b0;
end else begin
if (~cfg_tvalid[i]) begin
if (ins_req_wr[i]) begin
cfg_tvalid[i] <= 1'b1;
cfg_tdata[(CFG_W*i)+:CFG_W] <= {ins_req_data[i], ins_req_addr[i]};
end
end else begin
cfg_tvalid[i] <= ~cfg_tready[i];
end
end
end
assign ins_resp_ack[i] = cfg_tvalid[i] & cfg_tready[i];
end endgenerate
//---------------------------------------------------------------------------
// Multiplexer between XB ports and external configuration
//---------------------------------------------------------------------------
axi_mux #(
.WIDTH (CFG_W ),
.SIZE (CFG_PORTS),
.PRE_FIFO_SIZE (0 ),
.POST_FIFO_SIZE(1 )
) axi_mux_i (
.clk (clk ),
.reset (reset ),
.clear (1'b0 ),
.i_tdata (cfg_tdata ),
.i_tlast ({CFG_PORTS{1'b1}} ),
.i_tvalid(cfg_tvalid ),
.i_tready(cfg_tready ),
.o_tdata ({insert_tdata, insert_tdest}),
.o_tlast ( ),
.o_tvalid(insert_tvalid ),
.o_tready(insert_tready )
);
endmodule
`default_nettype wire
|