-------------------------------------------------------------------------------
-- addr_counter_mux.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:        addr_counter_mux.vhd
-- Version:         v1.10b
-- Description:     This file contains the addr_counter and mux for the EMC 
--                  design.
--                  
-- 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:          ALS
-- History:
--   ALS           12/04/02    First Version
--   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:                  "*_com" 
--      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_unsigned.all;

library proc_common_v1_00_b;
use proc_common_v1_00_b.proc_common_pkg.all;
use proc_common_v1_00_b.all;

library unisim;
use unisim.all;

-------------------------------------------------------------------------------
-- Definition of Generics:
--      C_ADDR_CNTR_WIDTH       -- width of address counter
--      C_IPIF_AWIDTH           -- width of IPIF address bus
--      C_ADDR_OFFSET           -- unused lower address bits based on data width
--      C_GLOBAL_DATAWIDTH_MATCH-- indicates whether any memory bank is
--                              -- supporting data width matching
--
-- Definition of Ports:
--      Addr_cnt_ce             -- address counter count enable
--      Addr_cnt_rst            -- address counter reset
--      Addr_cnt                -- address count
--
--      Mem_width_bytes         -- width in bytes of currently addressed memory bank
--      Datawidth_match         -- data-width matching for currently addressed memory bank 
--      Bus2IP_Addr             -- address from the processor bus
--      Mem_addr                -- address out to memory
--
--    -- Clocks and reset
--      Clk                 
--      Rst               
---------------------------------------------------------------------------

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

entity 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;
        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 entity addr_counter_mux;

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

architecture imp of addr_counter_mux is
-----------------------------------------------------------------------------
-- Constant declarations
-----------------------------------------------------------------------------
-- reset values
constant ADDRCNT_RST    : std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1)  := (others => '0');

-----------------------------------------------------------------------------
-- Signal declarations
-----------------------------------------------------------------------------
signal addr_cnt_i       : std_logic_vector(0 to C_ADDR_CNTR_WIDTH-1);
signal addr_suffix      : std_logic_vector(0 to C_ADDR_OFFSET-1) := (others => '0');

signal Addr_cnt_rst_int : std_logic;

-----------------------------------------------------------------------------
-- Component declarations
-----------------------------------------------------------------------------
component ld_arith_reg
    generic (
        C_ADD_SUB_NOT : boolean := false;
        C_REG_WIDTH   : natural := 8;
        C_RESET_VALUE : std_logic_vector;
        C_LD_WIDTH    : natural :=  8;
        C_LD_OFFSET   : natural :=  0;
        C_AD_WIDTH    : natural :=  8;
        C_AD_OFFSET   : natural :=  0
    );
    port (
        CK       : in  std_logic;
        RST      : in  std_logic; 
        Q        : out std_logic_vector(0 to C_REG_WIDTH-1);
        LD       : in  std_logic_vector(0 to C_LD_WIDTH-1); 
        AD       : in  std_logic_vector(0 to C_AD_WIDTH-1); 
        LOAD     : in  std_logic;  
        OP       : in  std_logic   
       );
end component ld_arith_reg;
 
-----------------------------------------------------------------------------
-- Begin architecture
-----------------------------------------------------------------------------

begin 

---------------------------- NO DATAWIDTH MATCHING ----------------------------
-- if datawidth matching has not been turned on for any memory banks, simplify
-- the logic
NO_DATAWIDTH_MATCH_GEN: if C_GLOBAL_DATAWIDTH_MATCH = 0 generate
    Addr_cnt <= (others => '0');
    Mem_addr <= Bus2IP_Addr;
end generate NO_DATAWIDTH_MATCH_GEN;

---------------------------- DATAWIDTH MATCHING ----------------------------
-- if datawidth matching has been turned on at least 1 memory bank, implement
-- the data width matching logic
-- Note that an individual bank with datawidth matching turned off will still
-- use this logic
--
DATAWIDTH_MATCH_GEN: if C_GLOBAL_DATAWIDTH_MATCH = 1 generate

    -------------------------------------------------------------------------------
    -- Assign output signals
    -------------------------------------------------------------------------------
    Addr_cnt <= addr_cnt_i;
    Mem_addr <= Bus2IP_Addr when Datawidth_match = '0'
                else Bus2IP_Addr(0 to C_IPIF_AWIDTH-C_ADDR_OFFSET-1) & addr_suffix;

    Addr_cnt_rst_int <= Addr_cnt_rst or not (valid_Memory_Access);

    -------------------------------------------------------------------------------
    -- Instantiate the addr_counter
    -------------------------------------------------------------------------------
    ADDRCNT_I: ld_arith_reg
        generic map (C_ADD_SUB_NOT  => true,
                     C_REG_WIDTH    => C_ADDR_CNTR_WIDTH,
                     C_RESET_VALUE  => ADDRCNT_RST,
                     C_LD_WIDTH     => C_ADDR_CNTR_WIDTH,
                     C_LD_OFFSET    => 0,
                     C_AD_WIDTH     => 1,
                     C_AD_OFFSET    => 0
                    )
        port map (   CK             => Clk,
                     RST            => Addr_cnt_rst_int,
                     Q              => addr_cnt_i,   
                     LD             => ADDRCNT_RST, 
                     AD             => "1",  
                     LOAD           => '0',
                     OP             => Addr_cnt_ce
                 );

    -------------------------------------------------------------------------------
    -- Create the address suffix 
    -------------------------------------------------------------------------------
    ADDR_SUFFIX_PROCESS: process(Mem_width_bytes, Bus2IP_Addr, addr_cnt_i)
    begin

        addr_suffix <= (others => '0');

        case Mem_width_bytes is
            when 1 =>   addr_suffix <= addr_cnt_i;

            when 2 =>   addr_suffix <= addr_cnt_i(1 to C_ADDR_CNTR_WIDTH-1) & '0';

            when 4 =>   -- if 32-bit IPIF, then addr_suffix = zero so don't need
                        -- to assign it here
                        -- only assign if 64-bit IPIF (ADDR_OFFSET=3)
                        if C_ADDR_OFFSET = 3 then
                            addr_suffix <= addr_cnt_i(2 to C_ADDR_CNTR_WIDTH-1) & "00";
                        end if;

            when 8 =>       addr_suffix <= (others => '0');

            when others=>   addr_suffix <= (others => '0');
        end case;

    end process ADDR_SUFFIX_PROCESS;
end generate DATAWIDTH_MATCH_GEN;
end imp;
