-- ==============================================================
-- FILE : CONVOLVE5x5.VHD
-- ==============================================================
--
-- This file is part of the Image Processing IP for HERON- FPGA
-- modules.
--
-- This file may be modified by advanced users.
--
-- ==============================================================
--
--  Date        : 01/12/2003
--  Author      : J. Maddocks
--  Description : 5x5 Convolution
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     J. Maddocks    01-12-03    First Written
--
-- ==============================================================


-----------------------------------------------------------------
--
--  Pixels referenced throughout as:
--
--  A1 B1 C1 D1 E1
--  A2 B2 C2 D2 E2
--  A3 B3 C3 D3 E3
--  A4 B4 C4 D4 E4
--  A5 B5 C5 D5 E5
--
-----------------------------------------------------------------

library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity convolve5x5 is
  generic(
    N              : integer := 8;
    LINE_LENGTH    : integer := 384;
    RAM_ADDR_WIDTH : integer := 5;
    KERNEL         : string  := "GENERAL"
  );
  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;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    K_A1       : in  std_logic_vector(17 downto 0);
    K_A2       : in  std_logic_vector(17 downto 0);
    K_A3       : in  std_logic_vector(17 downto 0);
    K_A4       : in  std_logic_vector(17 downto 0);
    K_A5       : in  std_logic_vector(17 downto 0);
    K_B1       : in  std_logic_vector(17 downto 0);
    K_B2       : in  std_logic_vector(17 downto 0);
    K_B3       : in  std_logic_vector(17 downto 0);
    K_B4       : in  std_logic_vector(17 downto 0);
    K_B5       : in  std_logic_vector(17 downto 0);
    K_C1       : in  std_logic_vector(17 downto 0);
    K_C2       : in  std_logic_vector(17 downto 0);
    K_C3       : in  std_logic_vector(17 downto 0);
    K_C4       : in  std_logic_vector(17 downto 0);
    K_C5       : in  std_logic_vector(17 downto 0);
    K_D1       : in  std_logic_vector(17 downto 0);
    K_D2       : in  std_logic_vector(17 downto 0);
    K_D3       : in  std_logic_vector(17 downto 0);
    K_D4       : in  std_logic_vector(17 downto 0);
    K_D5       : in  std_logic_vector(17 downto 0);
    K_E1       : in  std_logic_vector(17 downto 0);
    K_E2       : in  std_logic_vector(17 downto 0);
    K_E3       : in  std_logic_vector(17 downto 0);
    K_E4       : in  std_logic_vector(17 downto 0);
    K_E5       : in  std_logic_vector(17 downto 0);
    SHIFT      : in  std_logic_vector(3 downto 0);
    CLOCK      : in  std_logic;
    RESET      : in  std_logic
  );
end convolve5x5;

architecture Behavioral of convolve5x5 is

  component dataSupply5x5 is
    generic (
      N              : integer := 8;
      LINE_LENGTH    : integer := 32;
      RAM_ADDR_WIDTH : integer := 5
    );
    port (
      DATA_IN    : in  std_logic_vector(N - 1 downto 0);
      DATA_A1    : out std_logic_vector(N - 1 downto 0);
      DATA_A2    : out std_logic_vector(N - 1 downto 0);
      DATA_A3    : out std_logic_vector(N - 1 downto 0);
      DATA_A4    : out std_logic_vector(N - 1 downto 0);
      DATA_A5    : out std_logic_vector(N - 1 downto 0);
      DATA_B1    : out std_logic_vector(N - 1 downto 0);
      DATA_B2    : out std_logic_vector(N - 1 downto 0);
      DATA_B3    : out std_logic_vector(N - 1 downto 0);
      DATA_B4    : out std_logic_vector(N - 1 downto 0);
      DATA_B5    : out std_logic_vector(N - 1 downto 0);
      DATA_C1    : out std_logic_vector(N - 1 downto 0);
      DATA_C2    : out std_logic_vector(N - 1 downto 0);
      DATA_C3    : out std_logic_vector(N - 1 downto 0);
      DATA_C4    : out std_logic_vector(N - 1 downto 0);
      DATA_C5    : out std_logic_vector(N - 1 downto 0);
      DATA_D1    : out std_logic_vector(N - 1 downto 0);
      DATA_D2    : out std_logic_vector(N - 1 downto 0);
      DATA_D3    : out std_logic_vector(N - 1 downto 0);
      DATA_D4    : out std_logic_vector(N - 1 downto 0);
      DATA_D5    : out std_logic_vector(N - 1 downto 0);
      DATA_E1    : out std_logic_vector(N - 1 downto 0);
      DATA_E2    : out std_logic_vector(N - 1 downto 0);
      DATA_E3    : out std_logic_vector(N - 1 downto 0);
      DATA_E4    : out std_logic_vector(N - 1 downto 0);
      DATA_E5    : out std_logic_vector(N - 1 downto 0);
      DVALID_IN  : in  std_logic;
      DVALID_OUT : out std_logic;
      EOL_IN     : in  std_logic;
      EOL_OUT    : out std_logic;
      EOF_IN     : in  std_logic;
      EOF_OUT    : out std_logic;
      CLOCK      : in  std_logic;
      RESET      : in  std_logic
    );
  end component;

  component dataMaths5x5 is
    generic(
      N      : integer := 8;
      Kernel : string  := "GENERAL"
    );
    port (
      DATA_A1    : in  std_logic_vector(N - 1 downto 0);
      DATA_B1    : in  std_logic_vector(N - 1 downto 0);
      DATA_C1    : in  std_logic_vector(N - 1 downto 0);
      DATA_D1    : in  std_logic_vector(N - 1 downto 0);
      DATA_E1    : in  std_logic_vector(N - 1 downto 0);
      DATA_A2    : in  std_logic_vector(N - 1 downto 0);
      DATA_B2    : in  std_logic_vector(N - 1 downto 0);
      DATA_C2    : in  std_logic_vector(N - 1 downto 0);
      DATA_D2    : in  std_logic_vector(N - 1 downto 0);
      DATA_E2    : in  std_logic_vector(N - 1 downto 0);
      DATA_A3    : in  std_logic_vector(N - 1 downto 0);
      DATA_B3    : in  std_logic_vector(N - 1 downto 0);
      DATA_C3    : in  std_logic_vector(N - 1 downto 0);
      DATA_D3    : in  std_logic_vector(N - 1 downto 0);
      DATA_E3    : in  std_logic_vector(N - 1 downto 0);
      DATA_A4    : in  std_logic_vector(N - 1 downto 0);
      DATA_B4    : in  std_logic_vector(N - 1 downto 0);
      DATA_C4    : in  std_logic_vector(N - 1 downto 0);
      DATA_D4    : in  std_logic_vector(N - 1 downto 0);
      DATA_E4    : in  std_logic_vector(N - 1 downto 0);
      DATA_A5    : in  std_logic_vector(N - 1 downto 0);
      DATA_B5    : in  std_logic_vector(N - 1 downto 0);
      DATA_C5    : in  std_logic_vector(N - 1 downto 0);
      DATA_D5    : in  std_logic_vector(N - 1 downto 0);
      DATA_E5    : in  std_logic_vector(N - 1 downto 0);
      K_A1       : in  std_logic_vector(17 downto 0);
      K_A2       : in  std_logic_vector(17 downto 0);
      K_A3       : in  std_logic_vector(17 downto 0);
      K_A4       : in  std_logic_vector(17 downto 0);
      K_A5       : in  std_logic_vector(17 downto 0);
      K_B1       : in  std_logic_vector(17 downto 0);
      K_B2       : in  std_logic_vector(17 downto 0);
      K_B3       : in  std_logic_vector(17 downto 0);
      K_B4       : in  std_logic_vector(17 downto 0);
      K_B5       : in  std_logic_vector(17 downto 0);
      K_C1       : in  std_logic_vector(17 downto 0);
      K_C2       : in  std_logic_vector(17 downto 0);
      K_C3       : in  std_logic_vector(17 downto 0);
      K_C4       : in  std_logic_vector(17 downto 0);
      K_C5       : in  std_logic_vector(17 downto 0);
      K_D1       : in  std_logic_vector(17 downto 0);
      K_D2       : in  std_logic_vector(17 downto 0);
      K_D3       : in  std_logic_vector(17 downto 0);
      K_D4       : in  std_logic_vector(17 downto 0);
      K_D5       : in  std_logic_vector(17 downto 0);
      K_E1       : in  std_logic_vector(17 downto 0);
      K_E2       : in  std_logic_vector(17 downto 0);
      K_E3       : in  std_logic_vector(17 downto 0);
      K_E4       : in  std_logic_vector(17 downto 0);
      K_E5       : in  std_logic_vector(17 downto 0);
      DATA_OUT   : out std_logic_vector(20 downto 0);
      DVALID_IN  : in  std_logic;
      DVALID_OUT : out std_logic;
      EOL_IN     : in  std_logic;
      EOL_OUT    : out std_logic;
      EOF_IN     : in  std_logic;
      EOF_OUT    : out std_logic;
      CLOCK      : in  std_logic;
      RESET      : in  std_logic
    );
  end component;

  component framePad5x5 is
    generic(
      N           : integer := 32;
      LINE_LENGTH : 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;
      EOL_IN     : in  std_logic;
      EOL_OUT    : out std_logic;
      EOF_IN     : in  std_logic;
      EOF_OUT    : out std_logic;
      CLOCK      : in  std_logic;
      RESET      : in  std_logic
    );
  end component;

  signal DATA_A1       : std_logic_vector(N - 1 downto 0);
  signal DATA_A2       : std_logic_vector(N - 1 downto 0);
  signal DATA_A3       : std_logic_vector(N - 1 downto 0);
  signal DATA_A4       : std_logic_vector(N - 1 downto 0);
  signal DATA_A5       : std_logic_vector(N - 1 downto 0);
  signal DATA_B1       : std_logic_vector(N - 1 downto 0);
  signal DATA_B2       : std_logic_vector(N - 1 downto 0);
  signal DATA_B3       : std_logic_vector(N - 1 downto 0);
  signal DATA_B4       : std_logic_vector(N - 1 downto 0);
  signal DATA_B5       : std_logic_vector(N - 1 downto 0);
  signal DATA_C1       : std_logic_vector(N - 1 downto 0);
  signal DATA_C2       : std_logic_vector(N - 1 downto 0);
  signal DATA_C3       : std_logic_vector(N - 1 downto 0);
  signal DATA_C4       : std_logic_vector(N - 1 downto 0);
  signal DATA_C5       : std_logic_vector(N - 1 downto 0);
  signal DATA_D1       : std_logic_vector(N - 1 downto 0);
  signal DATA_D2       : std_logic_vector(N - 1 downto 0);
  signal DATA_D3       : std_logic_vector(N - 1 downto 0);
  signal DATA_D4       : std_logic_vector(N - 1 downto 0);
  signal DATA_D5       : std_logic_vector(N - 1 downto 0);
  signal DATA_E1       : std_logic_vector(N - 1 downto 0);
  signal DATA_E2       : std_logic_vector(N - 1 downto 0);
  signal DATA_E3       : std_logic_vector(N - 1 downto 0);
  signal DATA_E4       : std_logic_vector(N - 1 downto 0);
  signal DATA_E5       : std_logic_vector(N - 1 downto 0);
  signal EOL_A         : std_logic;
  signal EOF_A         : std_logic;
  signal DVALID_A      : std_logic;
  signal DATA_D        : std_logic_vector(20 downto 0);
  signal DATA_E        : std_logic_vector(20 downto 0);
  signal DATA_F        : std_logic_vector(20 downto 0);
  signal SHIFT_R_ONE   : std_logic_vector(20 downto 0);
  signal SHIFT_R_TWO   : std_logic_vector(20 downto 0);
  signal SHIFT_R_THREE : std_logic_vector(20 downto 0);
  signal SHIFT_R_FOUR  : std_logic_vector(20 downto 0);
  signal SHIFT_R_FIVE  : std_logic_vector(20 downto 0);
  signal SHIFT_R_SIX   : std_logic_vector(20 downto 0);
  signal SHIFT_R_SEVEN : std_logic_vector(20 downto 0);
  signal SHIFT_R_EIGHT : std_logic_vector(20 downto 0);
  signal SHIFT_L_ONE   : std_logic_vector(20 downto 0);
  signal SHIFT_L_TWO   : std_logic_vector(20 downto 0);
  signal SHIFT_L_THREE : std_logic_vector(20 downto 0);
  signal SHIFT_L_FOUR  : std_logic_vector(20 downto 0);
  signal SHIFT_L_FIVE  : std_logic_vector(20 downto 0);
  signal SHIFT_L_SIX   : std_logic_vector(20 downto 0);
  signal SHIFT_L_SEVEN : std_logic_vector(20 downto 0);
  signal EOL_D         : std_logic;
  signal EOF_D         : std_logic;
  signal DVALID_D      : std_logic;
  signal OVERFLOW      : std_logic;

begin

  idata5x5 : dataSupply5x5
    generic map (
      N              => N,
      LINE_LENGTH    => LINE_LENGTH,
      RAM_ADDR_WIDTH => RAM_ADDR_WIDTH )
    port map (
      DATA_IN    => DATA_IN,
      DATA_A1    => DATA_A1,
      DATA_B1    => DATA_B1,
      DATA_C1    => DATA_C1,
      DATA_D1    => DATA_D1,
      DATA_E1    => DATA_E1,
      DATA_A2    => DATA_A2,
      DATA_B2    => DATA_B2,
      DATA_C2    => DATA_C2,
      DATA_D2    => DATA_D2,
      DATA_E2    => DATA_E2,
      DATA_A3    => DATA_A3,
      DATA_B3    => DATA_B3,
      DATA_C3    => DATA_C3,
      DATA_D3    => DATA_D3,
      DATA_E3    => DATA_E3,
      DATA_A4    => DATA_A4,
      DATA_B4    => DATA_B4,
      DATA_C4    => DATA_C4,
      DATA_D4    => DATA_D4,
      DATA_E4    => DATA_E4,
      DATA_A5    => DATA_A5,
      DATA_B5    => DATA_B5,
      DATA_C5    => DATA_C5,
      DATA_D5    => DATA_D5,
      DATA_E5    => DATA_E5,
      DVALID_IN  => DVALID_IN,
      DVALID_OUT => DVALID_A,
      EOL_IN     => EOL_IN,
      EOL_OUT    => EOL_A,
      EOF_IN     => EOF_IN,
      EOF_OUT    => EOF_A,
      CLOCK      => CLOCK,
      RESET      => RESET );

  idataMaths5x5 : dataMaths5x5
    generic map (
      N      => N,
      Kernel => KERNEL )
    port map (
      DATA_A1    => DATA_A1,
      DATA_B1    => DATA_B1,
      DATA_C1    => DATA_C1,
      DATA_D1    => DATA_D1,
      DATA_E1    => DATA_E1,
      DATA_A2    => DATA_A2,
      DATA_B2    => DATA_B2,
      DATA_C2    => DATA_C2,
      DATA_D2    => DATA_D2,
      DATA_E2    => DATA_E2,
      DATA_A3    => DATA_A3,
      DATA_B3    => DATA_B3,
      DATA_C3    => DATA_C3,
      DATA_D3    => DATA_D3,
      DATA_E3    => DATA_E3,
      DATA_A4    => DATA_A4,
      DATA_B4    => DATA_B4,
      DATA_C4    => DATA_C4,
      DATA_D4    => DATA_D4,
      DATA_E4    => DATA_E4,
      DATA_A5    => DATA_A5,
      DATA_B5    => DATA_B5,
      DATA_C5    => DATA_C5,
      DATA_D5    => DATA_D5,
      DATA_E5    => DATA_E5,
      K_A1       => K_A1,
      K_A2       => K_A2,
      K_A3       => K_A3,
      K_A4       => K_A4,
      K_A5       => K_A5,
      K_B1       => K_B1,
      K_B2       => K_B2,
      K_B3       => K_B3,
      K_B4       => K_B4,
      K_B5       => K_B5,
      K_C1       => K_C1,
      K_C2       => K_C2,
      K_C3       => K_C3,
      K_C4       => K_C4,
      K_C5       => K_C5,
      K_D1       => K_D1,
      K_D2       => K_D2,
      K_D3       => K_D3,
      K_D4       => K_D4,
      K_D5       => K_D5,
      K_E1       => K_E1,
      K_E2       => K_E2,
      K_E3       => K_E3,
      K_E4       => K_E4,
      K_E5       => K_E5,
      DATA_OUT   => DATA_D,
      DVALID_IN  => DVALID_A,
      DVALID_OUT => DVALID_D,
      EOL_IN     => EOL_A,
      EOL_OUT    => EOL_D,
      EOF_IN     => EOF_A,
      EOF_OUT    => EOF_D,
      CLOCK      => CLOCK,
      RESET      => RESET );

  -- DATA_OUT is 8 bits
  OVERFLOW <= DATA_E(19) OR DATA_E(18) OR DATA_E(17) OR
              DATA_E(16) OR DATA_E(15) OR DATA_E(14) OR
              DATA_E(13) OR DATA_E(12) OR DATA_E(11) OR
              DATA_E(10) OR DATA_E(9)  OR DATA_E(8);

  DATA_F(0) <= ((NOT DATA_E(20)) AND (DATA_E(0) OR OVERFLOW));
  DATA_F(1) <= ((NOT DATA_E(20)) AND (DATA_E(1) OR OVERFLOW));
  DATA_F(2) <= ((NOT DATA_E(20)) AND (DATA_E(2) OR OVERFLOW));
  DATA_F(3) <= ((NOT DATA_E(20)) AND (DATA_E(3) OR OVERFLOW));
  DATA_F(4) <= ((NOT DATA_E(20)) AND (DATA_E(4) OR OVERFLOW));
  DATA_F(5) <= ((NOT DATA_E(20)) AND (DATA_E(5) OR OVERFLOW));
  DATA_F(6) <= ((NOT DATA_E(20)) AND (DATA_E(6) OR OVERFLOW));
  DATA_F(7) <= ((NOT DATA_E(20)) AND (DATA_E(7) OR OVERFLOW));

  SHIFT_L_ONE   <= DATA_D(20) & DATA_D(18 downto 0) & '0';
  SHIFT_L_TWO   <= DATA_D(20) & DATA_D(17 downto 0) & "00";
  SHIFT_L_THREE <= DATA_D(20) & DATA_D(16 downto 0) & "000";
  SHIFT_L_FOUR  <= DATA_D(20) & DATA_D(15 downto 0) & "0000";
  SHIFT_L_FIVE  <= DATA_D(20) & DATA_D(14 downto 0) & "00000";
  SHIFT_L_SIX   <= DATA_D(20) & DATA_D(13 downto 0) & "000000";
  SHIFT_L_SEVEN <= DATA_D(20) & DATA_D(12 downto 0) & "0000000";

  SHIFT_R_ONE   <= DATA_D(20) & DATA_D(20 downto 1);
  SHIFT_R_TWO   <= DATA_D(20) & DATA_D(20) & DATA_D(20 downto 2);
  SHIFT_R_THREE <= DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20 downto 3);
  SHIFT_R_FOUR  <= DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20 downto 4);
  SHIFT_R_FIVE  <= DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20 downto 5);
  SHIFT_R_SIX   <= DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20 downto 6);
  SHIFT_R_SEVEN <= DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20 downto 7);
  SHIFT_R_EIGHT <= DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20) & DATA_D(20 downto 8);

  DATA_E <= SHIFT_L_ONE   when SHIFT = "0001" else
            SHIFT_L_TWO   when SHIFT = "0010" else
            SHIFT_L_THREE when SHIFT = "0011" else
            SHIFT_L_FOUR  when SHIFT = "0100" else
            SHIFT_L_FIVE  when SHIFT = "0101" else
            SHIFT_L_SIX   when SHIFT = "0110" else
            SHIFT_L_SEVEN when SHIFT = "0111" else
            SHIFT_R_ONE   when SHIFT = "1111" else
            SHIFT_R_TWO   when SHIFT = "1110" else
            SHIFT_R_THREE when SHIFT = "1101" else
            SHIFT_R_FOUR  when SHIFT = "1100" else
            SHIFT_R_FIVE  when SHIFT = "1011" else
            SHIFT_R_SIX   when SHIFT = "1010" else
            SHIFT_R_SEVEN when SHIFT = "1001" else
            SHIFT_R_EIGHT when SHIFT = "1000" else
            DATA_D;

  iframePad5x5 : framePad5x5
    generic map (
      N           => N,
      LINE_LENGTH => LINE_LENGTH )
    port map (
      DATA_IN    => DATA_F(N - 1 downto 0),
      DATA_OUT   => DATA_OUT,
      DVALID_IN  => DVALID_D,
      DVALID_OUT => DVALID_OUT,
      EOL_IN     => EOL_D,
      EOL_OUT    => EOL_OUT,
      EOF_IN     => EOF_D,
      EOF_OUT    => EOF_OUT,
      CLOCK      => CLOCK,
      RESET      => RESET );

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

library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

  entity dataSupply5x5 is
    generic(
      N              : integer := 8;
      LINE_LENGTH    : integer := 384;
      RAM_ADDR_WIDTH : integer := 5
    );
    port (
      DATA_IN    : in  std_logic_vector(N - 1 downto 0);
      DATA_A1    : out std_logic_vector(N - 1 downto 0);
      DATA_A2    : out std_logic_vector(N - 1 downto 0);
      DATA_A3    : out std_logic_vector(N - 1 downto 0);
      DATA_A4    : out std_logic_vector(N - 1 downto 0);
      DATA_A5    : out std_logic_vector(N - 1 downto 0);
      DATA_B1    : out std_logic_vector(N - 1 downto 0);
      DATA_B2    : out std_logic_vector(N - 1 downto 0);
      DATA_B3    : out std_logic_vector(N - 1 downto 0);
      DATA_B4    : out std_logic_vector(N - 1 downto 0);
      DATA_B5    : out std_logic_vector(N - 1 downto 0);
      DATA_C1    : out std_logic_vector(N - 1 downto 0);
      DATA_C2    : out std_logic_vector(N - 1 downto 0);
      DATA_C3    : out std_logic_vector(N - 1 downto 0);
      DATA_C4    : out std_logic_vector(N - 1 downto 0);
      DATA_C5    : out std_logic_vector(N - 1 downto 0);
      DATA_D1    : out std_logic_vector(N - 1 downto 0);
      DATA_D2    : out std_logic_vector(N - 1 downto 0);
      DATA_D3    : out std_logic_vector(N - 1 downto 0);
      DATA_D4    : out std_logic_vector(N - 1 downto 0);
      DATA_D5    : out std_logic_vector(N - 1 downto 0);
      DATA_E1    : out std_logic_vector(N - 1 downto 0);
      DATA_E2    : out std_logic_vector(N - 1 downto 0);
      DATA_E3    : out std_logic_vector(N - 1 downto 0);
      DATA_E4    : out std_logic_vector(N - 1 downto 0);
      DATA_E5    : out std_logic_vector(N - 1 downto 0);
      DVALID_IN  : in  std_logic;
      DVALID_OUT : out std_logic;
      EOL_IN     : in  std_logic;
      EOL_OUT    : out std_logic;
      EOF_IN     : in  std_logic;
      EOF_OUT    : out std_logic;
      CLOCK      : in  std_logic;
      RESET      : in  std_logic
    );
  end dataSupply5x5;

architecture Behavioral of dataSupply5x5 is

  component spblockram5x5 is
    generic(
      N          : integer := 32;
      AddrN      : integer := 5;
      LINELENGTH : integer := 32
    );
    port (
      clk : in  std_logic;
      we  : in  std_logic;
      a   : in  std_logic_vector(AddrN - 1 downto 0);
      di  : in  std_logic_vector(N - 1 downto 0);
      do  : out std_logic_vector(N - 1 downto 0)
    );
  end component;

  type state_type is (A, B, C, D, E);

  signal state           : state_type;
  signal writeA          : std_logic;
  signal writeB          : std_logic;
  signal writeC          : std_logic;
  signal writeD          : std_logic;
  signal writeE          : std_logic;
  signal dataA           : std_logic_vector(N - 1 downto 0);
  signal dataB           : std_logic_vector(N - 1 downto 0);
  signal dataC           : std_logic_vector(N - 1 downto 0);
  signal dataD           : std_logic_vector(N - 1 downto 0);
  signal dataE           : std_logic_vector(N - 1 downto 0);
  signal line1           : std_logic_vector((N * 5) - 1 downto 0);
  signal line2           : std_logic_vector((N * 5) - 1 downto 0);
  signal line3           : std_logic_vector((N * 5) - 1 downto 0);
  signal line4           : std_logic_vector((N * 5) - 1 downto 0);
  signal line5           : std_logic_vector((N * 5) - 1 downto 0);
  signal inputPixelCount : std_logic_vector(11 downto 0);
  signal DATA_DEL        : std_logic_vector(N - 1 downto 0);
  signal DVALID_DEL      : std_logic;
  signal EOL_DEL         : std_logic;
  signal EOF_DEL         : std_logic;
  signal RAMaddr         : std_logic_vector(RAM_ADDR_WIDTH downto 0);

begin

------------------------------------------------------------------------
--State Machine controls data flow

  process(RESET, CLOCK)
  begin
    if RESET='1' then
      DATA_DEL   <= (others=>'0');
      EOL_DEL    <= '0';
      EOF_DEL    <= '0';
      DVALID_DEL <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
      DVALID_OUT <= '0';
    elsif rising_edge(CLOCK) then
      DATA_DEL   <= DATA_IN;
      EOL_DEL    <= EOL_IN;
      EOF_DEL    <= EOF_IN;
      DVALID_DEL <= DVALID_IN;
      EOL_OUT    <= EOL_DEL;
      EOF_OUT    <= EOF_DEL;
      DVALID_OUT <= DVALID_DEL;
    end if;
  end process;

  process(RESET, CLOCK)
  begin
    if RESET='1' then
      state <= A;
    elsif rising_edge(CLOCK) then
      case state is
        when A => if (EOL_DEL='1' or EOF_DEL='1') then state <= B;
                  else                                 state <= A;
                  end if;
        when B => if (EOL_DEL='1' or EOF_DEL='1') then state <= C;
                  else                                 state <= B;
                  end if;
        when C => if (EOL_DEL='1' or EOF_DEL='1') then state <= D;
                  else                                 state <= C;
                  end if;
        when D => if (EOL_DEL='1' or EOF_DEL='1') then state <= E;
                  else                                 state <= D;
                  end if;
        when E => if (EOL_DEL='1' or EOF_DEL='1') then state <= A;
                  else                                 state <= E;
                  end if;
      end case;
    end if;
  end process;

  process(state, DVALID_IN)
  begin
    case state is
      when A => writeA <= DVALID_IN; writeB <= '0'; writeC <= '0'; writeD <= '0'; writeE <= '0';
      when B => writeA <= '0'; writeB <= DVALID_IN; writeC <= '0'; writeD <= '0'; writeE <= '0';
      when C => writeA <= '0'; writeB <= '0'; writeC <= DVALID_IN; writeD <= '0'; writeE <= '0';
      when D => writeA <= '0'; writeB <= '0'; writeC <= '0'; writeD <= DVALID_IN; writeE <= '0';
      when E => writeA <= '0'; writeB <= '0'; writeC <= '0'; writeD <= '0'; writeE <= DVALID_IN;
    end case;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      line1 <= (others=>'0');
      line2 <= (others=>'0');
      line3 <= (others=>'0');
      line4 <= (others=>'0');
      line5 <= (others=>'0');
    elsif rising_edge(CLOCK)then
      if DVALID_DEL='1' then
        case state is
          when A => line1 <= line1((N * 4) - 1 downto 0) & dataB;
                    line2 <= line2((N * 4) - 1 downto 0) & dataC;
                    line3 <= line3((N * 4) - 1 downto 0) & dataD;
                    line4 <= line4((N * 4) - 1 downto 0) & dataE;
                    line5 <= line5((N * 4) - 1 downto 0) & DATA_DEL;
          when B => line1 <= line1((N * 4) - 1 downto 0) & dataC;
                    line2 <= line2((N * 4) - 1 downto 0) & dataD;
                    line3 <= line3((N * 4) - 1 downto 0) & dataE;
                    line4 <= line4((N * 4) - 1 downto 0) & dataA;
                    line5 <= line5((N * 4) - 1 downto 0) & DATA_DEL;
          when C => line1 <= line1((N * 4) - 1 downto 0) & dataD;
                    line2 <= line2((N * 4) - 1 downto 0) & dataE;
                    line3 <= line3((N * 4) - 1 downto 0) & dataA;
                    line4 <= line4((N * 4) - 1 downto 0) & dataB;
                    line5 <= line5((N * 4) - 1 downto 0) & DATA_DEL;
          when D => line1 <= line1((N * 4) - 1 downto 0) & dataE;
                    line2 <= line2((N * 4) - 1 downto 0) & dataA;
                    line3 <= line3((N * 4) - 1 downto 0) & dataB;
                    line4 <= line4((N * 4) - 1 downto 0) & dataC;
                    line5 <= line5((N * 4) - 1 downto 0) & DATA_DEL;
          when E => line1 <= line1((N * 4) - 1 downto 0) & dataA;
                    line2 <= line2((N * 4) - 1 downto 0) & dataB;
                    line3 <= line3((N * 4) - 1 downto 0) & dataC;
                    line4 <= line4((N * 4) - 1 downto 0) & dataD;
                    line5 <= line5((N * 4) - 1 downto 0) & DATA_DEL;
        end case;
      end if;
    end if;
  end process;

  DATA_A1 <= line1((N * 5) - 1 downto (N * 4));
  DATA_A2 <= line2((N * 5) - 1 downto (N * 4));
  DATA_A3 <= line3((N * 5) - 1 downto (N * 4));
  DATA_A4 <= line4((N * 5) - 1 downto (N * 4));
  DATA_A5 <= line5((N * 5) - 1 downto (N * 4));
  DATA_B1 <= line1((N * 4) - 1 downto (N * 3));
  DATA_B2 <= line2((N * 4) - 1 downto (N * 3));
  DATA_B3 <= line3((N * 4) - 1 downto (N * 3));
  DATA_B4 <= line4((N * 4) - 1 downto (N * 3));
  DATA_B5 <= line5((N * 4) - 1 downto (N * 3));
  DATA_C1 <= line1((N * 3) - 1 downto (N * 2));
  DATA_C2 <= line2((N * 3) - 1 downto (N * 2));
  DATA_C3 <= line3((N * 3) - 1 downto (N * 2));
  DATA_C4 <= line4((N * 3) - 1 downto (N * 2));
  DATA_C5 <= line5((N * 3) - 1 downto (N * 2));
  DATA_D1 <= line1((N * 2) - 1 downto (N * 1));
  DATA_D2 <= line2((N * 2) - 1 downto (N * 1));
  DATA_D3 <= line3((N * 2) - 1 downto (N * 1));
  DATA_D4 <= line4((N * 2) - 1 downto (N * 1));
  DATA_D5 <= line5((N * 2) - 1 downto (N * 1));
  DATA_E1 <= line1(N - 1 downto 0);
  DATA_E2 <= line2(N - 1 downto 0);
  DATA_E3 <= line3(N - 1 downto 0);
  DATA_E4 <= line4(N - 1 downto 0);
  DATA_E5 <= line5(N - 1 downto 0);

-----------------------------------------------------------------------
--Input pixel and line count

  process(RESET, CLOCK)
  begin
    if RESET='1' then
      inputPixelCount <= (others=>'0');
    elsif rising_edge(CLOCK) then
      if DVALID_IN='1' then
        inputPixelCount <= inputPixelCount + 1;
      elsif ((EOL_IN='1') or (EOF_IN='1')) then
        inputPixelCount <= (others=>'0');
      end if;
    end if;
  end process;

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

  RAMaddr <= inputPixelCount(RAM_ADDR_WIDTH - 1 downto 0);

  lineA : spblockram5x5
    generic map (
      N          => N,
      AddrN      => RAM_ADDR_WIDTH+1,
      LINELENGTH => LINE_LENGTH )
    port map (
      clk => CLOCK,
      we  => writeA,
      a   => RAMaddr,
      di  => DATA_IN,
      do  => dataA );

  lineB : spblockram5x5
    generic map (
      N          => N,
      AddrN      => RAM_ADDR_WIDTH+1,
      LINELENGTH => LINE_LENGTH )
    port map (
      clk => CLOCK,
      we  => writeB,
      a   => RAMaddr,
      di  => DATA_IN,
      do  => dataB);

  lineC : spblockram5x5
    generic map (
      N          => N,
      AddrN      => RAM_ADDR_WIDTH+1,
      LINELENGTH => LINE_LENGTH )
    port map (
      clk => CLOCK,
      we  => writeC,
      a   => RAMaddr,
      di  => DATA_IN,
      do  => dataC );

  lineD : spblockram5x5
    generic map (
      N          => N,
      AddrN      => RAM_ADDR_WIDTH+1,
      LINELENGTH => LINE_LENGTH )
    port map (
      clk => CLOCK,
      we  => writeD,
      a   => RAMaddr,
      di  => DATA_IN,
      do  => dataD );

  lineE : spblockram5x5
    generic map (
      N          => N,
      AddrN      => RAM_ADDR_WIDTH+1,
      LINELENGTH => LINE_LENGTH )
    port map (
      clk => CLOCK,
      we  => writeE,
      a   => RAMaddr,
      di  => DATA_IN,
      do  => dataE );

end Behavioral;

-------------------------------------------------------------------------
--The Maths Part

library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_SIGNED.ALL;

--pragma translate_off
library UNISIM;
  use UNISIM.VCOMPONENTS.all;
--pragma translate_on

  entity dataMaths5x5 is
    generic(
      N      : integer := 8;
      Kernel : string  := "GENERAL"
    );
    port (
      DATA_A1    : in  std_logic_vector(N - 1 downto 0);
      DATA_B1    : in  std_logic_vector(N - 1 downto 0);
      DATA_C1    : in  std_logic_vector(N - 1 downto 0);
      DATA_D1    : in  std_logic_vector(N - 1 downto 0);
      DATA_E1    : in  std_logic_vector(N - 1 downto 0);
      DATA_A2    : in  std_logic_vector(N - 1 downto 0);
      DATA_B2    : in  std_logic_vector(N - 1 downto 0);
      DATA_C2    : in  std_logic_vector(N - 1 downto 0);
      DATA_D2    : in  std_logic_vector(N - 1 downto 0);
      DATA_E2    : in  std_logic_vector(N - 1 downto 0);
      DATA_A3    : in  std_logic_vector(N - 1 downto 0);
      DATA_B3    : in  std_logic_vector(N - 1 downto 0);
      DATA_C3    : in  std_logic_vector(N - 1 downto 0);
      DATA_D3    : in  std_logic_vector(N - 1 downto 0);
      DATA_E3    : in  std_logic_vector(N - 1 downto 0);
      DATA_A4    : in  std_logic_vector(N - 1 downto 0);
      DATA_B4    : in  std_logic_vector(N - 1 downto 0);
      DATA_C4    : in  std_logic_vector(N - 1 downto 0);
      DATA_D4    : in  std_logic_vector(N - 1 downto 0);
      DATA_E4    : in  std_logic_vector(N - 1 downto 0);
      DATA_A5    : in  std_logic_vector(N - 1 downto 0);
      DATA_B5    : in  std_logic_vector(N - 1 downto 0);
      DATA_C5    : in  std_logic_vector(N - 1 downto 0);
      DATA_D5    : in  std_logic_vector(N - 1 downto 0);
      DATA_E5    : in  std_logic_vector(N - 1 downto 0);
      K_A1       : in  std_logic_vector(17 downto 0);
      K_A2       : in  std_logic_vector(17 downto 0);
      K_A3       : in  std_logic_vector(17 downto 0);
      K_A4       : in  std_logic_vector(17 downto 0);
      K_A5       : in  std_logic_vector(17 downto 0);
      K_B1       : in  std_logic_vector(17 downto 0);
      K_B2       : in  std_logic_vector(17 downto 0);
      K_B3       : in  std_logic_vector(17 downto 0);
      K_B4       : in  std_logic_vector(17 downto 0);
      K_B5       : in  std_logic_vector(17 downto 0);
      K_C1       : in  std_logic_vector(17 downto 0);
      K_C2       : in  std_logic_vector(17 downto 0);
      K_C3       : in  std_logic_vector(17 downto 0);
      K_C4       : in  std_logic_vector(17 downto 0);
      K_C5       : in  std_logic_vector(17 downto 0);
      K_D1       : in  std_logic_vector(17 downto 0);
      K_D2       : in  std_logic_vector(17 downto 0);
      K_D3       : in  std_logic_vector(17 downto 0);
      K_D4       : in  std_logic_vector(17 downto 0);
      K_D5       : in  std_logic_vector(17 downto 0);
      K_E1       : in  std_logic_vector(17 downto 0);
      K_E2       : in  std_logic_vector(17 downto 0);
      K_E3       : in  std_logic_vector(17 downto 0);
      K_E4       : in  std_logic_vector(17 downto 0);
      K_E5       : in  std_logic_vector(17 downto 0);
      DATA_OUT   : out std_logic_vector(20 downto 0);
      DVALID_IN  : in  std_logic;
      DVALID_OUT : out std_logic;
      EOL_IN     : in  std_logic;
      EOL_OUT    : out std_logic;
      EOF_IN     : in  std_logic;
      EOF_OUT    : out std_logic;
      CLOCK      : in  std_logic;
      RESET      : in  std_logic
    );
  end dataMaths5x5;

architecture Behavioral of dataMaths5x5 is

  signal DVALID_DEL   : std_logic_vector(4 downto 0);
  signal EOL_DEL      : std_logic_vector(4 downto 0);
  signal EOF_DEL      : std_logic_vector(4 downto 0);

  --Convert 8-bit unsigned data to 9-bit signed, ALL POSITIVE!
  signal CONV_A1      : std_logic_vector(17 downto 0);
  signal CONV_A2      : std_logic_vector(17 downto 0);
  signal CONV_A3      : std_logic_vector(17 downto 0);
  signal CONV_A4      : std_logic_vector(17 downto 0);
  signal CONV_A5      : std_logic_vector(17 downto 0);
  signal CONV_B1      : std_logic_vector(17 downto 0);
  signal CONV_B2      : std_logic_vector(17 downto 0);
  signal CONV_B3      : std_logic_vector(17 downto 0);
  signal CONV_B4      : std_logic_vector(17 downto 0);
  signal CONV_B5      : std_logic_vector(17 downto 0);
  signal CONV_C1      : std_logic_vector(17 downto 0);
  signal CONV_C2      : std_logic_vector(17 downto 0);
  signal CONV_C3      : std_logic_vector(17 downto 0);
  signal CONV_C4      : std_logic_vector(17 downto 0);
  signal CONV_C5      : std_logic_vector(17 downto 0);
  signal CONV_D1      : std_logic_vector(17 downto 0);
  signal CONV_D2      : std_logic_vector(17 downto 0);
  signal CONV_D3      : std_logic_vector(17 downto 0);
  signal CONV_D4      : std_logic_vector(17 downto 0);
  signal CONV_D5      : std_logic_vector(17 downto 0);
  signal CONV_E1      : std_logic_vector(17 downto 0);
  signal CONV_E2      : std_logic_vector(17 downto 0);
  signal CONV_E3      : std_logic_vector(17 downto 0);
  signal CONV_E4      : std_logic_vector(17 downto 0);
  signal CONV_E5      : std_logic_vector(17 downto 0);
  signal CONV_A       : std_logic_vector(19 downto 0);
  signal CONV_B       : std_logic_vector(19 downto 0);
  signal CONV_C       : std_logic_vector(19 downto 0);
  signal CONV_D       : std_logic_vector(19 downto 0);
  signal CONV_E       : std_logic_vector(19 downto 0);
  signal CONV_F       : std_logic_vector(19 downto 0);
  signal CONV_G       : std_logic_vector(19 downto 0);
  signal CONV_H       : std_logic_vector(19 downto 0);
  signal CONV_I       : std_logic_vector(19 downto 0);
  signal CONV_J       : std_logic_vector(19 downto 0);
  signal CONV_K       : std_logic_vector(19 downto 0);
  signal CONV_L       : std_logic_vector(19 downto 0);
  signal CONV_M       : std_logic_vector(19 downto 0);
  signal CONV_N       : std_logic_vector(19 downto 0);
  signal CONV_O       : std_logic_vector(19 downto 0);
  signal CONV_P       : std_logic_vector(19 downto 0);
  signal CONV_Q       : std_logic_vector(19 downto 0);
  signal CONV_R       : std_logic_vector(19 downto 0);
  signal CONV_S       : std_logic_vector(19 downto 0);
  signal CONV_T       : std_logic_vector(19 downto 0);
  signal CONV_U       : std_logic_vector(19 downto 0);
  signal CONV_V       : std_logic_vector(19 downto 0);
  signal CONV_W       : std_logic_vector(19 downto 0);
  signal CONV_X       : std_logic_vector(19 downto 0);
  signal CONV_Y       : std_logic_vector(19 downto 0);
  signal CONV_Z       : std_logic_vector(19 downto 0);

  --Multiplication results
  signal MULT_A1      : std_logic_vector(35 downto 0);
  signal MULT_A2      : std_logic_vector(35 downto 0);
  signal MULT_A3      : std_logic_vector(35 downto 0);
  signal MULT_A4      : std_logic_vector(35 downto 0);
  signal MULT_A5      : std_logic_vector(35 downto 0);
  signal MULT_B1      : std_logic_vector(35 downto 0);
  signal MULT_B2      : std_logic_vector(35 downto 0);
  signal MULT_B3      : std_logic_vector(35 downto 0);
  signal MULT_B4      : std_logic_vector(35 downto 0);
  signal MULT_B5      : std_logic_vector(35 downto 0);
  signal MULT_C1      : std_logic_vector(35 downto 0);
  signal MULT_C2      : std_logic_vector(35 downto 0);
  signal MULT_C3      : std_logic_vector(35 downto 0);
  signal MULT_C4      : std_logic_vector(35 downto 0);
  signal MULT_C5      : std_logic_vector(35 downto 0);
  signal MULT_D1      : std_logic_vector(35 downto 0);
  signal MULT_D2      : std_logic_vector(35 downto 0);
  signal MULT_D3      : std_logic_vector(35 downto 0);
  signal MULT_D4      : std_logic_vector(35 downto 0);
  signal MULT_D5      : std_logic_vector(35 downto 0);
  signal MULT_E1      : std_logic_vector(35 downto 0);
  signal MULT_E2      : std_logic_vector(35 downto 0);
  signal MULT_E3      : std_logic_vector(35 downto 0);
  signal MULT_E4      : std_logic_vector(35 downto 0);
  signal MULT_E5      : std_logic_vector(35 downto 0);

  signal RESULT_A     : std_logic_vector(20 downto 0);
  signal RESULT_B     : std_logic_vector(20 downto 0);
  signal RESULT_C     : std_logic_vector(20 downto 0);
  signal RESULT_D     : std_logic_vector(20 downto 0);
  signal RESULT_E     : std_logic_vector(20 downto 0);
  signal RESULT_F     : std_logic_vector(20 downto 0);
  signal RESULT_G     : std_logic_vector(20 downto 0);
  signal RESULT_H     : std_logic_vector(20 downto 0);
  signal RESULT_I     : std_logic_vector(20 downto 0);
  signal RESULT_J     : std_logic_vector(20 downto 0);
  signal RESULT_K     : std_logic_vector(20 downto 0);
  signal RESULT_L     : std_logic_vector(20 downto 0);
  signal RESULT_M     : std_logic_vector(20 downto 0);
  signal RESULT_N     : std_logic_vector(20 downto 0);
  signal RESULT_O     : std_logic_vector(20 downto 0);
  signal RESULT_P     : std_logic_vector(20 downto 0);
  signal RESULT_Q     : std_logic_vector(20 downto 0);
  signal RESULT_R     : std_logic_vector(20 downto 0);
  signal RESULT_S     : std_logic_vector(20 downto 0);
  signal RESULT_T     : std_logic_vector(20 downto 0);
  signal RESULT_U     : std_logic_vector(20 downto 0);
  signal RESULT_V     : std_logic_vector(20 downto 0);
  signal RESULT_W     : std_logic_vector(20 downto 0);
  signal RESULT_X     : std_logic_vector(20 downto 0);
  signal RESULT_y     : std_logic_vector(20 downto 0);
  signal RESULT_AA    : std_logic_vector(20 downto 0);
  signal RESULT_AB    : std_logic_vector(20 downto 0);
  signal RESULT_BA    : std_logic_vector(20 downto 0);
  signal RESULT_BB    : std_logic_vector(20 downto 0);
  signal RESULT_CA    : std_logic_vector(20 downto 0);
  signal RESULT_CB    : std_logic_vector(20 downto 0);
  signal RESULT_DA    : std_logic_vector(20 downto 0);
  signal RESULT_DB    : std_logic_vector(20 downto 0);
  signal RESULT_EA    : std_logic_vector(20 downto 0);
  signal RESULT_EB    : std_logic_vector(20 downto 0);
  signal RESULT_FA    : std_logic_vector(20 downto 0);
  signal RESULT_FB    : std_logic_vector(20 downto 0);
  signal RESULT_FC    : std_logic_vector(20 downto 0);
  signal RESULT_AAA   : std_logic_vector(20 downto 0);
  signal RESULT_BBB   : std_logic_vector(20 downto 0);
  signal RESULT_CCC   : std_logic_vector(20 downto 0);
  signal RESULT_DDD   : std_logic_vector(20 downto 0);
  signal RESULT_EEE   : std_logic_vector(20 downto 0);
  signal RESULT_FFF   : std_logic_vector(20 downto 0);
  signal RESULT_GGG   : std_logic_vector(20 downto 0);
  signal RESULT_AAAA  : std_logic_vector(20 downto 0);
  signal RESULT_BBBB  : std_logic_vector(20 downto 0);
  signal RESULT_CCCC  : std_logic_vector(20 downto 0);
  signal RESULT_DDDD  : std_logic_vector(20 downto 0);
  signal RESULT_AAAAA : std_logic_vector(20 downto 0);
  signal RESULT_BBBBB : std_logic_vector(20 downto 0);

  signal RESULT_AA_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_AB_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_BA_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_BB_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_CA_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_CB_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_DA_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_DB_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_EA_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_EB_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_FA_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_FB_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_FC_TEMP    : std_logic_vector(20 downto 0);
  signal RESULT_AAA_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_BBB_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_CCC_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_DDD_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_EEE_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_FFF_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_GGG_TEMP   : std_logic_vector(20 downto 0);
  signal RESULT_AAAA_TEMP  : std_logic_vector(20 downto 0);
  signal RESULT_BBBB_TEMP  : std_logic_vector(20 downto 0);
  signal RESULT_CCCC_TEMP  : std_logic_vector(20 downto 0);
  signal RESULT_DDDD_TEMP  : std_logic_vector(20 downto 0);
  signal RESULT_AAAAA_TEMP : std_logic_vector(20 downto 0);
  signal RESULT_BBBBB_TEMP : std_logic_vector(20 downto 0);
  signal RESULT_RESULT     : std_logic_vector(20 downto 0);

  signal PAD        : std_logic_vector(17 - N downto 0);
  signal PAD2       : std_logic_vector(20 - N downto 0);
  signal PAD3       : std_logic_vector(20 - (N - 1) - 1 downto 0);
  signal PAD4       : std_logic_vector(20 - (N - 3) - 3 downto 0);
  signal PAD5       : std_logic_vector(20 - (N - 2) - 2 downto 0);
  signal PAD6       : std_logic_vector(20 - (N - 4) - 4 downto 0);

  signal data_line1 : std_logic_vector(20 downto 0);
  signal data_line2 : std_logic_vector(20 downto 0);
  signal data_line3 : std_logic_vector(20 downto 0);
  signal data_line4 : std_logic_vector(20 downto 0);
  signal data_line5 : std_logic_vector(20 downto 0);

  component MULT18X18
    port (
      A : in  std_logic_vector(17 downto 0);
      B : in  std_logic_vector(17 downto 0);
      P : out std_logic_vector(35 downto 0)
    );
  end component;

  component new_add
    port (
      A : in  std_logic_vector(19 downto 0);
      B : in  std_logic_vector(19 downto 0);
      S : out std_logic_vector(20 downto 0)
    );
  end component;

begin

  PAD  <= (others=>'0');
  PAD2 <= (others=>'0');
  PAD3 <= (others=>'0');
  PAD4 <= (others=>'0');
  PAD5 <= (others=>'0');
  PAD6 <= (others=>'0');

general : if (Kernel="GENERAL") generate
  CONV_A1 <= PAD & DATA_A1;
  CONV_A2 <= PAD & DATA_A2;
  CONV_A3 <= PAD & DATA_A3;
  CONV_A4 <= PAD & DATA_A4;
  CONV_A5 <= PAD & DATA_A5;
  CONV_B1 <= PAD & DATA_B1;
  CONV_B2 <= PAD & DATA_B2;
  CONV_B3 <= PAD & DATA_B3;
  CONV_B4 <= PAD & DATA_B4;
  CONV_B5 <= PAD & DATA_B5;
  CONV_C1 <= PAD & DATA_C1;
  CONV_C2 <= PAD & DATA_C2;
  CONV_C3 <= PAD & DATA_C3;
  CONV_C4 <= PAD & DATA_C4;
  CONV_C5 <= PAD & DATA_C5;
  CONV_D1 <= PAD & DATA_D1;
  CONV_D2 <= PAD & DATA_D2;
  CONV_D3 <= PAD & DATA_D3;
  CONV_D4 <= PAD & DATA_D4;
  CONV_D5 <= PAD & DATA_D5;
  CONV_E1 <= PAD & DATA_E1;
  CONV_E2 <= PAD & DATA_E2;
  CONV_E3 <= PAD & DATA_E3;
  CONV_E4 <= PAD & DATA_E4;
  CONV_E5 <= PAD & DATA_E5;

  CellA1 : MULT18X18
    port map (
      A => CONV_A1,
      B => K_A1,
      P => MULT_A1 );

  CellA2 : MULT18X18
    port map (
      A => CONV_A2,
      B => K_A2,
      P => MULT_A2 );

  CellA3 : MULT18X18
    port map (
      A => CONV_A3,
      B => K_A3,
      P => MULT_A3 );

  CellA4 : MULT18X18
    port map (
      A => CONV_A4,
      B => K_A4,
      P => MULT_A4 );

  CellA5 : MULT18X18
    port map (
      A => CONV_A5,
      B => K_A5,
      P => MULT_A5 );

  CellB1 : MULT18X18
    port map (
      A => CONV_B1,
      B => K_B1,
      P => MULT_B1 );

  CellB2 : MULT18X18
    port map (
      A => CONV_B2,
      B => K_B2,
      P => MULT_B2 );

  CellB3 : MULT18X18
    port map (
      A => CONV_B3,
      B => K_B3,
      P => MULT_B3 );

  CellB4 : MULT18X18
    port map (
      A => CONV_B4,
      B => K_B4,
      P => MULT_B4 );

  CellB5 : MULT18X18
    port map (
      A => CONV_B5,
      B => K_B5,
      P => MULT_B5 );

  CellC1 : MULT18X18
    port map (
      A => CONV_C1,
      B => K_C1,
      P => MULT_C1 );

  CellC2 : MULT18X18
    port map (
      A => CONV_C2,
      B => K_C2,
      P => MULT_C2 );

  CellC3 : MULT18X18
    port map (
      A => CONV_C3,
      B => K_C3,
      P => MULT_C3 );

  CellC4 : MULT18X18
    port map (
      A => CONV_C4,
      B => K_C4,
      P => MULT_C4 );

  CellC5 : MULT18X18
    port map (
      A => CONV_C5,
      B => K_C5,
      P => MULT_C5 );

  CellD1 : MULT18X18
    port map (
      A => CONV_D1,
      B => K_D1,
      P => MULT_D1 );

  CellD2 : MULT18X18
    port map (
      A => CONV_D2,
      B => K_D2,
      P => MULT_D2 );

  CellD3 : MULT18X18
    port map (
      A => CONV_D3,
      B => K_D3,
      P => MULT_D3 );

  CellD4 : MULT18X18
    port map (
      A => CONV_D4,
      B => K_D4,
      P => MULT_D4 );

  CellD5 : MULT18X18
    port map (
      A => CONV_D5,
      B => K_D5,
      P => MULT_D5 );

  CellE1 : MULT18X18
    port map (
      A => CONV_E1,
      B => K_E1,
      P => MULT_E1 );

  CellE2 : MULT18X18
    port map (
      A => CONV_E2,
      B => K_E2,
      P => MULT_E2 );

  CellE3 : MULT18X18
    port map (
      A => CONV_E3,
      B => K_E3,
      P => MULT_E3 );

  CellE4 : MULT18X18
    port map (
      A => CONV_E4,
      B => K_E4,
      P => MULT_E4 );

  CellE5 : MULT18X18
    port map (
      A => CONV_E5,
      B => K_E5,
      P => MULT_E5 );

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      RESULT_A <=(others=>'0');
      RESULT_B <=(others=>'0');
      RESULT_C <=(others=>'0');
      RESULT_D <=(others=>'0');
      RESULT_E <=(others=>'0');
      RESULT_F <=(others=>'0');
      RESULT_G <=(others=>'0');
      RESULT_H <=(others=>'0');
      RESULT_I <=(others=>'0');
      RESULT_L <=(others=>'0');
      RESULT_M <=(others=>'0');
      RESULT_N <=(others=>'0');
      RESULT_O <=(others=>'0');
      RESULT_P <=(others=>'0');
      RESULT_Q <=(others=>'0');
      RESULT_R <=(others=>'0');
      RESULT_S <=(others=>'0');
      RESULT_T <=(others=>'0');
      RESULT_U <=(others=>'0');
      RESULT_V <=(others=>'0');
      RESULT_W <=(others=>'0');
      RESULT_X <=(others=>'0');
      RESULT_Y <=(others=>'0');
    elsif rising_edge(CLOCK) then
      RESULT_A <= '0' & MULT_A1(35) & MULT_A1(18 downto 0);
      RESULT_B <= '0' & MULT_A2(35) & MULT_A2(18 downto 0);
      RESULT_C <= '0' & MULT_A3(35) & MULT_A3(18 downto 0);
      RESULT_D <= '0' & MULT_A4(35) & MULT_A4(18 downto 0);
      RESULT_E <= '0' & MULT_A5(35) & MULT_A5(18 downto 0);
      RESULT_F <= '0' & MULT_B1(35) & MULT_B1(18 downto 0);
      RESULT_G <= '0' & MULT_B2(35) & MULT_B2(18 downto 0);
      RESULT_H <= '0' & MULT_B3(35) & MULT_B3(18 downto 0);
      RESULT_I <= '0' & MULT_B4(35) & MULT_B4(18 downto 0);
      RESULT_J <= '0' & MULT_B5(35) & MULT_B5(18 downto 0);
      RESULT_K <= '0' & MULT_C1(35) & MULT_C1(18 downto 0);
      RESULT_L <= '0' & MULT_C2(35) & MULT_C2(18 downto 0);
      RESULT_M <= '0' & MULT_C3(35) & MULT_C3(18 downto 0);
      RESULT_N <= '0' & MULT_C4(35) & MULT_C4(18 downto 0);
      RESULT_O <= '0' & MULT_C5(35) & MULT_C5(18 downto 0);
      RESULT_P <= '0' & MULT_D1(35) & MULT_D1(18 downto 0);
      RESULT_Q <= '0' & MULT_D2(35) & MULT_D2(18 downto 0);
      RESULT_R <= '0' & MULT_D3(35) & MULT_D3(18 downto 0);
      RESULT_S <= '0' & MULT_D4(35) & MULT_D4(18 downto 0);
      RESULT_T <= '0' & MULT_D5(35) & MULT_D5(18 downto 0);
      RESULT_U <= '0' & MULT_E1(35) & MULT_E1(18 downto 0);
      RESULT_V <= '0' & MULT_E2(35) & MULT_E2(18 downto 0);
      RESULT_W <= '0' & MULT_E3(35) & MULT_E3(18 downto 0);
      RESULT_X <= '0' & MULT_E4(35) & MULT_E4(18 downto 0);
      RESULT_Y <= '0' & MULT_E5(35) & MULT_E5(18 downto 0);
    end if;
  end process;

  iADD_A : new_add
    port map (
      A => RESULT_A(19 downto 0),
      B => RESULT_B(19 downto 0),
      S => RESULT_AA_TEMP(20 downto 0));

  iADD_B : new_add
    port map (
      A => RESULT_C(19 downto 0),
      B => RESULT_D(19 downto 0),
      S => RESULT_AB_TEMP(20 downto 0));

  iADD_C : new_add
    port map (
      A => RESULT_F(19 downto 0),
      B => RESULT_G(19 downto 0),
      S => RESULT_BA_TEMP(20 downto 0));

  iADD_D : new_add
    port map (
      A => RESULT_H(19 downto 0),
      B => RESULT_I(19 downto 0),
      S => RESULT_BB_TEMP(20 downto 0));

  iADD_E : new_add
    port map (
      A => RESULT_K(19 downto 0),
      B => RESULT_L(19 downto 0),
      S => RESULT_CA_TEMP(20 downto 0));

  iADD_F : new_add
    port map (
      A => RESULT_M(19 downto 0),
      B => RESULT_N(19 downto 0),
      S => RESULT_CB_TEMP(20 downto 0));

  iADD_G : new_add
    port map (
      A => RESULT_P(19 downto 0),
      B => RESULT_Q(19 downto 0),
      S => RESULT_DA_TEMP(20 downto 0));

  iADD_H : new_add
    port map (
      A => RESULT_R(19 downto 0),
      B => RESULT_S(19 downto 0),
      S => RESULT_DB_TEMP(20 downto 0));

  iADD_I : new_add
    port map (
      A => RESULT_U(19 downto 0),
      B => RESULT_V(19 downto 0),
      S => RESULT_EA_TEMP(20 downto 0));

  iADD_L : new_add
    port map (
      A => RESULT_W(19 downto 0),
      B => RESULT_X(19 downto 0),
      S => RESULT_EB_TEMP(20 downto 0));

  iADD_M : new_add
    port map (
      A => RESULT_E(19 downto 0),
      B => RESULT_J(19 downto 0),
      S => RESULT_FA_TEMP(20 downto 0));

  iADD_N : new_add
    port map (
      A => RESULT_O(19 downto 0),
      B => RESULT_T(19 downto 0),
      S => RESULT_FB_TEMP(20 downto 0));

  ------------------------------------------------
  --Second Adder Stage

  CONV_A <= RESULT_AA(20) & RESULT_AA(18 downto 0);
  CONV_B <= RESULT_AB(20) & RESULT_AB(18 downto 0);

  iADD_O : new_add
    port map (
      A => CONV_A,
      B => CONV_B,
      S => RESULT_AAA_TEMP(20 downto 0));

  CONV_C <= RESULT_BA(20) & RESULT_BA(18 downto 0);
  CONV_D <= RESULT_BB(20) & RESULT_BB(18 downto 0);

  iADD_P : new_add
    port map (
      A => CONV_C,
      B => CONV_D,
      S => RESULT_BBB_TEMP(20 downto 0));

  CONV_E <= RESULT_CA(20) & RESULT_CA(18 downto 0);
  CONV_F <= RESULT_CB(20) & RESULT_CB(18 downto 0);

  iADD_Q : new_add
    port map (
      A => CONV_E,
      B => CONV_F,
      S => RESULT_CCC_TEMP(20 downto 0));

  CONV_G <= RESULT_DA(20) & RESULT_DA(18 downto 0);
  CONV_H <= RESULT_DB(20) & RESULT_DB(18 downto 0);

  iADD_R : new_add
    port map (
      A => CONV_G,
      B => CONV_H,
      S => RESULT_DDD_TEMP(20 downto 0));

  CONV_I <= RESULT_EA(20) & RESULT_EA(18 downto 0);
  CONV_J <= RESULT_EB(20) & RESULT_EB(18 downto 0);

  iADD_S : new_add
    port map (
      A => CONV_I,
      B => CONV_J,
      S => RESULT_EEE_TEMP(20 downto 0));

  CONV_K <= RESULT_FB(20) & RESULT_FB(18 downto 0);
  CONV_L <= RESULT_FC(20) & RESULT_FC(18 downto 0);

  iADD_T : new_add
    port map (
      A => CONV_K,
      B => CONV_L,
      S => RESULT_FFF_TEMP(20 downto 0));

  ---------------------------------------------------
  --Third Adder Stage

  CONV_M <= RESULT_AAA(20) & RESULT_AAA(18 downto 0);
  CONV_N <= RESULT_GGG(20) & RESULT_GGG(18 downto 0);

  iADD_U : new_add
    port map (
      A => CONV_M,
      B => CONV_N,
      S => RESULT_AAAA_TEMP(20 downto 0));

  CONV_O <= RESULT_BBB(20) & RESULT_BBB(18 downto 0);
  CONV_P <= RESULT_CCC(20) & RESULT_CCC(18 downto 0);

  iADD_V : new_add
    port map (
      A => CONV_O,
      B => CONV_P,
      S => RESULT_BBBB_TEMP(20 downto 0));

  CONV_Q <= RESULT_DDD(20) & RESULT_DDD(18 downto 0);
  CONV_R <= RESULT_FFF(20) & RESULT_FFF(18 downto 0);

  iADD_W : new_add
    port map (
      A => CONV_Q,
      B => CONV_R,
      S => RESULT_CCCC_TEMP(20 downto 0));

  ---------------------------------------------------
  --Forth Adder Stage

  CONV_S <= RESULT_AAAA(20) & RESULT_AAAA(18 downto 0);
  CONV_T <= RESULT_BBBB(20) & RESULT_BBBB(18 downto 0);

  iADD_X : new_add
    port map (
      A => CONV_S,
      B => CONV_T,
      S => RESULT_AAAAA_TEMP(20 downto 0));

  CONV_U <= RESULT_CCCC(20) & RESULT_CCCC(18 downto 0);
  CONV_V <= RESULT_DDDD(20) & RESULT_DDDD(18 downto 0);

  iADD_Y : new_add
    port map (
      A => CONV_U,
      B => CONV_V,
      S => RESULT_BBBBB_TEMP(20 downto 0));

  -----------------------------------------------------
  --Fifth adder stage

  CONV_W <= RESULT_AAAAA(20) & RESULT_AAAAA(18 downto 0);
  CONV_X <= RESULT_BBBBB(20) & RESULT_BBBBB(18 downto 0);

  iADD_Z : new_add
    port map (
      A => CONV_W,
      B => CONV_X,
      S => RESULT_RESULT(20 downto 0));

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      RESULT_AA    <= (others=>'0');
      RESULT_AB    <= (others=>'0');
      RESULT_BA    <= (others=>'0');
      RESULT_BB    <= (others=>'0');
      RESULT_CA    <= (others=>'0');
      RESULT_CB    <= (others=>'0');
      RESULT_DA    <= (others=>'0');
      RESULT_DB    <= (others=>'0');
      RESULT_EA    <= (others=>'0');
      RESULT_EB    <= (others=>'0');
      RESULT_FA    <= (others=>'0');
      RESULT_FB    <= (others=>'0');
      RESULT_FC    <= (others=>'0');
      RESULT_AAA   <= (others=>'0');
      RESULT_BBB   <= (others=>'0');
      RESULT_CCC   <= (others=>'0');
      RESULT_DDD   <= (others=>'0');
      RESULT_EEE   <= (others=>'0');
      RESULT_FFF   <= (others=>'0');
      RESULT_GGG   <= (others=>'0');
      RESULT_AAAA  <= (others=>'0');
      RESULT_BBBB  <= (others=>'0');
      RESULT_CCCC  <= (others=>'0');
      RESULT_DDDD  <= (others=>'0');
      RESULT_AAAAA <= (others=>'0');
      RESULT_BBBBB <= (others=>'0');
  elsif rising_edge(CLOCK) then
      RESULT_AA    <= RESULT_AA_TEMP;
      RESULT_AB    <= RESULT_AB_TEMP;
      RESULT_BA    <= RESULT_BA_TEMP;
      RESULT_BB    <= RESULT_BB_TEMP;
      RESULT_CA    <= RESULT_CA_TEMP;
      RESULT_CB    <= RESULT_CB_TEMP;
      RESULT_DA    <= RESULT_DA_TEMP;
      RESULT_DB    <= RESULT_DB_TEMP;
      RESULT_EA    <= RESULT_EA_TEMP;
      RESULT_EB    <= RESULT_EB_TEMP;
      RESULT_FA    <= RESULT_FA_TEMP;
      RESULT_FB    <= RESULT_FB_TEMP;
      RESULT_FC    <= RESULT_Y(19) & RESULT_Y(19 downto 0);
      RESULT_AAA   <= RESULT_AAA_TEMP;
      RESULT_BBB   <= RESULT_BBB_TEMP;
      RESULT_CCC   <= RESULT_CCC_TEMP;
      RESULT_DDD   <= RESULT_DDD_TEMP;
      RESULT_EEE   <= RESULT_EEE_TEMP;
      RESULT_FFF   <= RESULT_FFF_TEMP;
      RESULT_GGG   <= RESULT_FA;
      RESULT_AAAA  <= RESULT_AAAA_TEMP;
      RESULT_BBBB  <= RESULT_BBBB_TEMP;
      RESULT_CCCC  <= RESULT_CCCC_TEMP;
      RESULT_DDDD  <= RESULT_EEE;
      RESULT_AAAAA <= RESULT_AAAAA_TEMP;
      RESULT_BBBBB <= RESULT_BBBBB_TEMP;
      DATA_OUT     <= RESULT_RESULT;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "00000";
      EOL_DEL    <= "00000";
      EOF_DEL    <= "00000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= DVALID_IN & DVALID_DEL(4 downto 1);
      EOL_DEL    <= EOL_IN & EOL_DEL(4 downto 1);
      EOF_DEL    <= EOF_IN & EOF_DEL(4 downto 1);
      DVALID_OUT <= DVALID_DEL(0);
      EOL_OUT    <= EOL_DEL(0);
      EOF_OUT    <= EOF_DEL(0);
    end if;
  end process;

end generate;

vSobel: if (Kernel="vSobel") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      data_line1 <= (others=>'0');
      data_line2 <= (others=>'0');
      data_line4 <= (others=>'0');
      data_line5 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      data_line1 <=(PAD2 & DATA_A1)
                 + (PAD3 & DATA_A2(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_A3(N - 1 downto 0) & '0') + (PAD2 & DATA_A3)
                 + (PAD3 & DATA_A4(N - 1 downto 0) & '0')
                 + (PAD2 & DATA_A5);
      data_line2 <=(PAD3 & DATA_B1(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_B2(N - 1 downto 0) & '0') + (PAD2 & DATA_B2)
                 + (PAD5 & DATA_B3(N - 1 downto 0) & "00")
                 + (PAD3 & DATA_B4(N - 1 downto 0) & '0') + (PAD2 & DATA_B4)
                 + (PAD3 & DATA_B5(N - 1 downto 0) & '0');
      data_line4 <=(PAD3 & DATA_D1(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_D2(N - 1 downto 0) & '0') + (PAD2 & DATA_D2)
                 + (PAD5 & DATA_D3(N - 1 downto 0) & "00")
                 + (PAD3 & DATA_D4(N - 1 downto 0) & '0') + (PAD2 & DATA_D4)
                 + (PAD3 & DATA_D5(N - 1 downto 0) & '0');
      data_line5 <=(PAD2 & DATA_E1)
                 + (PAD3 & DATA_E2(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_E3(N - 1 downto 0) & '0') + (PAD2 & DATA_E3)
                 + (PAD3 & DATA_E4(N - 1 downto 0) & '0')
                 + (PAD2 & DATA_E5);
      DATA_OUT <= data_line1 + data_line2 - data_line4 - data_line5;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "00000";
      EOL_DEL    <= "00000";
      EOF_DEL    <= "00000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= "0000" & DVALID_IN;
      EOL_DEL    <= "0000" & EOL_IN;
      EOF_DEL    <= "0000" & EOF_IN;
      DVALID_OUT <= DVALID_DEL(0);
      EOL_OUT    <= EOL_DEL(0);
      EOF_OUT    <= EOF_DEL(0);
    end if;
  end process;
end generate;

hSobel: if (Kernel="hSobel") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      data_line1 <= (others=>'0');
      data_line2 <= (others=>'0');
      data_line4 <= (others=>'0');
      data_line5 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      data_line1 <=(PAD2 & DATA_A1)
                 + (PAD3 & DATA_B1(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_C1(N - 1 downto 0) & '0') + (PAD2 & DATA_C1)
                 + (PAD3 & DATA_D1(N - 1 downto 0) & '0')
                 + (PAD2 & DATA_E1);
      data_line2 <=(PAD3 & DATA_A2(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_B2(N - 1 downto 0) & '0') + (PAD2 & DATA_B2)
                 + (PAD5 & DATA_C2(N - 1 downto 0) & "00")
                 + (PAD3 & DATA_D2(N - 1 downto 0) & '0') + (PAD2 & DATA_D2)
                 + (PAD3 & DATA_E2(N - 1 downto 0) & '0');
      data_line4 <=(PAD3 & DATA_A4(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_B4(N - 1 downto 0) & '0') + (PAD2 & DATA_B4)
                 + (PAD5 & DATA_C4(N - 1 downto 0) & "00")
                 + (PAD3 & DATA_D4(N - 1 downto 0) & '0') + (PAD2 & DATA_D4)
                 + (PAD3 & DATA_E4(N - 1 downto 0) & '0');
      data_line5 <=(PAD2 & DATA_A5)
                 + (PAD3 & DATA_B5(N - 1 downto 0) & '0')
                 + (PAD3 & DATA_C5(N - 1 downto 0) & '0') + (PAD2 & DATA_C5)
                 + (PAD3 & DATA_D5(N - 1 downto 0) & '0')
                 + (PAD2 & DATA_E5);
      DATA_OUT <= data_line1 + data_line2 - data_line4 - data_line5;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "00000";
      EOL_DEL    <= "00000";
      EOF_DEL    <= "00000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= "0000" & DVALID_IN;
      EOL_DEL    <= "0000" & EOL_IN;
      EOF_DEL    <= "0000" & EOF_IN;
      DVALID_OUT <= DVALID_DEL(0);
      EOL_OUT    <= EOL_DEL(0);
      EOF_OUT    <= EOF_DEL(0);
    end if;
  end process;
end generate;

laplacian: if (Kernel="Laplacian") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      data_line1 <= (others=>'0');
      data_line2 <= (others=>'0');
      data_line3 <= (others=>'0');
      data_line4 <= (others=>'0');
      data_line5 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      data_line1 <= (PAD2 & DATA_A1)
                  + (PAD3 & DATA_B1(N - 1 downto 0) & '0') + (PAD2 & DATA_B1)
                  + (PAD5 & DATA_C1(N - 1 downto 0) & "00")
                  + (PAD3 & DATA_D1(N - 1 downto 0) & '0') + (PAD2 & DATA_D1)
                  + (PAD2 & DATA_E1);
      data_line2 <= (PAD5 & DATA_C2(N - 1 downto 0) & "00") + (PAD3 & DATA_C2(N - 1 downto 0) & '0')
                  - (PAD3 & DATA_A2(N - 1 downto 0) & '0')  - (PAD2 & DATA_A2)
                  - (PAD3 & DATA_E2(N - 1 downto 0) & '0')  - (PAD2 & DATA_E2);
      data_line3 <= (PAD6 & DATA_C3(N - 1 downto 0) & "0000") + (PAD5 & DATA_C3(N - 1 downto 0) & "00")
                  - (PAD5 & DATA_A3(N - 1 downto 0) & "00")
                  + (PAD5 & DATA_B3(N - 1 downto 0) & "00") + (PAD3 & DATA_B3(N - 1 downto 0) & '0')
                  + (PAD5 & DATA_D3(N - 1 downto 0) & "00") + (PAD3 & DATA_D3(N - 1 downto 0) & '0')
                  - (PAD5 & DATA_E3(N - 1 downto 0) & "00");
      data_line4 <= (PAD5 & DATA_C4(N - 1 downto 0) & "00") + (PAD3 & DATA_C4(N - 1 downto 0) & '0')
                  - (PAD3 & DATA_A4(N - 1 downto 0) & '0')  - (PAD2 & DATA_A4)
                  - (PAD3 & DATA_E4(N - 1 downto 0) & '0')  - (PAD2 & DATA_E4);
      data_line5 <= (PAD2 & DATA_A5)
                  + (PAD3 & DATA_B5(N - 1 downto 0) & '0') + (PAD2 & DATA_B5)
                  + (PAD5 & DATA_C5(N - 1 downto 0) & "00")
                  + (PAD3 & DATA_D5(N - 1 downto 0) & '0') + (PAD2 & DATA_D5)
                  + (PAD2 & DATA_E5);
      DATA_OUT <= data_line2 + data_line3 + data_line4 - data_line1 - data_line5;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "00000";
      EOL_DEL    <= "00000";
      EOF_DEL    <= "00000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= "0000" & DVALID_IN;
      EOL_DEL    <= "0000" & EOL_IN;
      EOF_DEL    <= "0000" & EOF_IN;
      DVALID_OUT <= DVALID_DEL(0);
      EOL_OUT    <= EOL_DEL(0);
      EOF_OUT    <= EOF_DEL(0);
    end if;
  end process;
end generate;

end Behavioral;

-------------------------------------------------------------------------
--Frame Pad

library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity framePad5x5 is
  generic(
    N           : integer := 32;
    LINE_LENGTH : 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;
    EOL_IN     : in  std_logic;
    EOL_OUT    : out std_logic;
    EOF_IN     : in  std_logic;
    EOF_OUT    : out std_logic;
    CLOCK      : in  std_logic;
    RESET      : in  std_logic
  );
end framePad5x5;

architecture Behavioral of framePad5x5 is

  --Component output state machine
  type state_type is (A, B, C, D, E, F, G, H, I, J, K, L, M, O, P, Q, R);

  signal state            : state_type;
  signal outputPixelCount : std_logic_vector(11 downto 0);

  signal LineControlSelect  : std_logic_vector(1 downto 0);
  signal frameControlSelect : std_logic_vector(1 downto 0);
  signal DataControlSelect  : std_logic_vector(1 downto 0);
  signal DataSelect         : std_logic_vector(1 downto 0);

begin

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      state <= A;
    elsif rising_edge(CLOCK) then
      case state is
        when A => if (EOL_IN = '1') then state <= B;
                  else                   state <= A;
                  end if;
        when B => if (EOL_IN = '1') then state <= C;
                  else                   state <= B;
                  end if;
        when C => if (EOL_IN = '1') then state <= D;
                  else                   state <= C;
                  end if;
        when D => if (EOL_IN = '1') then state <= E;
                  else                   state <= D;
                  end if;
        when E => if    (EOF_IN = '1')    then state <= M;
                  elsif (DVALID_IN = '1') then state <= F;
                  else                         state <= E;
                  end if;
        when F => if (DVALID_IN = '1') then state <= G;
                  else                      state <= F;
                  end if;
        when G => if (DVALID_IN = '1') then state <= H;
                  else                      state <= G;
                  end if;
        when H => if (DVALID_IN = '1') then state <= I;
                  else                      state <= H;
                  end if;
        when I => if (EOL_IN = '1') then    state <= J;
                  else                      state <= I;
                  end if;
        when J => state <= K;
        when K => state <= L;
        when L => state <= E;
        when M => if(outputPixelCount = LINE_LENGTH - 1) then state <= O;
                  else                                        state <= M;
                  end if;
        when O => state <= P;
        when P => if(outputPixelCount = LINE_LENGTH - 1) then state <= Q;
                  else                                        state <= P;
                  end if;
        when Q => state <= R;
        when R => state <= A;
      end case;
    end if;
  end process;

  process (LineControlSelect, EOL_IN, DVALID_IN)
  begin
    case LineControlSelect is
      when "00"   => EOL_OUT <= '0';
      when "01"   => EOL_OUT <= '1';
      when "10"   => EOL_OUT <= EOL_IN;
      when "11"   => EOL_OUT <= DVALID_IN;
      when others => EOL_OUT <= '0';
    end case;
  end process;

  process (frameControlSelect, EOF_IN)
  begin
    case frameControlSelect is
      when "00"   => EOF_OUT <= '0';
      when "01"   => EOF_OUT <= '1';
      when "10"   => EOF_OUT <= EOF_IN;
      when "11"   => EOF_OUT <= EOF_IN;
      when others => EOF_OUT <= '0';
    end case;
  end process;

  process (DataControlSelect, DVALID_IN)
  begin
    case DataControlSelect is
      when "00"   => DVALID_OUT <= '0';
      when "01"   => DVALID_OUT <= '1';
      when "10"   => DVALID_OUT <= DVALID_IN;
      when "11"   => DVALID_OUT <= DVALID_IN;
      when others => DVALID_OUT <= '0';
    end case;
  end process;

  process (DataSelect, DATA_IN, outputPixelCount)
  begin
    case DataSelect is
      when "00"   => DATA_OUT <= (others=>'0');
      when "01"   => DATA_OUT <= (others=>'1');
      when "10"   => DATA_OUT <= DATA_IN;
      when "11"   => DATA_OUT <= "00000000000000000000" & outputPixelCount;
      when others => DATA_OUT <= (others=>'0');
    end case;
  end process;

  process(state)
  begin
    case state is
  -- Discard first line
      when A => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  -- Discard second line
      when B => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  --Output a line of zeros
      when C => LineControlSelect  <= "10";
                frameControlSelect <= "10";
                DataControlSelect  <= "10";
                DataSelect         <= "00";
  --Output a second line of zeros
      when D => LineControlSelect  <= "10";
                frameControlSelect <= "10";
                DataControlSelect  <= "10";
                DataSelect         <= "00";
  --Discard the first pixel of the line
      when E => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  --Discard the second pixel of the line
      when F => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  -- Change third pixel to a zero
      when G => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "10";
                DataSelect         <= "00";
  -- Change fourth pixel to a zero
      when H => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "10";
                DataSelect         <= "00";
  -- Output line of results
      when I => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "10";
                DataSelect         <= "10";
  --Output an extra pixel at the end of the line
      when J => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  --Output another extra pixel at the end of the line
      when K => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  -- Output EOL marker
      when L => LineControlSelect  <= "01";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  --Output a line of pixels
      when M => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  -- EOL marker
      when O => LineControlSelect  <= "01";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  --Output another line of pixels
      when P => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  -- EOL marker
      when Q => LineControlSelect  <= "01";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  -- EOF marker
      when R => LineControlSelect  <= "00";
                frameControlSelect <= "01";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
    end case;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      outputPixelCount <= (others=>'0');
    elsif rising_edge(CLOCK) then
      if (state=P or state=M) then
        outputPixelCount <= outputPixelCount + 1;
      else
        outputPixelCount <= (others=>'0');
      end if;
    end if;
  end process;

end Behavioral;

---------------------------------------------------------------------
--Storage

library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity spblockram5x5 is
  generic(
    N          : integer := 32;
    AddrN      : integer := 5;
    LINELENGTH : integer := 32
  );
  port (
    clk : in  std_logic;
    we  : in  std_logic;
    a   : in  std_logic_vector(AddrN - 1 downto 0);
    di  : in  std_logic_vector(N - 1 downto 0);
    do  : out std_logic_vector(N - 1 downto 0)
  ); 
end spblockram5x5;

architecture syn of spblockram5x5 is

  type ram_type is array (LINELENGTH - 1 downto 0) of std_logic_vector (N - 1 downto 0);

  signal RAM    : ram_type;
  signal read_a : std_logic_vector(AddrN - 1 downto 0);

begin

  process (clk)
  begin
    if rising_edge(clk) then
      if (we='1') then
        RAM(conv_integer(a)) <= di;
      end if;
      read_a <= a;
    end if;
  end process;

  do <= RAM(conv_integer(read_a));

end syn;

