---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2008
--
-- Filename: CalControl.vhd
-- Language: VHDL '93
-- Project:  NDTS2100 DSP FPGA
--
-- Design Description:
-- This module generates the select lines for the LUT delay circuit that
-- generate the required delay for the DQS with respect to the DQ.
-- It calculates the delay of a LUT dynamically by finding the number of LUTs
-- in a clock phase.
---------------------------------------------------------------------------

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

entity CalControl is
  port (Clk        : in  std_logic;
        ClkDcmLock : in  std_logic;
        nReset     : in  std_logic;
        TapForDqs  : out std_logic_vector(4 downto 0));
end CalControl;

architecture Rtl of CalControl is

  component TapDelay
    port (Clk   : in  std_logic;
          Reset : in  std_logic;
          TapIn : in  std_logic;
          Flop2 : out std_logic_vector(31 downto 0));
  end component;

  signal Flop2              : std_logic_vector(31 downto 0);
  signal Count              : std_logic_vector(5 downto 0);
  signal Count1             : std_logic_vector(5 downto 0);
  signal TransOneDetect     : std_logic;
  signal TransTwoDetect     : std_logic;
  signal PhaseCount         : std_logic_vector(4 downto 0);
  signal TapDelayReg        : std_logic_vector(31 downto 0);
  signal TransTwoDetectEn   : std_logic;
  signal iTapForDqs         : std_logic_vector(4 downto 0);
  signal CountInt           : integer;
  signal ResetD             : std_logic;

  constant cTap1        : std_logic_vector(4 downto 0) := "01111";
  constant cTap2        : std_logic_vector(4 downto 0) := "10111";
  constant cTap3        : std_logic_vector(4 downto 0) := "11011";
  constant cTap4        : std_logic_vector(4 downto 0) := "11101";
  constant cTap5        : std_logic_vector(4 downto 0) := "11110";
  constant cTap6        : std_logic_vector(4 downto 0) := "11111";
  constant cDefaultTap  : std_logic_vector(4 downto 0) := "11101";

  attribute syn_keep : boolean;
  attribute syn_keep of Count            : signal is true;
  attribute syn_keep of TransOneDetect   : signal is true;
  attribute syn_keep of TransTwoDetect   : signal is true;
  attribute syn_keep of TapDelayReg      : signal is true;
  attribute syn_keep of TransTwoDetectEn : signal is true;
  attribute syn_keep of PhaseCount       : signal is true;
  attribute syn_keep of iTapForDqs       : signal is true;

begin

  Rst: process(Clk)
  begin
    if Clk'event and Clk = '1' then
      if nReset = '0' or ClkDcmLock = '0' then
        ResetD <= '1';
      else
        ResetD <= '0';
      end if;
    end if;
  end process Rst;

  TapFF: process(Clk)
  begin
    if Clk'event and Clk = '1' then
      TapForDqs <= iTapForDqs;
    end if;
  end process TapFF;

  ----------- For Successive Transition -------------------

  GenEn: process(Clk)
  begin
    if Clk'event and Clk = '1' then
      if ResetD = '1' then
        TransTwoDetectEn <= '0';
      elsif PhaseCount >= "00001" then
        TransTwoDetectEn <= '1';
      else
        TransTwoDetectEn <= '0';
      end if;
    end if;
  end process GenEn;

  TapDel: TapDelay
    port map (Clk   => Clk,
              Reset => ResetD,
              TapIn => Clk,
              Flop2 => Flop2);

  TapDelFF: process (Clk)
  begin
    if Clk'event and Clk = '1' then
      if ResetD = '1' then
        TapDelayReg <= "00000000000000000000000000000000";
      elsif Count(5) = '1' then
        TapDelayReg <= Flop2;
      end if;
    end if;
  end process TapDelFF;

  ------- Free Running Counter For Counting 32 States ---------------------
  ------- Two parallel counters are used to fix the timing ----------------

  Counter: process (Clk)
  begin
    if Clk'event and Clk = '1' then
      if ResetD = '1' or Count(5) = '1' then
        Count <= "000000";
      else
        Count <= unsigned(Count) + '1';
      end if;
    end if;
  end process Counter;


  Counter1: process(Clk)
  begin
    if Clk'event and Clk = '1' then
      if ResetD = '1' or Count1(5) = '1' then
        Count1 <= "000000";
      else
        Count1 <= unsigned(Count1) + '1';
      end if;
    end if;
  end process Counter1;

  Phase: process(Clk)
  begin
    if Clk'event and Clk = '1' then
      if ResetD = '1' or Count(5) = '1' then
        PhaseCount <= "00000";
      elsif TransOneDetect = '1' and TransTwoDetect = '0' then
        PhaseCount <= unsigned(PhaseCount) + '1';
      end if;
    end if;
  end process Phase;

  ----------- Checking For The First Transition ------------------

  TransDetect: process(Clk)
  begin
    if Clk'event and Clk = '1' then
      if  ResetD = '1' or Count(5) = '1' then
        TransOneDetect <= '0';
        TransTwoDetect <= '0';
      elsif Count(4 downto 0) = "00000" then
        if TapDelayReg(0) = '1' then
          TransOneDetect <= '1';
          TransTwoDetect <= '0';
        end if;
      elsif TapDelayReg(CountInt) = '1' and TransTwoDetect = '0' then
        if TransOneDetect = '1' and TransTwoDetectEn = '1' then
          TransTwoDetect <= '1';
        else
          TransOneDetect <= '1';
        end if;
      end if;
    end if;
  end process TransDetect;

  CountInt <= conv_integer(unsigned(Count(4 downto 0)));

  process (Clk)
  begin
    if Clk'event and Clk = '1' then
      if ResetD = '1' then
        iTapForDqs <= cDefaultTap;
      elsif Count1(4 downto 0) = "11111" then
        if TransOneDetect = '0' or TransTwoDetect = '0' or PhaseCount > "01011" then
          iTapForDqs <= cTap4;
        elsif PhaseCount > "01000" then
          iTapForDqs <= cTap3;
        else
          iTapForDqs <= cTap2;
        end if;
      end if;
    end if;
  end process;

end Rtl;
