----------------------------------------------------
--
--  Library Name :  CTUasVTU
--  Unit    Name :  MemMap_ctuAsVtu
--  Unit    Type :  Package
--
------------------------------------------------------

-----------------------------------------------
-----------------------------------------------
-- Date          : Fri Feb 24 15:12:20 2017
--
-- Author        : dbarrien
--
-- Company       : CERN, BE-RF
--
-- Description   : VTU functionality in Chopper Trigger Unit (CTU)
--
-- Changelog     : 20170224 Initial version
--
-----------------------------------------------
-----------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;


-- MemoryMap : EDA-03072.
package MemMap_ctuAsVtu is
	-- register-data control2's code fields :
	constant C_Code_ctuAsVtu_control2_mode_singlePulse  : std_logic_vector(7 downto 5) := "000";
	constant C_Code_ctuAsVtu_control2_mode_infiniteWindow : std_logic_vector(7 downto 5) := "001";
	constant C_Code_ctuAsVtu_control2_mode_windowedOperation : std_logic_vector(7 downto 5) := "010";
	constant C_Code_ctuAsVtu_control2_mode_syncLessOperation : std_logic_vector(7 downto 5) := "011";
	constant C_Code_ctuAsVtu_control2_mode_lowFreqGeneration : std_logic_vector(7 downto 5) := "100";
	constant C_Code_ctuAsVtu_control2_mode_playMemory   : std_logic_vector(7 downto 5) := "101";
	constant C_Code_ctuAsVtu_control2_mode_HighFreqGeneration : std_logic_vector(7 downto 5) := "110";

end;
-- EOF

----------------------------------------------------
--
--      VHDL code generated by Visual Elite
--
--  Design Unit:
--  ------------
--      Unit    Name  :  PlayMemLogic
--      Library Name  :  CTUasVTU
--
--      Creation Date :  Tue Mar 07 11:40:50 2017
--      Version       :  2015.01 v4.6.0 build 42. Date: Feb 22 2015. License: 2015.2
--
--  Options Used:
--  -------------
--      Target
--         Language   :  As Is
--         Purpose    :  Synthesis
--         Vendor     :  Generic
--
--      Style
--         Use Procedures                 :  No
--         Code Destination               :  Combined file
--         Attach Packages                :  Yes
--         Generate Entity                :  Yes
--         Attach Directives              :  Yes
--         Structural                     :  No
--         Configuration Specification    :  No
--         library name in
--         Configuration Specification    :  No
--         Configuration Declaration      :  None
--         Preserve spacing for free text :  Yes
--         Declaration alignment          :  No
--
----------------------------------------------------
----------------------------------------------------
--
--  Library Name :  CTUasVTU
--  Unit    Name :  PlayMemLogic
--  Unit    Type :  Text Unit
--
------------------------------------------------------
----------------------------------------------------
--
--  Library Name :  CTUasVTU
--  Unit    Name :  PlayMemLogic
--  Unit    Type :  Text Unit
--
------------------------------------------------------
------------------------------------------
------------------------------------------
-- Date        : Tue Feb 28 17:09:40 2017
--
-- Author      : Diego Barrientos <diego.barrientos@cern.ch>
--
-- Company     : CERN, BE-RF-CS
--
-- Description : Logic to get address and output logic
--               for play memory.
--
------------------------------------------
------------------------------------------
library ieee;
use ieee.STD_LOGIC_1164.all;
library ieee;
use ieee.NUMERIC_STD.all;

entity PlayMemLogic is
    port(
        Clk : in std_logic;
        RunPlayMem : in std_logic;
        FirstOutput : in std_logic;
        PlayingMem : in std_logic;
        LastElem : in std_logic_vector; -- unconstrained
        RdData : in std_logic_vector(7 downto 0);
        RdDataPrev : in std_logic_vector(7 downto 0);
        RdDataZero : in std_logic_vector(7 downto 0);
        FirstBit : in std_logic_vector(2 downto 0);
        LastBit : in std_logic_vector(2 downto 0);
        Mem_Addr : out std_logic_vector; -- unconstrained
        DataOut : out std_logic_vector(7 downto 0)
    );
end PlayMemLogic;

------------------------------------------
------------------------------------------
-- Date        : Tue Feb 28 17:13:42 2017
--
-- Author      : Diego Barrientos <diego.barrientos@cern.ch>
--
-- Company     : CERN, BE-RF-CS
--
-- Description :
--
------------------------------------------
------------------------------------------

architecture V1 of PlayMemLogic is
    -- Constants
    constant CAddrZero : std_logic_vector(Mem_Addr'range) := (others  => '0');
    constant CAddrOne  : std_logic_vector(Mem_Addr'range) := std_logic_vector(to_unsigned(1, Mem_Addr'length));
    constant CAddrTwo  : std_logic_vector(Mem_Addr'range) := std_logic_vector(to_unsigned(2, Mem_Addr'length));

    -- Signals
    signal Mem_Addr_i : std_logic_vector(Mem_Addr'range) := (others => '0'); -- Local copy of Mem_Addr
    signal Mem_Addr_sync : std_logic_vector(Mem_Addr'range) := (others => '0'); -- Auxiliary signal for computing Mem_Addr (synchronous process)
    signal Mem_Addr_sync_prev : std_logic_vector(Mem_Addr'range) := (others => '0'); -- Previous value of Mem_Addr_sync
    signal DataOut_FirstWord : std_logic_vector(7 downto 0) := (others => '0'); -- First word to be put at the output
    signal DataOut_i : std_logic_vector(7 downto 0) := (others => '0'); -- Output word while running with LastElem not zero
    signal DataOut_Zero : std_logic_vector(7 downto 0) := (others => '0'); -- Output word while running with LastElem equal to zero
    signal ZeroInMSBs : std_logic := '0'; -- When active, put RdDataZero in MSBs of output word
    signal FirstBitInt : integer range 0 to 7 := 0; -- Integer conversion of FirstBit
    signal LastBitInt : integer range 0 to 7 := 0; -- Integer conversion of LastBit
    signal FirstSlice  : unsigned(3 downto 0) := (others => '0'); -- Last element of first slice (from 7 to 0) in output word
    signal SecondSlice : unsigned(2 downto 0) := (others => '0'); -- Last element of second slice (from 7 to 0) in output word
    signal LastBitPlayedZero, LastBitPlayedZero_prev : integer range 0 to 7 := 0; -- Last bit of Zero word played in DataOut_Zero
begin

    -- Synchronous process
    process(Clk)
    begin
        if rising_edge(Clk) then
            Mem_Addr_sync_prev <= Mem_Addr_sync;
            if RunPlayMem = '0' then
                -- When not running
                FirstSlice  <= (others => '0');
                SecondSlice <= (others => '0');
                Mem_Addr_sync <= (others => '0');
                ZeroInMSBs <= '0';
                LastBitPlayedZero_prev <= 0;
            elsif LastElem = CAddrZero then
                if PlayingMem = '1' then
                    LastBitPlayedZero_prev <= LastBitPlayedZero;
                else
                    LastBitPlayedZero_prev <= 0;
                end if;
            elsif LastElem = CAddrOne then
                -- Keep Addr always to 1
                Mem_Addr_sync <= CAddrOne;
                -- MSBs always from Zero
                ZeroInMSBs <= '1';
                if FirstOutput = '1' then
                    -- If FirstBitInt < 7: DataOut <= RdDataZero(FirstBitInt to 7) & RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                    -- Else: DataOut <= RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                    FirstSlice <= to_unsigned(FirstBitInt+1, 4);
                    if FirstBitInt >= LastBitInt then
                        SecondSlice <= to_unsigned(FirstBitInt-LastBitInt, 3);
                    else
                        SecondSlice <= (others => '0');
                    end if;
                elsif PlayingMem = '1' then
                    if to_integer(FirstSlice) >= LastBitInt+1 then
                        -- If FirstSlice < 8: DataOut <= RdDataZero(FirstSlice to 7) & RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                        -- Else: DataOut <= RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                        FirstSlice <= '0' & SecondSlice;
                        if to_integer(SecondSlice) > LastBitInt+1 then
                            SecondSlice <= to_unsigned(to_integer(SecondSlice)-LastBitInt-1, 3);
                        else
                            SecondSlice <= (others => '0');
                        end if;
                    else
                        if (to_integer(FirstSlice)-to_integer(SecondSlice)) < LastBitInt+1 then
                            -- DataOut <= RdData(FirstSlice-SecondSlice to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                            FirstSlice <= to_unsigned(8+to_integer(FirstSlice), 4);
                            SecondSlice <= to_unsigned(8+to_integer(FirstSlice)-LastBitInt-1, 3);
                        else
                            -- DataOut <= RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                            FirstSlice <= to_unsigned(8, 4);
                            SecondSlice <= to_unsigned(8-LastBitInt-1, 3);
                        end if;
                    end if;
                end if;
            elsif FirstOutput = '1' then
                -- First output
                -- If FirstBitInt < 7: DataOut <= RdDataPrev(FirstBitInt to 7) & RdData(0 to FirstBitInt-1);
                -- Else: DataOut <= RdData(0 to 7);
                FirstSlice <= to_unsigned(FirstBitInt+1, 4);
                SecondSlice <= (others => '0');
                Mem_Addr_sync <= CAddrTwo;
            elsif PlayingMem = '1' then
                -- While playing memory
                if Mem_Addr_i = LastElem then
                    -- Restart sequence
                    if to_integer(FirstSlice) > LastBitInt+1 then
                        -- Some bits from zero word can be added in next word
                        -- If FirstSlice < 8: DataOut <= RdDataPrev(FirstSlice to 7) & RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                        -- Else: DataOut <= RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                        SecondSlice <= to_unsigned(to_integer(FirstSlice)-LastBitInt-1, 3);
                        Mem_Addr_sync <= CAddrOne;
                    elsif to_integer(FirstSlice) = LastBitInt+1 then
                        -- Prepare jump to Data in next two clock cycles
                        SecondSlice <= (others => '0');
                        Mem_Addr_sync <= CAddrZero;
                    elsif Mem_Addr_sync_prev = Mem_Addr_sync then
                        -- Only execute at second cycle coming to this point
                        if (to_integer(FirstSlice)-to_integer(SecondSlice)) < LastBitInt+1 then
                            -- DataOut <= RdData(FirstSlice-SecondSlice to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                            FirstSlice <= to_unsigned(8+to_integer(FirstSlice), 4);
                            SecondSlice <= to_unsigned(8+to_integer(FirstSlice)-LastBitInt-1, 3);
                        else
                            -- DataOut <= RdData(0 to LastBitInt) & RdDataZero(0 to SecondSlice-1);
                            FirstSlice <= to_unsigned(8, 4);
                            SecondSlice <= to_unsigned(8-LastBitInt-1, 3);
                        end if;
                        Mem_Addr_sync <= CAddrOne;
                    end if;
                    ZeroInMSBs <= '0';
                elsif Mem_Addr_i = CAddrOne then
                    -- Sequence just restarted
                    if SecondSlice /= "000" then
                        -- DataOut <= RdDataZero(FirstSlice to 7) & RdData(0 to FirstSlice-1);
                        FirstSlice <= '0' & SecondSlice;
                        ZeroInMSBs <= '1';
                    else
                        -- Jump to Data
                        -- DataOut <= RdData(0 to 7);
                        FirstSlice <= to_unsigned(8, 4);
                        ZeroInMSBs <= '0';
                    end if;
                    SecondSlice <= (others => '0');
                    Mem_Addr_sync <= CAddrTwo;
                elsif Mem_Addr_i = CAddrZero then
                    -- Sequence restarted with SecondSlice = 0
                    FirstSlice <= (others => '0');
                    Mem_Addr_sync <= CAddrOne;
                    ZeroInMSBs <= '1';
                else
                    Mem_Addr_sync <= std_logic_vector(unsigned(Mem_Addr_i)+1);
                    ZeroInMSBs <= '0';
                end if;
            end if;
        end if;
    end process;

    -- Integer signals
    FirstBitInt <= to_integer(unsigned(FirstBit));
    LastBitInt <= to_integer(unsigned(LastBit));

    -- Concurrent assignment of DataOut_FirstWord
    process(RdDataZero, FirstBitInt)
    begin
        for i in 7 downto 0 loop
            if i <= FirstBitInt then
                -- Reverse order for RdDataZero (Index 0 goes to FirstBitInt)
                DataOut_FirstWord(i) <= RdDataZero(FirstBitInt-i);
            else
                -- Fill with zeros in MSBs
                DataOut_FirstWord(i) <= '0';
            end if;
        end loop;
    end process;

    -- Concurrent assignment of DataOut_i
    process(RdData, RdDataPrev, RdDataZero, FirstSlice, SecondSlice, ZeroInMSBs)
    begin
        for i in 7 downto 0 loop
            if i >= to_integer(FirstSlice) then
                if ZeroInMSBs = '0' then
                    -- MSBs => previous word
                    DataOut_i(i) <= RdDataPrev(7+to_integer(FirstSlice)-i);
                else
                    -- MSBs => zero word
                    DataOut_i(i) <= RdDataZero(7+to_integer(FirstSlice)-i);
                end if;
            elsif i >= to_integer(SecondSlice) then
                -- Intermediate bits => current word
                DataOut_i(i) <= RdData(to_integer(FirstSlice)-i-1);
            else
                -- LSBs => zero word
                DataOut_i(i) <= RdDataZero(to_integer(SecondSlice)-i-1);
            end if;
        end loop;
    end process;

    -- Concurrent assignment of DataOut_Zero
    process(RdDataZero, FirstBitInt, FirstOutput, LastBitInt, LastBitPlayedZero_prev)
        variable last_bit : integer range 0 to 7;
    begin
        if FirstOutput = '1' then
            -- First word
            last_bit := LastBitInt;
            for i in 7 downto 0 loop
                if i > FirstBitInt then
                    -- Fill with zeros in MSBs
                    DataOut_Zero(i) <= '0';
                elsif last_bit > 0 then
                    DataOut_Zero(i) <= RdDataZero(LastBitInt-last_bit);
                    last_bit := last_bit-1;
                else
                    DataOut_Zero(i) <= RdDataZero(LastBitInt);
                    last_bit := LastBitInt;
                end if;
            end loop;
            LastBitPlayedZero <= LastBitInt-last_bit;
        else
            last_bit := LastBitInt-LastBitPlayedZero_prev;
            for i in 7 downto 0 loop
                if last_bit > 0 then
                    DataOut_Zero(i) <= RdDataZero(LastBitInt-last_bit);
                    last_bit := last_bit-1;
                else
                    DataOut_Zero(i) <= RdDataZero(LastBitInt);
                    last_bit := LastBitInt;
                end if;
            end loop;
            LastBitPlayedZero <= LastBitInt-last_bit;
        end if;
    end process;

    -- Output signals
    Mem_Addr_i <= CAddrOne when FirstOutput='1' and LastElem /= CAddrZero else
                  Mem_Addr_sync when PlayingMem='1' and LastElem /= CAddrZero else
                  (others => '0');
    Mem_Addr <= Mem_Addr_i;
    DataOut <= DataOut_FirstWord when FirstOutput='1' and LastElem /= CAddrZero else
               DataOut_i when PlayingMem='1' and LastElem /= CAddrZero else
               DataOut_Zero when PlayingMem='1' and LastElem = CAddrZero else
               (others => '0');

end;

----------------------------------------------------
--
--  Library Name :  CommonVisual
--  Unit    Name :  RSFF
--  Unit    Type :  Text Unit
--
------------------------------------------------------
----------------------------------------------------------------
----------------------------------------------------------------
-- Date        : Wed Jun 11 17:46:39 2003
--
-- Author      : J.C.Molendijk
--
-- Company     : CERN BE-RF-CS
--
-- Description : A Synchronous Set Reset FF (Priority to Reset)
--
----------------------------------------------------------------
-- 20091030 : Addition of the pin reset with
--            default value '0'.
--            Replacement of Clk'event and Clk='1'
--            by rising_edge(Clk).(Done by Greg)
--
----------------------------------------------------------------
----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity RSFF is
port (Clk,Set,Clr: in std_logic;
      Rst : in std_logic:='0'; --Reset active high, port can be left open is unused
      Q: out std_logic);

end;

----------------------------------------------------------------
----------------------------------------------------------------
-- Date        : Wed Jun 11 17:46:39 2003
--
-- Author      : J.C.Molendijk
--
-- Company     : CERN BE-RF-CS
--
-- Description : A Synchronous Set Reset FF (Priority to Reset)
--
----------------------------------------------------------------
-- 20091030 : Addition of the pin reset with
--            default value '0'.
--            Replacement of Clk'event and Clk='1'
--            by rising_edge(Clk).(Done by Greg)
--
----------------------------------------------------------------
----------------------------------------------------------------
architecture  V1 of RSFF is
begin

process(Clk)
  begin
    if rising_edge(Clk) then
        if Clr = '1' or Rst='1' then
          Q <= '0';
        elsif Set = '1'then
          Q <= '1';
        end if;
    end if;
  end process;

end;


library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;

entity vtuDataShifter is
  generic (N : INTEGER := 16
           --  Number of bits of delay register. Minimum value: 4
           );
  port (
    Clk : in std_logic;

    --  Input data.  The first bit is the MSB.  This is handled as a pulse.
    DataIn : in std_logic_vector(7 downto 0);

    --  Delay to be applied to DataIn.  The 3 LSB is the fine delay (1/8 of CLK),
    --  the other bits are the coarse delay (CLK)
    Delay : in std_logic_vector(N - 1 downto 0);

    --  True if the coarse part of Delay is 0 (which is incorrect).
    CoarseZero : out std_logic;

    --  Data output, provided 1 clock cycle after DataIn.
    --  The first bit to generate is the MSB.
    DataOut : out std_logic_vector(7 downto 0);

    --  Set when the output is generated (1 pulse after the delay)
    OutputEnabled : out std_logic;

    --  Must be set to operate.
    Enabled : in std_logic;

    --  Set when a pulse has been detected on DataIn
    SyncPulse : out std_logic);
end vtuDataShifter;


architecture vtuDataShifter of vtuDataShifter is
  signal SyncPulse_i : std_logic;
  signal DataClean : std_logic_vector(7 downto 0 );
  signal DataOut_i : std_logic_vector(7 downto 0 );
  signal CoarseCnt : std_logic_vector(N - 4 downto 0 );
  signal Ready : std_logic;
  signal CoarseDly : std_logic_vector(N - 4 downto 0 );
  signal OutputEnabled_i : std_logic;
  signal Sync_i : std_logic;
  signal OutGood : std_logic;
  signal OutGood_d : std_logic;
  signal Disabled : std_logic;
  signal CoarseZero_i : std_logic;
  signal UseNextValue : std_logic;
  signal FineDly : std_logic_vector(2 downto 0 );

  -- Function clean_data
  --   Combinatorial. Search for the first '1' and removes other '1's.
  function clean_data( V: std_logic_vector(7 downto 0) ) return std_logic_vector is
    begin
      if V(7)='1' then
        return "10000000";
      elsif V(6)='1' then
        return "01000000";
      elsif V(5)='1' then
        return "00100000";
      elsif V(4)='1' then
        return "00010000";
      elsif V(3)='1' then
        return "00001000";
      elsif V(2)='1' then
        return "00000100";
      elsif V(1)='1' then
        return "00000010";
      elsif V(0)='1' then
        return "00000001";
      else
        return "00000000";
      end if;
    end clean_data;
begin
  --  Detect the sync pulse.
  b_sync_pulse: block
    begin
    --  Set if at least one bit is set.
    Sync_i <= '1' when DataIn /= b"0000_0000" else '0';

    --  Filter out sync pulses after the first one and before the first output.
    SyncPulse_i <= '1' when Sync_i = '1' and (Ready = '0' or OutputEnabled_i = '1') else '0';

    SyncPulse <= SyncPulse_i;

    --  Set Ready: when a pulse has been detected.
    process (Clk)
    begin
      if rising_edge(Clk) then
        if Enabled = '0' then
          Ready <= '0';
        elsif SyncPulse_i = '1' then
          Ready <= '1';
        elsif OutputEnabled_i = '1' then
          Ready <= '0';
        end if;
      end if;
    end process;
  end block;

  --  Capture the data containing the pulse.
  --  Clean to have only one bit set (so a real pulse)
  process (Clk)
  begin
    if rising_edge(Clk) then
      if SyncPulse_i = '1' then
        DataClean <= clean_data(DataIn);
      end if;
    end if;
  end process;

  --  Split Delay into coarse and fine delay.
  CoarseDly <= Delay(N-1 downto 3);
  FineDly <= Delay(2 downto 0);

  --  Prepare next data output: delay by FineDly.
  ShiftReg_proc: process (DataClean, FineDly)
    variable DataOut_aux : std_logic_vector(15 downto 0);
  begin
    --  Delay by FineDly. Because the first bit is the MSB, do a right shift.
    DataOut_aux := std_logic_vector(shift_right(unsigned(DataClean & x"00"), to_integer(unsigned(FineDly))));
    if DataOut_aux(7 downto 0) = (7 downto 0 => '0') then
      DataOut_i <= DataOut_aux(15 downto 8);
      --  Need to wait one cycle.
      UseNextValue <= '0';
    else
      DataOut_i <= DataOut_aux(7 downto 0);
      UseNextValue <= '1';
    end if;
  end process;

  --  True when Coarse is zero.
  CoarseZero_i <= '1' when CoarseDly = (N-4 downto 0 => '0') else '0';
  CoarseZero <= CoarseZero_i;

  --  Shift is disabled if not enabled or if Delay is less than 1 coarse cycle.
  Disabled <= (not Enabled) or CoarseZero_i;

  --  Coarse counter.
  process (Clk)
  begin
    if rising_edge (Clk) then
      if SyncPulse_i = '1' or Disabled = '1' then
        --  Start count at sync pulse.
        CoarseCnt <= (0 => '1', others => '0');
      else
        CoarseCnt <= std_logic_vector(unsigned (CoarseCnt) + 1);
      end if;
    end if;
  end process;

  --  Set when data output is to be generated for this cycle.
  OutGood <= Ready when CoarseCnt = CoarseDly else '0';

  process (Clk)
  begin
    if rising_edge (Clk) then
      --  Clear it when not used
      OutGood_d <= OutGood and UseNextValue;
    end if;
  end process;

  --  Maybe OutGood must be delayed by 1 cycle due to fine delay.
  OutputEnabled_i <= OutGood_d when UseNextValue = '1' else OutGood;
  OutputEnabled <= OutputEnabled_i and Enabled;

  DataOut <= DataOut_i when OutputEnabled_i = '1' and Enabled = '1' else (others => '0');
end vtuDataShifter;

library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
entity vtuSeq is
  port (
        Clk : in std_logic;
        Rst : in std_logic;
        Start : in std_logic;
        Stop : in std_logic;
        SyncPulse : in std_logic;
        OutputEnable1 : in std_logic;
        OutputEnable2 : in std_logic;
        Shifter1Ena : out std_logic := '0';
        Shifter2Ena : out std_logic := '0';
        SwitchtoHT : out std_logic := '0';    -- Select B or HT output.
        wValueOne : in std_logic;
        WindowDone : in std_logic;
        CounterRst : out std_logic := '0';
        State_Idle : out std_logic;
        State_Started : out std_logic;
        State_Run : out std_logic
        );
end vtuSeq;


architecture vtuSeq of vtuSeq is
  type visual_Idle_states is
    (
       Idle,
       S_waitSync,
       S_BValue,
       S_HTValue
    );
  signal state : visual_Idle_states;
begin
  -- Synchronous process
  vtuSeq_Idle:
  process (Clk)
  begin
    if rising_edge(Clk) then
      if Rst = '1' or Stop = '1' then
        --  Reset (or stop): back to idle.
        Shifter1Ena <= '0';
        Shifter2Ena <= '0';
        SwitchtoHT   <= '0';
        CounterRst <= '1';
        state <= Idle;
      else
        case state is
          when Idle =>
            Shifter2Ena <= '0';
            SwitchtoHT  <= '0';
            CounterRst  <= '0';
            if Start = '1' then
              --  Wait for Sync.
              Shifter1Ena <= '1';
              state <= S_waitSync;
            else
              Shifter1Ena <= '0';
              state <= Idle;
            end if;

          when S_waitSync =>
            if SyncPulse = '1' then
              --  Run.
              Shifter1Ena <= '1';
              Shifter2Ena <= '1';
              SwitchtoHT  <= '0';
              CounterRst  <= '0';
              state <= S_BValue;
            else
              CounterRst <= '0';
              state <= S_waitSync;
            end if;

          when S_BValue =>
            if OutputEnable1 = '1' and wValueOne = '0' then
              --  First pulse sent, send the others.
              Shifter1Ena <= '0';
              Shifter2Ena <= '1';
              SwitchtoHT  <= '1';
              CounterRst  <= '0';
              state <= S_HTValue;
            elsif OutputEnable1 = '1' and wValueOne = '1' then
              --  First pulse sent, but there is only one pulse to send.
              --  Back to idle.
              Shifter1Ena <= '0';
              Shifter2Ena <= '0';
              SwitchtoHT  <= '0';
              CounterRst  <= '1';
              state <= Idle;
            elsif Start = '1' then
              --  Restart, wait for sync
              Shifter1Ena <= '0';
              Shifter2Ena <= '0';
              SwitchtoHT  <= '0';
              CounterRst  <= '1';
              state <= S_waitSync;
            else
              CounterRst <= '0';
              state <= S_BValue;
            end if;

          when S_HTValue =>
            if OutputEnable2 = '1' and WindowDone = '1' then
              --  Done.
              Shifter1Ena <= '0';
              Shifter2Ena <= '0';
              SwitchtoHT  <= '0';
              CounterRst  <= '1';
              state <= Idle;
            else
              state <= S_HTValue;
            end if;

          when others =>
            state <= Idle;
        end case;
      end if;
    end if;
  end process vtuSeq_Idle;

  process(state) is
  begin
    State_Idle <= '0';
    State_Run <= '0';
    State_Started <= '0';
    
    case state is
      when Idle =>
        State_Idle <= '1';
      when s_WaitSync =>
        State_Started <= '1';
      when s_BValue
         | s_HTValue =>
        State_Run <= '1';
    end case;
  end process;
end vtuSeq;


library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
library work;
use work.MemMap_ctuAsVtu.all;
entity WrongValuesLogic is
  port (
        wrongB : out std_logic := '0';
        wrongHT : out std_logic := '0';
        wrongW : out std_logic := '0';
        BCoarseZero : in std_logic;
        HTCoarseZero : in std_logic;
        wValueZero : in std_logic;
        Mode : in std_logic_vector(2 downto 0 );
        Clk : in std_logic;
        Rst : in std_logic
        );

end WrongValuesLogic;


architecture WrongValuesLogic of WrongValuesLogic is
begin
  process (Clk)
  begin
    if rising_edge(Clk) then
      if Rst = '1' then
        wrongB <= '1';
        wrongHT <= '1';
        wrongW <= '1';
      else
        wrongB <= '0';
        wrongHT <= '0';
        wrongW <= '0';
        case Mode is
          when C_Code_ctuAsVtu_control2_mode_singlePulse =>
            wrongB <= BCoarseZero;
          when C_Code_ctuAsVtu_control2_mode_infiniteWindow =>
            wrongB <= BCoarseZero;
            wrongHT <= HTCoarseZero;
          when C_Code_ctuAsVtu_control2_mode_windowedOperation =>
            wrongB <= BCoarseZero;
            wrongHT <= HTCoarseZero;
            wrongW <= wValueZero;
          when C_Code_ctuAsVtu_control2_mode_syncLessOperation =>
            wrongHT <= HTCoarseZero;
          when C_Code_ctuAsVtu_control2_mode_lowFreqGeneration =>
            wrongB <= BCoarseZero;
            wrongHT <= HTCoarseZero;
          when C_Code_ctuAsVtu_control2_mode_playMemory =>
            wrongB <= BCoarseZero;
          when C_Code_ctuAsVtu_control2_mode_highFreqGeneration =>
            wrongB <= BCoarseZero;
          when others =>
            --  Unknown mode
            wrongB <= '1';
            wrongHT <= '1';
            wrongW <= '1';
        end case;
      end if;
    end if;
  end process;
end WrongValuesLogic;


library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
library work;
use work.MemMap_ctuAsVtu.all;

entity vtuCore is
  port (
        Clk : in std_logic;
        Rst : in std_logic; --  Synchronous to QCLk

        --  Inputs.
        Start : in std_logic;
        Stop : in std_logic;

        --  Sync input.
        DataIn : in std_logic_vector(7 downto 0 );

        --  Output.
        DataOut : out std_logic_vector(7 downto 0 );

        --  Mode Parameter:
        --   000: single pulse
        --   001: infinite window
        --   010: windowed operation,
        --   011: syncless operation
        --   100: low frequency generation
        --   101: play memory
        Mode : in std_logic_vector(2 downto 0 );

        --  Parameter:
        --   For single pulse mode: number of clock after the sync pulse.
        bValue : in std_logic_vector(63 downto 0 );
        wrongB : out std_logic;

        --  Parameter: number of pulses
        htValue : in std_logic_vector(63 downto 0 );
        wrongHT : out std_logic;

        --  Parameter: window size
        wValue : in std_logic_vector(63 downto 0 );
        wrongW : out std_logic;

        --  Parameter: first synchronize with sync (?)
        UseSyncAsStart : in std_logic;

        --  Switch between htValue and htValue-1.
        htSwitching : in std_logic;

        --  Interface to the memory for the play memory mode.
        Mem_RdDone : in std_logic;
        Mem_Addr : out std_logic_vector(14 downto 0 );
        Mem_RdData : in std_logic_vector(7 downto 0 );
        Mem_RdEna : out std_logic;

        --  Parameter: position of the last bit to be played.
        Mem_LastBit : in std_logic_vector(2 downto 0 );
        Mem_LastElem : in std_logic_vector(14 downto 0 );

        --  A pulse has been detected on DataIn.
        SyncPulse : out std_logic;

        --  The VTU state:
        --   Idle: waiting for the start pulse
        --   Started: waiting for the sync pulse
        --   Running: running
        State_Idle : out std_logic;
        State_Started : out std_logic;
        State_Running : out std_logic
        );
end vtuCore;


architecture vtuCore of vtuCore is
  signal PlayMemoryMode : std_logic;
  signal SyncLessOperationMode : std_logic;
  signal WindowedOperationMode : std_logic;
  signal InfiniteWindowMode : std_logic;
  signal LowFreqGenerationMode : std_logic;
  signal HighFreqGenerationMode : std_logic;
  signal SinglePulseMode : std_logic;

  signal RunSyncLess : std_logic;
  signal Run_seq : std_logic;
  signal State_Running_i : std_logic;
  signal State_Idle_i : std_logic;
  signal State_Started_i : std_logic;
  signal HTSwitchEna : std_logic;
  signal SwitchHTeffective : std_logic;
  signal htValue_effective : std_logic_vector(63 downto 0 );
  signal Start_i : std_logic;
  signal SyncPulse_i : std_logic;
  signal PlayingMem : std_logic;
  signal RstOrStopSeq : std_logic;

  signal DataOutLowFreq : std_logic_vector(7 downto 0 );
  signal DataOutPlayMem : std_logic_vector(7 downto 0 );
  signal DataOut_seq : std_logic_vector(7 downto 0 );
  signal DataOutHTSyncLess : std_logic_vector(7 downto 0 );
  signal DataOutHighFreq : std_logic_vector(7 downto 0 );
  signal DataOut_B : std_logic_vector(7 downto 0 );

  signal Shifter1Ena : std_logic;
  signal Shifter2Ena : std_logic;

  signal OE_SyncLess : std_logic;
  signal OE_B : std_logic;
  signal OE_HT : std_logic;
begin
  process (Mode)
  begin
    SinglePulseMode <= '0';
    InfiniteWindowMode <= '0';
    WindowedOperationMode <= '0';
    SyncLessOperationMode <= '0';
    LowFreqGenerationMode <= '0';
    HighFreqGenerationMode <= '0';
    PlayMemoryMode <= '0';

    case Mode is
      when C_Code_ctuAsVtu_control2_mode_singlePulse =>
        SinglePulseMode <= '1';
      when C_Code_ctuAsVtu_control2_mode_infiniteWindow =>
        InfiniteWindowMode <= '1';
      when C_Code_ctuAsVtu_control2_mode_windowedOperation =>
        WindowedOperationMode <= '1';
      when C_Code_ctuAsVtu_control2_mode_syncLessOperation =>
        SyncLessOperationMode <= '1';
      when C_Code_ctuAsVtu_control2_mode_lowFreqGeneration =>
        LowFreqGenerationMode <= '1';
      when C_Code_ctuAsVtu_control2_mode_highFreqGeneration =>
        HighFreqGenerationMode <= '1';
      when C_Code_ctuAsVtu_control2_mode_playMemory =>
        PlayMemoryMode <= '1';
      when others =>
        null;
    end case;
  end process;

  --  Select start input.
  Start_i <=  Start when UseSyncAsStart = '0' else SyncPulse_i;

  process (htValue, SwitchHTeffective)
  begin
     case SwitchHTeffective is
       when '0' =>
         htValue_effective <=  htValue;
       when others =>
         --  Do not care about overflow in the addition.  It can only happen when htValue is ffff_ffff_ffff_ffff,
         --  and thus the switch happen after the end of the universe.
         htValue_effective <=  std_logic_vector(unsigned(htValue) + 1);
     end case;
   end process;

  HTSwitchEna <= (OE_HT or OE_SyncLess) and htSwitching;

  process (Clk, State_Running_i)
  begin
    if State_Running_i = '0' then
      SwitchHTeffective <= '0';
    elsif Clk'event and Clk = '1' then
      if HTSwitchEna = '1' then
        SwitchHTeffective <= not SwitchHTeffective;
      end if;
    end if;
  end process;

  blk_seq: block
  is
    signal wrongHT_s : std_logic;
    signal wrongW_s : std_logic;
    signal wrongB_s : std_logic;
    signal BCoarseZero : std_logic;
    signal HTCoarseZero : std_logic;
    signal wValueZero : std_logic;
    signal wValueOne : std_logic;
    signal WindowDone_seq : std_logic;
    signal Stop_seq : std_logic;
    signal Start_seq : std_logic;
    signal DataOut_seq_i : std_logic_vector(7 downto 0 );
    signal wrongValue : std_logic;
    signal DataIn_HT : std_logic_vector(7 downto 0 );
    signal wValueOne_seq : std_logic;
    signal SwitchOutput : std_logic;
    signal counterEnable : std_logic;
    signal SwitchtoHT : std_logic;
    signal DataOut_HT : std_logic_vector(7 downto 0 );
    signal PulseCount : std_logic_vector(63 downto 0 );
    signal counterReset : std_logic;
    signal InfiniteWindow : std_logic;
  begin
    B_WrongValuesLogic: entity work.WrongValuesLogic
      port map (wrongB => wrongB_s,
                wrongHT => wrongHT_s,
                wrongW => wrongW_s,
                BCoarseZero => BCoarseZero,
                HTCoarseZero => HTCoarseZero,
                wValueZero => wValueZero,
                Mode => Mode(2 downto 0),
                Clk => Clk,
                Rst => Rst);

    wrongB <= wrongB_s;

    wrongHT <= wrongHT_s;

    wrongW <= wrongW_s;

    --  Data shifter using B parameters: from Sync pulse to the first pulse.
    B_DataShifterB: entity work.vtuDataShifter
      generic map (N => 64)
      port map (CoarseZero => BCoarseZero,
                DataOut => DataOut_B,
                OutputEnabled => OE_B,
                Clk => Clk,
                Delay => bValue,
                DataIn => DataIn,
                Enabled => Shifter1Ena,
                SyncPulse => SyncPulse_i);

    --  Data shifter using HT parameters: after the first pulse.
    B_DataShifterHT: entity work.vtuDataShifter
      generic map (N => 64)
      port map (CoarseZero => HTCoarseZero,
                DataOut => DataOut_HT,
                OutputEnabled => OE_HT,
                Clk => Clk,
                Delay => htValue_effective,
                DataIn => DataIn_HT,
                Enabled => Shifter2Ena,
                SyncPulse => open);

    B_vtuSeq: entity work.vtuSeq
      port map (Clk => Clk,
                Rst => Rst,
                Start => Start_seq,
                Stop => Stop_seq,
                SyncPulse => SyncPulse_i,
                OutputEnable1 => OE_B,
                OutputEnable2 => OE_HT,
                Shifter1Ena => Shifter1Ena,
                Shifter2Ena => Shifter2Ena,
                SwitchtoHT => SwitchtoHT,
                wValueOne => wValueOne_seq,
                WindowDone => WindowDone_seq,
                CounterRst => counterReset,
                State_Idle => State_Idle_i,
                State_Started => State_Started_i,
                State_Run => Run_seq);

    --  Start sequencer on start signal if sequencer mode selected.
    Start_seq <=  Start_i when (SyncLessOperationMode or PlayMemoryMode) = '0' else '0';

    wrongValue <= wrongB_s or wrongHT_s or wrongW_s;

    --  Stop sequencer on stop signal or if values aren't correct.
    Stop_seq <= Stop or wrongValue;

    SwitchOutput <= SwitchtoHT or (not Run_seq);

    process (DataOut_B, DataOut_HT, SwitchOutput)
    begin
      case SwitchOutput is
        when '0' =>
          --  B datashifter.
          DataOut_seq_i <=  DataOut_B;
        when others =>
          --  HT datashifter
          DataOut_seq_i <=  DataOut_HT;
      end case;
    end process;

    RstOrStopSeq <= Rst or Stop_seq;

    DataOut_seq <=  DataOut_seq_i when RstOrStopSeq = '0' else (others => '0');

    process (DataOut_B, DataOut_HT, SwitchtoHT)
    begin
      case SwitchtoHT is
        when '0' =>
          --  B datashifter to HT datashifter
          DataIn_HT <=  DataOut_B;
        when others =>
          --  HT datashifter loopback.
          DataIn_HT <=  DataOut_HT;
      end case;
    end process;

    counterEnable <= (OE_B or OE_HT) and Run_seq;

    process (Clk)
    begin
      if Clk'event and Clk = '1' then
        if counterReset = '1' then
          --  Start at 1 so that WindowDone_seq is set for the next pulse.
          PulseCount <= x"0000_0000_0000_0001";
        elsif counterEnable = '1' then
          PulseCount <= std_logic_vector(unsigned (PulseCount) + 1);
        end if;
      end if;
    end process;

    InfiniteWindow <= InfiniteWindowMode or LowFreqGenerationMode or HighFreqGenerationMode;

    process (PulseCount, wValue)
    begin
      if InfiniteWindow = '0' and (unsigned(PulseCount) >= unsigned(wValue)) then
        WindowDone_seq <= '1';
      else
        WindowDone_seq <= '0';
      end if;
    end process;

    wValueOne <= '1' when wValue = x"0000_0000_0000_0001" else '0';

    wValueZero <= '1' when wValue = x"0000_0000_0000_0000" else '0';

    wValueOne_seq <= (wValueOne or SinglePulseMode) and (not InfiniteWindow);
  end block blk_seq;

  blk_syncless: block
  is
    signal DataInHTSyncLess : std_logic_vector(7 downto 0 );
    signal SyncLessEna : std_logic;
    signal SetStartData : std_logic := '0';
    signal StartSyncLess : std_logic;
    signal SyncLessDisabled : std_logic;
  begin
    B_DataShifterHT_SyncLess: entity work.vtuDataShifter
      generic map (N => 64)
      port map (CoarseZero => open,
                DataOut => DataOutHTSyncLess,
                OutputEnabled => OE_SyncLess,
                Clk => Clk,
                Delay => htValue_effective,
                DataIn => DataInHTSyncLess,
                Enabled => SyncLessEna,
                SyncPulse => open);

    StartSyncLess <= Start and SyncLessOperationMode;

    --  Pulse on Start when in syncless.
    B_RSFFSyncLessMux: entity work.RSFF
      port map (Clk => Clk,
                Set => StartSyncLess,
                Clr => SetStartData,
                Rst => Rst,
                Q => SetStartData);

    process (DataOutHTSyncLess, SetStartData)
    begin
      case SetStartData is
        when '0' =>
          --  Loopback in normal mode.
          DataInHTSyncLess <=  DataOutHTSyncLess;
        when others =>
          --  On start
          DataInHTSyncLess <=  x"01";
      end case;
    end process;

    SyncLessEna <= SyncLessOperationMode and (not RstOrStopSeq);

    SyncLessDisabled <= not SyncLessEna;

    B_RSFFRunSyncLess: entity work.RSFF
      port map (Clk => Clk,
                Set => StartSyncLess,
                Clr => SyncLessDisabled,
                Rst => Rst,
                Q => RunSyncLess);
  end block blk_syncless;

  blk_playmem: block
  is
    signal Mem_RdData_prev : std_logic_vector(7 downto 0 ) := (others  => '0');
    signal FirstBit : std_logic_vector(2 downto 0);
    signal MemAddrIsZeroPrev : std_logic;
    signal StartPlayMem : std_logic;
    signal RunPlayAndSyncPulse : std_logic;
    signal RunPlayMem_i : std_logic;
    signal SetPlayingMem : std_logic;
    signal PlayingMem_i : std_logic;
    signal MemAddrIsZero : std_logic;
    signal PlayingMem_prev : std_logic;
    signal StopPlayMem : std_logic;
    signal Mem_RdDataZero : std_logic_vector(7 downto 0 ) := (others  => '0');
    signal Mem_Addr_i : std_logic_vector(14 downto 0 );
    signal FirstOutput : std_logic;
    signal RunPlayMem : std_logic;
    signal FirstSyncArrived : std_logic := '0';
    signal ReadDataZero : std_logic;
  begin
    B_PlayMemRunningFF: entity work.RSFF
      port map (Clk => Clk,
                Set => StartPlayMem,
                Clr => StopPlayMem,
                Rst => Rst,
                Q => RunPlayMem_i);

    B_FirstSyncFF: entity work.RSFF
      port map (Clk => Clk,
                Set => RunPlayAndSyncPulse,
                Clr => StopPlayMem,
                Rst => Rst,
                Q => FirstSyncArrived);

    B_PlayingMemFF: entity work.RSFF
      port map (Clk => Clk,
                Set => SetPlayingMem,
                Clr => StopPlayMem,
                Rst => Rst,
                Q => PlayingMem_i);

    B_PlayMemLogic: entity work.PlayMemLogic
      port map (Clk => Clk,
                RunPlayMem => RunPlayMem,
                FirstOutput => FirstOutput,
                PlayingMem => PlayingMem,
                LastElem => Mem_LastElem,
                RdData => Mem_RdData,
                RdDataPrev => Mem_RdData_prev,
                RdDataZero => Mem_RdDataZero,
                FirstBit => FirstBit,
                LastBit => Mem_LastBit,
                Mem_Addr => Mem_Addr_i,
                DataOut => DataOutPlayMem);

    StartPlayMem <= Start_i and PlayMemoryMode;

    StopPlayMem <= (not PlayMemoryMode) or RstOrStopSeq;

    RunPlayMem <= (RunPlayMem_i or StartPlayMem) and (not StopPlayMem);

    RunPlayAndSyncPulse <= RunPlayMem and SyncPulse_i;

    SetPlayingMem <= FirstSyncArrived and OE_B;

    PlayingMem <= (PlayingMem_i or SetPlayingMem) and (not StopPlayMem);

    Mem_RdEna <= RunPlayMem;

    process (Clk)
    begin
      if (Clk'event and Clk = '1') then
        PlayingMem_prev <= PlayingMem;
      end if;
    end process;

    process (Clk)
    begin
      if (Clk'event and Clk = '1') then
        Mem_RdData_prev <= Mem_RdData;
      end if;
    end process;

    FirstOutput <= PlayingMem and (not PlayingMem_prev);

    Mem_Addr <= Mem_Addr_i;

    process (Mem_Addr_i)
    begin
      if Mem_Addr_i = (14 downto 0 => '0') then
        MemAddrIsZero <= '1';
      else
        MemAddrIsZero <= '0';
      end if;
    end process;

    process (Clk)
    begin
      if (Clk'event and Clk = '1') then
        MemAddrIsZeroPrev <= MemAddrIsZero;
      end if;
    end process;

    ReadDataZero <= MemAddrIsZeroPrev and RunPlayMem;

    process (Clk)
    begin
      if (Clk'event and Clk = '1') then
        if ReadDataZero = '1' then
          Mem_RdDataZero <= Mem_RdData;
        end if;
      end if;
    end process;

    FirstBit <= "000" when FirstOutput='1' and DataOut_B(0)='1' else
                "001" when FirstOutput='1' and DataOut_B(1)='1' else
                "010" when FirstOutput='1' and DataOut_B(2)='1' else
                "011" when FirstOutput='1' and DataOut_B(3)='1' else
                "100" when FirstOutput='1' and DataOut_B(4)='1' else
                "101" when FirstOutput='1' and DataOut_B(5)='1' else
                "110" when FirstOutput='1' and DataOut_B(6)='1' else
                "111" when FirstOutput='1' and DataOut_B(7)='1' else
                "000";
  end block blk_playmem;

  --  LowFreq: post processing to generate a square wave from pulses.
  blk_lowfreq: block
  is
    signal DataFilled : std_logic_vector(7 downto 0 );
    signal ClkValueSwitch : std_logic;
  begin
    --  Toggle when a pulse is detected.
    process (Clk, RstOrStopSeq)
    begin
      if RstOrStopSeq = '1' or LowFreqGenerationMode = '0' then
        ClkValueSwitch <= '0';
      elsif (Clk'event and Clk = '1') then
        if DataOut_seq /= x"00" then
          ClkValueSwitch <= not ClkValueSwitch;
        end if;
      end if;
    end process;

    -- Fill data with ones or zeros after one when DataOutPulse='1'
    process (DataOut_seq, RstorStopSeq)
    begin
      if RstOrStopSeq = '1' or LowFreqGenerationMode = '0'  then
        --  Value at rest.
        DataFilled <= "00000000";
      else
        --  In case of pulse, start the wave.
        if DataOut_seq(7)='1' then
          DataFilled <= "01111111";
        elsif DataOut_seq(6)='1' then
          DataFilled <= "00111111";
        elsif DataOut_seq(5)='1' then
          DataFilled <= "00011111";
        elsif DataOut_seq(4)='1' then
          DataFilled <= "00001111";
        elsif DataOut_seq(3)='1' then
          DataFilled <= "00000111";
        elsif DataOut_seq(2)='1' then
          DataFilled <= "00000011";
        elsif DataOut_seq(1)='1' then
          DataFilled <= "00000001";
        else
          --  Either no pulse or start the wave on the next cycle.
          DataFilled <= "00000000";
        end if;
      end if;
    end process;

    DataOutLowFreq <= DataFilled when ClkValueSwitch = '0' else not DataFilled;
  end block blk_lowfreq;

  blk_highfreq: block
    --  True if running.
    signal Fdly : unsigned(3 downto 0);
    signal Ndly : unsigned(3 downto 0);
    signal Sht : unsigned(3 downto 0);
    signal Run_HF : std_logic;
    signal pattern : std_logic_vector (15 downto 0);
    signal waveform : std_logic_vector(15 downto 0);
    signal prev_dataout : std_logic_vector(7 downto 0);
  begin
    process (Clk)
      variable tmp : std_logic_vector(15 downto 0);
    begin
      if rising_edge (Clk) then
        if Rst = '1' or (Shifter1Ena = '0' and Shifter2Ena = '0') then
          Run_HF <= '0';
          waveform <= (others => '0');
          prev_dataout <= (others => '0');
          Sht <= "0000";
          DataOutHighFreq <= x"00";
        else
          if Run_HF = '0' then
            --  Ready to run: wait for sync.  Will clear these signals if no sync.
            Run_HF <= '1';
            waveform <= pattern;
            Sht <= Ndly;

            if DataOut_B (7) = '1' then
              Fdly <= "0001";
            elsif DataOut_B (6) = '1' then
              Fdly <= "0010";
            elsif DataOut_B (5) = '1' then
              Fdly <= "0011";
            elsif DataOut_B (4) = '1' then
              Fdly <= "0100";
            elsif DataOut_B (3) = '1' then
              Fdly <= "0101";
            elsif DataOut_B (2) = '1' then
              Fdly <= "0110";
            elsif DataOut_B (1) = '1' then
              Fdly <= "0111";
            elsif DataOut_B (0) = '1' then
              Fdly <= "1000";
            else
              --  No pulse, don't run.
              Run_HF <= '0';
              DataOutHighFreq <= x"00";
              --  But prepare the pattern.
              --  Ndly is where the first byte appears in the second byte as number of shift to the right.
              case htValue(3 downto 0) is
                when "0010" =>
                  pattern <= "10101010" & "10101010";
                  Ndly <= "0000";
                when "0011" =>
                  pattern <= "11011011" & "01101101";
                  Ndly <= "0001";
                when "0100" =>
                  pattern <= "11001100" & "11001100";
                  Ndly <= "0000";
                when "0101" =>
                  pattern <= "11100111" & "00111001";
                  Ndly <= "0010";
                when "0110" =>
                  pattern <= "11100011" & "10001110";
                  Ndly <= "0100";
                when "0111" =>
                  pattern <= "11110001" & "11100011";
                  Ndly <= "0110";
                when "1000" =>
                  pattern <= "11110000" & "11110000";
                  Ndly <= "0000";
                when "1001" =>
                  pattern <= "11111000" & "01111100";
                  Ndly <= "0001";
                when "1010" =>
                  pattern <= "11111000" & "00111110";
                  Ndly <= "0010";
                when "1011" =>
                  pattern <= "11111100" & "00011111";
                  Ndly <= "0011";
                when "1100" =>
                  pattern <= "11111100" & "00001111";
                  Ndly <= "0100";
                when "1101" =>
                  pattern <= "11111110" & "00000111";
                  Ndly <= "0101";
                when "1110" =>
                  pattern <= "11111110" & "00000011";
                  Ndly <= "0110";
                when "1111" =>
                  pattern <= "11111111" & "00000001";
                  Ndly <= "0111";
                when others =>
                  pattern <= "00000000" & "00000000";
              end case;
            end if;
          else
            --  Running.
            --  Generate the output byte.  We need to also shift from the initial delay.
            tmp := std_logic_vector(shift_right(unsigned(waveform), to_integer(unsigned(Fdly))));
            DataOutHighFreq <= prev_dataout or tmp (15 downto 8);
            prev_dataout <= tmp (7 downto 0);

            --  Prepare the next byte.
            tmp := std_logic_vector(shift_right(unsigned(Waveform), to_integer(unsigned(Ndly))));
            waveform <= waveform(7 downto 0) & tmp (7 downto 0);
            Sht <= Sht + Ndly;
          end if;
        end if;
      end if;
    end process;
  end block;

  with Mode select 
    DataOut <= DataOutHTSyncLess when C_Code_ctuAsVtu_control2_mode_syncLessOperation,
              DataOutLowFreq when C_Code_ctuAsVtu_control2_mode_lowFreqGeneration,
              DataOutHighFreq when C_Code_ctuAsVtu_control2_mode_highFreqGeneration,
              DataOutPlayMem when C_Code_ctuAsVtu_control2_mode_playMemory,
              DataOut_seq when others;

  --  Pulse detected.
  SyncPulse <= SyncPulse_i;

  --  True if running.
  State_Running_i <= Run_seq or RunSyncLess or PlayingMem;

  process (Clk)
  begin
    if rising_edge(Clk) then
      if Rst = '1' then
        State_Running <= '0';
        State_Idle <= '0';
        State_Started <= '0';
      else
        State_Running <= State_Running_i;
        State_Idle <= State_Idle_i;
        State_Started <= State_Started_i;
      end if;
    end if;
  end process;
end vtuCore;
