-------------------------------------------------------------------------------
-- Title      : Fan Controller Toplevel module
-------------------------------------------------------------------------------
-- File       : pwm_n_tach.vhd
-- Author     : Pavan Marisetti
-- Company    : Microsemi Corporation
-- Device     : SmartFusion
-- Standard   : VHDL
-------------------------------------------------------------------------------
-- Description: This code is toplevel module, which integrates PWM, Tacho, and 
--              digital filetr
-------------------------------------------------------------------------------
-- Copyright (c) 2011   Microsemi Corporation
--                      All rights reserved.
-------------------------------------------------------------------------------
-- Revisions  : V1.0
-------------------------------------------------------------------------------

LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;
   USE ieee.numeric_std.all;

ENTITY pwm_n_tach IS
   GENERIC (
      PWM_NUM              : INTEGER := 1;
      APB_DWIDTH           : INTEGER := 32;
      SHADOW_REG_EN1       : INTEGER := 0;
      SHADOW_REG_EN2       : INTEGER := 0;
      SHADOW_REG_EN3       : INTEGER := 0;
      SHADOW_REG_EN4       : INTEGER := 0;
      SHADOW_REG_EN5       : INTEGER := 0;
      SHADOW_REG_EN6       : INTEGER := 0;
      SHADOW_REG_EN7       : INTEGER := 0;
      SHADOW_REG_EN8       : INTEGER := 0;
      SHADOW_REG_EN9       : INTEGER := 0;
      SHADOW_REG_EN10      : INTEGER := 0;
      SHADOW_REG_EN11      : INTEGER := 0;
      SHADOW_REG_EN12      : INTEGER := 0;
      SHADOW_REG_EN13      : INTEGER := 0;
      SHADOW_REG_EN14      : INTEGER := 0;
      SHADOW_REG_EN15      : INTEGER := 0;
      SHADOW_REG_EN16      : INTEGER := 0;
      PWM_STRETCH_VALUE1   : INTEGER := 1;
      PWM_STRETCH_VALUE2   : INTEGER := 1;
      PWM_STRETCH_VALUE3   : INTEGER := 1;
      PWM_STRETCH_VALUE4   : INTEGER := 1;
      PWM_STRETCH_VALUE5   : INTEGER := 1;
      PWM_STRETCH_VALUE6   : INTEGER := 1;
      PWM_STRETCH_VALUE7   : INTEGER := 1;
      PWM_STRETCH_VALUE8   : INTEGER := 1;
      PWM_STRETCH_VALUE9   : INTEGER := 1;
      PWM_STRETCH_VALUE10  : INTEGER := 1;
      PWM_STRETCH_VALUE11  : INTEGER := 1;
      PWM_STRETCH_VALUE12  : INTEGER := 1;
      PWM_STRETCH_VALUE13  : INTEGER := 1;
      PWM_STRETCH_VALUE14  : INTEGER := 1;
      PWM_STRETCH_VALUE15  : INTEGER := 1;
      PWM_STRETCH_VALUE16  : INTEGER := 1
   );
   PORT (
      PRESETN              : IN STD_LOGIC;
      PCLK                 : IN STD_LOGIC;
      PSEL                 : IN STD_LOGIC;
      PENABLE              : IN STD_LOGIC;
      PWRITE               : IN STD_LOGIC;
      PADDR                : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
      PWDATA               : IN STD_LOGIC_VECTOR(APB_DWIDTH - 1 DOWNTO 0);
      PRDATA               : OUT STD_LOGIC_VECTOR(APB_DWIDTH - 1 DOWNTO 0);
      PREADY               : OUT STD_LOGIC;
      PSLVERR              : OUT STD_LOGIC;
      PWM                  : OUT STD_LOGIC_VECTOR(PWM_NUM DOWNTO 1);
      TACHIN               : IN STD_LOGIC_vector(3 DOWNTO 0);
      TACHINT              : OUT STD_LOGIC
   );
END pwm_n_tach;

ARCHITECTURE pwm_n_tach OF pwm_n_tach IS
 


component pwm_top IS
   GENERIC (
      PWM_NUM              : INTEGER := 1;
      APB_DWIDTH           : INTEGER := 8;
      SHADOW_REG_EN1       : INTEGER := 0;
      SHADOW_REG_EN2       : INTEGER := 0;
      SHADOW_REG_EN3       : INTEGER := 0;
      SHADOW_REG_EN4       : INTEGER := 0;
      SHADOW_REG_EN5       : INTEGER := 0;
      SHADOW_REG_EN6       : INTEGER := 0;
      SHADOW_REG_EN7       : INTEGER := 0;
      SHADOW_REG_EN8       : INTEGER := 0;
      SHADOW_REG_EN9       : INTEGER := 0;
      SHADOW_REG_EN10      : INTEGER := 0;
      SHADOW_REG_EN11      : INTEGER := 0;
      SHADOW_REG_EN12      : INTEGER := 0;
      SHADOW_REG_EN13      : INTEGER := 0;
      SHADOW_REG_EN14      : INTEGER := 0;
      SHADOW_REG_EN15      : INTEGER := 0;
      SHADOW_REG_EN16      : INTEGER := 0;
      PWM_STRETCH_VALUE1   : INTEGER := 1;
      PWM_STRETCH_VALUE2   : INTEGER := 1;
      PWM_STRETCH_VALUE3   : INTEGER := 1;
      PWM_STRETCH_VALUE4   : INTEGER := 1;
      PWM_STRETCH_VALUE5   : INTEGER := 1;
      PWM_STRETCH_VALUE6   : INTEGER := 1;
      PWM_STRETCH_VALUE7   : INTEGER := 1;
      PWM_STRETCH_VALUE8   : INTEGER := 1;
      PWM_STRETCH_VALUE9   : INTEGER := 1;
      PWM_STRETCH_VALUE10  : INTEGER := 1;
      PWM_STRETCH_VALUE11  : INTEGER := 1;
      PWM_STRETCH_VALUE12  : INTEGER := 1;
      PWM_STRETCH_VALUE13  : INTEGER := 1;
      PWM_STRETCH_VALUE14  : INTEGER := 1;
      PWM_STRETCH_VALUE15  : INTEGER := 1;
      PWM_STRETCH_VALUE16  : INTEGER := 1
   );
   PORT (
      PRESETN              : IN STD_LOGIC;
      PCLK                 : IN STD_LOGIC;
      PSEL                 : IN STD_LOGIC;
      PENABLE              : IN STD_LOGIC;
      PWRITE               : IN STD_LOGIC;
      PADDR                : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
      PWDATA               : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
      PRDATA_regif         : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
      PWM                  : OUT STD_LOGIC_VECTOR(PWM_NUM DOWNTO 1);
      PWM_STRETCH          : IN STD_LOGIC_VECTOR(0 DOWNTO 0)
      );
END component;




component top_level_tach_measure is
	generic ( APB_DWIDTH : INTEGER := 32 );
	port (	
        PRESETN              : IN STD_LOGIC;
		PCLK                 : IN STD_LOGIC;
		PSEL                 : IN STD_LOGIC;
		PENABLE              : IN STD_LOGIC;
		PWRITE               : IN STD_LOGIC;
		PADDR                : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
		PWDATA               : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
		PRDATA               : OUT STD_LOGIC_VECTOR(APB_DWIDTH - 1 DOWNTO 0);
		TACHIN               : IN STD_LOGIC;
		TACHINT              : OUT STD_LOGIC;
        TACHOUT              : OUT std_logic;
        PULSE_STRETC_EN      : OUT std_logic;
        TACH_SEL_LINE        : OUT std_logic_vector(1 downto 0)

        );
end component;

component dig_sch_trig is
	port (	PRESETN              : IN STD_LOGIC;
		    PCLK                 : IN STD_LOGIC;
		    Tach_input           : IN STD_LOGIC;
		    Tach_input_sc_trig   : OUT STD_LOGIC
        );
end component;


   signal tach_sel_line_w    : std_logic_vector(1 downto 0);
   signal PULSE_STRETC_EN    : std_logic;
   signal Tach_input         : std_logic;
   signal Tach_input_sc_trig : std_logic;
   SIGNAL PRDATA_TACH        : STD_LOGIC_VECTOR((APB_DWIDTH - 1) DOWNTO 0);
   SIGNAL PRDATA_regif       : STD_LOGIC_VECTOR(7 DOWNTO 0);
   signal PWM_STRETCH        : STD_LOGIC_VECTOR(0 DOWNTO 0);
BEGIN   
   -- APB Read data
   xhdl51 : IF (APB_DWIDTH = 32) GENERATE
      PRDATA <= "100000000000000000000000" & PRDATA_regif WHEN ((PADDR(7 DOWNTO 2) <= "100100") OR (PADDR(7 DOWNTO 2) = "111001")) ELSE
                (PRDATA_TACH((APB_DWIDTH - 1) DOWNTO 0));
   END GENERATE;
      xhdl53 : IF (APB_DWIDTH = 16) GENERATE
         PRDATA <= "1000000000000000" & PRDATA_regif WHEN ((PADDR(7 DOWNTO 2) <= "100100") OR (PADDR(7 DOWNTO 2) = "111001")) ELSE
                   PRDATA_TACH((APB_DWIDTH - 1) DOWNTO 0);
      END GENERATE;
      xhdl54 : IF (APB_DWIDTH = 8) GENERATE
         PRDATA <= PRDATA_regif;
      END GENERATE;
   

  -- APB Ready and Slave Error signals
   PREADY <= '1';
   PSLVERR <= '0';



pwm_inst: pwm_top 
   GENERIC MAP (
      PWM_NUM,              
      8,           
      SHADOW_REG_EN1,       
      SHADOW_REG_EN2,       
      SHADOW_REG_EN3,       
      SHADOW_REG_EN4,       
      SHADOW_REG_EN5,       
      SHADOW_REG_EN6,       
      SHADOW_REG_EN7,       
      SHADOW_REG_EN8,       
      SHADOW_REG_EN9,       
      SHADOW_REG_EN10,      
      SHADOW_REG_EN11,    
      SHADOW_REG_EN12,     
      SHADOW_REG_EN13,     
      SHADOW_REG_EN14,     
      SHADOW_REG_EN15,      
      SHADOW_REG_EN16,      
      PWM_STRETCH_VALUE1,   
      PWM_STRETCH_VALUE2,   
      PWM_STRETCH_VALUE3,   
      PWM_STRETCH_VALUE4,   
      PWM_STRETCH_VALUE5,   
      PWM_STRETCH_VALUE6,   
      PWM_STRETCH_VALUE7,   
      PWM_STRETCH_VALUE8,   
      PWM_STRETCH_VALUE9,  
      PWM_STRETCH_VALUE10,  
      PWM_STRETCH_VALUE11,  
      PWM_STRETCH_VALUE12,  
      PWM_STRETCH_VALUE13,  
      PWM_STRETCH_VALUE14,  
      PWM_STRETCH_VALUE15,  
      PWM_STRETCH_VALUE16
   )
   PORT MAP (
	   PRESETN    => PRESETN,
	   PCLK       => PCLK,
	   PSEL       => PSEL,  
       PENABLE    => PENABLE,
       PWRITE     => PWRITE,
       PADDR      => PADDR,
       PWDATA     => PWDATA(7 downto 0),
       PRDATA_regif => PRDATA_regif,
       PWM             => PWM,
       PWM_STRETCH  => PWM_STRETCH
      );

   tach_inst: top_level_tach_measure
	generic map ( APB_DWIDTH )
	port map(
	   PRESETN    => PRESETN,
	   PCLK       => PCLK,
	   PSEL       => PSEL,  
       PENABLE    => PENABLE,
       PWRITE     => PWRITE,
       PADDR      => PADDR,
       PWDATA     => PWDATA(7 downto 0 ),
	   PRDATA     => PRDATA_TACH,
	   TACHIN     => Tach_input_sc_trig,
	   TACHINT    => TACHINT,
       TACH_SEL_LINE => tach_sel_line_w,
       PULSE_STRETC_EN => PULSE_STRETC_EN
        );


dig_sch_trig_inst: dig_sch_trig
	port map(	PRESETN          => PRESETN,
		    PCLK                 => PCLK,
		    Tach_input           => Tach_input,
		    Tach_input_sc_trig   => Tach_input_sc_trig                 
        );
Tach_input <= TACHIN(0) when tach_sel_line_w = "00" else
              TACHIN(1) when tach_sel_line_w = "01" else
              TACHIN(2) when tach_sel_line_w = "10" else
              TACHIN(3) when tach_sel_line_w = "11";

PWM_STRETCH(0) <= PULSE_STRETC_EN when tach_sel_line_w = "00" else
                  '0';
--PWM_STRETCH(1) <= PULSE_STRETC_EN when tach_sel_line_w = "01" else
--                  '0';
--PWM_STRETCH(2) <= PULSE_STRETC_EN when tach_sel_line_w = "10" else
--                  '0';
--PWM_STRETCH(3) <= PULSE_STRETC_EN when tach_sel_line_w = "11" else
--                  '0';


END pwm_n_tach;




