--SINGLE_FILE_TAG
-------------------------------------------------------------------------------
-- select_param.vhd - entity/architecture pair
-------------------------------------------------------------------------------
--
--  ***************************************************************************
--  **  Copyright(C) 2003 by Xilinx, Inc. All rights reserved.               **
--  **                                                                       **
--  **  This text contains proprietary, confidential                         **
--  **  information of Xilinx, Inc. , is distributed by                      **
--  **  under license from Xilinx, Inc., and may be used,                    **
--  **  copied and/or disclosed only pursuant to the terms                   **
--  **  of a valid license agreement with Xilinx, Inc.                       **
--  **                                                                       **
--  **  Unmodified source code is guaranteed to place and route,             **
--  **  function and run at speed according to the datasheet                 **
--  **  specification. Source code is provided "as-is", with no              **
--  **  obligation on the part of Xilinx to provide support.                 **
--  **                                                                       **
--  **  Xilinx Hotline support of source code IP shall only include          **
--  **  standard level Xilinx Hotline support, and will only address         **
--  **  issues and questions related to the standard released Netlist        **
--  **  version of the core (and thus indirectly, the original core source). **
--  **                                                                       **
--  **  The Xilinx Support Hotline does not have access to source            **
--  **  code and therefore cannot answer specific questions related          **
--  **  to source HDL. The Xilinx Support Hotline will only be able          **
--  **  to confirm the problem in the Netlist version of the core.           **
--  **                                                                       **
--  **  This copyright and support notice must be retained as part           **
--  **  of this text at all times.                                           **
--  ***************************************************************************
--
-------------------------------------------------------------------------------
-- Filename:        select_param.vhd
-- Version:         v1.10b
-- Description:     Selects correct parameter for addressed memory bank
--
-------------------------------------------------------------------------------
-- Structure:   
--                  emc.vhd
--                      -- addr_counter_mux.vhd
--                      -- data_path.vhd
--                      -- io_registers.vhd
--                      -- mem_state_machine.vhd
--                      -- select_param.vhd
--                      -- wait_states.vhd
-------------------------------------------------------------------------------
-- Author:      DAB
-- History:
--  DAB             02-13-2002      
-- ^^^^^^
--      First version to determine which memory is synchronous (ZBT) vs. 
--      asynchronous (SRAM).
-- ~~~~~~
--  ALS            11-28-2002
-- ^^^^^^
--  Version 1.10a created to include bus width/mem data width matching.
-- ~~~~~~
--   ALS           03/10/03    
-- ^^^^^^
--  Version 1.10.b created to include a generic to include/exclude negedge 
--  io registers
-- ~~~~~~
-------------------------------------------------------------------------------
-- Naming Conventions:
--      active low signals:                     "*_n"
--      clock signals:                          "clk", "clk_div#", "clk_#x" 
--      reset signals:                          "rst", "rst_n" 
--      generics:                               "C_*" 
--      user defined types:                     "*_TYPE" 
--      state machine next state:               "*_ns" 
--      state machine current state:            "*_cs" 
--      combinatorial signals:                  "*_cmb" 
--      pipelined or register delay signals:    "*_d#" 
--      counter signals:                        "*cnt*"
--      clock enable signals:                   "*_ce" 
--      internal version of output port         "*_i"
--      device pins:                            "*_pin" 
--      ports:                                  - Names begin with Uppercase 
--      processes:                              "*_PROCESS" 
--      component instantiations:               "<ENTITY_>I_<#|FUNC>
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_misc.all;
library Unisim;
use Unisim.all;

--library emc_common_v1_10_a;
--use emc_common_v1_10_a.all;

-------------------------------------------------------------------------------
-- Definition of Generics:
--      C_NUM_BANKS_MEM             -- number of memory banks 
--      C_GLOBAL_SYNC_MEM           -- at least one memory bank is synchronous
--      C_SYNCH_MEM_(0:7)           -- memory bank (0:7) type
--      C_ACCESS_CNTR_(0:7)         -- memory bank (0:7) number of accesses for
--                                     datawidth matching
--      C_ADDR_CNTR_WIDTH           -- width of address counter in bits
--      C_MEM(0:7)_WIDTH            -- data width of memory banks
--      C_SYNCH_PIPEDELAY_(0:7)     -- synchronous pipe delay of memory banks
--      C_GLOBAL_DATAWIDTH_MATCH    -- datawidth matching is supported for at least
--                                     one memory bank
--      C_INCLUDE_DATAWIDTH_MATCHING_(0:7)  -- include datawidth matching for memory 
--                                             bank
--
-- Definition of Ports:
--  -- inputs
--     Bus2IP_Mem_CS                -- chip selects for memory banks
--                                     indicates which memory bank is being accessed
--                                   
--  -- outputs
--     Synch_mem                    -- addressed memory bank type
--     Access_cntr                  -- number of accesses for addressed memory bank
--                                     for datawidth matching
--     Mem_width_bytes              -- datawidth in bytes of addressed memory bank
--     Two_pipe_delay               -- synchronous memory pipe delay of addressed 
--                                     memory bank
--     Datawidth_match              -- perform datawidth matching for addressed 
--                                     memory bank
---------------------------------------------------------------------------

-----------------------------------------------------------------------------
-- Entity section
-----------------------------------------------------------------------------


entity select_param is
  generic (
    C_NUM_BANKS_MEM     : integer range 1 to 8 := 8;
    C_GLOBAL_SYNC_MEM   : integer range 0 to 1 := 0;
    C_SYNCH_MEM_0       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_1       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_2       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_3       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_4       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_5       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_6       : integer range 0 to 1 := 0;
    C_SYNCH_MEM_7       : integer range 0 to 1 := 0;
    C_ACCESS_CNTR_0     : std_logic_vector;
    C_ACCESS_CNTR_1     : std_logic_vector;
    C_ACCESS_CNTR_2     : std_logic_vector;
    C_ACCESS_CNTR_3     : std_logic_vector;
    C_ACCESS_CNTR_4     : std_logic_vector;
    C_ACCESS_CNTR_5     : std_logic_vector;
    C_ACCESS_CNTR_6     : std_logic_vector;
    C_ACCESS_CNTR_7     : std_logic_vector;
    C_ADDR_CNTR_WIDTH   : integer range 1 to 5;
    C_MEM0_WIDTH        : integer := 64;
    C_MEM1_WIDTH        : integer := 64;
    C_MEM2_WIDTH        : integer := 64;
    C_MEM3_WIDTH        : integer := 64;
    C_MEM4_WIDTH        : integer := 64;
    C_MEM5_WIDTH        : integer := 64;
    C_MEM6_WIDTH        : integer := 64;
    C_MEM7_WIDTH        : integer := 64;
    C_SYNCH_PIPEDELAY_0 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_1 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_2 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_3 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_4 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_5 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_6 : integer range 1 to 2 := 2;
    C_SYNCH_PIPEDELAY_7 : integer range 1 to 2 := 2;
    C_GLOBAL_DATAWIDTH_MATCH          : integer range 0 to 1 := 1;
    C_INCLUDE_DATAWIDTH_MATCHING_0    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_1    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_2    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_3    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_4    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_5    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_6    : integer := 1; 
    C_INCLUDE_DATAWIDTH_MATCHING_7    : integer := 1     
    );   
  port (              
    Bus2IP_Mem_CS       : in  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Synch_mem           : out std_logic;
    Access_cntr         : out std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);
    Mem_width_bytes     : out integer range 0 to 8 ;
    Two_pipe_delay      : out std_logic;
    Datawidth_match     : out std_logic
    );
end entity select_param;

-------------------------------------------------------------------------------
-- Architecture section
-------------------------------------------------------------------------------

architecture IMP of select_param is
-------------------------------------------------------------------------------
-- Constant Declaration
-------------------------------------------------------------------------------
type SYNCH_ARRAY_TYPE is array (0 to 7) of integer;

constant SYNCH_MEM_ARRAY : SYNCH_ARRAY_TYPE := 
       (C_SYNCH_MEM_0, 
        C_SYNCH_MEM_1, 
        C_SYNCH_MEM_2, 
        C_SYNCH_MEM_3, 
        C_SYNCH_MEM_4, 
        C_SYNCH_MEM_5, 
        C_SYNCH_MEM_6, 
        C_SYNCH_MEM_7); 

type CNTR_ARRAY_TYPE is array (0 to 7) of std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);

constant ACCESS_CNTR_ARRAY : CNTR_ARRAY_TYPE :=
       ( C_ACCESS_CNTR_0,
         C_ACCESS_CNTR_1,
         C_ACCESS_CNTR_2,
         C_ACCESS_CNTR_3,
         C_ACCESS_CNTR_4,
         C_ACCESS_CNTR_5,
         C_ACCESS_CNTR_6,
         C_ACCESS_CNTR_7);
       
type MEM_WIDTH_ARRAY_TYPE is array (0 to 7) of integer range 0 to 64;

constant MEM_WIDTH_ARRAY : MEM_WIDTH_ARRAY_TYPE :=
      ( C_MEM0_WIDTH,
        C_MEM1_WIDTH,
        C_MEM2_WIDTH,
        C_MEM3_WIDTH,
        C_MEM4_WIDTH,
        C_MEM5_WIDTH,
        C_MEM6_WIDTH,
        C_MEM7_WIDTH );
        
type PIPE_DELAY_ARRAY_TYPE is array (0 to 7) of integer range 1 to 2;

constant PIPE_DELAY_ARRAY : PIPE_DELAY_ARRAY_TYPE :=
      ( C_SYNCH_PIPEDELAY_0,
        C_SYNCH_PIPEDELAY_1,
        C_SYNCH_PIPEDELAY_2,
        C_SYNCH_PIPEDELAY_3,
        C_SYNCH_PIPEDELAY_4,
        C_SYNCH_PIPEDELAY_5,
        C_SYNCH_PIPEDELAY_6,
        C_SYNCH_PIPEDELAY_7 );

type DATAWIDTH_MATCH_ARRAY_TYPE is array (0 to 7) of integer range 0 to 1;

constant DATAWIDTH_MATCH_ARRAY : DATAWIDTH_MATCH_ARRAY_TYPE :=
      ( C_INCLUDE_DATAWIDTH_MATCHING_0,
        C_INCLUDE_DATAWIDTH_MATCHING_1,
        C_INCLUDE_DATAWIDTH_MATCHING_2,
        C_INCLUDE_DATAWIDTH_MATCHING_3,
        C_INCLUDE_DATAWIDTH_MATCHING_4,
        C_INCLUDE_DATAWIDTH_MATCHING_5,
        C_INCLUDE_DATAWIDTH_MATCHING_6,
        C_INCLUDE_DATAWIDTH_MATCHING_7 );


-------------------------------------------------------------------------------
-- Signal Declaration
-------------------------------------------------------------------------------
signal synch_mem_sig    : std_logic_vector(0 to C_NUM_BANKS_MEM -1);
signal mem_width        : integer range 0 to 64;

begin

------------------------------- Synchronous memories --------------------------
SYNC_MEM_GEN: if C_GLOBAL_SYNC_MEM = 1 generate
  synch_check: for i in 0 to (C_NUM_BANKS_MEM-1) generate
       SYNCH_PROCESS: process (Bus2IP_Mem_CS) is
          begin
           if SYNCH_MEM_ARRAY(i)  = 1 then
               synch_mem_sig(i)   <= Bus2IP_Mem_CS(i);
           else
               synch_mem_sig(i)   <= '0';
           end if;
        end process SYNCH_PROCESS;  
  end generate synch_check;

  synch_mem <= or_reduce(synch_mem_sig);
  
    SELECT_PIPEDELAY_PROCESS: process(Bus2IP_Mem_CS) is
    begin
        Two_pipe_delay <= '1';
        for i in 0 to C_NUM_BANKS_MEM-1 loop
            if Bus2IP_Mem_CS(i) = '1' then
                if PIPE_DELAY_ARRAY(i) = 1 then
                    Two_pipe_delay <= '0';
                else
                    Two_pipe_delay <= '1';
                end if;
            end if;
        end loop;
    end process SELECT_PIPEDELAY_PROCESS;
end generate SYNC_MEM_GEN;

------------------------------- No Synchronous memories -----------------------

NOSYNC_MEM_GEN: if C_GLOBAL_SYNC_MEM=0 generate
    synch_mem <= '0';
    Two_pipe_delay <= '0';
end generate NOSYNC_MEM_GEN;

------------------------------- Datawidth Matching ----------------------------
DATAWIDTH_MATCH_GEN: if C_GLOBAL_DATAWIDTH_MATCH = 1 generate
    SELECT_ACCESS_CNTR_PROCESS: process(Bus2IP_Mem_CS) is
    begin
        Access_cntr <= (others => '0');
        for i in 0 to C_NUM_BANKS_MEM-1 loop
            if Bus2IP_Mem_CS(i) = '1' then
                Access_cntr <= ACCESS_CNTR_ARRAY(i);
            end if;
        end loop;
    end process SELECT_ACCESS_CNTR_PROCESS;

    SELECT_MEM_WIDTH_PROCESS: process(Bus2IP_Mem_CS) is
    begin
        mem_width <= 0;
        for i in 0 to C_NUM_BANKS_MEM-1 loop
            if Bus2IP_Mem_CS(i) = '1' then
                mem_width <= MEM_WIDTH_ARRAY(i);
            end if;
        end loop;
    end process SELECT_MEM_WIDTH_PROCESS;

    -- This process is done in real time and is included to prevent implementation of the
    -- /8 function
    SELECT_MEM_WIDTH_BYTES_PROCESS: process(mem_width) is
    begin
        Mem_width_bytes <= 0;
        case mem_width is
            when 8  =>  Mem_width_bytes <= 1;
            when 16 =>  Mem_width_bytes <= 2;
            when 32 =>  Mem_width_bytes <= 4;
            when 64 =>  Mem_width_bytes <= 8;
            when others => Mem_width_bytes <= 0;
        end case;
    end process SELECT_MEM_WIDTH_BYTES_PROCESS;


    SELECT_DATAWIDTH_MATCH_PROCESS: process(Bus2IP_Mem_CS) is
    begin
        Datawidth_match <= '1';
        for i in 0 to C_NUM_BANKS_MEM-1 loop
            if Bus2IP_Mem_CS(i) = '1' then
                if DATAWIDTH_MATCH_ARRAY(i) = 0 then
                    Datawidth_match <= '0';
                end if;
            end if;
        end loop;
    end process SELECT_DATAWIDTH_MATCH_PROCESS;
end generate DATAWIDTH_MATCH_GEN;

------------------------------- No Datawidth Matching ----------------------------
NO_DATAWIDTH_MATCH_GEN: if C_GLOBAL_DATAWIDTH_MATCH = 0 generate
    Access_cntr <= conv_std_logic_vector(0,C_ADDR_CNTR_WIDTH);
    Mem_width_bytes <= 0;
    Datawidth_match <= '0';
end generate NO_DATAWIDTH_MATCH_GEN;

end architecture IMP;

