-------------------------------------------------------------
-- MSS copyright 2011-2012
--	Filename:  AD9627_ADC_DRIVER2.VHD
-- Author: 
--		Alain Zarembowitch / MSS, 
--	Version: 1
--	Date last modified: 7/10/12
-- Inheritance: 	AD9627_ADC_DRIVER,vhd rev0, 11-19-10
--
-- description:  Alternate driver for the 150 MSamples/s 12-bit ADCs.
-- This driver is to be used when the FPGA application drives the ADC clock (for example in a demodulator).
-- 
-- Rev 1 7/10/12 AZ
-- Added DCM to clean the noisy ADC_DCO clock received from the ADC.
----------------------------------------------------------------------------------
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 AD9627_ADC_DRIVER2 is
	 generic (
		ADC_NBITS: in integer := 12
	 );
    port ( 
			--// Clocks Resets
			ADC_CLK: in std_logic;
				-- FPGA controls the sampling rate here.
				-- ADC sampling clock to ADC (goes to ADC_CLKOUT_P/N)
			ADC_CLK2G: in std_logic;
				-- ADC sampling clock from ADC (from ADC_DCO(0) strobe)
				-- global (BUFG used within)
			
			--// User interface : received ADC samples. Synchronous with CLKG.
			-- If using this ADC within a COM-3504 module, format is always unsigned (offset binary). 
			ADC1_DOUT: out std_logic_vector((ADC_NBITS-1) downto 0);
			ADC2_DOUT: out std_logic_vector((ADC_NBITS-1) downto 0);
			
			--// 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((ADC_NBITS-1) downto 0);
			ADC2_DIN: in std_logic_vector((ADC_NBITS-1) downto 0);
				-- AD9627 data samples
			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;
				-- LVCMOS (not LVDS!) differential ADC sampling clock 150 MHz max
				
			--// Test points
			TP: out std_logic_vector(10 downto 1)
			
		
			);
end entity;

architecture Behavioral of AD9627_ADC_DRIVER2 is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
-- Suffix _D indicates a one clock delay

signal ADC_CLK_N: std_logic := '0';

--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin
ADC_CLK_N <= not ADC_CLK;

-- ADC clock output
-- It is recommended to only use a BUFG resource to drive clock loads.
-- It is recommended to use a Clock Forwarding technique to create a reliable and repeatable 
-- low skew solution, i.e. use ODDR2 to regenerate the output clock.
ADC_CLKOUT_GEN_001P : ODDR2
generic map(
	DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1" 
	INIT => '0', -- Sets initial state of the Q output to '0' or '1'
	SRTYPE => "SYNC") -- Specifies "SYNC" or "ASYNC" set/reset
port map (
	Q => ADC_CLKOUT_P, -- 1-bit output data
	C0 => ADC_CLK, -- 1-bit clock input
	C1 => ADC_CLK_N, -- 1-bit clock input
	CE => '1',  -- 1-bit clock enable input
	D0 => '1',   -- 1-bit data input (associated with C0)
	D1 => '0',   -- 1-bit data input (associated with C1)
	R => '0',    -- 1-bit reset input
	S => '0'     -- 1-bit set input
);

-- fake differential output (LVDS_33 is incompatible with LVCMOS33 in the same bank!)
ADC_CLKOUT_GEN_001N : ODDR2
generic map(
	DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1" 
	INIT => '0', -- Sets initial state of the Q output to '0' or '1'
	SRTYPE => "SYNC") -- Specifies "SYNC" or "ASYNC" set/reset
port map (
	Q => ADC_CLKOUT_N, -- 1-bit output data
	C0 => ADC_CLK, -- 1-bit clock input
	C1 => ADC_CLK_N, -- 1-bit clock input
	CE => '1',  -- 1-bit clock enable input
	D0 => '0',   -- 1-bit data input (associated with C0)
	D1 => '1',   -- 1-bit data input (associated with C1)
	R => '0',    -- 1-bit reset input
	S => '0'     -- 1-bit set input
);
 

-- reclock input samples at the rising edge of ADC_DCO() = CLKG 
RECLOCK_001: process(ADC_CLK2G)
begin
	if rising_edge(ADC_CLK2G) then
		ADC1_DOUT <= ADC1_DIN;
		ADC2_DOUT <= ADC2_DIN;
	end if;
end process;
 

--// TEST POINTS -------------------
--TP(1) <= ;
--TP(2) <= ;
--TP(3) <= ;


end Behavioral;

