--/******************************************************************************
--    Company      		: MICROSEMI

--    File Name    		: cdc_data_ram.vhd 
                   		
--    Description  		: This module implements CDC RAM

--    Targeted device 	: Family           Die          Package
--                   	  PolarFire     MPF300T_ES      MPF300T_ES

--    Author          	: India Solutions Team

--
-- SVN Revision Information:
-- SVN $Revision: 
-- SVN $Date:  $  
-- COPYRIGHT 2018 BY MICROSEMI 
-- THE INFORMATION CONTAINED IN THIS DOCUMENT IS SUBJECT TO LICENSING RESTRICTIONS 
-- FROM MICROSEMI CORP.  IF YOU ARE NOT IN POSSESSION OF WRITTEN AUTHORIZATION FROM 
-- MICROSEMI FOR USE OF THIS FILE, THEN THE FILE SHOULD BE IMMEDIATELY DESTROYED AND 
-- NO BACK-UP OF THE FILE SHOULD BE MADE. 
-- 

--******************************************************************************/
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

entity cdc_data_ram is
                generic(
                          g_NUM_AXC           : integer  := 4;                                          -- AXC count                         
                          g_DATAWIDTH         : integer  := 32                                          -- Data width
                        );
                port(
                            wrstn_i         : IN  std_logic_vector(g_NUM_AXC-1 downto 0);               -- Input write reset signal
                            rrstn_i         : IN  std_logic_vector(g_NUM_AXC-1 downto 0);               -- Input read reset signal
                            rclk_i          : IN  std_logic_vector(g_NUM_AXC-1 downto 0);               -- Read clock signal         
                            wclk_i          : IN  std_logic_vector(g_NUM_AXC-1 downto 0);               -- Write clock signal
                            wen_i           : IN  std_logic_vector(g_NUM_AXC-1 downto 0);               -- Input write enable signal
                            ren_i           : IN  std_logic_vector(g_NUM_AXC-1 downto 0);               -- Input read enable signal
                            wdata_i         : IN  std_logic_vector((g_NUM_AXC*g_DATAWIDTH)-1 downto 0); -- Input write data signal                  
                            rdata_o         : OUT std_logic_vector((g_NUM_AXC*g_DATAWIDTH)-1 downto 0); -- Output read data signal
                            rdata_vld_o     : OUT std_logic_vector(g_NUM_AXC-1 downto 0)                -- Output read valid signal
    );

end cdc_data_ram;
architecture architecture_cdc_data_ram of cdc_data_ram is
--------------------------------------------------------------------------------------------------------------------------
-- signal declaration
-------------------------------------------------------------------------------------------------------------------------- 
signal s_raddr : std_logic_vector(g_NUM_AXC*9-1 downto 0);
signal s_waddr : std_logic_vector(g_NUM_AXC*9-1 downto 0);
-----------------------------------------------------------------------------------------------------------------------
-- component declarations 
-----------------------------------------------------------------------------------------------------------------------
component cdcram is
port(
                        R_CLK  : IN  std_logic;                
                        W_CLK  : IN  std_logic; 
                        W_EN   : IN  std_logic;
                        R_EN   : IN  std_logic;
                        W_DATA : IN  std_logic_vector(g_DATAWIDTH-1 downto 0);
                        W_ADDR : IN  std_logic_vector( 8 downto 0);
                        R_ADDR : IN  std_logic_vector( 8 downto 0);
                        R_DATA : OUT std_logic_vector(g_DATAWIDTH-1 downto 0)
    );
end component;
begin

 p_RAM_Gen : for i in 0 to (g_NUM_AXC-1) generate
             begin 
--************************************************************************************************
 --** process id  : P_Waddr
 --** Description : This process generated RAM write address
--************************************************************************************************
                 P_Waddr:process(wclk_i(i),wrstn_i(i))
                    begin
                        if(wrstn_i(i)  = '0') then
                            s_waddr(9*i +8 downto 9*i) <= (others => '0');
                        elsif(rising_edge(wclk_i(i))) then
                                if(wen_i(i) = '1') then
                                    s_waddr(9*i +8 downto 9*i) <= s_waddr(9*i +8 downto 9*i) + '1';            
                                end if;
                        end if;
                    end process;

--************************************************************************************************
 --** process id  : P_Raddr
 --** Description : This process generated RAM read address
--************************************************************************************************
                 P_Raddr:process(rclk_i(i),rrstn_i(i))
                    begin
                        if(rrstn_i(i)  = '0') then
                            s_raddr(9*i +8 downto 9*i)  <= "100000000";       
                        elsif(rising_edge(rclk_i(i))) then  
                                if(ren_i(i) = '1') then
                                    s_raddr(9*i +8 downto 9*i) <= s_raddr(9*i +8 downto 9*i) + '1';           
                                end if;           
                        end if;
                    end process;         

                    U_cdcram : cdcram 
                                    port map(
                                            R_CLK  => rclk_i(i),              
                                            W_CLK  => wclk_i(i),
                                            W_EN   => wen_i(i),
                                            R_EN   => ren_i(i),
                                            W_DATA => wdata_i(g_DATAWIDTH*i +(g_DATAWIDTH-1) downto (g_DATAWIDTH*i)),
                                            W_ADDR => s_waddr(9*i +8 downto 9*i),
                                            R_ADDR => s_raddr(9*i +8 downto 9*i),
                                            R_DATA => rdata_o(g_DATAWIDTH*i +(g_DATAWIDTH-1) downto (g_DATAWIDTH*i))
                                            );

--************************************************************************************************
 --** process id  : P_Rvld
 --** Description : This process generated RAM read valid signal
--************************************************************************************************
                 P_Rvld:process(rclk_i(i),rrstn_i(i))
                    begin
                        if(rrstn_i(i)  = '0') then
                            rdata_vld_o(i)  <= '0';       
                        elsif(rising_edge(rclk_i(i))) then  
                             rdata_vld_o(i)  <= ren_i(i);             
                        end if;
                    end process;


 end generate p_RAM_Gen; 

end architecture_cdc_data_ram;
