-------------------------------------------------------------------------------
-- Title      : Tacho measurement unit
-------------------------------------------------------------------------------
-- File       : tach_measure.vhd
-- Author     : Pavan Marisetti
-- Company    : Microsemi Corporation
-- Device     : SmartFusion
-- Standard   : VHDL
-------------------------------------------------------------------------------
-- Description: This code implementes the tacho mesuremnt block
-------------------------------------------------------------------------------
-- Copyright (c) 2011   Microsemi Corporation
--                      All rights reserved.
-------------------------------------------------------------------------------
-- Revisions  : V1.0
-------------------------------------------------------------------------------


library ieee;
library std;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity tach_measure is
	port (clock  : in std_logic; -- clock
	      reset  : in std_logic; -- active low reset
	      enable : in std_logic; -- Tacho reading enable signal
	      TACHIN : in std_logic; -- TACH input 
          read_done : in std_logic; -- read done
	      counter_done : out std_logic; -- tacho count done signal
	      TACHREAD_DIR : out std_logic_vector(23 downto 0) -- TACHOREAD register
         ); 
end tach_measure;

architecture tach_measure of tach_measure is

signal tach_count : std_logic_vector(23 downto 0);
signal edge_cntr : std_logic_vector(3 downto 0);

signal count_done : std_logic;
signal TACHIN_sync : std_logic;
signal TACHIN_sync1 : std_logic;
signal TACHIN_sync2 : std_logic;
signal count_tach : std_logic;


begin
counter_done <= count_done;

-- Synchonisation of tacho signal
tach_sync_proc: process(clock, reset)
      begin
        if(reset = '0' ) then
          TACHIN_sync <= '0';
          TACHIN_sync1 <= '0';
          TACHIN_sync2 <= '0';
        elsif(clock = '1' and clock'event) then
           TACHIN_sync  <= TACHIN;
           TACHIN_sync1 <= TACHIN_sync;
           TACHIN_sync2 <= TACHIN_sync1;
        end if;
    end process; 

-- Process to count tacho edges
	edge_counter: process (reset, clock)
		begin
		if (not(reset) = '1') then
			edge_cntr <= "0000";
			count_tach <= '0';
            count_done <= '0';
		elsif (clock = '1' and clock'event) then			
          if( enable = '1') then
            if(edge_cntr =  "1000") then
		      edge_cntr <= "0000";
              count_tach <= '0';
              count_done <= '1';
            elsif(TACHIN_sync1 = '1' and TACHIN_sync2 = '0') then
			  edge_cntr <= edge_cntr + '1';
              count_tach <= '1';
              count_done <= '0';
            else
              count_done <= '0';              
            end if;
          else
            edge_cntr <= "0000";
            count_tach <= '0';
            count_done <= '0';
		  end if;
		end if;
	end process;

-- Process to cont the number of clocks between two tacho edges			
	tach_counter: process (reset, clock)
		begin
		if (not(reset) = '1') then
          tach_count <= (others => '0');
		elsif (clock = '1' and clock'event) then			
		  if(count_tach = '1') then
            tach_count <= tach_count + 1;
          else
            tach_count <= (others => '0');
		  end if;
        end if;
	end process;
-- Process to register tacho count value 
  tach_out_reg : process(reset, clock)
    begin
       if(not(reset) = '1') then
         TACHREAD_DIR <= (others => '0');
       elsif( clock = '1' and clock'event) then
          if(count_done = '1') then
            TACHREAD_DIR <= tach_count;
          end if;
       end if;
    end process;			


end tach_measure;