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.1 / February 25 2004 
-- Addition of the FIFO3 enable to start the
-- transfer into FIFO3

-- REV 1.2 / November 22 2004 
-- a> Split of the counters N1 and 4095-N1
-- b> Reset	dataready used to reset 2nd cnt and its ovf


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

entity fifo2 is
    Port ( reset 			: in std_logic;			 					-- reset
           clk 			: in std_logic;								-- clk (sampling)
           acqen 			: in std_logic;								-- acquisition enable (command)
			  trigmode		: in std_logic;								-- = 0 , acq w/ trig ##  = 1 w/o trig
           trigger		: in std_logic;			 					-- trigger signal (synch'd)
			  ren1			: in std_logic;			 					-- fifo#1 read enable (delay)
			  decim_ratio	: in std_logic_vector(1 downto 0);		-- decimation ratio
			  n1param		: in std_logic_vector(1 downto 0);		-- trigger location 00-512 | 01-1024 | 10-2048 | 11-2560
           rstdataready	: in std_logic;
			  dataready		: in std_logic;

           rst2 			: out std_logic;								-- fifo#2 Reset
           wen2 			: out std_logic;								-- fifo#2 Write Enable
           ren2 			: out std_logic;								-- fifo#2 Read Enable
			  trigger_en	: out std_logic;								-- Trigger Enable
			  decim_flag	: out std_logic;								-- Decimation Flag
			  fifo3_en		: out std_logic);								-- FIFO 3 transfer enable
end fifo2;




architecture Behavioral of fifo2 is

-- Components

	COMPONENT ren_wen
	PORT(
		reset 		: IN std_logic;
		clk 			: IN std_logic;
		decim_ratio : IN std_logic_vector(1 downto 0);
		decim_en 	: IN std_logic;
		decim_flag	: IN std_logic;
		enable_r 	: IN std_logic;
		enable_w 	: IN std_logic;          
		wen2 			: OUT std_logic;
		ren2 			: OUT std_logic
		);
	END COMPONENT;

	

-- 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 rst_fifo_cnt : std_logic;		 -- rst fifo and cnt
	
	signal enable_w 		: std_logic;	 -- enable w from FSM to ren_wen
	signal enable_r 		: std_logic;	 -- enable r from FSM to ren_wen

	signal decim_en			: std_logic;	 -- decim enable to ren_wen
	signal decim_flag_sig	: std_logic;	 -- decimation flag sig

	signal wen2_sig 		: std_logic;
	signal ren2_sig 		: std_logic;

	signal cnt_en1	 		: std_logic;						  	-- cnt enable n1
	signal cnt_en2	 		: std_logic;						  	-- cnt enable 4095-n1
	signal cnt_val1		: integer range 4095 downto 0;  	-- cnt
	signal cnt_val2		: integer range 4095 downto 0;  	-- cnt
	signal n1_val 			: integer range 4095 downto 0;  	-- n1 val
	signal cnt_ovf1 		: std_logic;						  	-- =0 when count = fs
	signal cnt_ovf2 		: std_logic;						  	-- =0 when count = fs

-------------------------------------------------------
-- architecture description
-------------------------------------------------------
begin

	----------------------------------------------------
 	-- component's call
	----------------------------------------------------

	Inst_ren_wen: ren_wen PORT MAP(
		reset 		=> reset,
		clk 			=> clk,
		decim_ratio	=> decim_ratio,
		decim_en 	=> decim_en,
		decim_flag 	=> decim_flag_sig,
		enable_r 	=> enable_r,
		enable_w 	=> enable_w,
		wen2 			=> wen2_sig,
		ren2 			=> ren2_sig
	);

	----------------------------------------------------
 	-- assignments
	----------------------------------------------------
	rst2 			<= rst_fifo_cnt;
	wen2 			<= wen2_sig;
	ren2			<= ren2_sig;
	decim_flag	<= decim_flag_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 (acqen, cnt_ovf1, cnt_ovf2, dataready, ren1, state, trigger, trigmode)
	begin
		case state is
			-------------------------
			when s0 =>	 -- Init

				rst_fifo_cnt	<= '0';
				decim_en			<= '1';
				decim_flag_sig	<= '0';
				enable_w			<= '1';
				enable_r			<= '1';
				cnt_en1			<= '1';
				cnt_en2			<= '1';
				trigger_en		<= '1';
				fifo3_en			<= '1';

				if acqen = '0'  then
					
					if trigmode = '0' then 	  -- normal acq
  						next_state <= s1;

					else
  						next_state <= s5;		  -- no trigger acq

					end if;

				else
					next_state <= s0;
				end if;
			
			-------------------------
			-- normal acq
			when s1 =>	-- Acq starts / Wait for FIFO1 delay	

				rst_fifo_cnt	<= '1';
				decim_en			<= '0'; --*
				decim_flag_sig	<= '0';
				enable_w			<= '1';
				enable_r			<= '1';
				cnt_en1			<= '1';
				cnt_en2			<= '1';
				trigger_en		<= '1';
				fifo3_en			<= '1';

				if acqen = '0'  then

					if ren1 = '0' then
						next_state <= s2;

					else
						next_state <= s1;

					end if;

				else
					next_state <= s0;
				end if;

			-------------------------
			-- normal acq
			when s2 =>	-- Record N1 samples and Enable Trigger	

				rst_fifo_cnt	<= '1';
				decim_en			<= '0';
				decim_flag_sig	<= '0';
				enable_w			<= '0'; --*
				enable_r			<= '1';
				cnt_en1			<= '0'; --*
				cnt_en2			<= '1'; --*
				trigger_en		<= '1';
				fifo3_en			<= '1';

				if acqen = '0'  then

					if cnt_ovf1 = '0' then  --N1 samples in FIFO#2
						next_state <= s3;

					else
						next_state <= s2;

					end if;

				else
					next_state <= s0;
				end if;

			-------------------------
			-- normal acq
			when s3 =>	-- Keep Refreshing N1 samples until Trigger	

				rst_fifo_cnt	<= '1';
				decim_en			<= '0';
				decim_flag_sig	<= '0';
				enable_w			<= '0'; 
				enable_r			<= '0'; --*  simultaneous read/write
				cnt_en1			<= '1'; --*	 n1 samples in mem
				cnt_en2			<= '1'; 
				trigger_en		<= '0'; --*
				fifo3_en			<= '1';

				if acqen = '0'  then

					if  dataready = '0' then
					 
						if trigger = '1' then 
							next_state <= s4;
						else
							next_state <= s3;
						end if;

					else
						next_state <= s3;

					end if;

				else
					next_state <= s0;
				end if;

			-------------------------
 			-- normal acq
			when s4 =>	--Trigger rec'd / Record N2 samples	/ Enable transfer to FIFO3

				rst_fifo_cnt	<= '1';
				decim_en			<= '0';
				decim_flag_sig	<= '1';
				enable_w			<= '0';
				enable_r			<= '1';
				cnt_en1			<= '1';
				cnt_en2			<= '0';	-- record N-N1 samples
				trigger_en		<= '1';
				fifo3_en			<= '0';

				if acqen = '0'  then

					if cnt_ovf2 = '0' then
					
						next_state <= s2;

					else
						next_state <= s4;
					end if;

				else
					next_state <= s0;
				end if;

			-------------------------
			-- no trigger acquisition
			when s5 =>	-- Wait for REN1 / Guarantees that FIFO#1 is not empty

				rst_fifo_cnt	<= '1';
				decim_en			<= '1';
				decim_flag_sig	<= '1';
				enable_w			<= '1';
				enable_r			<= '1';
				cnt_en1			<= '1';
				cnt_en2			<= '1';
				trigger_en		<= '1';
				fifo3_en			<= '1';

				if acqen = '0'  then

					if ren1 = '0' then	 -- wait for FIFO#1 to contain 32 samples
						next_state <= s6;

					else
						next_state <= s5;

					end if;

				else
					next_state <= s0;
				end if;

			-------------------------
			-- no trigger acquisition
			when s6 =>	-- Record Samples in FIFO1 -> 2 ->3	

				rst_fifo_cnt	<= '1';
				decim_en			<= '1';
				decim_flag_sig	<= '1';
				enable_w			<= '0';
				enable_r			<= '0';
				cnt_en1			<= '0';
				cnt_en2			<= '0';
				trigger_en		<= '1';
				fifo3_en			<= '0';

				if acqen = '0' then	 -- acquire until acq is stopped or halted
					next_state <= s6;
				else
					next_state <= s0;
				end if;

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

				rst_fifo_cnt	<= '1';
				decim_en			<= '1';
				decim_flag_sig	<= '1';
				enable_w			<= '1';
				enable_r			<= '1';
				cnt_en1			<= '1';
				cnt_en2			<= '1';
				trigger_en		<= '1';
				fifo3_en			<= '1';
			
				next_state <= s0;

		end case;
    end process;
	----------------------------------------------------

 	----------------------------------------------------
	-- N1 Val - Value Selection
 	----------------------------------------------------
	process (n1param)
	begin
		case n1param is 
			-- remove the ";--" from the following n1_val assignments
			-- to get the proper values: 510, 1022, 2046, 2558

			when "00" =>					
				n1_val <= 5;--10;			-- Value - 2
	
			when "01" =>
				n1_val <= 10;--22;

			when "10" =>
				n1_val <= 20;--46;

			when others =>
				n1_val <= 25;--58;

		end case;

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

	----------------------------------------------------
	-- process counter  n1
	----------------------------------------------------
	process(clk, cnt_en1, cnt_val1, n1_val, wen2_sig )
	begin
		if cnt_en1 = '1' then 

			cnt_val1	<= 0;
			cnt_ovf1	<= '1';

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

			if wen2_sig = '0' then

				if cnt_val1 < n1_val then
					cnt_ovf1	<= '1';
					cnt_val1	<= cnt_val1 + 1;
				else
					cnt_ovf1 <= '0';
					cnt_val1	<= cnt_val1;
				end if;

			else
				cnt_ovf1	<= cnt_ovf1;
				cnt_val1	<= cnt_val1;
				
			end if;	 

		end if;

	end process;
	----------------------------------------------------
	-- process counter  N-N1
	----------------------------------------------------
	process(clk, cnt_en2, cnt_val2, n1_val, rst_fifo_cnt, wen2_sig,rstdataready )
	begin
		if ( cnt_en2 = '1' or rstdataready = '0' ) then 

			cnt_val2	<= 0;
			cnt_ovf2	<= '1';

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

			if wen2_sig = '0' then

				if cnt_val2 < (40 - n1_val) then	 -- 4083 = 4095 - 12
					cnt_ovf2	<= '1';
					cnt_val2	<= cnt_val2 + 1;
				else
					cnt_ovf2 <= '0';
					cnt_val2 <= cnt_val2;
				end if;

			else	  -- wen2=1
				cnt_ovf2 <= cnt_ovf2;
				cnt_val2 <= cnt_val2;
			
			end if;

		end if;

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


end Behavioral;
