-- ==============================================================
-- FILE : CONVOLVE3x3.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 : 3x3 Convolution
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     J. Maddocks    01-12-03    First Written
--
-- ==============================================================


-----------------------------------------------------------------
--
--  Pixels referenced throughout as:
--
--  A1 B1 C1
--  A2 B2 C2
--  A3 B3 C3
--
-----------------------------------------------------------------

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

entity convolve is
  generic (
    N              : integer := 32;
    LINE_LENGTH    : integer := 32;
    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_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_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);
    SHIFT      : in  std_logic_vector(3 downto 0);
    CLOCK      : in  std_logic;
    RESET      : in  std_logic
  );
end convolve;

architecture Behavioral of convolve is

  component dataSupply3x3 is
    generic (
      N              : integer := 32;
      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_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_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);
      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 dataMaths is
    generic (
      N      : integer := 32;
      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_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_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);
      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_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_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);
      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 framePad 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_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_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 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_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 EOL_D         : std_logic;
  signal EOF_D         : std_logic;
  signal DVALID_D      : std_logic;
  signal OVERFLOW      : std_logic;

begin

  idata : dataSupply3x3
    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_A2    => DATA_A2,
      DATA_B2    => DATA_B2,
      DATA_C2    => DATA_C2,
      DATA_A3    => DATA_A3,
      DATA_B3    => DATA_B3,
      DATA_C3    => DATA_C3,
      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 );

  idataMaths : dataMaths
    generic map(
      N      => N,
      Kernel => KERNEL )
    port map (
      DATA_A1    => DATA_A1,
      DATA_B1    => DATA_B1,
      DATA_C1    => DATA_C1,
      DATA_A2    => DATA_A2,
      DATA_B2    => DATA_B2,
      DATA_C2    => DATA_C2,
      DATA_A3    => DATA_A3,
      DATA_B3    => DATA_B3,
      DATA_C3    => DATA_C3,
      K_A1       => K_A1,
      K_A2       => K_A2,
      K_A3       => K_A3,
      K_B1       => K_B1,
      K_B2       => K_B2,
      K_B3       => K_B3,
      K_C1       => K_C1,
      K_C2       => K_C2,
      K_C3       => K_C3,
      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_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);

  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_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
            DATA_D;

  iframePad : framePad
    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 dataSupply3x3 is
  generic(
    N              : integer := 8;
    LINE_LENGTH    : integer := 384;
    RAM_ADDR_WIDTH : integer := 9
  );
  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_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_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);
    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 dataSupply3x3;

architecture Behavioral of dataSupply3x3 is

  component spblockram 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);

  signal state           : state_type;
  signal writeA          : std_logic;
  signal writeB          : std_logic;
  signal writeC          : 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 line1           : std_logic_vector((N * 3) - 1 downto 0);
  signal line2           : std_logic_vector((N * 3) - 1 downto 0);
  signal line3           : std_logic_vector((N * 3) - 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 <= A;
                  else                                 state <= C;
                  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';
      when B => writeA <= '0'; writeB <= DVALID_IN; writeC <= '0';
      when C => writeA <= '0'; writeB <= '0'; writeC <= DVALID_IN;
    end case;
  end process;

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

  DATA_A1 <= line1((N * 3) - 1 downto (N * 2));
  DATA_A2 <= line2((N * 3) - 1 downto (N * 2));
  DATA_A3 <= line3((N * 3) - 1 downto (N * 2));
  DATA_B1 <= line1((N * 2) - 1 downto N);
  DATA_B2 <= line2((N * 2) - 1 downto N);
  DATA_B3 <= line3((N * 2) - 1 downto N);
  DATA_C1 <= line1(N - 1 downto 0);
  DATA_C2 <= line2(N - 1 downto 0);
  DATA_C3 <= line3(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 : spblockram
    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 : spblockram
    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 : spblockram
    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 );

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 dataMaths is
  generic (
    N      : integer := 32;
    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_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_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);
    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_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_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);
    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 dataMaths;

architecture Behavioral of dataMaths is

  signal DVALID_DEL : std_logic_vector(2 downto 0);
  signal EOL_DEL    : std_logic_vector(2 downto 0);
  signal EOF_DEL    : std_logic_vector(2 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);

  --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_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_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);

  --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_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_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 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 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);

  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_B1 <= PAD & DATA_B1;
  CONV_B2 <= PAD & DATA_B2;
  CONV_B3 <= PAD & DATA_B3;
  CONV_C1 <= PAD & DATA_C1;
  CONV_C2 <= PAD & DATA_C2;
  CONV_C3 <= PAD & DATA_C3;

  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 );

  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 );

  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 );

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      RESULT_A <=(others=>'0');
      RESULT_B <=(others=>'0');
      RESULT_C <=(others=>'0');
      RESULT_G <=(others=>'0');
      RESULT_H <=(others=>'0');
      RESULT_I <=(others=>'0');
      RESULT_M <=(others=>'0');
      RESULT_N <=(others=>'0');
      RESULT_O <=(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_G <= '0' & MULT_B1(35) & MULT_B1(18 downto 0);
      RESULT_H <= '0' & MULT_B2(35) & MULT_B2(18 downto 0);
      RESULT_I <= '0' & MULT_B3(35) & MULT_B3(18 downto 0);
      RESULT_M <= '0' & MULT_C1(35) & MULT_C1(18 downto 0);
      RESULT_N <= '0' & MULT_C2(35) & MULT_C2(18 downto 0);
      RESULT_O <= '0' & MULT_C3(35) & MULT_C3(18 downto 0);
    end if;
  end process;

  RESULT_E <= '0' & RESULT_D(20) & RESULT_D(18 downto 0);

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

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

  RESULT_K <= '0' & RESULT_J(20) & RESULT_J(18 downto 0);

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

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

  RESULT_Q <= '0' & RESULT_P(20) & RESULT_P(18 downto 0);

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

  iADD_F : new_add
    port map (
      A => RESULT_O(19 downto 0),
      B => RESULT_Q(19 downto 0),
      S => RESULT_R(20 downto 0));

  RESULT_S <= '0' & DATA_LINE1(20) & DATA_LINE1(18 downto 0);
  RESULT_T <= '0' & DATA_LINE2(20) & DATA_LINE2(18 downto 0);
  RESULT_U <= '0' & DATA_LINE3(20) & DATA_LINE3(18 downto 0);

  RESULT_W <= '0' & RESULT_V(20) & RESULT_V(18 downto 0);

  iADD_G : new_add
    port map (
      A => RESULT_S(19 downto 0),
      B => RESULT_T(19 downto 0),
      S => RESULT_V(20 downto 0));

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

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DATA_LINE1    <=(others=>'0');
      DATA_LINE2    <=(others=>'0');
      DATA_LINE3    <=(others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= RESULT_F;
      DATA_LINE2 <= RESULT_L;
      DATA_LINE3 <= RESULT_R;
      DATA_OUT   <= RESULT_X;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "000";
      EOL_DEL    <= "000";
      EOF_DEL    <= "000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
  elsif rising_edge(CLOCK) then
      DVALID_DEL <= DVALID_IN & DVALID_DEL(2 downto 1);
      EOL_DEL    <= EOL_IN & EOL_DEL(2 downto 1);
      EOF_DEL    <= EOF_IN & EOF_DEL(2 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_LINE3 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD3 & (DATA_A2(N - 1 downto 0) & '0')) + (PAD2 & DATA_A3);
      DATA_LINE3 <= (PAD2 & DATA_C1) + (PAD3 & (DATA_C2(N - 1 downto 0) & '0')) + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE1 - DATA_LINE3;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "000";
      EOL_DEL    <= "000";
      EOF_DEL    <= "000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= "00" & DVALID_IN;
      EOL_DEL    <= "00" & EOL_IN;
      EOF_DEL    <= "00" & 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_LINE3 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD3 & (DATA_B1(N - 1 downto 0) & '0')) + (PAD2 & DATA_C1);
      DATA_LINE3 <= (PAD2 & DATA_A3) + (PAD3 & (DATA_B3(N - 1 downto 0) & '0')) + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE1 - DATA_LINE3;
    end if;
  end process;

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

vPrewitt : if (Kernel="vPrewitt") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DATA_LINE1 <= (others=>'0');
      DATA_LINE3 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD2 & DATA_A2) + (PAD2 & DATA_A3);
      DATA_LINE3 <= (PAD2 & DATA_C1) + (PAD2 & DATA_C2) + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE1 - DATA_LINE3;
    end if;
  end process;

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

hPrewitt : if (Kernel = "hPrewitt") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DATA_LINE1 <= (others=>'0');
      DATA_LINE3 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD2 & DATA_B1) + (PAD2 & DATA_C1);
      DATA_LINE3 <= (PAD2 & DATA_A3) + (PAD2 & DATA_B3) + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE1 - DATA_LINE3;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "000";
      EOL_DEL    <= "000";
      EOF_DEL    <= "000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= "00" & DVALID_IN;
      EOL_DEL    <= "00" & EOL_IN;
      EOF_DEL    <= "00" & 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');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD2 & DATA_B1) + (PAD2 & DATA_C1);
      DATA_LINE2 <= (PAD4 & DATA_B2(N - 1 downto 0) & "000") - (PAD2 & DATA_A2) - (PAD2 & DATA_C2);
      DATA_LINE3 <= (PAD2 & DATA_A3) + (PAD2 & DATA_B3) + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE2 - DATA_LINE1 - DATA_LINE3;
    end if;
  end process;

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

LPFilter : if (Kernel="LPFilter") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DATA_LINE1 <= (others=>'0');
      DATA_LINE2 <= (others=>'0');
      DATA_LINE3 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD3 & DATA_B1(N - 1 downto 0) & '0') + (PAD2 & DATA_C1);
      DATA_LINE2 <= (PAD3 & DATA_A2(N - 1 downto 0) & '0') + (PAD5 & DATA_B2(N - 1 downto 0) & "00") + (PAD3 & DATA_C2(N -1 downto 0) & '0');
      DATA_LINE3 <= (PAD2 & DATA_A3) + (PAD3 & DATA_B3(N - 1 downto 0) & '0') + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE1 + DATA_LINE2 + DATA_LINE3;
    end if;
  end process;

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

Sharpen : if (Kernel="Sharpen") generate
  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DATA_LINE1 <= (others=>'0');
      DATA_LINE2 <= (others=>'0');
      DATA_LINE3 <= (others=>'0');
    elsif rising_edge(CLOCK) then
      DATA_LINE1 <= (PAD2 & DATA_A1) + (PAD2 & DATA_B1) + (PAD2 & DATA_C1);
      DATA_LINE2 <= (PAD6 & DATA_B2(N - 1 downto 0) & "0000") - (PAD2 & DATA_A2) - (PAD2 & DATA_C2);
      DATA_LINE3 <= (PAD2 & DATA_A3) + (PAD2 & DATA_B3) + (PAD2 & DATA_C3);
      DATA_OUT   <= DATA_LINE2 - DATA_LINE1 - DATA_LINE3;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET='1' then
      DVALID_DEL <= "000";
      EOL_DEL    <= "000";
      EOF_DEL    <= "000";
      DVALID_OUT <= '0';
      EOL_OUT    <= '0';
      EOF_OUT    <= '0';
    elsif rising_edge(CLOCK) then
      DVALID_DEL <= "00" & DVALID_IN;
      EOL_DEL    <= "00" & EOL_IN;
      EOF_DEL    <= "00" & 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 framePad 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 framePad;

architecture Behavioral of framePad is

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

  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 (EOF_IN = '1') then state <= J;
                  elsif (DVALID_IN = '1') then state <= D;
                  else                      state <= C;
                  end if;
        when D => if (DVALID_IN = '1') then state <= E;
                  else                      state <= D;
                  end if;
        when E => if    (EOF_IN = '1') then state <= H;
                  elsif (EOL_IN = '1') then state <= F;
                  else                      state <= E;
                  end if;
        when F => if EOF_IN = '1' then state <= I;
                  else state <= G;
                  end if;
        when G => if EOF_IN = '1' then state <= J;
                  else state <= C;
                  end if;
  --Output a zero (turned into a one by pack sync)
        when H => state <= I;
  --Output an EOL marker
        when I => state <= J;
  --Output a line of zeros (turned into ones by pack sync)
        when J => if(outputPixelCount = (LINE_LENGTH - 1)) then state <= K;
                  else                                          state <= J;
                  end if;
  --Output EOF marker
        when K => state <= L;
        when L => 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";
  --Output a line of zeros
      when B => LineControlSelect  <= "10";
                frameControlSelect <= "10";
                DataControlSelect  <= "10";
                DataSelect         <= "00";
  --Discard the first pixel of the line
      when C => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  -- Change second pixel to a zero
      when D => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "10";
                DataSelect         <= "00";
  -- Output line of results
      when E => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "10";
                DataSelect         <= "10";
  --Output an extra one at the end of the line
      when F => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  -- Output EOL marker
      when G => LineControlSelect  <= "01";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  --Output zero at the end of the line
      when H => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  -- EOL marker
      when I => LineControlSelect  <= "01";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  --  Line of zeros
      when J => LineControlSelect  <= "00";
                frameControlSelect <= "00";
                DataControlSelect  <= "01";
                DataSelect         <= "00";
  -- EOL marker
      when K => LineControlSelect  <= "01";
                frameControlSelect <= "00";
                DataControlSelect  <= "00";
                DataSelect         <= "00";
  -- EOF marker
      when L => 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 = J) 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 spblockram 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 spblockram;

architecture syn of spblockram 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;

