
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.

-- Copyright (C) 1991-2007 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions 
-- and other software and tools, and its AMPP partner logic 
-- functions, and any output files from any of the foregoing 
-- (including device programming or simulation files), and any 
-- associated documentation or information are expressly subject 
-- to the terms and conditions of the Altera Program License 
-- Subscription Agreement, Altera MegaCore Function License 
-- Agreement, or other applicable license agreement, including, 
-- without limitation, that your use is for the sole purpose of 
-- programming logic devices manufactured by Altera and sold by 
-- Altera or its authorized distributors.  Please refer to the 
-- applicable agreement for further details.


-- Generated by Quartus II Version 7.1 (Build Build 156 04/30/2007)
-- Created on Tue Aug 28 10:52:58 2007


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

USE ieee.numeric_std.ALL;
--USE std.textio.all;



--  Entity Declaration

ENTITY AD7656_readout IS
	-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
	PORT
	(
		clk : IN STD_LOGIC;
		reset : IN STD_LOGIC;
		BUSY : IN STD_LOGIC;
		ADC_DATA : IN STD_LOGIC_VECTOR(15 downto 0);
		ARM : IN STD_LOGIC;
		sampling_freq : IN STD_LOGIC_VECTOR(15 downto 0);
		software_trigger : IN STD_LOGIC;
		sampling_clk_source : IN STD_LOGIC;
		trig_select : IN STD_LOGIC;
		TRIG1 : IN STD_LOGIC;
		TRIG2 : IN STD_LOGIC;
		clk25 : IN STD_LOGIC;
		sample_clk_ext : IN STD_LOGIC;
		Single_Channel_Mode_Channel_number : IN STD_LOGIC_VECTOR(5 downto 0);
		Single_Channel_Mode : IN STD_LOGIC;
		num_of_measurements : IN STD_LOGIC_VECTOR(15 downto 0);
		result_wr_en : OUT STD_LOGIC;
		measurement_done : OUT STD_LOGIC;
		ADC_CONVST_A : OUT STD_LOGIC;
		ADC_CONVST_B : OUT STD_LOGIC;
		ADC_CONVST_C : OUT STD_LOGIC;
		ADC_CS : OUT STD_LOGIC;
		ADC_RD : OUT STD_LOGIC;
		BUF_CLK : OUT STD_LOGIC;
		status : OUT STD_LOGIC_VECTOR(7 downto 0);
		data_WR : OUT STD_LOGIC_VECTOR(15 downto 0);
		BUF_SEL : OUT STD_LOGIC_VECTOR(2 downto 0);
		ADC_OE : OUT STD_LOGIC;
		ADC_RST : OUT STD_LOGIC;
		sample_clk_out : OUT STD_LOGIC;
		armed : OUT STD_LOGIC;
		DPRAM_WR_ADDR : OUT STD_LOGIC_VECTOR(12 downto 0)
	);
	-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
	
END AD7656_readout;


--  Architecture Body

ARCHITECTURE AD7656_readout_architecture OF AD7656_readout IS

	TYPE STATE_TYPE IS (
	idle,
	wait_trigger,
	wait_sample_pulse1,
	wait_sample_pulse2,
	wait_sample_pulse3,
	wait_sample_pulse4,
	wait_sample_pulse5,
	wait_convst,
	wait_busy_1,
	wait_busy_2,
	wait_busy_3,
	wait_busy_4,
	read_ADCsl_1,
	read_ADCsl_2,
	read_ADCsh,
	scan_outputs,
	conversion_done,
	meas_done			
	);

SIGNAL state: STATE_TYPE;



    signal  ADC_count, Channel_count :  std_logic_vector(2 downto 0);
   
	signal  ADC_number : STD_LOGIC_VECTOR(7 downto 0);
	signal  Acq36_cnt : STD_LOGIC_VECTOR(12 downto 0);
	signal  ADC_CHANNEL, ADC_CHANNEL_tmp : STD_LOGIC_VECTOR(5 downto 0);
	signal  edge_regi,edge_rege  : STD_LOGIC_VECTOR(3 downto 0);
	signal  data_WR1,timer,addr_cnt: STD_LOGIC_VECTOR(15 downto 0);
	signal   addr_36ch_dpram : STD_LOGIC_VECTOR(12 downto 0);
	signal	measurements_counter : STD_LOGIC_VECTOR(15 downto 0);
    signal 	ADC_count_en,Channel_count_en,
			str_temp,
		    CS_temp,
			RD_temp,
			ADC_RST_temp,
			latch_adc_result,
			ADC_sample,
			result_wr_en_temp,
			result_wr_en_temp1,
			OE_temp,					
			ADC_count_rst,
			timer_init,
			Channel_count_rst,
			sample_clk_int,
			sample,
			BUSY_SYNCH,
			trigger,
			meas_num_rst,
			meas_num_count_en,
			meas_num_done,
			trigger_ext,
			trigger_int,
			addr_cnt_rst,
			addr_cnt_en,
			addr_cnt_en_temp,
			Acq36_cnt_en,
			reset_capt_logic : std_logic ;
			
			
			
	
BEGIN


--***********************************************************************************************************************************************
--*******************************************	data transfer state machine	*********************************************************************
--***********************************************************************************************************************************************

--STATE MACHINE INPUT SYNCHRONISATION
process(clk)
begin
	if clk'event and clk='0' then
		BUSY_SYNCH<= BUSY;
	end if;
end process;


	PROCESS (clk,reset)
	BEGIN
		IF reset = '1' THEN
			state <= idle;
		ELSIF clk'EVENT AND clk = '1' THEN	
				CASE state IS
					WHEN idle =>
					if ARM = '1' then
							state <=wait_trigger;
							end if;
							
					when wait_trigger =>		
							if trigger = '1' then
								state <=wait_Sample_pulse1;
							elsif ARM = '0' then 
								state <= idle;
							end if;		
							
							
					when wait_Sample_pulse1 => 
							if sample = '1' then
								state <=wait_Sample_pulse2;		
							end if;	
								
					when wait_Sample_pulse2 => 
								state <= wait_Sample_pulse3;										
								
					when wait_Sample_pulse3 => 
								state <= wait_Sample_pulse4;

					when wait_Sample_pulse4 => 
								state <= wait_Sample_pulse5;										
								
					when wait_Sample_pulse5 => 
								state <= wait_busy_1;										

					when wait_convst =>
							if sample = '1' then
								state <=wait_busy_1;
							end if;	
							
					when wait_busy_1 =>
							state <= wait_busy_2;
					
					when wait_busy_2 =>
							state <= wait_busy_3;
							
					when wait_busy_3 =>
							state <= wait_busy_4;
							
					when wait_busy_4 =>
							if BUSY_SYNCH = '0' then
								state <=read_ADCsl_1;
							elsif ARM = '0' then 
								state <= idle;
							end if;		
					
					when read_ADCsl_1 =>	
							state<=read_ADCsl_2;
														
					when read_ADCsl_2 =>	
							state<=read_ADCsh;
							
					when read_ADCsh =>  						
							state<=scan_outputs;
						
						
					when scan_outputs =>					
						if  Channel_count = "110"  and ADC_count = "110" then
							state <= conversion_done;
						elsif ADC_count = "110" then
								state<=read_ADCsl_1; 
						elsif ARM = '0' then 
								state <= idle;
						end if;	
				
					when conversion_done =>
							if meas_num_done = '1' then
								state <= meas_done;
							elsif sample = '0' and ARM = '1' then
								state <=wait_convst;
							elsif ARM = '0' then 
								state <= idle;
							end if;	
					
					when meas_done =>
						if arm = '0' then
								state <= idle;
						end if;
							
							
					when others =>
							state<=idle;

				END CASE;
			end if;
	END PROCESS;

	WITH state SELECT
	ADC_count_en 		<=	'0' when idle,								
							'1' when scan_outputs,
							'0' when others;
							
	WITH state SELECT						
	ADC_RST_temp		<=	'1' when idle,								
							'0' when others;				
							
							
	WITH state SELECT
	Channel_count_en 	<=	'0' when idle,					
							'1' when read_ADCsl_1,
							'0' when others;							
	
	WITH state SELECT
	CS_temp 			<=	'1' when idle,
							'1' when wait_trigger,
							'1' when wait_Sample_pulse1,
							'1' when wait_Sample_pulse2,
							'1' when wait_Sample_pulse3,
							'1' when wait_Sample_pulse4,
							'1' when wait_Sample_pulse5,
							'1' when wait_convst,						
							'0' when read_ADCsl_1,
							'0' when read_ADCsl_2,
							'0' when read_ADCsh,
							'0' when scan_outputs,
							'1' when conversion_done,
							'1' when others;		
	
	WITH state SELECT
	RD_temp 			<=	'1' when idle,						
							'0' when read_ADCsl_1,
							'0' when read_ADCsl_2,
							'1' when others;
									
	WITH state SELECT
	buf_clk     		<=	'1' when idle,							--clk when scan_outputs,
							'1' when conversion_done,
							'1' when others;
	
	WITH state SELECT
	measurement_done	<=	'0' when idle,							
							'1' when meas_done,
							'0' when others;
							
							
	WITH state SELECT
	Acq36_cnt_en		<=	'0' when idle,							
							'1' when conversion_done,
							'0' when others;					
					
			
	WITH state SELECT
	result_wr_en_temp1	<=	'0' when idle,							
							'1' when scan_outputs,
							'0' when others;
												
	WITH state SELECT
	latch_adc_result 	<=	'0' when idle,
							'1' when scan_outputs,
							'0' when others;					
					
					
	WITH state SELECT
	ADC_sample 			<=	'1' when idle,
							'1' when wait_trigger,
							'0' when wait_convst,
							'0' when wait_Sample_pulse1,
							'0' when wait_Sample_pulse2,
							'0' when wait_Sample_pulse3,
							'0' when wait_Sample_pulse4,
							'0' when wait_Sample_pulse5,
							'1' when wait_busy_1,							
							'1' when wait_busy_2,							
							'1' when wait_busy_3,														
							'1' when wait_busy_4,							
							'1' when read_ADCsl_1,
							'1' when read_ADCsl_2,
							'1' when read_ADCsh,
							'1' when scan_outputs,
							'1' when conversion_done,
							'1' when meas_done,
							'0' when others;
	WITH state SELECT
	OE_temp 			<=	'1' when idle,
							'0' when read_ADCsl_1,
							'0' when read_ADCsl_2,
							'0' when read_ADCsh,
							'0' when scan_outputs,
							'1' when conversion_done,
							'1' when others;		
					
					
					
		
				
	WITH state SELECT
	ADC_count_rst		<=	'0' when idle,
							'1' when read_ADCsh,
							'0' when scan_outputs,
							'0' when conversion_done,
							'0' when others;
				
				
				
	WITH state SELECT
	timer_init			<=	'1' when idle,  -- TO GET RID OF "1" ON adc SAMPLE INPUTS
							'1' when wait_trigger,
							'0' when others;				
				
	WITH state SELECT
	addr_cnt_rst		<=	'1' when idle,
							'0' when read_ADCsh,
							'0' when scan_outputs,
							'0' when conversion_done,
							'0' when others;				

				
				
	WITH state SELECT
	Channel_count_rst 	<=	'1' when idle,
							'1' when wait_convst,
							'1' when wait_busy_3,							
							'0' when others;
							
							
							
					
							
	with state select						
	armed <=				'0' when idle,
							'1' when wait_trigger,
							'0' when conversion_done,	
							'1' when others;						
		
	with state select						
	meas_num_rst <=			'1' when idle,
							'1' when wait_trigger,
							'0' when others;
	
	
	with state select						
	meas_num_count_en <=	'0' when idle,
							'1' when conversion_done,
							'0' when others;					



ADC_CONVST_A <= ADC_sample; --or sample;
ADC_CONVST_B <= ADC_sample; --or sample;
ADC_CONVST_C <= ADC_sample; --or sample;						
							
--generation of glitch-free signals
process(clk,reset)
begin
	if clk'event and clk='0' then
		ADC_CS <= CS_temp;
		ADC_RD <= RD_temp;
		BUF_SEL <= ADC_count;
		ADC_OE <=OE_temp;	 
		ADC_RST <= ADC_RST_temp; 
		
	end if;
end process;

--ADC_RST <= reset;

addr_cnt_en_temp <= result_wr_en_temp when (Single_Channel_Mode = '0'and result_wr_en_temp1 = '1') else
			   result_wr_en_temp when (Single_Channel_Mode_Channel_number = ADC_CHANNEL) and Single_Channel_Mode = '1' 
				else '0' ;

-- delay address count and wrte strobe  by 1 clk cycle
process(clk,reset)
begin
	if clk'event and clk='1' then
		addr_cnt_en <= addr_cnt_en_temp;
		result_wr_en_temp<= result_wr_en_temp1;	
		result_wr_en <= addr_cnt_en_temp;
		end if;
end process;





process(clk,reset)
begin
	if clk'event and clk='1' then
			if addr_cnt_rst = '1' then
				addr_cnt <= (others => '0');
			elsif addr_cnt_en = '1'  then
				addr_cnt<=addr_cnt + '1';		
			end if;		
	end if;
end process;




--for 36 channel operation, do the channel sorting and proper layout in the memory.
--delay address by one clock cycle to align it with ADC data correctly
process(clk,reset)
begin
	if clk'event and clk='1' then
		addr_36ch_dpram <= Acq36_cnt + ADC_CHANNEL;
	end if;		
end process;

DPRAM_WR_ADDR <= addr_cnt(12 downto 0) when Single_Channel_Mode = '1' else addr_36ch_dpram;


 
process(clk,reset)
begin
	if clk'event and clk='1' then
			if meas_num_rst = '1' then
				measurements_counter <= (others => '0');
				meas_num_done <= '0';
			elsif meas_num_count_en = '1' and meas_num_done = '0' then
				measurements_counter<=measurements_counter + '1';		
			end if;		
			if measurements_counter = (num_of_measurements - '1') then
			--DEBUG
			--
				meas_num_done <= '1';
			--
			--
			end if;	
	end if;
end process;











-- data set counter, counts number of 36-channel acqusitions

process(clk,addr_cnt_rst)
begin
	if clk'event and clk='1' then
			if addr_cnt_rst = '1' then
				Acq36_cnt <= (others => '0');
			elsif Acq36_cnt_en = '1' then
				Acq36_cnt <=Acq36_cnt+ std_logic_vector(to_signed(36,8));		
			end if;		
	end if;
end process;



-- currently read ADC counter
process(clk,reset)
begin
	if clk'event and clk='1' then
			if ADC_count_rst = '1' then
				ADC_count <= (others => '0');
			elsif ADC_count_en='1' then
				ADC_count <=ADC_count+'1';		
			end if;		
	end if;
end process;

--currently read ADC channel
process(clk,reset)
begin
	if clk'event and clk='1' then
		if Channel_count_rst = '1' then
			Channel_count <= (others => '0');
		elsif Channel_count_en='1' then
			Channel_count <=Channel_count+'1';		
		end if;
		
	end if;
end process;



--currently read ADC channel
process(clk,reset)
begin
	if clk'event and clk='0' then
					data_WR1 <= ADC_DATA;	
	end if;
end process;

process(clk,reset)
begin
	if clk'event and clk='1' then
			if latch_adc_result = '1' then
				--	data_WR1 <= "000" & addr_cnt(12 downto 0);	
					data_WR <= data_WR1;		
			end if;
	end if;
end process;




--***************************************************************************************************
--***************************************   ADC sorting look-up-table *******************************
--***************************************************************************************************

--subtract 1 since both counters cout from 1 to 6
	ADC_number <= '0' & (Channel_count - '1') & '0' & (ADC_count - 	std_logic_vector(to_signed(1,3)));

ADC_CH_SORT: with ADC_number select
	ADC_CHANNEL <= 	std_logic_vector(to_signed(35,6)) when x"00",
					std_logic_vector(to_signed(23,6)) when x"01",
					std_logic_vector(to_signed(2,6)) when x"02",
					std_logic_vector(to_signed(5,6)) when x"03",
					std_logic_vector(to_signed(20,6)) when x"04",
					std_logic_vector(to_signed(17,6)) when x"05",
					std_logic_vector(to_signed(34,6)) when x"10",
					std_logic_vector(to_signed(31,6)) when x"11",
					std_logic_vector(to_signed(10,6)) when x"12",
					std_logic_vector(to_signed(13,6)) when x"13",
					std_logic_vector(to_signed(28,6)) when x"14",
					std_logic_vector(to_signed(25,6)) when x"15",
					std_logic_vector(to_signed(33,6)) when x"20",
					std_logic_vector(to_signed(0,6)) when x"21",
					std_logic_vector(to_signed(3,6)) when x"22",
					std_logic_vector(to_signed(6,6)) when x"23",
					std_logic_vector(to_signed(21,6)) when x"24",
					std_logic_vector(to_signed(18,6)) when x"25",
					std_logic_vector(to_signed(32,6)) when x"30",
					std_logic_vector(to_signed(8,6)) when x"31",
					std_logic_vector(to_signed(11,6)) when x"32",
					std_logic_vector(to_signed(14,6)) when x"33",
					std_logic_vector(to_signed(29,6)) when x"34",
					std_logic_vector(to_signed(26,6)) when x"35",
					std_logic_vector(to_signed(16,6)) when x"40",
					std_logic_vector(to_signed(1,6)) when x"41",
					std_logic_vector(to_signed(4,6)) when x"42",
					std_logic_vector(to_signed(7,6)) when x"43",
					std_logic_vector(to_signed(22,6)) when x"44",
					std_logic_vector(to_signed(19,6)) when x"45",
					std_logic_vector(to_signed(24,6)) when x"50",
					std_logic_vector(to_signed(9,6)) when x"51",
					std_logic_vector(to_signed(12,6)) when x"52",
					std_logic_vector(to_signed(15,6)) when x"53",
					std_logic_vector(to_signed(30,6)) when x"54",
					std_logic_vector(to_signed(27,6)) when x"55",	
					std_logic_vector(to_signed(36,6)) when others; -- write nowhere - this position will be overwritten anyway and should never happen1



--***************************************************************************************************
--***************************************   trigger edge detection    *******************************
--***************************************************************************************************
	
	edge_rege(0)<= TRIG1 when trig_select = '0' else TRIG2 ;
	edge_regi(0) <= software_trigger;
	
 process (clk)
 begin
 if rising_edge(clk) then
--ext trigger
	edge_rege(1)<=edge_rege(0);
	edge_rege(2)<=edge_rege(1);
	edge_rege(3)<=edge_rege(2);
--int software trigger	
	edge_regi(1)<=edge_regi(0);
	edge_regi(2)<=edge_regi(1);
	edge_regi(3)<=edge_regi(2);
 end if;
 end process;
 
	trigger_ext <= (not edge_rege(3)) and (not edge_rege(2)) and edge_rege(1)and edge_rege(0) ;
	trigger_int <= (not edge_regi(3)) and (not edge_regi(2)) and edge_regi(1)and edge_regi(0) ;

	trigger <= trigger_int or trigger_ext;
	
--*************************************************************************************************************	
--sample clock generator
--*************************************************************************************************************
process (clk25, reset)
begin  -- process count
  if reset = '1' or timer_init = '1' then                   -- asynchronous reset (active high)
    timer <= x"0001";  		            -- set the timer to 1 in order to generate mesurmeent one cycle after trigger
	sample_clk_int <= '0';   
  elsif clk25'event and clk25 = '1' then    -- rising clock edge
    timer <= timer - '1';             -- decrease counts
    if timer = x"0000" then
          timer <= sampling_freq;
	  sample_clk_int <= '1';
	else
	  sample_clk_int <= '0';
    end if;
  end if;
end process count;

sample <= sample_clk_ext when sampling_clk_source = '1' else  sample_clk_int;
sample_clk_out <= sample;

END AD7656_readout_architecture;

