--SINGLE_FILE_TAG
-------------------------------------------------------------------------------
-- EMC - 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:        emc.vhd
-- Version:         v1.10b
-- Description:     External Memory Controller
--
-- VHDL-Standard:   VHDL'93
-------------------------------------------------------------------------------
-- 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             11-28-2001 
-- ^^^^^^
-- First version
-- ~~~~~~
--  DAB             01-18-2002      -- Updated for Separate Read and Write Reqs
-- 
--  DAB             01-31-2002      -- Baseline for delivery with SRAM and Flash
--                                     with basic IPIF and no back to back read
--                                     write read capability.
-- 
--  DAB            02-05-2002       -- Modify to add ZBT SRAM
--
--  DAB            03-18-2002       -- Modity to remove redundancy decode and
--                                     rename to EMC.
--  ALS            11-28-2002
-- ^^^^^^
--  Version 1.10.a 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. Also, extended OEN assertion for synchronous memories.
-- ~~~~~~
-------------------------------------------------------------------------------
-- 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 proc_common_v1_00_b;
use proc_common_v1_00_b.all;
use proc_common_v1_00_b.proc_common_pkg.all;

library emc_common_v1_10_b;
use emc_common_v1_10_b.all;

-------------------------------------------------------------------------------
-- Definition of Generics:
--
--  C_NUM_BANKS_MEM                     -- Number of memory banks
--  C_INCLUDE_BURST                     -- Include logic for burst transactions
--  C_IPIF_DWIDTH                       -- Width of processor data bus
--  C_IPIF_AWIDTH                       -- Width of processor address bus
--  C_INCLUDE_NEGEDGE_IOREGS            -- Include negative edge IO registers
--  C_MEM(0:7)_WIDTH                    -- Width of memory bank's data bus
--  C_MAX_MEM_WIDTH                     -- Maximum width of memory data bus
--  C_INCLUDE_DATAWIDTH_MATCHING_(0:7)  -- Include datawidth matching logic for
--                                      -- memory bank
--  C_BUS_CLK_PERIOD_PS                 -- Bus clock period to calculate wait
--                                         state pulse widths.
--  C_SYNCH_MEM_(0:7)0                  -- Memory bank is synchronous
--  C_RD_ADDR_TO_OUT_SLOW_PS_(0:7)      -- Slow Time that output en goes low.
--                                         Non-page reads.
--  C_WR_ADDR_TO_OUT_SLOW_PS_(0:7)      -- Slow Time that write en goes low.
--                                         Applies to all writes.
--  C_WR_MIN_PULSE_WIDTH_PS_(0:7)       -- Minimum time that write en goes low.
--                                         Applies to all writes.
--  C_RD_ADDR_TO_OUT_FAST_PS_(0:7)      -- Fast Time that output en goes low.
--                                         Non-page reads
--  C_WR_ADDR_TO_OUT_FAST_PS_(0:7)      -- Fast Time that write enable goes low.
--                                         Applies to all writes.
--  C_RD_RECOVERY_BEFORE_WRITE_PS_(0:7) -- Time of delay inserted before write en
--                                         goes low if previous access was read
--  C_WR_RECOVERY_BEFORE_READ_PS_(0:7)  -- Time of delay inserted before output en
--                                          goes low if previous access was write
--
-- Definition of Ports:
--
--  Bus2IP_Clk             -- System clock
--  Bus2IP_Reset           -- System Reset
--
--    -- Bus and IPIC Interface signals
--  Bus2IP_Addr             -- Processor bus address
--  Bus2IP_BE               -- Processor bus byte enables
--  Bus2IP_Data             -- Processor data
--  Bus2IP_RNW              -- Processor read not write
--  Bus2IP_Burst            -- Processor burst
--  Bus2IP_WrReq            -- Processor write request
--  Bus2IP_RdReq            -- Processor read request
--  Bus2IP_Mem_CS           -- Memory address range is being accessed
--  Bus2IP_Reg_CS           -- Register is being accessed
--  Bus2IP_WrCE             -- Write chip enable
--  Bus2IP_RdCE             -- Read chip enable
--  
--  -- EMC to bus signals 
--  IP2Bus_Data             -- Data to processor bus
--  IP2Bus_errAck           -- Error acknowledge
--  IP2Bus_retry            -- Retry indicator
--  IP2Bus_toutSup          -- Suppress watch dog timer
--  IP2Bus_RdAck            -- Read acknowledge
--  IP2Bus_WrAck            -- Write acknowledge
--
--    -- Memory signals
--  Mem_A                   -- Memory address inputs
--  Mem_DQ_I                -- Memory input data bus
--  Mem_DQ_O                -- Memory output data bus
--  Mem_DQ_T                -- Memory data output enable
--  Mem_CEN                 -- Memory chip select
--  Mem_OEN                 -- Memory output enable
--  Mem_WEN                 -- Memory write enable
--  Mem_QWEN                -- Memory qualified write enable
--  Mem_BEN                 -- Memory byte enables
--  Mem_RPN                 -- Memory reset/power down
--  Mem_CE                  -- Memory chip enable
--  Mem_ADV_LDN             -- Memory counter advance/load (=0)
--  Mem_LBON                -- Memory linear/interleaved burst order (=0)
--  Mem_CKEN                -- Memory clock enable (=0)
--  Mem_RNW                 -- Memory read not write
-------------------------------------------------------------------------------
-- Port declarations
-------------------------------------------------------------------------------

entity EMC is
  generic (
    C_NUM_BANKS_MEM                 : integer range 1 to 8 := 2;
    C_INCLUDE_BURST                 : integer range 0 to 1 := 0;
    C_IPIF_DWIDTH                   : integer := 64;
    C_IPIF_AWIDTH                   : integer := 32;
    C_INCLUDE_NEGEDGE_IOREGS        : integer := 0;
    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_MAX_MEM_WIDTH                 : integer := 64;

    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; 

    -- Memory read and write access times for all memory banks
    C_BUS_CLOCK_PERIOD_PS             : integer := 40000;

    C_SYNCH_MEM_0                     : integer := 0;
    C_SYNCH_PIPEDELAY_0               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_0      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_0     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_0      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_0      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_0     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_0 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_0 : integer := 0;

    C_SYNCH_MEM_1                     : integer := 0;
    C_SYNCH_PIPEDELAY_1               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_1      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_1     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_1      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_1      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_1     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_1 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_1 : integer := 0;

    C_SYNCH_MEM_2                     : integer := 0;
    C_SYNCH_PIPEDELAY_2               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_2      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_2     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_2      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_2      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_2     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_2 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_2 : integer := 0;

    C_SYNCH_MEM_3                     : integer := 0;
    C_SYNCH_PIPEDELAY_3               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_3      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_3     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_3      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_3      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_3     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_3 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_3 : integer := 0;

    C_SYNCH_MEM_4                     : integer := 0;
    C_SYNCH_PIPEDELAY_4               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_4      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_4     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_4      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_4      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_4     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_4 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_4 : integer := 0;

    C_SYNCH_MEM_5                     : integer := 0;
    C_SYNCH_PIPEDELAY_5               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_5      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_5     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_5      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_5      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_5     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_5 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_5 : integer := 0;

    C_SYNCH_MEM_6                     : integer := 0;
    C_SYNCH_PIPEDELAY_6               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_6      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_6     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_6      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_6      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_6     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_6 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_6 : integer := 0;

    C_SYNCH_MEM_7                     : integer := 0;
    C_SYNCH_PIPEDELAY_7               : integer := 2;
    C_READ_ADDR_TO_OUT_SLOW_PS_7      : integer := 0;
    C_WRITE_ADDR_TO_OUT_SLOW_PS_7     : integer := 0;
    C_WRITE_MIN_PULSE_WIDTH_PS_7      : integer := 0;
    C_READ_ADDR_TO_OUT_FAST_PS_7      : integer := 0;
    C_WRITE_ADDR_TO_OUT_FAST_PS_7     : integer := 0;
    C_READ_RECOVERY_BEFORE_WRITE_PS_7 : integer := 0;
    C_WRITE_RECOVERY_BEFORE_READ_PS_7 : integer := 0
    );
  port (
    Bus2IP_Clk             : in  std_logic;
    Bus2IP_Reset           : in  std_logic;

    -- Bus and IPIC Interface signals
    Bus2IP_Addr            : in  std_logic_vector(0 to C_IPIF_AWIDTH-1);
    Bus2IP_BE              : in  std_logic_vector(0 to C_IPIF_DWIDTH/8-1);
    Bus2IP_Data            : in  std_logic_vector(0 to C_IPIF_DWIDTH-1);
    Bus2IP_RNW             : in  std_logic;
    Bus2IP_Burst           : in  std_logic;
    Bus2IP_WrReq           : in  std_logic;
    Bus2IP_RdReq           : in  std_logic;
    Bus2IP_Mem_CS          : in  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Bus2IP_Reg_CS          : in  std_logic;
    Bus2IP_WrCE            : in  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Bus2IP_RdCE            : in  std_logic_vector(0 to C_NUM_BANKS_MEM-1);

    IP2Bus_Data            : out std_logic_vector(0 to C_IPIF_DWIDTH-1);
    IP2Bus_errAck          : out std_logic;
    IP2Bus_retry           : out std_logic;
    IP2Bus_toutSup         : out std_logic;
    IP2Bus_RdAck           : out std_logic;
    IP2Bus_WrAck           : out std_logic;


    -- Memory signals
    Mem_A                  : out   std_logic_vector(0 to C_IPIF_AWIDTH-1);
    Mem_DQ_I               : in    std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
    Mem_DQ_O               : out   std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
    Mem_DQ_T               : out   std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
    Mem_CEN                : out   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Mem_OEN                : out   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Mem_WEN                : out   std_logic;
    Mem_QWEN               : out   std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1); --Qualified WE
    Mem_BEN                : out   std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
    Mem_RPN                : out   std_logic;
    Mem_CE                 : out   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Mem_ADV_LDN            : out   std_logic;
    Mem_LBON               : out   std_logic;
    Mem_CKEN               : out   std_logic;
    Mem_RNW                : out   std_logic
    );
end entity EMC;

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

architecture IMP of EMC is

-------------------------------------------------------------------------------
-- Data Types
-------------------------------------------------------------------------------

type EMC_ARRAY_TYPE is
  array (0 to 7) of integer;

type INTEGER_ARRAY is array (natural range <>) of integer;

-------------------------------------------------------------------------------
-- Functions
-------------------------------------------------------------------------------
function max(indata : INTEGER_ARRAY ) return integer is
  variable max_val : integer;
begin
  max_val := 0;
  for i in 0 to indata'length-1 loop
    if indata(i) > max_val then
        max_val := indata(i);
    end if;
 end loop;
  
 return max_val; 
end max;
-------------------
function "and"  ( l : std_logic_vector; r : std_logic )
return std_logic_vector is
    variable rex : std_logic_vector(l'range);
begin
    rex := (others=>r);
    return( l and rex );
end function "and";
-------------------
function get_effective_access_cnt(include_data_matching     : integer range 0 to 1;
                                 mem_width                  : integer range 1 to 64;
                                 bus_width                  : integer range 1 to 64)
                                 return integer is
    variable effective_access_cnt : integer range 0 to 8;
begin
    if include_data_matching = 1 then
        effective_access_cnt := bus_width/mem_width;
    else
        effective_access_cnt := 1;
    end if;
    return effective_access_cnt;
end function get_effective_access_cnt;
-------------------
function not_all_zeros(input_array          : EMC_ARRAY_TYPE;
                       num_real_elements    : integer) 
                       return integer is
    variable sum        : integer range 0 to 8 := 0;
begin
    for i in 0 to num_real_elements -1 loop
        sum := sum + input_array(i);
    end loop;
    
    if sum = 0 then
        return 0;
    else
        return 1;
    end if;
end function not_all_zeros;
-------------------
function get_effective_recovery_ws(sync_mem         : integer range 0 to 1;
                                   recovery_time    : integer;
                                   bus_clock_period : integer )
                                 return integer is
    variable effective_recovery_ws : integer range 0 to 31;
begin
    if sync_mem = 1 or recovery_time = 0 then
        effective_recovery_ws := 0;
    else
        effective_recovery_ws := ((recovery_time-1)/bus_clock_period)+1;
    end if;
    return effective_recovery_ws;
end function get_effective_recovery_ws;

-------------------------------------------------------------------------------
-- Constant Declarations
-------------------------------------------------------------------------------
constant MCCR_DWIDTH             : integer := 32;
constant C_INCLUDE_READ_MUX      : boolean := true;

-- minimum memory data width supported is 8 bits
constant MIN_MEM_WIDTH           : integer := 8;

-- address offset
constant ADDR_OFFSET        : integer range 0 to 4  := log2(C_IPIF_DWIDTH/8);
constant ADDR_CNTR_WIDTH    : integer range 1 to 5  := max2(1,log2(C_IPIF_DWIDTH/8));

-- create arrays of generics for use in functions
constant SYNCH_MEM_ARRAY : EMC_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); 

constant DATAWIDTH_MATCH_ARRAY : EMC_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); 

-- create global constants that indicate if any data matching is needed or if any memories
-- are synchronous
-- These can be used to eliminate un-necessary logic
constant GLOBAL_SYNC_MEM : integer range 0 to 1 := 
                    not_all_zeros(SYNCH_MEM_ARRAY,C_NUM_BANKS_MEM);
constant GLOBAL_DATAWIDTH_MATCH : integer range 0 to 1 := 
                    not_all_zeros(DATAWIDTH_MATCH_ARRAY,C_NUM_BANKS_MEM);

-- Data Width Matching Constants
-- If memory bank is not parameterized to include data width matching, the access count is 1
constant ACCESS_CNT_0   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_0,C_MEM0_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_1   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_1,C_MEM1_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_2   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_2,C_MEM2_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_3   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_3,C_MEM3_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_4   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_4,C_MEM4_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_5   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_5,C_MEM5_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_6   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_6,C_MEM6_WIDTH,C_IPIF_DWIDTH);
constant ACCESS_CNT_7   : integer range 0 to 31 := 
            get_effective_access_cnt(C_INCLUDE_DATAWIDTH_MATCHING_7,C_MEM7_WIDTH,C_IPIF_DWIDTH);

constant ACCESS_CNTR_0  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_0-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_1  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_1-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_2  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_2-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_3  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_3-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_4  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_4-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_5  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_5-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_6  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_6-1,ADDR_CNTR_WIDTH);
constant ACCESS_CNTR_7  : std_logic_vector(0 to ADDR_CNTR_WIDTH-1) :=
                    conv_std_logic_vector(ACCESS_CNT_7-1,ADDR_CNTR_WIDTH);

                    
-- Bank0 Wait State Calculations
constant RD_RECOVERY_0  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_0,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_0,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_0  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_0,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_0,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_0             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_0-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_0     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_0-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_0             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_0,C_WRITE_MIN_PULSE_WIDTH_PS_0)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_0             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_0,C_WRITE_MIN_PULSE_WIDTH_PS_0)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

-- Bank1 Wait State Calculations
constant RD_RECOVERY_1  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_1,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_1,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_1  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_1,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_1,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_1             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_1-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_1     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_1-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_1             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_1,C_WRITE_MIN_PULSE_WIDTH_PS_1)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_1             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_1,C_WRITE_MIN_PULSE_WIDTH_PS_1)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;


-- Bank2 Wait State Calculations
constant RD_RECOVERY_2  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_2,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_2,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_2  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_2,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_2,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_2             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_2-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_2     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_2-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_2             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_2,C_WRITE_MIN_PULSE_WIDTH_PS_2)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_2             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_2,C_WRITE_MIN_PULSE_WIDTH_PS_2)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

-- Bank3 Wait State Calculations
constant RD_RECOVERY_3  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_3,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_3,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_3  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_0,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_3,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_3             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_3-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_3     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_3-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_3             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_3,C_WRITE_MIN_PULSE_WIDTH_PS_3)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_3             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_3,C_WRITE_MIN_PULSE_WIDTH_PS_3)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;


-- Bank4 Wait State Calculations
constant RD_RECOVERY_4  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_4,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_4,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_4  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_4,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_4,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_4             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_4-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_4     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_4-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_4             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_4,C_WRITE_MIN_PULSE_WIDTH_PS_4)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_4             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_4,C_WRITE_MIN_PULSE_WIDTH_PS_4)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;


-- Bank5 Wait State Calculations
constant RD_RECOVERY_5  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_5,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_5,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_5  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_5,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_5,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_5             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_5-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_5     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_5-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_5             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_5,C_WRITE_MIN_PULSE_WIDTH_PS_5)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_5             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_5,C_WRITE_MIN_PULSE_WIDTH_PS_5)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

-- Bank6 Wait State Calculations
constant RD_RECOVERY_6  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_6,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_6,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_6  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_6,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_6,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_6             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_6-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_6     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_6-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_6             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_6,C_WRITE_MIN_PULSE_WIDTH_PS_6)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_6             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_6,C_WRITE_MIN_PULSE_WIDTH_PS_6)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

-- Bank7 Wait State Calculations
constant RD_RECOVERY_7  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_7,
                                          C_READ_RECOVERY_BEFORE_WRITE_PS_7,
                                          C_BUS_CLOCK_PERIOD_PS); 
                                          
constant WR_RECOVERY_7  : integer range 0 to 31 := 
                get_effective_recovery_ws(C_SYNCH_MEM_7,
                                          C_WRITE_RECOVERY_BEFORE_READ_PS_7,
                                          C_BUS_CLOCK_PERIOD_PS);
                                          
constant RD_SLOW_7             : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_SLOW_PS_7-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant RD_FAST_7     : integer range 1 to 31 :=
  (C_READ_ADDR_TO_OUT_FAST_PS_7-1)/C_BUS_CLOCK_PERIOD_PS+2;

constant WR_SLOW_7             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_SLOW_PS_7,C_WRITE_MIN_PULSE_WIDTH_PS_7)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;

constant WR_FAST_7             : integer range 1 to 31 :=
  (max2(C_WRITE_ADDR_TO_OUT_FAST_PS_7,C_WRITE_MIN_PULSE_WIDTH_PS_7)-1)/
      C_BUS_CLOCK_PERIOD_PS+2;


-------------------------------------------------------------------------------
-- Component Declarations
-------------------------------------------------------------------------------
component Mem_State_Machine is
  generic(C_ADDR_CNTR_WIDTH : integer range 1 to 5;
          C_INCLUDE_BURST   : integer range 0 to 1);
  port (
    Clk                 : in  std_logic;
    Rst                 : in  std_logic;
    Valid_Memory_Access : in  std_logic;
    Valid_Read          : in  std_logic;
    Valid_Write         : in  std_logic;
    Valid_Reg_Write     : in  std_logic;
    Valid_Reg_Read      : in  std_logic;
    Bus2IP_Reg_CS       : in  std_logic;
    Prev_Access_Read    : in  std_logic;
    Synch_Mem           : in  std_logic;
    Two_pipe_delay      : in  std_logic;
    Mem_Wait_States     : in  std_logic_vector(0 to 4);
    Rec_Wait_States     : in  std_logic_vector(0 to 4);
    Bus2IP_RNW          : in  std_logic;
    Bus2IP_Burst        : in  std_logic;
    Mem_RdAck           : in  std_logic;
    Addr_cnt            : in  std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);
    Access_cnt          : in  std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);
    Addr_cnt_ce         : out std_logic;
    Addr_cnt_rst        : out std_logic;
    Reg_RdAck           : out std_logic;
    Reg_WrAck           : out std_logic;
    Mem_Wrcycle_Done    : out std_logic;
    Mem_WrAck           : out std_logic;
    Mem_Rdcycle_Done    : out std_logic;
    Burst_RdAck         : out std_logic;
    Burst_WrAck         : out std_logic;
    Mem_OEN             : out std_logic;
    Mem_WEN             : out std_logic;
    Sync_mem_cs         : out std_logic
    );
end component Mem_State_Machine;


component data_path is
  generic ( C_MAX_MEM_WIDTH             : integer;
            C_MIN_MEM_WIDTH             : integer;
            C_IPIF_DWIDTH               : integer;
            C_ADDR_CNTR_WIDTH           : integer range 1 to 5;
            C_GLOBAL_DATAWIDTH_MATCH    : integer range 0 to 1;
            C_GLOBAL_SYNC_MEM           : integer range 0 to 1);
  port (
    -- inputs
    Valid_Memory_Access : in  std_logic;
    Mem_DQ_I            : in  std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
    Bus2IP_Data         : in  std_logic_vector(0 to C_IPIF_DWIDTH-1);
    Bus2IP_BE           : in  std_logic_vector(0 to C_IPIF_DWIDTH/8-1);
    
    Addr_cnt            : in  std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);
    
    Mem_Wrcycle_Done    : in  std_logic;
    Mem_Rdcycle_Done    : in  std_logic;
    Mem_OEN             : in  std_logic;
    
    Mem_width_bytes     : in  integer range 0 to 8;
    Datawidth_match     : in  std_logic;
       
    Synch_mem           : in  std_logic;
    Two_pipe_delay      : in  std_logic;
    
    -- outputs
    Mem_RdAck           : out std_logic;
    Mem_ReadData        : out std_logic_vector(0 to C_IPIF_DWIDTH-1);
    Mem_WriteData       : out std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
    Mem_BE              : out std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
    
    -- Clocks and reset
    Clk                 : in  std_logic;
    Rst                 : in  std_logic;
    Input_datareg_rst   : in  std_logic
    );
end component data_path;

component Wait_States is
  generic (
    C_NUM_BANKS_MEM  : integer range 1 to 8 := 8;
    C_RD_SLOW_0      : integer := 14;
    C_RD_FAST_0      : integer := 4;
    C_WR_SLOW_0      : integer := 13;
    C_WR_FAST_0      : integer := 2;
    C_RD_RECOVERY_0  : integer := 21;
    C_WR_RECOVERY_0  : integer := 17;
    C_RD_SLOW_1      : integer := 14;
    C_RD_FAST_1      : integer := 4;
    C_WR_SLOW_1      : integer := 13;
    C_WR_FAST_1      : integer := 2;
    C_RD_RECOVERY_1  : integer := 21;
    C_WR_RECOVERY_1  : integer := 17;
    C_RD_SLOW_2      : integer := 4;
    C_RD_FAST_2      : integer := 26;
    C_WR_SLOW_2      : integer := 6;
    C_WR_FAST_2      : integer := 23;
    C_RD_RECOVERY_2  : integer := 12;
    C_WR_RECOVERY_2  : integer := 7;
    C_RD_SLOW_3      : integer := 30;
    C_RD_FAST_3      : integer := 27;
    C_WR_SLOW_3      : integer := 2;
    C_WR_FAST_3      : integer := 1;
    C_RD_RECOVERY_3  : integer := 28;
    C_WR_RECOVERY_3  : integer := 15;
    C_RD_SLOW_4      : integer := 12;
    C_RD_FAST_4      : integer := 19;
    C_WR_SLOW_4      : integer := 3;
    C_WR_FAST_4      : integer := 7;
    C_RD_RECOVERY_4  : integer := 23;
    C_WR_RECOVERY_4  : integer := 6;
    C_RD_SLOW_5      : integer := 17;
    C_RD_FAST_5      : integer := 22;
    C_WR_SLOW_5      : integer := 23;
    C_WR_FAST_5      : integer := 24;
    C_RD_RECOVERY_5  : integer := 8;
    C_WR_RECOVERY_5  : integer := 5;
    C_RD_SLOW_6      : integer := 29;
    C_RD_FAST_6      : integer := 5;
    C_WR_SLOW_6      : integer := 13;
    C_WR_FAST_6      : integer := 17;
    C_RD_RECOVERY_6  : integer := 28;
    C_WR_RECOVERY_6  : integer := 4;
    C_RD_SLOW_7      : integer := 24;
    C_RD_FAST_7      : integer := 16;
    C_WR_SLOW_7      : integer := 7;
    C_WR_FAST_7      : integer := 26;
    C_RD_RECOVERY_7  : integer := 12;
    C_WR_RECOVERY_7  : integer := 2
    );
  port (
    Bus2IP_Mem_CS       : in  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    Fast_Slow_Select    : in  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
    RNW                 : in  std_logic;
    Mem_Wait_States     : out std_logic_vector(0 to 4);
    Recover_Wait_States : out std_logic_vector(0 to 4)  -- Recovery time WS
    );
end component Wait_States;

component 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 component select_param;

component addr_counter_mux is
  generic ( C_ADDR_CNTR_WIDTH           : integer range 1 to 5;
            C_IPIF_AWIDTH               : integer;
            C_ADDR_OFFSET               : integer range 0 to 4;
            C_GLOBAL_DATAWIDTH_MATCH    : integer range 0 to 1
            );
  port (
        Addr_cnt_ce             : in  std_logic;
        Addr_cnt_rst            : in  std_logic;
        Addr_cnt                : out std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);
        
        Mem_width_bytes         : in  integer range 0 to 8;
        Datawidth_match         : in  std_logic;
        valid_Memory_Access : in  std_logic;
        Bus2IP_Addr             : in  std_logic_vector(0 to C_IPIF_AWIDTH-1);
        Mem_addr                : out std_logic_vector(0 to C_IPIF_AWIDTH-1);

        -- Clocks and reset
        Clk                     : in  std_logic;
        Rst                     : in  std_logic
    );
end component addr_counter_mux;


component io_registers is
  generic ( C_GLOBAL_DATAWIDTH_MATCH   : integer range 0 to 1;
            C_INCLUDE_NEGEDGE_IOREGS   : integer range 0 to 1;
            C_IPIF_AWIDTH              : integer;
            C_MAX_MEM_WIDTH            : integer;
            C_NUM_BANKS_MEM            : integer
            );
  port (

        -- internal Memory signals
        Mem_A_int              : in   std_logic_vector(0 to C_IPIF_AWIDTH-1);
        Mem_DQ_I_int           : out  std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
        Mem_DQ_O_int           : in   std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
        Mem_DQ_T_int           : in   std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
        Mem_CEN_int            : in   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
        Mem_OEN_int            : in   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
        Mem_WEN_int            : in   std_logic;
        Mem_QWEN_int           : in   std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1); --Qualified WE
        Mem_BEN_int            : in   std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
        Mem_RPN_int            : in   std_logic;
        Mem_CE_int             : in   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
        Mem_ADV_LDN_int        : in   std_logic;
        Mem_LBON_int           : in   std_logic;
        Mem_CKEN_int           : in   std_logic;
        Mem_RNW_int            : in   std_logic;

        -- Memory signals
        Mem_A                  : out   std_logic_vector(0 to C_IPIF_AWIDTH-1);
        Mem_DQ_I               : in    std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
        Mem_DQ_O               : out   std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
        Mem_DQ_T               : out   std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
        Mem_CEN                : out   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
        Mem_OEN                : out   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
        Mem_WEN                : out   std_logic;
        Mem_QWEN               : out   std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1); --Qualified WE
        Mem_BEN                : out   std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
        Mem_RPN                : out   std_logic;
        Mem_CE                 : out   std_logic_vector(0 to C_NUM_BANKS_MEM-1);
        Mem_ADV_LDN            : out   std_logic;
        Mem_LBON               : out   std_logic;
        Mem_CKEN               : out   std_logic;
        Mem_RNW                : out   std_logic;

        -- Clocks and reset
        Clk                     : in  std_logic;
        Rst                     : in  std_logic;
        Input_datareg_rst       : in  std_logic
    );
end component io_registers;

component FDR is
  port (
    Q : out std_logic;
    C : in  std_logic;
    D : in  std_logic;
    R : in  std_logic
  );
end component FDR;

component FDRE is
  port (
    Q  : out std_logic;
    C  : in  std_logic;
    D  : in  std_logic;
    R  : in  std_logic;
    CE : in std_logic
  );
end component FDRE;



-------------------------------------------------------------------------------
-- Signal Declarations
-------------------------------------------------------------------------------
signal input_datareg_rst    : std_logic;
signal page_Hit             : std_logic;
signal prev_Access_Read     : std_logic;
signal prev_Addr            : std_logic_vector(0 to C_IPIF_AWIDTH-4);
signal page_Mode_Enable     : std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal fast_Mode_Enable     : std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal fast_Slow_Select     : std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal reg_Select           : std_logic;
signal sm_WEN               : std_logic;
signal sm_OEN               : std_logic;
signal sync_mem_cs          : std_logic;
signal valid_Memory_Access  : std_logic;
signal valid_Memory_Read    : std_logic;
signal valid_Memory_Write   : std_logic;
signal valid_Memory_T       : std_logic;
signal valid_Reg_Write      : std_logic;
signal valid_Reg_Read       : std_logic;
signal valid_Read_Mux_En    : std_logic;
signal valid_Reg_Read_Bus   : std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal ReadReg2_ReadMux     : std_logic_vector(0 to C_IPIF_DWIDTH-1);
signal valid_Reg_Write_Bus  : std_logic_vector(0 to C_NUM_BANKS_MEM-1);

signal synch_Mem            : std_logic;
signal mem_Wait_States      : std_logic_vector(0 to 4);
signal recover_Wait_States  : std_logic_vector(0 to 4);

signal IP2Bus_RdAck_Out     : std_logic;
signal IP2Bus_WrAck_Out     : std_logic;

signal Bus2IP_RNW_d1        : std_logic;

signal addr_cnt             : std_logic_vector(0 to ADDR_CNTR_WIDTH-1);
signal addr_cnt_ce          : std_logic;
signal addr_cnt_rst         : std_logic;

signal access_cnt           : std_logic_vector(0 to ADDR_CNTR_WIDTH-1);
signal two_pipe_delay       : std_logic;
signal datawidth_match      : std_logic;

signal reg_rdack            : std_logic;
signal reg_wrack            : std_logic;

signal burst_rdack          : std_logic;
signal burst_wrack          : std_logic;

signal mem_wrcycle_done     : std_logic;
signal mem_rdcycle_done     : std_logic;
signal mem_width_bytes      : integer range 0 to 8;
signal mem_wrack            : std_logic;
signal mem_rdack            : std_logic;

signal mem_addr             : std_logic_vector(0 to C_IPIF_AWIDTH-1);
signal mem_writedata        : std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
signal mem_readdata         : std_logic_vector(0 to C_IPIF_DWIDTH-1);

signal mem_a_int        :  std_logic_vector(0 to C_IPIF_AWIDTH-1);
signal mem_dq_i_int     :  std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
signal mem_dq_o_int     :  std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
signal mem_dq_t_int     :  std_logic_vector(0 to C_MAX_MEM_WIDTH-1);
signal mem_cen_int      :  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal mem_oen_int      :  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal mem_wen_int      :  std_logic;
signal mem_qwen_int     :  std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
signal mem_be_int       :  std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
signal mem_ben_int      :  std_logic_vector(0 to C_MAX_MEM_WIDTH/8-1);
signal mem_rpn_int      :  std_logic;
signal mem_ce_int       :  std_logic_vector(0 to C_NUM_BANKS_MEM-1);
signal mem_adv_ldn_int  :  std_logic;
signal mem_lbon_int     :  std_logic;
signal mem_cken_int     :  std_logic;
signal mem_rnw_int      :  std_logic;

-----------------------------------------------------------------------------
-- Begin architecture
-------------------------------------------------------------------------------

begin -- architecture IMP

-------------------------------------------------------------------------------
-- IPIC 
-------------------------------------------------------------------------------
  IP2Bus_errAck         <= '0';
  IP2Bus_retry          <= '0';
  IP2Bus_toutsup        <= or_reduce(Bus2IP_Mem_CS);

  BURST_ACK_GEN: if C_INCLUDE_BURST = 1 generate
    IP2Bus_RdAck  <= reg_rdack or mem_rdack or burst_rdack;
    IP2Bus_WrAck  <= reg_wrack or mem_wrack or burst_wrack;
  end generate BURST_ACK_GEN;
  
  NOBURST_ACK_GEN: if C_INCLUDE_BURST = 0 generate
    IP2Bus_RdAck  <= reg_rdack or mem_rdack;
    IP2Bus_WrAck  <= reg_wrack or mem_wrack;
  end generate NOBURST_ACK_GEN;


  -----------------------------------------------------------------------------
  -- Interface to memory
  -----------------------------------------------------------------------------
  -- internal outputs
  mem_a_int    <= mem_addr;
  mem_ben_int  <= not mem_be_int;
  mem_rnw_int  <= Bus2IP_RNW; 
  mem_wen_int  <= sm_WEN;
  mem_qwen_int <= not(mem_be_int and not(sm_WEN));
  mem_oen_int  <= not (Bus2IP_Mem_CS and not (sm_OEN));

  mem_rpn_int  <= not Bus2IP_Reset;
  mem_cen_int  <= not (Bus2IP_Mem_CS);
  
  -- assign the active-high CE based on if the memory bank is synchronous or not
  MEM_CE_PROCESS: process(Bus2IP_Mem_CS, sync_mem_cs)
  begin
    for i in 0 to C_NUM_BANKS_MEM-1 loop
        if SYNCH_MEM_ARRAY(i) = 1 then
            mem_ce_int(i) <= sync_mem_cs;
        else
            mem_ce_int(i) <= Bus2IP_Mem_CS(i);
        end if;
    end loop;
  end process MEM_CE_PROCESS;
  
  mem_dq_o_int <= mem_writedata;

  -- replicate the output enable for all bits in the output bus to allow use of
  -- IO registers
  MEM_DQT_PROCESS: process(valid_Memory_T)
  begin
    for i in 0 to C_MAX_MEM_WIDTH-1 loop
            --mem_dq_t_int(i) <= not valid_Memory_T;
            mem_dq_t_int(i) <= valid_Memory_T;
    end loop;
  end process MEM_DQT_PROCESS;

  -- Tie the synchronous memory burst signals to inactive state as the burst
  -- of the ZBT is not utilized (note that registers for these signals will
  -- be optimized away)
  mem_adv_ldn_int  <= '0';                        
  mem_lbon_int     <= '0'; 
  
  -- Tie the clock enable signal of the synchronous memories to active state
  -- to keep the devices clock enabled (note that register for this signal will
  -- be optimized away)
  mem_cken_int     <= '0'; -- keep clock enabled to ZBT devices


  -----------------------------------------------------------------------------
  -- Instantiate the IO register block to memory
  -- IO registers will be instantiated based on the parameter settings
  -----------------------------------------------------------------------------
  IO_REGISTERS_I: io_registers
  generic map ( C_GLOBAL_DATAWIDTH_MATCH   => GLOBAL_DATAWIDTH_MATCH   ,                  
                C_INCLUDE_NEGEDGE_IOREGS   => C_INCLUDE_NEGEDGE_IOREGS ,                
                C_IPIF_AWIDTH              => C_IPIF_AWIDTH            ,                
                C_MAX_MEM_WIDTH            => C_MAX_MEM_WIDTH          ,                    
                C_NUM_BANKS_MEM            => C_NUM_BANKS_MEM                               
              )
  port map (
        -- internal memory signals
        Mem_A_int              =>  mem_a_int      ,
        Mem_DQ_I_int           =>  mem_dq_i_int   ,
        Mem_DQ_O_int           =>  mem_dq_o_int   ,
        Mem_DQ_T_int           =>  mem_dq_t_int   ,
        Mem_CEN_int            =>  mem_cen_int    ,
        Mem_OEN_int            =>  mem_oen_int    ,
        Mem_WEN_int            =>  mem_wen_int    ,
        Mem_QWEN_int           =>  mem_qwen_int   ,
        Mem_BEN_int            =>  mem_ben_int    ,
        Mem_RPN_int            =>  mem_rpn_int    ,
        Mem_CE_int             =>  mem_ce_int     ,
        Mem_ADV_LDN_int        =>  mem_adv_ldn_int,
        Mem_LBON_int           =>  mem_lbon_int   ,
        Mem_CKEN_int           =>  mem_cken_int   ,
        Mem_RNW_int            =>  mem_rnw_int    ,

        -- external memory signals
        Mem_A                  =>  Mem_A          ,
        Mem_DQ_I               =>  Mem_DQ_I       ,
        Mem_DQ_O               =>  Mem_DQ_O       ,
        Mem_DQ_T               =>  Mem_DQ_T       ,
        Mem_CEN                =>  Mem_CEN        ,
        Mem_OEN                =>  Mem_OEN        ,
        Mem_WEN                =>  Mem_WEN        ,
        Mem_QWEN               =>  Mem_QWEN       ,
        Mem_BEN                =>  Mem_BEN        ,
        Mem_RPN                =>  Mem_RPN        ,
        Mem_CE                 =>  Mem_CE         ,
        Mem_ADV_LDN            =>  Mem_ADV_LDN    ,
        Mem_LBON               =>  Mem_LBON       ,
        Mem_CKEN               =>  Mem_CKEN       ,
        Mem_RNW                =>  Mem_RNW        ,

        -- Clocks and reset
        Clk                    =>  Bus2IP_Clk,  
        Rst                    =>  Bus2IP_Reset,
        Input_datareg_rst      =>  input_datareg_rst
    );
    

  -----------------------------------------------------------------------------
  -- Address decode Bank Selects and Register Select
  -----------------------------------------------------------------------------
   -----------------------------------------------------------------------------
   -- Valid Access Address decode
   -----------------------------------------------------------------------------
   valid_Memory_Access <= or_reduce(Bus2IP_Mem_CS);
   valid_Memory_Read   <= valid_Memory_Access and Bus2IP_RdReq;
   valid_Memory_Write  <= valid_Memory_Access and Bus2IP_WrReq;
   valid_Reg_Write     <= Bus2IP_Reg_CS and Bus2IP_WrReq;
   valid_Reg_Read      <= Bus2IP_Reg_CS and Bus2IP_RdReq;
   valid_Read_Mux_En   <= Bus2IP_Reg_CS and Bus2IP_RNW;

   valid_Memory_T      <= '0' when valid_Memory_Access='1' and Bus2IP_RNW='0'
                            else '1';

   INPUT_DATAREG_RST_REG: process (Bus2IP_Clk)
   begin
    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
        if Bus2IP_Reset = '1' then
            input_datareg_rst <= '1';
        elsif (valid_Memory_Access='1' and Bus2IP_RNW='1') then
            input_datareg_rst <= '0';
        else
            input_datareg_rst <= '1';
        end if;
    end if;
   end process INPUT_DATAREG_RST_REG; 
   -----------------------------------------------------------------------------
   -- Valid MCCR DECODE from the IPIF
   -----------------------------------------------------------------------------
   valid_Reg_Write_Bus <= Bus2IP_WrCE;
   valid_Reg_Read_Bus  <= Bus2IP_RdCE;

  -----------------------------------------------------------------------------
  -- Read Register Mux for Page and Fast Modes
  -----------------------------------------------------------------------------

READ_MUX_GEN: if C_INCLUDE_READ_MUX = true generate
   component mux_onehot
       generic( C_DW: integer := 32;
                C_NB: integer := 5 );
       port(
          D: in std_logic_vector(0 to C_DW*C_NB-1);
          S: in std_logic_vector(0 to C_NB-1);
          Y: out std_logic_vector(0 to C_DW-1));

   end component;

   signal fast_page_bus          : std_logic_vector(0 to (C_NUM_BANKS_MEM*2) -1);
   signal fast_page_mode_mux_out : std_logic_vector(0 to 1);

   begin
       FAST_PAGE_MODE_MUX: mux_onehot
           generic map(C_DW => 2,
                       C_NB => C_NUM_BANKS_MEM
                       )
           port map (
                       D => fast_page_bus,
                       S => Valid_Reg_Read_Bus,
                       Y => fast_page_mode_mux_out
                    );
       BUILD_FAST_PAGE_BUS_PROCESS: process(fast_Mode_Enable,page_Mode_Enable)
           begin
               for i in 0 to C_NUM_BANKS_MEM-1 loop
                   fast_page_bus(i*2)   <= fast_Mode_Enable(i);
                   fast_page_bus(i*2+1) <= page_Mode_Enable(i);
               end loop;
       end process BUILD_FAST_PAGE_BUS_PROCESS;

       READ_MUX_PROCESS: process(mem_readdata,
                                 fast_page_mode_mux_out, valid_Read_Mux_En
                                  )
           begin
               IP2Bus_Data <= (others => '0');

               if valid_Read_Mux_En = '1' then
                   IP2Bus_Data(MCCR_DWIDTH -1) <= fast_page_mode_mux_out(0);
                   IP2Bus_Data(MCCR_DWIDTH -2) <= fast_page_mode_mux_out(1);
               else
                   IP2Bus_Data <= mem_readdata;                   
               end if;
        end process READ_MUX_PROCESS;
end generate READ_MUX_GEN;

NO_READ_MUX_GEN: if C_INCLUDE_READ_MUX = false generate
      IP2Bus_Data <= mem_readdata;
end generate NO_READ_MUX_GEN;


  -----------------------------------------------------------------------------
  -- Memory Controller Control Register
  -- LSB:    fast_Mode_Enable  0 = slow access time, 1 = fast access time
  -- LSB-1:  page_Mode_Enable  0 = page mode disabled, 1 = page mode enabled
  -- Function:
  --   page_Mode_Enable    fast_Mode_Enable     Function
  --   ----------------------------------------------------------------------
  --          0                  0             Always slow access
  --          0                  1             Always fast access
  --          1                  X             Fast in page, slow not in page
  -----------------------------------------------------------------------------

  MCCR_GEN: for i in 0 to C_NUM_BANKS_MEM-1 generate
    MCCR_FAST_MODE_I: FDRE  -- LSB of MCCR [bit 31 in a 32-b system]
      port map (
        Q  => fast_Mode_Enable(i),              -- [out]
        C  => Bus2IP_Clk,                       -- [in]
        D  => Bus2IP_Data(MCCR_DWIDTH-1),   -- [in]
        R  => Bus2IP_Reset,                     -- [in]
        CE => valid_Reg_Write_Bus(i)            -- [in]
      );
    MCCR_PAGE_MODE_I: FDRE  -- LSB-1 of MCCR [bit 30 in a 32-b system]
      port map (
        Q  => page_Mode_Enable(i),             -- [out]
        C  => Bus2IP_Clk,                      -- [in]
        D  => Bus2IP_Data(MCCR_DWIDTH-2),  -- [in]
        R  => Bus2IP_Reset,                    -- [in]
        CE => valid_Reg_Write_Bus(i)           -- [in]

      );
  end generate MCCR_GEN;

  -----------------------------------------------------------------------------
  -- Fast or Slow slection logic
  -----------------------------------------------------------------------------

  fast_Slow_Select <= (not page_Mode_Enable and fast_Mode_Enable) or
                      (page_Mode_Enable and page_Hit);

  -----------------------------------------------------------------------------
  -- Wait State Generator
  -----------------------------------------------------------------------------
  WAIT_STATES_I: component Wait_States
    generic map (
      C_NUM_BANKS_MEM  => C_NUM_BANKS_MEM,
      C_RD_SLOW_0      => RD_SLOW_0,
      C_RD_FAST_0      => RD_FAST_0,
      C_WR_SLOW_0      => WR_SLOW_0,
      C_WR_FAST_0      => WR_FAST_0,
      C_RD_RECOVERY_0  => RD_RECOVERY_0,
      C_WR_RECOVERY_0  => WR_RECOVERY_0,
      C_RD_SLOW_1      => RD_SLOW_1,
      C_RD_FAST_1      => RD_FAST_1,
      C_WR_SLOW_1      => WR_SLOW_1,
      C_WR_FAST_1      => WR_FAST_1,
      C_RD_RECOVERY_1  => RD_RECOVERY_1,
      C_WR_RECOVERY_1  => WR_RECOVERY_1,
      C_RD_SLOW_2      => RD_SLOW_2,
      C_RD_FAST_2      => RD_FAST_2,
      C_WR_SLOW_2      => WR_SLOW_2,
      C_WR_FAST_2      => WR_FAST_2,
      C_RD_RECOVERY_2  => RD_RECOVERY_2,
      C_WR_RECOVERY_2  => WR_RECOVERY_2,
      C_RD_SLOW_3      => RD_SLOW_3,
      C_RD_FAST_3      => RD_FAST_3,
      C_WR_SLOW_3      => WR_SLOW_3,
      C_WR_FAST_3      => WR_FAST_3,
      C_RD_RECOVERY_3  => RD_RECOVERY_3,
      C_WR_RECOVERY_3  => WR_RECOVERY_3,
      C_RD_SLOW_4      => RD_SLOW_4,
      C_RD_FAST_4      => RD_FAST_4,
      C_WR_SLOW_4      => WR_SLOW_4,
      C_WR_FAST_4      => WR_FAST_4,
      C_RD_RECOVERY_4  => RD_RECOVERY_4,
      C_WR_RECOVERY_4  => WR_RECOVERY_4,
      C_RD_SLOW_5      => RD_SLOW_5,
      C_RD_FAST_5      => RD_FAST_5,
      C_WR_SLOW_5      => WR_SLOW_5,
      C_WR_FAST_5      => WR_FAST_5,
      C_RD_RECOVERY_5  => RD_RECOVERY_5,
      C_WR_RECOVERY_5  => WR_RECOVERY_5,
      C_RD_SLOW_6      => RD_SLOW_6,
      C_RD_FAST_6      => RD_FAST_6,
      C_WR_SLOW_6      => WR_SLOW_6,
      C_WR_FAST_6      => WR_FAST_6,
      C_RD_RECOVERY_6  => RD_RECOVERY_6,
      C_WR_RECOVERY_6  => WR_RECOVERY_6,
      C_RD_SLOW_7      => RD_SLOW_7,
      C_RD_FAST_7      => RD_FAST_7,
      C_WR_SLOW_7      => WR_SLOW_7,
      C_WR_FAST_7      => WR_FAST_7,
      C_RD_RECOVERY_7  => RD_RECOVERY_7,
      C_WR_RECOVERY_7  => WR_RECOVERY_7)
  port map (
      Bus2IP_Mem_CS       => bus2ip_mem_cs,         --[in]
      Fast_Slow_Select    => fast_Slow_Select,    --[in]
      RNW                 => Bus2IP_RNW,      --[in]
      Mem_Wait_States     => mem_Wait_States,     --[out]
      Recover_Wait_States => recover_Wait_States  --[out]
      );

  -----------------------------------------------------------------------------
  -- Memory Control
  -----------------------------------------------------------------------------
  MEM_STATE_MACHINE_I: Mem_State_Machine
    generic map ( C_ADDR_CNTR_WIDTH => ADDR_CNTR_WIDTH,
                  C_INCLUDE_BURST   => C_INCLUDE_BURST)
    port map (
      Clk                   =>  Bus2IP_Clk,          -- [in]
      Rst                   =>  Bus2IP_Reset,        -- [in]
      Valid_Memory_Access   =>  valid_Memory_Access, -- [in]
      Valid_Read            =>  valid_Memory_Read,   -- [in]
      Valid_Write           =>  valid_Memory_Write,  -- [in]
      Valid_Reg_Write       =>  valid_Reg_Write,     -- [in]
      Valid_Reg_Read        =>  Valid_Reg_Read ,     -- [in]
      Bus2IP_Reg_CS         =>  Bus2IP_Reg_CS,
      Prev_Access_Read      =>  prev_Access_Read,    -- [in]
      Synch_Mem             =>  synch_Mem,           -- [in]
      Two_pipe_delay        =>  two_pipe_delay,   -- [in]
      Mem_Wait_States       =>  mem_Wait_States,     -- [in]
      Rec_Wait_States       =>  recover_Wait_States, -- [in]
      Bus2IP_RNW            =>  Bus2IP_RNW,          -- [in]
      Bus2IP_Burst          =>  Bus2IP_Burst,         -- [in]
      Mem_RdAck             =>  mem_rdack,            -- [in]
      Addr_cnt              =>  addr_cnt,             -- [in]
      Access_cnt            =>  access_cnt,       -- [in]
      Addr_cnt_ce           =>  addr_cnt_ce,          -- [out]
      Addr_cnt_rst          =>  addr_cnt_rst,         -- [out]
      Reg_RdAck             =>  reg_rdack,           -- [out]
      Reg_WrAck             =>  reg_wrack,           -- [out]
      Mem_Wrcycle_done      =>  mem_wrcycle_done,     -- [out]
      Mem_WrAck             =>   mem_wrack       ,    -- [out]  
      Mem_Rdcycle_done      =>  mem_rdcycle_done,    -- [out]
      Burst_RdAck           =>  burst_rdack,          -- [out]
      Burst_WrAck           =>  burst_wrack,          -- [out]
      Mem_OEN               =>  sm_OEN,              -- [out]
      Mem_WEN               =>  sm_WEN,              -- [out]
      Sync_mem_cs           =>  sync_mem_cs       -- [out]
      );

DATA_PATH_I: data_path 
  generic map ( C_MAX_MEM_WIDTH             => C_MAX_MEM_WIDTH  ,        
                C_MIN_MEM_WIDTH             => MIN_MEM_WIDTH    ,       
                C_IPIF_DWIDTH               => C_IPIF_DWIDTH    ,      
                C_ADDR_CNTR_WIDTH           => ADDR_CNTR_WIDTH  ,
                C_GLOBAL_DATAWIDTH_MATCH    => GLOBAL_DATAWIDTH_MATCH,
                C_GLOBAL_SYNC_MEM           => GLOBAL_SYNC_MEM)      
  port map (
    -- inputs
    Valid_Memory_Access =>   valid_Memory_Access,
    Mem_DQ_I            =>   mem_dq_i_int    ,
    Bus2IP_Data         =>   Bus2IP_Data     ,
    Bus2IP_BE           =>   Bus2IP_BE       ,
    Addr_cnt            =>   addr_cnt        ,
    Mem_Wrcycle_Done    =>   mem_wrcycle_done,
    Mem_Rdcycle_Done    =>   mem_rdcycle_done,
    Mem_OEN             =>   sm_oen,
    Mem_width_bytes     =>   mem_width_bytes ,
    Datawidth_match     =>   datawidth_match ,
    Synch_mem           =>   synch_mem,
    Two_pipe_delay      =>   two_pipe_delay,
    Mem_RdAck           =>   mem_rdack       ,
    Mem_ReadData        =>   mem_readdata    ,
    Mem_WriteData       =>   mem_writedata   ,
    Mem_BE              =>   mem_be_int      ,
    Clk                 =>   Bus2IP_Clk      ,  
    Rst                 =>   Bus2IP_Reset    ,
    Input_datareg_rst   =>   input_datareg_rst
    );

SELECT_PARAM_I: select_param
    generic map (
      C_NUM_BANKS_MEM    =>  C_NUM_BANKS_MEM,
      C_GLOBAL_SYNC_MEM  =>  GLOBAL_SYNC_MEM,
      C_SYNCH_MEM_0      =>  C_SYNCH_MEM_0,   
      C_SYNCH_MEM_1      =>  C_SYNCH_MEM_1,   
      C_SYNCH_MEM_2      =>  C_SYNCH_MEM_2,   
      C_SYNCH_MEM_3      =>  C_SYNCH_MEM_3,   
      C_SYNCH_MEM_4      =>  C_SYNCH_MEM_4,   
      C_SYNCH_MEM_5      =>  C_SYNCH_MEM_5,   
      C_SYNCH_MEM_6      =>  C_SYNCH_MEM_6,   
      C_SYNCH_MEM_7      =>  C_SYNCH_MEM_7,    
      C_ACCESS_CNTR_0    =>  ACCESS_CNTR_0,
      C_ACCESS_CNTR_1    =>  ACCESS_CNTR_1,
      C_ACCESS_CNTR_2    =>  ACCESS_CNTR_2,
      C_ACCESS_CNTR_3    =>  ACCESS_CNTR_3,
      C_ACCESS_CNTR_4    =>  ACCESS_CNTR_4,
      C_ACCESS_CNTR_5    =>  ACCESS_CNTR_5,
      C_ACCESS_CNTR_6    =>  ACCESS_CNTR_6,
      C_ACCESS_CNTR_7    =>  ACCESS_CNTR_7,
      C_ADDR_CNTR_WIDTH  =>  ADDR_CNTR_WIDTH,
      C_MEM0_WIDTH       =>  C_MEM0_WIDTH,
      C_MEM1_WIDTH       =>  C_MEM1_WIDTH,
      C_MEM2_WIDTH       =>  C_MEM2_WIDTH,
      C_MEM3_WIDTH       =>  C_MEM3_WIDTH,
      C_MEM4_WIDTH       =>  C_MEM4_WIDTH,
      C_MEM5_WIDTH       =>  C_MEM5_WIDTH,
      C_MEM6_WIDTH       =>  C_MEM6_WIDTH,
      C_MEM7_WIDTH       =>  C_MEM7_WIDTH,
      C_SYNCH_PIPEDELAY_0   =>  C_SYNCH_PIPEDELAY_0,
      C_SYNCH_PIPEDELAY_1   =>  C_SYNCH_PIPEDELAY_1,
      C_SYNCH_PIPEDELAY_2   =>  C_SYNCH_PIPEDELAY_2,
      C_SYNCH_PIPEDELAY_3   =>  C_SYNCH_PIPEDELAY_3,
      C_SYNCH_PIPEDELAY_4   =>  C_SYNCH_PIPEDELAY_4,
      C_SYNCH_PIPEDELAY_5   =>  C_SYNCH_PIPEDELAY_5,
      C_SYNCH_PIPEDELAY_6   =>  C_SYNCH_PIPEDELAY_6,
      C_SYNCH_PIPEDELAY_7   =>  C_SYNCH_PIPEDELAY_7,
      C_GLOBAL_DATAWIDTH_MATCH          =>  GLOBAL_DATAWIDTH_MATCH,
      C_INCLUDE_DATAWIDTH_MATCHING_0    =>  C_INCLUDE_DATAWIDTH_MATCHING_0,
      C_INCLUDE_DATAWIDTH_MATCHING_1    =>  C_INCLUDE_DATAWIDTH_MATCHING_1,
      C_INCLUDE_DATAWIDTH_MATCHING_2    =>  C_INCLUDE_DATAWIDTH_MATCHING_2,
      C_INCLUDE_DATAWIDTH_MATCHING_3    =>  C_INCLUDE_DATAWIDTH_MATCHING_3,
      C_INCLUDE_DATAWIDTH_MATCHING_4    =>  C_INCLUDE_DATAWIDTH_MATCHING_4,
      C_INCLUDE_DATAWIDTH_MATCHING_5    =>  C_INCLUDE_DATAWIDTH_MATCHING_5,
      C_INCLUDE_DATAWIDTH_MATCHING_6    =>  C_INCLUDE_DATAWIDTH_MATCHING_6,
      C_INCLUDE_DATAWIDTH_MATCHING_7    =>  C_INCLUDE_DATAWIDTH_MATCHING_7
      )
    port map(
      Bus2IP_Mem_CS     =>  bus2ip_mem_cs,     
      Synch_mem         =>  Synch_mem,         
      Access_cntr       =>  access_cnt,
      Mem_width_bytes   =>  mem_width_bytes,
      Two_pipe_delay    =>  two_pipe_delay,
      Datawidth_match   =>  datawidth_match
      );

ADDR_CNTRMUX_I: addr_counter_mux
    generic map ( C_ADDR_CNTR_WIDTH         => ADDR_CNTR_WIDTH,
                  C_IPIF_AWIDTH             => C_IPIF_AWIDTH,
                  C_ADDR_OFFSET             => ADDR_OFFSET,
                  C_GLOBAL_DATAWIDTH_MATCH  => GLOBAL_DATAWIDTH_MATCH
                )
    port map (
        Addr_cnt_ce         =>  addr_cnt_ce ,
        Addr_cnt_rst        =>  addr_cnt_rst,
        Addr_cnt            =>  addr_cnt       ,
        Mem_width_bytes     =>  mem_width_bytes,
        Datawidth_match     =>  datawidth_match,
        valid_Memory_Access     =>  valid_Memory_Access ,
        Bus2IP_Addr         =>  Bus2IP_Addr,
        Mem_addr            =>  mem_addr,
        Clk                 =>  Bus2IP_Clk  ,
        Rst                 =>  Bus2IP_Reset         
        );
                
  -----------------------------------------------------------------------------
  -- Previous cycle information
  -----------------------------------------------------------------------------

  PREV_ADDR_PROCESS: process (Bus2IP_Clk) is
  begin
    if Bus2IP_Clk'event and Bus2IP_Clk='1' then
      if Bus2IP_Reset='1' then
        prev_Addr <= (others => '0');
        prev_Access_Read <= '0';
      elsif mem_rdack ='1'or mem_wrack ='1' then
        prev_Addr <= Bus2IP_Addr(0 to C_IPIF_AWIDTH-4);
        prev_Access_Read <= Bus2IP_RNW;
      end if;
    end if;
  end process PREV_ADDR_PROCESS;

  PAGE_HIT_PROCESS: process (Bus2IP_Addr,prev_Addr) is
  begin
    if Bus2IP_Addr(0 to C_IPIF_AWIDTH-4) = prev_Addr then
      page_Hit <= '1';
    else
      page_Hit <= '0';
    end if;
  end process PAGE_HIT_PROCESS;

  -----------------------------------------------------------------------------
  -- Previous cycle information
  -----------------------------------------------------------------------------

end architecture IMP;

