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

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [Altera/] [ip.hwp.cpu/] [nios_ii_sram/] [1.0/] [hdl/] [ip/] [hpd_tx_control.vhd] - Rev 147

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Title      : HIBI PE DMA - tx controller
-- Project    : 
-------------------------------------------------------------------------------
-- File       : hpd_tx_control.vhd
-- Author     : kulmala3
-- Created    : 2012-01-10
-- Last update: 2012-02-08
-- Description: 
--
-------------------------------------------------------------------------------
-- Copyright (c) 2005 
-- 
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 30.03.2005  1.0      AK      Created
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
 
entity hpd_tx_control is
 
  generic (
 
    data_width_g  : integer := 32;
    addr_width_g  : integer := 32;
    words_width_g : integer := 16);
 
  port (
    clk                     : in  std_logic;
    rst_n                   : in  std_logic;
    -- Avalon master read interface
    avalon_addr_out         : out std_logic_vector(addr_width_g-1 downto 0);
    avalon_re_out           : out std_logic;
    avalon_readdata_in      : in  std_logic_vector(data_width_g-1 downto 0);
    avalon_waitrequest_in   : in  std_logic;
    avalon_readdatavalid_in : in  std_logic;
 
    -- hibi write interface
    hibi_data_out : out std_logic_vector(data_width_g-1 downto 0);
    hibi_av_out   : out std_logic;
    hibi_full_in  : in  std_logic;
    hibi_comm_out : out std_logic_vector(4 downto 0);
    hibi_we_out   : out std_logic;
 
    -- DMA conf interface
    tx_start_in        : in  std_logic;
    tx_status_done_out : out std_logic;
    tx_comm_in         : in  std_logic_vector(4 downto 0);
    tx_hibi_addr_in    : in  std_logic_vector(addr_width_g-1 downto 0);
    tx_ram_addr_in     : in  std_logic_vector(addr_width_g-1 downto 0);
    tx_words_in        : in  std_logic_vector(words_width_g-1 downto 0)
    );
 
end hpd_tx_control;
 
architecture rtl of hpd_tx_control is
 
  type     control_states is (idle, transmit_addr, transmit, hfull);
  signal   control_r     : control_states;
  constant addr_offset_c : integer := data_width_g/8;
 
  signal addr_cnt_en     : std_logic;
  signal addr_cnt_value  : std_logic_vector(addr_width_g-1 downto 0);
  signal addr_cnt_load   : std_logic;
  signal addr_r            : std_logic_vector(addr_width_g-1 downto 0);
  signal words_cnt_en      : std_logic;
  signal words_cnt_value : std_logic_vector(addr_width_g-1 downto 0);
  signal words_cnt_load    : std_logic;
  signal words_r           : std_logic_vector(addr_width_g-1 downto 0);
 
  signal addr_words_eq : std_logic;
 
  signal addr_to_stop : std_logic_vector(addr_width_g-1 downto 0);
  signal avalon_re    : std_logic;
  signal start_re_r     : std_logic;
 
  signal hibi_write_addr_r : std_logic;
  signal data_src_sel      : std_logic;
  signal hibi_we         : std_logic;
  signal hibi_stop_we_r    : std_logic;
 
 
begin  -- rtl
 
  -----------------------------------------------------------------------------
  -- 1) waitrequest affects the data reading
  -- 2) readdatavalid data write to hibi
  -- 3) avalon side read must control the amount of data
  -- 4) whenever readdatavalid is asserted, data is written to HIBI
  -- 5) HIBI full is problematic. A counter must be added to see from which
  --    address we have succesfully read the data so far. We cannot
  --    save the data to register, because we are unaware of the latency.
  --    So when full comes, the read process from avalon must be started
  --    again.
  -- 6) write and read signals should be asynchronously controlled by
  --    signals from hibi and avalon in order to react as fast as possible.
  -- 7) after full the write should be ceased. readdatavalid from older data
  --    should be taken care of. Write continues only after read enable has
  --    been asserted again?
  -- 8) read from avalon must proceed as fast as possible. for example,
  --    start already when writing address to hibi. (at least one clock
  --    cycle latency expected, should be safe). Or after full.
  -- 9) data to hibi comes from either register input (address) or
  --    straight from the memory. mux is needed.
  -----------------------------------------------------------------------------
 
  hibi_comm_out   <= tx_comm_in;
  avalon_addr_out <= addr_r;
 
  addr_cnt_s : process (clk, rst_n)
  begin  -- process addr_cnt
    if rst_n = '0' then                 -- asynchronous reset (active low)
      addr_r <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      if addr_cnt_en = '1' then
        addr_r <= addr_r +
                  std_logic_vector(to_unsigned(addr_offset_c, addr_width_g));
      elsif addr_cnt_load = '1' then
        addr_r <= addr_cnt_value;
      end if;
    end if;
  end process addr_cnt_s;
 
 
  addr_cnt_load <= (tx_start_in or hibi_full_in);
 
  addr_cnt : process (tx_ram_addr_in, words_r, tx_start_in)
  begin  -- process addr_cnt
    if tx_start_in = '1' then
      -- addr from input
      addr_cnt_value <= tx_ram_addr_in;
    else
      -- addr from counter
      addr_cnt_value <= words_r;
    end if;
  end process addr_cnt;
 
 
  words_cnt : process (clk, rst_n)
  begin
    if rst_n = '0' then                 -- asynchronous reset (active low)
      words_r <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      if words_cnt_en = '1' then
        words_r <= words_r +
                   std_logic_vector(to_unsigned(addr_offset_c, addr_width_g));
      elsif words_cnt_load = '1' then
        words_r <= words_cnt_value;
      end if;
    end if;
  end process words_cnt;
 
  -- words counted only when data is written
  words_cnt_en <= hibi_we and (not data_src_sel);
 
  -- hibi_we depends on readdatavalid and full + control signal for
  -- address writing
  -- start address writing right when the signal comes in.
  -- no old readdatavalids should be written if full is short.
  hibi_we_out <= hibi_we;
  hibi_we <= ((data_src_sel) or
                (avalon_readdatavalid_in and (not hibi_stop_we_r)))
               and (not hibi_full_in);
 
  data_src_sel <= tx_start_in or hibi_write_addr_r;
  hibi_av_out  <= data_src_sel;
 
  addr_data : process (tx_hibi_addr_in, avalon_readdata_in, data_src_sel)
  begin  -- process addr_data
    if data_src_sel = '1' then
      hibi_data_out                          <= (others => '0');
      hibi_data_out(addr_width_g-1 downto 0) <= tx_hibi_addr_in;
    else
      hibi_data_out <= avalon_readdata_in;
    end if;
  end process addr_data;
 
  -- if we're reading and not forced to wait,
  -- increase the address. we want to cease reading if hibi goes full
  -- (reload address)
  addr_cnt_en <= (avalon_re and (not avalon_waitrequest_in)) and
                   (not hibi_full_in);
  avalon_re_out <= avalon_re;
  -- read enable depends on the words transferred, if a 
  -- transmission is ongoing. shoot as soon as possible,
  -- whenever new transmission is assigned.
  avalon_re   <= start_re_r;
 
  comparison : process (addr_r, addr_to_stop)
  begin  -- process comparison
    if addr_r = addr_to_stop then
      addr_words_eq <= '1';
    else
      addr_words_eq <= '0';
    end if;
  end process comparison;
 
  addr_to_stop_p : process (tx_words_in, tx_ram_addr_in)
  begin  -- process addr_to_stop
    addr_to_stop <= tx_ram_addr_in + std_logic_vector(
      resize(unsigned(tx_words_in)*addr_offset_c, addr_width_g));
  end process addr_to_stop_p;
 
  words_cnt_value <= tx_ram_addr_in;
  words_cnt_load  <= tx_start_in;
 
  main : process (clk, rst_n)
  begin  -- process main
    if rst_n = '0' then                 -- asynchronous reset (active low)
      control_r          <= idle;
      start_re_r         <= '0';
      hibi_write_addr_r  <= '0';
      tx_status_done_out <= '1';
      hibi_stop_we_r     <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
      case control_r is
        when idle =>
          hibi_write_addr_r  <= '0';
          start_re_r         <= '0';
          tx_status_done_out <= '1';
          hibi_stop_we_r     <= '1';
 
          if tx_start_in = '1' then
            -- avalon read address
            -- address which contents written to hibi
            tx_status_done_out <= '0';
            hibi_stop_we_r     <= '0';
 
            if hibi_full_in = '0' then
              -- address will be transferred in this clock cycle
              control_r  <= transmit;
              start_re_r <= '1';
            else
              hibi_write_addr_r <= '1';
              control_r         <= transmit_addr;
            end if;
          end if;
 
        when transmit_addr =>
          -- if we're here, hibi was full
          if hibi_full_in = '0' then
            -- we wrote the addr
            start_re_r        <= '1';
            control_r         <= transmit;
            hibi_write_addr_r <= '0';
          else
            start_re_r        <= '0';
            control_r         <= transmit_addr;
            hibi_write_addr_r <= '1';
          end if;
 
        when transmit =>
          if hibi_full_in = '1' then
            start_re_r     <= '0';
            control_r      <= hfull;
            hibi_stop_we_r <= '1';
          else
            start_re_r     <= '1';
            hibi_stop_we_r <= '0';
            control_r      <= transmit;
          end if;
 
--          if addr_words_eq = '1' and hibi_full_in = '0' then
          if addr_words_eq = '1' and hibi_we = '1' then
            control_r          <= idle;
            -- stopped transferring
            tx_status_done_out <= '1';
            hibi_stop_we_r     <= '1';
          end if;
 
        when hfull =>
          if hibi_full_in = '0' and avalon_readdatavalid_in = '0' then
            -- datavalid has to go down before proceed.
            -- so we make sure that no invalid data is written
            -- when there's a short full.
            start_re_r     <= '1';
            hibi_stop_we_r <= '0';
            control_r      <= transmit;
          else
            start_re_r     <= '0';
            hibi_stop_we_r <= '1';
            control_r      <= hfull;
          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.