-- ==============================================================
-- FILE : fixedCoefficientImageFunctions.VHD
--          may be modified by the USER
-- ==============================================================
--
-- This file is part of the Image Processing Demo, for the HERON-
-- FPGA14 module.
--
-- This file may be modified by the users to implement their
-- own logic.
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     R. Williams    06-04-06    Taken from FPGA12 Example.
--
-- ==============================================================


-----------------------------------------------------------------
--                                                             --
--  Notes: By setting the synchronous generic option to        --
--  TRUE the image block will act synchronously, if it         --
--  is set to false then the block will act asynchronously.    --
--                                                             --
--  The N option sets the data width for the component.        --
--                                                             --
-----------------------------------------------------------------


--NOT function
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity invert is
  generic (
    Synchronous : boolean := True;
    N           : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N-1 downto 0);
    DATA_OUT   : out std_logic_vector(N-1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic
  );
end invert;

architecture Behavioral of invert is

signal DATA_TEMP : std_logic_vector(N - 1 downto 0);

begin

  DATA_TEMP <= NOT DATA_IN;

syncInvert : if(Synchronous) generate
  process(RESET, CLOCK)
  begin
    if RESET = '1' then
      DATA_OUT   <= (others=>'0');
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT <= DVALID_IN;
      EOL_OUT    <= EOL_IN;
      EOF_OUT    <= EOF_IN;
      DATA_OUT   <= DATA_TEMP;
    end if;
  end process;
end generate;

AsyncInvert : if(NOT Synchronous) generate
  DVALID_OUT <= DVALID_IN;
  EOL_OUT    <= EOL_IN;
  EOF_OUT    <= EOF_IN;
  DATA_OUT   <= DATA_TEMP;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function ADDK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ADDK is
  generic (
    Synchronous : boolean := True;
    N           : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end ADDK;

architecture Behavioral of ADDK is

signal DATA_A : std_logic_vector(N downto 0);
signal DATA_B : std_logic_vector(N downto 0);
signal DATA_C : std_logic_vector(N downto 0);
signal DATA_D : std_logic_vector(N - 1 downto 0);
signal DATA_E : std_logic_vector(N - 1 downto 0);

begin

  DATA_A <= '0' & DATA_IN;
  DATA_B <= '0' & K_IN;
  DATA_C <= DATA_A + DATA_B;
  DATA_D <= (others=>'1');
  DATA_E <= DATA_C(N - 1 downto 0) when DATA_C(N)='0' else DATA_D;

SyncANDK : if(Synchronous) generate
  process(RESET, CLOCK)
    begin
    if RESET = '1' then
      DATA_OUT    <= (others=>'0');
      DVALID_OUT  <= '0';
      EOL_OUT     <= '0';
      EOF_OUT     <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT  <= DVALID_IN;
      EOL_OUT     <= EOL_IN;
      EOF_OUT     <= EOF_IN;
      DATA_OUT    <= DATA_E;
    end if;
  end process;
end generate;

ASyncANDK : if(NOT Synchronous) generate
  DVALID_OUT <= DVALID_IN;
  EOL_OUT    <= EOL_IN;
  EOF_OUT    <= EOF_IN;
  DATA_OUT   <= DATA_E;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function ANDK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ANDK is
  generic (
    Synchronous : boolean := True;
    N           : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end ANDK;

architecture Behavioral of ANDK is

signal DATA_TEMP : std_logic_vector(N - 1 downto 0);

begin

  DATA_TEMP <= DATA_IN and K_IN;

SyncANDK : if(Synchronous) generate
  process(RESET, CLOCK)
    begin
    if RESET = '1' then
      DATA_OUT    <= (others=>'0');
      DVALID_OUT  <= '0';
      EOL_OUT     <= '0';
      EOF_OUT     <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT  <= DVALID_IN;
      EOL_OUT     <= EOL_IN;
      EOF_OUT     <= EOF_IN;
      DATA_OUT    <= DATA_TEMP;
    end if;
  end process;
end generate;

ASyncANDK : if(NOT Synchronous) generate
  DVALID_OUT <= DVALID_IN;
  EOL_OUT    <= EOL_IN;
  EOF_OUT    <= EOF_IN;
  DATA_OUT   <= DATA_TEMP;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function RSHK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity RSHK is
  generic (
    Synchronous  : boolean := True;
    FillWithOnes : boolean := False;
    N            : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end RSHK;

architecture Behavioral of RSHK is

signal SEL_A   : std_logic_vector(1 downto 0);
signal SEL_B   : std_logic_vector(1 downto 0);
signal SEL_C   : std_logic;
signal C,D     : std_logic_vector(N - 1 downto 0);
signal x       : std_logic;

signal E,F,G,H : std_logic_vector(31 downto 0);

begin

  SEL_A <= K_IN(1 downto 0);
  SEL_B <= K_IN(3 downto 2);
  SEL_C <= K_IN(4);

  x <= '1' when FillWithOnes = True else '0';

SmallWord : if (N < 32) generate

  E(N - 1 downto 0) <= DATA_IN(N - 1 downto 0);

  gINIT : for I in N to 31 generate
    begin
      E(I) <= x;
  end generate;

SW_SyncRSHK : if(Synchronous) generate
  process(CLOCK, RESET)
  begin
    if RESET = '1' then
      EOF_OUT     <= '0';
      EOL_OUT     <= '0';
      DVALID_OUT  <= '0';
    elsif rising_edge(CLOCK) then
      EOF_OUT  <= EOF_IN;
      EOL_OUT  <= EOL_IN;
      DVALID_OUT <= DVALID_IN;
    end if;
  end process;

  process(CLOCK)
  begin
    case SEL_A is
      when "00"   => F <= E;--shift by 0
      when "01"   => F(31) <= x; F(30 downto 0) <= E(31 downto 1);--shift by 1
      when "10"   => F(31 downto 30) <= x&x; F(29 downto 0) <= E(31 downto 2);--shift by 2
      when "11"   => F(31 downto 29) <= x&x&x; F(28 downto 0) <= E(31 downto 3);--shift by 3
      when others => F <= E;
    end case;
  end process;
end generate;

SW_AsyncRSHK : if(NOT Synchronous) generate

  EOF_OUT <= EOF_IN;
  EOL_OUT <= EOL_IN;
  DVALID_OUT <= DVALID_IN;

  process(SEL_A, E)
  begin
    case SEL_A is
      when "00"   => F <= E;--shift by 0
      when "01"   => F(31) <= x; F(30 downto 0) <= E(31 downto 1);--shift by 1
      when "10"   => F(31 downto 30) <= x&x; F(29 downto 0) <= E(31 downto 2);--shift by 2
      when "11"   => F(31 downto 29) <= x&x&x; F(28 downto 0) <= E(31 downto 3);--shift by 3
      when others => F <= E;
    end case;
  end process;
end generate;

  process(C,SEL_B)
  begin
    case SEL_B is
      when "00" => G <= F;--shift by 0 more
      when "01" => G(31 downto 28) <= x&x&x&x; G(27 downto 0) <= F(31 downto 4); --shift by 4 more
      when "10" => G(31 downto 24) <= x&x&x&x&x&x&x&x; G(23 downto 0) <= F(31 downto 8);--shift by 8 more
      when "11" => G(31 downto 20) <= x&x&x&x&x&x&x&x&x&x&x&x; G(19 downto 0) <= F(31 downto 12);--shift by 12 more
      when others => G <= F;
    end case;
  end process;

  process(D,SEL_C)
  begin
    case SEL_C is
      when '0' => H <= G;--shift by 0 more
      when '1' => H(31 downto 16) <= x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x; H(15 downto 0) <= G(31 downto 16); --shift by 16 more
      when others => H <= G;
    end case;
  end process;

  DATA_OUT(N - 1 downto 0) <= H(N - 1 downto 0);

end generate;

BigWord : if (N >= 32) generate

BW_SyncRSHK : if(Synchronous) generate
  process(CLOCK, RESET)
  begin
    if RESET = '1' then
      EOF_OUT     <= '0';
      EOL_OUT     <= '0';
      DVALID_OUT  <= '0';
    elsif rising_edge(CLOCK) then
      EOF_OUT  <= EOF_IN;
      EOL_OUT  <= EOL_IN;
      DVALID_OUT <= DVALID_IN;
    end if;
  end process;

  process(CLOCK)
  begin
    case SEL_A is
      when "00" => C <= DATA_IN;--shift by 0
      when "01" => C(N - 1) <= x; C(N - 2 downto 0) <= DATA_IN(N - 1 downto 1);--shift by 1
      when "10" => C(N - 1 downto N - 2) <= x&x; C(N - 3 downto 0) <= DATA_IN(N - 1 downto 2);
      when "11" => C(N - 1 downto N - 3) <= x&x&x; C(N - 4 downto 0) <= DATA_IN(N - 1 downto 3);--shift by 3
      when others => C <= DATA_IN;
    end case;
  end process;
end generate;

BW_AsyncRSHK : if(NOT Synchronous) generate

  EOF_OUT <= EOF_IN;
  EOL_OUT <= EOL_IN;
  DVALID_OUT <= DVALID_IN;

  process(SEL_A, DATA_IN)
  begin
    case SEL_A is 
      when "00" => C <= DATA_IN;--shift by 0
      when "01" => C(N - 1) <= x; C(N - 2 downto 0) <= DATA_IN(N - 1 downto 1);--shift by 1
      when "10" => C(N - 1 downto N - 2) <= x&x; C(N - 3 downto 0) <= DATA_IN(N - 1 downto 2);
      when "11" => C(N - 1 downto N - 3) <= x&x&x; C(N - 4 downto 0) <= DATA_IN(N - 1 downto 3);--shift by 3
      when others => C <= DATA_IN;
    end case;
  end process;
end generate;

  process(C,SEL_B)
  begin
    case SEL_B is 
      when "00" => D <= C;--shift by 0 more
      when "01" => D(N - 1 downto N - 4) <= x&x&x&x; D(N - 5 downto 0) <= C(N - 1 downto 4); --shift by 4 more
      when "10" => D(N - 1 downto N - 8) <= x&x&x&x&x&x&x&x; D(N - 9 downto 0) <= C(N - 1 downto 8);--shift by 8 more
      when "11" => D(N - 1 downto N - 12) <= x&x&x&x&x&x&x&x&x&x&x&x; D(N - 13 downto 0) <= C(N - 1 downto 12);--shift by 12 more
      when others => D <= C;
    end case;
  end process;

  process(D,SEL_C)
  begin
    case SEL_C is 
      when '0' => DATA_OUT <= D;--shift by 0 more
      when '1' => DATA_OUT(N - 1 downto N - 16) <= x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x; DATA_OUT(N - 17 downto 0) <= D(N - 1 downto 16); --shift by 16 more
      when others => DATA_OUT <= D;
    end case;
  end process;

end generate;

end Behavioral;
-----------------------------------------------------------------

--Function LSHK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity LSHK is
  generic (
    Synchronous  : boolean := True;
    FillWithOnes : boolean := False;
    N            : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end LSHK;

architecture Behavioral of LSHK is

signal SEL_A      : std_logic_vector(1 downto 0);
signal SEL_B      : std_logic_vector(1 downto 0);
signal SEL_C      : std_logic;
signal C,D        : std_logic_vector(N - 1 downto 0);
signal x          : std_logic;
signal OVERFLOW_A : std_logic_vector(31 downto 0);
signal OVERFLOW_B : std_logic_vector(31 downto 0);
signal OVERFLOW_C : std_logic_vector(31 downto 0);
signal TEMP_A     : std_logic_vector(N - 1 downto 0);
signal TEMP_B     : std_logic_vector(N - 1 downto 0);
signal DATA_INT   : std_logic_vector(N - 1 downto 0);

begin

  SEL_A <= K_IN(1 downto 0);
  SEL_B <= K_IN(3 downto 2);
  SEL_C <= K_IN(4);

  x <= '1' when FillWithOnes = True else '0';

SyncLSHK : if (Synchronous) generate
  process(CLOCK, RESET)
  begin
    if RESET = '1' then
      EOF_OUT    <= '0';
      EOL_OUT    <= '0';
      DVALID_OUT <= '0';
      DATA_OUT   <= (others=>'0');
    elsif rising_edge(CLOCK) then
      EOF_OUT    <= EOF_IN;
      EOL_OUT    <= EOL_IN;
      DVALID_OUT <= DVALID_IN;
      if DVALID_IN='1' then
        DATA_OUT <= DATA_INT;
      end if;
    end if;
  end process;
end generate;

AsyncLSHK : if (NOT Synchronous) generate
  EOF_OUT    <= EOF_IN;
  EOL_OUT    <= EOL_IN;
  DVALID_OUT <= DVALID_IN;
  DATA_OUT   <= DATA_INT;
end generate;

  process(SEL_A, DATA_IN)
  begin
    case SEL_A is
      when "00" => C                       <= DATA_IN;                  --shift by 0
                   OVERFLOW_A              <= (others=>'0');
      when "01" => C(0)                    <= x;                        --shift by 1
                   C(N - 1 downto 1)       <= DATA_IN(N - 2 downto 0);
                   OVERFLOW_A(0)           <= DATA_IN(N - 1);
                   OVERFLOW_A(31 downto 1) <= (others=>'0');
      when "10" => C(1 downto 0)           <= x&x;                      --shift by 2
                   C(N - 1 downto 2)       <= DATA_IN(N - 3 downto 0);
                   OVERFLOW_A(1 downto 0)  <= DATA_IN(N - 1 downto N - 2);
                   OVERFLOW_A(31 downto 2) <= (others=>'0');
      when "11" => C(2 downto 0)           <= x&x&x;                    --shift by 3
                   C(N - 1 downto 3)       <= DATA_IN(N - 4 downto 0);
                   OVERFLOW_A(2 downto 0)  <= DATA_IN(N - 1 downto N - 3);
                   OVERFLOW_A(31 downto 3) <= (others=>'0');
      when others => C <= DATA_IN;
    end case;
  end process;

iLSH8 : if (N <= 8) generate

  process(C,SEL_B)
  begin
    case SEL_B is
      when "00" => D                       <= C;                           --shift by 0 more
                   OVERFLOW_B              <= OVERFLOW_A;
      when "01" => D(3 downto 0)           <= x&x&x&x;                     --shift by 4 more
                   D(N - 1 downto 4)       <= C(N - 5 downto 0);
                   OVERFLOW_B(3 downto 0)  <= C(N - 1 downto N - 4);
                   OVERFLOW_B(31 downto 4) <= OVERFLOW_A(27 downto 0);
      when "10" => D                       <= (others=>x);                 --shift by 8 more
                   OVERFLOW_B              <= (others=>'0');
      when "11" => D                       <= (others=>x);                 --shift by 12 more
                   OVERFLOW_B              <= (others=>'0');
      when others => D <= C; OVERFLOW_B <= OVERFLOW_A;
    end case;
  end process;

  TEMP_A   <= D;
  TEMP_B   <= (others=>'1');
  DATA_INT <= TEMP_A when OVERFLOW_B="00000000000000000000000000000000" else TEMP_B;

end generate;

iLSH12 : if (N <= 12 and N > 8) generate

  process(C,SEL_B)
  begin
    case SEL_B is
      when "00" => D                        <= C;                           --shift by 0 more
                   OVERFLOW_B               <= OVERFLOW_A;
      when "01" => D(3 downto 0)            <= x&x&x&x;                     --shift by 4 more
                   D(N - 1 downto 4)        <= C(N - 5 downto 0);
                   OVERFLOW_B(3 downto 0)   <= C(N - 1 downto N - 4);
                   OVERFLOW_B(31 downto 4)  <= OVERFLOW_A(27 downto 0);
      when "10" => D(7 downto 0)            <= x&x&x&x&x&x&x&x;             --shift by 8 more
                   D(N - 1 downto 8)        <= C(N - 9 downto 0);
                   OVERFLOW_B(7 downto 0)   <= C(N - 1 downto N - 8);
                   OVERFLOW_B(31 downto 8)  <= OVERFLOW_A(23 downto 0);
      when "11" => D                        <= (others=>x);                 --shift by 12 more
                   OVERFLOW_B               <= (others=>'0');
      when others => D <= C; OVERFLOW_B <= OVERFLOW_A;
    end case;
  end process;

  TEMP_A   <= D;
  TEMP_B   <= (others=>'1');
  DATA_INT <= TEMP_A when OVERFLOW_B="00000000000000000000000000000000" else TEMP_B;

end generate;

iLSH16 : if (N <= 16 and N > 12) generate

  process(C,SEL_B)
  begin
    case SEL_B is
      when "00" => D                        <= C;                           --shift by 0 more
                   OVERFLOW_B               <= OVERFLOW_A;
      when "01" => D(3 downto 0)            <= x&x&x&x;                     --shift by 4 more
                   D(N - 1 downto 4)        <= C(N - 5 downto 0);
                   OVERFLOW_B(3 downto 0)   <= C(N - 1 downto N - 4);
                   OVERFLOW_B(31 downto 4)  <= OVERFLOW_A(27 downto 0);
      when "10" => D(7 downto 0)            <= x&x&x&x&x&x&x&x;             --shift by 8 more
                   D(N - 1 downto 8)        <= C(N - 9 downto 0);
                   OVERFLOW_B(7 downto 0)   <= C(N - 1 downto N - 8);
                   OVERFLOW_B(31 downto 8)  <= OVERFLOW_A(23 downto 0);
      when "11" => D(11 downto 0)           <= x&x&x&x&x&x&x&x&x&x&x&x;    --shift by 12 more
                   D(N - 1 downto 12)       <= C(N - 13 downto 0);
                   OVERFLOW_B(11 downto 0)  <= C(N - 1 downto N - 12);
                   OVERFLOW_B(31 downto 12) <= OVERFLOW_A(19 downto 0);
      when others => D <= C; OVERFLOW_B <= OVERFLOW_A;
    end case;
  end process;

  process(D,SEL_C)
  begin
    case SEL_C is
      when '0' => TEMP_A                   <= D;                               --shift by 0 more
                  OVERFLOW_C               <= OVERFLOW_B;
      when '1' => TEMP_A                   <= (others=>x);                     --shift by 16 more
                  OVERFLOW_C               <= (others=>'0');
      when others => TEMP_A <= D; OVERFLOW_C <= OVERFLOW_B;
    end case;
  end process;

  TEMP_B   <= (others=>'1');
  DATA_INT <= TEMP_A when OVERFLOW_C="00000000000000000000000000000000" else TEMP_B;

end generate;

iLSH32 : if (N > 16) generate

  process(C,SEL_B)
  begin
    case SEL_B is
      when "00" => D                        <= C;                           --shift by 0 more
                   OVERFLOW_B               <= OVERFLOW_A;
      when "01" => D(3 downto 0)            <= x&x&x&x;                     --shift by 4 more
                   D(N - 1 downto 4)        <= C(N - 5 downto 0);
                   OVERFLOW_B(3 downto 0)   <= C(N - 1 downto N - 4);
                   OVERFLOW_B(31 downto 4)  <= OVERFLOW_A(27 downto 0);
      when "10" => D(7 downto 0)            <= x&x&x&x&x&x&x&x;             --shift by 8 more
                   D(N - 1 downto 8)        <= C(N - 9 downto 0);
                   OVERFLOW_B(7 downto 0)   <= C(N - 1 downto N - 8);
                   OVERFLOW_B(31 downto 8)  <= OVERFLOW_A(23 downto 0);
      when "11" => D(11 downto 0)           <= x&x&x&x&x&x&x&x&x&x&x&x;    --shift by 12 more
                   D(N - 1 downto 12)       <= C(N - 13 downto 0);
                   OVERFLOW_B(11 downto 0)  <= C(N - 1 downto N - 12);
                   OVERFLOW_B(31 downto 12) <= OVERFLOW_A(19 downto 0);
      when others => D <= C; OVERFLOW_B <= OVERFLOW_A;
    end case;
  end process;

  process(D,SEL_C)
  begin
    case SEL_C is
      when '0' => TEMP_A                   <= D;                               --shift by 0 more
                  OVERFLOW_C               <= OVERFLOW_B;
      when '1' => TEMP_A(15 downto 0)      <= x&x&x&x&x&x&x&x&x&x&x&x&x&x&x&x; --shift by 16 more
                  TEMP_A(N - 1 downto 16)  <= D(N - 17 downto 0);
                  OVERFLOW_C(15 downto 0)  <= D(N - 1 downto N - 16);
                  OVERFLOW_C(31 downto 16) <= OVERFLOW_B(15 downto 0);
      when others => TEMP_A <= D; OVERFLOW_C <= OVERFLOW_B;
    end case;
  end process;

  TEMP_B   <= (others=>'1');
  DATA_INT <= TEMP_A when OVERFLOW_C="00000000000000000000000000000000" else TEMP_B;

end generate;

end Behavioral;
-----------------------------------------------------------------

--Function ORK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ORK is
  generic (
    Synchronous : boolean := True;
    N           : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end ORK;

architecture Behavioral of ORK is

signal DATA_TEMP : std_logic_vector(N - 1 downto 0);

begin

  DATA_TEMP <= DATA_IN OR K_IN;

SyncORK : if(Synchronous) generate
  process(RESET, CLOCK)
  begin
    if RESET = '1' then
      DATA_OUT   <= (others=>'0');
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT <= DVALID_IN;
      EOL_OUT    <= EOL_IN;
      EOF_OUT    <= EOF_IN;
      DATA_OUT   <= DATA_TEMP;
    end if;
  end process;
end generate;

ASyncORK : if(NOT Synchronous) generate
  DVALID_OUT <= DVALID_IN;
  EOL_OUT    <= EOL_IN;
  EOF_OUT    <= EOF_IN;
  DATA_OUT   <= DATA_TEMP;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function XORK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity XORK is
  generic (
    Synchronous : boolean := True;
    N           : Integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end XORK;

architecture Behavioral of XORK is

signal DATA_TEMP : std_logic_vector(N - 1 downto 0);

begin

  DATA_TEMP <= DATA_IN XOR K_IN;

SyncXORK : if(Synchronous) generate
  process(RESET, CLOCK)
  begin
    if RESET = '1' then
      DATA_OUT   <= (others=>'0');
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT  <= DVALID_IN;
      EOL_OUT     <= EOL_IN;
      EOF_OUT     <= EOF_IN;
      DATA_OUT    <= DATA_TEMP;
    end if;
  end process;
end generate;

ASyncXORK : if(NOT Synchronous) generate
  DVALID_OUT <= DVALID_IN;
  EOL_OUT    <= EOL_IN;
  EOF_OUT    <= EOF_IN;
  DATA_OUT   <= DATA_TEMP;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function FillK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FILLK is
  generic (
    N : integer := 32
  );
  port (
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end FILLK;

architecture Behavioral of FILLK is

begin

  process(RESET, CLOCK)
  begin
    if RESET = '1' then
      DATA_OUT   <= (others=>'0');
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT <= DVALID_IN;
      EOL_OUT    <= EOL_IN;
      EOF_OUT    <= EOF_IN;
      DATA_OUT   <= K_IN;
    end if;
  end process;

end Behavioral;

-----------------------------------------------------------------

--Function FILLRAMP
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FILLRAMP  is
  generic (
    N : integer := 32
  );
  port (
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end FILLRAMP;

architecture Behavioral of FILLRAMP is

signal RAMP_VALUE : std_logic_vector(N - 1 downto 0);

begin

  process(RESET, CLOCK)
  begin
    if RESET = '1' then
      RAMP_VALUE <= (others=>'0');
      DATA_OUT   <= (others=>'0');
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT <= DVALID_IN;
      EOL_OUT    <= EOL_IN;
      EOF_OUT    <= EOF_IN;
      DATA_OUT   <= RAMP_VALUE;
      if DVALID_IN = '1' then
        if ((RAMP_VALUE >= K_IN) or (EOL_IN = '1') or (EOF_IN = '1')) then
           RAMP_VALUE   <= (others=>'0');
        else
          RAMP_VALUE <= RAMP_VALUE + '1';
        end if;
      end if;
    end if;
  end process;

end Behavioral;
-----------------------------------------------------------------

--Function SUBK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SUBK is
  generic (
    Synchronous : boolean := True;
    StopAtZero  : boolean := True;
    N           : integer := 32
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end SUBK;

architecture Behavioral of SUBK is

signal DATA_TEMP : std_logic_vector(N - 1 downto 0);

begin

  DATA_TEMP <= DATA_IN - K_IN;

SyncSUBK : if(Synchronous) generate
  process(RESET, CLOCK)
  begin
    if RESET = '1' then
      DATA_OUT   <= (others=>'0');
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_OUT  <= DVALID_IN;
      EOL_OUT     <= EOL_IN;
      EOF_OUT     <= EOF_IN;
      if StopAtZero = True then
        if DATA_IN >= K_IN then
          DATA_OUT    <= DATA_TEMP;
        else
          DATA_OUT    <= (others=>'0');
        end if;
      else
        DATA_OUT <= DATA_TEMP;
      end if;
    end if;
  end process;
end generate;

ASyncSUBK : if(NOT Synchronous) generate
  DVALID_OUT  <= DVALID_IN;
  EOL_OUT     <= EOL_IN;
  EOF_OUT     <= EOF_IN;
  process(DATA_TEMP, K_IN, DATA_IN)
  begin
    if StopAtZero = True then
      if DATA_IN >= K_IN then
        DATA_OUT    <= DATA_TEMP;
      else
        DATA_OUT    <= (others=>'0');
      end if;
    else
      DATA_OUT <= DATA_TEMP;
    end if;
  end process;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function MPYK
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity MPYK is
  generic (
    Synchronous : boolean := False;
    N           : integer := 18
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end MPYK;

architecture Behavioral of MPYK is

signal DATA_A       : std_logic_vector(N - 1 downto 0);
signal DATA_B       : std_logic_vector(N downto 0);
signal DATA_C       : std_logic_vector(N downto 0);
signal DATA_D       : std_logic_vector(N - 1 downto 0);
signal EOL_A        : std_logic;
signal EOF_A        : std_logic;
signal DVALID_A     : std_logic;
signal DATA_A_OUT   : signed((N * 2) downto 0);
signal DATA_B_OUT   : std_logic_vector((N * 2) downto 0);
signal DATA_C_OUT   : std_logic_vector((N * 2) downto 0);
signal DATA_D_OUT   : std_logic_vector((N * 2) downto 0);
signal DATA_E_OUT   : std_logic_vector((N * 2) downto 0);
signal DATA_F_OUT   : std_logic_vector(47 downto 0);
signal DATA_G_OUT   : std_logic_vector(63 downto 0);
signal DVALID_DELAY : std_logic_vector(4 downto 0);
signal EOL_DELAY    : std_logic_vector(4 downto 0);
signal EOF_DELAY    : std_logic_vector(4 downto 0);

component multi24x24
  port (
    clk : in  std_logic;
    a   : in  std_logic_vector(23 downto 0);
    b   : in  std_logic_vector(23 downto 0);
    q   : out std_logic_vector(47 downto 0)
  );
end component;

component multi32x32
  port (
    clk : in  std_logic;
    a   : in  std_logic_vector(31 downto 0);
    b   : in  std_logic_vector(31 downto 0);
    q   : out std_logic_vector(63 downto 0)
  );
end component;

begin

SyncMult18x18 : if (Synchronous and N <= 17) generate

  DATA_B <= '0' & DATA_A;
  DATA_C <= '0' & DATA_D;

  DATA_A_OUT <= signed(DATA_B) * signed(DATA_C);

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      DATA_A   <= DATA_IN;
      EOF_A    <= EOF_IN;
      EOL_A    <= EOL_IN;
      DVALID_A <= DVALID_IN;
      DATA_D   <= K_IN;
    end if;
  end process;

  DATA_D_OUT((N * 2) downto N + 1) <= (others=>'0');
  DATA_D_OUT(N) <= '1';
  DATA_D_OUT(N - 1 downto 0) <= (others=>'0');

  DATA_E_OUT((N * 2) downto N) <= (others=>'0');
  DATA_E_OUT(N - 1 downto 0) <= (others=>'1');

  DATA_B_OUT <= std_logic_vector(unsigned(DATA_A_OUT));
  DATA_C_OUT <= DATA_B_OUT when DATA_B_OUT < DATA_D_OUT else DATA_E_OUT;

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      DATA_OUT   <= DATA_C_OUT(N - 1 downto 0);
      EOF_OUT    <= EOF_A;
      EOL_OUT    <= EOL_A;
      DVALID_OUT <= DVALID_A;
    end if;
  end process;
end generate;

SyncMult24x24 : if (Synchronous and N <=23 and N > 17) generate

  DATA_B <= '0' & DATA_IN;
  DATA_C <= '0' & K_IN;

  i24x24multi : multi24x24
    port map (
      clk => CLOCK,
      a   => DATA_C,
      b   => DATA_B,
      q   => DATA_F_OUT );

  DATA_D_OUT((N * 2) - 1 downto N + 1) <= (others=>'0');
  DATA_D_OUT(N) <= '1';
  DATA_D_OUT(N - 1 downto 0) <= (others=>'0');

  DATA_E_OUT((N * 2) - 1 downto N) <= (others=>'0');
  DATA_E_OUT(N - 1 downto 0) <= (others=>'1');

  DATA_B_OUT <= DATA_F_OUT((N * 2) - 1 downto 0);
  DATA_C_OUT <= DATA_B_OUT when DATA_B_OUT < DATA_D_OUT else DATA_E_OUT;

  DATA_OUT   <= DATA_C_OUT(N - 1 downto 0);

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      DVALID_DELAY <= DVALID_IN & DVALID_DELAY(4 downto 1);
      EOF_DELAY    <= EOF_IN & EOF_DELAY(4 downto 1);
      EOL_DELAY    <= EOL_IN & EOL_DELAY(4 downto 1);
      DVALID_OUT   <= DVALID_DELAY(0);
      EOL_OUT      <= EOL_DELAY(0);
      EOF_OUT      <= EOF_DELAY(0);
    end if;
  end process;
end generate;

SyncMult32x32 : if (Synchronous and N <=31 and N > 23) generate

  DATA_B <= '0' & DATA_IN;
  DATA_C <= '0' & K_IN;

  i32x32multi : multi32x32
    port map (
      clk => CLOCK,
      a   => DATA_C,
      b   => DATA_B,
      q   => DATA_G_OUT );

  DATA_D_OUT((N * 2) - 1 downto N + 1) <= (others=>'0');
  DATA_D_OUT(N) <= '1';
  DATA_D_OUT(N - 1 downto 0) <= (others=>'0');

  DATA_E_OUT((N * 2) - 1 downto N) <= (others=>'0');
  DATA_E_OUT(N - 1 downto 0) <= (others=>'1');

  DATA_B_OUT <= DATA_G_OUT((N * 2) - 1 downto 0);
  DATA_C_OUT <= DATA_B_OUT when DATA_B_OUT < DATA_D_OUT else DATA_E_OUT;

  DATA_OUT   <= DATA_C_OUT(N - 1 downto 0);

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      DVALID_DELAY <= DVALID_IN & DVALID_DELAY(4 downto 1);
      EOF_DELAY    <= EOF_IN & EOF_DELAY(4 downto 1);
      EOL_DELAY    <= EOL_IN & EOL_DELAY(4 downto 1);
      DVALID_OUT   <= DVALID_DELAY(0);
      EOL_OUT      <= EOL_DELAY(0);
      EOF_OUT      <= EOF_DELAY(0);
    end if;
  end process;
end generate;

AsyncMult : if (NOT Synchronous) generate

  DATA_B <= '0' & DATA_A;
  DATA_C <= '0' & K_IN;

  DATA_A_OUT <= signed(DATA_B) * signed(DATA_C);
  DATA_A <= DATA_IN;
  EOF_A <= EOF_IN;
  EOL_A <= EOL_IN;
  DVALID_A <= DVALID_IN;

  DATA_D_OUT((N * 2) - 1 downto N + 1) <= (others=>'0');
  DATA_D_OUT(N) <= '1';
  DATA_D_OUT(N - 1 downto 0) <= (others=>'0');

  DATA_E_OUT((N * 2) - 1 downto N) <= (others=>'0');
  DATA_E_OUT(N - 1 downto 0) <= (others=>'1');

  DATA_B_OUT <= std_logic_vector(unsigned(DATA_A_OUT));
  DATA_C_OUT <= DATA_B_OUT when DATA_B_OUT < DATA_D_OUT else DATA_E_OUT;

  DATA_OUT <= DATA_C_OUT(N - 1 downto 0);

  EOF_OUT <= EOF_A;
  EOL_OUT <= EOL_A;
  DVALID_OUT <= DVALID_A;
end generate;

end Behavioral;
-----------------------------------------------------------------

--Function SQUARE
library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SQUARE is
  generic (
    Synchronous : boolean := False;
    N           : integer := 18
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic
  );
end SQUARE;

architecture Behavioral of SQUARE is

component MPYK is
  generic (
    Synchronous : boolean := True;
    N           : integer := 18
  );
  port (
    DATA_IN    : in  std_logic_vector(N - 1 downto 0);
    DATA_OUT   : out std_logic_vector(N - 1 downto 0);
    DVALID_IN  : in  std_logic;
    DVALID_OUT : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_IN       : in  std_logic_vector(N - 1 downto 0)
  );
end component;

begin

squ : MPYK
  generic map (
    Synchronous => Synchronous,
    N           => N )
  port map (
    DATA_IN    => DATA_IN,
    DATA_OUT   => DATA_OUT,
    DVALID_IN  => DVALID_IN,
    DVALID_OUT => DVALID_OUT,
    CLOCK      => CLOCK,
    RESET      => RESET,
    EOL_IN     => EOL_IN,
    EOL_OUT    => EOL_OUT,
    EOF_IN     => EOF_IN,
    EOF_OUT    => EOF_OUT,
    K_IN       => DATA_IN );

end Behavioral;

