----------------------------------------------------------------------------------
-- マルツ電子株式会社
--
-- 　　　　【MFPGA-BASE】　　FPGAトレーニング用学習ベースボード 
-- 
-- 　　　　　　機能検証用　サンプルコード
--
-- 設計言語	: VHDL言語
-- FPGA名	: 米国ザイリンクス社　XC3S250E-VQ100
-- 設計日	: 2009年2月14日
-- 提供日	: 2009年4月10日
-- バージョン	: 1.0.0
--
----------------------------------------------------------------------------------
-- Description: 
--
--		PUSH Switch clock synchronizer.
--		- 128Clock cycle SWITCH input masking function.
--		- L->H or H->L edge trigger detect.
--
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Module_PUSHsw_sync is
	port (
		SysCLK_in		: in	std_logic ;
		SysRST_in		: in	std_logic ;
		
		PUSHSW_in		: in	std_logic ;
		PUSHSW_porarity	: in	std_logic ;							-- 1 : Active-H, 0 : Active-L
		
	--********--
		PUSHSW_out		: out	std_logic ;
		PUSHSW_H_edge	: out	std_logic ;
		PUSHSW_L_edge	: out	std_logic
	) ;
end Module_PUSHsw_sync ;

architecture Behavioral of Module_PUSHsw_sync is

	signal	wire_PUSHSW			: std_logic ;

	signal	reg_PUSHSW_sync		: std_logic_vector(3 downto 0) ;
	signal	reg_MASK_counter	: std_logic_vector(6 downto 0) ;		-- 0 to 127
	signal	reg_MASK_cnt_enb	: std_logic ;

begin

--********************************************************--
	wire_PUSHSW	<= PUSHSW_in when ( PUSHSW_porarity = '1' ) else not PUSHSW_in ;		-- XNOR operation

SWITCH_sync	: process ( SysCLK_in )
begin
	if ( SysCLK_in = '1' and SysCLK_in'event ) then
		if ( SysRST_in = '1' ) then
			reg_PUSHSW_sync <= ( others => '0' ) ;
		else
			reg_PUSHSW_sync <= reg_PUSHSW_sync(2 downto 0) & wire_PUSHSW ;
		end if ;
	end if ;
end process ;

SWITCH_mask	: process ( SysCLK_in )
begin
	if ( SysCLK_in = '1' and SysCLK_in'event ) then
		if ( SysRST_in = '1' ) then
			reg_MASK_cnt_enb <= '0' ;
			reg_MASK_counter <= ( others => '0' ) ;
		else
			if ( reg_MASK_counter = "1111111" ) then				-- If counter is full
				reg_MASK_cnt_enb <= '0' ;							-- Reset counter enable flag to 0.
			else
				if (												-- If switch edge is detected.
					( reg_PUSHSW_sync(3) = '1' and reg_PUSHSW_sync(2) = '0' ) or	-- H->L
					( reg_PUSHSW_sync(3) = '0' and reg_PUSHSW_sync(2) = '1' )		-- L->H
				) then
					reg_MASK_cnt_enb <= '1' ;						-- Set counter enable flag to 1.
				end if ;
			end if ;
			
			if ( reg_MASK_cnt_enb = '1' ) then						-- If ENABLE signal is setted.
				reg_MASK_counter <= reg_MASK_counter + 1 ;			-- Counter UP
			else
				reg_MASK_counter <= ( others => '0' ) ;				-- Counter clear
			end if ;
		end if ;
	end if ;
end process ;

--********************************************************--
STATUS_out	: process ( SysCLK_in )
begin
	if ( SysCLK_in = '1' and SysCLK_in'event ) then
		if ( SysRST_in = '1' ) then
			PUSHSW_out		<= '0' ;
			PUSHSW_H_edge	<= '0' ;
			PUSHSW_L_edge	<= '0' ;
		else
		--********--
			if ( reg_PUSHSW_sync = "1111" ) then
				PUSHSW_out	<= '1' ;
			else	
				PUSHSW_out	<= '0' ;
			end if ;
		--********--
			if ( reg_MASK_cnt_enb = '0' ) then
				if ( reg_PUSHSW_sync(3 downto 2) = "01" ) then
					PUSHSW_H_edge	<= '1' ;
				end if ;
				if ( reg_PUSHSW_sync(3 downto 2) = "10" ) then
					PUSHSW_L_edge	<= '1' ;
				end if ;
			else
				PUSHSW_H_edge	<= '0' ;
				PUSHSW_L_edge	<= '0' ;
			end if ;
		end if ;
	end if ;
end process ;




end Behavioral;

