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
|