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_rx_stream.vhd] - Rev 147

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Title      : HIBI PE DMA - streaming rx channel
-- Project    : 
-------------------------------------------------------------------------------
-- File       : hpd_rx_stream.vhd
-- Author     : Lasse Lehtonen
-- Created    : 2012-01-10
-- Last update: 2012-02-28
-------------------------------------------------------------------------------
-- Copyright (c) 2012
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2012-01-10  1.0      LL      Created
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
entity hpd_rx_stream is
 
  generic (
    data_width_g      : integer := 0;
    hibi_addr_width_g : integer := 0;
    addr_width_g      : integer := 0;
    words_width_g     : integer := 0;
    addr_cmp_lo_g     : integer := 0;
    addr_cmp_hi_g     : integer := 0
    );
 
  port (
    clk   : in std_logic;
    rst_n : in std_logic;
 
    -- keep still until a new init
    avalon_addr_in : in std_logic_vector(addr_width_g-1 downto 0);
    hibi_addr_in   : in std_logic_vector(hibi_addr_width_g-1 downto 0);
    irq_words_in   : in std_logic_vector(words_width_g-1 downto 0);
 
    hibi_data_in      : in std_logic_vector(hibi_addr_width_g-1 downto 0);
    hibi_av_in        : in std_logic;
    hibi_empty_in     : in std_logic;
    init_in           : in std_logic;
    irq_ack_in        : in std_logic;
    avalon_waitreq_in : in std_logic;
    avalon_we_in      : in std_logic;
 
    avalon_addr_out    : out std_logic_vector(addr_width_g-1 downto 0);
    avalon_we_out      : out std_logic;
    avalon_be_out      : out std_logic_vector(data_width_g/8-1 downto 0);
    addr_match_out     : out std_logic;
    addr_match_cmb_out : out std_logic;
    irq_out            : out std_logic;
    -- new words in buffer
    words_out          : out std_logic_vector(words_width_g-1 downto 0);
    read_ack_in        : in  std_logic
    );
 
end hpd_rx_stream;
 
architecture rtl of hpd_rx_stream is
 
  constant addr_offset_c : integer := data_width_g/8;
 
  constant words_per_hibi_data_c : integer   := data_width_g/32;
  constant upper_valid_c         : std_logic := '0';
  -- in case of odd data words, is
  -- either upper ('1') or lower ('0') half-word valid?
 
  constant be_width_c       : integer := data_width_g/8;
  signal   addr_match_r     : std_logic;
  signal   addr_match_cmb_s : std_logic;
  signal   write_addr_r     : std_logic_vector(addr_width_g-1 downto 0);
  signal   enable_r         : std_logic;
  signal   ena_av_empty     : std_logic_vector(2 downto 0);
  signal   read_counter_r   : std_logic_vector(words_width_g-1 downto 0);
  signal   irq_counter_r    : std_logic_vector(words_width_g-1 downto 0);
  signal   cnt_max_r        : std_logic_vector(words_width_g-1 downto 0);
  signal   irq_r            : std_logic;
  signal   we_match_waitreq : std_logic_vector(2 downto 0);
  signal   ena_reading_r    : std_logic;
  signal   words_out_r      : std_logic_vector(words_width_g-1 downto 0);
  signal   hibi_av_in_r     : std_logic;
 
begin  -- rtl
 
  we_match_waitreq <= avalon_we_in & addr_match_r & avalon_waitreq_in;
  avalon_we_out    <= addr_match_r and enable_r and ena_reading_r;
  irq_out          <= irq_r;
 
  addr_match_out     <= addr_match_r and enable_r;
  addr_match_cmb_out <= addr_match_cmb_s;
  avalon_addr_out    <= write_addr_r;
 
  ena_av_empty <= enable_r & hibi_av_in & hibi_empty_in;
 
  words_out <= words_out_r;
 
  addr_match : process (hibi_data_in, hibi_addr_in, addr_match_r, ena_av_empty)
  begin  -- process addr_match
 
    case ena_av_empty is
      when "000" | "010" | "011" | "001" =>
        addr_match_cmb_s <= '0';
      when "110" =>
        if hibi_data_in(addr_cmp_hi_g downto addr_cmp_lo_g) =
          hibi_addr_in(addr_cmp_hi_g downto addr_cmp_lo_g) then
          addr_match_cmb_s <= '1';
        else
          addr_match_cmb_s <= '0';
        end if;
      when others =>
        addr_match_cmb_s <= addr_match_r;
    end case;
 
  end process addr_match;
 
  addr_match_reg : process (clk, rst_n)
  begin  -- process addr_matching
    if rst_n = '0' then                 -- asynchronous reset (active low)
      addr_match_r <= '0';
    elsif clk'event and clk = '1' then  -- rising clock edge
      addr_match_r <= addr_match_cmb_s;
    end if;
  end process addr_match_reg;
 
 
  ena : process (clk, rst_n)
    variable inter_addr     : std_logic_vector(addr_width_g-1 downto 0);
    variable read_counter_v : std_logic_vector(words_width_g-1 downto 0);
  begin  -- process ena
    if rst_n = '0' then                 -- asynchronous reset (active low)
      enable_r       <= '0';
      irq_counter_r  <= (others => '0');
      read_counter_r <= (others => '0');
      write_addr_r   <= (others => '0');
      cnt_max_r      <= (others => '0');
      irq_r          <= '0';
      ena_reading_r  <= '0';
      words_out_r    <= (others => '0');
      hibi_av_in_r   <= '0';
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      words_out_r <= read_counter_r - irq_counter_r;
 
      read_counter_v := read_counter_r;
 
      hibi_av_in_r <= hibi_av_in;
 
      if init_in = '1' then
        enable_r       <= '1';
        ena_reading_r  <= '1';
        read_counter_r <= irq_words_in;
        irq_counter_r  <= irq_words_in;
        cnt_max_r      <= irq_words_in;
        write_addr_r   <= avalon_addr_in;
      end if;
 
      if read_ack_in = '1' then
        read_counter_v := read_counter_r - irq_words_in;
        read_counter_r <= read_counter_v;
        if read_counter_v = 0 then
          read_counter_r <= cnt_max_r;
          irq_counter_r  <= cnt_max_r;
          write_addr_r   <= avalon_addr_in;
        end if;
        if enable_r = '0' then          -- 
          read_counter_r <= irq_words_in;
          irq_counter_r  <= irq_words_in;
          cnt_max_r      <= irq_words_in;
        end if;
        ena_reading_r <= '1';
      end if;
 
      if irq_ack_in = '1' then
        irq_r <= '0';
      else
        irq_r <= irq_r;
      end if;
 
      if ena_reading_r = '1' then
 
        case we_match_waitreq is
          when "110" =>
            -- we're writing here
            if irq_counter_r <= conv_std_logic_vector(words_per_hibi_data_c,
                                                      words_width_g)
            then
              write_addr_r  <= write_addr_r + addr_offset_c;
              ena_reading_r <= '0';
              irq_r         <= '1';
              irq_counter_r <= irq_counter_r - words_per_hibi_data_c;
            else
              write_addr_r  <= write_addr_r + addr_offset_c;
              irq_counter_r <= irq_counter_r - words_per_hibi_data_c;
            end if;
 
          when others =>
            if irq_counter_r /= read_counter_r
              and (hibi_av_in = '0' or hibi_av_in_r = '1')
            then
              ena_reading_r <= '0';
              irq_r         <= '1';
            end if;
 
        end case;
 
      end if;
 
    end if;
  end process ena;
 
  byteena : process (irq_counter_r)
  begin  -- process byteena
    if irq_counter_r = conv_std_logic_vector(1, words_width_g)
      and words_per_hibi_data_c = 2
    then
      -- odd number of words wanted, e.g. 64 bit hibi, wanted 5 32-bit
      -- words
      avalon_be_out(be_width_c-1 downto be_width_c/2) <=
        (others => upper_valid_c);
      avalon_be_out(be_width_c/2-1 downto 0) <=
        (others => (not upper_valid_c));
    else
      avalon_be_out <= (others => '1');
    end if;
 
  end process byteena;
 
 
 
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.