----------------------------------------------------------------------------------
-- Company: 
-- Engineer: GAMOM 
-- 
-- Create Date:    05:37:34 03/06/2012 
-- Design Name: 
-- Module Name:    Ex0_Fsm - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: Fournit le temps en µs depuis l'initialisation de la bibliothèque
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library NocLib ;

--use NocLib.CoreTypes.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Ex0_Fsm is
    Port ( Initialized : in  STD_LOGIC;
           
           Instruction : in  STD_LOGIC_VECTOR (7 downto 0);
			  instruction_en: in STD_LOGIC; --ceci n'est pas nécessaire dans ce module
													-- car le module fonctionne en permanence.
           clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           ClkRate : in  STD_LOGIC_VECTOR; --la fréquence de l'horloge en Mhz
			uTimeResult : out  STD_LOGIC_VECTOR; 
			TickResult : out STD_LOGIC_VECTOR;
			OvFus : out STD_Logic:='0'
			  );
end Ex0_Fsm;

architecture Behavioral of Ex0_Fsm is
 
 --Use descriptive names for the states, like st1_reset, st2_search
   type state_type is (Init,COunt,UsOut,OverFlow); 
   signal state, next_state : state_type; 
   --Declare internal signals for all outputs of the state-machine
   signal Tick_Count: std_logic_vector(31 downto 0):=(others=>'0');
	signal Time_Ucount :std_logic_vector(31 downto 0):=(others=>'0');
	signal OvF,Ovf_us,ovF_i,zero :std_logic;   -- overflow flag
   signal ClkR_Count : std_logic_vector(ClkRate'high downto ClkRate'low):=(others=>'0');
	signal en : std_logic:='1';
	--other outputs
begin
utime_PROC: process (clk)
   begin
      if (rising_edge(clk)) then
         if (reset = '1') or Initialized='0' then
            state <= init;
          --  Time_UCount<= (others=>'0');
			--	Tick_Count <=(others=>'0');
         else
            state <= next_state;
			TickResult<= Tick_Count;
			uTimeResult <=Time_ucount;
			OvF<=OvF_i;
			OvfUs<=Ovf_us;
           -- <output> <= <output>_i;
         -- assign other outputs to internal signals
         end if;        
      end if;
   end process;
 
   --MOORE State-Machine - Outputs based on state only
   OUTPUT_DECODE: process (state)
   FUNCTION incr_vec(s1:std_logic_vector;en:std_logic) return std_logic_vector is 
                  --this function increments a std_logic_vector type by '1' 
        VARIABLE V : std_logic_vector(s1'high downto s1'low) ; 
        VARIABLE tb : std_logic_vector(s1'high downto s1'low); 
        BEGIN 
        tb(s1'low) := en; 
        V := s1; 
        for i in (V'low + 1) to V'high loop 
            tb(i) := V(i - 1) and tb(i -1); 
        end loop; 
        for i in V'low to V'high loop 
            if(tb(i) = '1') then 
                V(i) := not(V(i)); 
            end if; 
        end loop; 
        return V; 
        end incr_vec; -- end function


FUNCTION  dcr_vec(s1:std_logic_vector;en:std_logic) return std_logic_vector is 
                  --this function decrements a std_logic_vector type by '1' 
        VARIABLE V : std_logic_vector(s1'high downto s1'low) ; 
        VARIABLE tb : std_logic_vector(s1'high downto s1'low); 
        BEGIN 
        tb(s1'low) := not(en); 
        V := s1; 
        for i in (V'low + 1) to V'high loop 
            tb(i) := V(i - 1) or tb(i -1); 
        end loop; 
        for i in V'low to V'high loop 
            if(tb(i) = '0') then 
                V(i) := not(V(i)); 
            end if; 
        end loop; 
        return V; 
        end dcr_vec; -- end function
FUNCTION all_ones(s1:std_logic_vector) return std_logic is 
                  --this function tells if all bits of a vector are '1' 
                  --return value Z is '1', then vector has all 1 bits 
        --VARIABLE V : std_logic_vector(s1'high downto s1'low) ; 
        VARIABLE Z : std_logic; 
        BEGIN 
        Z := s1(s1'low); 
        FOR i IN (s1'low+1) to s1'high LOOP 
            Z := Z AND s1(i); 
        END LOOP; 
        RETURN Z; 
        END all_ones; -- end function
FUNCTION all_zeros(s1:std_logic_vector) return std_logic is 
                  --this function tells if all bits of a vector are '0' 
                  --return value Z if '1', then vector has all 0 bits 
        --VARIABLE V : std_logic_vector(s1'high downto s1'low) ; 
        VARIABLE Z : std_logic; 
        BEGIN 
        Z := '0'; 
        FOR i IN (s1'low) to s1'high LOOP 
            Z := Z OR s1(i); 
        END LOOP; 
        RETURN not(Z); 
        END all_zeros; -- end function

	begin
      --insert statements to decode internal output signals
      --below is simple example
      case state is
		When Init =>
			Clkr_Count<=ClkRate;  --initialiser le décompte
			Time_uCount<=( others =>'0'); -- mettre à 0 le compteur des µS
			Tick_Count<=(others =>'0');  --mettre à 0 les ticks
		When Count =>
		  Tick_count<=incr_vec(Tick_Count,en);
		  ClkR_Count<=dcr_vec(Clkr_Count,en); --compteur de µs
		  zero<=all_zeros(ClkR_Count);   --
		  OvF_i<=All_ones(Tick_count);   --
		when UsOut =>
			Time_Ucount<=incr_vec(time_ucount,en);
			Clkr_Count<=ClkRate;
			Tick_count<=incr_vec(Tick_Count,en);
			OvF_i<=All_ones(Tick_count);
			zero<='0';
         OvF_us<=All_ones(Time_Ucount);
      when OverFlow =>
         Tick_count<=incr_vec(Tick_Count,en); --compteur de tick
		  ClkR_Count<=dcr_vec(Clkr_Count,en);
			OvF_us<=All_ones(Time_Ucount);
		   OvF_i<=All_ones(Tick_count); 
     end case;
   end process;
 
   NEXT_STATE_DECODE: process (state, Initialized, zero, OvF)
   begin
      --declare default state for next_state to avoid latches
      next_state <= state;  --default is to stay in current state
      --insert statements to decode next_state
      --below is a simple example
      case (state) is
         when Init =>
            if Initialized = '1' then
				   
               next_state <= count;
            end if;
         when Count =>
            if Zero = '0'  then
               next_state <= Count;
				elsif Zero = '1'  then
					next_state <=Usout;
			
            end if;
         when UsOut =>
				If OvF='0'  then
					next_state <= count;
				elsif OvF='1' then
					next_state <= OverFlow;
				end if;
			When OverFlow =>
					next_state<=Count;
--         when others =>
--            next_state <= Init;
      end case;      
   end process;


end Behavioral;

