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

Subversion Repositories udp_ipv4_for_10g_ethernet

[/] [udp_ipv4_for_10g_ethernet/] [trunk/] [src/] [hdl/] [frame_process.vhd] - Rev 3

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- (C) Copyright 2013 DFC Design, s.r.o., Brno, Czech Republic
-- Author: Marek Kvas (m.kvas@dfcdesign.cz)
--
-------------------------------------------------------------------------------
-- This file is part of UDP/IPv4 for 10 G Ethernet core.
-- 
-- UDP/IPv4 for 10 G Ethernet core is free software: you can 
-- redistribute it and/or modify it under the terms of 
-- the GNU Lesser General Public License as published by the Free 
-- Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- 
-- UDP/IPv4 for 10 G Ethernet core is distributed in the hope that 
-- it will be useful, but WITHOUT ANY WARRANTY; without even 
-- the implied warranty of MERCHANTABILITY or FITNESS FOR A 
-- PARTICULAR PURPOSE.  See the GNU Lesser General Public License 
-- for more details.
-- 
-- You should have received a copy of the GNU Lesser General Public 
-- License along with UDP/IPv4 for 10 G Ethernet core.  If not, 
-- see <http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------------
--
-- This core processes UDP/IPv4 frames. It is supposed to be connected to
-- frame_received core on input as it assumes aligned raw data with
-- convenient data valid and byte enable signals + checksum validation flags.
--
-- The purpose of this block is to filter out packets that are not intended
-- for us. All packets thats destination MAC and IP addresses don't match
-- set host addresses are rejected. Broadcast packets can be accepted too.
--
--
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
library work;
use work.frame_pkg.all;
 
Library UNISIM;
use UNISIM.vcomponents.all;
 
 
entity frame_process is
   port (
      RST               : in  std_logic;
      CLK               : in  std_logic;
 
      -- Interface towards frame receiver
      RX_DATA           : in  std_logic_vector(63 downto 0);
      RX_DV             : in  std_logic;
      RX_BE             : in  std_logic_vector(7 downto 0);
      RX_ERR            : in  std_logic;
      RX_ERR_VALID      : in  std_logic;
 
      -- Interfaces of tag and data fifos
      DFIFO_DATA        : out fp_dfifo_data_type;
      DFIFO_WR_EN       : out std_logic;
      DFIFO_FULL        : in  std_logic;
 
      TFIFO_DATA        : out fp_tfifo_data_type;
      TFIFO_WR_EN       : out std_logic;
      TFIFO_FULL        : in  std_logic;
 
      -- Host MAC and IP addresses
      MAC_ADDR          : in  mac_addr_type;
      IP_ADDR           : in  ip_addr_type;
      IP_NET_MASK       : in  ip_addr_type
        );
end entity;
 
 
architecture synthesis of frame_process is
 
   -- Constants
   constant LC_MAC_ADDR_BITLEN      : integer := 48;
   constant LC_DST_MAC_POS_RIGHT    : integer := 0;
   constant LC_DST_MAC_POS_LEFT     : integer := LC_DST_MAC_POS_RIGHT +
                                                 LC_MAC_ADDR_BITLEN - 1;
   constant LC_MAC_BROADCAST_ADDR   : std_logic_vector(LC_MAC_ADDR_BITLEN - 1
                                                   downto 0) := (others => '1');
 
   constant LC_MAC_ETHERTYPE_BITLEN : integer := 16;
   constant LC_MAC_ETHERTYPE_POS_RIGHT : integer := 12 * 8;
   constant LC_MAC_ETHERTYPE_POS_LEFT  : integer := LC_MAC_ETHERTYPE_POS_RIGHT +
                                                    LC_MAC_ETHERTYPE_BITLEN - 1;
 
   constant LC_MAC_ETHERTYPE_IPV4   : std_logic_vector(LC_MAC_ETHERTYPE_BITLEN -1
                                       downto 0) := x"0800";
   constant LC_MAC_ETHERTYPE_ARP    : std_logic_vector(LC_MAC_ETHERTYPE_BITLEN -1
                                       downto 0) := x"0806";
   constant LC_IP_ADDR_BITLEN       : integer := 32;
   constant LC_DST_IP_POS_RIGHT     : integer := 6*8;
   constant LC_DST_IP_POS_LEFT      : integer := LC_DST_IP_POS_RIGHT +
                                                 LC_IP_ADDR_BITLEN - 1;
   constant LC_IP_PROTO_BITLEN      : integer := 8;
   constant LC_IP_PROTO_POS_RIGHT   : integer := 7*8;   
   constant LC_IP_PROTO_POS_LEFT    : integer := LC_IP_PROTO_POS_RIGHT + 
                                                 LC_IP_PROTO_BITLEN - 1;
   constant LC_IP_PROTO_UDP         : std_logic_vector(LC_IP_PROTO_BITLEN - 1 
                                                         downto 0) := x"11";
   constant LC_THIS_NET_BROADCAST_IP: std_logic_vector(LC_IP_ADDR_BITLEN - 1 
                                                      downto 0) := x"ffffffff";
   constant LC_UDP_ADDR_BITLEN      : integer := 16;
   constant LC_DST_UDP_POS_RIGHT    : integer := 4*8;
   constant LC_DST_UDP_POS_LEFT     : integer := LC_DST_UDP_POS_RIGHT + 
                                                 LC_UDP_ADDR_BITLEN - 1;
   constant LC_UDP_LENGTH_BITLEN    : integer := 16;
   constant LC_UDP_LENGTH_POS_RIGHT : integer := 6*8;
   constant LC_UDP_LENGTH_POS_LEFT  : integer := LC_UDP_LENGTH_POS_RIGHT + 
                                                 LC_UDP_LENGTH_BITLEN - 1;
   constant LC_UDP_DATA_POS         : integer := 2*8;
   constant LC_UDP_HDR_LEN          : integer := 8;
 
 
   constant LC_SRC_MAC_BITLEN       : integer := 32;
   constant LC_SRC_MAC_POS_RIGHT0   : integer := 6*8;   
   constant LC_SRC_MAC_POS_LEFT0    : integer := LC_SRC_MAC_POS_RIGHT0 + 
                                          LC_SRC_MAC_BITLEN - 1;
 
   constant LC_SRC_MAC_BITLEN1      : integer := 16;
   constant LC_SRC_MAC_POS_RIGHT1   : integer := 2*8;   
   constant LC_SRC_MAC_POS_LEFT1    : integer := LC_SRC_MAC_POS_RIGHT1 + 
                                          LC_SRC_MAC_BITLEN1 - 1;
 
   constant LC_SRC_IP_BITLEN        : integer := 16;
   constant LC_SRC_IP_POS_RIGHT0    : integer := 18*8;   
   constant LC_SRC_IP_POS_LEFT0     : integer := LC_SRC_IP_POS_RIGHT0 + 
                                         LC_SRC_IP_BITLEN - 1;
 
   constant LC_SRC_IP_BITLEN1       : integer := 16;
   constant LC_SRC_IP_POS_RIGHT1    : integer := 4*8;   
   constant LC_SRC_IP_POS_LEFT1     : integer := LC_SRC_IP_POS_RIGHT1 + 
                                         LC_SRC_IP_BITLEN1 - 1;
 
 
   constant LC_SRC_UDP_BITLEN       : integer := 16;
   constant LC_SRC_UDP_POS_RIGHT    : integer := 10*8;   
   constant LC_SRC_UDP_POS_LEFT     : integer := LC_SRC_UDP_POS_RIGHT + 
                                                 LC_SRC_UDP_BITLEN - 1;                                                 
 
 
   -- Main FSM sorting frames and stripping headers
   type sort_fsm_type is (S_MAC0, S_MAC1_IP0, S_IP1, S_IP2, S_IP3_UDP0,
                          S_UDP1_DATA, 
                          --S_CHECK_ERR, 
                          S_TAG, 
                          S_TAG_DISCARD,
                          S_MAC1_ARP 
                       --   ,S_FILTERED
                       );
   signal sort_fsm_cur  : sort_fsm_type;
   signal sort_fsm_next : sort_fsm_type;
 
   -- FSM control signals
   signal all_data_written    : std_logic;
   signal load_udp_data_length: std_logic;
   signal write_udp_data      : std_logic;
 
   signal cur_broadcast       : std_logic;
   signal cur_broadcast_s     : std_logic;
   signal cur_broadcast_r     : std_logic;
 
   signal mac_ethertype_ipv4  : std_logic;
   signal mac_ethertype_arp   : std_logic;
   signal mac_filter_unicast  : std_logic;
   signal mac_filter_broadcast: std_logic;
 
   signal ip_filter_unicast   : std_logic;
   signal ip_filter_broadcast : std_logic;
   signal ip_next_proto_udp   : std_logic;
 
   signal udp_data_length     : unsigned(C_FP_TAG_LENGTH_BITLEN - 1 downto 0);
   signal udp_data_length_reg : unsigned(udp_data_length'range);
 
   signal rx_udp_be           : std_logic_vector(RX_BE'range);
   signal rx_udp_data         : std_logic_vector(RX_DATA'range);
 
   -- internal form of output ports
   signal tfifo_wr_en_i       : std_logic;
   signal tfifo_data_i        : fp_tfifo_data_type;
 
   -- Counter of data to send
   signal data_cnt            : unsigned(15 downto 0);
   -- Counter of data to be discarded if needed
   signal data_to_discard     : unsigned(data_cnt'range);
 
   signal dst_udp_reg         : udp_port_type;
   signal dst_udp_port        : udp_port_type;
 
   -- Register versions of inputs
   signal rx_data_d           : std_logic_vector(63 downto 0);
   signal rx_dv_d             : std_logic;
   signal rx_be_d             : std_logic_vector(7 downto 0);
   signal rx_err_d            : std_logic;
   signal rx_err_valid_d      : std_logic;
   signal rx_err_dd           : std_logic;
   signal rx_be_dd            : std_logic_vector(7 downto 0);
   signal rx_dv_dd            : std_logic;
   signal rx_data_dd          : std_logic_vector(63 downto 0);
   signal rx_err_valid_dd     : std_logic;
   signal rx_err_ddd          : std_logic;
   signal rx_be_ddd           : std_logic_vector(7 downto 0);
   signal rx_dv_ddd           : std_logic;
   signal rx_dv_dddd          : std_logic;
   signal rx_data_ddd         : std_logic_vector(63 downto 0);
   signal rx_err_valid_ddd    : std_logic;
 
 
 
   -- Function definitions
   -- Cut out byte enables from two delayed words - compensate for shift in UDP
   function derive_udp_be_func(be_ddd : std_logic_vector;
                           be_dd : std_logic_vector) return std_logic_vector is
      variable res : std_logic_vector(be_dd'range);
      variable tmp : std_logic_vector(be_dd'length * 2 - 1 downto 0);
   begin
 
      -- We know the offset for standard UDP packet (without options)
 
      tmp := be_dd & be_ddd;
      res := tmp(LC_UDP_DATA_POS/8 + be_dd'left downto LC_UDP_DATA_POS/8);
 
      return res;
   end function;
 
 
   -- Cut out data from two delayed words - compensate for shift in UDP
   function derive_udp_data_func(data_ddd : std_logic_vector;
                           data_dd : std_logic_vector) return std_logic_vector is
      variable res : std_logic_vector(data_dd'range);
      variable tmp : std_logic_vector(data_dd'length * 2 - 1 downto 0);
   begin
 
      -- We know the offset for standard UDP packet (without options)
      tmp := data_dd & data_ddd;
      res := tmp(LC_UDP_DATA_POS + data_dd'left downto LC_UDP_DATA_POS);
      return res;
   end function;
 
   -- Basically finds first 1 bit from left (MSB) to find out
   -- how many byte enables is 1 (gaps are not alowed)
   function be_to_cnt_udp_func(be_ddd : std_logic_vector;
                           be_dd : std_logic_vector) return integer is
      variable tmp : std_logic_vector(be_ddd'range);
      variable res : integer range 0 to be_ddd'length;
   begin
      tmp := derive_udp_be_func(be_ddd, be_dd);
      for i in tmp'left downto 0 loop
         if tmp(i) = '1' then
            return i + 1;
         end if;
      end loop;
      return 0;
   end function;
 
 
   -- Change endians
   function swap_bytes(fi : std_logic_vector) return std_logic_vector is
      variable f   : std_logic_vector(fi'length - 1 downto 0);
      variable res : std_logic_vector(f'length - 1 downto 0);
      variable blen : integer;
   begin
      f := fi;
      blen := f'length/8 - 1;
      for i in 0 to blen loop
         res(i*8 + 7 downto i * 8) := f((blen - i)*8 + 7 downto (blen - i) * 8);
      end loop;
      return res;
   end Function;
 
   function swap_bytes(f : unsigned) return unsigned is
   begin
      return unsigned(swap_bytes(std_logic_vector(f)));
   end function;
 
begin
 
   -- Create delayed signal, first to isolate from previous
   -- block, second to align filter results with data
   delay_input_proc : process (RST, CLK)
   begin
      if RST = '1' then
         rx_data_d         <= (others => '0');
         rx_data_dd        <= (others => '0');
         rx_data_ddd       <= (others => '0');
         rx_dv_d           <= '0';
         rx_dv_dd          <= '0';
         rx_dv_ddd         <= '0';
         rx_dv_dddd         <= '0';
         rx_be_d           <= (others => '0');
         rx_be_dd          <= (others => '0');
         rx_be_ddd         <= (others => '0');
         rx_err_d          <= '0';
         rx_err_dd         <= '0';
         rx_err_ddd        <= '0';
         rx_err_valid_d    <= '0';
         rx_err_valid_dd   <= '0';
         rx_err_valid_ddd  <= '0';
      elsif rising_edge(CLK) then
         rx_data_d         <= RX_DATA;  
         rx_data_dd        <= rx_data_d;
         rx_data_ddd       <= rx_data_dd;
         rx_dv_d           <= RX_DV;
         rx_dv_dd          <= rx_dv_d;
         rx_dv_ddd         <= rx_dv_dd;
         rx_dv_dddd        <= rx_dv_ddd;
         rx_be_d           <= RX_BE;
         rx_be_dd          <= rx_be_d;
         rx_be_ddd         <= rx_be_dd;
         rx_err_d          <= RX_ERR;
         rx_err_dd         <= rx_err_d;
         rx_err_ddd        <= rx_err_dd;
         rx_err_valid_d    <= RX_ERR_VALID;
         rx_err_valid_dd   <= rx_err_valid_d;  
         rx_err_valid_ddd  <= rx_err_valid_dd;  
      end if;
   end process;
 
 
   -- Main FSM sorting frames and stripping headers
   sort_fsm_adv_proc : process (CLK, RST)
   begin
      if RST ='1' then
         sort_fsm_cur <= S_MAC0;
         cur_broadcast <= '0';
      elsif rising_edge(CLK) then
         sort_fsm_cur <= sort_fsm_next;
 
         if cur_broadcast_s = '1' then
            cur_broadcast <= '1';
         elsif cur_broadcast_r = '1' then
            cur_broadcast <= '0';
         end if;
      end if;
   end process;
 
   sort_fsm_trans_out_proc : process (sort_fsm_cur, dst_udp_port,
                                      udp_data_length, rx_dv_ddd, rx_dv_dddd, 
                                      mac_filter_unicast, mac_filter_broadcast,
                                      mac_ethertype_ipv4, mac_ethertype_arp,
                                      ip_filter_unicast, ip_filter_broadcast,
                                      all_data_written, ip_next_proto_udp, 
                                      DFIFO_FULL, rx_err_valid_ddd, 
                                      rx_err_ddd, TFIFO_FULL, cur_broadcast, 
                                      data_to_discard, rx_data_d, rx_data_dd, rx_data_ddd)
     variable header : std_logic_vector(3*64-1 downto 0);
   begin
 
      header := rx_data_d & rx_data_dd & rx_data_ddd; 
 
      load_udp_data_length  <= '0';
      write_udp_data <= '0';
 
      tfifo_wr_en_i <= '0';
      cur_broadcast_s <= '0';
      cur_broadcast_r <= '0';
 
      -- Dafault state of tfifo data
      tfifo_data_i <= C_FP_TAG_UDP & dst_udp_port & 
                                             std_logic_vector(udp_data_length);
 
      sort_fsm_next <= sort_fsm_cur;
 
      case sort_fsm_cur is
         when S_MAC0 =>
            cur_broadcast_r <= '1';
            if rx_dv_ddd = '1' and rx_dv_dddd = '0' then
               -- Process only our packets and broadcast
               if mac_filter_unicast = '1' or
                  mac_filter_broadcast = '1' then
                  if mac_filter_broadcast = '1' then
                     -- Remember we process broadcast
                     -- because we will need to know later
                     cur_broadcast_s <= '1';
                  end if;
                  -- Differentiate between IPv4 and ARP
                  if mac_ethertype_ipv4 = '1' then
                     sort_fsm_next <= S_MAC1_IP0;
                  elsif mac_ethertype_arp = '1' then
                     sort_fsm_next <= S_MAC1_ARP;
                  else
                     -- We process IPv4 and ARP packets only
                     NULL;
                  end if;
                  -- Save the first part of return info - part of src MAC addr
                  if TFIFO_FULL = '0' then
                     tfifo_wr_en_i <= '1';
                  else
                     -- tag FIFO full; As nothing has been written yet
                     -- we can stay in this state and wait for next frame
                     sort_fsm_next <= S_MAC0;
                  end if;
                  tfifo_data_i <= C_FP_TAG_RETINF & 
                     swap_bytes(header(LC_SRC_MAC_POS_LEFT0 downto 
                                                      LC_SRC_MAC_POS_RIGHT0));
               end if;
            end if;
         when S_MAC1_ARP =>
            -- ARP not supported in this version
            sort_fsm_next <= S_MAC0;
         when S_MAC1_IP0 =>
            -- Only first ten bytes of IP header available
            if rx_dv_ddd = '1' then
               sort_fsm_next <= S_IP1;
               -- Save the second part of return info - rest of src MAC addr
               -- and part of src IP
               if TFIFO_FULL = '0' then
                  tfifo_wr_en_i <= '1';
               else
                  -- tag FIFO full; no date have been written so just ignere pkt
                  sort_fsm_next <= S_MAC0;
               end if;
               tfifo_data_i <= C_FP_TAG_RETINF & 
                  swap_bytes(header(LC_SRC_MAC_POS_LEFT1 downto 
                                                   LC_SRC_MAC_POS_RIGHT1)) &
                  swap_bytes(header(LC_SRC_IP_POS_LEFT0 downto 
                                                   LC_SRC_IP_POS_RIGHT0));
            else
               sort_fsm_next <= S_TAG_DISCARD;
            end if;
         when S_IP1 =>
            -- Check if next protocol is UDP
            -- Destination IP is not yet completely loaded
            if rx_dv_ddd = '1' and
               ip_next_proto_udp = '1' then
               sort_fsm_next <= S_IP2;
            else
               sort_fsm_next <= S_MAC0;
            end if;
         when S_IP2 =>
            -- Continue if destination address is ours or
            -- broadcast and MAC was broadcast too
            if rx_dv_ddd = '1' and
               ((ip_filter_unicast = '1' and   cur_broadcast = '0')or
                (ip_filter_broadcast = '1' and cur_broadcast = '1')
               ) then
               sort_fsm_next <= S_IP3_UDP0;
               -- Save the third part of return info - rest of src IP addr
               -- and src UDP port
               if TFIFO_FULL = '0' then
                  tfifo_wr_en_i <= '1';
               else
                  -- data FIFO full; discard if anything has been written
                  sort_fsm_next <= S_MAC0;
               end if;
               tfifo_data_i <= C_FP_TAG_RETINF & 
                  swap_bytes(header(LC_SRC_IP_POS_LEFT1 downto 
                                                LC_SRC_IP_POS_RIGHT1)) &
                  swap_bytes(header(LC_SRC_UDP_POS_LEFT downto 
                                                LC_SRC_UDP_POS_RIGHT));
 
            else
               sort_fsm_next <= S_MAC0;
            end if;
         when S_IP3_UDP0 =>
            -- Now we can determine destination socket
            -- based on destination UDP port
            if rx_dv_ddd = '1' then
               load_udp_data_length <= '1';
               sort_fsm_next <= S_UDP1_DATA;
            else
               sort_fsm_next <= S_MAC0;
            end if;
         when S_UDP1_DATA =>
            -- For UDP data are not aligned and first two bytes
            -- are mixed with header; because we want data aligned
            -- in fifo it may happen that there are no data
            -- to write in last cycle of dv
            if rx_dv_ddd = '1' then
               if all_data_written = '0' then
                  if DFIFO_FULL = '0' then
                     write_udp_data <= '1';
                  else
                     -- We dont have space in data fifo; data will be 
                     -- corrupted; discard packet
                     -- Data are still valid so we have enough time
                     -- to go to discard state
                     sort_fsm_next <= S_TAG_DISCARD;
                  end if;
               end if;
            else
               if all_data_written = '0' or
                  rx_err_ddd = '1'then
                  -- DV deasserted before all data received
                  -- or error occurred in packet
                  -- We don't have time to go to discard state
                  -- write discard tag now (minimal IFG is only one cycle)
                  if TFIFO_FULL = '0' then
                     tfifo_wr_en_i <= '1';
                     sort_fsm_next <= S_MAC0;
                  else
                     -- Tag fifo is full go waiting for space for discard tag
                     sort_fsm_next <= S_TAG_DISCARD;
                  end if;
                  tfifo_data_i <= C_FP_TAG_DISCARD & dst_udp_port & 
                                          std_logic_vector(data_to_discard);
               else
                  -- All is fine, write ok tag
                  if TFIFO_FULL = '0' then
                     -- Write default - i.e. length and destination port
                     tfifo_wr_en_i <= '1';
                     sort_fsm_next <= S_MAC0;
                  else
                     -- There is no space for tag, go waiting
                     sort_fsm_next <= S_TAG;
                  end if;
               end if;
            end if;
         when S_TAG =>
            -- Wait until there is space in tag fifo and write ok tag
            if TFIFO_FULL = '0' then
               -- Write default - i.e. length and destination port
               tfifo_wr_en_i <= '1';
               sort_fsm_next <= S_MAC0;
            end if;
         when S_TAG_DISCARD =>
            -- Wait until there is space in tag fifo and write discard tag
            if TFIFO_FULL = '0' then
               tfifo_wr_en_i <= '1';
               sort_fsm_next <= S_MAC0;
            end if;
            tfifo_data_i <= C_FP_TAG_DISCARD & dst_udp_port & 
                                             std_logic_vector(data_to_discard);
--         when S_FILTERED =>
--            -- Wait until packet that we don't care of ends
--            if rx_dv_ddd = '0' then
--               sort_fsm_next <= S_MAC0;
--            end if;
      end case;
 
   end process;
 
   -- Count data written; check against
   -- header info - valid for UDP only
   data_cnt_proc : process (RST, CLK)
      variable be_cnt : integer;
   begin
      if RST = '1' then
         data_cnt <= (others => '0');
         data_to_discard <= (others => '0');
         all_data_written <= '0';
      elsif rising_edge(CLK) then
         if load_udp_data_length = '1' then
            -- Subtract 8 as a length of UDP_HEADER
            udp_data_length <= swap_bytes(udp_data_length_reg) - LC_UDP_HDR_LEN;
            data_cnt <= swap_bytes(udp_data_length_reg) - LC_UDP_HDR_LEN;
            dst_udp_port <= swap_bytes(dst_udp_reg);
            all_data_written <= '0';
            data_to_discard <= (others => '0');
         elsif write_udp_data = '1' then
            -- Count data for case of discarding
            -- hede we don't have to play on byte enables
            data_to_discard <= data_to_discard + 8;
 
            -- Now, we have to derive how many bytes to write
            if data_cnt > 8 then
               -- Most often case
               data_cnt <= data_cnt - 8;
            elsif data_cnt = 8 then
               -- Data were 8 by aligned
               data_cnt <= data_cnt - 8;
               all_data_written <= '1';
            elsif data_cnt < 8 then
               be_cnt := be_to_cnt_udp_func(rx_be_ddd, rx_be_dd);
               if be_cnt >= data_cnt then
                  -- If equal it is ok; if more there are 
                  -- trailing data in packet and it is fine too
                  data_cnt <= (others => '0');
                  all_data_written <= '1';
               else
                  -- Packet was shorter and will be discarded
                  -- because DV will go down
                  null;    
               end if;
            end if;
         end if;
      end if;
   end process;
 
   rx_udp_be   <= derive_udp_be_func(rx_be_ddd, rx_be_dd);
   rx_udp_data <= derive_udp_data_func(rx_data_ddd, rx_data_dd);
 
 
 
   -- Register udp length and dst port
   udp_length_reg_proc : process (RST, CLK)
      variable header : std_logic_vector(127 downto 0);
   begin
      if RST = '1' then
         udp_data_length_reg <= (others => '0');
      elsif rising_edge(CLK) then
         header := rx_data_d & rx_data_dd;
         udp_data_length_reg <= unsigned(
                  header(LC_UDP_LENGTH_POS_LEFT downto LC_UDP_LENGTH_POS_RIGHT));
         dst_udp_reg <= header(LC_DST_UDP_POS_LEFT downto LC_DST_UDP_POS_RIGHT);
      end if;
   end process;
 
 
   -- Filters for various info from header
   -- Output is aligned with data in ddd version
 
   -- MAC filter; Check ethertype field of MAC
   mac_filter_proc : process (RST, CLK)
      variable header      : std_logic_vector(127 downto 0);
      variable dst_mac     : std_logic_vector(LC_MAC_ADDR_BITLEN - 1 downto 0);
      variable ethertype   : std_logic_vector(LC_MAC_ETHERTYPE_BITLEN -1
                                                                     downto 0);
   begin
      if RST = '1' then
         mac_filter_unicast   <= '0';
         mac_filter_broadcast <= '0';
         mac_ethertype_ipv4   <= '0';
         mac_ethertype_arp    <= '0';
      elsif rising_edge(CLK) then
 
         mac_filter_unicast   <= '0';
         mac_filter_broadcast <= '0';
         mac_ethertype_ipv4   <= '0';
         mac_ethertype_arp    <= '0';
 
         -- Extract destination MAC and ethertype from received headers
         header := rx_data_d & rx_data_dd;
         dst_mac := header(LC_DST_MAC_POS_LEFT downto LC_DST_MAC_POS_RIGHT);
         ethertype := header(LC_MAC_ETHERTYPE_POS_LEFT downto 
                                                   LC_MAC_ETHERTYPE_POS_RIGHT);
         -- Check for broadcast MAC
         if dst_mac = LC_MAC_BROADCAST_ADDR then
            mac_filter_broadcast <= '1';
         end if;
         -- Check for unicast with our MAC
         if dst_mac = swap_bytes(MAC_ADDR) then
            mac_filter_unicast <= '1';
         end if;
 
         -- Check for ipv4 ethertype
         if ethertype = swap_bytes(LC_MAC_ETHERTYPE_IPV4) then
            mac_ethertype_ipv4 <= '1';
         end if;
         -- Check for arp ethertype
         if ethertype = swap_bytes(LC_MAC_ETHERTYPE_ARP) then
            mac_ethertype_arp <= '1';
         end if;
 
      end if;
   end process;
 
 
   -- IP filter; Check for UDP as next protocol
   ip_filter_proc : process (RST, CLK)
      variable header : std_logic_vector(127 downto 0);
      variable dst_ip : std_logic_vector(LC_IP_ADDR_BITLEN - 1 downto 0);
      variable next_proto : std_logic_vector(LC_IP_PROTO_BITLEN - 1 downto 0);
      variable tmpip : ip_addr_type;
   begin
      if RST = '1' then
         ip_filter_unicast <= '0';
         ip_filter_broadcast <= '0';
         ip_next_proto_udp <= '0';
      elsif rising_edge(CLK) then
 
         ip_filter_unicast <= '0';
         ip_filter_broadcast <= '0';
         ip_next_proto_udp <= '0';
 
         -- Extract destination IP from received headers
         header := rx_data_d & rx_data_dd;
         dst_ip := header(LC_DST_IP_POS_LEFT downto LC_DST_IP_POS_RIGHT);
         next_proto := header(LC_IP_PROTO_POS_LEFT downto LC_IP_PROTO_POS_RIGHT);
         -- Check for broadcast IP
         tmpip := IP_ADDR and IP_NET_MASK;
         if (swap_bytes(dst_ip) and IP_NET_MASK)  = tmpip or
            dst_ip = LC_THIS_NET_BROADCAST_IP then
            ip_filter_broadcast <= '1';
         end if;
         -- Check for unicast with our IP
         if dst_ip = swap_bytes(IP_ADDR) then
            ip_filter_unicast <= '1';
         end if;
         -- Check for UDP as next protocol
         if next_proto = LC_IP_PROTO_UDP then
            ip_next_proto_udp <= '1';
         end if;
      end if;
   end process;
 
   -- Outputs assignment
   TFIFO_DATA <= tfifo_data_i;
   TFIFO_WR_EN <= tfifo_wr_en_i;
 
   DFIFO_DATA <= rx_udp_be & rx_udp_data;
   DFIFO_WR_EN <= write_udp_data;
 
 
end architecture;
 
 
 
 
 
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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