Line 21... |
Line 21... |
--
|
--
|
-- Revision:
|
-- Revision:
|
-- Revision 0.01 - File Created
|
-- Revision 0.01 - File Created
|
-- Revision 0.02 - Added req for mac tx and wait for grant
|
-- Revision 0.02 - Added req for mac tx and wait for grant
|
-- Revision 0.03 - Added data_out_first
|
-- Revision 0.03 - Added data_out_first
|
|
-- Revision 0.04 - Added arp response timeout
|
|
-- Revision 0.05 - Added arp cache reset control
|
-- Additional Comments:
|
-- Additional Comments:
|
--
|
--
|
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
library IEEE;
|
library IEEE;
|
use IEEE.STD_LOGIC_1164.ALL;
|
use IEEE.STD_LOGIC_1164.ALL;
|
use IEEE.NUMERIC_STD.ALL;
|
use IEEE.NUMERIC_STD.ALL;
|
use work.arp_types.all;
|
use work.arp_types.all;
|
|
|
entity arp is
|
entity arp is
|
|
generic (
|
|
CLOCK_FREQ : integer := 125000000; -- freq of data_in_clk -- needed to timout cntr
|
|
ARP_TIMEOUT : integer := 60 -- ARP response timeout (s)
|
|
);
|
Port (
|
Port (
|
-- lookup request signals
|
-- lookup request signals
|
arp_req_req : in arp_req_req_type;
|
arp_req_req : in arp_req_req_type;
|
arp_req_rslt : out arp_req_rslt_type;
|
arp_req_rslt : out arp_req_rslt_type;
|
-- MAC layer RX signals
|
-- MAC layer RX signals
|
Line 53... |
Line 58... |
data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame
|
data_out_last : out std_logic; -- with data out valid indicates the last byte of a frame
|
data_out : out std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame)
|
data_out : out std_logic_vector (7 downto 0); -- ethernet frame (from dst mac addr through to last byte of frame)
|
-- system signals
|
-- system signals
|
our_mac_address : in STD_LOGIC_VECTOR (47 downto 0);
|
our_mac_address : in STD_LOGIC_VECTOR (47 downto 0);
|
our_ip_address : in STD_LOGIC_VECTOR (31 downto 0);
|
our_ip_address : in STD_LOGIC_VECTOR (31 downto 0);
|
|
control : in arp_control_type;
|
req_count : out STD_LOGIC_VECTOR(7 downto 0) -- count of arp pkts received
|
req_count : out STD_LOGIC_VECTOR(7 downto 0) -- count of arp pkts received
|
);
|
);
|
end arp;
|
end arp;
|
|
|
architecture Behavioral of arp is
|
architecture Behavioral of arp is
|
|
|
type req_state_type is (IDLE,LOOKUP,REQUEST,WAIT_REPLY);
|
type req_state_type is (IDLE,LOOKUP,REQUEST,WAIT_REPLY,PAUSE1,PAUSE2,PAUSE3);
|
type rx_state_type is (IDLE,PARSE,PROCESS_ARP,WAIT_END);
|
type rx_state_type is (IDLE,PARSE,PROCESS_ARP,WAIT_END);
|
type rx_event_type is (NO_EVENT,DATA);
|
type rx_event_type is (NO_EVENT,DATA);
|
type count_mode_type is (RST,INCR,HOLD);
|
type count_mode_type is (RST,INCR,HOLD);
|
type arp_oper_type is (NOP,REQUEST,REPLY);
|
type arp_oper_type is (NOP,REQUEST,REPLY);
|
type set_clr_type is (SET, CLR, HOLD);
|
type set_clr_type is (SET, CLR, HOLD);
|
Line 83... |
Line 89... |
signal req_ip_addr : std_logic_vector (31 downto 0); -- IP address to lookup
|
signal req_ip_addr : std_logic_vector (31 downto 0); -- IP address to lookup
|
signal mac_addr_found : STD_LOGIC_VECTOR (47 downto 0); -- mac address found
|
signal mac_addr_found : STD_LOGIC_VECTOR (47 downto 0); -- mac address found
|
signal mac_addr_valid_reg: std_logic;
|
signal mac_addr_valid_reg: std_logic;
|
signal send_request_needed : std_logic;
|
signal send_request_needed : std_logic;
|
signal tx_mac_chn_reqd : std_logic;
|
signal tx_mac_chn_reqd : std_logic;
|
|
signal freq_scaler : unsigned (31 downto 0); -- scales data_in_clk downto 1Hz
|
|
signal timer : unsigned (7 downto 0); -- counts seconds timeout
|
|
signal timeout_reg : std_logic;
|
|
|
signal rx_state : rx_state_type;
|
signal rx_state : rx_state_type;
|
signal rx_count : unsigned (7 downto 0);
|
signal rx_count : unsigned (7 downto 0);
|
signal arp_operation : arp_oper_type;
|
signal arp_operation : arp_oper_type;
|
signal arp_req_count : unsigned (7 downto 0);
|
signal arp_req_count : unsigned (7 downto 0);
|
Line 108... |
Line 117... |
signal set_req_ip : std_logic;
|
signal set_req_ip : std_logic;
|
signal set_mac_addr : std_logic;
|
signal set_mac_addr : std_logic;
|
signal set_mac_addr_invalid : std_logic;
|
signal set_mac_addr_invalid : std_logic;
|
signal set_send_req : std_logic;
|
signal set_send_req : std_logic;
|
signal clear_send_req : std_logic;
|
signal clear_send_req : std_logic;
|
|
signal set_timer : count_mode_type; -- timer reset, count, hold control
|
|
signal timer_enable : std_logic; -- enable the timer counting
|
|
signal set_timeout : set_clr_type; -- control the timeout register
|
|
|
|
|
-- rx control signals
|
-- rx control signals
|
signal next_rx_state : rx_state_type;
|
signal next_rx_state : rx_state_type;
|
signal set_rx_state : std_logic;
|
signal set_rx_state : std_logic;
|
Line 182... |
Line 194... |
req_combinatorial : process (
|
req_combinatorial : process (
|
-- input signals
|
-- input signals
|
arp_req_req,
|
arp_req_req,
|
-- state variables
|
-- state variables
|
req_state, req_ip_addr, mac_addr_found, mac_addr_valid_reg, send_request_needed, arp_entry,
|
req_state, req_ip_addr, mac_addr_found, mac_addr_valid_reg, send_request_needed, arp_entry,
|
|
freq_scaler, timer, timeout_reg,
|
-- control signals
|
-- control signals
|
next_req_state, set_req_state, set_req_ip, set_mac_addr,set_mac_addr_invalid,set_send_req, clear_send_req)
|
next_req_state, set_req_state, set_req_ip, set_mac_addr, control,
|
|
set_mac_addr_invalid,set_send_req, clear_send_req, set_timer, timer_enable, set_timeout
|
|
)
|
begin
|
begin
|
-- set output followers
|
-- set output followers
|
arp_req_rslt.got_err <= '0'; -- errors not returned in this version
|
if arp_req_req.lookup_req = '1' then
|
|
arp_req_rslt.got_err <= '0';
|
|
else
|
|
arp_req_rslt.got_err <= timeout_reg;
|
|
end if;
|
-- zero time response to lookup request if already in cache
|
-- zero time response to lookup request if already in cache
|
if arp_req_req.lookup_req = '1' and arp_req_req.ip = arp_entry.ip and arp_entry.is_valid = '1' then
|
if arp_req_req.lookup_req = '1' and arp_req_req.ip = arp_entry.ip and arp_entry.is_valid = '1' then
|
arp_req_rslt.got_mac <= '1';
|
arp_req_rslt.got_mac <= '1';
|
arp_req_rslt.mac <= arp_entry.mac;
|
arp_req_rslt.mac <= arp_entry.mac;
|
elsif arp_req_req.lookup_req = '1' then
|
elsif arp_req_req.lookup_req = '1' then
|
Line 207... |
Line 226... |
set_req_ip <= '0';
|
set_req_ip <= '0';
|
set_mac_addr <= '0';
|
set_mac_addr <= '0';
|
set_mac_addr_invalid <= '0';
|
set_mac_addr_invalid <= '0';
|
set_send_req <= '0';
|
set_send_req <= '0';
|
clear_send_req <= '0';
|
clear_send_req <= '0';
|
|
set_timer <= INCR; -- default is timer running, unless we hold or reset it
|
|
set_timeout <= HOLD;
|
|
timer_enable <= '0';
|
|
|
|
-- combinatorial logic
|
|
if freq_scaler = x"00000000" then
|
|
timer_enable <= '1';
|
|
end if;
|
|
|
-- REQ FSM
|
-- REQ FSM
|
case req_state is
|
case req_state is
|
when IDLE =>
|
when IDLE =>
|
|
set_timer <= RST;
|
if arp_req_req.lookup_req = '1' then
|
if arp_req_req.lookup_req = '1' then
|
-- check if we already have the info in cache
|
-- check if we already have the info in cache
|
if arp_req_req.ip = arp_entry.ip and arp_entry.is_valid = '1' then
|
if arp_req_req.ip = arp_entry.ip and arp_entry.is_valid = '1' then
|
-- already have this IP
|
-- already have this IP
|
set_mac_addr <= '1';
|
set_mac_addr <= '1';
|
else
|
else
|
|
set_timeout <= CLR;
|
next_req_state <= LOOKUP;
|
next_req_state <= LOOKUP;
|
set_req_state <= '1';
|
set_req_state <= '1';
|
set_req_ip <= '1';
|
set_req_ip <= '1';
|
set_mac_addr_invalid <= '1';
|
set_mac_addr_invalid <= '1';
|
end if;
|
end if;
|
Line 232... |
Line 261... |
next_req_state <= IDLE;
|
next_req_state <= IDLE;
|
set_req_state <= '1';
|
set_req_state <= '1';
|
set_mac_addr <= '1';
|
set_mac_addr <= '1';
|
else
|
else
|
-- need to request mac for this IP
|
-- need to request mac for this IP
|
|
set_send_req <= '1';
|
|
set_timer <= RST;
|
next_req_state <= REQUEST;
|
next_req_state <= REQUEST;
|
set_req_state <= '1';
|
set_req_state <= '1';
|
set_send_req <= '1';
|
|
end if;
|
end if;
|
|
|
when REQUEST =>
|
when REQUEST =>
|
clear_send_req <= '1';
|
clear_send_req <= '1';
|
next_req_state <= WAIT_REPLY;
|
next_req_state <= WAIT_REPLY;
|
Line 248... |
Line 278... |
if arp_entry.is_valid = '1' then
|
if arp_entry.is_valid = '1' then
|
-- have reply, go back to LOOKUP state to see if it is the right one
|
-- have reply, go back to LOOKUP state to see if it is the right one
|
next_req_state <= LOOKUP;
|
next_req_state <= LOOKUP;
|
set_req_state <= '1';
|
set_req_state <= '1';
|
end if;
|
end if;
|
-- TODO: add timeout here
|
if timer >= ARP_TIMEOUT then
|
|
set_timeout <= SET;
|
|
next_req_state <= PAUSE1;
|
|
set_req_state <= '1';
|
|
end if;
|
|
|
|
when PAUSE1 =>
|
|
next_req_state <= PAUSE2;
|
|
set_req_state <= '1';
|
|
|
|
when PAUSE2 =>
|
|
next_req_state <= PAUSE3;
|
|
set_req_state <= '1';
|
|
|
|
when PAUSE3 =>
|
|
next_req_state <= IDLE;
|
|
set_req_state <= '1';
|
|
|
end case;
|
end case;
|
end process;
|
end process;
|
|
|
req_sequential : process (data_in_clk,reset)
|
req_sequential : process (data_in_clk,reset)
|
Line 263... |
Line 309... |
req_state <= IDLE;
|
req_state <= IDLE;
|
req_ip_addr <= (others => '0');
|
req_ip_addr <= (others => '0');
|
mac_addr_found <= (others => '0');
|
mac_addr_found <= (others => '0');
|
mac_addr_valid_reg <= '0';
|
mac_addr_valid_reg <= '0';
|
send_request_needed <= '0';
|
send_request_needed <= '0';
|
|
freq_scaler <= to_unsigned(CLOCK_FREQ,32);
|
|
timer <= (others => '0');
|
|
timeout_reg <= '0';
|
else
|
else
|
-- Next req_state processing
|
-- Next req_state processing
|
if set_req_state = '1' then
|
if set_req_state = '1' then
|
req_state <= next_req_state;
|
req_state <= next_req_state;
|
else
|
else
|
Line 299... |
Line 348... |
else
|
else
|
mac_addr_found <= mac_addr_found;
|
mac_addr_found <= mac_addr_found;
|
mac_addr_valid_reg <= mac_addr_valid_reg;
|
mac_addr_valid_reg <= mac_addr_valid_reg;
|
end if;
|
end if;
|
|
|
|
-- freq scaling and 1-sec timer
|
|
if freq_scaler = x"00000000" then
|
|
freq_scaler <= to_unsigned(CLOCK_FREQ,32);
|
|
else
|
|
freq_scaler <= freq_scaler - 1;
|
|
end if;
|
|
|
|
-- timer processing
|
|
case set_timer is
|
|
when RST =>
|
|
timer <= x"00";
|
|
when INCR =>
|
|
if timer_enable = '1' then
|
|
timer <= timer + 1;
|
|
else
|
|
timer <= timer;
|
|
end if;
|
|
when HOLD =>
|
|
timer <= timer;
|
|
end case;
|
|
|
|
-- timeout latching
|
|
case set_timeout is
|
|
when CLR => timeout_reg <= '0';
|
|
when SET => timeout_reg <= '1';
|
|
when HOLD => timeout_reg <= timeout_reg;
|
|
end case;
|
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
|
|
Line 512... |
Line 589... |
if (set_ip2 = '1') then new_arp_entry.ip(23 downto 16) <= dataval; end if;
|
if (set_ip2 = '1') then new_arp_entry.ip(23 downto 16) <= dataval; end if;
|
if (set_ip1 = '1') then new_arp_entry.ip(15 downto 8) <= dataval; end if;
|
if (set_ip1 = '1') then new_arp_entry.ip(15 downto 8) <= dataval; end if;
|
if (set_ip0 = '1') then new_arp_entry.ip(7 downto 0) <= dataval; end if;
|
if (set_ip0 = '1') then new_arp_entry.ip(7 downto 0) <= dataval; end if;
|
|
|
-- set arp entry request
|
-- set arp entry request
|
if set_arp_entry_request = '1' then
|
if control.clear_cache = '1' then
|
|
arp_entry.ip <= x"00000000";
|
|
arp_entry.mac <= x"000000000000";
|
|
arp_entry.is_valid <= '0';
|
|
arp_entry.reply_required <= '0';
|
|
elsif set_arp_entry_request = '1' then
|
-- copy info from new entry to arp_entry and set reply required
|
-- copy info from new entry to arp_entry and set reply required
|
arp_entry.mac <= new_arp_entry.mac;
|
arp_entry.mac <= new_arp_entry.mac;
|
arp_entry.ip <= new_arp_entry.ip;
|
arp_entry.ip <= new_arp_entry.ip;
|
arp_entry.is_valid <= '1';
|
arp_entry.is_valid <= '1';
|
if arp_operation = REQUEST then
|
if arp_operation = REQUEST then
|