--=================================================================================================
-- File Name                           : hall_interface_tb.vhd

-- Description                         : This module implements the test environment for
--                                       hall interface block

-- Targeted device                     : Microsemi-SoC
-- Author                              : India Solutions Team
--
-- SVN Revision Information            :
-- SVN $Revision                       :
-- SVN $Date                           :
--
-- COPYRIGHT 2015 BY MICROSEMI
-- THE INFORMATION CONTAINED IN THIS DOCUMENT IS SUBJECT TO LICENSING RESTRICTIONS FROM MICROSEMI
-- CORP. IF YOU ARE NOT IN POSSESSION OF WRITTEN AUTHORIZATION FROM MICROSEMI FOR USE OF THIS
-- FILE, THEN THE FILE SHOULD BE IMMEDIATELY DESTROYED AND NO BACK-UP OF THE FILE SHOULD BE MADE.
--
--=================================================================================================
--=================================================================================================
-- Libraries
--=================================================================================================
library ieee;
use ieee.std_logic_1164.all;
USE IEEE.std_logic_unsigned.ALL      ;
USE IEEE.STD_LOGIC_ARITH.ALL; 

--=================================================================================================
-- hall_interface_tb entity declaration
--=================================================================================================

ENTITY hall_interface_tb IS
END hall_interface_tb;


--=================================================================================================
-- encoder_interface_tb architecture body
--=================================================================================================

ARCHITECTURE behavioral OF hall_interface_tb IS
--=================================================================================================
-- Signal declarations
--=================================================================================================

    CONSTANT SYSCLK_PERIOD      : TIME := 10 ns;
    
    SIGNAL SYSCLK               : STD_LOGIC := '0';
    SIGNAL NSYSRESET            : STD_LOGIC := '0';
	SIGNAL hall_timer           : STD_LOGIC_VECTOR(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL hall_timer_match     : STD_LOGIC_VECTOR(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL hall_sig_gen_cnt     : STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0');
	SIGNAL hall_timer_flag      : STD_LOGIC := '0';
	SIGNAL hall_sig_gen_flag    : STD_LOGIC := '0';
	SIGNAL ha_s 			    : STD_LOGIC := '0';
	SIGNAL hb_s 			    : STD_LOGIC := '0';
	SIGNAL hc_s 			    : STD_LOGIC := '0';
	SIGNAL run_hall			    : STD_LOGIC := '0';
	SIGNAL s_hall_sensor_pol	: STD_LOGIC := '1';
	SIGNAL s_direction          : STD_LOGIC := '0';
	SIGNAL s_motor_stopped      : STD_LOGIC := '0';
	SIGNAL s_speed_factor       : STD_LOGIC_VECTOR(17 DOWNTO 0) := (OTHERS => '0');
	SIGNAL theta_buff_s         : STD_LOGIC_VECTOR(12 DOWNTO 0) := (OTHERS => '0');
	SIGNAL hall_cnt_buff        : STD_LOGIC_VECTOR(17 DOWNTO 0) := (OTHERS => '0');
	SIGNAL hall_count_s         : STD_LOGIC_VECTOR(17 DOWNTO 0) := (OTHERS => '0');
	SIGNAL omega_out_s          : STD_LOGIC_VECTOR(17 DOWNTO 0) := (OTHERS => '0');
	SIGNAL theta_output_s       : STD_LOGIC_VECTOR(17 DOWNTO 0) := (OTHERS => '0');
	SIGNAL theta_out_s          : STD_LOGIC_VECTOR(12 DOWNTO 0) := (OTHERS => '0');
	SIGNAL s_fil_factor         : STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0');
	
    COMPONENT hall_interface
    -- ports
    port( 
    -- System reset
    reset_i                                   : IN  STD_LOGIC;
	
    -- System clock
    sys_clk_i                                 : IN  STD_LOGIC;
	
	-- Hall input A
    ha_i									  : IN  STD_LOGIC;
	
	-- Hall input B
    hb_i                                      : IN  STD_LOGIC;
	
	-- Hall input C
	hc_i                                      : IN  STD_LOGIC;

    --Filter trigger
	fil_trig_i                                : IN  STD_LOGIC;

    --Clear buffer
	clear_buffer_i                            : IN  STD_LOGIC;
	    
    --Filter Factor
    filter_factor_i						      : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

	-- Data input for hall sensor active high (1) or low (0)
	hall_sensor_pol_i                         : IN STD_LOGIC;

    -- Speed Factor Multiplier
    speed_factor_i  						  : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
	
	-- Data output indicating motor speed computation complete
    omega_done_o                              : OUT STD_LOGIC;

    -- Data output indicating motor speed
    omega_out_o                               : OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
	
	-- Data output indicating raw rotor angle from hall
	angle_out_raw_o                           : OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
	
	-- Data output representing 
	theta_output_o							  : OUT STD_LOGIC_VECTOR(17 DOWNTO 0) 		                               
        );
    END COMPONENT;

BEGIN
--------------------------------------------------------------------------
-- Name       : MAIN
-- Description: Process provides various test inputs
--------------------------------------------------------------------------
MAIN:
    PROCESS
        VARIABLE vhdl_initial : BOOLEAN := TRUE;

    BEGIN
        IF ( vhdl_initial ) THEN
            -- Assert Reset
            REPORT("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            REPORT(">>>>>>>>                     HALL INTERFACE SIMULATION                              <<<<<<<");
            REPORT("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            NSYSRESET <= '0';
            s_motor_stopped <= '1';
			s_hall_sensor_pol <= '1';
			s_direction <= '0';
			s_speed_factor <= "00"&x"0FFF";
			s_fil_factor <= x"6";
			hall_timer_match <= x"FFFF";
            WAIT FOR ( SYSCLK_PERIOD * 10 );
            NSYSRESET <= '1';
			run_hall <= '1';
            s_motor_stopped <= '0';
			s_hall_sensor_pol <= '1';
			s_direction <= '0';
			s_speed_factor <= "00"&x"1000";
			s_fil_factor <= x"6";
			hall_timer_match <= x"8FFF";
             WAIT FOR ( 150 ms );
            REPORT("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            REPORT("<<<<          END OF HALL INTERFACE IP SIMULATION              >>>>");
            REPORT("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            wait;
        END if;
    END process;
--------------------------------------------------------------------------
-- Name       : CLOCK_GEN
-- Description: Logic generates 10 Mhz clock
--------------------------------------------------------------------------
SYSCLK <= NOT SYSCLK AFTER (SYSCLK_PERIOD / 2.0 );
--------------------------------------------------------------------------
-- Name       : HALL_SIG_GEN_PROC
-- Description: Process generates hall signal states based on 
-------------------------------------------------------------------------- 
HALL_SIG_GEN_PROC:PROCESS(NSYSRESET,SYSCLK)
BEGIN
	IF(NSYSRESET = '0')THEN
		hall_sig_gen_cnt <= (OTHERS => '0');
		hall_sig_gen_flag <= '0';
	ELSIF RISING_EDGE(SYSCLK) THEN
		IF(hall_sig_gen_cnt = x"6")THEN
			hall_sig_gen_cnt <= (OTHERS => '0');
			hall_sig_gen_flag <= '1';
		ELSIF(hall_timer_flag = '1')THEN
			hall_sig_gen_cnt <= hall_sig_gen_cnt + 1;
			hall_sig_gen_flag <= '0';
		END IF;
	END IF;
END PROCESS;

--------------------------------------------------------------------------
-- Name       : HALL_TIMER_PROC
-- Description: Process runs a timer to generate timing pulses for 
--              hall signal generation.
--------------------------------------------------------------------------
HALL_TIMER_PROC:PROCESS(NSYSRESET,SYSCLK)
BEGIN
	IF(NSYSRESET = '0')THEN
		hall_timer <= (OTHERS => '0');
		hall_timer_flag <= '0';
	ELSIF RISING_EDGE(SYSCLK) THEN
		IF(run_hall = '1') THEN
			IF(hall_timer = hall_timer_match)THEN
				hall_timer <= (OTHERS => '0');
				hall_timer_flag <= '1';
			ELSE
				hall_timer <= hall_timer + 1;
				hall_timer_flag <= '0';
			END IF;
		END IF;
	END IF;
END PROCESS;

--------------------------------------------------------------------------
-- Name       : HALL_THETA_GEN_PROC
-- Description: Process generates hall signals based on hall states 
--              and direction.
--------------------------------------------------------------------------   
HALL_THETA_GEN_PROC:PROCESS(hall_sig_gen_cnt)
BEGIN
    IF(s_direction = '0') THEN
		CASE hall_sig_gen_cnt IS
			WHEN "0101"=>ha_s <= '1';
              			 hb_s <= '0';
			             hc_s <= '1';
			WHEN "0100"=>ha_s <= '1';
			             hb_s <= '0';
              			 hc_s <= '0';
			WHEN "0011"=>ha_s <= '1';
              			 hb_s <= '1';
              			 hc_s <= '0';
			WHEN "0010"=>ha_s <= '0';
              			 hb_s <= '1';
              			 hc_s <= '0';
			WHEN "0001"=>ha_s <= '0';
              			 hb_s <= '1';
              			 hc_s <= '1';
			WHEN "0000"=>ha_s <= '0';
              			 hb_s <= '0';
              			 hc_s <= '1';
			WHEN OTHERS=> 
		END CASE;
    ELSE
        CASE hall_sig_gen_cnt IS
			WHEN "0000"=>ha_s <= '1';
              			 hb_s <= '0';
			             hc_s <= '1';
			WHEN "0001"=>ha_s <= '1';
			             hb_s <= '0';
              			 hc_s <= '0';
			WHEN "0010"=>ha_s <= '1';
              			 hb_s <= '1';
              			 hc_s <= '0';
			WHEN "0011"=>ha_s <= '0';
              			 hb_s <= '1';
              			 hc_s <= '0';
			WHEN "0100"=>ha_s <= '0';
              			 hb_s <= '1';
              			 hc_s <= '1';
			WHEN "0101"=>ha_s <= '0';
              			 hb_s <= '0';
              			 hc_s <= '1';
			WHEN OTHERS=> 
		END CASE;
    END IF;
END PROCESS;


--=================================================================================================
-- Component Instantiations
--=================================================================================================
-------------------------------------------------
-- HALL_INTERFACE_UUT_INST
-------------------------------------------------
HALL_INTERFACE_UUT_INST : hall_interface
    PORT MAP( 
        -- Inputs
        reset_i           => NSYSRESET,
        sys_clk_i         => SYSCLK,
        ha_i              => ha_s,
        hb_i              => hb_s,
        hc_i              => hc_s,
        fil_trig_i        => hall_timer_flag,
        filter_factor_i   => s_fil_factor,
        hall_sensor_pol_i => s_hall_sensor_pol,
        speed_factor_i    => s_speed_factor,
        clear_buffer_i    => s_motor_stopped,
        -- Outputs
        omega_done_o      => OPEN,
        omega_out_o       => omega_out_s,
        angle_out_raw_o   => OPEN,
        theta_output_o    => theta_output_s 
        );

END behavioral;
