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/] [tx_ctrl.vhd] - Rev 145

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Title      : Tx control block
-- Project    : UDP2HIBI
-------------------------------------------------------------------------------
-- File       : tx_ctrl.vhd
-- Author     : Jussi Nieminen  <niemin95@galapagosinkeiju.cs.tut.fi>
-- Last update: 2012-03-23
-- Platform   : 
-------------------------------------------------------------------------------
-- Description: Sub-block of udp2hibi.
--              Takes care of chatting with udp/ip block.
--              This gets data from HIBI receiver and gives it to UDP/IP.
--              Includes multclk-fifo and a state machine.
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2009/12/11  1.0      niemin95        Created
-- 2012-03-23  1.0      ege             Beautifying and commenting.
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.udp2hibi_pkg.all;
 
 
entity tx_ctrl is
 
  generic (
    frequency_g           : integer := 50_000_000;
    multiclk_fifo_depth_g : integer := 10
    );
 
  port (
    clk                 : in  std_logic;
    clk_udp             : in  std_logic;
    rst_n               : in  std_logic;
 
    -- for multiclk fifo
    tx_data_in          : in  std_logic_vector (udp_block_data_w_c-1 downto 0);
    tx_we_in            : in  std_logic;
    tx_full_out         : out std_logic;
 
    -- from multiclk fifo to udp/ip
    tx_data_out         : out std_logic_vector (udp_block_data_w_c-1 downto 0);
    tx_data_valid_out   : out std_logic;
    tx_re_in            : in  std_logic;
 
    -- other signals to udp/ip
    new_tx_out          : out std_logic;
    tx_len_out          : out std_logic_vector (tx_len_w_c-1 downto 0);
    dest_ip_out         : out std_logic_vector (ip_addr_w_c-1 downto 0);
    dest_port_out       : out std_logic_vector (udp_port_w_c-1 downto 0);
    source_port_out     : out std_logic_vector (udp_port_w_c-1 downto 0);
 
    -- signals to and from hibi_receiver
    new_tx_in           : in  std_logic;
    tx_len_in           : in  std_logic_vector (tx_len_w_c-1 downto 0);
    new_tx_ack_out      : out std_logic;
    timeout_in          : in  std_logic_vector (timeout_w_c-1 downto 0);
    timeout_to_hr_out   : out std_logic;
 
    -- signals to and from ctrl regs
    tx_ip_in            : in  std_logic_vector (ip_addr_w_c-1 downto 0);
    tx_dest_port_in     : in  std_logic_vector (udp_port_w_c-1 downto 0);
    tx_source_port_in   : in  std_logic_vector (udp_port_w_c-1 downto 0);
    timeout_release_out : out std_logic
    );
 
end tx_ctrl;
 
 
architecture rtl of tx_ctrl is
 
  component multiclk_fifo
    generic (
      re_freq_g    : integer;
      we_freq_g    : integer;
      depth_g      : integer;
      data_width_g : integer);
    port (
      clk_re    : in  std_logic;
      clk_we    : in  std_logic;
      rst_n     : in  std_logic;
      data_in   : in  std_logic_vector (data_width_g-1 downto 0);
      we_in     : in  std_logic;
      full_out  : out std_logic;
      one_p_out : out std_logic;
      re_in     : in  std_logic;
      data_out  : out std_logic_vector (data_width_g-1 downto 0);
      empty_out : out std_logic;
      one_d_out : out std_logic);
  end component;
 
 
  signal  new_tx_r        : std_logic;
  signal  tx_cnt_r        : integer range 0 to 2**(tx_len_w_c-1);
  subtype timeout_int is integer range 0 to 2**timeout_w_c-1;
  signal  timeout_cnt_r   : timeout_int;
  signal  timeout_value_r : timeout_int;
 
  signal tx_data_to_fifo      : std_logic_vector(udp_block_data_w_c-1 downto 0);
  signal tx_we_to_fifo        : std_logic;
  signal tx_full_from_fifo    : std_logic;
  signal full_to_h_receiver_r : std_logic;
  signal gain_tx_control_r    : std_logic;
  signal tx_we_local_r        : std_logic;
  signal empty_from_fifo      : std_logic;
  signal udp_ip_re_old_r      : std_logic;
  signal new_tx_ack_r         : std_logic;
 
  -- states:
  -- idle: as one might guess..
  -- tx: count writes to fifo, and reset timeout_cnt every time data is written
  -- dump: timeout, dump fake data to fifo until tx_len of data is written
  type   state_type is (idle, tx, dump);
  signal state_r : state_type;
 
-------------------------------------------------------------------------------
begin  -- rtl
-------------------------------------------------------------------------------
 
  tx_multiclk_fifo : multiclk_fifo
    generic map (
      re_freq_g    => udp_block_freq_c,
      we_freq_g    => frequency_g,
      depth_g      => multiclk_fifo_depth_g,
      data_width_g => udp_block_data_w_c
      )
    port map (
      clk_re    => clk_udp,
      clk_we    => clk,
      rst_n     => rst_n,
 
      data_in   => tx_data_to_fifo,
      we_in     => tx_we_to_fifo,
      full_out  => tx_full_from_fifo,
      one_p_out => open,
 
      re_in     => tx_re_in,
      data_out  => tx_data_out,
      empty_out => empty_from_fifo,
      one_d_out => open
      );
 
  tx_data_valid_out <= not empty_from_fifo;
 
  -- Inputs from ctrl-regs go directly to hibi
  dest_ip_out     <= tx_ip_in;
  dest_port_out   <= tx_dest_port_in;
  source_port_out <= tx_source_port_in;
  new_tx_out      <= new_tx_r;
 
  tx_full_out <= tx_full_from_fifo or full_to_h_receiver_r;
 
 
  -----------------------------------------------------------------------------
  -- in case of a timeout, this block has to take care of finishing the tx
  -- (with fake data ofcourse)
  -----------------------------------------------------------------------------
  tx_fifo_mux : process (gain_tx_control_r, tx_we_local_r, tx_we_in, tx_data_in)
  begin  -- process tx_fifo_mux
    if gain_tx_control_r = '1' then
      -- timeout has occured, write zeroes to fifo
      tx_data_to_fifo <= (others => '0');
      tx_we_to_fifo   <= tx_we_local_r;
    else
      -- situation normal, nothing fouled up...
      tx_data_to_fifo <= tx_data_in;
      tx_we_to_fifo   <= tx_we_in;
    end if;
  end process tx_fifo_mux;
 
  new_tx_ack_out <= new_tx_ack_r;
 
  -----------------------------------------------------------------------------
  --
  -----------------------------------------------------------------------------
  main : process (clk, rst_n)
    variable sub_from_len_v : integer range 0 to 1;
  begin  -- process main
    if rst_n = '0' then                 -- asynchronous reset (active low)
 
      tx_cnt_r        <= 0;
      timeout_cnt_r   <= 0;
      timeout_value_r <= 0;
      state_r         <= idle;
 
      full_to_h_receiver_r <= '0';
      gain_tx_control_r    <= '0';
      tx_we_local_r        <= '0';
      udp_ip_re_old_r      <= '0';
 
      timeout_release_out <= '0';
      timeout_to_hr_out   <= '0';
      new_tx_r            <= '0';
      tx_len_out          <= (others => '0');
      new_tx_ack_r        <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      udp_ip_re_old_r <= tx_re_in;
 
      -- default values
      new_tx_ack_r        <= '0';
      timeout_release_out <= '0';
      timeout_to_hr_out   <= '0';
      tx_we_local_r       <= '0';
 
      -- We don't know in which state we are when udp/ip starts to read, so
      -- clear new_tx here
      if new_tx_r = '1' and tx_re_in = '1' and udp_ip_re_old_r = '0' then
        -- Rising edge of re, clear new_tx
        new_tx_r <= '0';
      end if;
 
      case state_r is
 
        -----------------------------------------------------------------------
        when idle =>
 
          if new_tx_in = '1' and new_tx_ack_r = '0' then
            new_tx_ack_r <= '1';
 
            -- store length (in halfwords) and timeout
            sub_from_len_v := 0;
            if tx_we_in = '1' and tx_full_from_fifo = '0' then
              -- if new_tx comes parallel with the first write operation, we
              -- must subtrackt one from the tx_cnt
              sub_from_len_v := 1;
            end if;
            tx_cnt_r <= to_integer(unsigned(tx_len_in(tx_len_w_c-1 downto 1)))
                        + to_integer(unsigned(tx_len_in(0 downto 0)))
                        - sub_from_len_v;
            timeout_value_r <= to_integer(unsigned(timeout_in));
            timeout_cnt_r   <= 0;
 
            if to_integer(unsigned(tx_len_in)) > 2 or sub_from_len_v = 0 then
              -- no need to get into tx state if tx_len is 1 and the data is already
              -- written (in fact going to tx state would result in malfunction)
              state_r <= tx;
            end if;
 
            new_tx_r   <= '1';
            tx_len_out <= tx_len_in;
          end if;
 
 
          -----------------------------------------------------------------------
        when tx =>
 
          if tx_we_in = '1' and tx_full_from_fifo = '0' then
 
            -- reset timeout counter
            timeout_cnt_r <= 0;
 
            if tx_cnt_r = 1 then
              -- last data written
              state_r  <= idle;
              tx_cnt_r <= 0;
            else
              tx_cnt_r <= tx_cnt_r - 1;
            end if;
 
          elsif timeout_cnt_r = timeout_value_r then
 
            -- timeout! Fill fifo with fake data, and inform ctrl regs
            state_r              <= dump;
            timeout_release_out  <= '1';
            timeout_to_hr_out    <= '1';
            -- take control over the data line
            gain_tx_control_r    <= '1';
            full_to_h_receiver_r <= '1';
            timeout_cnt_r        <= 0;
 
          else
            -- increase timeout counter
            timeout_cnt_r <= timeout_cnt_r + 1;
          end if;
 
 
          -----------------------------------------------------------------------
        when dump =>
 
          if tx_full_from_fifo = '0' then
 
            -- write them zeroes
            tx_we_local_r <= '1';
 
            if tx_we_local_r = '1' then
 
              if tx_cnt_r = 1 then
                -- last data
                state_r  <= idle;
                tx_cnt_r <= 0;
 
                -- give fifo back to hibi_receiver
                gain_tx_control_r    <= '0';
                full_to_h_receiver_r <= '0';
 
              else
                tx_cnt_r <= tx_cnt_r - 1;
              end if;
            end if;
          end if;
 
        when others => null;
      end case;
 
    end if;
  end process main;
 
 
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.