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

Subversion Repositories ether_arp_1g

[/] [ether_arp_1g/] [trunk/] [rtl/] [arp_responder.vhdl] - Rev 4

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: Eastern Washington University, Cheney, WA 
-- Engineer: Justin Wagner
-- 
-- Create Date:    7/Oct/2011
-- Design Name: 
-- Module Name:    arp_responder - rtl 
-- Project Name: 
-- Target Devices:  n/a
-- Tool versions: 
-- Description: Project for Job application to XR Trading
--
-- Dependencies: arp_package.vhdl (Definitions of various constants)
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.arp_package.all;
 
entity arp_responder is
Port (  ARESET        : in   STD_LOGIC;
        MY_MAC        : in   std_logic_vector(47 downto 0); --my MAC address
        MY_IPV4       : in   std_logic_vector(31 downto 0); --my IPV4 address
        CLK_RX        : in   STD_LOGIC;
        DATA_VALID_RX : in   STD_LOGIC;
        DATA_RX       : in   std_logic_vector(7 downto 0);
        CLK_TX        : in   STD_LOGIC;
        DATA_ACK_TX   : in   STD_LOGIC;
        DATA_VALID_TX : out  STD_LOGIC;
        DATA_TX       : out  std_logic_vector(7 downto 0)
      );
end arp_responder;
----------------------------------------------------------------------------------
architecture rtl of arp_responder is
    -- Edge Detector used to find positive edge of DATA_VALID_RX
    component edge_detector
        port(
                din   :  in  std_logic;
                clk   :  in  std_logic;
                rst_n :  in  std_logic;
                dout  :  out std_logic
            );
    end component edge_detector;
 
    --the following declares the various states for the machine
    type state_type is (IDLE, 
                        CHECK_DA, CHECK_SA, CHECK_E_TYPE, CHECK_H_TYPE, CHECK_P_TYPE, 
                        CHECK_H_LEN, CHECK_P_LEN, CHECK_OPER, CHECK_SHA, CHECK_SPA, 
                        IGNORE_THA, CHECK_TPA,
                        GEN_DA, GEN_SA, GEN_E_TYPE, GEN_H_TYPE, GEN_P_TYPE, 
                        GEN_H_LEN, GEN_P_LEN, GEN_OPER, GEN_SHA, GEN_SPA, 
                        GEN_THA, GEN_TPA);
 
    signal SA_mem, next_SA_mem                      : HA_mem_type;
    signal SPA_mem, next_SPA_mem                    : PA_mem_type;
    signal next_state, state                        : state_type;    
    signal next_counter, counter                    : std_logic_vector(3 downto 0);
    signal posedge_DATA_VALID_RX                    : std_logic;
    signal next_DATA_VALID_TX, next_2_DATA_VALID_TX : std_logic;
    signal next_DATA_TX, next_2_DATA_TX             : std_logic_vector(7 downto 0);
 
begin
 
    -- A positive edge detector for the DATA_VALID_RX signal
    ed_1: edge_detector
          port map(
                  din   =>  DATA_VALID_RX,
                  clk   =>  CLK_RX,
                  rst_n =>  not(ARESET),
                  dout  =>  posedge_DATA_VALID_RX
                  );
 
----------------------------------------------------------------------------------
-- This process describes the flow from one state to another in the FSM-----------
-- It also describes what the outputs should be at each state---------------------
----------------------------------------------------------------------------------
combo:process(state, posedge_DATA_VALID_RX, counter, SA_mem, SPA_mem, DATA_ACK_TX, 
                MY_MAC, MY_IPV4)
begin
-- Hold Values by Default
-- These values will hold true in every state unless a state explicitly defines 
-- a different value for any of these signals.
 next_DATA_TX           <= (others => '0');
 next_DATA_VALID_TX     <= '0';
 next_counter           <= counter;
 next_SA_mem            <= SA_mem;
 next_SPA_mem           <= SPA_mem;
 
------------------------------------------------------------------
--State Machine Start...Please see ASM chart for State Diagram----
    case state is
 
        when IDLE =>
            if (posedge_DATA_VALID_RX ='1') then
              next_state                    <= CHECK_DA;
            else                            
              next_state                    <= IDLE;
            end if;
            next_SA_mem                     <=  ((others => '0'),(others => '0'),(others => '0'),(others => '0'),(others => '0'),(others => '0'));                         
            next_SPA_mem                    <=  ((others => '0'),(others => '0'),(others => '0'),(others => '0'));                          
            next_counter                    <=  (others => '0');
 
        when CHECK_DA =>
        -- Validate that the DA is a Broadcast, if not return to IDLE
            next_counter                    <= counter + 1;
            if (DATA_RX = MAC_BDCST_ADDR(conv_integer(counter))) then
                if (counter < 5) then
                    next_state              <= CHECK_DA;
                else                        
                    next_state              <= CHECK_SA;
                    next_counter            <= (others => '0');
                end if;
            else
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_SA =>
        -- Lets store the SA so we can respond to it later
            next_counter                        <= counter + 1;
            next_state                          <= CHECK_SA;
            next_SA_mem(conv_integer(counter))  <= DATA_RX;
            if (counter >= 5) then
                next_state                  <= CHECK_E_TYPE;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_E_TYPE =>  
        -- Verify that the E_TYPE is the ARP ETYPE
            next_counter                    <= counter + 1;
            if (DATA_RX = E_TYPE_ARP(conv_integer(counter))) then
                next_state                  <= CHECK_E_TYPE;
                if (counter >= 1) then
                    next_state              <= CHECK_H_TYPE;
                    next_counter            <= (others => '0');
                end if;
            else
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_H_TYPE =>
        -- Verify that the H_TYPE is the Ethernet HTYPE
            next_counter                    <= counter + 1;
            if (DATA_RX = H_TYPE_ETH(conv_integer(counter))) then
                next_state                  <= CHECK_H_TYPE;
                if (counter >= 1) then
                    next_state              <= CHECK_P_TYPE;
                    next_counter            <= (others => '0');
                end if;
            else
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_P_TYPE =>
        -- Verify that the P_TYPE is the IPV4 PTYPE
            next_counter                    <= counter + 1;
            if (DATA_RX = P_TYPE_IPV4(conv_integer(counter))) then
                next_state                  <= CHECK_P_TYPE;
                if (counter >= 1) then
                    next_state              <= CHECK_H_LEN;
                    next_counter            <= (others => '0');
                end if;
            else
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_H_LEN =>
        -- Verify that the H_LEN is the Ethernet Length
            next_counter                    <= (others => '0');
            if (DATA_RX = H_TYPE_ETH_LEN) then
                next_state                  <= CHECK_P_LEN;
            else
                next_state                  <= IDLE;
            end if;
 
        when CHECK_P_LEN =>
        -- Verify that the P_LEN is the IPV4 Length
            next_counter                    <= (others => '0');
            if (DATA_RX = P_TYPE_IPV4_LEN) then
                next_state                  <= CHECK_OPER;
            else
                next_state                  <= IDLE;
            end if;
 
        when CHECK_OPER =>
        -- Verify that we received an ARP Request
            next_counter                    <= counter + 1;
            if (DATA_RX = ARP_OPER_REQ(conv_integer(counter))) then
                next_state                  <= CHECK_OPER;
                if (counter >= 1) then
                    next_state              <= CHECK_SHA;
                    next_counter            <= (others => '0');
                end if;
            else
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_SHA =>
        -- Ignore the SHA field since we already retrieved this 
        -- from the Ethernet header
            next_counter                    <= counter + 1;
            next_state                      <= CHECK_SHA;
            if (counter >= 5) then
                next_counter                <= (others => '0');
                next_state                  <= CHECK_SPA;
            end if;
 
        when CHECK_SPA =>         
        -- Lets store the SPA so we can respond to it later
            next_counter                        <= counter + 1;
            next_state                          <= CHECK_SPA;
            next_SPA_mem(conv_integer(counter)) <= DATA_RX;
            if (counter >= 3) then
                next_state                  <= IGNORE_THA;
                next_counter                <= (others => '0');
            end if;
 
        when IGNORE_THA => 
        -- Ignore the destination Hardware Address (ARP requests can't fill this out by definition)
            next_state                      <= IGNORE_THA;
            next_counter                    <= counter + 1;
            if (counter >= 5) then
                next_state                  <= CHECK_TPA;
                next_counter                <= (others => '0');
            end if;
 
        when CHECK_TPA =>       
        -- Make sure we are the destination Protocol Address       
            next_counter                    <= counter + 1;
            if (DATA_RX = MY_IPV4((31-(conv_integer(counter)*8)) downto (24-(conv_integer(counter)*8)))) then
                next_state                  <= CHECK_TPA;
                if (counter >= 3) then
                    next_state              <= GEN_DA;
                    next_counter            <= (others => '0');
                end if;
            else
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        -- GENERATE AN ARP RESPONSE
 
        when GEN_DA =>  
        -- Generate the DA for the response
            next_DATA_VALID_TX              <= '1';
            next_DATA_TX                    <= SA_mem(conv_integer(counter));
            if (DATA_ACK_TX = '0' AND counter = 0) then
                next_counter                <= (others => '0');
            else
                next_counter                <= counter + 1;
            end if;
            if (counter < 5) then
                next_state                  <= GEN_DA;
            else                            
                next_state                  <= GEN_SA;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_SA =>  
        -- Generate the DA for the response
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= MY_MAC((47-(conv_integer(counter)*8)) downto (40-(conv_integer(counter)*8)));
            if (counter < 5) then
                next_state                  <= GEN_SA;
            else                            
                next_state                  <= GEN_E_TYPE;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_E_TYPE =>                  
        -- Generate the E_TYPE for the response
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= E_TYPE_ARP(conv_integer(counter));
            if (counter < 1) then
                next_state                  <= GEN_E_TYPE;
            else                            
                next_state                  <= GEN_H_TYPE;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_H_TYPE =>                  
        -- Generate the H_TYPE for the response
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= H_TYPE_ETH(conv_integer(counter));
            if (counter < 1) then
                next_state                  <= GEN_H_TYPE;
            else                            
                next_state                  <= GEN_P_TYPE;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_P_TYPE =>                  
        -- Generate the P_TYPE for the response
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= P_TYPE_IPV4(conv_integer(counter));
            if (counter < 1) then
                next_state                  <= GEN_P_TYPE;
            else                            
                next_state                  <= GEN_H_LEN;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_H_LEN =>                   
            next_DATA_VALID_TX              <= '1';
            next_DATA_TX                    <= H_TYPE_ETH_LEN;
            next_state                      <= GEN_P_LEN;              
 
        when GEN_P_LEN =>                   
            next_DATA_VALID_TX              <= '1';
            next_DATA_TX                    <= P_TYPE_IPV4_LEN;
            next_state                      <= GEN_OPER;              
 
        when GEN_OPER =>                    
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= ARP_OPER_RESP(conv_integer(counter));
            if (counter < 1) then
                next_state                  <= GEN_OPER;
            else                            
                next_state                  <= GEN_SHA;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_SHA =>                     
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= MY_MAC((47-(conv_integer(counter)*8)) downto (40-(conv_integer(counter)*8)));
            if (counter < 5) then
                next_state                  <= GEN_SHA;
            else                            
                next_state                  <= GEN_SPA;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_SPA =>                     
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= MY_IPV4((31-(conv_integer(counter)*8)) downto (24-(conv_integer(counter)*8)));
            if (counter < 3) then
                next_state                  <= GEN_SPA;
            else                            
                next_state                  <= GEN_THA;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_THA =>                     
        -- Generate the THA for the response
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= SA_mem(conv_integer(counter));
            if (counter < 5) then
                next_state                  <= GEN_THA;
            else                            
                next_state                  <= GEN_TPA;
                next_counter                <= (others => '0');
            end if;
 
        when GEN_TPA =>                     
        -- Generate the TPA for the response
            next_DATA_VALID_TX              <= '1';
            next_counter                    <= counter + 1;
            next_DATA_TX                    <= SPA_mem(conv_integer(counter));
            if (counter < 3) then
                next_state                  <= GEN_TPA;
            else                            
                next_state                  <= IDLE;
                next_counter                <= (others => '0');
            end if;
 
        when others =>            
            next_state    <= IDLE;
 
    end case;
 
end process combo;
----------------------------------------------------------------------------------
--Sequential Logic Processes--------------------------------------------------------
----------------------------------------------------------------------------------
seq_RX:process(CLK_RX, ARESET)
begin
 
    if (ARESET='1') then --resetting the board
        state               <= IDLE;
        counter             <= (others => '0');
        SA_mem              <= ((others => '0'),(others => '0'),(others => '0'),(others => '0'),(others => '0'),(others => '0'));
        SPA_mem             <= ((others => '0'),(others => '0'),(others => '0'),(others => '0'));
 
    -- move next state values into registers on clock edge
    elsif (CLK_RX'event and CLK_RX ='1') then 
        state               <= next_state;
        counter             <= next_counter;
        SA_mem              <= next_SA_mem;
        SPA_mem             <= next_SPA_mem;
 
    else
        NULL;
    end if;
 
end process seq_RX;
 
seq_TX:process(CLK_TX, ARESET)
begin
 
    if (ARESET='1') then --resetting the board
        DATA_VALID_TX               <= '0'; 
        DATA_TX                     <= (others => '0'); 
        next_2_DATA_VALID_TX        <= '0';
        next_2_DATA_TX              <= (others => '0'); 
    -- move next state values into registers on clock edge
    elsif (CLK_TX'event and CLK_TX ='1') then 
        next_2_DATA_VALID_TX        <= next_DATA_VALID_TX;
        next_2_DATA_TX              <= next_DATA_TX;
        DATA_VALID_TX               <= next_2_DATA_VALID_TX;
        DATA_TX                     <= next_2_DATA_TX;
    else
        NULL;
    end if;
 
end process seq_TX;
 
end rtl;
 

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.