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

ENTITY testbench_symtericPWM IS
END;

ARCHITECTURE Behavioral OF testbench_symtericPWM IS

	CONSTANT clock_period: 	delay_length := 20 ns;	--! Clock period of system CLK (50MHz)

	SIGNAL SYSCLK			:	std_logic := '0'; --! system clock signal
	
	SIGNAL EPWMXA			:	std_logic := '0'; --! ePWM output A and B
	SIGNAL EPWMXB			:	std_logic := '0'; --! ePWM output A and B
	SIGNAL EPWMxSOCA		: 	std_logic := '0'; --! ePWM SOC pulse output A
	SIGNAL EPWMxSOCB		: 	std_logic := '0'; --! ePWM SOC pulse output B
	SIGNAL EPWMxINTn		: 	std_logic := '0'; --! ePWM ET interrupt pulse
	SIGNAL EPWMxSYNCI		:	std_logic := '0';
	SIGNAL EPWMxSYNCO		:	std_logic := '0';
	
	SIGNAL TBCTL			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL TBPRD			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL TBPHS			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL TBCTR			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	
	SIGNAL CMPCTL			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL CMPA				:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL CMPB				:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	
	SIGNAL AQCTLA			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL AQCTLB			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	
	SIGNAL DBCTL			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL DBRED			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL DBFED			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	
BEGIN

	--! clock signal generation
	
	clock_process: PROCESS 
	BEGIN
		SYSCLK <= NOT SYSCLK;
      WAIT FOR clock_period/2;
	END PROCESS;
	
	--! device under test
	
	NA: ENTITY work.ePWM PORT MAP(	SYSCLK 		=> SYSCLK, 
												EPWMXA 		=> EPWMXA, 
												EPWMXB 		=> EPWMXB, 
												TBCTL 		=> TBCTL,
												TBSTS 		=>	open,
												TBPHS 		=> TBPHS, 
												TBCTR 		=> TBCTR, 
												TBPRD 		=> TBPRD,
												CMPCTL 		=> CMPCTL, 
												CMPA 			=> CMPA, 
												CMPB 			=> CMPB,
												AQCTLA 		=> AQCTLA, 
												AQCTLB 		=> AQCTLB, 
												DBCTL 		=> DBCTL, 
												DBRED 		=> DBRED, 
												DBFED 		=> DBFED,
												TZSEL 		=> "0000000000000000", 
												TZCTL 		=> "0000000000001111", 
												TZEINT 		=>	"0000000000000000", 
												TZFLG 		=> open, 
												TZCLR		 	=> "0000000000000000", 
												TZFRC 		=> "0000000000000110",
												ETSEL 		=> "1100110000001100", 
												--ETPS 			=> "0011111100000000", 
												ETFLG 		=> open,
												ETCLR 		=> "0000000000000000", 
												ETFRC 		=> "0000000000001101", 
												PCCTL 		=> "0000000000000000", -- 0000001111100001											
												TZ 			=> "000000",
												EPWMxSYNCI 	=> EPWMxSYNCI, 
												EPWMxSYNCO 	=> EPWMxSYNCO,
												EPWMxSOCA 	=> EPWMxSOCA,
												EPWMxSOCB 	=> EPWMxSOCB,
												EPWMxINTn 	=> EPWMxINTn);
												
	--! testbench sequence

	main_sequence: PROCESS
	
	BEGIN
	
		WAIT FOR 100 us;	-- power up and wait for 100 us
		
      assert ((EPWMXA = '0') AND (EPWMXB = '0'))	-- expecting both EPWM signals at log 0

      report "EPWMXA a EPWMXB nejsou po startu v log. 0!" severity error;	-- if not report error
	
		-- registers initialization
	
/*		
   bit 15-14   FREE,SOFT = 11   ; 11 => nezastavovat casovou zakladnu pri emulaci
   bit 13      PHSDIR    = 0    ; 0 => v up-down rezimu citat po synchronizaci smerem dolu
   bit 12-10   CLKDIV    = 000  ; TBCLK = SYSCLKOUT / (2*"HSPCLKDIV" * 2^CLKDIV)
   bit 9-7     HSPCLKDIV = 000  ; TBCLK = SYSCLKOUT / (2*"HSPCLKDIV" * 2^CLKDIV)
   bit 6       SWFSYNC   = 0    ; zapis jednicky by pri PHSEN=1 vyvolal softwarovou synchronizaci
   bit 5-4     SYNCOSEL  = 11   ; 11 => signal EWMxSYNCO zakazan
   bit 3       PRDLD     = 0    ; 0  => perioda casove zakladny pres stinovy registr (kopiruje se pri TBCTR=0)
   bit 2       PHSEN     = 0    ; 0  => ignorovat synchronizaci (EPWMxSYNCI nebo softwarovou synchronizace).
   bit 1-0     CTRMODE   = 10   ; 10 => timer UP/DOWN
*/	 
		TBCTL 	<= x"c032";
		
/*
	frekvence clk = 50 MHz
	frekvence pwm = 10 kHz
	musime pomer delit dvemi kvuli symetricke pwm - CTRMODE = UP/DOWN
	(50 000 000 / 10 000)/2 = 2500 = 0x09c4
*/		
		TBPRD 	<= x"09c4";
		
/*
	fazi neposouvame
*/		
		TBPHS 	<= x"0000";
		
/*
   bit 11-10     00:     CBD, 00 = do nothing
   bit 9-8       00:     CBU, 00 = do nothing
   bit 7-6       01:     CAD, 01 = clear
   bit 5-4       10:     CAU, 10 = set
   bit 3-2       00:     PRD, 00 = do nothing
   bit 1-0       00:     ZRO, 01 = clear	
*/		
		AQCTLA 	<= x"0061";
		AQCTLB 	<= x"0000";
/*		
   bit 15-6      0's:    reserved
   bit 5-4       00:     IN_MODE, 00 = EPWMxA is source EPWM1A & EPWM1B
   bit 3-2       10:     POLSEL, 10 = channel B output is inverted
   bit 1-0       11:     OUT_MODE, 11 = delay on A input, delay on B input (rising & falling edge!)		
*/		
		DBCTL 	<= x"000b";
		
/* t_dead = 3.5 us (3500ns/20ns = 175 clk = 0x00af)*/
		
		DBRED 	<= x"00af";  	
		DBFED 	<= x"00af";

		CMPCTL	<= x"0000";
		
		CMPA 		<= x"0000";		-- change duty cycle 0%
		CMPB 		<= x"0001";		-- must contain different value than CMPA because of priority in Action Qualifier (described in sprug04a)
		
		WAIT FOR 110 us;			-- wait for 1 period and 10 us to test shadow register
		
		CMPA 		<= x"0271";		-- change duty cycle to 25%
		
		WAIT FOR 200 us;
		
		CMPA 		<= x"04e2";		-- change duty cycle to 50%

		WAIT FOR 200 us;
		
		CMPA 		<= x"0753";		-- change duty cycle to 75%

		WAIT FOR 200 us;
		
		CMPA 		<= x"09c4";		-- change duty cycle to 100%

		WAIT;
	
	END PROCESS;
												
END Behavioral;