--=================================================================================================
-- File Name                           : rate_limiter_tb.vhd

-- Description                         : This module implements the test environment for 
--                                       rate_limiter module.

-- Targeted device                     : Microsemi-SoC
-- Author                              : India Solutions Team
--
-- SVN Revision Information            :
-- SVN $Revision                       :
-- SVN $Date                           :
--
-- COPYRIGHT 2016 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 STD.TEXTIO.ALL;
USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE IEEE.STD_LOGIC_SIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;   -- FOR UNIFORM, TRUNC FUNCTIONS
USE WORK.SIM_PKG.ALL;
LIBRARY MODELSIM_LIB;
USE MODELSIM_LIB.UTIL.ALL;
USE WORK.SIM_PKG.ALL;
--=================================================================================================
-- rate_limiter_tb entity declaration
--=================================================================================================

ENTITY rate_limiter_tb IS

END rate_limiter_tb;

--=================================================================================================
-- rate_limiter_tb architecture body
--=================================================================================================
ARCHITECTURE BEHAVIOURAL OF rate_limiter_tb IS

--=================================================================================================
-- Component declarations
--=================================================================================================

COMPONENT rate_limiter IS
PORT (
    reset_i                            : IN  STD_LOGIC;
    sys_clk_i                          : IN  STD_LOGIC;
    start_i                            : IN  STD_LOGIC;
    soft_stop_i                        : IN  STD_LOGIC;
    reset_rl_i                         : IN  STD_LOGIC;
    direction_i                        : IN  STD_LOGIC;
    slew_count_i                       : IN  STD_LOGIC_VECTOR(17 DOWNTO 0);
    rate_count_i                       : IN  STD_LOGIC_VECTOR(17 DOWNTO 0);
    rl_in_i                            : IN  STD_LOGIC_VECTOR(17 DOWNTO 0);
    rl_out_o                           : OUT STD_LOGIC_VECTOR(17 DOWNTO 0);
    rl_done_o                          : OUT STD_LOGIC
);
END COMPONENT;

--=================================================================================================
-- Synthesis Attributes
--=================================================================================================
--NA--

--=================================================================================================
-- Signal declarations
--=================================================================================================
TYPE rate_state IS (IDLE,START,INP_DRIVER,SLEW_COUNT,INT_OUT_COMP,RESET_STATE,OUTPUT_COMPARE);
SIGNAL state                           : rate_state;
CONSTANT SYSCLK_PERIOD                 : TIME   := 10 ns;
CONSTANT g_RESET_STATE                 : INTEGER:= 0;
CONSTANT g_STD_IO_WIDTH                : INTEGER:= 18;
SIGNAL sys_clk_tb                      : STD_LOGIC := '0';
SIGNAL reset_tb                        : STD_LOGIC := '0';
SIGNAL s_reset_tb_dly                  : STD_LOGIC;
SIGNAL s_reset_pul_tb                  : STD_LOGIC;
SIGNAL s_start_tb                      : STD_LOGIC;
SIGNAL s_rl_done_tb                    : STD_LOGIC;
SIGNAL reset                           : STD_LOGIC;
SIGNAL s_rl_done_tb_pul                : STD_LOGIC;
SIGNAL s_rl_done_tb_dly                : STD_LOGIC;
SIGNAL s_soft_stop_tb                  : STD_LOGIC;
SIGNAL s_reset_rl_tb                   : STD_LOGIC;
SIGNAL s_direction_tb                  : STD_LOGIC;
SIGNAL rl_done_out_tb                  : STD_LOGIC;
SIGNAL s_start_rand_tb                 : STD_LOGIC;
SIGNAL counter                         : STD_LOGIC_VECTOR(11 DOWNTO 0);
SIGNAL s_rl_out_tb                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_slew_count_tb                 : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_rate_count_tb                 : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_rl_in_tb                      : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL slew_count_tb                   : STD_LOGIC_VECTOR(g_STD_IO_WIDTH   DOWNTO 0);
SIGNAL out_tb                          : STD_LOGIC_VECTOR(g_STD_IO_WIDTH   DOWNTO 0);
SIGNAL s_ref_tb                        : STD_LOGIC_VECTOR(g_STD_IO_WIDTH   DOWNTO 0);
SIGNAL s_rl_in_ext     				   : STD_LOGIC_VECTOR(g_STD_IO_WIDTH   DOWNTO 0);
SIGNAL s_slew_count_ext				   : STD_LOGIC_VECTOR(g_STD_IO_WIDTH   DOWNTO 0);
SIGNAL s_rate_count_ext				   : STD_LOGIC_VECTOR(g_STD_IO_WIDTH   DOWNTO 0);
SIGNAL s_stim                          : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_stim_slew                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
SIGNAL s_stim_rate                     : STD_LOGIC_VECTOR(g_STD_IO_WIDTH-1 DOWNTO 0);
--========================================================
-- File read operations
--========================================================
--NA--
--========================================================
-- File write operations
--========================================================
--NA--
--========================================================
-- Procedure Declarations
--========================================================
PROCEDURE rate_lim
	(
	SIGNAL reset_tb     		: IN STD_LOGIC;
	SIGNAL sys_clk_tb   		: IN STD_LOGIC;
	SIGNAL start        		: IN STD_LOGIC;
	SIGNAL done          		: IN STD_LOGIC;
	SIGNAL direction      		: IN STD_LOGIC;
	SIGNAL reset_rl      		: IN STD_LOGIC;
	SIGNAL soft_stop    		: IN STD_LOGIC;
	SIGNAL rl_in        		: IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH DOWNTO 0);
	SIGNAL slew_count   		: IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH DOWNTO 0);
	SIGNAL rate_count   		: IN STD_LOGIC_VECTOR(g_STD_IO_WIDTH DOWNTO 0);
	SIGNAL rl_done_out_tb       : INOUT STD_LOGIC;
	SIGNAL slew_count_out_tb    : INOUT STD_LOGIC_VECTOR(g_STD_IO_WIDTH DOWNTO 0);
	SIGNAL s_ref               	: INOUT STD_LOGIC_VECTOR(g_STD_IO_WIDTH DOWNTO 0);
	SIGNAL rl_out_tb         	: INOUT STD_LOGIC_VECTOR(g_STD_IO_WIDTH DOWNTO 0)
	) IS
BEGIN
    IF reset_tb = '0' THEN
        slew_count_out_tb 	<= (OTHERS =>'0');
        rl_out_tb 			<= (OTHERS =>'0');
		rl_done_out_tb 		<= '0';
        s_ref    <= (OTHERS => '0');
    ELSIF RISING_EDGE (sys_clk_tb) THEN
		IF(reset_rl = '1') THEN
			slew_count_out_tb <= (OTHERS => '0');
			rl_out_tb <= (OTHERS => '0');
			rl_done_out_tb <= start;
            s_ref    <= (OTHERS => '0');
        ELSIF(soft_stop = '1') THEN
            s_ref    <= (OTHERS => '0');
            IF(slew_count_out_tb < slew_count) THEN
            	IF (start = '1') THEN
            		slew_count_out_tb  <= slew_count_out_tb + '1' ;
            		rl_done_out_tb     <= '0';
            	END IF;
            ELSE
            	IF(done = '1') THEN
            		slew_count_out_tb <= (OTHERS =>'0');
            		rl_done_out_tb    <= start;
            	END IF;
            END IF;
            
            IF(start = '1') THEN
            	IF(slew_count_out_tb = slew_count-1) THEN
                    IF((s_ref - rl_out_tb) > rate_count) THEN
                        rl_out_tb  <= rl_out_tb + rate_count ;
                        ELSIF(((NOT(s_ref) + '1') - rl_out_tb) < (NOT(rate_count) + '1')) THEN
                        rl_out_tb  <= rl_out_tb - rate_count ;
                    ELSE
                        IF(direction = '1') THEN
                            rl_out_tb  <= s_ref;
                        ELSE
                            rl_out_tb  <= (NOT(s_ref) + '1');                            
                        END IF;
                    END IF;            		
            	END IF;
            END IF;
		ELSE
            s_ref  <= rl_in;
			IF(slew_count_out_tb < slew_count) THEN
				IF (start = '1') THEN
					slew_count_out_tb  <= slew_count_out_tb + '1' ;
					rl_done_out_tb     <= '0';
				END IF;
			ELSE
				IF(done = '1') THEN
					slew_count_out_tb <= (OTHERS =>'0');
					rl_done_out_tb    <= start;
				END IF;
			END IF;

			IF(start = '1') THEN                
				IF(slew_count_out_tb = slew_count-1) THEN
					IF(direction = '1') THEN
						IF((s_ref - rl_out_tb) > rate_count) THEN
							rl_out_tb  <= rl_out_tb + rate_count ;
						ELSE
							rl_out_tb  <= s_ref;
						END IF;
					ELSE
						IF(((NOT(s_ref) + '1') - rl_out_tb) < (NOT(rate_count) + '1')) THEN
							rl_out_tb  <= rl_out_tb - rate_count ;
						ELSE
							rl_out_tb  <= (NOT(s_ref) + '1');
						END IF;
					END IF;
				END IF;
			END IF;
		END IF;
    END IF;
END rate_lim;


BEGIN
--------------------------------------------------------------------------
-- Name       : RESET_GEN_PROC
-- Description: PROCESS generates the reset signal
--------------------------------------------------------------------------
RESET_GEN_PROC:
    PROCESS
        VARIABLE vhdl_initial : BOOLEAN := TRUE;
    BEGIN
        IF ( vhdl_initial ) THEN
            reset_tb <= '0';
            WAIT FOR ( SYSCLK_PERIOD * 10 );
            reset_tb <= '1';
            WAIT;
        END IF;
    END PROCESS;

--------------------------------------------------------------------------
-- Name       : CLOCK_GEN
-- Description: Logic generates 10 Mhz clock
--------------------------------------------------------------------------
sys_clk_tb <= NOT sys_clk_tb AFTER (SYSCLK_PERIOD / 2.0 );

-- rate limiter done signal pulse generation
s_rl_done_tb_pul                      <=  s_rl_done_tb AND NOT s_rl_done_tb_dly;
-- rl_in sign extension
s_rl_in_ext      <= s_rl_in_tb(g_STD_IO_WIDTH-1) & s_rl_in_tb ;
-- slew count sign extension
s_slew_count_ext <= s_slew_count_tb(g_STD_IO_WIDTH-1) & s_slew_count_tb;
-- rate count sign extension
s_rate_count_ext <= s_rate_count_tb(g_STD_IO_WIDTH-1) & s_rate_count_tb;
--------------------------------------------------------------------------
-- Name       : RESET_TEST_PROC
-- Description: Process to check the state of outputs at reset
--------------------------------------------------------------------------
RESET_TEST_PROC:
    PROCESS(s_reset_pul_tb,s_rl_out_tb)
    BEGIN
        IF (s_reset_pul_tb = '1') THEN
            IF(s_rl_out_tb = "00"&x"0000")THEN
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print(">>>>>>>>                      RATE_LIMITER IP SIMULATION                            <<<<<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print(">>>>>>>>     THIS TESTBENCH COMPARES THE FUNCTIONALITY W.R.T THE TESTBENCH MODEL    <<<<<<<");
                print(">>>>>>>>     WITH IN THE TOLERANCE RANGE [-1,0,+1]                                  <<<<<<<");
                print(">>>>>>>>                                                                            <<<<<<<");
                print(">>>>>>>>     ALL  PARAMETERS/GENERICS ARE FIXED TO THE FOLLOWING:                   <<<<<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print(">>>>>>>>     g_STD_IO_WIDTH    = 18                                                 <<<<<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print("                                                        ");
                print("                                                        ");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
				print(">>>>                                                <<<<");
                print(">>>>     TESTCASE         : RESET_TEST              <<<<");
				print(">>>>     rl_out_o         = 0                       <<<<");
				print(">>>>     rl_done_o        = 0                       <<<<");
				print(">>>>     STATUS           : PASSED                  <<<<");
				print(">>>>     DESCRIPTION      :                         <<<<");
				print(">>>>                                                <<<<");
				print(">>>>     FEATURES COVERED :                         <<<<");
				print(">>>>                                                <<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            ELSE
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print(">>>>>>>>                      RATE_LIMITER IP SIMULATION                            <<<<<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print(">>>>>>>>     THIS TESTBENCH COMPARES THE FUNCTIONALITY W.R.T THE MATLAB MODEL       <<<<<<<");
                print(">>>>>>>>     WITH IN THE TOLERANCE RANGE [-1,0,+1]                                  <<<<<<<");
                print(">>>>>>>>                                                                            <<<<<<<");
                print(">>>>>>>>     ALL  PARAMETERS/GENERICS ARE FIXED TO THE FOLLOWING:                   <<<<<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print(">>>>>>>>     g_STD_IO_WIDTH    = 18                                                 <<<<<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                print("                                                        ");
                print("                                                        ");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
				print(">>>>                                                <<<<");
                print(">>>>     TESTCASE         : RESET_TEST              <<<<");
				print(">>>>     rl_out_o         /= 0                      <<<<");
				print(">>>>     rl_done_o        /= 0                      <<<<");
				print(">>>>     STATUS           : FAILED                  <<<<");
				print(">>>>     DESCRIPTION      :                         <<<<");
				print(">>>>                                                <<<<");
				print(">>>>     FEATURES COVERED :                         <<<<");
				print(">>>>                                                <<<<");
                print("<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            END IF;
        END IF;
    END PROCESS;

--------------------------------------------------------------------------
-- Name       : DONE_DLY_PROC
-- Description: Process to delay done signal
--------------------------------------------------------------------------
DONE_DLY_PROC:
    PROCESS(sys_clk_tb,reset_tb)
    BEGIN
        IF (reset_tb = '0') THEN
            s_rl_done_tb_dly <= '0';
        ELSIF (rising_edge(sys_clk_tb)) THEN
            s_rl_done_tb_dly <= s_rl_done_tb;
        END IF;
    END PROCESS ;

--------------------------------------------------------------------------
-- Name       : RESET_PUL_GEN_PROC
-- Description: Process to generate reset pulse 
--------------------------------------------------------------------------
RESET_PUL_GEN_PROC:
    PROCESS(reset_tb,sys_clk_tb)
    BEGIN
        IF(reset_tb = '0') THEN
            s_reset_tb_dly <= '0';
        ELSIF(RISING_EDGE (sys_clk_tb))THEN
            s_reset_tb_dly <= reset_tb;
        END IF;
    END PROCESS;
    s_reset_pul_tb <= reset_tb AND (not(s_reset_tb_dly));

--------------------------------------------------------------------------
-- Name       : INPUT_DRIVER_PROC
-- Description: Process to provide the input test vectors
-------------------------------------------------------------------------- 
---------------------------
-- rl_in
---------------------------
PROCESS(reset_tb,sys_clk_tb)
  VARIABLE seed1, seed2: integer :=7;
  VARIABLE rand: real;
  VARIABLE int_rand: integer;
BEGIN
	IF(reset_tb = '0') THEN
		s_stim   <= (OTHERS => '0');
	ELSIF  RISING_EDGE(sys_clk_tb) THEN
		IF(s_start_rand_tb = '1') THEN
			UNIFORM(seed1,seed2, rand);
			int_rand := INTEGER(rand*131071.0);
			s_stim <= std_logic_vector(to_signed(int_rand, 18));
		END IF;
	END IF;
END PROCESS;
---------------------------
-- slew_count
---------------------------
PROCESS(reset_tb,sys_clk_tb)
  VARIABLE seed3, seed4: integer := 2;
  VARIABLE rand1: real;
  VARIABLE int_rand1: integer;
BEGIN
	IF(reset_tb = '0') THEN
		s_stim_slew<= (OTHERS => '0');
	ELSIF  RISING_EDGE(sys_clk_tb) THEN
		IF(s_start_rand_tb = '1') THEN
			UNIFORM(seed3, seed4, rand1);
			int_rand1 := INTEGER(rand1*8192.0);
			s_stim_slew <= std_logic_vector(to_unsigned(int_rand1, 18));
		END IF;
	END IF;
END PROCESS;
---------------------------
-- rate_count
---------------------------
PROCESS(reset_tb,sys_clk_tb)
  VARIABLE seed5, seed6: integer := 10;
  VARIABLE rand2: real;
  VARIABLE int_rand2: integer;
BEGIN
	IF(reset_tb = '0') THEN
		s_stim_rate<= (OTHERS => '0');
	ELSIF  RISING_EDGE(sys_clk_tb) THEN
		IF(s_start_rand_tb = '1') THEN
			UNIFORM(seed5, seed6, rand2);
			int_rand2 := INTEGER(rand2*4096.0);
			s_stim_rate <= std_logic_vector(to_unsigned(int_rand2, 18));
		END IF;
	END IF;
END PROCESS;
--------------------------------------------------------------------------
-- Name       : FSM_RATE_LIM_TB_PROC
-- Description: FSM implements rate limiter testbench controller operation
--------------------------------------------------------------------------
FSM_RATE_LIM_TB_PROC:
    PROCESS(sys_clk_tb,reset_tb)	
    BEGIN
        IF(reset_tb = '0') THEN
            state                       <= IDLE;
            s_rl_in_tb                  <= (OTHERS => '0');
            s_soft_stop_tb              <= '0';
            s_reset_rl_tb               <= '0';
            reset                       <= '0';
			s_start_rand_tb             <= '0';
			s_start_tb             		<= '0';
			s_direction_tb              <= '0';			
            s_slew_count_tb             <= (OTHERS => '0');
            s_rate_count_tb             <= (OTHERS => '0');
        ELSIF (RISING_EDGE(sys_clk_tb)) THEN
            CASE(state)IS
--------------------
-- IDLE state
--------------------
            WHEN IDLE =>
                s_slew_count_tb         <= (OTHERS => '0');
                s_rate_count_tb         <= (OTHERS => '0');                                
				IF(counter < x"015") THEN -- 20 inputs
					state               <= START ;
					s_start_rand_tb 	<= '1';
				ELSE
					state <= IDLE;                                        
				END IF;

--------------------
-- START state
--------------------
			WHEN START =>
				s_start_rand_tb <= '0';
				state <= INP_DRIVER;

--------------------
-- INP_DRIVER state
--------------------
            WHEN INP_DRIVER =>
				s_start_rand_tb 		<= '0';
                s_start_tb     		<= '1';
                s_slew_count_tb         <= s_stim_slew;
                s_rate_count_tb         <= s_stim_rate;
                s_rl_in_tb              <= s_stim;
				IF(counter < x"00A") THEN
					s_direction_tb      <= NOT(s_stim(g_STD_IO_WIDTH-1));
				ELSIF(counter = x"014") THEN
					s_direction_tb      <= '0';
                ELSE
					s_direction_tb      <= s_stim(g_STD_IO_WIDTH-1);
				END IF;               
                state <= OUTPUT_COMPARE;               
                IF(counter = x"014") THEN
                    s_soft_stop_tb <= '1';
                ELSE
                    s_soft_stop_tb <= '0';
                END IF;

--------------------
-- OUTPUT_COMPARE state
--------------------
			WHEN OUTPUT_COMPARE =>
				s_start_tb     		        <= '0';
				IF(slew_count_tb < s_slew_count_tb) THEN
					IF(s_rl_done_tb_pul = '1') THEN
						state               <= INP_DRIVER;
					ELSE
						state               <= OUTPUT_COMPARE;
					END IF;
				ELSE
                    IF(counter < x"013") THEN
                        IF(s_rl_done_tb_pul = '1' ) THEN
                            IF(s_direction_tb = '1') THEN
                                IF(s_rl_out_tb < s_rl_in_tb AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) < s_rl_in_tb) THEN
                                    state <= INP_DRIVER;
                                ELSE
                                    IF(s_rl_out_tb = s_rl_in_tb AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) = s_rl_in_tb) THEN
                                        state <= RESET_STATE;
                                        s_reset_rl_tb       <= '1';
                                        print("                                                                 ");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  PASSED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS MATCH         <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    ELSE
                                        state <= RESET_STATE;
                                        s_reset_rl_tb       <= '1';
                                        print("                                                                 ");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  FAILED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS DO NOT MATCH  <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    END IF;
                                END IF;
                            ELSE
                                IF(s_rl_out_tb > (NOT(s_rl_in_tb) + '1') AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) > (NOT(s_rl_in_tb) + '1')) THEN
                                    state                   <= INP_DRIVER;
                                ELSE
                                    IF(s_rl_out_tb = (NOT(s_rl_in_tb) + '1') AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) = (NOT(s_rl_in_tb) + '1')) THEN
                                        state <= RESET_STATE;
                                        s_reset_rl_tb       <= '1';
                                        print("                                                                 ");									
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  PASSED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS MATCH         <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    ELSE
                                        state <= RESET_STATE;
                                        s_reset_rl_tb       <= '1';
                                        print("                                                                 ");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  FAILED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS DO NOT MATCH  <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    END IF;
                                END IF;
                            END IF;
                        END IF;
                    ELSIF(counter = x"013") THEN
                        IF(s_rl_done_tb_pul = '1' ) THEN
                            IF(s_direction_tb = '1') THEN
                                IF(s_rl_out_tb < s_rl_in_tb AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) < s_rl_in_tb) THEN
                                    state <= INP_DRIVER;
                                ELSE
                                    IF(s_rl_out_tb = s_rl_in_tb AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) = s_rl_in_tb) THEN
                                        state <= RESET_STATE;
                                        print("                                                                 ");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  PASSED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS MATCH         <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    ELSE
                                        state <= RESET_STATE;
                                        print("                                                                 ");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  FAILED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS DO NOT MATCH  <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    END IF;
                                END IF;
                            ELSE
                                IF(s_rl_out_tb > (NOT(s_rl_in_tb) + '1') AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) > (NOT(s_rl_in_tb) + '1')) THEN
                                    state                   <= INP_DRIVER;
                                ELSE
                                    IF(s_rl_out_tb = (NOT(s_rl_in_tb) + '1') AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) = (NOT(s_rl_in_tb) + '1')) THEN
                                        state <= RESET_STATE;
                                        print("                                                                 ");									
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  PASSED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS MATCH         <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    ELSE
                                        state <= RESET_STATE;
                                        print("                                                                 ");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                        print("   INPUTS                                                                        ");
                                        print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                        print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                        print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                        IF(s_direction_tb = '1') THEN
                                            print("         DIRECTION         =  FORWARD                                            ");
                                        ELSE
                                            print("         DIRECTION         =  REVERSE                                            ");
                                        END IF;
                                        print("         SOFT_STOP         =  0                                                  ");
                                        print("                                                                                 ");
                                        print("     OUTPUTS                                                                     ");
                                        print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                        print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                        print(">>>>                                                           <<<<");
                                        print(">>>>     STATUS            :  FAILED                           <<<<");
                                        print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS DO NOT MATCH  <<<<");
                                        print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    END IF;
                                END IF;
                            END IF;                            
                        END IF;
                    ELSE
                       IF(s_rl_done_tb_pul = '1' ) THEN                           
                           IF(s_rl_out_tb < "00"&x"0000" AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) < "00"&x"0000") THEN
                                state                   <= INP_DRIVER;
                            ELSE
                                IF(s_rl_out_tb = "00"&x"0000" AND out_tb(g_STD_IO_WIDTH-1 DOWNTO 0) = "00"&x"0000") THEN
                                    state <= RESET_STATE;
                                    print("                                                                 ");									
                                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    print("   INPUTS                                                                        ");
                                    print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                    print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                    print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                    IF(s_direction_tb = '1') THEN
                                        print("         DIRECTION         =  FORWARD                                            ");
                                    ELSE
                                        print("         DIRECTION         =  REVERSE                                            ");
                                    END IF;
                                    print("         SOFT_STOP         =  0                                                  ");
                                    print("                                                                                 ");
                                    print("     OUTPUTS                                                                     ");
                                    print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                    print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                    print(">>>>                                                           <<<<");
                                    print(">>>>     STATUS            :  PASSED                           <<<<");
                                    print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS MATCH         <<<<");
                                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                ELSE
                                    state <= RESET_STATE;
                                    print("                                                                 ");
                                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    print_text_val("|  TESTCASE   :  ",(to_integer(signed(counter))),"                                               |");
                                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                    print("   INPUTS                                                                        ");
                                    print_text_val("         RL_IN             =  ",(to_integer(signed(s_rl_in_tb))),"      ");
                                    print_text_val("         SLEW_COUNT        =  ",(to_integer(signed(s_slew_count_tb)))," ");
                                    print_text_val("         RATE_COUNT        =  ",(to_integer(signed(s_rate_count_tb)))," ");
                                    IF(s_direction_tb = '1') THEN
                                        print("         DIRECTION         =  FORWARD                                            ");
                                    ELSE
                                        print("         DIRECTION         =  REVERSE                                            ");
                                    END IF;
                                    print("         SOFT_STOP         =  0                                                  ");
                                    print("                                                                                 ");
                                    print("     OUTPUTS                                                                     ");
                                    print_text_val("         DUT_OUTPUT        =  ",(to_integer(signed(s_rl_out_tb))),"     ");
                                    print_text_val("         TB_OUTPUT         =  ",(to_integer(signed(out_tb(g_STD_IO_WIDTH-1 DOWNTO 0))))," ");
                                    print(">>>>                                                           <<<<");
                                    print(">>>>     STATUS            :  FAILED                           <<<<");
                                    print(">>>>     DESCRIPTION       :  TB AND DUT OUTPUTS DO NOT MATCH  <<<<");
                                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                                END IF;
                            END IF;                                                      
                        END IF;
                    END IF;
                END IF;
--------------------
-- RESET_STATE state
--------------------
			WHEN RESET_STATE =>
				state <= IDLE;
				s_reset_rl_tb       <= '0';
                IF(counter = x"014") THEN                    
                    state <= IDLE;
                    print("");
                    print("");
                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                    print("<<<<            END OF RATE_LIMITER IP SIMULATION              >>>>");
                    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                END IF;   

--------------------
-- DEFAULT state
--------------------
            WHEN OTHERS =>
                state               <= IDLE;
            END CASE;
        END IF;
    END PROCESS;
--------------------------------------------------------------------------
-- Name       : COUNT_PROC
-- Description: Counter to decide the number of iterations
--------------------------------------------------------------------------
COUNT_PROC:
	PROCESS(reset_tb,sys_clk_tb)
	BEGIN
		IF(reset_tb = '0') THEN
			counter <= (OTHERS => '0');
		ELSIF RISING_EDGE (sys_clk_tb) THEN
			IF(state = RESET_STATE) THEN
				IF(counter < x"015") THEN
					counter <= counter + '1';
				END IF;
			END IF;
		END IF;
	END PROCESS;
--=================================================================================================
-- Component Instantiations
--=================================================================================================
-- Testbench rate limiter model
	PROCESS(reset_tb,sys_clk_tb)
	BEGIN
		rate_lim (reset_tb,sys_clk_tb,s_start_tb,s_rl_done_tb,s_direction_tb,s_reset_rl_tb,s_soft_stop_tb,s_rl_in_ext,
				s_slew_count_ext,s_rate_count_ext,rl_done_out_tb,slew_count_tb,s_ref_tb,out_tb);
	END PROCESS;
-------------------------------------------------
-- RATE_LIMITER_UUT_INST
-------------------------------------------------
RATE_LIMITER_UUT_INST:rate_limiter
PORT MAP(
    reset_i                           => reset_tb,
    sys_clk_i                         => sys_clk_tb,
    start_i                           => s_start_tb,
    soft_stop_i                       => s_soft_stop_tb,
	direction_i                       => s_direction_tb,
    reset_rl_i                        => s_reset_rl_tb,
    slew_count_i                      => s_slew_count_tb,
    rate_count_i                      => s_rate_count_tb,
    rl_in_i                           => s_rl_in_tb,
    rl_out_o                          => s_rl_out_tb,
    rl_done_o                         => s_rl_done_tb
);
end behavioural;