LIBRARY ieee;
USE ieee.std_logic_1164. all;
USE ieee.numeric_std.all;
 
ENTITY trip_zone IS

	PORT (
    TBCLK		: 	IN std_logic; -- prescaled clock from timebase
	 
	 EPWMXA_IN	: 	IN std_logic; -- pwm A in
	 EPWMXB_IN	:	IN std_logic; -- pwm B in
	 TZ			:	IN std_logic_vector(5 DOWNTO 0); -- trip inputs

	 TZSEL_CBC	:	IN std_logic_vector(5 DOWNTO 0); -- cbc trip source select
	 TZSEL_OSHT	:	IN std_logic_vector(5 DOWNTO 0); -- one shot trip source select
	 
	 TZA			:	IN std_logic_vector(1 DOWNTO 0); -- TZA logic select
	 TZB			:	IN std_logic_vector(1 DOWNTO 0); -- TZB logic select	 
	 
	 CTR_ZERO	: 	IN std_logic; -- cnt equal 0

	 TZEINT_CBC	:	IN std_logic; -- trip zone one shot reset 
	 TZEINT_OST	:	IN std_logic; -- trip zone one shot reset
	 
	 TZFLG_CBC	:  OUT std_logic;
	 TZFLG_OST	:  OUT std_logic;
	 TZFLG_INT	:	OUT std_logic;
	 
	 TZCLR_CBC	:	IN std_logic; -- trip zone one shot reset 	 
	 TZCLR_OST	:	IN std_logic; -- trip zone one shot reset
	 TZCLR_INT	:	IN std_logic;
	 
	 TZFRC_CBC	:	IN std_logic; -- trip zone one shot interrupt enable
	 TZFRC_OSHT :  IN std_logic; -- trip zone cycle by cycle interrupt enable	 
	 
	 EPWMXA_OUT	: 	OUT std_logic; -- pwm A out
	 EPWMXB_OUT	:	OUT std_logic; -- pwm B out	 
	 EPWMXTZINT	:	OUT std_logic	 
	);
END trip_zone;
 

ARCHITECTURE Behavioral OF trip_zone IS
	
	SIGNAL CBC_SIG 	: std_logic_vector(5 DOWNTO 0);
	SIGNAL OSHT_SIG 	: std_logic_vector(5 DOWNTO 0);
	
	SIGNAL CBC_SYNC 	: std_logic;
	SIGNAL OSHT_SYNC 	: std_logic;
	
	SIGNAL CBC_SET		: std_logic;
	SIGNAL OSHT_SET	: std_logic;
	
	SIGNAL CBC_EVENT	: std_logic;
	SIGNAL OSHT_EVENT	: std_logic;	
	
	SIGNAL TZINT_CBC	: std_logic;	
	SIGNAL TZINT_OST	: std_logic;	
	SIGNAL TZINT		: std_logic;
	
	SIGNAL iTZFLG_CBC	: std_logic;
	SIGNAL iTZFLG_OST	: std_logic;
	SIGNAL iEPWMXTZINT: std_logic;

BEGIN

	-- cycle by cycle mode

	CBC_SIG(0) <= NOT TZ(0) WHEN TZSEL_CBC(0) = '1' ELSE '0';
	CBC_SIG(1) <= NOT TZ(1) WHEN TZSEL_CBC(1) = '1' ELSE '0';
	CBC_SIG(2) <= NOT TZ(2) WHEN TZSEL_CBC(2) = '1' ELSE '0';
	CBC_SIG(3) <= NOT TZ(3) WHEN TZSEL_CBC(3) = '1' ELSE '0';
	CBC_SIG(4) <= NOT TZ(4) WHEN TZSEL_CBC(4) = '1' ELSE '0';
	CBC_SIG(5) <= NOT TZ(5) WHEN TZSEL_CBC(5) = '1' ELSE '0';
	
	CBC_SYNC <= '0' WHEN CBC_SIG = "000000" ELSE '1';
	CBC_SET <= CBC_SYNC WHEN TZFRC_CBC = '1' ELSE '0';
	
	PROCESS (CBC_SET, CTR_ZERO) IS
	BEGIN
		IF CTR_ZERO = '1' THEN
			CBC_EVENT <= '0';
		ELSIF CBC_EVENT = '1' THEN
			CBC_EVENT <= '1';
		END IF;
	END PROCESS;
	
	PROCESS (TZCLR_CBC, CBC_SET) IS
	BEGIN
		IF (TZCLR_CBC = '1') THEN
			iTZFLG_CBC <= '0';
		ELSIF (CBC_EVENT = '1') THEN
			iTZFLG_CBC <= '1';
		END IF;
		TZFLG_CBC <= iTZFLG_CBC;
	END PROCESS;
	
	
	-- one shot mode
	OSHT_SIG(0) <= NOT TZ(0) WHEN TZSEL_OSHT(0) = '1' ELSE '0';
	OSHT_SIG(1) <= NOT TZ(1) WHEN TZSEL_OSHT(1) = '1' ELSE '0';
	OSHT_SIG(2) <= NOT TZ(2) WHEN TZSEL_OSHT(2) = '1' ELSE '0';
	OSHT_SIG(3) <= NOT TZ(3) WHEN TZSEL_OSHT(3) = '1' ELSE '0';
	OSHT_SIG(4) <= NOT TZ(4) WHEN TZSEL_OSHT(4) = '1' ELSE '0';
	OSHT_SIG(5) <= NOT TZ(5) WHEN TZSEL_OSHT(5) = '1' ELSE '0';
	
	OSHT_SYNC <= '0' WHEN OSHT_SIG = "000000" ELSE '1';
	OSHT_SET <= OSHT_SYNC WHEN TZFRC_OSHT = '1' ELSE '0';

	PROCESS (OSHT_SET, TZCLR_OST) IS
	BEGIN
		IF (TZCLR_OST = '1') THEN
			OSHT_EVENT <= '0';
		ELSIF (OSHT_SET = '1') THEN
			OSHT_EVENT <= '1';
		END IF;
	END PROCESS;
	
	PROCESS (TZCLR_OST, CBC_SET) IS
	BEGIN
		IF (TZCLR_OST = '1') THEN
			iTZFLG_OST <= '0';
		ELSIF (OSHT_EVENT = '1') THEN
			iTZFLG_OST <= '1';
		END IF;
		TZFLG_OST <= iTZFLG_OST;
	END PROCESS;
	
	
	-- interrupt logic

	TZINT_CBC 	<= iTZFLG_CBC WHEN TZEINT_CBC = '1' ELSE '0';
	TZINT_OST	<=	iTZFLG_OST WHEN TZEINT_OST = '1' ELSE '0';
	TZINT			<=	TZINT_CBC OR TZINT_OST;
	
	-- interrupt pulse generation
	PROCESS (TBCLK, TZINT) IS
	VARIABLE	cnt	:	unsigned(10 DOWNTO 0)	:= (OTHERS => '0');
	BEGIN
		IF rising_edge (TBCLK) THEN
			IF (TZINT = '0') THEN
				cnt	:=	(OTHERS => '0');
				iEPWMXTZINT	<= '0';
			ELSIF	cnt = "1111111111" THEN
				iEPWMXTZINT	<= '0';
			ELSE
				cnt	:=	cnt + 1;
				iEPWMXTZINT	<= '1';
			END IF;
		END IF;
		EPWMXTZINT <= iEPWMXTZINT;
	END PROCESS;
	
	PROCESS (iEPWMXTZINT, TZCLR_INT) IS
	BEGIN
		IF (TZCLR_INT = '1') THEN
			TZFLG_INT <= '0';
		ELSIF (iEPWMXTZINT = '1') THEN
			TZFLG_INT <= '1';
		END IF;
	END PROCESS;	
	
	-- trip zone logic
	PROCESS (TZA, TZB, CBC_EVENT, OSHT_EVENT, EPWMXA_IN, EPWMXB_IN) IS
	BEGIN
		IF (CBC_EVENT = '1' OR OSHT_EVENT = '1') THEN
			CASE TZA IS		
				WHEN "00" => 	EPWMXA_OUT <= 'Z';								
				WHEN "01" => 	EPWMXA_OUT <= '1';								
				WHEN "10" => 	EPWMXA_OUT <= '0';
				WHEN OTHERS => EPWMXA_OUT <= EPWMXA_IN;
			END CASE;
			CASE TZB IS	
				WHEN "00" => 	EPWMXB_OUT <= 'Z';						
				WHEN "01" => 	EPWMXB_OUT <= '1';					
				WHEN "10" => 	EPWMXB_OUT <= '0';
				WHEN OTHERS => EPWMXB_OUT <= EPWMXB_IN;
			END CASE;
		ELSE
			EPWMXA_OUT <= EPWMXA_IN;
			EPWMXB_OUT <= EPWMXB_IN;
		END IF;
	END PROCESS;
	
	
END Behavioral;