---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2008
--
-- Filename: TCGControl.vhd
-- Language: VHDL '93
-- Project:  NDTS2100
--
-- Design Description:
-- Module to control the TCG DAC/RAM
---------------------------------------------------------------------------

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


entity TCGControl is
  port (nReset          : in  std_ulogic;
        SysClk          : in  std_ulogic;
        TCGEnable       : in  std_ulogic;
        TCGAbsoluteTrig : in  std_ulogic;
        TCGPoints       : in  std_logic_vector(18 downto 0);
        TCGSamples      : in  std_logic_vector(15 downto 0);
        TrigAbsolute    : in  std_ulogic;
        TrigInterface   : in  std_ulogic;
        SampleEn        : in  std_ulogic;
        CaptureDone     : in  std_ulogic;
        -- LBUS RAM access Signals
        LClk            : in  std_ulogic;
        TCGRAMWr        : in  std_ulogic;
        TCGRAMRd        : in  std_ulogic;
        TCGRAMAck       : out std_ulogic;
        TCGRAMAddr      : in  std_logic_vector(17 downto 0);
        -- DAC SRAM Signals
        nTcgDacDOe      : out std_ulogic;
        TcgDacA         : out std_logic_vector(17 downto 0);
        nTcgDacCs       : out std_ulogic;
        nTcgDacBLE      : out std_ulogic;
        nTcgDacBHE      : out std_ulogic;
        nTcgDacOe       : out std_ulogic;
        nTcgDacWr       : out std_ulogic;
        -- Actual DAC Signals
        TcgDacSleep     : out std_ulogic;
        TcgDacClk       : out std_ulogic);
end entity TCGControl;


architecture Rtl of TCGControl is

  signal iTCGRAMAck:  std_ulogic;
  signal TCGRamDel:   std_ulogic;
  signal TCGRAMAddrD: std_logic_vector(17 downto 0);

  signal TCGEnableD:  std_ulogic;
  signal Trigger:     std_ulogic;
  signal PointCount:  unsigned(18 downto 0);
  signal PointCountZero: std_ulogic;
  signal SampleEnD:   std_ulogic;
  signal SampCount:   unsigned(15 downto 0);
  signal SampCountZero: std_ulogic;
  signal AddrCount:   unsigned(17 downto 0);
  signal AddrReset:   std_ulogic;
  signal AddrEn:      std_ulogic;
  signal DacClkWr:    std_ulogic;
  signal DacClkLast:  std_ulogic;
  signal DacClkRst:   std_ulogic;
  signal DacClk:      std_ulogic;
  signal DacA:        std_logic_vector(17 downto 0);

begin

  TcgDacSleep <= '0';

  nTcgDacCs <= '0';
  nTcgDacBLE <= '0';
  nTcgDacBHE <= '0';

  RamSM: process(nReset, LClk)
  begin
    if nReset = '0' then
      nTcgDacWr <= '1';
      nTcgDacDOe <= '1';
      iTCGRAMAck <= '0';
      TCGRamDel <= '0';
      TCGRAMAddrD <= (others => '0');
      DacClkWr <= '0';
    elsif LClk'event and LClk = '1' then
      nTcgDacWr <= '1';
      nTcgDacDOe <= '1';
      DacClkWr <= '0';
      if TCGEnable = '0' then
        if TCGRAMWr = '1' then
          TCGRamDel <= '1';
          nTcgDacDOe <= '0';
          if TCGRamDel = '1' then
            nTcgDacWr <= '0';
            iTCGRAMAck <= '1';
            DacClkWr <= '1';
          else
            TCGRAMAddrD <= TCGRAMAddr;
          end if;
        end if;
        if TCGRAMRd = '1' then
          TCGRamDel <= '1';
          if TCGRamDel = '1' then
            iTCGRAMAck <= '1';
          else
            TCGRAMAddrD <= TCGRAMAddr;
          end if;
        end if;

        if iTCGRAMAck = '1' then
          nTcgDacWr <= '1';
          iTCGRAMAck <= '0';
          TCGRamDel <= '0';
        end if;
      else
        if (TCGRAMWr = '1' or TCGRAMRd = '1') and iTCGRAMAck = '0' then
          iTCGRAMAck <= '1';
        else
          iTCGRAMAck <= '0';
        end if;
      end if;
    end if;
  end process RamSm;

  OeFF: process(nReset, LClk)
  begin
    if nReset = '0' then
      nTcgDacOe <= '1';
    elsif LClk'event and LClk = '0' then
      nTcgDacOe <= '0';
      if TCGEnable = '0' then
        if TCGRAMWr = '1' or DacClkWr = '1' then
          nTcgDacOe <= '1';
        end if;
      end if;
    end if;
  end process OeFF;

  TCGRAMAck <= iTCGRAMAck;

  Trig: process(nReset, SysClk)
  begin
    if nReset = '0' then
      Trigger   <= '0';
    elsif SysClk'event and SysClk = '1' then
      if TCGEnable = '1' then
        if TCGAbsoluteTrig = '1' then
          Trigger <= TrigAbsolute;
        else
          Trigger <= TrigInterface;
        end if;
      else
        -- TCG Operation is disabled
        Trigger <= '0';
      end if;
    end if;
  end process Trig;


  En:  process(nReset, SysClk)
  begin
    if nReset = '0' then
      TCGEnableD <= '0';
      SampleEnD <= '0';
      AddrEn <= '0';
      PointCount <= (others => '0');
      PointCountZero <= '1';
      SampCount <= (others => '0');
      SampCountZero <= '1';
      DacClkLast <= '0';
      DacClk <= '0';
      TcgDacClk <= '0';
    elsif SysClk'event and SysClk = '1' then
      TCGEnableD <= TCGEnable;
      SampleEnD <= SampleEn;
      AddrEn <= '0';
      DacClkLast <= '0';
      DacClk <= DacClkWr or DacClkLast or (TCGEnable and not TCGEnableD);
      TcgDacClk <= DacClk;

      if Trigger = '1' then
        PointCount <= unsigned(TCGPoints);
        if unsigned(TCGPoints) = 0 then
          PointCountZero <= '1';
        else
          PointCountZero <= '0';
        end if;
      elsif SampleEnD = '1' then
        if PointCountZero = '0' or SampCountZero = '0' then
          if SampCountZero = '1' then
            SampCount <= unsigned(TCGSamples) - 1;
            if unsigned(TCGSamples) <= 1 then
              SampCountZero <= '1';
            else
              SampCountZero <= '0';
            end if;

            PointCount <= PointCount - 1;
            if PointCount(18 downto 1) = 0 then
              PointCountZero <= '1';
            else
              PointCountZero <= '0';
            end if;
            AddrEn <= '1';
            DacClk <= '1';
          else
            SampCount <= SampCount - 1;
            if SampCount(15 downto 1) = 0 then
              SampCountZero <= '1';
              if PointCountZero = '1' then
                DacClkLast <= '1';
              end if;
            else
              SampCountZero <= '0';
            end if;
          end if;
        end if;
      end if;
    end if;
  end process En;


  Addr: process(nReset, SysClk)
  begin
    if nReset = '0' then
      AddrReset <= '1';
      AddrCount <= (others => '0');
      DacClkRst <= '0';
    elsif SysClk'event and SysClk = '1' then
      DacClkRst <= '0';
      if Trigger = '1' then
        AddrReset <= '0';
      elsif CaptureDone = '1' then
        AddrReset <= '1';
        DacClkRst <= '1';
      end if;

      if AddrReset = '1' then
        AddrCount <= (others => '0');
      elsif AddrEn = '1' then
        AddrCount <= AddrCount + 1;
      end if;
    end if;
  end process Addr;


  GenDACA: process(nReset, SysClk)
  begin
    if nReset = '0' then
      DacA <= (others => '0');
      TcgDacA <= (others => '0');
    elsif SysClk'event and SysClk = '1' then
      if TCGEnable = '0' then
        DacA <= TCGRAMAddrD;
      else
        DacA <= std_logic_vector(AddrCount);
      end if;
      TcgDacA <= DacA;
    end if;
  end process GenDACA;


end Rtl;
