--*******************************************************************
-- RTC Demo Design
-- Actel Corporation
-- Date: 2/3/2006
-- Design Description:
-- Using the Fusion device’s RTC, this application provides a count 
-- of seconds, minutes, hours, day of the week, day of the month, month,
-- and year. The month-ending date is automatically adjusted for months
-- with less than 31 days, including corrections for leap years. Moreover,
-- the FPGA core can be powered off to save power, and the RTC will continue 
-- to keep track of the time and date information.
--
--****************************************************************************
-- IMPORTANT-READ THESE TERMS CAREFULLY BEFORE UTILIZING THE INFORMATION
-- CONTAINED IN THIS APPLICATION NOTE. 
--
-- NO SUPPORT/NO WARRANTY. THE DESIGN FILES AND DOCUMENTATION ARE PROVIDED
-- WITHOUT SUPPORT OR WARRANTY OF ANY KIND. ACTEL IS NOT OBLIGATED TO 
-- PROVIDE UPDATES, BUG FIXES, OR TECHNICAL SUPPORT AND DISCLAIMS ALL 
-- WARRANTIES INCLUDING, WITHOUT LIMITATION, THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE, AND WARRANTIES OF NON-INFRINGEMENT OF THE
-- RIGHTS OF THIRD PARTIES (INCLUDING, WITHOUT LIMITATION, RIGHTS UNDER PATENT,
-- COPYRIGHT, TRADE SECRET, OR OTHER INTELLECTUAL PROPERTY RIGHTS).  RECIPIENT
-- ACCEPTS THE APPLICATION NOTE DESIGN FILES AND DOCUMENTATION IN "AS-IS"
-- CONDITION.
--*****************************************************************************

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library fusion;


entity RTC_demo is

	port(SYS_RESET		: in std_logic;			
		 INIT_DONE 		: out std_logic;     	
		 VAREF 			: inout std_logic := 'Z';
		 DATAVALID 		: out std_logic; 
         ASSC_DONE		: out std_logic;
         ASSC_CHSAT		: out std_logic;
         ASSC_CHLATD 	: out std_logic;	   
        	
         RS_LCD 		: out std_logic; --LCD signals
         DATA_LCD 		: out std_logic_vector(7 downto 4);
         EN_LCD 		: out std_logic;
         R_nW_LCD 		: out std_logic;   
	           
		 ACM_CLK		: out std_logic;
		 clk_78khz		: out std_logic;		
	     FPGAGOOD	 	: out std_logic; 
	     PUCORE 	 	: out std_logic; 
	     PUB		 	: in std_logic;  -- Wake up the device - SW7
--	     
       	 SW1    		: in std_logic;  -- reset LCD - SW1 	     
		 SW2			: in std_logic;  -- time/date switch - SW2	      
		 POWER_down		: in std_logic;  -- power down the fpga core - SW3
--		 	   	   	           
	     XTAL1	 		: in std_logic;   
	     RTCCLK_out   	: out std_logic;  
	     clk1hz  		: out std_logic;  
	     RTC_act		: out std_logic;  
	     RTC_year		: out std_logic_vector(7 downto 0); 
	     RTC_month		: out std_logic_vector(7 downto 0); 
	     RTC_date		: out std_logic_vector(7 downto 0); 
	     RTC_day		: out std_logic_vector(7 downto 0); 
	     RTC_hours		: out std_logic_vector(7 downto 0); 
	     RTC_minutes	: out std_logic_vector(7 downto 0); 
	     RTC_seconds	: out std_logic_vector(7 downto 0)	
        );
end RTC_demo;

architecture DEF_ARCH of RTC_demo is

-- 100 MHz embedded RC Oscillator
component RCO 
    port(CLKOUT 	: out std_logic) ;
end component;

--PLL created by Smartgen
component PLL_100_10 
    port(POWERDOWN			: in  std_logic;
    	    CLKA 				: in  std_logic;  
    	    LOCK	 			: out std_logic;
    	    GLA 				: out std_logic;  
         OADIVRST 			: in  std_logic
         );
end component;

--RTC Calendar application
component RTC_calendar
	port(SYS_RESET 			: in  std_logic; 
		 SYS_CLOCK 			: in  std_logic;     -- ACM clock - 10Mhz
		 INIT_DONE 			: in  std_logic;     -- this module is active when Init_done = '1'
		 POWER_down			: in  std_logic;	 -- assume async to 10Mhz clock	
	   	 clk1hz				: in  std_logic;	
         ACMRDATA    		: in  std_logic_vector(7 downto 0);
         ACMADDR			: out std_logic_vector(7 downto 0);
         ACMWDATA  			: out std_logic_vector(7 downto 0);
	     ACMWEN				: out std_logic; 
		 LOAD_rtc			: in  std_logic;	 -- assume async to 10Mhz clock   		 
	     LOAD_year			: in  std_logic_vector(7 downto 0);
	     LOAD_month			: in  std_logic_vector(7 downto 0);
	     LOAD_date			: in  std_logic_vector(7 downto 0);
	     LOAD_day			: in  std_logic_vector(7 downto 0);
	     LOAD_hours			: in  std_logic_vector(7 downto 0);
	     LOAD_minutes		: in  std_logic_vector(7 downto 0);
	     LOAD_seconds		: in  std_logic_vector(7 downto 0);
	     RTC_act			: out std_logic;	
--	     toggle			: out std_logic;	     	     	     
	     RTC_year			: out std_logic_vector(7 downto 0);
	     RTC_month			: out std_logic_vector(7 downto 0);
	     RTC_date			: out std_logic_vector(7 downto 0);
	     RTC_day			: out std_logic_vector(7 downto 0);
	     RTC_hours			: out std_logic_vector(7 downto 0);
	     RTC_minutes		: out std_logic_vector(7 downto 0);
	     RTC_seconds		: out std_logic_vector(7 downto 0)	     	     	     	     	            
          );
end component;

--Crystal Oscillator
component XTAL_RTC
    port( XTL 				: in  std_logic; 
    		CLKOUT			: out std_logic; 
    		CLKOUTINT 		: out std_logic; 
        	SELMODE			: in  std_logic;
        	RTC_MODE0		: in  std_logic;
        	RTC_MODE1 		: in  std_logic
        	);   
end component;        	

--Flash Memory System
component NVM_analog
    port(	INIT_CLK			: in  std_logic; 
    		SYS_RESET			: in  std_logic; 
    		INIT_POWER_UP 		: in  std_logic; 
        	INIT_DONE 			: out std_logic; 
        	INIT_DATA 			: out std_logic_vector(8 downto 0); 
        	INIT_ADDR 			: out std_logic_vector(8 downto 0); 
        	INIT_ACM_RTC_WEN	: out std_logic;
        	INIT_ACM_WEN		: out std_logic;
        	INIT_ASSC_WEN		: out std_logic;
        	INIT_EV_WEN			: out std_logic;
        	INIT_TR_WEN 		: out std_logic
        	);
end component;

--RTC Analog System
component Analog_RTC
    port(	SYS_CLK				: in  std_logic; 
    		SYS_RESET 			: in  std_logic; 
    		VAREF 				: inout std_logic := 'Z'; 
    		DATAVALID			: out std_logic;
    		ASSC_DONE			: out std_logic;
    		ASSC_WAIT			: out std_logic;
        	ASSC_CHSAT			: out std_logic;
        	ASSC_CHLATD 		: out std_logic; 
        	INIT_ADDR 			: in  std_logic_vector(8 downto 0); 
        	INIT_DATA 			: in  std_logic_vector(8 downto 0); 
        	INIT_ACM_WEN		: in  std_logic;
        	INIT_ACM_RTC_WEN	: in  std_logic; 
        	INIT_ASSC_WEN		: in  std_logic;
        	INIT_EV_WEN			: in  std_logic;
        	INIT_TR_WEN			: in  std_logic;
        	INIT_DONE			: in  std_logic;
        	ACMCLK 				: in  std_logic; 
        	ACMRDATA_I 			: out std_logic_vector(7 downto 0); 
        	RTCCLK 				: in  std_logic; 
        	RTCXTLSEL 			: out std_logic; 
        	RTCXTLMODE_I 		: out std_logic_vector(1 downto 0); 
        	RTCMATCH			: out std_logic;
        	RTCPSMMATCH 		: out std_logic
        	);
end component;

--LCD Display Driver
component LCD_DIS
	port(CLK 					: in std_logic;
	    	RS_LCD 				: out std_logic;
	    	DATA_LCD 			: out std_logic_vector(7 downto 4);
	    	EN_LCD 				: out std_logic;
	    	R_nW_LCD 			: out std_logic;
	    	SW2      			: in std_logic;                   
		RTC_year				: in std_logic_vector(7 downto 0);
	     RTC_month				: in std_logic_vector(7 downto 0);
	     RTC_date				: in std_logic_vector(7 downto 0);
		RTC_hours				: in std_logic_vector(7 downto 0);
		RTC_minutes				: in std_logic_vector(7 downto 0);
		RTC_seconds				: in std_logic_vector(7 downto 0);	
	    	SW1 				: in std_logic
	     );
end component;

--Voltage Regulator 
component VR_mon
    	port(PUB				: in std_logic;
    		VRPU 				: in std_logic;  
    		FPGAGOOD			: out std_logic;
    		PUCORE 				: out std_logic
    		);
end component;    	

--Shift Register to delay the power off of the FPGA core
--The current data / time data must be stored before the power down of the  FPGA core 
component Shift8_reg 
    	port(Shiften			: in std_logic; 
    		Shiftin				: in std_logic; 
    		Aclr				: in std_logic; 
    		Clock 				: in std_logic;  
    		Shiftout 			: out std_logic
    		);
end component;    		

component clkint
	port (a	: in std_logic;
	      y   : out std_logic
	      );
end component;	 

--signal VCC_net      : std_logic;
--signal LOCK         : std_logic;
signal sys_clk      : std_logic;
signal sys_clk_int  : std_logic;
signal sys_reset_int: std_logic;
signal sys_reset_gl	: std_logic;

signal INIT_ADDR			: std_logic_vector(8 downto 0);
signal INIT_DATA 			: std_logic_vector(8 downto 0);
signal INIT_ADDR_int 		: std_logic_vector(8 downto 0);
signal INIT_DATA_int 		: std_logic_vector(8 downto 0);
signal INIT_DONE_net 		: std_logic;
signal INIT_ACM_WEN, INIT_ASSC_WEN, INIT_EV_WEN, INIT_TR_WEN : std_logic;
signal INIT_ACM_RTC_WEN 		: std_logic;
signal RTCCLK				: std_logic;
signal RTC_year_int			: std_logic_vector(7 downto 0);
signal RTC_month_int		: std_logic_vector(7 downto 0);     
signal RTC_date_int			: std_logic_vector(7 downto 0);  
signal RTC_day_int			: std_logic_vector(7 downto 0);
signal RTC_hours_int		: std_logic_vector(7 downto 0);	     
signal RTC_minutes_int		: std_logic_vector(7 downto 0);    
signal RTC_seconds_int		: std_logic_vector(7 downto 0);     
signal ACMRDATA    			: std_logic_vector(7 downto 0);         
signal ACMADDR				: std_logic_vector(7 downto 0);         
signal ACMWDATA  			: std_logic_vector(7 downto 0);         
signal ACMWEN				: std_logic; 
signal RTC_MODE  			: std_logic_vector(1 downto 0);  
signal SELMODE  			: std_logic;                           
signal NVM_ACM_WEN 			: std_logic; 
signal count	  			: std_logic_vector(7 downto 0);
signal RTCcount  			: std_logic_vector(15 downto 0);
signal RTCCLK_c			: std_logic; 
signal SW1_int				: std_logic;  
signal SW2_int				: std_logic; 
signal PWR_dwn				: std_logic;

begin

	 INIT_DONE		<= INIT_DONE_net;
	 ACM_CLK		<= sys_clk_int;
	 RTC_year		<= RTC_year_int;		     
     RTC_month		<= RTC_month_int;	
     RTC_date		<= RTC_date_int;  
	 RTC_day		<= RTC_day_int;		     
     RTC_hours		<= RTC_hours_int;	     
     RTC_minutes	<= RTC_minutes_int;      
     RTC_seconds	<= RTC_seconds_int;		 
     RTCCLK_out		<= RTCCLK_c;
 
-- RC oscillator generate the 100MHz clock
-- The 100 MHz clock is connected to the input of the PLL
RC_osc : RCO port map
		(CLKOUT 			=> sys_clk
		);
-- PLL takes the 100MHz clock from the RC oscillator 
-- to generate the 10MHz system clock
PLL_acm : PLL_100_10 port map
    		(POWERDOWN		=> '1',	     
    	     CLKA 			=> sys_clk, 		
    	     LOCK	 		=> open ,	 	     
    	     GLA 			=> sys_clk_int, 		     
             OADIVRST 		=> sys_reset_gl 	     
          );
          
	sys_reset_int	<= not sys_reset;
reset : clkint port map (sys_reset_int, sys_reset_gl);

-- Voltage Regulator
Vreg : VR_mon port map
	    (	PUB				=> PUB,		
    		VRPU 			=> PWR_dwn, 	
    		FPGAGOOD		=> FPGAGOOD,	
    		PUCORE 			=> PUCORE 	
    		);

-- Shift Register to delay the PUB signal
sreg8 :  Shift8_reg port map
    	    (Shiften			=> '1',
    		Shiftin			=> POWER_down,
    		Aclr			=> sys_reset_gl,
    		Clock 			=> sys_clk_int,
    		Shiftout 		=> PWR_dwn
    		);

RTC_cal : RTC_calendar port map
		( SYS_RESET 		=> sys_reset_gl, 		
		  SYS_CLOCK 		=> sys_clk_int, 		
		  INIT_DONE 		=> INIT_DONE_net, 		
		  POWER_down		=> POWER_down,		
		  clk1hz			=> RTCcount(14),
          ACMRDATA    		=> ACMRDATA,    		
          ACMADDR			=> ACMADDR,			
          ACMWDATA  		=> ACMWDATA,  		
	      ACMWEN			=> ACMWEN,			
		  LOAD_rtc			=> '0',	  	
	      LOAD_year			=> x"06", -- Default setting of the time and date info     
	      LOAD_month		=> x"02", 
	      LOAD_date			=> x"28",      
	      LOAD_day			=> x"02", 	
	      LOAD_hours		=> x"71", 
	      LOAD_minutes		=> x"59", 		
	      LOAD_seconds		=> x"45", 
	      RTC_act			=> RTC_act,
--	      toggle			=> toggle,
	      RTC_year			=> RTC_year_int,			
	      RTC_month			=> RTC_month_int,		     
	      RTC_date			=> RTC_date_int,			
	      RTC_day			=> RTC_day_int,			
	      RTC_hours			=> RTC_hours_int,		     
	      RTC_minutes		=> RTC_minutes_int,		
	      RTC_seconds		=> RTC_seconds_int		 	            
           );
           
	SW1_int 	<= SW1;     
	SW2_int	<= SW2;      
	
LCD_DIS_inst: LCD_DIS port map
	     (	 CLK 			=> sys_clk_int,
    		 RS_LCD 		=> RS_LCD,
    		 DATA_LCD 		=> DATA_LCD,
    		 EN_LCD 		=> EN_LCD,
    		 R_nW_LCD 		=> R_nW_LCD, 
    		 SW2      		=> SW2_int,      	
    		 RTC_year		=> RTC_year_int,	
    		 RTC_month		=> RTC_month_int,	
    		 RTC_date		=> RTC_date_int, 
    		 RTC_hours		=> RTC_hours_int,	
    		 RTC_minutes	=> RTC_minutes_int,
    		 RTC_seconds	=> RTC_seconds_int,
    		 SW1 			=> SW1_int
		 );           

XTALRTC : XTAL_RTC port map
    		(XTL 			=> XTAL1, 		     
    		 CLKOUT			=> RTCCLK,		
    		 CLKOUTINT 		=> RTCCLK_c,      
        	 SELMODE		=> SELMODE,		
        	 RTC_MODE0		=> RTC_MODE(0),	     
        	 RTC_MODE1 		=> RTC_MODE(1)      
        	 );       
   
--Debugging Counter
	process (RTCCLK_c, sys_reset_gl) 
	begin
		if (sys_reset_gl = '0') then
			RTCcount	<= x"0000";
		elsif rising_edge(RTCCLK_c) then
			RTCcount	<= RTCcount + 1;
		end if;
	end process;
	
	clk1hz	<= RTCcount(14);
	        	    	

NVManalog : NVM_analog  port map
    		(INIT_CLK			=> sys_clk_int,			
    		 SYS_RESET			=> sys_reset_gl,		     
    		 INIT_POWER_UP		=> '1',	     
        	 INIT_DONE 			=> INIT_DONE_net, 		
        	 INIT_DATA 			=> INIT_DATA_int, 		
        	 INIT_ADDR 			=> INIT_ADDR_int, 		
        	 INIT_ACM_RTC_WEN	=> INIT_ACM_RTC_WEN,	
        	 INIT_ACM_WEN		=> NVM_ACM_WEN,		
        	 INIT_ASSC_WEN		=> INIT_ASSC_WEN,		
        	 INIT_EV_WEN		=> INIT_EV_WEN,		
        	 INIT_TR_WEN 		=> INIT_TR_WEN 		
        	 );

AnalogRTC : Analog_RTC port map
    		(SYS_CLK			=> sys_clk_int,
    		 SYS_RESET 			=> sys_reset_gl,
    		 VAREF 				=> VAREF,
    		 DATAVALID			=> DATAVALID,
    		 ASSC_DONE			=> ASSC_DONE,
    		 ASSC_WAIT			=> open ,
        	 ASSC_CHSAT			=> ASSC_CHSAT,
        	 ASSC_CHLATD 		=> ASSC_CHLATD,
        	 INIT_ADDR 			=> INIT_ADDR,
        	 INIT_DATA 			=> INIT_DATA,
        	 INIT_ACM_WEN		=> INIT_ACM_WEN,
        	 INIT_ACM_RTC_WEN	=> '0',   --INIT_ACM_RTC_WEN,  -- '0', --
        	 INIT_ASSC_WEN		=> INIT_ASSC_WEN,
        	 INIT_EV_WEN		=> INIT_EV_WEN,
        	 INIT_TR_WEN		=> INIT_TR_WEN,
        	 INIT_DONE		     => INIT_DONE_net,
        	 
        	 ACMCLK 			=> SYS_CLK_int, 	     
        	 ACMRDATA_I 		=> ACMRDATA, 	     
        	 RTCCLK 			=> RTCCLK, 	          
        	 RTCXTLSEL 			=> SELMODE, 	     
        	 RTCXTLMODE_I 		=> RTC_MODE,       
        	 RTCMATCH			=> open ,               
        	 RTCPSMMATCH 		=> open 	          
        	);

	process (INIT_DONE_net, INIT_ADDR_int, INIT_DATA_int, 
		    ACMADDR, ACMWDATA, ACMWEN, NVM_ACM_WEN)
	begin	    
		if (INIT_DONE_net = '0') then
			init_data		<= INIT_DATA_int;
			init_addr		<= INIT_ADDR_int;	
			init_acm_wen	<= '0';   --NVM_ACM_WEN;
		else 
			init_acm_wen	<= ACMWEN;
			init_data		<= '0' & ACMWDATA;
			init_addr		<= '0' & ACMADDR;	
		end if;
	end process;
	
	process (SYS_CLK_int, sys_reset_gl) 
	begin
		if (sys_reset_gl = '0') then
			count	<= x"00";
		elsif rising_edge(SYS_CLK_int) then
			count <= count + 1;
		end if;
	end process;
	
	clk_78khz	<= count(6);					
    
end DEF_ARCH;