---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: AdcModel.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card FPGAs
--
-- Design Description:
-- ADC Model
---------------------------------------------------------------------------

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

library work;
use work.AdcModelPkg.all;


entity AdcModel is
  port(-- Control signals to/from main simulation module
       ToAdcModel  : in  tToAdcModel;
       FromAdcModel: out tFromAdcModel;
       -- Signals from ADC to DSP FPGA
       pAdcClk     : out std_ulogic;
       pAdcTrigger : out std_ulogic;
       pAdcDataA   : out std_logic_vector(11 downto 0);
       pAdcDataB   : out std_logic_vector(11 downto 0);
       -- Trigger input for internal trigger mode
       pTriggerIn  : in  std_ulogic);
end entity AdcModel;



architecture beh of AdcModel is

  signal AdcClk: std_ulogic;
  signal Toggle: std_ulogic := '0';

begin

  -- Generate the AdcClk at 50 MHz (The DSP FPGA doubles this to 100MHz)
  GenAdcClk: process
  begin
    wait for 2 ns;
    AdcClk <= '0';
    wait for 10 ns;
    AdcClk <= '1';
    wait for 8 ns;
  end process GenAdcClk;

  pAdcClk <= AdcClk;


  GenToggle: process(AdcClk)
  begin
    if rising_edge(AdcClk) then
      Toggle <= not Toggle;
    end if;
  end process GenToggle;



  GenAScan: process

    variable vLine: Line;
    variable vRepeatCount: integer;

  begin
    pAdcTrigger <= '0';
    pAdcDataA   <= X"000";
    pAdcDataB   <= X"000";
    vRepeatCount := 0;

    while true loop

      while vRepeatCount = 0 loop
        FromAdcModel.Done <= '1';
        wait on ToAdcModel.Start until falling_edge(ToAdcModel.Start);
        vRepeatCount := ToAdcModel.RepeatTimes;
      end loop;
      FromAdcModel.Done <= '0';
      vRepeatCount := vRepeatCount - 1;
      wait on AdcClk until rising_edge(AdcClk);

      write (vLine, string'("ADC Model: Sending A-Scan (Test pattern: "));
      write (vLine, ToAdcModel.TestPattern);
      write (vLine, string'(") "));
      write (vLine, ToAdcModel.RepeatTimes - vRepeatCount);
      write (vLine, string'(" of "));
      write (vLine, ToAdcModel.RepeatTimes);
      writeline (OUTPUT, vLine);

      -- New A-Scan requested
      wait on Toggle until rising_edge(Toggle);
      if (ToAdcModel.IntTrigger = '1') then
        wait until rising_edge(pTriggerIn);
      else
        pAdcTrigger <= transport '1' after 10 ns;
        pAdcTrigger <= transport '0' after 110 ns;
      end if;

      if ToAdcModel.TestPattern = 0 then
        --
        -- Send Test pattern 0
        --

        -- Samples 0 to 99 - Data = 0
        for count in 0 to 52 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;

        -- Samples 100 to 199 - Data = 500 downto 0
        for count in 0 to 49 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((500 - 2*count * (500/100)), 12);
          pAdcDataB <= conv_std_logic_vector((500 - (2*count+1) * (500/100)), 12);
        end loop;

        -- Samples 200 to 299 - Data = -500 to 0
        for count in 0 to 49 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((-500 + 2*count * (500/100)), 12);
          pAdcDataB <= conv_std_logic_vector((-500 + (2*count+1) * (500/100)), 12);
        end loop;

        -- Samples 300 to 399 - Data = 700 downto 0
        for count in 0 to 49 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((700 - 2*count * (700/100)), 12);
          pAdcDataB <= conv_std_logic_vector((700 - (2*count+1) * (700/100)), 12);
        end loop;

        -- Samples 400 to 499 - Data = -720 to 0
        for count in 0 to 49 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((-720 + 2*count * (720/100)), 12);
          pAdcDataB <= conv_std_logic_vector((-720 + (2*count+1) * (720/100)), 12);
        end loop;


        -- Samples 500 to 599 - Data = 400 downto 0
        for count in 0 to 49 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((400 - 2*count * (400/100)), 12);
          pAdcDataB <= conv_std_logic_vector((400 - (2*count+1) * (400/100)), 12);
        end loop;

        -- Samples 600 to 699 - Data = - 400 to 0
        for count in 0 to 49 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((-400 + 2*count * (500/100)), 12);
          pAdcDataB <= conv_std_logic_vector((-400 + (2*count+1) * (500/100)), 12);
        end loop;

        -- Samples 700 to 849 - Data = 0
        for count in 0 to 99 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;


      elsif ToAdcModel.TestPattern = 1 then
        --
        -- Send Test pattern 1
        --

        -- Samples 0 to 99 - Data = 0
        for count in 0 to 52 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;

        -- Samples 100 to 199 - Data = 0 to 500
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector(((2*count-1) * (500/100)), 12);
          pAdcDataB <= conv_std_logic_vector(((2*count) * (500/100)), 12);
        end loop;

        -- Samples 200 to 299 - Data = 0 downto -500
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((0 - (2*count-1) * (500/100)), 12);
          pAdcDataB <= conv_std_logic_vector((0 - (2*count) * (500/100)), 12);
        end loop;

        -- Samples 300 to 399 - Data = 0 to 700
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector(((2*count-1) * (700/100)), 12);
          pAdcDataB <= conv_std_logic_vector(((2*count) * (700/100)), 12);
        end loop;

        -- Samples 400 to 499 - Data = 0 downto -720
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((0 - (2*count-1) * 720/100), 12);
          pAdcDataB <= conv_std_logic_vector((0 - (2*count) * 720/100), 12);
        end loop;


        -- Samples 500 to 599 - Data = 0 to 400
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector(((2*count-1) * (400/100)), 12);
          pAdcDataB <= conv_std_logic_vector(((2*count) * (400/100)), 12);
        end loop;

        -- Samples 600 to 699 - Data = 0 downto -400
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((0 - (2*count-1) * (400/100)), 12);
          pAdcDataB <= conv_std_logic_vector((0 - (2*count) * (400/100)), 12);
        end loop;

        -- Samples 700 to 849 - Data = 0
        for count in 0 to 99 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;

      elsif ToAdcModel.TestPattern = 2 then
        --
        -- Send Test pattern 2
        --

        -- Samples 0 to 99 - Data = 0
        for count in 0 to 52 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"800";
          pAdcDataB <= X"800";
        end loop;

        wait on AdcClk until rising_edge(AdcClk);
        pAdcDataA <= X"940";
        pAdcDataB <= X"0F0";

        wait on AdcClk until rising_edge(AdcClk);
        pAdcDataA <= X"3D0";
        pAdcDataB <= X"170";

        wait on AdcClk until rising_edge(AdcClk);
        pAdcDataA <= X"DC0";
        pAdcDataB <= X"BB0";

        wait on AdcClk until rising_edge(AdcClk);
        pAdcDataA <= X"AF0";
        pAdcDataB <= X"800";

        for count in 0 to 299 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"800";
          pAdcDataB <= X"800";
        end loop;

      elsif ToAdcModel.TestPattern = 3 then
        --
        -- Send Test Pattern 3
        --

        -- Samples 0 to 99 - Data = 0
        for count in 0 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;

        -- Samples 100 to 199 - Data = 0 to 500
        for count in 1 to 50 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector(((2*count-1) * (500/100)), 12);
          pAdcDataB <= conv_std_logic_vector(((2*count) * (500/100)), 12);
        end loop;

        -- Samples 200 to 209 - Data = 0
        for count in 1 to 5 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;

        -- Samples 210 to 300 - Data = 500 to 700
        for count in 1 to 45 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= conv_std_logic_vector((500 + (2*count-1) * (200/90)), 12);
          pAdcDataB <= conv_std_logic_vector((500 + (2*count) * (200/90)), 12);
        end loop;

        -- Samples 300 to 399 - Data = 0
        for count in 0 to 200 loop
          wait on AdcClk until rising_edge(AdcClk);
          pAdcDataA <= X"000";
          pAdcDataB <= X"000";
        end loop;

      else
        -- Unknown test pattern - Report and stop simulation
        report "ADC Model: Error - Unknown test pattern"
          severity failure;
      end if;

      write (vLine, string'("ADC Model: Sending A-Scan "));
      write (vLine, ToAdcModel.RepeatTimes - vRepeatCount);
      write (vLine, string'(" of "));
      write (vLine, ToAdcModel.RepeatTimes);
      write (vLine, string'(" Completed"));
      writeline (OUTPUT, vLine);


    end loop;

      wait on AdcClk until rising_edge(AdcClk);


  end process GenAScan;


end architecture beh;