1 |
15 |
dinesha |
/*-----------------------------------------------------------------
|
2 |
|
|
| Ethernet Traffic Generator Testbench |
|
3 |
|
|
| |
|
4 |
|
|
------------------------------------------------------------------*/
|
5 |
|
|
|
6 |
|
|
/*-----------------------------------------------------------------\
|
7 |
|
|
| DESCRIPTION: |
|
8 |
|
|
| tb_pktgn.v: Packet generation tasks |
|
9 |
|
|
| |
|
10 |
|
|
| Instantiated modules: none |
|
11 |
|
|
| Included files: none |
|
12 |
|
|
\-----------------------------------------------------------------*/
|
13 |
|
|
|
14 |
|
|
task construct_frame;
|
15 |
|
|
integer size;
|
16 |
|
|
integer payload_byte;
|
17 |
|
|
reg [`MAX_PKT_SIZE*8 -1:0] packet;
|
18 |
|
|
integer i,j;
|
19 |
|
|
begin
|
20 |
|
|
size = current_pkt_size;
|
21 |
|
|
// clear packet
|
22 |
|
|
packet = 0;
|
23 |
|
|
add_L2_header(packet);
|
24 |
|
|
if (flow_type >= 3)
|
25 |
|
|
add_L3_header(packet);
|
26 |
|
|
if (flow_type >= 5)
|
27 |
|
|
add_L4_header(packet);
|
28 |
|
|
add_payload(packet);
|
29 |
|
|
|
30 |
|
|
transmit_pkt = packet;
|
31 |
|
|
transmit_pkt_size= size;
|
32 |
|
|
end
|
33 |
|
|
endtask // construct_frame
|
34 |
|
|
|
35 |
|
|
task add_L2_header;
|
36 |
|
|
inout [`MAX_PKT_SIZE*8 -1:0] packet;
|
37 |
|
|
reg [47:0] mac_addr;
|
38 |
|
|
reg [15:0] temp;
|
39 |
|
|
integer length_field, next_offset, j;
|
40 |
|
|
reg [`MAX_HEADER_SIZE*8-1:0] std_LLC_header;
|
41 |
|
|
|
42 |
|
|
begin
|
43 |
|
|
if (L2_custom_header_enable) // use user-defined header
|
44 |
|
|
begin
|
45 |
|
|
insert_header(packet, 0, L2_custom_header,
|
46 |
|
|
L2_custom_header_length);
|
47 |
|
|
L3_header_position = L2_custom_header_length;
|
48 |
|
|
if (flow_type < 3) // Layer-2 flow
|
49 |
|
|
payload_position = L2_custom_header_length;
|
50 |
|
|
end // if (L2_custom_header_enable)
|
51 |
|
|
else
|
52 |
|
|
begin
|
53 |
|
|
mac_addr = current_dstn_mac;
|
54 |
|
|
//swap bytes in MAC address
|
55 |
|
|
// MS byte goes first on the link
|
56 |
|
|
packet[ 7: 0] = mac_addr[47:40];
|
57 |
|
|
packet[15: 8] = mac_addr[39:32];
|
58 |
|
|
packet[23:16] = mac_addr[31:24];
|
59 |
|
|
packet[31:24] = mac_addr[23:16];
|
60 |
|
|
packet[39:32] = mac_addr[15: 8];
|
61 |
|
|
packet[47:40] = mac_addr[ 7: 0];
|
62 |
|
|
|
63 |
|
|
mac_addr = current_src_mac;
|
64 |
|
|
packet[55:48] = mac_addr[47:40];
|
65 |
|
|
packet[63:56] = mac_addr[39:32];
|
66 |
|
|
packet[71:64] = mac_addr[31:24];
|
67 |
|
|
packet[79:72] = mac_addr[23:16];
|
68 |
|
|
packet[87:80] = mac_addr[15: 8];
|
69 |
|
|
packet[95:88] = mac_addr[ 7: 0];
|
70 |
|
|
|
71 |
|
|
length_field = current_pkt_size - 6*2 - 2 -4; // SA, DA, length, CRC
|
72 |
|
|
next_offset = 12;
|
73 |
|
|
if ((L2_protocol_type == 1) ||
|
74 |
|
|
(L2_protocol_type == 3)) // tagged frame
|
75 |
|
|
begin // attach VLAN tag
|
76 |
|
|
packet[103:96] = (L2_VLAN_TPID >> 8) & 8'hff;
|
77 |
|
|
packet[111:104] = L2_VLAN_TPID & 8'hff;
|
78 |
|
|
temp = current_VLAN_TCI;
|
79 |
|
|
packet[119:112] = temp[15:8];
|
80 |
|
|
packet[127:120] = temp[7:0];
|
81 |
|
|
length_field = length_field -4;
|
82 |
|
|
next_offset = next_offset +4;
|
83 |
|
|
end
|
84 |
|
|
|
85 |
|
|
// set type-length field
|
86 |
|
|
if ((L2_protocol_type == 0) ||
|
87 |
|
|
(L2_protocol_type == 1)) // Ethernet frame
|
88 |
|
|
begin
|
89 |
|
|
if (flow_type < 3) // Layer-2 flow
|
90 |
|
|
temp[15:0] = L2_type_field;
|
91 |
|
|
else
|
92 |
|
|
case(L3_protocol_type)
|
93 |
|
|
4: // IP Version 4
|
94 |
|
|
temp = 16'h0800;
|
95 |
|
|
6: // IP version 6
|
96 |
|
|
temp = 16'h08dd;
|
97 |
|
|
8: // TCP/IP ARP
|
98 |
|
|
temp = 16'h0806;
|
99 |
|
|
9: // IPX
|
100 |
|
|
temp = 16'h8137;
|
101 |
|
|
default:
|
102 |
|
|
temp = 16'h0800; // default is IP Version 4
|
103 |
|
|
endcase // case(L3_protocol)
|
104 |
|
|
end // if ((L2_protocol_type == 0) ||...
|
105 |
|
|
else
|
106 |
|
|
begin // 802.3 frame
|
107 |
|
|
// Allow undersize L2 frames with padding
|
108 |
|
|
// by setting length field based on payload length
|
109 |
|
|
if ((flow_type <= 2) // Layer-2 flow
|
110 |
|
|
&& (payload_length < length_field))
|
111 |
|
|
length_field = payload_length;
|
112 |
|
|
temp[15:0] = length_field[15:0];
|
113 |
|
|
end // else: !if((L2_protocol_type == 0) ||...
|
114 |
|
|
|
115 |
|
|
for (i=0; i<8; i=i+1)
|
116 |
|
|
packet[next_offset*8 +i] = temp[8+i];
|
117 |
|
|
next_offset = next_offset+1;
|
118 |
|
|
for (i=0; i<8; i=i+1)
|
119 |
|
|
packet[next_offset*8 +i] = temp[i];
|
120 |
|
|
next_offset = next_offset+1;
|
121 |
|
|
|
122 |
|
|
// set LLC header for 802.3 frames
|
123 |
|
|
if ((L2_protocol_type == 2) ||
|
124 |
|
|
(L2_protocol_type == 3)) // 802.3 frame
|
125 |
|
|
begin
|
126 |
|
|
std_LLC_header[63:48] = 16'haaaa; //DSAP and SSAP
|
127 |
|
|
std_LLC_header[47:40] = 8'd3; // control
|
128 |
|
|
std_LLC_header[39:16] = 24'd0; // org code
|
129 |
|
|
// set type field
|
130 |
|
|
if (flow_type < 3) // Layer-2 flow
|
131 |
|
|
std_LLC_header[15:0] = L2_type_field;
|
132 |
|
|
else
|
133 |
|
|
case(L3_protocol_type)
|
134 |
|
|
4: // IP Version 4
|
135 |
|
|
std_LLC_header[15:0] = 16'h0800;
|
136 |
|
|
6: // IP version 6
|
137 |
|
|
std_LLC_header[15:0] = 16'h08dd;
|
138 |
|
|
8: // TCP/IP ARP
|
139 |
|
|
std_LLC_header[15:0] = 16'h0806;
|
140 |
|
|
9: // IPX
|
141 |
|
|
std_LLC_header[15:0] = 16'h8137;
|
142 |
|
|
default:
|
143 |
|
|
std_LLC_header[15:0] = 16'h0800; // default is IPv4
|
144 |
|
|
endcase // case(L3_protocol)
|
145 |
|
|
|
146 |
|
|
if (L2_LLC_header_enable) // use user-defined header
|
147 |
|
|
begin
|
148 |
|
|
insert_header(packet, next_offset, L2_LLC_header,
|
149 |
|
|
L2_LLC_header_length);
|
150 |
|
|
next_offset = next_offset + L2_LLC_header_length;
|
151 |
|
|
end // if (L2_LLC_header_enable)
|
152 |
|
|
else
|
153 |
|
|
begin
|
154 |
|
|
insert_header(packet, next_offset, std_LLC_header, 8);
|
155 |
|
|
next_offset = next_offset + 8;
|
156 |
|
|
end // else: !if(L2_LLC_header_enable)
|
157 |
|
|
end // if ((L2_protocol_type == 2) ||...
|
158 |
|
|
|
159 |
|
|
L3_header_position = next_offset;
|
160 |
|
|
if (flow_type < 3) // Layer-2 flow
|
161 |
|
|
payload_position = next_offset;
|
162 |
|
|
end // else: !if(L2_custom_header_enable)
|
163 |
|
|
end
|
164 |
|
|
endtask // add_L2_header
|
165 |
|
|
|
166 |
|
|
task add_L3_header;
|
167 |
|
|
inout [`MAX_PKT_SIZE*8 -1:0] packet;
|
168 |
|
|
|
169 |
|
|
reg [`MAX_HEADER_SIZE*8-1:0] L3_header;
|
170 |
|
|
integer length;
|
171 |
|
|
reg [31:0] x;
|
172 |
|
|
|
173 |
|
|
begin
|
174 |
|
|
if (L3_custom_header_enable) // use user-defined header
|
175 |
|
|
begin
|
176 |
|
|
insert_header(packet, L3_header_position, L3_custom_header,
|
177 |
|
|
L3_custom_header_length);
|
178 |
|
|
L4_header_position = L3_header_position + L3_custom_header_length;
|
179 |
|
|
if (flow_type < 5) // Layer-4 flow
|
180 |
|
|
payload_position = L4_header_position;
|
181 |
|
|
end // if (L3_custom_header_enable)
|
182 |
|
|
else
|
183 |
|
|
begin
|
184 |
|
|
case (L3_protocol_type)
|
185 |
|
|
4: // IP Version 4
|
186 |
|
|
begin
|
187 |
|
|
L3_header[159:156] = 4'h4;// Version = 4
|
188 |
|
|
L3_header[155:152] = 4'd5 + IP_ext_header_length/4;
|
189 |
|
|
// size of datagram
|
190 |
|
|
|
191 |
|
|
L3_header[151:144] = IP_service_type;// TOS field
|
192 |
|
|
|
193 |
|
|
// Determine length of datagram
|
194 |
|
|
length = current_pkt_size - L3_header_position -4; // leave 4 bytes for CRC
|
195 |
|
|
// check payload length defined by user
|
196 |
|
|
if (flow_type >= 5) // Layer-4 flow
|
197 |
|
|
begin
|
198 |
|
|
if (L4_protocol_type == 1) // UDP, header length = 8 bytes
|
199 |
|
|
begin
|
200 |
|
|
if ((payload_length + 20 + IP_ext_header_length + 8)
|
201 |
|
|
< length)
|
202 |
|
|
length = payload_length + 20 + IP_ext_header_length + 8;
|
203 |
|
|
end // if (L4_protocol_type == 1)
|
204 |
|
|
else // TCP, header length = 20 bytes
|
205 |
|
|
begin
|
206 |
|
|
if ((payload_length + 20 + IP_ext_header_length + 20) < length)
|
207 |
|
|
length = payload_length + 20 + IP_ext_header_length + 20;
|
208 |
|
|
end // else: !if(L4_protocol_type == 1)
|
209 |
|
|
end // if (flow_type >= 5)
|
210 |
|
|
else // Layer-3 flow
|
211 |
|
|
if ((payload_length + 20 + IP_ext_header_length) < length)
|
212 |
|
|
length = payload_length + 20 + IP_ext_header_length;
|
213 |
|
|
|
214 |
|
|
L3_header[143:128] = length[15:0];
|
215 |
|
|
L3_header[127:112] = L3_sequence_number[15:0]; //IP sequence number
|
216 |
|
|
L3_sequence_number = L3_sequence_number+1;
|
217 |
|
|
|
218 |
|
|
L3_header[111:109] = IP_flags[2:0]; // IP flags
|
219 |
|
|
L3_header[108:96] = IP_fragment_offset[12:0]; // fragment offset
|
220 |
|
|
|
221 |
|
|
L3_header[95:88] = L3_TTL[7:0]; // IP time to live
|
222 |
|
|
L3_header[87:80] = IP_protocol_field[7:0]; // L4 protocol
|
223 |
|
|
// If flow is defined as Layer-4 set protocol field
|
224 |
|
|
// according to the L4 protocol defined
|
225 |
|
|
if (flow_type >= 5) // Layer-4 flow
|
226 |
|
|
case(L4_protocol_type)
|
227 |
|
|
0: // TCP
|
228 |
|
|
L3_header[87:80] = 8'h06;
|
229 |
|
|
1: // UDP
|
230 |
|
|
L3_header[87:80] = 8'h11;
|
231 |
|
|
endcase // case(L4_protocol_type)
|
232 |
|
|
L3_header[79:64] = 16'h0; // reset IP checksum
|
233 |
|
|
L3_header[63:32] = L3_src_address;
|
234 |
|
|
L3_header[31:0] = L3_dstn_address;
|
235 |
|
|
// calculate IP checksum
|
236 |
|
|
L3_header[79:64] = IP_checksum(L3_header, 20);
|
237 |
|
|
|
238 |
|
|
// insert IP header in packet
|
239 |
|
|
insert_header(packet, L3_header_position, L3_header, 20);
|
240 |
|
|
|
241 |
|
|
// insert IP extension header
|
242 |
|
|
if (IP_ext_header_length != 0)
|
243 |
|
|
insert_header(packet, L3_header_position + 20,
|
244 |
|
|
IP_ext_header, IP_ext_header_length);
|
245 |
|
|
L4_header_position = L3_header_position + 20 +
|
246 |
|
|
IP_ext_header_length;
|
247 |
|
|
payload_position = L4_header_position;
|
248 |
|
|
end // case: 4
|
249 |
|
|
default:
|
250 |
|
|
begin
|
251 |
|
|
L4_header_position = L3_header_position;
|
252 |
|
|
payload_position = L4_header_position;
|
253 |
|
|
end // case: default
|
254 |
|
|
endcase // case(L3_protocol_type)
|
255 |
|
|
end // else: !if(L3_custom_header_enable)
|
256 |
|
|
end
|
257 |
|
|
endtask // add_L3_header
|
258 |
|
|
|
259 |
|
|
task add_L4_header;
|
260 |
|
|
inout [`MAX_PKT_SIZE*8 -1:0] packet;
|
261 |
|
|
reg [`MAX_HEADER_SIZE*8-1:0] L4_header;
|
262 |
|
|
|
263 |
|
|
integer length;
|
264 |
|
|
|
265 |
|
|
begin
|
266 |
|
|
if (L4_custom_header_enable) // use user-defined header
|
267 |
|
|
begin
|
268 |
|
|
insert_header(packet, L4_header_position, L4_custom_header,
|
269 |
|
|
L4_custom_header_length);
|
270 |
|
|
payload_position = L4_header_position + L4_custom_header_length;
|
271 |
|
|
end // if (L4_custom_header_enable)
|
272 |
|
|
else
|
273 |
|
|
begin
|
274 |
|
|
case(L4_protocol_type)
|
275 |
|
|
|
276 |
|
|
1: begin // UDP, header size = 8 bytes
|
277 |
|
|
L4_header[63:48] = L4_src_port;
|
278 |
|
|
L4_header[47:32] = L4_dstn_port;
|
279 |
|
|
|
280 |
|
|
// Determine length field
|
281 |
|
|
length = current_pkt_size - L4_header_position -4; // leave 4 bytes for CRC
|
282 |
|
|
// check payload length defined by user
|
283 |
|
|
if ((payload_length + 8) < length)
|
284 |
|
|
length = payload_length + 8;
|
285 |
|
|
|
286 |
|
|
L4_header[31:16] = length[15:0];
|
287 |
|
|
L4_header[15:0] = 0; // calculate checksum later after constructing payload
|
288 |
|
|
|
289 |
|
|
insert_header(packet, L4_header_position, L4_header, 8);
|
290 |
|
|
payload_position = L4_header_position + 8;
|
291 |
|
|
end
|
292 |
|
|
|
293 |
|
|
default: begin // TCP, header size = 20 bytes
|
294 |
|
|
|
295 |
|
|
L4_header[159:144] = L4_src_port;
|
296 |
|
|
L4_header[143:128] = L4_dstn_port;
|
297 |
|
|
L4_header[127:96] = L4_sequence_number;
|
298 |
|
|
L4_header[95:64] = L4_ack_number;
|
299 |
|
|
L4_header[63:60] = 4'd5; // length of header in 32-bit words
|
300 |
|
|
L4_header[59:54] = 6'd0; // reserved field
|
301 |
|
|
L4_header[53:48] = TCP_flags;
|
302 |
|
|
L4_header[47:32] = TCP_window_size;
|
303 |
|
|
L4_header[31:16] = 16'd0; // calculate checksum later
|
304 |
|
|
L4_header[15:0] = TCP_urgent_pointer; // calculate checksum later
|
305 |
|
|
insert_header(packet, L4_header_position, L4_header, 20);
|
306 |
|
|
payload_position = L4_header_position + 20;
|
307 |
|
|
|
308 |
|
|
// update TCP sequence number
|
309 |
|
|
length = current_pkt_size - payload_position - 4; // leave 4 bytes for CRC
|
310 |
|
|
if (payload_length < length)
|
311 |
|
|
length = payload_length;
|
312 |
|
|
L4_sequence_number = L4_sequence_number + length;
|
313 |
|
|
end // case: default
|
314 |
|
|
endcase // case(L4_protocol_type)
|
315 |
|
|
end // else: !if(L4_custom_header_enable)
|
316 |
|
|
end
|
317 |
|
|
endtask // add_L4_header
|
318 |
|
|
|
319 |
|
|
task add_payload;
|
320 |
|
|
inout [`MAX_PKT_SIZE*8 -1:0] packet;
|
321 |
|
|
|
322 |
|
|
integer length, checksum_position, i, j;
|
323 |
|
|
reg [31:0] x;
|
324 |
|
|
reg [7:0] payload_byte;
|
325 |
|
|
reg [15:0] next_word;
|
326 |
|
|
reg [31:0] checksum;
|
327 |
|
|
|
328 |
|
|
begin
|
329 |
|
|
|
330 |
|
|
length = current_pkt_size - payload_position;
|
331 |
|
|
if (flowrec_crc_option != 2'b10)
|
332 |
|
|
length = length - 4; // leave 4 bytes for CRC
|
333 |
|
|
if (payload_length < length)
|
334 |
|
|
length = payload_length;
|
335 |
|
|
case(payload_option)
|
336 |
|
|
0: begin // increasing sequence of bytes
|
337 |
|
|
payload_byte = payload_start;
|
338 |
|
|
for (i = payload_position; i < (payload_position+length); i = i+1)
|
339 |
|
|
begin
|
340 |
|
|
for (j=0; j<8; j=j+1)
|
341 |
|
|
packet[i*8 +j] = payload_byte[j];
|
342 |
|
|
payload_byte = payload_byte +1;
|
343 |
|
|
end // for (i = payload_position; i < (payload_position+length); i = i+1)
|
344 |
|
|
end // case: 0
|
345 |
|
|
|
346 |
|
|
1: begin // decreasing sequence of bytes
|
347 |
|
|
payload_byte = payload_start;
|
348 |
|
|
for (i = payload_position; i < (payload_position+length); i = i+1)
|
349 |
|
|
begin
|
350 |
|
|
for (j=0; j<8; j=j+1)
|
351 |
|
|
packet[i*8 +j] = payload_byte[j];
|
352 |
|
|
payload_byte = payload_byte -1;
|
353 |
|
|
end // for (i = payload_position; i < (payload_position+length); i = i+1)
|
354 |
|
|
end // case: 1
|
355 |
|
|
|
356 |
|
|
2: begin // random payload
|
357 |
|
|
for (i = payload_position; i < (payload_position+length); i = i+1)
|
358 |
|
|
begin
|
359 |
|
|
x = $random();
|
360 |
|
|
for (j=0; j<8; j=j+1)
|
361 |
|
|
packet[i*8 +j] = x[j];
|
362 |
|
|
end // for (i = payload_position; i < (payload_position+length); i = i+1)
|
363 |
|
|
end // case: 2
|
364 |
|
|
|
365 |
|
|
3: begin // user-defined payload
|
366 |
|
|
for (i=0; i < length; i = i+1)
|
367 |
|
|
for (j=0; j < 8; j= j+1)
|
368 |
|
|
packet[(payload_position+i)*8 +j] = user_payload[(length-i-1)*8 +j];
|
369 |
|
|
end // case: 3
|
370 |
|
|
endcase // case(payload_option)
|
371 |
|
|
|
372 |
|
|
// for TCP and UDP flows, update L4 checksum
|
373 |
|
|
if (flow_type >= 5)
|
374 |
|
|
begin
|
375 |
|
|
if (L4_protocol_type == 1) // UDP
|
376 |
|
|
checksum_position = L4_header_position + 6; // position of checksum in pkt
|
377 |
|
|
else // TCP
|
378 |
|
|
checksum_position = L4_header_position + 16;
|
379 |
|
|
|
380 |
|
|
// determine length of packet, including TCP/UDP header
|
381 |
|
|
length = current_pkt_size - payload_position - 4; // leave 4 bytes for CRC
|
382 |
|
|
if (payload_length < length)
|
383 |
|
|
length = payload_length;
|
384 |
|
|
if (L4_protocol_type == 1) // UDP
|
385 |
|
|
length = length + 8;
|
386 |
|
|
else // TCP
|
387 |
|
|
length = length + 20;
|
388 |
|
|
|
389 |
|
|
// calculate checksum
|
390 |
|
|
checksum[31:0] = 32'd0;
|
391 |
|
|
for (i=0; i < length; i = i+2)
|
392 |
|
|
begin
|
393 |
|
|
next_word[15:8] = 0;
|
394 |
|
|
for (j=0; j < 8; j= j+1)
|
395 |
|
|
next_word[8+j] = packet[(L4_header_position+i)*8 +j];
|
396 |
|
|
// if length is an odd number of bytes, pad last byte with zeroes
|
397 |
|
|
next_word[7:0] = 0;
|
398 |
|
|
if ((i+1) < length)
|
399 |
|
|
for (j=0; j < 8; j= j+1)
|
400 |
|
|
next_word[j] = packet[(L4_header_position+i+1)*8 +j];
|
401 |
|
|
checksum = checksum + {16'd0, next_word[15:0]};
|
402 |
|
|
end // for (i=0; i < length; i = i+2)
|
403 |
|
|
// add pseudo header
|
404 |
|
|
checksum = checksum +
|
405 |
|
|
{16'd0, L3_src_address[31:16]} +
|
406 |
|
|
{16'd0, L3_src_address[15:0]} +
|
407 |
|
|
{16'd0, L3_dstn_address[31:16]} +
|
408 |
|
|
{16'd0, L3_dstn_address[15:0]};
|
409 |
|
|
if (L4_protocol_type == 1) // UDP
|
410 |
|
|
checksum = checksum + 32'h00000011 // protocol = 17
|
411 |
|
|
+ {16'd0, length[15:0]};
|
412 |
|
|
// length field from UDP header
|
413 |
|
|
else // TCP
|
414 |
|
|
checksum = checksum + 32'h00000006 // protocol = 6
|
415 |
|
|
+ {16'd0, length[15:0]}; // length of payload + TCP header
|
416 |
|
|
|
417 |
|
|
// add "end-around carry"
|
418 |
|
|
checksum = checksum + {16'd0, checksum[31:16]};
|
419 |
|
|
|
420 |
|
|
if (checksum[15:0] == 16'd0) // complement checksum
|
421 |
|
|
checksum[15:0] = 16'hffff;
|
422 |
|
|
|
423 |
|
|
case(L4_checksum_option)
|
424 |
|
|
0: // calculate good checksum
|
425 |
|
|
begin
|
426 |
|
|
// nothing to do
|
427 |
|
|
end // case: 0
|
428 |
|
|
|
429 |
|
|
1: // generate bad checksum
|
430 |
|
|
begin
|
431 |
|
|
x = $random();
|
432 |
|
|
if (x[15:0] == checksum[15:0]) // if we got correct checksum by accident
|
433 |
|
|
x[15] = ~x[15]; //invert MS bit;
|
434 |
|
|
checksum[15:0] = x[15:0];
|
435 |
|
|
end // case: 1
|
436 |
|
|
|
437 |
|
|
2: // set checksum to zero
|
438 |
|
|
checksum[15:0] = 16'd0;
|
439 |
|
|
|
440 |
|
|
3: // set checksum to user-defined value
|
441 |
|
|
checksum[15:0] = L4_user_checksum;
|
442 |
|
|
endcase // case(L4_checksum_option)
|
443 |
|
|
|
444 |
|
|
// insert checkum in L4 header
|
445 |
|
|
for (j=0; j < 8; j= j+1)
|
446 |
|
|
packet[checksum_position*8 +j] = checksum[8+j];
|
447 |
|
|
for (j=0; j < 8; j= j+1)
|
448 |
|
|
packet[(checksum_position +1)*8 +j] = checksum[j];
|
449 |
|
|
end // if (flow_type >= 5)
|
450 |
|
|
end
|
451 |
|
|
endtask // add_payload
|
452 |
|
|
|
453 |
|
|
task insert_header;
|
454 |
|
|
inout [`MAX_PKT_SIZE*8 -1:0] packet;
|
455 |
|
|
input offset;
|
456 |
|
|
input [`MAX_HEADER_SIZE*8-1:0] header;
|
457 |
|
|
input length;
|
458 |
|
|
integer offset, length;
|
459 |
|
|
integer i,j;
|
460 |
|
|
begin
|
461 |
|
|
if (length != 0)
|
462 |
|
|
for (i=0; i < length; i = i+1)
|
463 |
|
|
for (j=0; j < 8; j= j+1)
|
464 |
|
|
packet[(offset+i)*8 +j] = header[(length-i-1)*8 +j];
|
465 |
|
|
end
|
466 |
|
|
endtask // insert_header
|
467 |
|
|
|
468 |
|
|
task construct_pause_frame;
|
469 |
|
|
// Constructs an 802.3x PAUSE frame
|
470 |
|
|
input [47:0] src_mac;
|
471 |
|
|
input [15:0] pause_time;
|
472 |
|
|
output [`MAX_PKT_SIZE*8 -1:0] packet;
|
473 |
|
|
output size;
|
474 |
|
|
integer i,j, size;
|
475 |
|
|
|
476 |
|
|
reg [47:0] mac_addr;
|
477 |
|
|
reg [15:0] temp;
|
478 |
|
|
begin
|
479 |
|
|
size = 64;
|
480 |
|
|
// clear packet
|
481 |
|
|
packet = 0;
|
482 |
|
|
// construct header;
|
483 |
|
|
mac_addr = `PAUSE_DEST_MAC;
|
484 |
|
|
//swap bytes in MAC address
|
485 |
|
|
// MS byte goes first on the link
|
486 |
|
|
packet[ 7: 0] = mac_addr[47:40];
|
487 |
|
|
packet[15: 8] = mac_addr[39:32];
|
488 |
|
|
packet[23:16] = mac_addr[31:24];
|
489 |
|
|
packet[31:24] = mac_addr[23:16];
|
490 |
|
|
packet[39:32] = mac_addr[15: 8];
|
491 |
|
|
packet[47:40] = mac_addr[ 7: 0];
|
492 |
|
|
|
493 |
|
|
mac_addr = src_mac;
|
494 |
|
|
packet[55:48] = mac_addr[47:40];
|
495 |
|
|
packet[63:56] = mac_addr[39:32];
|
496 |
|
|
packet[71:64] = mac_addr[31:24];
|
497 |
|
|
packet[79:72] = mac_addr[23:16];
|
498 |
|
|
packet[87:80] = mac_addr[15: 8];
|
499 |
|
|
packet[95:88] = mac_addr[ 7: 0];
|
500 |
|
|
|
501 |
|
|
// set type-length field
|
502 |
|
|
temp = `PAUSE_TYPE;
|
503 |
|
|
packet[103:96] = temp[15:8];
|
504 |
|
|
packet[111:104] = temp[7:0];
|
505 |
|
|
// set PAUSE opcode
|
506 |
|
|
temp = `PAUSE_OPCODE;
|
507 |
|
|
packet[119:112] = temp[15:8];
|
508 |
|
|
packet[127:120] = temp[7:0];
|
509 |
|
|
|
510 |
|
|
// set pause parameter
|
511 |
|
|
temp = pause_time;
|
512 |
|
|
packet[135:128] = temp[15:8];
|
513 |
|
|
packet[143:136] = temp[7:0];
|
514 |
|
|
end
|
515 |
|
|
endtask // construct_pause_frame
|
516 |
|
|
|
517 |
|
|
function [15:0] IP_checksum;
|
518 |
|
|
input [`MAX_PKT_SIZE*8 -1:0] header;
|
519 |
|
|
input length;
|
520 |
|
|
integer length;
|
521 |
|
|
reg [31:0] checksum;
|
522 |
|
|
reg [15:0] next_word;
|
523 |
|
|
integer i, j;
|
524 |
|
|
reg [31:0] x;
|
525 |
|
|
|
526 |
|
|
begin
|
527 |
|
|
// compute header checksum
|
528 |
|
|
checksum[31:0] = 32'd0;
|
529 |
|
|
for (i=0; i< length/2; i=i+1)
|
530 |
|
|
begin
|
531 |
|
|
for (j=0; j<16; j=j+1)
|
532 |
|
|
next_word[j] = header[i*16 +j]; // get next 16 bits
|
533 |
|
|
checksum = checksum + {16'd0, next_word[15:0]};
|
534 |
|
|
end // for (j=0; j<16; j=j+1)
|
535 |
|
|
|
536 |
|
|
// include IP extension header, if present
|
537 |
|
|
if (IP_ext_header_length != 0)
|
538 |
|
|
begin
|
539 |
|
|
for (i=0; i< IP_ext_header_length/2; i=i+1)
|
540 |
|
|
begin
|
541 |
|
|
for (j=0; j<16; j=j+1)
|
542 |
|
|
next_word[j] = IP_ext_header[i*16 +j]; // get next 16 bits
|
543 |
|
|
checksum = checksum + {16'd0, next_word[15:0]};
|
544 |
|
|
end // for (j=0; j<16; j=j+1)
|
545 |
|
|
end // if (IP_ext_header_length != 0)
|
546 |
|
|
|
547 |
|
|
// add "end-around carry"
|
548 |
|
|
checksum = checksum + {16'd0, checksum[31:16]};
|
549 |
|
|
|
550 |
|
|
case (L3_checksum_option)
|
551 |
|
|
0: // calculate good checksum
|
552 |
|
|
begin
|
553 |
|
|
IP_checksum = ~checksum[15:0];
|
554 |
|
|
end // case: 0
|
555 |
|
|
|
556 |
|
|
1: // generate bad checksum
|
557 |
|
|
begin
|
558 |
|
|
x = $random();
|
559 |
|
|
if (x[15:0] == ~checksum[15:0])
|
560 |
|
|
// if the checksum is good by accident
|
561 |
|
|
x[15:0] = x[15:0] ^ 16'h8000; // complement MS bit
|
562 |
|
|
IP_checksum = x[15:0];
|
563 |
|
|
end // case: 1
|
564 |
|
|
|
565 |
|
|
2: // set checksum to zero
|
566 |
|
|
IP_checksum = 16'd0;
|
567 |
|
|
|
568 |
|
|
3: // set checksum to user-defined value
|
569 |
|
|
IP_checksum = L3_user_checksum;
|
570 |
|
|
endcase // case(L3_checksum_option[flow_id])
|
571 |
|
|
end
|
572 |
|
|
endfunction
|
573 |
|
|
|