---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2007
--
-- Filename: AD5621.vhd
-- Language: VHDL '93
-- Project:  NDTS2100 System FPGA
--
-- Design Description:
-- Serial DAC model
---------------------------------------------------------------------------

library IEEE;
use IEEE.Std_Logic_1164.all;
use IEEE.Std_Logic_Arith.all;
use std.textio.all;

entity AD5621 is
  port(SClk    : in  std_ulogic;
       nSync   : in  std_ulogic;
       Din     : in  std_ulogic;
       Vout    : out integer range 0 to 4095;
       VoutRdy : out std_ulogic := '0';
       TestFail: out boolean := false);
end entity AD5621;


architecture beh of AD5621 is

  constant t1: time := 33 ns;  -- SCLK cycle time
  constant t2: time := 5 ns;   -- SCLK high time
  constant t3: time := 5 ns;   -- SCLK low time
  constant t4: time := 10 ns;  -- nSYNC to SCLK low time
  constant t5: time := 5 ns;   -- Data setup time
  constant t6: time := 4.5 ns; -- Data hold time
  constant t8: time := 20 ns;  -- Minimum SYNC high time

begin

  State : process
    variable vSClkFall: time := 0 ns;
    variable vDShift:   std_logic_vector(15 downto 0);
    variable vBitCount: integer;
  begin
    wait on SClk, nSync, Din;

    if falling_edge(SClk) then
      if (now - vSClkFall) < t1 then
        SClkPeriodErr: assert false report "Invalid SClk period time AD5621" severity error;
        TestFail <= true;
      end if;
      if not SClk'delayed'stable(t2) then
        SClkHighErr: assert false report "Invalid SClk high time AD5621" severity error;
        TestFail <= true;
      end if;

      if (nSync = '0') then
        if not nSync'stable(t4) then
          nSyncSetupErr: assert false report "Invalid nSync to SClk fall setup time AD5621" severity error;
          TestFail <= true;
        end if;
        if not Din'stable(t5) then
          DinSetupErr: assert false report "Invalid Din setup time AD5621" severity error;
          TestFail <= true;
        end if;

        vDShift := vDShift(14 downto 0) & Din;
        vBitCount := vBitCount + 1;
      end if;
      vSClkFall := now;
    end if;

    if rising_edge(SClk) then
      if not SClk'delayed'stable(t3) then
        SClkLowErr: assert false report "Invalid SClk low time AD5621" severity error;
        TestFail <= true;
      end if;
    end if;

    if Din'event then
      if SClk = '0' and not SClk'stable(t6) then
        DinHoldErr: assert false report "Invalid Din hold time AD5621" severity error;
        TestFail <= true;
      end if;
    end if;

    if falling_edge(nSync) then
      -- check for high time
      if not nSync'delayed'stable(t8) then
        SyncHighErr: assert false report "Invalid nSync high time AD5621" severity error;
        TestFail <= true;
      end if;
      vBitCount := 0;
    end if;

    if rising_edge(nSync) then
      -- check number of bits received
      if vBitCount < 16 then
        SyncInterruptWarn: assert false report "Sync Interrupt to AD5621" severity warning;
      end if;
      if vDShift(15 downto 14) /= "00" then
        PowerDownWarn: assert false report "AD5621 powered down (output not driven)" severity warning;
      end if;
      Vout <= conv_integer(unsigned(vDShift(13 downto 2)));
      VoutRdy <= '1', '0' after 1 ns;
    end if;

  end process State;    

end architecture beh;