----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    11:39:20 10/23/2015 
-- Design Name: 
-- Module Name:    dac_interface - Behavioral 
-- Project Name: 
-- Target Devices: 
-- 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 using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

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


entity dac_interface is
port(
	-- in
	reg_clk: in STD_LOGIC;
	sys_clk125: in STD_LOGIC;
	dac_clk_in: in STD_LOGIC;
	dac_clk_rst: in STD_LOGIC;		-- sys_clk_dll_reset
	
	dac_ctrl_reg: in STD_LOGIC_VECTOR(32 downto 0);
	dac_data_reg: in STD_LOGIC_VECTOR(32 downto 0);
	addr_0x20_reg_q: in STD_LOGIC_VECTOR(32 downto 0);
	addr_0x4E_reg_q: in STD_LOGIC_VECTOR(32 downto 0);
	addr_0x4F_reg_q: in STD_LOGIC_VECTOR(32 downto 0);

	dac1_ram_wea: in STD_LOGIC_VECTOR(0 downto 0);
	dac1_ram_addra: in STD_LOGIC_VECTOR(31 downto 0);
	dac1_ram_dina: in STD_LOGIC_VECTOR(31 downto 0);
	dac2_ram_wea: in STD_LOGIC_VECTOR(0 downto 0);
	dac2_ram_addra: in STD_LOGIC_VECTOR(31 downto 0);
	dac2_ram_dina: in STD_LOGIC_VECTOR(31 downto 0);
	
	dac1_adc_pipe_din: in std_logic_vector(15 downto 0);	-- adc_ch1_pipe_din
	dac2_adc_pipe_din: in std_logic_vector(15 downto 0);	-- adc_ch2_pipe_din

	external_trigger_signal: in STD_LOGIC;		-- external_ored_trigger_signal
	
	adc_ch1_trigger_pulse: in STD_LOGIC;		-- internal adc_ch<x>_trigger_out_length_pulse
	adc_ch2_trigger_pulse: in STD_LOGIC;
	adc_ch3_trigger_pulse: in STD_LOGIC;
	adc_ch4_trigger_pulse: in STD_LOGIC;
	adc_ch5_trigger_pulse: in STD_LOGIC;
	adc_ch6_trigger_pulse: in STD_LOGIC;
	adc_ch7_trigger_pulse: in STD_LOGIC;
	adc_ch8_trigger_pulse: in STD_LOGIC;
	adc_ch9_trigger_pulse: in STD_LOGIC;
	adc_ch10_trigger_pulse: in STD_LOGIC;
	
	-- out
	addr_0x20_reg_feedback: out STD_LOGIC_VECTOR(31 downto 0);
	addr_0x4E_reg_feedback: out STD_LOGIC_VECTOR(31 downto 0);
	addr_0x4F_reg_feedback: out STD_LOGIC_VECTOR(31 downto 0);
	
	dac_clk_test1 : OUT std_logic;
	dac_clk_test2 : OUT std_logic;
	
	MUX_DAC_SEL0: out STD_LOGIC;
  	MUX_DAC_SEL1: out STD_LOGIC; 
	DAC_PD_H: out STD_LOGIC;
	DAC_TORB: out STD_LOGIC;
	DAC_SELIQ_P: out STD_LOGIC;
	DAC_SELIQ_N: out STD_LOGIC;
	DAC_D_P: out STD_LOGIC_VECTOR(15 downto 0);
	DAC_D_N: out STD_LOGIC_VECTOR(15 downto 0)
);
end dac_interface;

architecture Behavioral of dac_interface is

	COMPONENT risingedge2pulse_generator
	PORT(
		adc_clk : IN std_logic;
		rising_edge_signal_in : IN std_logic;          
		signal_pulse_out : OUT std_logic
		);
	END COMPONENT;


	COMPONENT bram_dac_64kx16b
	  PORT (
		 clka : IN STD_LOGIC;
		 wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
		 addra : IN STD_LOGIC_VECTOR(14 DOWNTO 0);
		 dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
		 clkb : IN STD_LOGIC;
		 addrb : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
		 doutb : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
	  );
	END COMPONENT;


	COMPONENT dac_fd_out_logic
	PORT(
		sys_clk125 : in  STD_LOGIC;
		dac_clk_in : IN std_logic;
		dac_odelay_clk : IN std_logic;
		dac_odelay_rst : IN std_logic;
		dac_odelay_value : IN std_logic_vector(4 downto 0);
		dac_dcm_reset_pulse : IN std_logic;
		dac1_data_out : IN std_logic_vector(15 downto 0);
		dac2_data_out : IN std_logic_vector(15 downto 0);		
		dac_clk_dcm_lock : IN std_logic;
		dac_out_synch_clk : OUT std_logic;
		dac_clk_test1 : OUT std_logic;
		dac_clk_test2 : OUT std_logic;
		DAC_SELIQ_P : OUT std_logic;
		DAC_SELIQ_N : OUT std_logic;
		DAC_D_P : OUT std_logic_vector(15 downto 0);
		DAC_D_N : OUT std_logic_vector(15 downto 0)
		);
	END COMPONENT;
	
	
	COMPONENT sys_clk_distribution
	PORT(
		sys_clk125 : IN std_logic;
		sys_rst : IN std_logic;          
		dac_clk_tap_idelayctrl : OUT std_logic;
		mmcm_locked : OUT std_logic
		);
	END COMPONENT;

signal dac_synch_clk: std_logic;

signal dac_dcm_reset_pulse: std_logic;
signal dac_tap_write_pulse: std_logic;

signal dac_test_mode: std_logic_vector(1 downto 0);

signal dac_data_mux_out:  STD_LOGIC_VECTOR(15 downto 0);

signal dac1_ram_wea_latch, dac2_ram_wea_latch: STD_LOGIC_VECTOR(0 downto 0);
signal dac1_ram_addra_latch, dac2_ram_addra_latch: STD_LOGIC_VECTOR(31 downto 0);
signal dac1_ram_dina_latch, dac2_ram_dina_latch: STD_LOGIC_VECTOR(31 downto 0);

signal dac_test_counter:  STD_LOGIC_VECTOR(19 downto 0);
signal dac1_data_out, dac2_data_out:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_addra_counter, dac2_ram_addra_counter:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_addrb_counter, dac2_ram_addrb_counter:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_addrb_counter_latch, dac2_ram_addrb_counter_latch:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_addrb_end_pointer, dac2_ram_addrb_end_pointer:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_doutb, dac2_ram_doutb:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_doutb_latch, dac2_ram_doutb_latch:  STD_LOGIC_VECTOR(15 downto 0);
signal dac1_ram_clk_prescaler, dac2_ram_clk_prescaler:  STD_LOGIC_VECTOR(7 downto 0);
signal dac1_ram_clk_prescaler_counter, dac2_ram_clk_prescaler_counter:  STD_LOGIC_VECTOR(7 downto 0);
signal dac1_ram_clk_prescaler_pulse, dac2_ram_clk_prescaler_pulse:  STD_LOGIC;
signal dac1_ram_addrb_counter_reset, dac2_ram_addrb_counter_reset:  STD_LOGIC;
signal dac1_ram_wen_pulse, dac2_ram_wen_pulse:  STD_LOGIC_VECTOR(0 downto 0);
signal dac1_disable_pulse, dac2_disable_pulse	: std_logic;
signal dac1_arm_tigger_pulse, dac2_arm_tigger_pulse	: std_logic;
signal dac1_soft_trigger, dac2_soft_trigger		: std_logic;

signal dac1_trigger_delay1, dac1_trigger_delay2, dac1_trigger_pulse : std_logic;
signal dac2_trigger_delay1, dac2_trigger_delay2, dac2_trigger_pulse : std_logic;
signal dac1_intern_trigger_mux_pulse, dac2_intern_trigger_mux_pulse : std_logic;
signal dac1_start_output, dac2_start_output: std_logic;
signal dac1_output_in_process, dac2_output_in_process: std_logic;
signal dac1_output_in_process_delay1, dac2_output_in_process_delay1: std_logic;
signal dac1_output_in_process_delay2, dac2_output_in_process_delay2: std_logic;
signal dac1_wrap_enable, dac2_wrap_enable: std_logic;
signal dac1_trigger_status, dac2_trigger_status: std_logic;
signal dac1_arm_for_trigger, dac2_arm_for_trigger : std_logic;
signal synch_dac1_clk_soft_trigger, synch_dac2_clk_soft_trigger		: std_logic;
signal synch_dac1_clk_external_trigger, synch_dac2_clk_external_trigger	: std_logic;
signal synch_dac1_clk_internal_trigger, synch_dac2_clk_internal_trigger	: std_logic;
type fsm_dac_control_type is(
	WAIT_OF_TRIGGER,
	WAIT_OF_READ_LOGIC,
	TRIGGERED
);
signal dac1_fsm_state, dac2_fsm_state 	: fsm_dac_control_type;

signal dac_clk_tap_idelayctrl : std_logic;
signal dac_clk_dcm_lock : std_logic;

begin


	dac1_ram_addrb_counter_reset <= dac_dcm_reset_pulse or dac1_disable_pulse;
	dac2_ram_addrb_counter_reset <= dac_dcm_reset_pulse or dac2_disable_pulse;

dac_reg_logic : process(reg_clk)
begin

	DAC_PD_H      	<=  not dac_ctrl_reg(5)  ; 
   DAC_TORB      	<=      dac_ctrl_reg(4)  ;

  	MUX_DAC_SEL1	<=      dac_ctrl_reg(17)  ; 
	MUX_DAC_SEL0   <=      dac_ctrl_reg(16)  ; 
	
	if rising_edge(reg_clk) then
		dac_dcm_reset_pulse  		<=  dac_ctrl_reg(32) and dac_ctrl_reg(8)  ;
		dac_tap_write_pulse  		<=  dac_ctrl_reg(32) and dac_ctrl_reg(31)  ;
		
		dac1_wrap_enable				<= dac_ctrl_reg(20);
		dac2_wrap_enable				<= dac_ctrl_reg(21);
	
		addr_0x20_reg_feedback(31 downto 6)	<=  (others => '0');
		addr_0x20_reg_feedback(5 downto 4)	<= addr_0x20_reg_q(5 downto 4);
		addr_0x20_reg_feedback(3)				<= dac2_arm_for_trigger;
		addr_0x20_reg_feedback(2) 				<= dac2_trigger_status;
		addr_0x20_reg_feedback(1)				<= dac1_arm_for_trigger;
		addr_0x20_reg_feedback(0) 				<= dac1_trigger_status;
		
		addr_0x4E_reg_feedback(31 downto 0)	<= addr_0x4E_reg_q(31 downto 0);
		
		dac1_disable_pulse		<= addr_0x20_reg_q(32) and addr_0x20_reg_q(4);
		dac2_disable_pulse		<= addr_0x20_reg_q(32) and addr_0x20_reg_q(5);
		dac1_arm_tigger_pulse	<=	addr_0x20_reg_q(32) and addr_0x20_reg_q(1);
		dac2_arm_tigger_pulse	<=	addr_0x20_reg_q(32) and addr_0x20_reg_q(3);
		dac1_soft_trigger			<=	addr_0x20_reg_q(32) and addr_0x20_reg_q(0);
		dac2_soft_trigger			<= addr_0x20_reg_q(32) and addr_0x20_reg_q(2);	

	end if;
end process;


-- DAC trigger logic
dac1_arm_for_trigger_logic: process (reg_clk) 
begin
	if(dac_dcm_reset_pulse = '1') then
		dac1_arm_for_trigger <= '0';
   elsif rising_edge(reg_clk) then  --
		if(dac1_disable_pulse = '1') then
			dac1_arm_for_trigger <= '0';
		elsif((dac1_arm_tigger_pulse = '1') or (dac1_soft_trigger = '1')) then
			dac1_arm_for_trigger <= '1';
		else
			dac1_arm_for_trigger <= dac1_arm_for_trigger;
		end if;
   end if;
end process;

dac2_arm_for_trigger_logic: process (reg_clk) 
begin
	if(dac_dcm_reset_pulse = '1') then
		dac2_arm_for_trigger <= '0';
   elsif rising_edge(reg_clk) then  --
		if(dac2_disable_pulse = '1') then
			dac2_arm_for_trigger <= '0';
		elsif((dac2_arm_tigger_pulse = '1') or (dac2_soft_trigger = '1')) then
			dac2_arm_for_trigger <= '1';
		else
			dac2_arm_for_trigger <= dac2_arm_for_trigger;
		end if;
   end if;
end process;


-- DAC RAM
dac_ram_latch_logic : process(reg_clk)
begin
	if rising_edge(reg_clk) then
		dac1_ram_wea_latch 	<= dac1_ram_wea;
		dac1_ram_addra_latch <= dac1_ram_addra;
		dac1_ram_dina_latch	<= dac1_ram_dina;
		
		dac2_ram_wea_latch 	<= dac2_ram_wea;
		dac2_ram_addra_latch <= dac2_ram_addra;
		dac2_ram_dina_latch	<= dac2_ram_dina;
	end if;
end process;

Inst_dac1_bram_64kx16b : bram_dac_64kx16b
  PORT MAP (
	 clka => reg_clk,
	 wea => dac1_ram_wea_latch,
	 addra => dac1_ram_addra_latch(14 downto 0),
	 dina => dac1_ram_dina_latch,
	 clkb => dac_synch_clk,
	 addrb => dac1_ram_addrb_counter(15 downto 0),
	 doutb => dac1_ram_doutb
  );

Inst_dac2_bram_64kx16b : bram_dac_64kx16b
  PORT MAP (
	 clka => reg_clk,
	 wea => dac2_ram_wea_latch,
	 addra => dac2_ram_addra_latch(14 downto 0),
	 dina => dac2_ram_dina_latch,
	 clkb => dac_synch_clk,
	 addrb => dac2_ram_addrb_counter(15 downto 0),
	 doutb => dac2_ram_doutb
  );


-- DAC RAM endpoint
dac_bram_end_point_logic: process (dac_synch_clk) 
begin
	if rising_edge(dac_synch_clk) then
		dac2_ram_addrb_end_pointer 				<= addr_0x4F_reg_q(31 downto 16);
		dac1_ram_addrb_end_pointer				 	<= addr_0x4F_reg_q(15 downto  0);
		addr_0x4F_reg_feedback(31 downto 0) 	<= addr_0x4F_reg_q(31 downto  0);			
	end if;
end process;


-- DAC readout
dac1_bram_read_and_output_fsm: process (dac_synch_clk) 
begin
	if ((dac1_ram_addrb_counter_reset = '1') or (dac_test_mode /= "11"))then 
		dac1_start_output  		<= '0';						-- 1
		dac1_trigger_status		<= '0';						-- 2
		dac1_fsm_state				<= WAIT_OF_TRIGGER;		--	3
	elsif rising_edge(dac_synch_clk) then  --
	
		case dac1_fsm_state is
			when WAIT_OF_TRIGGER =>
				if(dac1_trigger_pulse = '1') then
					dac1_start_output 		<= '1';						-- 1
					dac1_trigger_status		<= '1';						-- 2							
					dac1_fsm_state				<= WAIT_OF_READ_LOGIC;	--	3
				else
					dac1_start_output 		<= '0';						-- 1
					dac1_trigger_status		<= '0';						-- 2
					dac1_fsm_state				<= WAIT_OF_TRIGGER;		--	3
				end if;
				
			when WAIT_OF_READ_LOGIC =>	
				dac1_start_output 		<= '1';							-- 1
				dac1_trigger_status		<= '1';							-- 2
				if(dac1_output_in_process = '1') then
					dac1_fsm_state			<= TRIGGERED;					--	3
				else
					dac1_fsm_state			<= WAIT_OF_READ_LOGIC;		--	3		
				end if;						
			
			when TRIGGERED =>
				if(dac1_output_in_process = '1') then
					dac1_start_output 		<= '1';						-- 1
					dac1_trigger_status		<= '1';						-- 2
					dac1_fsm_state				<= TRIGGERED;				--	3
				else
					dac1_start_output 		<= '0';						-- 1
					dac1_trigger_status		<= '0';						-- 2
					dac1_fsm_state				<= WAIT_OF_TRIGGER;		--	3		
				end if;
				
			when others =>
				dac1_start_output 	<= '0';								-- 1
				dac1_trigger_status	<= '0';								-- 2
				dac1_fsm_state			<= WAIT_OF_TRIGGER;				--	3					
		end case;
	end if;	
end process;

dac1_bram_read_and_output_logic: process (dac_synch_clk) 
begin
	if ((dac1_ram_addrb_counter_reset = '1') or (dac_test_mode /= "11")) then 
		dac1_ram_addrb_counter <= X"0000";
		dac1_output_in_process	<= '0';
	elsif rising_edge(dac_synch_clk) then  -- 
		if(dac1_start_output = '1') then
			if(dac1_ram_addrb_counter /= dac1_ram_addrb_end_pointer)then
				if(dac1_ram_clk_prescaler_pulse = '1') then
					dac1_ram_addrb_counter <= dac1_ram_addrb_counter + 1;
				else
					dac1_ram_addrb_counter <= dac1_ram_addrb_counter;
				end if;
				dac1_output_in_process	<= '1';
			elsif(dac1_wrap_enable = '1') then				-- 
				dac1_ram_addrb_counter <= X"0000";
				dac1_output_in_process	<= '1';				
			else
				dac1_ram_addrb_counter <= dac1_ram_addrb_counter;
				dac1_output_in_process	<= '0';					
			end if;
		else
			dac1_ram_addrb_counter <= X"0000";
			dac1_output_in_process	<= '0';
		end if;
	end if;
end process;	


dac1_bram_doutb_latch: process(dac_synch_clk)
begin
	
	dac1_output_in_process_delay1 <= dac1_output_in_process;
	dac1_output_in_process_delay2 <= dac1_output_in_process_delay1;

	if (dac1_ram_addrb_counter_reset = '1') then 
		dac1_ram_doutb_latch <= x"8000";
	elsif rising_edge(dac_synch_clk) then
		if(dac1_output_in_process_delay2 = '1') then
			dac1_ram_doutb_latch <= dac1_ram_doutb;
		else
			dac1_ram_doutb_latch <= dac1_ram_doutb_latch;
		end if;
	end if;
end process;



dac2_bram_read_and_output_fsm: process(dac_synch_clk)
begin
	if ((dac2_ram_addrb_counter_reset = '1') or (dac_test_mode /= "11"))then 
		dac2_start_output 	<= '0';								-- 1
		dac2_trigger_status		<= '0';							-- 2
		dac2_fsm_state					<= WAIT_OF_TRIGGER;		--	3
	elsif rising_edge(dac_synch_clk) then  --

		case dac2_fsm_state is
			when WAIT_OF_TRIGGER =>
				if(dac2_trigger_pulse = '1') then
					dac2_start_output 		<= '1';						-- 1
					dac2_trigger_status		<= '1';						-- 2							
					dac2_fsm_state				<= WAIT_OF_READ_LOGIC;	--	3
				else
					dac2_start_output 		<= '0';						-- 1
					dac2_trigger_status		<= '0';						-- 2
					dac2_fsm_state				<= WAIT_OF_TRIGGER;		--	3
				end if;
				
			when WAIT_OF_READ_LOGIC =>	
				dac2_start_output 		<= '1';							-- 1
				dac2_trigger_status		<= '1';							-- 2
				if(dac2_output_in_process = '1') then
					dac2_fsm_state			<= TRIGGERED;					--	3
				else
					dac2_fsm_state			<= WAIT_OF_READ_LOGIC;		--	3		
				end if;						
			
			when TRIGGERED =>
				if(dac2_output_in_process = '1') then
					dac2_start_output 		<= '1';						-- 1
					dac2_trigger_status		<= '1';						-- 2
					dac2_fsm_state				<= TRIGGERED;				--	3
				else
					dac2_start_output 		<= '0';						-- 1
					dac2_trigger_status		<= '0';						-- 2
					dac2_fsm_state				<= WAIT_OF_TRIGGER;		--	3		
				end if;
				
			when others =>
				dac2_start_output 	<= '0';								-- 1
				dac2_trigger_status	<= '0';								-- 2
				dac2_fsm_state			<= WAIT_OF_TRIGGER;				--	3					
		end case;
	end if;	
end process;
		
dac2_bram_read_and_output_logic: process(dac_synch_clk)
begin	
	if ((dac2_ram_addrb_counter_reset = '1') or (dac_test_mode /= "11")) then 
		dac2_ram_addrb_counter <= X"0000";
		dac2_output_in_process	<= '0';
	elsif rising_edge(dac_synch_clk) then  -- 
		if(dac2_start_output = '1') then
			if(dac2_ram_addrb_counter /= dac2_ram_addrb_end_pointer)then
				if(dac2_ram_clk_prescaler_pulse = '1') then
					dac2_ram_addrb_counter <= dac2_ram_addrb_counter + 1;
				else
					dac2_ram_addrb_counter <= dac2_ram_addrb_counter;
				end if;
				dac2_output_in_process	<= '1';
			elsif(dac2_wrap_enable = '1') then				-- 
				dac2_ram_addrb_counter <= X"0000";
				dac2_output_in_process	<= '1';				
			else
				dac2_ram_addrb_counter <= dac2_ram_addrb_counter;
				dac2_output_in_process	<= '0';					
			end if;
		else
			dac2_ram_addrb_counter <= X"0000";
			dac2_output_in_process	<= '0';
		end if;
	end if;
end process;


dac2_bram_doutb_latch: process(dac_synch_clk)
begin

	dac2_output_in_process_delay1 <= dac2_output_in_process;
	dac2_output_in_process_delay2 <= dac2_output_in_process_delay1;

	if (dac2_ram_addrb_counter_reset = '1') then 
		dac2_ram_doutb_latch <= x"8000";
	elsif rising_edge(dac_synch_clk) then
		if(dac2_output_in_process_delay1 = '1') then
			dac2_ram_doutb_latch <= dac2_ram_doutb;
		else
			dac2_ram_doutb_latch <= dac2_ram_doutb_latch;
		end if;
	end if;
end process;


-- DAC clk prescaler
dac1_clk_prescaler_logic: process (dac_synch_clk) 
begin
	if rising_edge(dac_synch_clk) then  -- 
		if (dac1_start_output = '0') then
			dac1_ram_clk_prescaler			 <= addr_0x4E_reg_q(23 downto 16);
			dac1_ram_clk_prescaler_counter <= addr_0x4E_reg_q(23 downto 16);
			dac1_ram_clk_prescaler_pulse <= '0';
		elsif(dac1_ram_clk_prescaler_counter /= x"0000") then
				dac1_ram_clk_prescaler			 	<= dac1_ram_clk_prescaler;
				dac1_ram_clk_prescaler_counter 	<= dac1_ram_clk_prescaler_counter - 1;
				dac1_ram_clk_prescaler_pulse 		<= '0';
			else
				dac1_ram_clk_prescaler			 	<= dac1_ram_clk_prescaler;
				dac1_ram_clk_prescaler_counter 	<= dac1_ram_clk_prescaler;
				dac1_ram_clk_prescaler_pulse 		<= '1';
			end if;
	end if;
end process;

dac2_clk_prescaler_logic: process (dac_synch_clk) 
begin	
	if rising_edge(dac_synch_clk) then  --
		if (dac2_start_output = '0') then
			dac2_ram_clk_prescaler			 <= addr_0x4E_reg_q(31 downto 24);
			dac2_ram_clk_prescaler_counter <= addr_0x4E_reg_q(31 downto 24);
			dac2_ram_clk_prescaler_pulse <= '0'; 
		elsif(dac2_ram_clk_prescaler_counter /= x"0000") then
				dac2_ram_clk_prescaler			 	<= dac2_ram_clk_prescaler;
				dac2_ram_clk_prescaler_counter 	<= dac2_ram_clk_prescaler_counter - 1;
				dac2_ram_clk_prescaler_pulse 		<= '0';
			else
				dac2_ram_clk_prescaler			 	<= dac2_ram_clk_prescaler;
				dac2_ram_clk_prescaler_counter 	<= dac2_ram_clk_prescaler;
				dac2_ram_clk_prescaler_pulse 		<= '1';
			end if;
	end if;
end process;


-- Internal trigger multiplexer
-- DAC 1
with addr_0x4E_reg_q(3 downto 0) select
	dac1_intern_trigger_mux_pulse	<= 	adc_ch1_trigger_pulse when x"0",
													adc_ch2_trigger_pulse when x"1",
													adc_ch3_trigger_pulse when x"2",
													adc_ch4_trigger_pulse when x"3",
													adc_ch5_trigger_pulse when x"4",
													adc_ch6_trigger_pulse when x"5",
													adc_ch7_trigger_pulse when x"6",
													adc_ch8_trigger_pulse when x"7",
													adc_ch9_trigger_pulse when x"8",
													adc_ch10_trigger_pulse when x"9",
													'0'						 when others;
														
-- DAC 2	
with addr_0x4E_reg_q(11 downto 8) select
	dac2_intern_trigger_mux_pulse	<= 	adc_ch1_trigger_pulse when x"0",
													adc_ch2_trigger_pulse when x"1",
													adc_ch3_trigger_pulse when x"2",
													adc_ch4_trigger_pulse when x"3",
													adc_ch5_trigger_pulse when x"4",
													adc_ch6_trigger_pulse when x"5",
													adc_ch7_trigger_pulse when x"6",
													adc_ch8_trigger_pulse when x"7",
													adc_ch9_trigger_pulse when x"8",
													adc_ch10_trigger_pulse when x"9",
													'0'						 when others;


-- DAC 1
-- software trigger synch with dac_synch_clk domain 
dac1_sync_soft_trigger_dac_clk_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
	adc_clk => dac_synch_clk,
	rising_edge_signal_in => dac1_soft_trigger,
	signal_pulse_out => synch_dac1_clk_soft_trigger
);
 
-- external trigger synch with dac_synch_clk domain 
dac1_external_trigger_dac_clk_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
	adc_clk => dac_synch_clk,
	rising_edge_signal_in => external_trigger_signal,
	signal_pulse_out => synch_dac1_clk_external_trigger
);

-- internal trigger synch with dac_synch_clk domain 
dac1_internal_trigger_dac_clk_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
	adc_clk => dac_synch_clk,
	rising_edge_signal_in => dac1_intern_trigger_mux_pulse,
	signal_pulse_out => synch_dac1_clk_internal_trigger
);

-- DAC 2
-- software trigger synch with dac_synch_clk domain 
dac2_sync_soft_trigger_dac_clk_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
	adc_clk => dac_synch_clk,
	rising_edge_signal_in => dac2_soft_trigger,
	signal_pulse_out => synch_dac2_clk_soft_trigger
);
 
-- external trigger synch with dac_synch_clk domain 
dac2_external_trigger_dac_clk_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
	adc_clk => dac_synch_clk,
	rising_edge_signal_in => external_trigger_signal,
	signal_pulse_out => synch_dac2_clk_external_trigger
);

-- internal trigger synch with dac_synch_clk domain 
dac2_internal_trigger_dac_clk_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
	adc_clk => dac_synch_clk,
	rising_edge_signal_in => dac2_intern_trigger_mux_pulse,
	signal_pulse_out => synch_dac2_clk_internal_trigger
);	


-- Trigger control logic
dac_trigger_control_logic: process(dac_synch_clk)
begin
	if rising_edge(dac_synch_clk) then
	
		dac1_trigger_pulse <= 	dac1_arm_for_trigger and (
											 synch_dac1_clk_soft_trigger
										or	(synch_dac1_clk_external_trigger and addr_0x4E_reg_q(5))
										or (synch_dac1_clk_internal_trigger and addr_0x4E_reg_q(4))
										);
		
		dac2_trigger_pulse <= 	dac2_arm_for_trigger and (	 
											 synch_dac2_clk_soft_trigger
										or	(synch_dac2_clk_external_trigger and addr_0x4E_reg_q(13))
										or (synch_dac2_clk_internal_trigger and addr_0x4E_reg_q(12))
										);
	end if;
end process;


-- Testcounter and data mux
dac_test_logic: process (dac_synch_clk, dac_clk_rst) 
begin
   if rising_edge(dac_synch_clk) then  -- 
       dac_test_mode <=  dac_ctrl_reg(1 downto 0)  ; 
   end if;

   if ((dac_clk_rst='1') or (dac_test_mode /= "01")) then 
      dac_test_counter <= X"00000";
    elsif rising_edge(dac_synch_clk) then  -- 
		dac_test_counter <= dac_test_counter + 11;
   end if;


   if rising_edge(dac_synch_clk) then  -- 
			case dac_test_mode(1 downto 0) is
				when "00" =>
			      dac1_data_out(15)           <=   not dac_data_reg(15);
               dac1_data_out(14 downto 0)  <=       dac_data_reg(14 downto 0);
               dac2_data_out(15)           <=   not dac_data_reg(31);
               dac2_data_out(14 downto 0)  <=       dac_data_reg(30 downto 16);
				when "01" =>
					dac1_data_out(15)           <=   not dac_test_counter(15);
					dac1_data_out(14 downto 0)  <=       dac_test_counter(14 downto 0);
					dac2_data_out(15)           <=   not dac_test_counter(15);
					dac2_data_out(14 downto 0)  <=   not dac_test_counter(14 downto 0);
				when "10" =>			
			      dac1_data_out(15)           <=   not dac1_adc_pipe_din(15);
               dac1_data_out(14 downto 0)  <=       dac1_adc_pipe_din(14 downto 0);
               dac2_data_out(15)           <=   not dac2_adc_pipe_din(15);
               dac2_data_out(14 downto 0)  <=       dac2_adc_pipe_din(14 downto 0);
				when "11" =>
					dac1_data_out(15 downto 0)  <=       dac1_ram_doutb_latch(15 downto 0);
					dac2_data_out(15 downto 0)  <=       dac2_ram_doutb_latch(15 downto 0);
				when others =>
               dac1_data_out(15 downto 0)  <=       X"0000";
               dac2_data_out(15 downto 0)  <=       X"0000";
			end case;
   end if;

end process;


  
	Inst_dac_fd_out_logic: dac_fd_out_logic PORT MAP(
		sys_clk125 => sys_clk125,
		dac_clk_in => dac_clk_in,
		dac_odelay_clk => reg_clk,
		dac_odelay_rst => dac_tap_write_pulse,
		dac_odelay_value => dac_ctrl_reg(28 downto 24),
		dac_dcm_reset_pulse => dac_dcm_reset_pulse,
		dac1_data_out => dac1_data_out,
		dac2_data_out => dac2_data_out,
		dac_clk_dcm_lock => dac_clk_dcm_lock,
		dac_out_synch_clk => dac_synch_clk,
		dac_clk_test1 => dac_clk_test1,
		dac_clk_test2 => dac_clk_test2,
		DAC_SELIQ_P => DAC_SELIQ_P,
		DAC_SELIQ_N => DAC_SELIQ_N,
		DAC_D_P => DAC_D_P,
		DAC_D_N => DAC_D_N
	);

end Behavioral;
