--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    15:31:32 03/13/06
-- Design Name:    
-- Module Name:    control_unit - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

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

entity analyser  is
    Port ( 
	    clk 					: 	in 	std_logic;
        reset 					: 	in 	std_logic;
        ANA_record_len 			: 	in 	std_logic_vector(9 downto 0);
        ANA_addr_pointer 		: 	out std_logic_vector(9 downto 0);
		ANA_RD_addr				:	in 	std_logic_vector(10 downto 0);
		ANA_RD_DAT				:	out std_logic_vector(31 downto 0);
		ANA_slope				: 	in 	std_logic;
		ANA_ARM					: 	in	std_logic;
		ANA_timer_en			: 	in	std_logic;
		ANA_DATA_ACQUIRED 		: 	out std_logic;
		ANA_ARMED    			: 	out std_logic;
		ANA_trig 				: 	in 	std_logic_vector(7 downto 0);
		data_0					:	in	std_logic_vector(31 downto 0);
		data_1					:	in	std_logic_vector(31 downto 0);
		data_2					:	in	std_logic_vector(31 downto 0);
		data_3					:	in	std_logic_vector(31 downto 0);
        ANA_trig_src 			: 	in 	std_logic_vector(2 downto 0);
		ANA_CH1_src 			: 	in 	std_logic_vector(1 downto 0);
		ANA_CH2_src 			: 	in 	std_logic_vector(1 downto 0);
		ANA_timer 				: 	in 	std_logic_vector(23 downto 0);
        ANA_delay 				: 	in 	std_logic_vector(31 downto 0);
		ANA_tick_out			: 	out std_logic
			  );
end analyser;




architecture Behavioral of analyser is

--counters signals
signal 	addr_cnt,RAM_addr,
		sample_cnt 			:	std_logic_vector(9 downto 0);
signal  addr_cnt_en,
		sample_cnt_en,
		sample_cnt_end,
		sample_cnt_load		: 	std_logic;
signal 	delay_cnt 			:	std_logic_vector(31 downto 0) ;
signal 	delay_cnt_en,
		delay_cnt_load,
		delay_cnt_end		: std_logic;		

signal	RAM1_rd_dat,
		RAM2_rd_dat,
		CH1_din,
		CH2_din				:	std_logic_vector(31 downto 0) ;

signal	clk_en,clock_enable	:	std_logic;
signal	timer			 	:	std_logic_vector(23 downto 0) ;

signal 	trig_sel,
		RAM_wren 			:	std_logic;
signal	trig_edge_det		:	std_logic_vector(3 downto 0) ;
signal	trig_edge_r			:	std_logic;
signal	trig_edge_f			:	std_logic;
signal	trig_edge			:	std_logic;


TYPE STATE_TYPE IS (idle,wait_trig,capture,completed,trig_delay);
SIGNAL state: STATE_TYPE;


component SPRAM1kx32
	PORT
	(
		address		: IN STD_LOGIC_VECTOR (9 DOWNTO 0);
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (31 DOWNTO 0);
		wren		: IN STD_LOGIC ;
		q			: OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
	);
end component;

begin


--***************************************************************************************************
--***************************************     data input selector	    *******************************
--***************************************************************************************************

with ANA_CH2_src select
    CH2_din <= 		data_0 when "00",
				 	data_1 when "01",               
					data_2 when "10",
					data_3 when others;
					
					

with ANA_CH1_src select
    CH1_din <= 		data_0 when "00",
					data_1 when "01",               
					data_2 when "10",
					data_3 when others;
					

--***************************************************************************************************
--***************************************   trigger input selector    *******************************
--***************************************************************************************************

with ANA_trig_src select
    trig_sel <= 	 ANA_trig(0) when "000",
				 	 ANA_trig(1) when "001",               
					 ANA_trig(2) when "010",
					 ANA_trig(3) when "011",
					 ANA_trig(4) when "100", 
					 ANA_trig(5) when "101",
					 ANA_trig(6) when "110",
					 ANA_trig(7) when others;


--***************************************************************************************************
--***************************************   trigger edge detection    *******************************
--***************************************************************************************************
	
 process (clk)
 begin
 if rising_edge(clk) then
	trig_edge_det(0)<= trig_sel;
	trig_edge_det(1)<=trig_edge_det(0);
	trig_edge_det(2)<=trig_edge_det(1);
	trig_edge_det(3)<=trig_edge_det(2);
 end if;
 end process;
 
 trig_edge_f <= (not trig_edge_det(0)) and (not trig_edge_det(1)) and trig_edge_det(2)and trig_edge_det(3) ;
 trig_edge_r <= (not trig_edge_det(3)) and (not trig_edge_det(2)) and trig_edge_det(1)and trig_edge_det(0) ;
 trig_edge <= trig_edge_r when  ANA_slope = '0' else trig_edge_f;

--***************************************************************************************************
--***************************************     main state machine	    *******************************
--***************************************************************************************************

PROCESS (clk, reset)
	BEGIN
		IF reset = '1' THEN
			state <= idle;
		ELSIF rising_edge(clk)  THEN
			CASE state IS
				WHEN idle =>
					IF ANA_ARM ='1' THEN
						state <= wait_trig;
					END IF;

				WHEN wait_trig=>
					IF trig_edge ='1' THEN
						state <= trig_delay;
					END IF;
					
				WHEN trig_delay =>
					IF  delay_cnt_end='1' THEN
						state <= capture;
					END IF;
						
				WHEN capture=>
					IF sample_cnt_end ='1' THEN
						state <= completed;	
					END IF;
						
				WHEN completed=>
					IF ANA_ARM ='0' THEN
						 state <= idle;
					END IF;
			
			END CASE;
		END IF;
	END PROCESS;

WITH state SELECT
delay_cnt_en		<=	'1'	WHEN	trig_delay,
						'0'	WHEN	others;

WITH state SELECT
delay_cnt_load <=		'1'	WHEN	wait_trig,
						'0'	WHEN	others;

WITH state SELECT
addr_cnt_en		<=		'0'				WHEN	completed,    --register data all the time except reading sequence
						clock_enable	WHEN	others;
							
WITH state SELECT
sample_cnt_en	<=		'1'	WHEN	capture,
						'0'	WHEN	others;

WITH state SELECT
sample_cnt_load <=	'1'	WHEN	trig_delay,
						'0'	WHEN	others;

WITH state SELECT
RAM_wren    <=			'0'				WHEN	completed,    --register data all the time except reading sequence
						clock_enable	WHEN	others;
							
						
WITH state SELECT
ANA_DATA_ACQUIRED <=	'1'	WHEN	completed,
						'0'	WHEN	others;
							
							WITH state SELECT
ANA_ARMED          <=	'0'	WHEN idle,
						'1'	WHEN	others;
							
							
						

	


--***************************************************************************************************
--***************************************   		bufer memories		    *******************************
--***************************************************************************************************
--switching address bus between writes/reads
RAM_addr <= ANA_RD_addr(9 downto 0) when (state = completed) else addr_cnt;



buffer1 : SPRAM1kx32 PORT MAP 
	(
		address	 => RAM_addr,
		clock	 =>	clk,
		data	 => CH1_din,
		wren	 => RAM_wren,
		q	 => RAM1_rd_dat
	);
			
			
buffer2 : SPRAM1kx32 PORT MAP 
	(
		address	 => RAM_addr,
		clock	 =>	clk,
		data	 => CH2_din,
		wren	 => RAM_wren,
		q	 => RAM2_rd_dat
	);			
--switching RAM READ data bus between 2 memories depending on MSB READ address bit.
ANA_RD_DAT <= RAM1_rd_dat when ANA_RD_addr(10) = '0' else RAM2_rd_dat;



--***************************************************************************************************
--***************************************   			counters			    *******************************
--***************************************************************************************************



--DPRAM address counter
process(clk,reset)
begin
if rising_edge(clk) then
	if  reset = '1' then
		addr_cnt <= (others=>'0');
	elsif addr_cnt_en = '1' then
		addr_cnt <= addr_cnt+'1';
	end if;
end if;
end process;


--trigger delay counter
process(clk,reset)
begin
if rising_edge(clk) then
	if reset = '1' then
		delay_cnt <= (others=>'0');
	elsif delay_cnt_load = '1' then
		delay_cnt <=	  ANA_delay;
	elsif delay_cnt_en = '1' then
		delay_cnt <= delay_cnt - '1';
	end if;
	if delay_cnt = x"FFFFFFFF" then
		delay_cnt_end <= '1';
	else
		delay_cnt_end <= '0';
	end if;
end if;
end process;


--sample number counter
process(clk,reset)
begin
if rising_edge(clk) then
	if reset = '1' then
		sample_cnt <= (others=>'0');
	elsif sample_cnt_load = '1' then
		sample_cnt <=	  ANA_record_len;
	elsif sample_cnt_en = '1' then
		sample_cnt <= sample_cnt - '1';
	end if;
	if sample_cnt = "0000001" then
		sample_cnt_end <= '1';
	else
		sample_cnt_end <= '0';
	end if;
end if;
end process;



--data address pointer latch
process(clk)
begin
if rising_edge(clk) then
	if  reset = '1' then
		ANA_addr_pointer  <= (others=>'0');
	elsif state = completed then
		ANA_addr_pointer  <= addr_cnt;
	end if;
end if;
end process;

																						

------------------------------------------------------------------------------------------------------	
--CLK generator
------------------------------------------------------------------------------------------------------
	process(clk,reset,timer)
begin
	if reset='1' then
		timer<=x"000100";
	elsif clk'event and clk ='0' then
		if clk_en = '1' then
		   timer <= ANA_timer ;
		else
		   timer <=timer -'1';
		end if;
	end if;
	if timer = "000000" then  
		clk_en<='1';
	else
		clk_en<='0';
	end if;
	end process;
	
	
	clock_enable	<= clk_en when  ANA_timer_en = '1' else '1';

	ANA_tick_out 	<= clk_en;





end Behavioral;
