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/] [udp2hibi/] [1.0/] [vhd/] [ctrl_regs.vhd] - Rev 183

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

-------------------------------------------------------------------------------
-- Title      : Control registers
-- Project    : UDP2HIBI
-------------------------------------------------------------------------------
-- File       : ctrl_regs.vhd
-- Author     : Jussi Nieminen
-- Last update: 2012-03-22
-- Platform   : 
-------------------------------------------------------------------------------
-- Description: Keep track of current sender and update a table with receiver
--              information.
--              Only 1 tx (fpga -> outside world) at a time,
--              but generic number of rx-operations.
--              
--              ES 2012-03-22: Check if there is a bug in table_valid.
--              That note is marked with "!!!", approx. at line 229
--              
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2009/12/08  1.0      niemin95        Created
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use work.udp2hibi_pkg.all;
 
 
entity ctrl_regs is
 
  generic (
    receiver_table_size_g : integer := 4;
    hibi_addr_width_g     : integer := 32
    );
 
  port (
    clk                : in  std_logic;
    rst_n              : in  std_logic;
 
    -- from hibi_receiver, new configurations
    release_lock_in    : in  std_logic;
    new_tx_conf_in     : in  std_logic;
    new_rx_conf_in     : in  std_logic;
    ip_in              : in  std_logic_vector( ip_addr_w_c-1 downto 0 );
    dest_port_in       : in  std_logic_vector( udp_port_w_c-1 downto 0 );
    source_port_in     : in  std_logic_vector( udp_port_w_c-1 downto 0 );
    lock_addr_in       : in  std_logic_vector( hibi_addr_width_g-1 downto 0 );
    response_addr_in   : in  std_logic_vector( hibi_addr_width_g-1 downto 0 );
    lock_out           : out std_logic;
    lock_addr_out      : out std_logic_vector( hibi_addr_width_g-1 downto 0 );
 
    -- to tx_ctrl, config params for sending
    tx_ip_out          : out std_logic_vector( ip_addr_w_c-1 downto 0 );
    tx_dest_port_out   : out std_logic_vector( udp_port_w_c-1 downto 0 );
    tx_source_port_out : out std_logic_vector( udp_port_w_c-1 downto 0 );
    timeout_release_in : in  std_logic;
 
    -- from rx_ctrl, params of the received ip packet
    rx_ip_in           : in  std_logic_vector( ip_addr_w_c-1 downto 0 );
    rx_dest_port_in    : in  std_logic_vector( udp_port_w_c-1 downto 0 );
    rx_source_port_in  : in  std_logic_vector( udp_port_w_c-1 downto 0 );
    rx_addr_valid_out  : out std_logic;
 
    -- to hibi_transmitter, send acknowledges
    ack_addr_out       : out std_logic_vector( hibi_addr_width_g-1 downto 0 );
    rx_addr_out        : out std_logic_vector( hibi_addr_width_g-1 downto 0 );
    send_tx_ack_out    : out std_logic;
    send_tx_nack_out   : out std_logic;
    send_rx_ack_out    : out std_logic;
    send_rx_nack_out   : out std_logic;
 
    -- from toplevel
    eth_link_up_in     : in  std_logic
    );
 
end ctrl_regs;
 
 
architecture rtl of ctrl_regs is
 
  -- Wildcards
  constant any_ip_c   : std_logic_vector( ip_addr_w_c-1 downto 0 )  := x"FFFFFFFF";
  constant any_port_c : std_logic_vector( udp_port_w_c-1 downto 0 ) := x"FFFF";
 
 
  -- Registers holding current tx info
  signal current_ip_r          : std_logic_vector(ip_addr_w_c-1 downto 0);
  signal current_dest_port_r   : std_logic_vector(udp_port_w_c-1 downto 0);
  signal current_source_port_r : std_logic_vector(udp_port_w_c-1 downto 0);
 
  -- Tx lock information
  signal locked_r : std_logic;
  signal lock_addr_r : std_logic_vector( hibi_addr_width_g-1 downto 0 );
 
 
  -- Table for rx receivers (each agent willing to receive data will have to
  -- register its hibi address to some source ip and ports)
  type receiver_info_type is
    record
      source_ip   : std_logic_vector(ip_addr_w_c-1 downto 0);
      source_port : std_logic_vector(udp_port_w_c-1 downto 0);
      dest_port   : std_logic_vector(udp_port_w_c-1 downto 0);
      hibi_addr   : std_logic_vector(hibi_addr_width_g-1 downto 0);
    end record;
  type     receiver_table_type is array (0 to receiver_table_size_g-1) of receiver_info_type;
  signal   receiver_table_r    : receiver_table_type;
  -- validness
  signal   table_valid_array_r : std_logic_vector(receiver_table_size_g-1 downto 0);
  -- to easily compare if full:
  constant table_full_c        : std_logic_vector(receiver_table_size_g-1 downto 0) := (others => '1');
 
 
 
 
-------------------------------------------------------------------------------
begin  -- rtl
-------------------------------------------------------------------------------
 
  lock_out      <= locked_r;
  lock_addr_out <= lock_addr_r;
  tx_ip_out     <= current_ip_r;
 
  tx_dest_port_out   <= current_dest_port_r;
  tx_source_port_out <= current_source_port_r;
 
  -----------------------------------------------------------------------------
  --
  -----------------------------------------------------------------------------
  main: process (clk, rst_n)
    variable spot_found_v : std_logic;
    variable match_found_v : std_logic;
  begin  -- process main
    if rst_n = '0' then                 -- asynchronous reset (active low)
 
      current_source_port_r <= (others => '0');
      current_dest_port_r   <= (others => '0');
      current_ip_r          <= (others => '0');
      locked_r              <= '0';
      lock_addr_r           <= (others => '0');
      table_valid_array_r   <= (others => '0');
      receiver_table_r      <= (others => ( (others => '0'), (others => '0'), (others => '0'), (others => '0') ));
 
      send_rx_nack_out  <= '0';
      send_rx_ack_out   <= '0';
      send_tx_nack_out  <= '0';
      send_tx_ack_out   <= '0';
      ack_addr_out      <= (others => '0');
      rx_addr_out       <= (others => '0');
      rx_addr_valid_out <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      -- default values
      send_tx_ack_out  <= '0';
      send_tx_nack_out <= '0';
      send_rx_ack_out  <= '0';
      send_rx_nack_out <= '0';
 
 
 
      -------------------------------------------------------------------------
      -- Handle the configuration requests
      -------------------------------------------------------------------------
      if new_tx_conf_in = '1' then
        -- New tx conf coming. Ensure that is not already locked at all, or
        -- locked to the same address, and then update values and send ack.
        -- Otherwise send nack.
 
        if ( locked_r = '0' or lock_addr_r = lock_addr_in )
          and eth_link_up_in = '1'
        then
          -- accept configuration
          current_ip_r          <= ip_in;
          current_dest_port_r   <= dest_port_in;
          current_source_port_r <= source_port_in;
          lock_addr_r           <= lock_addr_in;
          locked_r              <= '1';
 
          -- send ack
          send_tx_ack_out <= '1';
 
        else
          -- reject configuration attempt
          send_tx_nack_out <= '1';
        end if;
 
        ack_addr_out <= response_addr_in;
 
 
      elsif new_rx_conf_in = '1' then
        -- New rx conf coming. Check if there's room in the table, and store
        -- information if possible. Otherwise send a nack.
 
        -- Check if table full
        if table_valid_array_r = table_full_c then
          -- send a nack
          send_rx_nack_out <= '1';
        else
 
          -- Find an empty spot
          spot_found_v := '0';
          for n in 0 to receiver_table_size_g-1 loop
            if table_valid_array_r(n) = '0' and spot_found_v = '0' then
              -- Put it here, to smallest empty spot
              receiver_table_r(n).source_ip   <= ip_in;
              receiver_table_r(n).source_port <= source_port_in;
              receiver_table_r(n).dest_port   <= dest_port_in;
              receiver_table_r(n).hibi_addr   <= response_addr_in;
              table_valid_array_r(n)          <= '1';
 
              spot_found_v := '1';
            end if;
          end loop;  -- n
 
          send_rx_ack_out <= '1';
 
        end if;
 
        ack_addr_out <= response_addr_in;
 
 
      elsif release_lock_in = '1' then
        -- Release tx lock if requested
        locked_r    <= '0';
      end if;
      -- /conf requests
 
 
 
      -- !!! ES 2012-03-22
      -- It seems that signal table_valid_array_r(n) is never
      -- assigned to '0' after reset? Once the table gets full,
      -- there is not way to get more room.
      -- !!!
 
 
      -------------------------------------------------------------------------
      -- Address translation to rx address (hibi addr) according to info
      -- provided by rx_ctrl.
      -- Check that all 3 fields: src ip addr, src port and dst port match.
      -- Wildcards are accepted.
      -------------------------------------------------------------------------
      match_found_v := '0';
      for n in 0 to receiver_table_size_g-1 loop
        if table_valid_array_r(n) = '1'
          and (rx_ip_in = receiver_table_r(n).source_ip
                or
                receiver_table_r(n).source_ip = any_ip_c)
          and (rx_source_port_in = receiver_table_r(n).source_port
                or
                receiver_table_r(n).source_port = any_port_c)
          and (rx_dest_port_in = receiver_table_r(n).dest_port
                or
                receiver_table_r(n).dest_port = any_port_c)
        then
          rx_addr_out   <= receiver_table_r(n).hibi_addr;
          match_found_v := '1';
        end if;
      end loop;  -- n
 
      if match_found_v = '1' then
        rx_addr_valid_out <= '1';
      else
        rx_addr_valid_out <= '0';
      end if;
 
      -------------------------------------------------------------------------
      -- If timeout occures during a tx, tx_ctrl notifies about it and lock
      -- must be released in order to reset hibi_receiver's state
      -------------------------------------------------------------------------
      if timeout_release_in = '1' then
        locked_r <= '0';
      end if;
 
    end if;
  end process main;
 
 
 
end rtl;
 

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.