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

--    File Name    		: CF_Demux_Mux.vhd 
                   		
--    Description  		: This module implements demuxing based on 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 CF_Demux_Mux is
                generic(                       
                        g_NUMCHANNELS    : integer := 4;										-- Number of 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
                          data_i		  : in  std_logic_vector (g_DATA_WIDTH-1 downto 0);     -- Input data 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
                          data1_o		  : out std_logic_vector (g_DATA_WIDTH-1 downto 0 ); 	-- Output demux data1 signal 
                          data2_o		  : out std_logic_vector (g_DATA_WIDTH-1 downto 0 ); 	-- Output demux data2 signal 
                          data_vld_o      : out std_logic										-- Output data valid signal
                    );
end CF_Demux_Mux;
architecture architecture_CF_Demux_Mux of CF_Demux_Mux is
-----------------------------------------------------------------------------------------------------------------------
-- signal declarations
----------------------------------------------------------------------------------------------------------------------- 
 signal s_data1             : std_logic_vector (g_DATA_WIDTH-1 downto 0); 
 signal s_data2             : 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_data1_d           : std_logic_vector ((g_DATA_WIDTH-1)   downto 0):= (others=>'0');
 type   T_chan_reg          is array (1 to g_NUMCHANNELS+1)  of std_logic_vector ((g_CHAN_WIDTH-1)   downto 0);
 signal s_chan_delay        : T_chan_reg;
 type   T_vld_reg           is array (1 to g_NUMCHANNELS+1)  of std_logic_vector (0 downto 0);
 signal s_vld_delay         : T_vld_reg;
 signal s_data_vld          : std_logic_vector(0 downto 0);

begin

--************************************************************************************************
 --** process id  : p_Demux
 --** Description : This process does demuxing the input data signal
--************************************************************************************************
p_Demux:process(nreset_i,clock_i) 
         begin
              if(nreset_i =  '0') then   
                    s_data1<= (others => '0'); 
                    s_data2 <= (others => '0');               
              elsif(rising_edge(clock_i)) then   
                   if(chan_in_i < std_logic_vector(to_unsigned( g_NUMCHANNELS,g_CHAN_WIDTH))) then
                        s_data1  <= data_i;
                        s_data2  <= (others => '0');
                   else
                        s_data2  <= data_i;
                        s_data1  <= (others => '0'); 
                   end if;
              end if;
          end process p_Demux;


--****************************************************************************************
--** Process name  : p_datadelay
--** Description   : This process implements programmable delay to the first data 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 <= s_data1 & s_data1_delay(1 to g_NUMCHANNELS-1);  
                  end if;                 
           end process p_datadelay ;

s_data1_d   <= s_data1_delay(g_NUMCHANNELS);
data1_o     <= s_data1_d;
data2_o     <= s_data2;

--****************************************************************************************
--** Process name  : p_chandelay
--** Description   : This process implements programmable delay to the channel number input
--                   
--**************************************************************************************** 
p_chandelay : process (nreset_i, clock_i) 
            begin
                  if(nreset_i = '0') then
                     s_chan_delay <= (others =>(others=>'0'));
                  elsif(rising_edge(clock_i)) then
                      s_chan_delay <= chan_in_i & s_chan_delay(1 to g_NUMCHANNELS);  
                  end if;                 
           end process p_chandelay ;

 chan_out_o  <= s_chan_delay(g_NUMCHANNELS+1);

--****************************************************************************************
--** Process name  : p_vlddelay
--** Description   : This process implements programmable delay to the valid signal 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);  
                  end if;                 
           end process p_vlddelay ;

 s_data_vld(0) <= data_vld_i;
 data_vld_o    <= s_vld_delay(g_NUMCHANNELS+1)(0);

end architecture_CF_Demux_Mux;
