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

Subversion Repositories esoc

[/] [esoc/] [trunk/] [Sources/] [logixa/] [esoc_search_engine_sa.vhd] - Rev 49

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

--------------------------------------------------------------------------------
----                                                                        ----
---- Ethernet Switch on Configurable Logic IP Core                          ----
----                                                                        ----
---- This file is part of the ESoCL project                                 ----
---- http://www.opencores.org/cores/esoc/                                   ----
----                                                                        ----
---- Description: see design description ESoCL_dd_71022001.pdf              ----
----                                                                        ----
---- To Do: see roadmap description ESoCL_dd_71022001.pdf                   ----
----        and/or release bulleting ESoCL_rb_71022001.pdf                  ----
----                                                                        ----
---- Author(s): L.Maarsen                                                   ----
---- Bert Maarsen, lmaarsen@opencores.org                                   ----
----                                                                        ----
--------------------------------------------------------------------------------
----                                                                        ----
---- Copyright (C) 2009 Authors and OPENCORES.ORG                           ----
----                                                                        ----
---- This source file may be used and distributed without                   ----
---- restriction provided that this copyright statement is not              ----
---- removed from the file and that any derivative work contains            ----
---- the original copyright notice and the associated disclaimer.           ----
----                                                                        ----
---- This source file 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 2.1 of the License, or (at your option) any             ----
---- later version.                                                         ----
----                                                                        ----
---- This source 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 this source; if not, download it             ----
---- from http://www.opencores.org/lgpl.shtml                               ----
----                                                                        ----
--------------------------------------------------------------------------------
-- Object        : Entity work.esoc_search_engine_sa
-- Last modified : Mon Apr 14 12:50:09 2014.
--------------------------------------------------------------------------------
 
 
 
library ieee, std, work;
use ieee.std_logic_1164.all;
use std.textio.all;
use ieee.numeric_std.all;
use work.package_hash10_24b.all;
use work.package_esoc_configuration.all;
 
entity esoc_search_engine_sa is
  port(
    clk_search                : in     std_logic;
    reset                     : in     std_logic;
    search_aging_tick         : in     std_logic;
    search_entry_age_time     : in     std_logic_vector(11 downto 0);
    search_entry_age_time_ena : in     std_logic;
    search_sa_drop_cnt        : out    std_logic;
    search_sa_store_empty     : in     std_logic;
    search_sa_store_q         : in     std_logic_vector(79 downto 0);
    search_sa_store_rd        : out    std_logic;
    search_sa_store_words     : in     STD_LOGIC_VECTOR(6 downto 0);
    search_table_address      : out    STD_LOGIC_VECTOR(12 downto 0);
    search_table_data         : out    STD_LOGIC_VECTOR(79 downto 0);
    search_table_q            : in     STD_LOGIC_VECTOR(79 downto 0);
    search_table_rden         : out    STD_LOGIC;
    search_table_wren         : out    STD_LOGIC);
end entity esoc_search_engine_sa;
 
--------------------------------------------------------------------------------
-- Object        : Architecture work.esoc_search_engine_sa.esoc_search_engine_sa
-- Last modified : Mon Apr 14 12:50:09 2014.
--------------------------------------------------------------------------------
 
 
architecture esoc_search_engine_sa of esoc_search_engine_sa is
 
type   search_states is (idle, wait_sa, wait_hash, compare, add);
signal search_state: search_states;
 
type   aging_states is (idle, wait_empty, wait_entry, evaluate);
signal aging_state: aging_states;
 
signal search_table_address_i: std_logic_vector(search_table_address'high downto 0);
 
signal search_hash_delay_cnt: integer range esoc_search_engine_hash_delay downto 0;
signal search_table_coll_cnt: integer range esoc_search_engine_col_depth downto 0;
signal search_table_free_entry_os: integer range esoc_search_engine_col_depth downto 0;
signal search_table_free_entry: std_logic;
 
signal search_key_i: std_logic_vector(search_table_data'high downto 0);
 
signal aging_count_down: integer range 2**search_entry_age_time'length-1 downto 0;
signal aging_address: integer range 2**search_table_address'length-1 downto 0;
 
begin
 
--=============================================================================================================
-- Process		  : proces search requests for source MAC address
-- Description	: 
--=============================================================================================================    
search_sa:  process(clk_search, reset)
            begin
              if reset = '1' then
                search_table_free_entry     <= '0';
                search_table_free_entry_os  <= 0;
                search_table_coll_cnt       <= 0;
 
                search_hash_delay_cnt       <= 0;
                search_sa_drop_cnt          <= '0';
 
                search_table_rden           <= '0';
                search_table_wren           <= '0';
                search_sa_store_rd          <= '0';
                search_key_i                <= (others => '0');
 
                search_table_address_i      <= (others => '0');
 
                search_state                <= idle;
                aging_state                 <= idle;
                aging_address               <= 0;
                aging_count_down            <= 0;
 
              elsif clk_search'event and clk_search = '1' then
                -- clear one-clock active signals
                search_sa_drop_cnt <= '0';
                search_table_rden  <= '0';  
                search_table_wren  <= '0';
                search_sa_store_rd <= '0';
 
                --
                -- process new search requests 
                --
                case search_state is
                  when idle       =>  -- get Source Port + SA and calculate hash pointer (additional delay may be required after synthesis, due to large XOR tree)  
                                      if search_sa_store_empty = '0' then
                                        search_key_i                <= search_sa_store_q;
                                        search_table_address_i      <= CALC_HASH10_24b(search_sa_store_q(esoc_search_bus_mac+23 downto esoc_search_bus_mac)) & "000";
                                        search_table_rden           <= '1';  
                                        search_table_free_entry     <= '0';
                                        search_table_free_entry_os  <= 0;
                                        search_table_coll_cnt       <= 0;
 
                                        -- use delay mechanism to give the hash function - large xor tree - time to provide stable result
                                        -- depends on target speed, use target timing analysis result to optimze this delay! At least one clock
                                        -- delay due to RAM latency
                                        search_hash_delay_cnt <= esoc_search_engine_hash_delay-1;
                                        search_state          <= wait_hash;
 
                                        search_sa_store_rd <= '1';
                                      end if;
 
                  when wait_hash  =>  -- hash result stable?  
                                      if search_hash_delay_cnt = 0 then
                                        search_table_address_i  <= std_logic_vector(to_unsigned(to_integer(unsigned(search_table_address_i))+1,search_table_address_i'length));
                                        search_state <= compare;
                                      else
                                        search_hash_delay_cnt <= search_hash_delay_cnt-1;
                                      end if;
 
                                      search_table_rden           <= '1';  
 
                  when compare  => -- there is a hit on SA and VID and the entry is valid
                                   if search_table_q(esoc_search_entry_vlan+11 downto esoc_search_entry_vlan) = search_key_i(esoc_search_entry_vlan+11 downto esoc_search_entry_vlan) and
                                     search_table_q(esoc_search_entry_mac+47 downto esoc_search_entry_mac)   = search_key_i(esoc_search_entry_mac+47 downto esoc_search_entry_mac)   and  
                                     search_table_q(esoc_search_entry_valid) = '1' then
 
                                    search_table_address_i                 <= std_logic_vector(to_unsigned(to_integer(unsigned(search_table_address_i))-1,search_table_address_i'length));
                                    search_key_i(esoc_search_entry_valid)  <= '1';
                                    search_key_i(esoc_search_entry_update) <= '1';
                                    search_table_wren                      <= '1';
                                    search_state                           <= idle;
 
                                  -- there is no hit on SA and VID
                                  else
                                    -- end of collission buffer not reached, prepare for next entry
                                    if search_table_coll_cnt < esoc_search_engine_col_depth then 
                                      -- is the current entry empty, remember position to use it when end of collission buffer is reached without a hit
                                      if search_table_free_entry = '0' and search_table_q(esoc_search_entry_valid) = '0' then
                                        search_table_free_entry <= '1';
                                      elsif search_table_free_entry = '0' then
                                        search_table_free_entry_os <= search_table_free_entry_os + 1;
                                      end if;
 
                                      search_table_coll_cnt   <= search_table_coll_cnt + 1;      
                                      search_table_address_i  <= std_logic_vector(to_unsigned(to_integer(unsigned(search_table_address_i))+1,search_table_address_i'length)); 
                                      search_table_rden       <= '1';  
 
                                    -- end of collission buffer without a hit, check previous empty entries were found or that last entry is empty else report full collission buffer
                                    else
                                      -- previous entry of collission buffer was empty, use it to store new SA + VID
                                      if search_table_free_entry = '1' then
                                        search_table_address_i <= std_logic_vector(to_unsigned(to_integer(unsigned(search_table_address_i))-esoc_search_engine_col_depth+search_table_free_entry_os-1,search_table_address_i'length));
                                        search_table_wren      <= '1';
 
                                      -- no previous empty entries, if last entry of collission buffer is empty, use it to store new SA + VID
                                      elsif search_table_q(esoc_search_entry_valid) = '0' then
                                        search_table_address_i <= std_logic_vector(to_unsigned(to_integer(unsigned(search_table_address_i))-1,search_table_address_i'length));
                                        search_table_wren <= '1';
 
                                      -- no entry of collission buffer is empty, no space to store new SA + VID  
                                      else
                                        search_sa_drop_cnt <= '1';
                                      end if;
 
                                      search_key_i(esoc_search_entry_valid)  <= '1';
                                      search_key_i(esoc_search_entry_update) <= '1';
                                      search_state <= idle;
                                    end if;
                                  end if;
 
                  when others =>  search_state <= idle;
                end case;
 
                --
                -- process aging cycles
                --
                if search_aging_tick = '1' then
                  -- create aging timer based upon aging time setting register
                  if aging_count_down = 0 then
                    aging_count_down <= to_integer(unsigned(search_entry_age_time))+1;
                  else
                    aging_count_down <= aging_count_down - 1;
                  end if;
                end if;
 
                case aging_state is
                  when idle       =>  -- start aging cycle when aging mechanism is enabled and timer expires
                                      if aging_count_down = 0 and search_entry_age_time_ena = '1' then
                                        aging_address <= 0;
                                        aging_state   <= wait_empty;
                                      end if;
 
                  when wait_empty =>  -- wait for access to table with learned address (SA Search request first!)
                                      -- provide access when table is free for aging process
                                      if search_sa_store_empty = '1' and search_state = idle then
                                        search_table_address_i <= std_logic_vector(to_unsigned(aging_address,search_table_address_i'length));
                                        search_table_rden      <= '1';  
                                        aging_state            <= wait_entry;
                                      end if;
 
                  when wait_entry =>  -- if table is still free prepare for entry evaluation else return to wait for access
                                      if search_sa_store_empty = '0' then
                                        aging_state <= wait_empty;
                                      else
                                        aging_state <= evaluate;
                                      end if;
 
                  when evaluate   =>  -- if table is still free update entry and increment address pointer else return to wait for access
                                      if search_sa_store_empty = '0' then
                                        aging_state <= wait_empty;
                                      else
                                        -- update the entry or even invalidate the entry
                                        if search_table_q(esoc_search_entry_valid) = '1' then
                                          search_key_i <= search_table_q;
                                          search_key_i(esoc_search_entry_valid)  <= search_table_q(esoc_search_entry_update);
                                          search_key_i(esoc_search_entry_update) <= '0';
                                          search_table_wren      <= '1';
                                        end if;
 
                                        -- update address pointer to process next entry
                                        if aging_address = 2**search_table_address_i'length - 1 then
                                          aging_state <= idle;
                                        else
                                          aging_address <= aging_address + 1;
                                          aging_state <= wait_empty;
                                        end if;
                                      end if;
 
                  when others     =>  aging_state <= idle;
                end case;
              end if;
            end process;
 
            search_table_address <= search_table_address_i;
            search_table_data    <= search_key_i;
 
end architecture esoc_search_engine_sa ; -- of esoc_search_engine_sa
 
 

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.