-------------------------------------------------------------
--	Filename:  COM3504TEST.VHD
-- Author: 
--		Alain Zarembowitch / MSS, 
--	Version: 0
--	Date last modified: 9-29-10
-- Inheritance: 	none
--
-- description:  Hardware verification test for the COM-1600 (or COM-1500) + COM-3504 assembly.
-- The COM-3504 plug-in module includes dual 250 MSamples/s 16-bit DACs
-- and dual 150 MSamples/s 12-bit ADCs.
-- Two auxiliary 12-bit DACs and one auxiliary 12-bit ADC are also available for
-- gain control and power measurement.
-- See inside this test component for the actual ADCs and DACs drivers.

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity COM3504TEST is
	generic (
		DAC_SPEEDx: in integer := 2
			-- 1 = same sampling speed for high-speed ADCs and DACs. For example 150/150 MHz
			-- 2 = DAC sampling rate = 2 x ADC sampling rate. For example DAC 250/ ADC 125 MHz
			-- The ADCs sampling rate is set by the reference clock CLK.
	);
    port ( 
			--// Clocks Resets
			CLK: in std_logic;
				-- reference clock for high-speed ADCs (x1) and DACs (x1 or x2 depending on DAC_SPEEDx parameter)
			ASYNC_RESET: in std_logic;
			
			--// CONTROL 
			CONTROL: in std_logic_vector(31 downto 0);
				-- 32-bit control word. meaning depends on signal generator instantiated within

			--// AD9747 Dual 250 MS/s D/A Converter  (connect directly to top-level port)
			-- FPGA - high-speed DAC interface
			DAC1_DOUT: out std_logic_vector(15 downto 0);
			DAC2_DOUT: out std_logic_vector(15 downto 0);
				-- 16-bit output samples (1 per DAC_CLKOUT_P period) .
			DAC_CLKOUT_P: out std_logic;
			DAC_CLKOUT_N: out std_logic;
				-- LVDS differential reference clock (delayed 1/4 CLK period to 
				-- meet the DAC tDBS and tDBH setup and hold requirements
			
			--// AD9627 Dual 150 MS/s A/D Converter (connect directly to top-level port)
			-- FPGA - high-speed ADC interface
			ADC1_DIN: in std_logic_vector(11 downto 0);
			ADC2_DIN: in std_logic_vector(11 downto 0);
				-- AD9627 data samples, 12-bits used, 2 LSbs are ignored
			ADC_DCO: in std_logic_vector(1 downto 0);
				-- two data strobe signals (one for each ADC)
			ADC_CLKOUT_P: out std_logic;
			ADC_CLKOUT_N: out std_logic;
				-- LVDS differential ADC sampling clock 150 MHz max
				
			--// Auxilliary DACs + ADC interface (connect directly to top-level port)
			AUX_SPI1: inout std_logic;	-- SDATA
			AUX_SPI2: out std_logic;	-- SCLK
			AUX_SPI3: out std_logic;	-- AUX DAC1 SYNC#
			AUX_SPI4: out std_logic;	-- AUX DAC2 SYNC#
			AUX_SPI5: out std_logic;	-- AUX ADC CS#
				
			--// TEST POINTS / ComScope monitoring
			ADC1_DOUT: out std_logic_vector(11 downto 0);
			ADC2_DOUT: out std_logic_vector(11 downto 0);
			AUXADC1_DOUT: out std_logic_vector(11 downto 0);
				-- received samples from ADC. Visualize using ComScope.
			TP: out std_logic_vector(10 downto 1)
		
			);
end entity;

architecture Behavioral of COM3504TEST is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
	COMPONENT AD9747_DAC_DRIVER
	generic (
		DAC_SPEEDx: in integer
	);
	PORT(
		CLK : IN std_logic;
		ASYNC_RESET : IN std_logic;
		DAC1A_DIN : IN std_logic_vector(15 downto 0);
		DAC1B_DIN : IN std_logic_vector(15 downto 0);
		DAC2A_DIN : IN std_logic_vector(15 downto 0);
		DAC2B_DIN : IN std_logic_vector(15 downto 0);
		DAC_EN : IN std_logic;          
		DAC1_DOUT : OUT std_logic_vector(15 downto 0);
		DAC2_DOUT : OUT std_logic_vector(15 downto 0);
		DAC_CLKOUT_P : OUT std_logic;
		DAC_CLKOUT_N : OUT std_logic
		);
	END COMPONENT;

	COMPONENT AD9627_ADC_DRIVER
	generic (
		ADC_NBITS: in integer
	);
	PORT(
		CLK : IN std_logic;
		ADC1_DIN : IN std_logic_vector(11 downto 0);
		ADC2_DIN : IN std_logic_vector(11 downto 0);
		ADC_DCO : IN std_logic_vector(1 downto 0);          
		ADC1_DOUT : OUT std_logic_vector(11 downto 0);
		ADC2_DOUT : OUT std_logic_vector(11 downto 0);
		ADC_CLKOUT_P : OUT std_logic;
		ADC_CLKOUT_N : OUT std_logic;
		TP: out std_logic_vector(10 downto 1)
		);
	END COMPONENT;

	COMPONENT DAC_TEST
	PORT(
		CLK : IN std_logic;
		ENABLE_N : IN std_logic;          
		TPS : OUT std_logic_vector(10 downto 1);
		SYNC_B : OUT std_logic;
		SCLK : OUT std_logic;
		SDIN : OUT std_logic
		);
	END COMPONENT;

	COMPONENT DIGITAL_DC2
	PORT(
		CLK : IN std_logic;
		DATA_I_IN : IN std_logic_vector(11 downto 0);
		DATA_Q_IN : IN std_logic_vector(11 downto 0);
		SAMPLE_CLK_IN : IN std_logic;
		PHASE_ROTATION : IN std_logic_vector(11 downto 0);          
		DATA_I_OUT : OUT std_logic_vector(11 downto 0);
		DATA_Q_OUT : OUT std_logic_vector(11 downto 0);
		SAMPLE_CLK_OUT : OUT std_logic;
		SATURATION : OUT std_logic
		);
	END COMPONENT;

	COMPONENT NCO32
	PORT(
		CLK : IN std_logic;
		SYNC_RESET : IN std_logic;
		NOMINAL_FREQUENCY : IN std_logic_vector(31 downto 0);
		PHASE_OFFSET : IN std_logic_vector(31 downto 0);
		PHASE_OFFSET_SAMPLE_CLK : IN std_logic;          
		PHASE : OUT std_logic_vector(31 downto 0)
		);
	END COMPONENT;

--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
-- Suffix _D indicates a one clock delay

--// HIGH-SPEED DUAL DACs -----------------------------------------------
signal DAC_CLK: std_logic;
signal DAC_CLKOUT: std_logic;
signal DAC1A_DIN: std_logic_vector(15 downto 0) := (others => '0');
signal DAC1B_DIN: std_logic_vector(15 downto 0) := (others => '0');
signal DAC2A_DIN: std_logic_vector(15 downto 0) := (others => '0');
signal DAC2B_DIN: std_logic_vector(15 downto 0) := (others => '0');
signal DAC_EN: std_logic;

-- TEST TEST TEST
signal DATA2_I: std_logic_vector(11 downto 0);
signal DATA2_Q: std_logic_vector(11 downto 0);
signal CCF_PHASE: std_logic_vector(31 downto 0);

--// HIGH-SPEED DUAL ADCs -----------------------------------------------
signal ADC_CLKOUT: std_logic;

--// AUXILIARY DACs + ADC
signal AUX_ADC1_ENABLE_N: std_logic;
signal TIMER_CNTR: std_logic_vector(18 downto 0);
signal AUX_DAC1_ENABLE_N: std_logic;
signal AUXDAC1_SCLK: std_logic;
signal AUXDAC1_SDIN: std_logic;
signal AUX_DAC2_ENABLE_N: std_logic;
signal AUXDAC2_SCLK: std_logic;
signal AUXDAC2_SDIN: std_logic;


--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin

--// HIGH-SPEED DUAL DACs -----------------------------------------------
AD9747_DAC_DRIVER_001: AD9747_DAC_DRIVER 
generic map(
	DAC_SPEEDx => DAC_SPEEDx
)
PORT MAP(
	CLK => CLK,
	ASYNC_RESET => ASYNC_RESET,
	DAC1A_DIN => DAC1A_DIN,
	DAC1B_DIN => DAC1B_DIN,	-- ignored when DAC_SPEEDx = 1
	DAC2A_DIN => DAC2A_DIN,
	DAC2B_DIN => DAC2B_DIN, -- ignored when DAC_SPEEDx = 1
	DAC_EN => DAC_EN,
	DAC1_DOUT => DAC1_DOUT,
	DAC2_DOUT => DAC2_DOUT,
	DAC_CLKOUT_P => DAC_CLKOUT_P,
	DAC_CLKOUT_N => DAC_CLKOUT_N
);

--// DAC data stimulus (for test purposes)
-- generate two ramps in opposite direction
DACGEN: process(CLK)
begin
	if rising_edge(CLK) then
		DAC1A_DIN <= DAC1A_DIN + 2;  -- jump two ramp positions
		DAC1B_DIN <= DAC1A_DIN + 3;  -- jump three ramp positions
		DAC2A_DIN <= DAC2A_DIN - 2;
		DAC2B_DIN <= DAC2A_DIN - 3;
	end if;
end process;
DAC_EN <= '1';

-- Alternative waveform generation: sinewaves
--// Frequency translation to 0 center frequency
-- Latency is 3 CLKs.
--DIGITAL_DC2_001: DIGITAL_DC2 port map(
--	CLK => CLK, 
--	DATA_I_IN => x"780",
--	DATA_Q_IN => x"000",
--	SAMPLE_CLK_IN => '1',	
--	PHASE_ROTATION => CCF_PHASE(31 downto 20),	
--	DATA_I_OUT => DATA2_I,
--	DATA_Q_OUT => DATA2_Q,
--	SAMPLE_CLK_OUT => open,
--	SATURATION => open
--	);
--
----// Carrier center frequency NCO
--
--CCF_NCO_001: NCO32 port map(
--	CLK => CLK,
--	SYNC_RESET => '0',
--	NOMINAL_FREQUENCY => CONTROL,
--	PHASE_OFFSET => x"00000000",
--	PHASE_OFFSET_SAMPLE_CLK => '0',
--	PHASE => CCF_PHASE
--	);
--
--DAC1A_DIN <= (not DATA2_I(11)) & DATA2_I(10 downto 0) & "0000"; -- unsigned format
--DAC2A_DIN <= (not DATA2_Q(11)) & DATA2_Q(10 downto 0) & "0000";
 

--// HIGH-SPEED DUAL ADCs -----------------------------------------------
-- AD9627 driver
Inst_AD9627_ADC_DRIVER: AD9627_ADC_DRIVER 
generic map(
	ADC_NBITS => 12
)
PORT MAP(
	CLK => CLK,
	ADC1_DOUT => ADC1_DOUT,
	ADC2_DOUT => ADC2_DOUT,
	ADC1_DIN => ADC1_DIN,
	ADC2_DIN => ADC2_DIN,
	ADC_DCO => ADC_DCO,
	ADC_CLKOUT_P => ADC_CLKOUT_P,
	ADC_CLKOUT_N => ADC_CLKOUT_N,
	TP => TP
);

--// AUXILIARY DACs (AD5621) -----------------------------------------------------
-- Two auxiliary DACs

AUX_DAC1_TEST: DAC_TEST PORT MAP(
	CLK => CLK,
	ENABLE_N => AUX_DAC1_ENABLE_N,
	TPS => open,
	SYNC_B => AUX_SPI3,					-- DAC serial connections. Do not modify.
--	SCLK => AUXDAC1_SCLK,				-- DAC serial connections. Do not modify.
--	SDIN => AUXDAC1_SDIN 				-- DAC serial connections. Do not modify.
-- test test test (board rev0 has inverted signals!)
	SCLK => AUXDAC1_SDIN,				-- DAC serial connections. Do not modify.
	SDIN => AUXDAC1_SCLK 				-- DAC serial connections. Do not modify.
);

AUX_DAC2_TEST: DAC_TEST PORT MAP(
	CLK => CLK,
	ENABLE_N => AUX_DAC2_ENABLE_N,
	TPS => open,
	SYNC_B => AUX_SPI4,					-- DAC serial connections. Do not modify.
--	SCLK => AUXDAC2_SCLK,				-- DAC serial connections. Do not modify.
--	SDIN => AUXDAC2_SDIN 				-- DAC serial connections. Do not modify.
-- test test test (board rev0 has inverted signals!)
	SCLK => AUXDAC2_SDIN,				-- DAC serial connections. Do not modify.
	SDIN => AUXDAC2_SCLK 				-- DAC serial connections. Do not modify.
);


--// AUXILIARY ADC (AD7276) -----------------------------------------------------
-- TODO
AUX_SPI5 <= '1';	-- disable AUX ADC temporarily (rev0, crossed nets conflicts)


--// SCHEDULER 
-- Time share the SPI bus for the three SPI devices (2 DACs, 1 ADC)
TIMER_GEN: process(CLK)
begin
	if rising_edge(CLK) then
		TIMER_CNTR <= TIMER_CNTR + 1;
	end if;
end process;

AUX_DAC1_ENABLE_N <= '0' when (TIMER_CNTR(18 downto 17) = "00") else '0';	-- 1 ms approx for AUX_DAC1
AUX_DAC2_ENABLE_N <= '0' when (TIMER_CNTR(18 downto 17) = "01") else '0';	-- 1 ms approx for AUX_DAC2
AUX_ADC1_ENABLE_N <= not TIMER_CNTR(18);												-- 2 ms approx for AUX_ADC1

AUX_SPI2 <= AUXDAC1_SCLK when (AUX_DAC1_ENABLE_N = '0') else 
				AUXDAC2_SCLK when (AUX_DAC2_ENABLE_N = '0') else 
				'0';

AUX_SPI1 <= AUXDAC1_SDIN when (AUX_DAC1_ENABLE_N = '0') else 
				AUXDAC2_SDIN when (AUX_DAC2_ENABLE_N = '0') else 
				'0';

end Behavioral;

