URL
https://opencores.org/ocsvn/udp_ip_stack/udp_ip_stack/trunk
Subversion Repositories udp_ip_stack
[/] [udp_ip_stack/] [trunk/] [rtl/] [vhdl/] [arp_STORE_br.vhd] - Rev 36
Compare with Previous | Blame | View Log
---------------------------------------------------------------------------------- -- Company: -- Engineer: Peter Fall -- -- Create Date: 12:00:04 05/31/2011 -- Design Name: -- Module Name: arp_STORE_br - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- ARP storage table using block ram with lookup based on IP address -- implements upto 255 entries with sequential search -- uses round robin overwrite when full (LRU would be better, but ...) -- -- store may take a number of cycles and the request is latched -- lookup may take a number of cycles. Assumes that request signals remain valid during lookup -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all; use ieee.std_logic_unsigned.all; use work.arp_types.all; entity arp_STORE_br is generic ( MAX_ARP_ENTRIES : integer := 255 -- max entries in the store ); port ( -- read signals read_req : in arp_store_rdrequest_t; -- requesting a lookup or store read_result : out arp_store_result_t; -- the result -- write signals write_req : in arp_store_wrrequest_t; -- requesting a lookup or store -- control and status signals clear_store : in std_logic; -- erase all entries entry_count : out unsigned(7 downto 0); -- how many entries currently in store -- system signals clk : in std_logic; reset : in std_logic ); end arp_STORE_br; architecture Behavioral of arp_STORE_br is type st_state_t is (IDLE, PAUSE, SEARCH, FOUND, NOT_FOUND); type ip_ram_t is array (0 to MAX_ARP_ENTRIES-1) of std_logic_vector(31 downto 0); type mac_ram_t is array (0 to MAX_ARP_ENTRIES-1) of std_logic_vector(47 downto 0); subtype addr_t is integer range 0 to MAX_ARP_ENTRIES; type count_mode_t is (RST, INCR, HOLD); type mode_t is (MREAD, MWRITE); -- state variables signal ip_ram : ip_ram_t; -- will be implemented as block ram signal mac_ram : mac_ram_t; -- will be implemented as block ram signal st_state : st_state_t; signal next_write_addr : addr_t; -- where to make the next write signal num_entries : addr_t; -- number of entries in the store signal next_read_addr : addr_t; -- next addr to read from signal entry_found : arp_entry_t; -- entry found in search signal mode : mode_t; -- are we writing or reading? signal req_entry : arp_entry_t; -- entry latched from req -- busses signal next_st_state : st_state_t; signal arp_entry_val : arp_entry_t; signal mode_val : mode_t; signal write_addr : addr_t; -- actual write address to use signal read_result_int : arp_store_result_t; -- control signals signal set_st_state : std_logic; signal set_next_write_addr : count_mode_t; signal set_num_entries : count_mode_t; signal set_next_read_addr : count_mode_t; signal write_ram : std_logic; signal set_entry_found : std_logic; signal set_mode : std_logic; function read_status(status : arp_store_rslt_t; signal mode : mode_t) return arp_store_rslt_t is variable ret : arp_store_rslt_t; begin case status is when IDLE => ret := status; when others => if mode = MWRITE then ret := BUSY; else ret := status; end if; end case; return ret; end read_status; begin combinatorial : process ( -- input signals read_req, write_req, clear_store, reset, -- state variables st_state, next_write_addr, num_entries, next_read_addr, entry_found, mode, req_entry, -- busses arp_entry_val -- control signals ) begin -- set output followers read_result_int.status <= IDLE; read_result_int.entry <= entry_found; entry_count <= to_unsigned(num_entries, 8); -- set bus defaults next_st_state <= IDLE; mode_val <= MREAD; write_addr <= next_write_addr; -- set signal defaults set_st_state <= '0'; set_next_write_addr <= HOLD; set_num_entries <= HOLD; set_next_read_addr <= HOLD; write_ram <= '0'; set_entry_found <= '0'; set_mode <= '0'; -- STORE FSM case st_state is when IDLE => if write_req.req = '1' then -- need to search to see if this IP already there set_next_read_addr <= RST; -- start lookup from beginning mode_val <= MWRITE; set_mode <= '1'; next_st_state <= PAUSE; set_st_state <= '1'; elsif read_req.req = '1' then set_next_read_addr <= RST; -- start lookup from beginning mode_val <= MREAD; set_mode <= '1'; next_st_state <= PAUSE; set_st_state <= '1'; end if; when PAUSE => -- wait until read addr is latched and we get first data out of the ram read_result_int.status <= read_status(BUSY, mode); set_next_read_addr <= INCR; next_st_state <= SEARCH; set_st_state <= '1'; when SEARCH => read_result_int.status <= read_status(SEARCHING, mode); -- check if have a match at this entry if req_entry.ip = arp_entry_val.ip and next_read_addr <= num_entries then -- found it set_entry_found <= '1'; next_st_state <= FOUND; set_st_state <= '1'; elsif next_read_addr > num_entries or next_read_addr >= MAX_ARP_ENTRIES then -- reached end of entry table read_result_int.status <= read_status(NOT_FOUND, mode); next_st_state <= NOT_FOUND; set_st_state <= '1'; else -- no match at this entry , go to next set_next_read_addr <= INCR; end if; when FOUND => read_result_int.status <= read_status(FOUND, mode); if mode = MWRITE then write_addr <= next_read_addr - 1; write_ram <= '1'; next_st_state <= IDLE; set_st_state <= '1'; elsif read_req.req = '0' then -- wait in this state until request de-asserted next_st_state <= IDLE; set_st_state <= '1'; end if; when NOT_FOUND => read_result_int.status <= read_status(NOT_FOUND, mode); if mode = MWRITE then -- need to write into the next free slot write_addr <= next_write_addr; write_ram <= '1'; set_next_write_addr <= INCR; if num_entries < MAX_ARP_ENTRIES then -- if not full, count another entry (if full, it just wraps) set_num_entries <= INCR; end if; next_st_state <= IDLE; set_st_state <= '1'; elsif read_req.req = '0' then -- wait in this state until request de-asserted next_st_state <= IDLE; set_st_state <= '1'; end if; end case; end process; sequential : process (clk) begin if rising_edge(clk) then -- ram processing if write_ram = '1' then ip_ram(write_addr) <= req_entry.ip; mac_ram(write_addr) <= req_entry.mac; end if; if next_read_addr < MAX_ARP_ENTRIES then arp_entry_val.ip <= ip_ram(next_read_addr); arp_entry_val.mac <= mac_ram(next_read_addr); else arp_entry_val.ip <= (others => '0'); arp_entry_val.mac <= (others => '0'); end if; read_result <= read_result_int; if reset = '1' or clear_store = '1' then -- reset state variables st_state <= IDLE; next_write_addr <= 0; num_entries <= 0; next_read_addr <= 0; entry_found.ip <= (others => '0'); entry_found.mac <= (others => '0'); req_entry.ip <= (others => '0'); req_entry.mac <= (others => '0'); mode <= MREAD; else -- Next req_state processing if set_st_state = '1' then st_state <= next_st_state; else st_state <= st_state; end if; -- mode setting and write request latching if set_mode = '1' then mode <= mode_val; if mode_val = MWRITE then req_entry <= write_req.entry; else req_entry.ip <= read_req.ip; req_entry.mac <= (others => '0'); end if; else mode <= mode; req_entry <= req_entry; end if; -- latch entry found if set_entry_found = '1' then entry_found <= arp_entry_val; else entry_found <= entry_found; end if; -- next_write_addr counts and wraps case set_next_write_addr is when HOLD => next_write_addr <= next_write_addr; when RST => next_write_addr <= 0; when INCR => if next_write_addr < MAX_ARP_ENTRIES-1 then next_write_addr <= next_write_addr + 1; else next_write_addr <= 0; end if; end case; -- num_entries counts and holds at max case set_num_entries is when HOLD => num_entries <= num_entries; when RST => num_entries <= 0; when INCR => if next_write_addr < MAX_ARP_ENTRIES then num_entries <= num_entries + 1; else num_entries <= num_entries; end if; end case; -- next_read_addr counts and wraps case set_next_read_addr is when HOLD => next_read_addr <= next_read_addr; when RST => next_read_addr <= 0; when INCR => if next_read_addr < MAX_ARP_ENTRIES then next_read_addr <= next_read_addr + 1; else next_read_addr <= 0; end if; end case; end if; end if; end process; end Behavioral;