OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [ip_repo/] [udp_ip_10g/] [src/] [hdl/] [frame_process.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
-------------------------------------------------------------------------------
2
--
3
-- (C) Copyright 2013 DFC Design, s.r.o., Brno, Czech Republic
4
-- Author: Marek Kvas (m.kvas@dfcdesign.cz)
5
--
6
-------------------------------------------------------------------------------
7
-- This file is part of UDP/IPv4 for 10 G Ethernet core.
8
-- 
9
-- UDP/IPv4 for 10 G Ethernet core is free software: you can 
10
-- redistribute it and/or modify it under the terms of 
11
-- the GNU Lesser General Public License as published by the Free 
12
-- Software Foundation, either version 3 of the License, or
13
-- (at your option) any later version.
14
-- 
15
-- UDP/IPv4 for 10 G Ethernet core is distributed in the hope that 
16
-- it will be useful, but WITHOUT ANY WARRANTY; without even 
17
-- the implied warranty of MERCHANTABILITY or FITNESS FOR A 
18
-- PARTICULAR PURPOSE.  See the GNU Lesser General Public License 
19
-- for more details.
20
-- 
21
-- You should have received a copy of the GNU Lesser General Public 
22
-- License along with UDP/IPv4 for 10 G Ethernet core.  If not, 
23
-- see <http://www.gnu.org/licenses/>.
24
-------------------------------------------------------------------------------
25
--
26
-- This core processes UDP/IPv4 frames. It is supposed to be connected to
27
-- frame_received core on input as it assumes aligned raw data with
28
-- convenient data valid and byte enable signals + checksum validation flags.
29
--
30
-- The purpose of this block is to filter out packets that are not intended
31
-- for us. All packets thats destination MAC and IP addresses don't match
32
-- set host addresses are rejected. Broadcast packets can be accepted too.
33
--
34
--
35
-------------------------------------------------------------------------------
36
 
37
library ieee;
38
use ieee.std_logic_1164.all;
39
use ieee.numeric_std.all;
40
 
41
library work;
42
use work.frame_pkg.all;
43
 
44
Library UNISIM;
45
use UNISIM.vcomponents.all;
46
 
47
 
48
entity frame_process is
49
   port (
50
      RST               : in  std_logic;
51
      CLK               : in  std_logic;
52
 
53
      -- Interface towards frame receiver
54
      RX_DATA           : in  std_logic_vector(63 downto 0);
55
      RX_DV             : in  std_logic;
56
      RX_BE             : in  std_logic_vector(7 downto 0);
57
      RX_ERR            : in  std_logic;
58
      RX_ERR_VALID      : in  std_logic;
59
 
60
      -- Interfaces of tag and data fifos
61
      DFIFO_DATA        : out fp_dfifo_data_type;
62
      DFIFO_WR_EN       : out std_logic;
63
      DFIFO_FULL        : in  std_logic;
64
 
65
      TFIFO_DATA        : out fp_tfifo_data_type;
66
      TFIFO_WR_EN       : out std_logic;
67
      TFIFO_FULL        : in  std_logic;
68
 
69
      -- Host MAC and IP addresses
70
      MAC_ADDR          : in  mac_addr_type;
71
      IP_ADDR           : in  ip_addr_type;
72
      IP_NET_MASK       : in  ip_addr_type
73
        );
74
end entity;
75
 
76
 
77
architecture synthesis of frame_process is
78
 
79
   -- Constants
80
   constant LC_MAC_ADDR_BITLEN      : integer := 48;
81
   constant LC_DST_MAC_POS_RIGHT    : integer := 0;
82
   constant LC_DST_MAC_POS_LEFT     : integer := LC_DST_MAC_POS_RIGHT +
83
                                                 LC_MAC_ADDR_BITLEN - 1;
84
   constant LC_MAC_BROADCAST_ADDR   : std_logic_vector(LC_MAC_ADDR_BITLEN - 1
85
                                                   downto 0) := (others => '1');
86
 
87
   constant LC_MAC_ETHERTYPE_BITLEN : integer := 16;
88
   constant LC_MAC_ETHERTYPE_POS_RIGHT : integer := 12 * 8;
89
   constant LC_MAC_ETHERTYPE_POS_LEFT  : integer := LC_MAC_ETHERTYPE_POS_RIGHT +
90
                                                    LC_MAC_ETHERTYPE_BITLEN - 1;
91
 
92
   constant LC_MAC_ETHERTYPE_IPV4   : std_logic_vector(LC_MAC_ETHERTYPE_BITLEN -1
93
                                       downto 0) := x"0800";
94
   constant LC_MAC_ETHERTYPE_ARP    : std_logic_vector(LC_MAC_ETHERTYPE_BITLEN -1
95
                                       downto 0) := x"0806";
96
   constant LC_IP_ADDR_BITLEN       : integer := 32;
97
   constant LC_DST_IP_POS_RIGHT     : integer := 6*8;
98
   constant LC_DST_IP_POS_LEFT      : integer := LC_DST_IP_POS_RIGHT +
99
                                                 LC_IP_ADDR_BITLEN - 1;
100
   constant LC_IP_PROTO_BITLEN      : integer := 8;
101
   constant LC_IP_PROTO_POS_RIGHT   : integer := 7*8;
102
   constant LC_IP_PROTO_POS_LEFT    : integer := LC_IP_PROTO_POS_RIGHT +
103
                                                 LC_IP_PROTO_BITLEN - 1;
104
   constant LC_IP_PROTO_UDP         : std_logic_vector(LC_IP_PROTO_BITLEN - 1
105
                                                         downto 0) := x"11";
106
   constant LC_THIS_NET_BROADCAST_IP: std_logic_vector(LC_IP_ADDR_BITLEN - 1
107
                                                      downto 0) := x"ffffffff";
108
   constant LC_UDP_ADDR_BITLEN      : integer := 16;
109
   constant LC_DST_UDP_POS_RIGHT    : integer := 4*8;
110
   constant LC_DST_UDP_POS_LEFT     : integer := LC_DST_UDP_POS_RIGHT +
111
                                                 LC_UDP_ADDR_BITLEN - 1;
112
   constant LC_UDP_LENGTH_BITLEN    : integer := 16;
113
   constant LC_UDP_LENGTH_POS_RIGHT : integer := 6*8;
114
   constant LC_UDP_LENGTH_POS_LEFT  : integer := LC_UDP_LENGTH_POS_RIGHT +
115
                                                 LC_UDP_LENGTH_BITLEN - 1;
116
   constant LC_UDP_DATA_POS         : integer := 2*8;
117
   constant LC_UDP_HDR_LEN          : integer := 8;
118
 
119
 
120
   constant LC_SRC_MAC_BITLEN       : integer := 32;
121
   constant LC_SRC_MAC_POS_RIGHT0   : integer := 6*8;
122
   constant LC_SRC_MAC_POS_LEFT0    : integer := LC_SRC_MAC_POS_RIGHT0 +
123
                                          LC_SRC_MAC_BITLEN - 1;
124
 
125
   constant LC_SRC_MAC_BITLEN1      : integer := 16;
126
   constant LC_SRC_MAC_POS_RIGHT1   : integer := 2*8;
127
   constant LC_SRC_MAC_POS_LEFT1    : integer := LC_SRC_MAC_POS_RIGHT1 +
128
                                          LC_SRC_MAC_BITLEN1 - 1;
129
 
130
   constant LC_SRC_IP_BITLEN        : integer := 16;
131
   constant LC_SRC_IP_POS_RIGHT0    : integer := 18*8;
132
   constant LC_SRC_IP_POS_LEFT0     : integer := LC_SRC_IP_POS_RIGHT0 +
133
                                         LC_SRC_IP_BITLEN - 1;
134
 
135
   constant LC_SRC_IP_BITLEN1       : integer := 16;
136
   constant LC_SRC_IP_POS_RIGHT1    : integer := 4*8;
137
   constant LC_SRC_IP_POS_LEFT1     : integer := LC_SRC_IP_POS_RIGHT1 +
138
                                         LC_SRC_IP_BITLEN1 - 1;
139
 
140
 
141
   constant LC_SRC_UDP_BITLEN       : integer := 16;
142
   constant LC_SRC_UDP_POS_RIGHT    : integer := 10*8;
143
   constant LC_SRC_UDP_POS_LEFT     : integer := LC_SRC_UDP_POS_RIGHT +
144
                                                 LC_SRC_UDP_BITLEN - 1;
145
 
146
 
147
   -- Main FSM sorting frames and stripping headers
148
   type sort_fsm_type is (S_MAC0, S_MAC1_IP0, S_IP1, S_IP2, S_IP3_UDP0,
149
                          S_UDP1_DATA,
150
                          --S_CHECK_ERR, 
151
                          S_TAG,
152
                          S_TAG_DISCARD,
153
                          S_MAC1_ARP
154
                       --   ,S_FILTERED
155
                       );
156
   signal sort_fsm_cur  : sort_fsm_type;
157
   signal sort_fsm_next : sort_fsm_type;
158
 
159
   -- FSM control signals
160
   signal all_data_written    : std_logic;
161
   signal load_udp_data_length: std_logic;
162
   signal write_udp_data      : std_logic;
163
 
164
   signal cur_broadcast       : std_logic;
165
   signal cur_broadcast_s     : std_logic;
166
   signal cur_broadcast_r     : std_logic;
167
 
168
   signal mac_ethertype_ipv4  : std_logic;
169
   signal mac_ethertype_arp   : std_logic;
170
   signal mac_filter_unicast  : std_logic;
171
   signal mac_filter_broadcast: std_logic;
172
 
173
   signal ip_filter_unicast   : std_logic;
174
   signal ip_filter_broadcast : std_logic;
175
   signal ip_next_proto_udp   : std_logic;
176
 
177
   signal udp_data_length     : unsigned(C_FP_TAG_LENGTH_BITLEN - 1 downto 0);
178
   signal udp_data_length_reg : unsigned(udp_data_length'range);
179
 
180
   signal rx_udp_be           : std_logic_vector(RX_BE'range);
181
   signal rx_udp_data         : std_logic_vector(RX_DATA'range);
182
 
183
   -- internal form of output ports
184
   signal tfifo_wr_en_i       : std_logic;
185
   signal tfifo_data_i        : fp_tfifo_data_type;
186
 
187
   -- Counter of data to send
188
   signal data_cnt            : unsigned(15 downto 0);
189
   -- Counter of data to be discarded if needed
190
   signal data_to_discard     : unsigned(data_cnt'range);
191
 
192
   signal dst_udp_reg         : udp_port_type;
193
   signal dst_udp_port        : udp_port_type;
194
 
195
   -- Register versions of inputs
196
   signal rx_data_d           : std_logic_vector(63 downto 0);
197
   signal rx_dv_d             : std_logic;
198
   signal rx_be_d             : std_logic_vector(7 downto 0);
199
   signal rx_err_d            : std_logic;
200
   signal rx_err_valid_d      : std_logic;
201
   signal rx_err_dd           : std_logic;
202
   signal rx_be_dd            : std_logic_vector(7 downto 0);
203
   signal rx_dv_dd            : std_logic;
204
   signal rx_data_dd          : std_logic_vector(63 downto 0);
205
   signal rx_err_valid_dd     : std_logic;
206
   signal rx_err_ddd          : std_logic;
207
   signal rx_be_ddd           : std_logic_vector(7 downto 0);
208
   signal rx_dv_ddd           : std_logic;
209
   signal rx_dv_dddd          : std_logic;
210
   signal rx_data_ddd         : std_logic_vector(63 downto 0);
211
   signal rx_err_valid_ddd    : std_logic;
212
 
213
 
214
 
215
   -- Function definitions
216
   -- Cut out byte enables from two delayed words - compensate for shift in UDP
217
   function derive_udp_be_func(be_ddd : std_logic_vector;
218
                           be_dd : std_logic_vector) return std_logic_vector is
219
      variable res : std_logic_vector(be_dd'range);
220
      variable tmp : std_logic_vector(be_dd'length * 2 - 1 downto 0);
221
   begin
222
 
223
      -- We know the offset for standard UDP packet (without options)
224
 
225
      tmp := be_dd & be_ddd;
226
      res := tmp(LC_UDP_DATA_POS/8 + be_dd'left downto LC_UDP_DATA_POS/8);
227
 
228
      return res;
229
   end function;
230
 
231
 
232
   -- Cut out data from two delayed words - compensate for shift in UDP
233
   function derive_udp_data_func(data_ddd : std_logic_vector;
234
                           data_dd : std_logic_vector) return std_logic_vector is
235
      variable res : std_logic_vector(data_dd'range);
236
      variable tmp : std_logic_vector(data_dd'length * 2 - 1 downto 0);
237
   begin
238
 
239
      -- We know the offset for standard UDP packet (without options)
240
      tmp := data_dd & data_ddd;
241
      res := tmp(LC_UDP_DATA_POS + data_dd'left downto LC_UDP_DATA_POS);
242
      return res;
243
   end function;
244
 
245
   -- Basically finds first 1 bit from left (MSB) to find out
246
   -- how many byte enables is 1 (gaps are not alowed)
247
   function be_to_cnt_udp_func(be_ddd : std_logic_vector;
248
                           be_dd : std_logic_vector) return integer is
249
      variable tmp : std_logic_vector(be_ddd'range);
250
      variable res : integer range 0 to be_ddd'length;
251
   begin
252
      tmp := derive_udp_be_func(be_ddd, be_dd);
253
      for i in tmp'left downto 0 loop
254
         if tmp(i) = '1' then
255
            return i + 1;
256
         end if;
257
      end loop;
258
      return 0;
259
   end function;
260
 
261
 
262
   -- Change endians
263
   function swap_bytes(fi : std_logic_vector) return std_logic_vector is
264
      variable f   : std_logic_vector(fi'length - 1 downto 0);
265
      variable res : std_logic_vector(f'length - 1 downto 0);
266
      variable blen : integer;
267
   begin
268
      f := fi;
269
      blen := f'length/8 - 1;
270
      for i in 0 to blen loop
271
         res(i*8 + 7 downto i * 8) := f((blen - i)*8 + 7 downto (blen - i) * 8);
272
      end loop;
273
      return res;
274
   end Function;
275
 
276
   function swap_bytes(f : unsigned) return unsigned is
277
   begin
278
      return unsigned(swap_bytes(std_logic_vector(f)));
279
   end function;
280
 
281
begin
282
 
283
   -- Create delayed signal, first to isolate from previous
284
   -- block, second to align filter results with data
285
   delay_input_proc : process (RST, CLK)
286
   begin
287
      if RST = '1' then
288
         rx_data_d         <= (others => '0');
289
         rx_data_dd        <= (others => '0');
290
         rx_data_ddd       <= (others => '0');
291
         rx_dv_d           <= '0';
292
         rx_dv_dd          <= '0';
293
         rx_dv_ddd         <= '0';
294
         rx_dv_dddd         <= '0';
295
         rx_be_d           <= (others => '0');
296
         rx_be_dd          <= (others => '0');
297
         rx_be_ddd         <= (others => '0');
298
         rx_err_d          <= '0';
299
         rx_err_dd         <= '0';
300
         rx_err_ddd        <= '0';
301
         rx_err_valid_d    <= '0';
302
         rx_err_valid_dd   <= '0';
303
         rx_err_valid_ddd  <= '0';
304
      elsif rising_edge(CLK) then
305
         rx_data_d         <= RX_DATA;
306
         rx_data_dd        <= rx_data_d;
307
         rx_data_ddd       <= rx_data_dd;
308
         rx_dv_d           <= RX_DV;
309
         rx_dv_dd          <= rx_dv_d;
310
         rx_dv_ddd         <= rx_dv_dd;
311
         rx_dv_dddd        <= rx_dv_ddd;
312
         rx_be_d           <= RX_BE;
313
         rx_be_dd          <= rx_be_d;
314
         rx_be_ddd         <= rx_be_dd;
315
         rx_err_d          <= RX_ERR;
316
         rx_err_dd         <= rx_err_d;
317
         rx_err_ddd        <= rx_err_dd;
318
         rx_err_valid_d    <= RX_ERR_VALID;
319
         rx_err_valid_dd   <= rx_err_valid_d;
320
         rx_err_valid_ddd  <= rx_err_valid_dd;
321
      end if;
322
   end process;
323
 
324
 
325
   -- Main FSM sorting frames and stripping headers
326
   sort_fsm_adv_proc : process (CLK, RST)
327
   begin
328
      if RST ='1' then
329
         sort_fsm_cur <= S_MAC0;
330
         cur_broadcast <= '0';
331
      elsif rising_edge(CLK) then
332
         sort_fsm_cur <= sort_fsm_next;
333
 
334
         if cur_broadcast_s = '1' then
335
            cur_broadcast <= '1';
336
         elsif cur_broadcast_r = '1' then
337
            cur_broadcast <= '0';
338
         end if;
339
      end if;
340
   end process;
341
 
342
   sort_fsm_trans_out_proc : process (sort_fsm_cur, dst_udp_port,
343
                                      udp_data_length, rx_dv_ddd, rx_dv_dddd,
344
                                      mac_filter_unicast, mac_filter_broadcast,
345
                                      mac_ethertype_ipv4, mac_ethertype_arp,
346
                                      ip_filter_unicast, ip_filter_broadcast,
347
                                      all_data_written, ip_next_proto_udp,
348
                                      DFIFO_FULL, rx_err_valid_ddd,
349
                                      rx_err_ddd, TFIFO_FULL, cur_broadcast,
350
                                      data_to_discard, rx_data_d, rx_data_dd, rx_data_ddd)
351
     variable header : std_logic_vector(3*64-1 downto 0);
352
   begin
353
 
354
      header := rx_data_d & rx_data_dd & rx_data_ddd;
355
 
356
      load_udp_data_length  <= '0';
357
      write_udp_data <= '0';
358
 
359
      tfifo_wr_en_i <= '0';
360
      cur_broadcast_s <= '0';
361
      cur_broadcast_r <= '0';
362
 
363
      -- Dafault state of tfifo data
364
      tfifo_data_i <= C_FP_TAG_UDP & dst_udp_port &
365
                                             std_logic_vector(udp_data_length);
366
 
367
      sort_fsm_next <= sort_fsm_cur;
368
 
369
      case sort_fsm_cur is
370
         when S_MAC0 =>
371
            cur_broadcast_r <= '1';
372
            if rx_dv_ddd = '1' and rx_dv_dddd = '0' then
373
               -- Process only our packets and broadcast
374
               if mac_filter_unicast = '1' or
375
                  mac_filter_broadcast = '1' then
376
                  if mac_filter_broadcast = '1' then
377
                     -- Remember we process broadcast
378
                     -- because we will need to know later
379
                     cur_broadcast_s <= '1';
380
                  end if;
381
                  -- Differentiate between IPv4 and ARP
382
                  if mac_ethertype_ipv4 = '1' then
383
                     sort_fsm_next <= S_MAC1_IP0;
384
                  elsif mac_ethertype_arp = '1' then
385
                     sort_fsm_next <= S_MAC1_ARP;
386
                  else
387
                     -- We process IPv4 and ARP packets only
388
                     NULL;
389
                  end if;
390
                  -- Save the first part of return info - part of src MAC addr
391
                  if TFIFO_FULL = '0' then
392
                     tfifo_wr_en_i <= '1';
393
                  else
394
                     -- tag FIFO full; As nothing has been written yet
395
                     -- we can stay in this state and wait for next frame
396
                     sort_fsm_next <= S_MAC0;
397
                  end if;
398
                  tfifo_data_i <= C_FP_TAG_RETINF &
399
                     swap_bytes(header(LC_SRC_MAC_POS_LEFT0 downto
400
                                                      LC_SRC_MAC_POS_RIGHT0));
401
               end if;
402
            end if;
403
         when S_MAC1_ARP =>
404
            -- ARP not supported in this version
405
            sort_fsm_next <= S_MAC0;
406
         when S_MAC1_IP0 =>
407
            -- Only first ten bytes of IP header available
408
            if rx_dv_ddd = '1' then
409
               sort_fsm_next <= S_IP1;
410
               -- Save the second part of return info - rest of src MAC addr
411
               -- and part of src IP
412
               if TFIFO_FULL = '0' then
413
                  tfifo_wr_en_i <= '1';
414
               else
415
                  -- tag FIFO full; no date have been written so just ignere pkt
416
                  sort_fsm_next <= S_MAC0;
417
               end if;
418
               tfifo_data_i <= C_FP_TAG_RETINF &
419
                  swap_bytes(header(LC_SRC_MAC_POS_LEFT1 downto
420
                                                   LC_SRC_MAC_POS_RIGHT1)) &
421
                  swap_bytes(header(LC_SRC_IP_POS_LEFT0 downto
422
                                                   LC_SRC_IP_POS_RIGHT0));
423
            else
424
               sort_fsm_next <= S_TAG_DISCARD;
425
            end if;
426
         when S_IP1 =>
427
            -- Check if next protocol is UDP
428
            -- Destination IP is not yet completely loaded
429
            if rx_dv_ddd = '1' and
430
               ip_next_proto_udp = '1' then
431
               sort_fsm_next <= S_IP2;
432
            else
433
               sort_fsm_next <= S_MAC0;
434
            end if;
435
         when S_IP2 =>
436
            -- Continue if destination address is ours or
437
            -- broadcast and MAC was broadcast too
438
            if rx_dv_ddd = '1' and
439
               ((ip_filter_unicast = '1' and   cur_broadcast = '0')or
440
                (ip_filter_broadcast = '1' and cur_broadcast = '1')
441
               ) then
442
               sort_fsm_next <= S_IP3_UDP0;
443
               -- Save the third part of return info - rest of src IP addr
444
               -- and src UDP port
445
               if TFIFO_FULL = '0' then
446
                  tfifo_wr_en_i <= '1';
447
               else
448
                  -- data FIFO full; discard if anything has been written
449
                  sort_fsm_next <= S_MAC0;
450
               end if;
451
               tfifo_data_i <= C_FP_TAG_RETINF &
452
                  swap_bytes(header(LC_SRC_IP_POS_LEFT1 downto
453
                                                LC_SRC_IP_POS_RIGHT1)) &
454
                  swap_bytes(header(LC_SRC_UDP_POS_LEFT downto
455
                                                LC_SRC_UDP_POS_RIGHT));
456
 
457
            else
458
               sort_fsm_next <= S_MAC0;
459
            end if;
460
         when S_IP3_UDP0 =>
461
            -- Now we can determine destination socket
462
            -- based on destination UDP port
463
            if rx_dv_ddd = '1' then
464
               load_udp_data_length <= '1';
465
               sort_fsm_next <= S_UDP1_DATA;
466
            else
467
               sort_fsm_next <= S_MAC0;
468
            end if;
469
         when S_UDP1_DATA =>
470
            -- For UDP data are not aligned and first two bytes
471
            -- are mixed with header; because we want data aligned
472
            -- in fifo it may happen that there are no data
473
            -- to write in last cycle of dv
474
            if rx_dv_ddd = '1' then
475
               if all_data_written = '0' then
476
                  if DFIFO_FULL = '0' then
477
                     write_udp_data <= '1';
478
                  else
479
                     -- We dont have space in data fifo; data will be 
480
                     -- corrupted; discard packet
481
                     -- Data are still valid so we have enough time
482
                     -- to go to discard state
483
                     sort_fsm_next <= S_TAG_DISCARD;
484
                  end if;
485
               end if;
486
            else
487
               if all_data_written = '0' or
488
                  rx_err_ddd = '1'then
489
                  -- DV deasserted before all data received
490
                  -- or error occurred in packet
491
                  -- We don't have time to go to discard state
492
                  -- write discard tag now (minimal IFG is only one cycle)
493
                  if TFIFO_FULL = '0' then
494
                     tfifo_wr_en_i <= '1';
495
                     sort_fsm_next <= S_MAC0;
496
                  else
497
                     -- Tag fifo is full go waiting for space for discard tag
498
                     sort_fsm_next <= S_TAG_DISCARD;
499
                  end if;
500
                  tfifo_data_i <= C_FP_TAG_DISCARD & dst_udp_port &
501
                                          std_logic_vector(data_to_discard);
502
               else
503
                  -- All is fine, write ok tag
504
                  if TFIFO_FULL = '0' then
505
                     -- Write default - i.e. length and destination port
506
                     tfifo_wr_en_i <= '1';
507
                     sort_fsm_next <= S_MAC0;
508
                  else
509
                     -- There is no space for tag, go waiting
510
                     sort_fsm_next <= S_TAG;
511
                  end if;
512
               end if;
513
            end if;
514
         when S_TAG =>
515
            -- Wait until there is space in tag fifo and write ok tag
516
            if TFIFO_FULL = '0' then
517
               -- Write default - i.e. length and destination port
518
               tfifo_wr_en_i <= '1';
519
               sort_fsm_next <= S_MAC0;
520
            end if;
521
         when S_TAG_DISCARD =>
522
            -- Wait until there is space in tag fifo and write discard tag
523
            if TFIFO_FULL = '0' then
524
               tfifo_wr_en_i <= '1';
525
               sort_fsm_next <= S_MAC0;
526
            end if;
527
            tfifo_data_i <= C_FP_TAG_DISCARD & dst_udp_port &
528
                                             std_logic_vector(data_to_discard);
529
--         when S_FILTERED =>
530
--            -- Wait until packet that we don't care of ends
531
--            if rx_dv_ddd = '0' then
532
--               sort_fsm_next <= S_MAC0;
533
--            end if;
534
      end case;
535
 
536
   end process;
537
 
538
   -- Count data written; check against
539
   -- header info - valid for UDP only
540
   data_cnt_proc : process (RST, CLK)
541
      variable be_cnt : integer;
542
   begin
543
      if RST = '1' then
544
         data_cnt <= (others => '0');
545
         data_to_discard <= (others => '0');
546
         all_data_written <= '0';
547
      elsif rising_edge(CLK) then
548
         if load_udp_data_length = '1' then
549
            -- Subtract 8 as a length of UDP_HEADER
550
            udp_data_length <= swap_bytes(udp_data_length_reg) - LC_UDP_HDR_LEN;
551
            data_cnt <= swap_bytes(udp_data_length_reg) - LC_UDP_HDR_LEN;
552
            dst_udp_port <= swap_bytes(dst_udp_reg);
553
            all_data_written <= '0';
554
            data_to_discard <= (others => '0');
555
         elsif write_udp_data = '1' then
556
            -- Count data for case of discarding
557
            -- hede we don't have to play on byte enables
558
            data_to_discard <= data_to_discard + 8;
559
 
560
            -- Now, we have to derive how many bytes to write
561
            if data_cnt > 8 then
562
               -- Most often case
563
               data_cnt <= data_cnt - 8;
564
            elsif data_cnt = 8 then
565
               -- Data were 8 by aligned
566
               data_cnt <= data_cnt - 8;
567
               all_data_written <= '1';
568
            elsif data_cnt < 8 then
569
               be_cnt := be_to_cnt_udp_func(rx_be_ddd, rx_be_dd);
570
               if be_cnt >= data_cnt then
571
                  -- If equal it is ok; if more there are 
572
                  -- trailing data in packet and it is fine too
573
                  data_cnt <= (others => '0');
574
                  all_data_written <= '1';
575
               else
576
                  -- Packet was shorter and will be discarded
577
                  -- because DV will go down
578
                  null;
579
               end if;
580
            end if;
581
         end if;
582
      end if;
583
   end process;
584
 
585
   rx_udp_be   <= derive_udp_be_func(rx_be_ddd, rx_be_dd);
586
   rx_udp_data <= derive_udp_data_func(rx_data_ddd, rx_data_dd);
587
 
588
 
589
 
590
   -- Register udp length and dst port
591
   udp_length_reg_proc : process (RST, CLK)
592
      variable header : std_logic_vector(127 downto 0);
593
   begin
594
      if RST = '1' then
595
         udp_data_length_reg <= (others => '0');
596
      elsif rising_edge(CLK) then
597
         header := rx_data_d & rx_data_dd;
598
         udp_data_length_reg <= unsigned(
599
                  header(LC_UDP_LENGTH_POS_LEFT downto LC_UDP_LENGTH_POS_RIGHT));
600
         dst_udp_reg <= header(LC_DST_UDP_POS_LEFT downto LC_DST_UDP_POS_RIGHT);
601
      end if;
602
   end process;
603
 
604
 
605
   -- Filters for various info from header
606
   -- Output is aligned with data in ddd version
607
 
608
   -- MAC filter; Check ethertype field of MAC
609
   mac_filter_proc : process (RST, CLK)
610
      variable header      : std_logic_vector(127 downto 0);
611
      variable dst_mac     : std_logic_vector(LC_MAC_ADDR_BITLEN - 1 downto 0);
612
      variable ethertype   : std_logic_vector(LC_MAC_ETHERTYPE_BITLEN -1
613
                                                                     downto 0);
614
   begin
615
      if RST = '1' then
616
         mac_filter_unicast   <= '0';
617
         mac_filter_broadcast <= '0';
618
         mac_ethertype_ipv4   <= '0';
619
         mac_ethertype_arp    <= '0';
620
      elsif rising_edge(CLK) then
621
 
622
         mac_filter_unicast   <= '0';
623
         mac_filter_broadcast <= '0';
624
         mac_ethertype_ipv4   <= '0';
625
         mac_ethertype_arp    <= '0';
626
 
627
         -- Extract destination MAC and ethertype from received headers
628
         header := rx_data_d & rx_data_dd;
629
         dst_mac := header(LC_DST_MAC_POS_LEFT downto LC_DST_MAC_POS_RIGHT);
630
         ethertype := header(LC_MAC_ETHERTYPE_POS_LEFT downto
631
                                                   LC_MAC_ETHERTYPE_POS_RIGHT);
632
         -- Check for broadcast MAC
633
         if dst_mac = LC_MAC_BROADCAST_ADDR then
634
            mac_filter_broadcast <= '1';
635
         end if;
636
         -- Check for unicast with our MAC
637
         if dst_mac = swap_bytes(MAC_ADDR) then
638
            mac_filter_unicast <= '1';
639
         end if;
640
 
641
         -- Check for ipv4 ethertype
642
         if ethertype = swap_bytes(LC_MAC_ETHERTYPE_IPV4) then
643
            mac_ethertype_ipv4 <= '1';
644
         end if;
645
         -- Check for arp ethertype
646
         if ethertype = swap_bytes(LC_MAC_ETHERTYPE_ARP) then
647
            mac_ethertype_arp <= '1';
648
         end if;
649
 
650
      end if;
651
   end process;
652
 
653
 
654
   -- IP filter; Check for UDP as next protocol
655
   ip_filter_proc : process (RST, CLK)
656
      variable header : std_logic_vector(127 downto 0);
657
      variable dst_ip : std_logic_vector(LC_IP_ADDR_BITLEN - 1 downto 0);
658
      variable next_proto : std_logic_vector(LC_IP_PROTO_BITLEN - 1 downto 0);
659
      variable tmpip : ip_addr_type;
660
   begin
661
      if RST = '1' then
662
         ip_filter_unicast <= '0';
663
         ip_filter_broadcast <= '0';
664
         ip_next_proto_udp <= '0';
665
      elsif rising_edge(CLK) then
666
 
667
         ip_filter_unicast <= '0';
668
         ip_filter_broadcast <= '0';
669
         ip_next_proto_udp <= '0';
670
 
671
         -- Extract destination IP from received headers
672
         header := rx_data_d & rx_data_dd;
673
         dst_ip := header(LC_DST_IP_POS_LEFT downto LC_DST_IP_POS_RIGHT);
674
         next_proto := header(LC_IP_PROTO_POS_LEFT downto LC_IP_PROTO_POS_RIGHT);
675
         -- Check for broadcast IP
676
         tmpip := IP_ADDR and IP_NET_MASK;
677
         if (swap_bytes(dst_ip) and IP_NET_MASK)  = tmpip or
678
            dst_ip = LC_THIS_NET_BROADCAST_IP then
679
            ip_filter_broadcast <= '1';
680
         end if;
681
         -- Check for unicast with our IP
682
         if dst_ip = swap_bytes(IP_ADDR) then
683
            ip_filter_unicast <= '1';
684
         end if;
685
         -- Check for UDP as next protocol
686
         if next_proto = LC_IP_PROTO_UDP then
687
            ip_next_proto_udp <= '1';
688
         end if;
689
      end if;
690
   end process;
691
 
692
   -- Outputs assignment
693
   TFIFO_DATA <= tfifo_data_i;
694
   TFIFO_WR_EN <= tfifo_wr_en_i;
695
 
696
   DFIFO_DATA <= rx_udp_be & rx_udp_data;
697
   DFIFO_WR_EN <= write_udp_data;
698
 
699
 
700
end architecture;
701
 
702
 
703
 
704
 
705
 
706
 
707
 
708
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.