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

--    File Name    		: Channel_Mux.vhd 
                   		
--    Description  		: This module implements mux for data channels

--    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 Channel_Mux is
                generic(                     
                        g_NUMCHANNELS    : integer := 2;											-- Channel count
                        g_DATA_WIDTH     : integer := 16;											-- Data width
                        g_CHAN_WIDTH     : integer := 3 											-- Channel width
                       );
                 port( 
                          clock_i               : in std_logic;										-- Clock signal 
                          nreset_i              : in std_logic;										-- Asynchronous reset signal 
                          data_vld_i            : in std_logic;										-- Input data valid signal 
                          data1_i				: in std_logic_vector (g_DATA_WIDTH-1 downto 0); 	-- Input data1 signal 
                          data2_i				: in std_logic_vector (g_DATA_WIDTH-1 downto 0 );   -- Input data2 signal         
                          chan_in_i             : in std_logic_vector (g_CHAN_WIDTH-1 downto 0);	-- Input channel count signal
                          chan_out_o            : out std_logic_vector (g_CHAN_WIDTH-1 downto 0); 	-- Output channel count signal
                          data_o				: out std_logic_vector (g_DATA_WIDTH-1 downto 0 );  -- Output mux data signal                      
                          data_vld_o            : out std_logic										-- Output data valid signal 
                    );
end Channel_Mux;
architecture architecture_Channel_Mux of Channel_Mux is
-----------------------------------------------------------------------------------------------------------------------
-- signal declarations
----------------------------------------------------------------------------------------------------------------------- 
 signal  s_data             : std_logic_vector (g_DATA_WIDTH-1 downto 0); 
 type  T_data_reg           is array (1 to g_NUMCHANNELS)  of std_logic_vector ((g_DATA_WIDTH-1)   downto 0);
 signal s_data1_delay       : T_data_reg;
 signal s_data2_d           : std_logic_vector ((g_DATA_WIDTH-1)   downto 0):= (others=>'0');
 type  T_vld_reg            is array (1 to g_NUMCHANNELS)  of std_logic_vector (0 downto 0);
 signal s_vld_delay         : T_vld_reg;
 signal s_data_vld          : std_logic_vector(0 downto 0);
 signal s_chan              : std_logic_vector ((g_CHAN_WIDTH-1)   downto 0);

begin

--****************************************************************************************
--** Process name  : p_datadelay
--** Description   : This process implements programmable delay to the input
--                   
--**************************************************************************************** 
p_datadelay : process (nreset_i, clock_i) 
            begin
                  if(nreset_i = '0') then
                     s_data1_delay <= (others =>(others=>'0'));
                  elsif(rising_edge(clock_i)) then
                      s_data1_delay <= data2_i & s_data1_delay(1 to g_NUMCHANNELS-1);  
                  end if;                 
           end process p_datadelay ;
 s_data2_d  <= s_data1_delay(g_NUMCHANNELS);

--****************************************************************************************
--** Process name  : p_chandelay
--** Description   : This process implements programmable delay to the input
--                   
--**************************************************************************************** 
p_chandelay : process (nreset_i, clock_i) 
            begin
                  if(nreset_i = '0') then
                     s_chan <= (others=>'0');
                  elsif(rising_edge(clock_i)) then
                        if(data_vld_i ='1') then
                            s_chan  <= chan_in_i; 
                        else
                            s_chan  <= chan_in_i + std_logic_vector(to_unsigned(g_NUMCHANNELS,g_CHAN_WIDTH)); 
                        end if;
                  end if;                 
           end process p_chandelay ;

--************************************************************************************************
 --** process id  : p_Mux
 --** Description : This process registers the input Data Valid signal 
--************************************************************************************************
p_Mux:process(nreset_i,clock_i) 
         begin
              if(nreset_i =  '0') then   
                 s_data<= (others => '0');                                 
              elsif(rising_edge(clock_i)) then   
                   if(data_vld_i ='1') then
                        s_data  <= data1_i;                        
                   else
                        s_data  <= s_data2_d;                        
                   end if;
              end if;
          end process p_Mux;

--****************************************************************************************
--** Process name  : p_vlddelay
--** Description   : This process implements programmable delay to the data valid input
--                   
--**************************************************************************************** 
p_vlddelay : process (nreset_i, clock_i) 
            begin
                  if(nreset_i = '0') then
                     s_vld_delay <= (others =>(others=>'0'));
                  elsif(rising_edge(clock_i)) then
                      s_vld_delay <= s_data_vld & s_vld_delay(1 to g_NUMCHANNELS-1);  
                  end if;                 
           end process p_vlddelay ;

--****************************************************************************************
--** Process name  : p_datavld
--** Description   : This process generates output data valid signal
--                   
--**************************************************************************************** 
p_datavld : process (nreset_i, clock_i) 
            begin
                  if(nreset_i = '0') then
                     s_data_vld(0) <= '0';
                  elsif(rising_edge(clock_i)) then
                      s_data_vld(0) <= data_vld_i;
                  end if;                 
           end process p_datavld ;



data_vld_o  <= s_data_vld(0) or s_vld_delay(g_NUMCHANNELS)(0);
chan_out_o <= s_chan;
data_o <= s_data;

end architecture_Channel_Mux;
