-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathvsid_parser.sv
316 lines (230 loc) · 11.7 KB
/
vsid_parser.sv
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
`timescale 1ns / 1ps
`default_nettype none
//VSID field constants
`define L4_OFFSET 34
`define EXTRA_OFFSET_VX 8
`define VSID_OFFSET 4
`define VSID_SIZE 32
`define VSID_MASK {32'h00FFFFFF} //Actually 24 bit value
`define VSID_LANES (`VSID_SIZE/16)
`define DA_MAC_OFFSET 8
`define DA_MAC_SIZE 48
`define DA_MAC_BYTES (`DA_MAC_SIZE/8)
`define DA_MAC_LANES (`DA_MAC_SIZE/16)
`define LAST_BYTE `L4_OFFSET + `EXTRA_OFFSET_VX + `DA_MAC_OFFSET + `DA_MAC_BYTES - 1
//The VSID Parser
module vsid_parser
#(
//AXI Stream Params
parameter AXIS_BUS_WIDTH = 64,
parameter AXIS_ID_WIDTH = 4,
//Derived params for AXI Stream
localparam NUM_BUS_BYTES = AXIS_BUS_WIDTH/8,
localparam NUM_BUS_LANES = AXIS_BUS_WIDTH/16,
localparam NUM_BUS_BYTES_LOG2 = $clog2(NUM_BUS_BYTES),
localparam NUM_AXIS_ID = (2 ** AXIS_ID_WIDTH),
//Network Packet Params
parameter MAX_PACKET_LENGTH = 1522,
//Constants and Derived params for network packet
localparam PACKET_LENGTH_CBITS = $clog2(MAX_PACKET_LENGTH+1),
localparam MAX_ADDED_OFFSET = 64,
localparam MAX_OFFSET_INTERNAL = MAX_ADDED_OFFSET + `LAST_BYTE,
localparam MAX_OFFSET_CBITS = $clog2(MAX_OFFSET_INTERNAL+1),
localparam MAX_ADDED_OFFSET_CBITS = $clog2(MAX_ADDED_OFFSET+1)
)
(
//Input AXI stream
input wire [AXIS_BUS_WIDTH-1:0] axis_in_tdata,
input wire [NUM_BUS_BYTES-1:0] axis_in_tkeep,
input wire axis_in_tlast,
input wire axis_in_tvalid,
output wire axis_in_tready,
//Output AXI stream
output wire [AXIS_BUS_WIDTH-1:0] axis_out_tdata,
output wire [NUM_BUS_BYTES-1:0] axis_out_tkeep,
output wire axis_out_tlast,
output wire axis_out_tvalid,
input wire axis_out_tready,
//Side channel signals from previous stage (port parser)
input wire [NUM_AXIS_ID-1:0] route_mask_in,
input wire poisoned_in,
input wire parsing_done_in,
input wire next_is_config_in,
input wire has_udp_checksum_in,
input wire [PACKET_LENGTH_CBITS-1:0] cur_pos,
input wire [MAX_ADDED_OFFSET_CBITS-1:0] added_offset,
input wire next_can_have_vsid,
//Side channel signals passed to next stage (filtering)
output wire [NUM_AXIS_ID-1:0] route_mask_out,
output wire poisoned_out,
output wire parsing_done_out,
output wire next_is_config_out,
output wire has_udp_checksum_out,
output wire parsing_vsid_done,
//Configuration register inputs
input wire is_vxlan,
//CAM contents
input wire [`VSID_SIZE-1:0] vsids [NUM_AXIS_ID-1:0],
input wire vsid_cam_must_match [NUM_AXIS_ID-1:0],
input wire [`DA_MAC_SIZE-1:0] mac_encap_addresses [NUM_AXIS_ID-1:0],
input wire mac_encap_cam_must_match [NUM_AXIS_ID-1:0],
//Clocking
input wire aclk,
input wire aresetn
);
//--------------------------------------------------------//
// Signals Used Throughout //
//--------------------------------------------------------//
//Stream passthrough
assign axis_out_tdata = axis_in_tdata;
assign axis_out_tkeep = axis_in_tkeep;
assign axis_out_tlast = axis_in_tlast;
assign axis_out_tvalid = axis_in_tvalid;
assign axis_in_tready = axis_out_tready;
//Other passthrough
assign next_is_config_out = next_is_config_in;
assign poisoned_out = poisoned_in;
assign parsing_done_out = parsing_done_in;
assign has_udp_checksum_out = has_udp_checksum_in;
//Divide the data bus into 2-byte wide lanes
wire [15:0] axis_in_tdata_lanes [NUM_BUS_LANES-1:0];
generate
for(genvar j = 0; j < NUM_BUS_LANES; j = j + 1) begin : bus_lanes
assign axis_in_tdata_lanes[j] = axis_in_tdata[(j*16)+:16];
end
endgenerate
//Valid and Ready beat
wire axis_valid_beat = axis_in_tvalid & axis_out_tready;
wire axis_last_beat = axis_valid_beat & axis_in_tlast;
//Current Position Count
wire [PACKET_LENGTH_CBITS-1:0] current_position = cur_pos;
//Added offset internal
wire [MAX_ADDED_OFFSET_CBITS:0] added_offset_int = added_offset + (is_vxlan ? `EXTRA_OFFSET_VX : 0);
//Params to split offset counters into important parts
localparam LOWER_PORTION = NUM_BUS_BYTES_LOG2;
localparam UPPER_PORTION = PACKET_LENGTH_CBITS; /*(MAX_OFFSET_CBITS <= NUM_BUS_BYTES_LOG2)
? NUM_BUS_BYTES_LOG2 + 1
: MAX_OFFSET_CBITS;*/
//--------------------------------------------------------//
// VSID Field Parsing //
//--------------------------------------------------------//
//custom field lanes
wire [15:0] vsid_lanes [`VSID_LANES-1:0];
wire vsid_lane_valid [`VSID_LANES-1:0];
//Extract Dest port lanes
generate
for(genvar j = 0; j < `VSID_LANES; j = j + 1) begin : vsid_lanes_loop
//Address where the byte-pair lane is expected
wire [UPPER_PORTION-1:0] lane_offset = `L4_OFFSET + `VSID_OFFSET + (j*2) + added_offset_int;
wire [LOWER_PORTION-1:0] lane_lower = lane_offset[LOWER_PORTION-1:0];
wire [UPPER_PORTION-LOWER_PORTION-1:0] lane_upper = lane_offset[UPPER_PORTION-1:LOWER_PORTION];
//The specific byte-pair lane in the current stream flit
wire [15:0] lane_data = axis_in_tdata_lanes[lane_lower[LOWER_PORTION-1:1]];
wire lane_present = (lane_upper == current_position[PACKET_LENGTH_CBITS-1:LOWER_PORTION]) && axis_valid_beat;
//Assign parsed values
assign vsid_lanes[j] = lane_data;
assign vsid_lane_valid[j] = lane_present;
end
endgenerate
//--------------------------------------------------------//
// Encap MAC Field Parsing //
//--------------------------------------------------------//
//custom field lanes
wire [15:0] dest_mac_lanes [`DA_MAC_LANES-1:0];
wire dest_mac_lane_valid [`DA_MAC_LANES-1:0];
//Extract Dest port lanes
generate
for(genvar j = 0; j < `DA_MAC_LANES; j = j + 1) begin : dest_lanes
//Address where the byte-pair lane is expected
wire [UPPER_PORTION-1:0] lane_offset = `L4_OFFSET + `DA_MAC_OFFSET + (j*2) + added_offset_int;
wire [LOWER_PORTION-1:0] lane_lower = lane_offset[LOWER_PORTION-1:0];
wire [UPPER_PORTION-LOWER_PORTION-1:0] lane_upper = lane_offset[UPPER_PORTION-1:LOWER_PORTION];
//The specific byte-pair lane in the current stream flit
wire [15:0] lane_data = axis_in_tdata_lanes[lane_lower[LOWER_PORTION-1:1]];
wire lane_present = (lane_upper == current_position[PACKET_LENGTH_CBITS-1:LOWER_PORTION]) && axis_valid_beat;
//Assign parsed values
assign dest_mac_lanes[j] = lane_data;
assign dest_mac_lane_valid[j] = lane_present;
end
endgenerate
//--------------------------------------------------------//
// VSID Routing CAM //
//--------------------------------------------------------//
//Signal final result of CAM
wire [NUM_AXIS_ID-1:0] vsid_out_route_mask;
wire [`VSID_SIZE-1:0] vsid_match_mask = `VSID_MASK;
//Loop over CAM array
generate
for(genvar k = 0; k < NUM_AXIS_ID; k = k + 1) begin: vsid_cam_array
//cam signals
reg reg_out_route_mask;
wire [`VSID_LANES-1:0] cur_out_route_mask;
wire [`VSID_LANES-1:0] eff_out_route_mask;
//Loop over lanes
for(genvar j = 0; j < `VSID_LANES; j = j + 1) begin : vsid_cam
//Check current entry match
wire tag_match = (vsid_lanes[j] & vsid_match_mask[(j*16)+:16]) ==
(vsids[k][(j*16)+:16] & vsid_match_mask[(j*16)+:16]);
assign cur_out_route_mask[j] = tag_match;
assign eff_out_route_mask[j] = !vsid_lane_valid[j] || cur_out_route_mask[j];
end
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_out_route_mask <= 1;
else if(!(&eff_out_route_mask)) reg_out_route_mask <= 0;
end
//Assign output values
assign vsid_out_route_mask[k] = (&eff_out_route_mask) & reg_out_route_mask;
end
endgenerate
//--------------------------------------------------------//
// Dest Address Routing CAM //
//--------------------------------------------------------//
//Signal final result of CAM
wire [NUM_AXIS_ID-1:0] mac_out_route_mask;
//Loop over CAM array
generate
for(genvar k = 0; k < NUM_AXIS_ID; k = k + 1) begin: mac_cam_array
//cam signals
reg reg_out_route_mask;
wire [`DA_MAC_LANES-1:0] cur_out_route_mask;
wire [`DA_MAC_LANES-1:0] eff_out_route_mask;
//Loop over lanes
for(genvar j = 0; j < `DA_MAC_LANES; j = j + 1) begin : dest_cam
//Check current entry match
wire dest_adr_match = (dest_mac_lanes[j] == mac_encap_addresses[k][(j*16)+:16]);
assign cur_out_route_mask[j] = dest_adr_match;
assign eff_out_route_mask[j] = !dest_mac_lane_valid[j] || cur_out_route_mask[j];
end
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_out_route_mask <= 1;
else if(!(&eff_out_route_mask)) reg_out_route_mask <= 0;
end
//Assign output values
assign mac_out_route_mask[k] = (&eff_out_route_mask) & reg_out_route_mask;
end
endgenerate
//Assign Output Value
wire [NUM_AXIS_ID-1:0] mac_encap_cam_must_match_packed = {>>{mac_encap_cam_must_match}};
wire [NUM_AXIS_ID-1:0] internal_mac_route_mask =
mac_out_route_mask | ~(mac_encap_cam_must_match_packed);
wire [NUM_AXIS_ID-1:0] vsid_cam_must_match_packed = {>>{vsid_cam_must_match}};
wire [NUM_AXIS_ID-1:0] internal_vsid_route_mask =
~(vsid_cam_must_match_packed) |
((parsing_vsid_done && next_can_have_vsid) ? vsid_out_route_mask : '0);
assign route_mask_out = internal_mac_route_mask & internal_vsid_route_mask & route_mask_in;
//--------------------------------------------------------//
// End of Processing Indication //
//--------------------------------------------------------//
//Register
reg reg_parsing_done;
//Assign Registered values
always @(posedge aclk) begin
if(~aresetn || axis_last_beat) reg_parsing_done <= 0;
else if (dest_mac_lane_valid[`DA_MAC_LANES-1]) reg_parsing_done <= 1;
end
//Assign output value
assign parsing_vsid_done = (dest_mac_lane_valid[`DA_MAC_LANES-1] ? 1 : reg_parsing_done);
endmodule
`default_nettype wire