library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--  Uncomment the following lines to use the declarations that are
--  provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;

-- ********************************************
-- ALL Signals are active LOW unless specified
-- ********************************************
-- 
-- REV 1.0 / February 25 2004 
-- 
-- Data Ready Signal is active HIGH

-- REV 1.2 / November 22 2004 
-- Reset	dataready used to reset cnt and its ovf 

-- ********************************************


entity fifo3 is
    Port ( reset 			: in std_logic;
           clk 			: in std_logic;
			  acqen			: in std_logic;
			  tmode			: in std_logic;
           fifo3_en 		: in std_logic;
           rstdataready	: in std_logic;
			  dataready		: out std_logic;
           rst3 			: out std_logic;
           wen3 			: out std_logic );
end fifo3;

architecture Behavioral of fifo3 is

-- Signals
-------------------------------------------------------
	type state_TYPE is (s0, s1, s2, s3, s4, s5, s6);
	attribute ENUM_ENCODING: STRING;
	attribute ENUM_ENCODING of state_TYPE: type is "000 001 010 011 100 101 110";

	signal state, next_state : state_TYPE;

	signal ovf4096			: std_logic;
	signal cnt_en 			: std_logic;
	signal cnt				: integer range 4095 downto 0;
	signal dataready_sig : std_logic;


begin

	dataready <= dataready_sig;

	----------------------------------------------------
	-- processes
	----------------------------------------------------

	----------------------------------------------------
	-- FSM sequence / definition	
	process (reset, clk)
	begin
		if reset = '0' then
			state <= s0;
		elsif (clk'event and clk= '1') then
				state <= next_state;
			else
				state <= state;
		end if;
	end process;
	----------------------------------------------------


	----------------------------------------------------
	-- FSM Description
	process (state, acqen, fifo3_en, tmode, ovf4096)
	begin
		case state is
			----------------------------------------------------------
			when s0 =>	 -- Init

				rst3 		<=  '0';
				wen3 		<=	 '1';
				cnt_en	<=  '1';

				if acqen = '0' then			
					next_state <= s1;

				else
					next_state <= s0;

				end if;

			----------------------------------------------------------
			when s1 =>	 -- Wait for trig event and fifo3_en

				rst3 		<=  '1';
				wen3 		<=	 '1';
				cnt_en	<=  '1';

				if acqen = '0' then			

					if fifo3_en = '0' then
						next_state <= s2;
					
					else
						next_state <= s1;
					
					end if;
				
				else
					next_state <= s0;

				end if;

			----------------------------------------------------------
			when s2 =>	 -- transfer 4096 data points from fifo2

				rst3 		<=  '1';
				wen3 		<=	 '0';
				cnt_en	<=  '0';

				if acqen = '0' then			

					if tmode ='0' then		  -- acq with trig
						if ovf4096 = '0' then
							next_state <= s1;
					  	else
							next_state <= s2;
						end if;
					else
						next_state <= s2;
					end if;
				
				else
					next_state <= s0;

				end if;

			----------------------------------------------------------
 			when others =>

				rst3 		<=  '1';
				wen3 		<=	 '1';
				cnt_en	<=  '1';
			
				next_state <= s0;

		end case;
	end process;

	----------------------------------------------------
	-- Counter 
	----------------------------------------------------
	process (reset, clk, cnt_en, rstdataready)
	begin
		if ( reset = '0' or rstdataready = '0' )then

			cnt <= 0;
			ovf4096 <= '1';

		elsif (clk'event and clk = '1') then

			if cnt_en = '0' then
			
				if cnt < 4086 then
					cnt <= cnt + 1;
					ovf4096 <= '1';
				else
					cnt <= cnt; 
					ovf4096 <= '0';
				end if;

			else

				cnt <= cnt;
				ovf4096 <= ovf4096;

			end if;

		end if;
    end process;

	----------------------------------------------------
	-- Data Ready Process
	----------------------------------------------------
	process (clk, ovf4096, reset, rstdataready)
	begin
		if ( reset = '0' or rstdataready = '0' ) then 
			dataready_sig <= '0';
		
		elsif (clk'event and clk = '1') then

			if ovf4096 = '0' then
				dataready_sig <= '1';
			
			else
				dataready_sig <= dataready_sig;
			end if;

		end if;

	end process;
	----------------------------------------------------
	
	 
end Behavioral;
