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

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.interface/] [udp_ip/] [1.0/] [vhd/] [arp3.vhd] - Rev 185

Go to most recent revision | Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- arp3.vhd
--
-- Author(s):     Jussi Nieminen after Ashley Partis and Jorgen Peddersen
-- Created:       Feb 2001
-- Last Modified: 2009-09-03
-- 
-- Manages an ARP table for the network stack project.  This protocol listens
-- to incoming data and when an ARP request or reply arrives, the data of the
-- source is added to the ARP table.  The ARP table contains two entries.
-- When a request arrives a signal is also asserted telling the arp sender to
-- send an ARP reply when possible.  The incoming data from the ethernet layer
-- is a byte stream.
-- Licenced under LGPL.
-------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.udp_ip_pkg.all;
 
entity ARP is
  port (
    clk               : in  std_logic;  -- clock signal
    rstn              : in  std_logic;  -- asynchronous active low reset
    new_frame_in      : in  std_logic;  -- from ethernet layer indicates data arrival
    new_word_valid_in : in  std_logic;  -- indicates a new word in the stream
    frame_re_out      : out std_logic;
    frame_data_in     : in  std_logic_vector (15 downto 0);  -- the stream data
    frame_valid_in    : in  std_logic;  -- indicates validity
    frame_len_in      : in  std_logic_vector( tx_len_w_c-1 downto 0 );
    sending_reply_in  : in  std_logic;  -- ARP sender asserts this when the reply is been transmitted
    req_IP_in         : in  std_logic_vector (31 downto 0);  -- ARP sender can request MACs for this address
    gen_ARP_rep_out   : out std_logic;  -- tell ARP sender to generate a reply
    gen_ARP_IP_out    : out std_logic_vector (31 downto 0);  -- destination IP for generated reply
    lookup_MAC_out    : out std_logic_vector (47 downto 0);  -- if valid, MAC for requested IP
    valid_entry_out   : out std_logic;   -- indicates if req_IP_in is in table
    done_out          : out std_logic
    );
end ARP;
 
architecture ARP_arch of ARP is
 
-- State signals and types
  type STATETYPE is (stIdle, stHandleARP, stOperate, stCheckValid);
  signal presState : STATETYPE;
  signal nextState : STATETYPE;
 
  -- range of 0 to 25 should be enough, but just to be sure..
  signal cnt    : integer range 0 to 2**tx_len_w_c-1;
  signal incCnt : std_logic;              -- signal to increment cnt
  signal rstCnt : std_logic;              -- signal to clear cnt
 
  signal latchFrameData   : std_logic;  -- signal to latch stream data
  signal frameData_r      : std_logic_vector (15 downto 0);  -- register for latched data
  signal shiftSourceIPIn  : std_logic;  -- signal to shift in source IP
  signal source_IP_r      : std_logic_vector (31 downto 0);  -- stores source IP
  signal shiftSourceMACIn : std_logic;  -- signal to shift in source MAC
  signal source_MAC_r     : std_logic_vector (47 downto 0);  -- stores source MAC
 
  signal ARP_operation_r    : std_logic;  -- '0' for reply, '1' for request
  signal determineOperation : std_logic;  -- signal to latch ARP_operation_r from stream
 
  signal updateARPTable      : std_logic;  -- this signal updates the ARP table
  signal ARP_entry_IP_r      : std_logic_vector (31 downto 0);  -- most recent ARP entry IP
  signal ARP_entry_MAC_r     : std_logic_vector (47 downto 0);  -- most recent ARP entry MAC
  signal ARP_entry_IP_old_r  : std_logic_vector (31 downto 0);  -- 2nd ARP entry IP
  signal ARP_entry_MAC_old_r : std_logic_vector (47 downto 0);  -- 2nd ARP entry MAC
 
  signal doGenARPRep : std_logic;       -- asserted when an ARP reply must be generated
 
  signal frame_len_r : integer range 0 to 2**tx_len_w_c-1;
  signal frame_invalid_r : std_logic;
  signal frame_invalid : std_logic;
  signal clear_invalid : std_logic;
 
-------------------------------------------------------------------------------
begin
-------------------------------------------------------------------------------
 
  process (clk, rstn)
  begin
    if rstn = '0' then                  -- reset state and ARP entries
 
      presState           <= stIdle;
      ARP_entry_IP_r      <= (others => '0');
      ARP_entry_MAC_r     <= (others => '0');
      ARP_entry_IP_old_r  <= (others => '0');
      ARP_entry_MAC_old_r <= (others => '0');
      frame_re_out <= '0';
      cnt <= 0;
      ARP_operation_r <= '0';
      frameData_r <= (others => '0');
      source_IP_r <= (others => '0');
      source_MAC_r <= (others => '0');
      frame_invalid_r <= '0';
      gen_ARP_rep_out <= '0';
      gen_ARP_IP_out <= (others => '0');
 
    elsif clk'event and clk = '1' then
      presState <= nextState;           -- go to next state
      frame_re_out <= '0';
 
      if incCnt = '1' then              -- handle counter
        cnt <= cnt + 1;
      elsif rstCnt = '1' then
        cnt <= 0;
      end if;
 
      if latchFrameData = '1' then      -- latch stream data
        frameData_r <= frame_data_in;
        frame_re_out <= '1';
      end if;
 
      if determineOperation = '1' then  -- determine ARP Operation value
        ARP_operation_r <= frameData_r(8);
      end if;
 
      if shiftSourceIPIn = '1' then     -- shift in IP
        source_IP_r <= source_IP_r (15 downto 0) &
                       frameData_r( 7 downto 0 ) & frameData_r( 15 downto 8 );
      end if;
 
      if shiftSourceMACIn = '1' then    -- shift in MAC
        source_MAC_r <= source_MAC_r (31 downto 0) &
                        frameData_r( 7 downto 0 ) & frameData_r( 15 downto 8 );
      end if;
 
      if updateARPTable = '1' then      -- update ARP table
        if ARP_entry_IP_r = source_IP_r then  -- We already have this ARP, so update
          ARP_entry_MAC_r     <= source_MAC_r;
        else                            -- Lose one old ARP entry and add new one.
          ARP_entry_IP_old_r  <= ARP_entry_IP_r;
          ARP_entry_MAC_old_r <= ARP_entry_MAC_r;
          ARP_entry_IP_r      <= source_IP_r;
          ARP_entry_MAC_r     <= source_MAC_r;
        end if;
      end if;
 
      if frame_invalid = '1' then
        frame_invalid_r <= '1';
      elsif clear_invalid = '1' then
        frame_invalid_r <= '0';
      end if;
 
      if new_frame_in = '1' then
        frame_len_r <= to_integer( unsigned( frame_len_in ));
      end if;
 
      -- gen_ARP_rep_out is asserted by doGenARPRep and will stay high until cleared 
      -- by sending_reply_in
      if doGenARPRep = '1' then
        gen_ARP_rep_out <= '1';         -- when a request is needed assert gen_ARP_rep_out
        gen_ARP_IP_out  <= source_IP_r;  -- and latch the outgoing address
      elsif sending_reply_in = '1' then
        gen_ARP_rep_out <= '0';         -- when the request is been generated, stop requesting
      end if;
    end if;
  end process;
 
  process (presState, ARP_operation_r, cnt, new_frame_in, frame_invalid_r,
           new_word_valid_in, frameData_r, frame_valid_in, frame_len_r)
  begin
    -- defaulting of signals
    rstCnt             <= '0';
    incCnt             <= '0';
    shiftSourceIPIn    <= '0';
    determineOperation <= '0';
    updateARPTable     <= '0';
    shiftSourceIPIn    <= '0';
    shiftSourceMACIn   <= '0';
    latchFrameData     <= '0';
    doGenARPRep        <= '0';
    frame_invalid      <= '0';
    clear_invalid      <= '0';
    done_out           <= '0';
 
    case presState is
      when stIdle =>
        -- wait for an ARP frame to arrive (udp_ip makes sure that it really is
        -- an ARP frame)
        if new_frame_in = '1' then
          nextState <= stHandleARP;
          rstCnt    <= '1';
        else
          -- if there is data still coming to ARP, just pretend to be reading it
          if new_word_valid_in = '1' then
            latchFrameData <= '1';
          end if;
 
          nextState <= stIdle;
        end if;
 
      when stHandleARP =>
        -- receive a byte from the stream
        if new_word_valid_in = '0' then
          nextState      <= stHandleARP;
        else
          nextState      <= stOperate;
          latchFrameData <= '1';
        end if;
 
      when stOperate =>
        -- increment counter
        incCnt <= '1';
        -- choose state based on values in the header
        -- The following will make us ignore the frame (all values hexadecimal):
        -- Hardware Type /= 1
        -- Protocol Type /= 800
        -- Hardware Length /= 6
        -- Protocol Length /= 4
        -- Operation /= 1 or 2
        -- Target IP /= our IP (i.e. message is not meant for us)
        if (cnt = 0 and frameData_r /= x"0100") or
          (cnt = 1 and frameData_r /= x"0008") or  -- MSByte = 0 to 7, LSByte = 8 to 15
          (cnt = 2 and frameData_r /= x"0406") or
          (cnt = 3 and frameData_r /= x"0100" and frameData_r /= x"0200") or
          (cnt = 12 and frameData_r /= own_ip_c( 23 downto 16 ) & own_ip_c( 31 downto 24 )) or
          (cnt = 13 and frameData_r /= own_ip_c( 7 downto 0 ) & own_ip_c( 15 downto 8 )) then
 
          --if ((cnt = "00000" or cnt = "00011" or cnt = "00110") and frameData_r /= 0 )or
          --  (cnt = "00001" and frameData_r /= 1) or
          --  (cnt = "00010" and frameData_r /= 8) or
          --  (cnt = "00100" and frameData_r /= 6) or
          --  (cnt = "00101" and frameData_r /= 4) or
          --  (cnt = "00111" and frameData_r /= 1 and frameData_r /= 2 )or
          --  (cnt = "11000" and frameData_r /= DEVICE_IP (31 downto 24)) or
          --  (cnt = "11001" and frameData_r /= DEVICE_IP (23 downto 16)) or
          --  (cnt = "11010" and frameData_r /= DEVICE_IP (15 downto 8)) or
          --  (cnt = "11011" and frameData_r /= DEVICE_IP (7 downto 0)) then
 
          frame_invalid <= '1';
        end if;
 
        -- frame len is in bytes, so divide by two
        if cnt = frame_len_r/2-1 then
          nextState <= stCheckValid;  -- exit when data is totally received
        else
          nextState <= stHandleARP;   -- otherwise loop until complete
        end if;
 
 
        -- latch and shift in signals from stream when needed
        if cnt = 3 then
          determineOperation <= '1';
        end if;
        if cnt = 4 or cnt = 5 or cnt = 6 then
          shiftSourceMACIn   <= '1';
        end if;
        if cnt = 7 or cnt = 8 then
          shiftSourceIPIn    <= '1';
        end if;
 
      when stCheckValid =>
        clear_invalid <= '1';
 
        done_out  <= '1';
        nextState <= stIdle;
 
        if frame_valid_in = '1' and frame_invalid_r = '0' then
          -- frame didn't fail CRC and it's not invalid in any other way either
          -- generate a reply if required and wait for more messages
          if ARP_operation_r = '1' then
            doGenARPRep  <= '1';
          end if;
          updateARPTable <= '1';        -- update the ARP table with the new data
        end if;
 
      when others => null;
 
    end case;
  end process;
 
  -- handle requests for entries in the ARP table.
  process (req_IP_in, ARP_entry_IP_r, ARP_entry_MAC_r, ARP_entry_IP_old_r, ARP_entry_MAC_old_r)
  begin
    if req_IP_in = ARP_entry_IP_r then  -- check most recent entry
      valid_entry_out <= '1';
      lookup_MAC_out  <= ARP_entry_MAC_r;
    elsif req_IP_in = ARP_entry_IP_old_r then  -- check 2nd entry
      valid_entry_out <= '1';
      lookup_MAC_out  <= ARP_entry_MAC_old_r;
    else                                -- if neither entry matches, valid = 0
      valid_entry_out <= '0';
      lookup_MAC_out  <= (others => '1');
    end if;
  end process;
end ARP_arch;
 

Go to most recent revision | 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.