library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity tdc is
    Port ( reset : in  STD_LOGIC;
           clk_i : in  STD_LOGIC;			-- 125 MHz
			  ready : out std_logic;
			  data_in : in  STD_LOGIC;
--           data_in_p : in  STD_LOGIC;
--           data_in_n : in  STD_LOGIC;
           data_out : out  STD_LOGIC_VECTOR (7 downto 0);
			  strobe_out	: out STD_LOGIC;
			  fine_time_stamp_out : out  STD_LOGIC_VECTOR (2 downto 0) 
			  );
end tdc;

architecture Behavioral of tdc is

signal sig_data : std_logic_vector( 23  downto 0);
signal sig_strobe : std_logic;
signal sig_fts : std_logic_vector( 2  downto 0);
signal sig_data2slave : std_logic;
signal sig_ioclk : std_logic;
signal sig_gclk1 : std_logic;
--signal data_in : std_logic;
signal sig_ioce : std_logic;
signal sig_rst_serdes : std_logic;

signal sig_locked : std_logic;
signal sig_pll_locked : std_logic;
signal sig_clk0 : std_logic; 
signal sig_pll_fb : std_logic;
signal gclk : std_logic;
signal sig_clk1 : std_logic; 
signal clkfbout : std_logic;
signal sig_pll_reset : std_logic;

begin

   ISERDES2_master : ISERDES2
   generic map (
      BITSLIP_ENABLE => FALSE,        -- Enable Bitslip Functionality (TRUE/FALSE)
      DATA_RATE => "SDR",             -- Data-rate ("SDR" or "DDR")
      DATA_WIDTH => 8,                -- Parallel data width selection (2-8)
      INTERFACE_TYPE => "RETIMED", -- "NETWORKING", "NETWORKING_PIPELINED" or "RETIMED" 
      SERDES_MODE => "MASTER"           -- "NONE", "MASTER" or "SLAVE" 
   )
   port map (
      CFB0 => open,           -- 1-bit output: Clock feed-through route output
      CFB1 => open,           -- 1-bit output: Clock feed-through route output
      DFB => open,             -- 1-bit output: Feed-through clock output
      FABRICOUT => open, -- 1-bit output: Unsynchrnonized data output
      INCDEC => open,       -- 1-bit output: Phase detector output
      -- Q1 - Q4: 1-bit (each) output: Registered outputs to FPGA logic
      Q1 =>  sig_data(3),
      Q2 =>  sig_data(2),
      Q3 =>  sig_data(1),
      Q4 =>  sig_data(0),
      SHIFTOUT => sig_data2slave,   -- 1-bit output: Cascade output signal for master/slave I/O
      VALID => open,         -- 1-bit output: Output status of the phase detector
      BITSLIP => '0',     -- 1-bit input: Bitslip enable input
      CE0 => '1',             -- 1-bit input: Clock enable input
      CLK0 => sig_ioclk,           -- 1-bit input: I/O clock network input
      CLK1 => '0' ,           -- 1-bit input: Secondary I/O clock network input
      CLKDIV => sig_gclk1,       -- 1-bit input: FPGA logic domain clock input
      D => data_in,                 -- 1-bit input: Input data
      IOCE => sig_ioce,           -- 1-bit input: Data strobe input
      RST => sig_rst_serdes,             -- 1-bit input: Asynchronous reset input
      SHIFTIN => '0'      -- 1-bit input: Cascade input signal for master/slave I/O
   );

   ISERDES2_slave : ISERDES2
   generic map (
      BITSLIP_ENABLE => FALSE,        -- Enable Bitslip Functionality (TRUE/FALSE)
      DATA_RATE => "SDR",             -- Data-rate ("SDR" or "DDR")
      DATA_WIDTH => 8,                -- Parallel data width selection (2-8)
      INTERFACE_TYPE => "RETIMED", -- "NETWORKING", "NETWORKING_PIPELINED" or "RETIMED" 
      SERDES_MODE => "SLAVE"           -- "NONE", "MASTER" or "SLAVE" 
   )
   port map (
      CFB0 => open,           -- 1-bit output: Clock feed-through route output
      CFB1 => open,           -- 1-bit output: Clock feed-through route output
      DFB => open,             -- 1-bit output: Feed-through clock output
      FABRICOUT => open, -- 1-bit output: Unsynchrnonized data output
      INCDEC => open,       -- 1-bit output: Phase detector output
      -- Q1 - Q4: 1-bit (each) output: Registered outputs to FPGA logic
      Q1 =>  sig_data(7),
      Q2 =>  sig_data(6),
      Q3 =>  sig_data(5),
      Q4 =>  sig_data(4),
      SHIFTOUT => open,   -- 1-bit output: Cascade output signal for master/slave I/O
      VALID => open,         -- 1-bit output: Output status of the phase detector
      BITSLIP =>  '0',     -- 1-bit input: Bitslip enable input
      CE0 => '1',             -- 1-bit input: Clock enable input
      CLK0 => sig_ioclk,           -- 1-bit input: I/O clock network input
      CLK1 => '0' ,           -- 1-bit input: Secondary I/O clock network input
      CLKDIV => sig_gclk1,       -- 1-bit input: FPGA logic domain clock input
      D => '0',                 -- 1-bit input: Input data
      IOCE => sig_ioce,          -- 1-bit input: Data strobe input
      RST => sig_rst_serdes,             -- 1-bit input: Asynchronous reset input
      SHIFTIN => sig_data2slave      -- 1-bit input: Cascade input signal for master/slave I/O
   );

	
--   IBUFDS_inst : IBUFDS
--   generic map (
--      DIFF_TERM => FALSE, -- Differential Termination 
--      IBUF_LOW_PWR => TRUE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
--      IOSTANDARD => "DEFAULT")
--   port map (
--      O => data_in,  -- Buffer output
--      I => data_in_p,  -- Diff_p buffer input (connect directly to top-level port)
--      IB => data_in_n -- Diff_n buffer input (connect directly to top-level port)
--   );

   BUFPLL_inst : BUFPLL
   generic map (
      DIVIDE => 8,         -- DIVCLK divider (1-8)
      ENABLE_SYNC => TRUE  -- Enable synchrnonization between PLL and GCLK (TRUE/FALSE)
   )
   port map (
      IOCLK => sig_ioclk,               -- 1-bit output: Output I/O clock
      LOCK => sig_locked,                 -- 1-bit output: Synchronized LOCK output
      SERDESSTROBE => sig_ioce, -- 1-bit output: Output SERDES strobe (connect to ISERDES2/OSERDES2)
      GCLK => sig_gclk1,                 -- 1-bit input: BUFG clock input
      LOCKED => sig_pll_locked,             -- 1-bit input: LOCKED input from PLL
      PLLIN => sig_clk0                -- 1-bit input: Clock input from PLL
   );

   BUFIO2FB_inst : BUFIO2FB
   generic map (
      DIVIDE_BYPASS => TRUE  -- Bypass divider (TRUE/FALSE)
   )
   port map (
      O => sig_pll_fb, -- 1-bit output: Output feedback clock (connect to feedback input of DCM/PLL)
      I => sig_ioclk  -- 1-bit input: Feedback clock input (connect to input port)
   );


--   IBUFG_inst : IBUFG
--   generic map (
--      IBUF_LOW_PWR => TRUE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
--      IOSTANDARD => "DEFAULT")
--   port map (
--      O => gclk, -- Clock buffer output
--      I => clk  -- Clock buffer input (connect directly to top-level port)
--   );

   BUFG_inst : BUFG
   port map (
      O => sig_gclk1, -- 1-bit output: Clock buffer output
      I => sig_clk1  -- 1-bit input: Clock buffer input
   );
	
  PLL_BASE_inst : PLL_BASE
   generic map (
      BANDWIDTH => "OPTIMIZED",             -- "HIGH", "LOW" or "OPTIMIZED" 
      CLKFBOUT_MULT => 8,                   -- Multiply value for all CLKOUT clock outputs (1-64)
      CLKFBOUT_PHASE => 0.0,                -- Phase offset in degrees of the clock feedback output
                                            -- (0.0-360.0).
      CLKIN_PERIOD => 8.000,                  -- Input clock period in ns to ps resolution (i.e. 33.333 is 30
                                            -- MHz).
      -- CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for CLKOUT# clock output (1-128)
      CLKOUT0_DIVIDE => 1,
      CLKOUT1_DIVIDE => 8,
      CLKOUT2_DIVIDE => 1,
      CLKOUT3_DIVIDE => 1,
      CLKOUT4_DIVIDE => 1,
      CLKOUT5_DIVIDE => 1,
      -- CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for CLKOUT# clock output (0.01-0.99).
      CLKOUT0_DUTY_CYCLE => 0.5,
      CLKOUT1_DUTY_CYCLE => 0.5,
      CLKOUT2_DUTY_CYCLE => 0.5,
      CLKOUT3_DUTY_CYCLE => 0.5,
      CLKOUT4_DUTY_CYCLE => 0.5,
      CLKOUT5_DUTY_CYCLE => 0.5,
      -- CLKOUT0_PHASE - CLKOUT5_PHASE: Output phase relationship for CLKOUT# clock output (-360.0-360.0).
      CLKOUT0_PHASE => 0.0,
      CLKOUT1_PHASE => 0.0,
      CLKOUT2_PHASE => 0.0,
      CLKOUT3_PHASE => 0.0,
      CLKOUT4_PHASE => 0.0,
      CLKOUT5_PHASE => 0.0,
      CLK_FEEDBACK => "CLKOUT0",           -- Clock source to drive CLKFBIN ("CLKFBOUT" or "CLKOUT0")
      COMPENSATION => "SYSTEM_SYNCHRONOUS", -- "SYSTEM_SYNCHRONOUS", "SOURCE_SYNCHRONOUS", "EXTERNAL" 
      DIVCLK_DIVIDE => 1,                   -- Division value for all output clocks (1-52)
      REF_JITTER => 0.1,                    -- Reference Clock Jitter in UI (0.000-0.999).
      RESET_ON_LOSS_OF_LOCK => FALSE        -- Must be set to FALSE
   )
   port map (
      CLKFBOUT => open, -- 1-bit output: PLL_BASE feedback output
      -- CLKOUT0 - CLKOUT5: 1-bit (each) output: Clock outputs
      CLKOUT0 => sig_clk0,
      CLKOUT1 => sig_clk1,
      CLKOUT2 => open,
      CLKOUT3 => open,
      CLKOUT4 => open,
      CLKOUT5 => open,
      LOCKED => sig_pll_locked,     -- 1-bit output: PLL_BASE lock status output
      CLKFBIN => sig_pll_fb,   -- 1-bit input: Feedback clock input
      CLKIN => clk_i, --gclk,       -- 1-bit input: Clock input
      RST => sig_pll_reset            -- 1-bit input: Reset input
   );


process(sig_locked, clk_i)
 begin
	if(sig_locked = '0') then	
		sig_data(23 downto 8)  <= (others => '0');
		sig_strobe <= '0'; 
		sig_fts <=  (others => '0');

	elsif rising_edge( clk_i ) then
		
		sig_data(15 downto 8) <= sig_data(7 downto 0);
		sig_data(23 downto 16) <= sig_data(15 downto 8);
			
		if 	sig_data(17 downto 14 ) = "0011" then  
			sig_strobe <='1'; sig_fts <="000";
		elsif sig_data(16 downto 13 ) = "0011" then
			sig_strobe <='1'; sig_fts <="001";
		elsif sig_data(15 downto 12 ) = "0011" then
			sig_strobe <='1'; sig_fts <="010";
		elsif sig_data(14 downto 11 ) = "0011" then
			sig_strobe <='1'; sig_fts <="011";
		elsif sig_data(13 downto 10 ) = "0011" then
			sig_strobe <='1'; sig_fts <="100";
		elsif sig_data(12 downto 9 ) = "0011" then
			sig_strobe <='1'; sig_fts <="101";
		elsif sig_data(11 downto 8 ) = "0011" then
			sig_strobe <='1'; sig_fts <="110";
		elsif sig_data(10 downto 7 ) = "0011" then
			sig_strobe <='1'; sig_fts <="111";
		else 
			sig_strobe <='0'; sig_fts <="000";
		end if;	
	end if;
end process; 




strobe_out	<= sig_strobe;
fine_time_stamp_out <= sig_fts;

sig_pll_reset <= reset ;
sig_rst_serdes <= not sig_locked;
data_out <= sig_data(15 downto 8);
ready <= sig_locked;



end Behavioral;
