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

--    File Name    		: duc_axc_tdm_data.vhd 
                   		
--    Description  		: This module implements muxing of cpri axc rx data to DUC  

--    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 duc_axc_tdm_data is
                generic(
                        g_NUM_AXC       : integer := 4;                                                 -- AXC count
                        g_AXC_RATE      : integer := 8;                                                 -- AXC Rate
                        g_NUM_ANTENNA   : integer := 4;                                                 -- RF ANTENNA COUNT
                        g_DATAWIDTH     : integer := 32                                                 -- DATA WIDTH
                );
                port (
                       nreset_i         : in std_logic;                                                 --Asynchronous reset signal
                       clock_i          : in std_logic;                                                 --Clock signal
                       data_i           : in std_logic_vector((g_NUM_AXC*g_DATAWIDTH)-1 downto 0);      --Input AXC data signal
                       data_vld_i       : in std_logic;                                                 --Input AXC data valid signal
                       rd_req_o         : out std_logic_vector(g_NUM_AXC-1 downto 0);                   --Output AXC read req signal
                       data_vld_o       : out std_logic;                                                --Output data valid signal
                       data_o           : out std_logic_vector((g_DATAWIDTH/2)-1 downto 0);             --Output ducin data signal
                       data_chan_0      : out std_logic_vector(g_NUM_ANTENNA-1 downto 0)                --Output duc channel count signal
                );
end duc_axc_tdm_data;
architecture architecture_duc_axc_tdm_data of duc_axc_tdm_data is
-------------------------------------------------------------------
-- Signals declaration
-------------------------------------------------------------------
signal s_chan           :  integer  range    0 to (g_AXC_RATE-1); 
signal s_rd_req         :  std_logic; 
signal s_data_in        :  std_logic_vector((g_NUM_AXC*g_DATAWIDTH)-1 downto 0);
signal s_chan_count     :  integer  range    0 to (g_AXC_RATE-1);
signal s_chan_count_d1  :  integer  range    0 to (g_AXC_RATE-1); 
signal s_data           :  std_logic_vector((g_DATAWIDTH/2)-1 downto 0);
signal s_data_vld       :  std_logic;
begin

--************************************************************************************************
--** process id  : p_Rdreq
--** Description : This process generates rd request for CDC RAM based on AXC Rate
--************************************************************************************************
p_Rdreq: process(clock_i,nreset_i)
         begin
               if nreset_i = '0' then
                  s_chan <= 0;                    
                  s_rd_req <= '0';
              elsif rising_edge(clock_i) then
                    if(s_chan = g_AXC_RATE-1) then
                       s_chan <= 0;
                       s_rd_req <= '1';
                    else
                        s_chan <= s_chan+ 1;
                        s_rd_req <= '0';
                    end if;
              end if;
         end process p_Rdreq;

Rdreq_Gen: for i in 0 to (g_NUM_AXC-1) generate
            begin
                rd_req_o(i) <= s_rd_req;               
           end generate;

--************************************************************************************************
--** process id  : p_VldCount
--** Description : This process channel count based on data valid signal
--************************************************************************************************
p_VldCount: process(clock_i,nreset_i)
         begin
               if nreset_i = '0' then
                  s_chan_count <= 0;   
                  s_chan_count_d1 <= 0;                   
              elsif rising_edge(clock_i) then
                    if(data_vld_i = '1') then
                       s_chan_count <= 0;                       
                    else
                        s_chan_count <= s_chan_count+ 1;                       
                    end if;
                    s_chan_count_d1 <= s_chan_count;  
              end if;
         end process p_VldCount;

--************************************************************************************************
--** process id  : p_DataDelay
--** Description : This process delay input dat by a clock cycle.
--************************************************************************************************
p_DataDelay: process(clock_i,nreset_i)
         begin
               if nreset_i = '0' then
                  s_data_in <= (others => '0');                                    
              elsif rising_edge(clock_i) then
                   s_data_in <= data_i;
              end if;
         end process p_DataDelay;

--************************************************************************************************
--** process id  : p_Data
--** Description : This process demux the antenna data based on channel numbers
--************************************************************************************************
p_Data:process(clock_i,nreset_i)
       begin
        if(nreset_i  = '0') then
           s_data <= (others => '0');   
           s_data_vld   <= '0';
        elsif(rising_edge(clock_i)) then  
           case(s_chan_count)  is
                when 0 =>
                     s_data <= s_data_in((g_DATAWIDTH/2)-1 downto 0);                               --A0C0 I component 
                when 1 =>
                     s_data <= s_data_in((g_DATAWIDTH+ (g_DATAWIDTH/2))-1 downto g_DATAWIDTH);      --A1C0 I component 
                when 2 =>
                     s_data <= (others => '0');                                                     --A0C1 I component 
                when 3 =>
                     s_data <= (others => '0');                                                     --A1C1 I component 
                when 4 =>
                     s_data <= s_data_in(g_DATAWIDTH-1 downto (g_DATAWIDTH/2));                     --A0C0 Q component 
                when 5 =>
                     s_data <= s_data_in((2*g_DATAWIDTH)-1 downto (g_DATAWIDTH+ (g_DATAWIDTH/2))) ; --A1C0 Q component 
                when 6 =>
                     s_data <= (others => '0');                                                     --A0C1 Q component  
               when 7 =>
                     s_data <= (others => '0');                                                     --A0C1 Q component 
               when others =>
                         null;
          end case;
          s_data_vld   <= '1';
        end if;
      end process p_Data;


data_chan_0 <= std_logic_vector(to_unsigned(s_chan_count_d1,g_NUM_ANTENNA));     
data_o <= s_data;
data_vld_o <= s_data_vld;


end architecture_duc_axc_tdm_data;
