-------------------------------------------------------------------------------
--
-- Copyright (C) 2014
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program 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 General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------

-- Purpose: IP components declarations for various devices that get wrapped by the tech components

library IEEE;
  use IEEE.std_logic_1164.all;

package tech_memory_component_pkg is

  -----------------------------------------------------------------------------
  -- ip_stratixiv
  -----------------------------------------------------------------------------

  component ip_stratixiv_ram_crwk_crw is  -- support different port data widths and corresponding address ranges
    generic (
      g_adr_a_w     : natural := 5;
      g_dat_a_w     : natural := 32;
      g_adr_b_w     : natural := 7;
      g_dat_b_w     : natural := 8;
      g_nof_words_a : natural := 2**5;
      g_nof_words_b : natural := 2**7;
      g_rd_latency  : natural := 2;  -- choose 1 or 2
      g_init_file   : string  := "UNUSED"
    );
    port (
      address_a   : in std_logic_vector(g_adr_a_w - 1 downto 0);
      address_b   : in std_logic_vector(g_adr_b_w - 1 downto 0);
      clock_a   : in std_logic  := '1';
      clock_b   : in std_logic ;
      data_a    : in std_logic_vector(g_dat_a_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_b_w - 1 downto 0);
      enable_a    : in std_logic  := '1';
      enable_b    : in std_logic  := '1';
      rden_a    : in std_logic  := '1';
      rden_b    : in std_logic  := '1';
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a   : out std_logic_vector(g_dat_a_w - 1 downto 0);
      q_b   : out std_logic_vector(g_dat_b_w - 1 downto 0)
    );
  end component;

  component ip_stratixiv_ram_crw_crw is
    generic (
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 2;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port (
      address_a   : in std_logic_vector(g_adr_w - 1 downto 0);
      address_b   : in std_logic_vector(g_adr_w - 1 downto 0);
      clock_a   : in std_logic  := '1';
      clock_b   : in std_logic ;
      data_a    : in std_logic_vector(g_dat_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_w - 1 downto 0);
      enable_a    : in std_logic  := '1';
      enable_b    : in std_logic  := '1';
      rden_a    : in std_logic  := '1';
      rden_b    : in std_logic  := '1';
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a   : out std_logic_vector(g_dat_w - 1 downto 0);
      q_b   : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_stratixiv_ram_cr_cw is
    generic (
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 2;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port (
      data      : in  std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      rdclock   : in  std_logic ;
      rdclocken : in  std_logic  := '1';
      wraddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      wrclock   : in  std_logic  := '1';
      wrclocken : in  std_logic  := '1';
      wren      : in  std_logic  := '0';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_stratixiv_ram_r_w is
    generic (
      g_adr_w     : natural := 5;
      g_dat_w     : natural := 8;
      g_nof_words : natural := 2**5;
      g_init_file : string  := "UNUSED"
    );
    port (
      clock       : in std_logic  := '1';
      enable      : in std_logic  := '1';
      data        : in std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress   : in std_logic_vector(g_adr_w - 1 downto 0);
      wraddress   : in std_logic_vector(g_adr_w - 1 downto 0);
      wren        : in std_logic  := '0';
      q           : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_stratixiv_rom_r is
    generic (
      g_adr_w     : natural := 5;
      g_dat_w     : natural := 8;
      g_nof_words : natural := 2**5;
      g_init_file : string  := "UNUSED"
    );
    port (
      address   : in std_logic_vector(g_adr_w - 1 downto 0);
      clock     : in std_logic  := '1';
      clken     : in std_logic  := '1';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;


  -----------------------------------------------------------------------------
  -- ip_arria10
  -----------------------------------------------------------------------------

  component ip_arria10_ram_crwk_crw is
    generic (
      g_adr_a_w     : natural := 5;
      g_dat_a_w     : natural := 32;
      g_adr_b_w     : natural := 4;
      g_dat_b_w     : natural := 64;
      g_nof_words_a : natural := 2**5;
      g_nof_words_b : natural := 2**4;
      g_rd_latency  : natural := 1;  -- choose 1 or 2
      g_init_file   : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_a_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_b_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_a_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_b_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_a_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_b_w - 1 downto 0)
    );
  end component;

  component ip_arria10_ram_crw_crw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_ram_cr_cw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      data      : in  std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      rdclk     : in  std_logic ;
      wraddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      wrclk     : in  std_logic  := '1';
      wren      : in  std_logic  := '0';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_ram_r_w is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port (
      clk         : in std_logic  := '1';
      data        : in std_logic_vector(g_dat_w - 1 downto 0) := (others => '0');
      rdaddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wraddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wren        : in std_logic  := '0';
      q           : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  -----------------------------------------------------------------------------
  -- ip_arria10_e3sge3
  -----------------------------------------------------------------------------

  component ip_arria10_e3sge3_ram_crwk_crw is
    generic (
      g_adr_a_w     : natural := 5;
      g_dat_a_w     : natural := 32;
      g_adr_b_w     : natural := 4;
      g_dat_b_w     : natural := 64;
      g_nof_words_a : natural := 2**5;
      g_nof_words_b : natural := 2**4;
      g_rd_latency  : natural := 1;  -- choose 1 or 2
      g_init_file   : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_a_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_b_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_a_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_b_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_a_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_b_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e3sge3_ram_crw_crw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e3sge3_ram_cr_cw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      data      : in  std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      rdclk     : in  std_logic ;
      wraddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      wrclk     : in  std_logic  := '1';
      wren      : in  std_logic  := '0';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e3sge3_ram_r_w is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port (
      clk         : in std_logic  := '1';
      data        : in std_logic_vector(g_dat_w - 1 downto 0) := (others => '0');
      rdaddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wraddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wren        : in std_logic  := '0';
      q           : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  -----------------------------------------------------------------------------
  -- ip_arria10_e1sg
  -----------------------------------------------------------------------------

  component ip_arria10_e1sg_ram_crwk_crw is
    generic (
      g_adr_a_w     : natural := 5;
      g_dat_a_w     : natural := 32;
      g_adr_b_w     : natural := 4;
      g_dat_b_w     : natural := 64;
      g_nof_words_a : natural := 2**5;
      g_nof_words_b : natural := 2**4;
      g_rd_latency  : natural := 1;  -- choose 1 or 2
      g_init_file   : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_a_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_b_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_a_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_b_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_a_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_b_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e1sg_ram_crw_crw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e1sg_ram_cr_cw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      data      : in  std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      rdclk     : in  std_logic ;
      wraddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      wrclk     : in  std_logic  := '1';
      wren      : in  std_logic  := '0';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e1sg_ram_r_w is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port (
      clk         : in std_logic  := '1';
      data        : in std_logic_vector(g_dat_w - 1 downto 0) := (others => '0');
      rdaddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wraddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wren        : in std_logic  := '0';
      q           : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  -----------------------------------------------------------------------------
  -- ip_arria10_e2sg
  -----------------------------------------------------------------------------

  component ip_arria10_e2sg_ram_crwk_crw is
    generic (
      g_adr_a_w     : natural := 5;
      g_dat_a_w     : natural := 32;
      g_adr_b_w     : natural := 4;
      g_dat_b_w     : natural := 64;
      g_nof_words_a : natural := 2**5;
      g_nof_words_b : natural := 2**4;
      g_rd_latency  : natural := 1;  -- choose 1 or 2
      g_init_file   : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_a_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_b_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_a_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_b_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_a_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_b_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e2sg_ram_crw_crw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e2sg_ram_cr_cw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port
  (
      data      : in  std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      rdclk     : in  std_logic ;
      wraddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      wrclk     : in  std_logic  := '1';
      wren      : in  std_logic  := '0';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_arria10_e2sg_ram_r_w is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "UNUSED"
    );
    port (
      clk         : in std_logic  := '1';
      data        : in std_logic_vector(g_dat_w - 1 downto 0) := (others => '0');
      rdaddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wraddress   : in std_logic_vector(g_adr_w - 1 downto 0) := (others => '0');
      wren        : in std_logic  := '0';
      q           : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  -----------------------------------------------------------------------------
  -- ip_ultrascale
  -----------------------------------------------------------------------------
  component ip_ultrascale_ram_crw_crw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "none"
    );
    port
  (
      address_a : in std_logic_vector(g_adr_w - 1 downto 0);
      address_b : in std_logic_vector(g_adr_w - 1 downto 0);
      clk_a     : in std_logic  := '1';
      clk_b     : in std_logic ;
      data_a    : in std_logic_vector(g_dat_w - 1 downto 0);
      data_b    : in std_logic_vector(g_dat_w - 1 downto 0);
      wren_a    : in std_logic  := '0';
      wren_b    : in std_logic  := '0';
      q_a       : out std_logic_vector(g_dat_w - 1 downto 0);
      q_b       : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

  component ip_ultrascale_ram_cr_cw is
    generic (
      g_inferred   : boolean := false;
      g_adr_w      : natural := 5;
      g_dat_w      : natural := 8;
      g_nof_words  : natural := 2**5;
      g_rd_latency : natural := 1;  -- choose 1 or 2
      g_init_file  : string  := "none"
    );
    port
  (
      data      : in  std_logic_vector(g_dat_w - 1 downto 0);
      rdaddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      rdclk     : in  std_logic ;
      wraddress : in  std_logic_vector(g_adr_w - 1 downto 0);
      wrclk     : in  std_logic  := '1';
      wren      : in  std_logic  := '0';
      q         : out std_logic_vector(g_dat_w - 1 downto 0)
    );
  end component;

end tech_memory_component_pkg;