library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity UUT is
    generic(
       Delay: TIME := 100 ns
    );
    port(
       OK : out STD_LOGIC
    );
end UUT;


architecture behavioral of UUT is
-- Components --
component PFSM
  port(
       CLK : in STD_LOGIC;
       Reset : in STD_LOGIC;
       X : in STD_LOGIC_VECTOR(1 to 5);
       Y : out STD_LOGIC_VECTOR(1 to 13)
  );
end component;
component PFSM_VHDL
  port(
       CLK : in STD_LOGIC;
       Reset : in STD_LOGIC;
       X : in STD_LOGIC_VECTOR(1 to 5);
       Y : out STD_LOGIC_VECTOR(1 to 13)
  );
end component;
component PFSM_SYNTHESIS
  port(
       CLK : in STD_LOGIC;
       Reset : in STD_LOGIC;
       X : in STD_LOGIC_VECTOR(1 to 5);
       Y : out STD_LOGIC_VECTOR(1 to 13)
  );
end component;
component PFSM_TIMING
  port(
       CLK : in STD_LOGIC;
       Reset : in STD_LOGIC;
       X : in STD_LOGIC_VECTOR(1 to 5);
       Y : out STD_LOGIC_VECTOR(1 to 13)
  );
end component;
-- PFSM
signal UUT_CLK, UUT2_CLK, UUT3_CLK, UUT4_CLK: STD_LOGIC;
signal UUT_Reset, UUT2_Reset, UUT3_Reset, UUT4_Reset: STD_LOGIC;
signal UUT_X, UUT2_X, UUT3_X, UUT4_X: STD_LOGIC_VECTOR (1 to 5);
signal UUT_Y, UUT2_Y, UUT3_Y, UUT4_Y: STD_LOGIC_VECTOR (1 to 13);
-- Other
signal CLK: STD_LOGIC;

begin

Schematic: PFSM
    port map (
       CLK => UUT_CLK,
        Reset => UUT_Reset,
       X => UUT_X,
       Y => UUT_Y
    );
    
VHDL: PFSM_VHDL
    port map (
       CLK => UUT2_CLK,
        Reset => UUT2_Reset,
       X => UUT2_X,
       Y => UUT2_Y
    );

SYNTHESIS: PFSM_synthesis
    port map (
       CLK => UUT3_CLK,
        Reset => UUT3_Reset,
       X => UUT3_X,
       Y => UUT3_Y
    );
    
EPM3032ALC44: PFSM_timing
    port map (
       CLK => UUT4_CLK,
        Reset => UUT4_Reset,
       X => UUT4_X,
       Y => UUT4_Y
    );

CLKGenerator: process (CLK) is
begin
    
    if CLK = 'U' then
       CLK <= '0';
    else
       CLK <= not (CLK) after Delay / 4;
    end if;
    
end process CLKGenerator;

Tester: process (CLK) is
variable CntrDelay: INTEGER := 0;
variable CurN: INTEGER := 1;
constant n: INTEGER := 15;

constant Y_ToCheck: STD_LOGIC_VECTOR (1 to n) := "011111111111111";
--                                                    |  |  |
--                                                    |  |  |
constant Reset_Set: STD_LOGIC_VECTOR (1 to n) := "010000000000010";
--                                                    |  |  |
--                                                    |  |  |
constant X1_Set:    STD_LOGIC_VECTOR (1 to n) := "000010000000100";
constant X2_Set:    STD_LOGIC_VECTOR (1 to n) := "000000100000000";
constant X3_Set:    STD_LOGIC_VECTOR (1 to n) := "000000000000000";
constant X4_Set:    STD_LOGIC_VECTOR (1 to n) := "000000000000000";
constant X5_Set:    STD_LOGIC_VECTOR (1 to n) := "000000010000000";
--                                                    |  |  |
--                                                    |  |  |
constant Y1_Set:    STD_LOGIC_VECTOR (1 to n) := "-01100000001001";
--                                                    |  |  |
constant Y2_Set:    STD_LOGIC_VECTOR (1 to n) := "-00010000000100";
constant Y3_Set:    STD_LOGIC_VECTOR (1 to n) := "-00001000000000";
--                                                    |  |  |
constant Y4_Set:    STD_LOGIC_VECTOR (1 to n) := "-00000010000000";
constant Y5_Set:    STD_LOGIC_VECTOR (1 to n) := "-00000001000000";
--                                                    |  |  |
constant Y6_Set:    STD_LOGIC_VECTOR (1 to n) := "-00000010000000";
constant Y7_Set:    STD_LOGIC_VECTOR (1 to n) := "-00000001000000";
--                                                    |  |  |
constant Y8_Set:    STD_LOGIC_VECTOR (1 to n) := "-00010000000100";
constant Y9_Set:    STD_LOGIC_VECTOR (1 to n) := "-00000000000000";
constant Y10_Set:   STD_LOGIC_VECTOR (1 to n) := "-00000000000000";
constant Y11_Set:   STD_LOGIC_VECTOR (1 to n) := "-00001100000000";
constant Y12_Set:   STD_LOGIC_VECTOR (1 to n) := "-00000010000000";
--                                                    |  |  |
constant Y13_Set:   STD_LOGIC_VECTOR (1 to n) := "-00000000100000";
begin
    
    if CntrDelay = 3 then
       CntrDelay := 0;
    else
       CntrDelay := CntrDelay + 1;
    end if;
    
    case CntrDelay is
       
       when 0 => UUT_CLK <= '0' after Delay/10;
              UUT2_CLK <= '0' after Delay/10;
              UUT3_CLK <= '0' after Delay/10;
              UUT4_CLK <= '0' after Delay/10;
              
              if CurN = n then
                 CurN := 1;
              else
                 CurN := CurN + 1;
              end if;                   
              
       when 2 => UUT_CLK <= '1' after Delay/10;
              UUT_Reset <= Reset_Set (CurN);
              UUT_X(1) <= X1_Set (CurN);
              UUT_X(2) <= X2_Set (CurN);
              UUT_X(3) <= X3_Set (CurN);
              UUT_X(4) <= X4_Set (CurN);
              UUT_X(5) <= X5_Set (CurN);
              
              UUT2_CLK <= '1' after Delay/10;
              UUT2_Reset <= Reset_Set (CurN);
              UUT2_X(1) <= X1_Set (CurN);
              UUT2_X(2) <= X2_Set (CurN);
              UUT2_X(3) <= X3_Set (CurN);
              UUT2_X(4) <= X4_Set (CurN);
              UUT2_X(5) <= X5_Set (CurN);
              
              UUT3_CLK <= '1' after Delay/10;
              UUT3_Reset <= Reset_Set (CurN);
              UUT3_X(1) <= X1_Set (CurN);
              UUT3_X(2) <= X2_Set (CurN);
              UUT3_X(3) <= X3_Set (CurN);
              UUT3_X(4) <= X4_Set (CurN);
              UUT3_X(5) <= X5_Set (CurN);
              
              UUT4_CLK <= '1' after Delay/10;
              UUT4_Reset <= Reset_Set (CurN);
              UUT4_X(1) <= X1_Set (CurN);
              UUT4_X(2) <= X2_Set (CurN);
              UUT4_X(3) <= X3_Set (CurN);
              UUT4_X(4) <= X4_Set (CurN);
              UUT4_X(5) <= X5_Set (CurN);
              
       when 3 => if Y_ToCheck(CurN) = '0' or
                 (Y1_Set (CurN) = UUT_Y(1) and
                 Y2_Set (CurN) = UUT_Y(2) and
                 Y3_Set (CurN) = UUT_Y(3) and
                 Y4_Set (CurN) = UUT_Y(4) and
                 Y5_Set (CurN) = UUT_Y(5) and
                 Y6_Set (CurN) = UUT_Y(6) and
                 Y7_Set (CurN) = UUT_Y(7) and
                 Y8_Set (CurN) = UUT_Y(8) and
                 Y9_Set (CurN) = UUT_Y(9) and
                 Y10_Set (CurN) = UUT_Y(10) and
                 Y11_Set (CurN) = UUT_Y(11) and
                 Y12_Set (CurN) = UUT_Y(12) and
                 Y13_Set (CurN) = UUT_Y(13) and
                 
                 Y1_Set (CurN) = UUT2_Y(1) and
                 Y2_Set (CurN) = UUT2_Y(2) and
                 Y3_Set (CurN) = UUT2_Y(3) and
                 Y4_Set (CurN) = UUT2_Y(4) and
                 Y5_Set (CurN) = UUT2_Y(5) and
                 Y6_Set (CurN) = UUT2_Y(6) and
                 Y7_Set (CurN) = UUT2_Y(7) and
                 Y8_Set (CurN) = UUT2_Y(8) and
                 Y9_Set (CurN) = UUT2_Y(9) and
                 Y10_Set (CurN) = UUT2_Y(10) and
                 Y11_Set (CurN) = UUT2_Y(11) and
                 Y12_Set (CurN) = UUT2_Y(12) and
                 Y13_Set (CurN) = UUT2_Y(13) and
                 
                 Y1_Set (CurN) = UUT3_Y(1) and
                 Y2_Set (CurN) = UUT3_Y(2) and
                 Y3_Set (CurN) = UUT3_Y(3) and
                 Y4_Set (CurN) = UUT3_Y(4) and
                 Y5_Set (CurN) = UUT3_Y(5) and
                 Y6_Set (CurN) = UUT3_Y(6) and
                 Y7_Set (CurN) = UUT3_Y(7) and
                 Y8_Set (CurN) = UUT3_Y(8) and
                 Y9_Set (CurN) = UUT3_Y(9) and
                 Y10_Set (CurN) = UUT3_Y(10) and
                 Y11_Set (CurN) = UUT3_Y(11) and
                 Y12_Set (CurN) = UUT3_Y(12) and
                 Y13_Set (CurN) = UUT3_Y(13) and
                 
                 Y1_Set (CurN) = UUT4_Y(1) and
                 Y2_Set (CurN) = UUT4_Y(2) and
                 Y3_Set (CurN) = UUT4_Y(3) and
                 Y4_Set (CurN) = UUT4_Y(4) and
                 Y5_Set (CurN) = UUT4_Y(5) and
                 Y6_Set (CurN) = UUT4_Y(6) and
                 Y7_Set (CurN) = UUT4_Y(7) and
                 Y8_Set (CurN) = UUT4_Y(8) and
                 Y9_Set (CurN) = UUT4_Y(9) and
                 Y10_Set (CurN) = UUT4_Y(10) and
                 Y11_Set (CurN) = UUT4_Y(11) and
                 Y12_Set (CurN) = UUT4_Y(12) and
                 Y13_Set (CurN) = UUT4_Y(13)) then
                   OK <= '1';
              else
                   OK <= '0';
              end if;
       when others => null;
              
    end case;
    
end process;

end behavioral;