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

--    File Name    		: dds_demux.vhd 
                   		
--    Description  		: This module implements demuxing of DDS 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;
use work.System_pack.all;
use work.dds_pack.all;

entity dds_demux is            
                 port( 
                          clock_i         : in std_logic;                                           -- Clock signal
                          nreset_i        : in std_logic;                                           -- Asynchronous reset signal
                          cos_i           : in std_logic_vector (g_DATAWIDTH-1 downto 0);           -- Input cosine signal
                          sin_i           : in std_logic_vector (g_DATAWIDTH-1 downto 0);           -- Input sine signal
                          chan_i          : in std_logic_vector (g_NUM_CHANNELS_WIDTH-1 downto 0);  -- Input cahnnel count signal
                          data_chan_i     : in std_logic_vector (g_NUM_CHANNELS_WIDTH-1 downto 0);  -- Input data channel count signal
                          cos0_o	      : out std_logic_vector ((g_DATAWIDTH)-1 downto 0 );       -- Output channel 0 cosine signal
                          sin0_o		  : out std_logic_vector ((g_DATAWIDTH)-1 downto 0 );       -- Output channel 0 sine signal
                          cos1_o	      : out std_logic_vector ((g_DATAWIDTH)-1 downto 0 );       -- Output channel 1 cosine signal
                          sin1_o		  : out std_logic_vector ((g_DATAWIDTH)-1 downto 0 )        -- Output channel 1 sine signal             
                    );
end dds_demux;
architecture architecture_dds_demux of dds_demux is
--------------------------------------------------------------------------------------------------------------------------
-- signal declaration
--------------------------------------------------------------------------------------------------------------------------
 signal s_chan              : integer range    0 to (g_NUM_CHANNELS-1); 
 signal s_cos0	            : std_logic_vector ((g_DATAWIDTH)-1 downto 0 ); 
 signal s_sin0     		    : std_logic_vector ((g_DATAWIDTH)-1 downto 0 );
 signal s_cos1	            : std_logic_vector ((g_DATAWIDTH)-1 downto 0 ); 
 signal s_sin1		        : std_logic_vector ((g_DATAWIDTH)-1 downto 0 ); 
 signal s_cos1_d1	        : std_logic_vector ((g_DATAWIDTH)-1 downto 0 ); 
 signal s_sin1_d1		    : std_logic_vector ((g_DATAWIDTH)-1 downto 0 );     
 signal s_cos0_d1           : std_logic_vector ((g_DATAWIDTH)-1 downto 0 );
 signal s_sin0_d1           : std_logic_vector ((g_DATAWIDTH)-1 downto 0 );
 signal s_cos0_d2           : std_logic_vector ((g_DATAWIDTH)-1 downto 0 );
 signal s_sin0_d2           : std_logic_vector ((g_DATAWIDTH)-1 downto 0 );

begin

s_chan  <= to_integer(unsigned(chan_i));
----************************************************************************************************
 ----** process id  : p_Demux
 ----** Description : This process demux the dds sin and cos based on the chan number 
----************************************************************************************************
p_demux : process (nreset_i, clock_i) 
              begin
                  if(nreset_i = '0') then
                     s_cos0 <= (others=>'0');
                     s_sin0 <= (others=>'0');
                     s_cos1 <= (others=>'0');
                     s_sin1 <= (others=>'0');
                  elsif(rising_edge(clock_i)) then
                        case (s_chan) is
                            when 0 =>
                                s_cos0 <= cos_i; 
                                s_sin0 <= sin_i; 
                            when 1 =>
                                s_cos1 <= cos_i; 
                                s_sin1 <= sin_i; 
                            when others => 
                                    null;
                        end case;
                   end if;
               end process;

----************************************************************************************************
 ----** process id  : p_reg
 ----** Description : This process aligns the demux outputs to the delays introduced by TDM
----************************************************************************************************
p_reg : process (nreset_i, clock_i) 
              begin
                  if(nreset_i = '0') then
                     s_cos1_d1 <= (others=>'0');
                     s_sin1_d1 <= (others=>'0');
                     s_cos0_d2 <= (others=>'0');
                     s_sin0_d2 <= (others=>'0');
                     s_cos0_d1 <= (others=>'0');
                     s_sin0_d1 <= (others=>'0');                  
                  elsif(rising_edge(clock_i)) then 
                      s_cos1_d1    <= s_cos1; 
                      s_sin1_d1    <= s_sin1; 
                      s_cos0_d1    <= s_cos0; 
                      s_sin0_d1    <= s_sin0;
                      s_cos0_d2    <= s_cos0_d1; 
                      s_sin0_d2    <= s_sin0_d1; 
                   end if;
               end process;

----************************************************************************************************
----** process id  : p_chanlatch
----** Description : This process aligns the demux outputs to the delays introduced by TDM
----************************************************************************************************
p_chanlatch : process (nreset_i, clock_i) 
              begin
                  if(nreset_i = '0') then
                     cos0_o <= (others=>'0');
                     sin0_o <= (others=>'0');
                     cos1_o <= (others=>'0');
                     sin1_o <= (others=>'0');                                   
                  elsif(rising_edge(clock_i)) then 
                    if(data_chan_i  = std_logic_vector(to_unsigned((g_NUM_CHANNELS-1),g_NUM_CHANNELS_WIDTH)  ))then
                          cos1_o    <= s_cos1_d1; 
                          sin1_o    <= s_sin1_d1;                          
                          cos0_o    <= s_cos0_d2; 
                          sin0_o    <= s_sin0_d2; 
                     end if;
                   end if;
               end process;

end architecture_dds_demux;
