-- ==============================================================
-- FILE : CAMLINK_HSB.VHD  -  May be modified by the USER
-- ==============================================================
--
-- This file is part of the CameraLink IP for HERON-FPGA modules.
--
-- This file can be copied into a new project and modified by the
-- user to implement their own logic.
--
-- ==============================================================
--
--  Date        : 12/06/2006
--  Author      : R. Williams - HUNT ENGINEERING
--  Description : HUNT Message Interface for camera control
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     R. Williams    12-06-06    Developed from previous
--                                     Camera Link examples.
--  3.1     R. Williams    07-09-07    Changes to CamLink_IF.vhd
--                                     to ensure correct operation
--                                     under ISE9.1.
--
-- ==============================================================


LIBRARY IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.std_logic_arith.all;
  use IEEE.numeric_std.all;
  use IEEE.std_logic_unsigned.all;


entity CAMLINK_HSB is
  port (
    RESET           : in  std_logic;
    CLOCK           : in  std_logic;
    PIXEL_CLOCK     : in  std_logic;
    DIN             : in  std_logic_vector(7 downto 0);
    ADDR            : in  std_logic_vector(7 downto 0);
    AEN             : in  std_logic;
    WEN             : in  std_logic;
    REN             : in  std_logic;
    DONE            : in  std_logic;
    COUNT           : in  std_logic;
    CLEAR           : in  std_logic;
    READY           : out std_logic;
    SEND_MSG        : out std_logic;
    CE              : out std_logic;
    DOUT            : out std_logic_vector(7 downto 0);
    SEND_ID         : out std_logic;
    LAST_BYTE       : out std_logic;
    M4_X_8          : out std_logic;
    M2_X_16         : out std_logic;
    M1_X_32         : out std_logic;
    BIT_SEL         : out std_logic_vector(1 downto 0);
    CP_SEL          : out std_logic;
    CONTINUOUS      : out std_logic;
    ODD_ONLY        : out std_logic;
    LOAD            : out std_logic;
    FRAMES          : out std_logic_vector(3 downto 0);
    AUTO_RES        : out std_logic;
    POLARITY        : out std_logic;
    USE_DVAL        : out std_logic;
    CAM_INPUTS      : out std_logic_vector(3 downto 0);
    START_PIXEL     : out std_logic_vector(11 downto 0);
    STOP_PIXEL      : out std_logic_vector(11 downto 0);
    START_LINE      : out std_logic_vector(11 downto 0);
    STOP_LINE       : out std_logic_vector(11 downto 0);
    OUTFIFO_SEL     : out std_logic_vector(5 downto 0);
    TX              : out std_logic;
    RX              : in  std_logic;
    PIXEL_TOTAL     : in  std_logic_vector(11 downto 0);
    LINE_TOTAL      : in  std_logic_vector(11 downto 0);
    FIRST_PIXEL     : in  std_logic_vector(11 downto 0);
    LAST_PIXEL      : in  std_logic_vector(11 downto 0);
    FIRST_LINE      : in  std_logic_vector(11 downto 0);
    LAST_LINE       : in  std_logic_vector(11 downto 0);
    ACTIVE          : in  std_logic_vector(3 downto 0);
    ROI_VALID       : in  std_logic;
    IMAGE_BLOCK_SEL : out std_logic_vector(7 downto 0);
    CAT1_CONST      : out std_logic_vector(7 downto 0);
    EOF_A           : in  std_logic;
    K_A1            : out std_logic_vector(7 downto 0);
    K_A2            : out std_logic_vector(7 downto 0);
    K_A3            : out std_logic_vector(7 downto 0);
    K_A4            : out std_logic_vector(7 downto 0);
    K_A5            : out std_logic_vector(7 downto 0);
    K_B1            : out std_logic_vector(7 downto 0);
    K_B2            : out std_logic_vector(7 downto 0);
    K_B3            : out std_logic_vector(7 downto 0);
    K_B4            : out std_logic_vector(7 downto 0);
    K_B5            : out std_logic_vector(7 downto 0);
    K_C1            : out std_logic_vector(7 downto 0);
    K_C2            : out std_logic_vector(7 downto 0);
    K_C3            : out std_logic_vector(7 downto 0);
    K_C4            : out std_logic_vector(7 downto 0);
    K_C5            : out std_logic_vector(7 downto 0);
    K_D1            : out std_logic_vector(7 downto 0);
    K_D2            : out std_logic_vector(7 downto 0);
    K_D3            : out std_logic_vector(7 downto 0);
    K_D4            : out std_logic_vector(7 downto 0);
    K_D5            : out std_logic_vector(7 downto 0);
    K_E1            : out std_logic_vector(7 downto 0);
    K_E2            : out std_logic_vector(7 downto 0);
    K_E3            : out std_logic_vector(7 downto 0);
    K_E4            : out std_logic_vector(7 downto 0);
    K_E5            : out std_logic_vector(7 downto 0);
    SHIFT           : out std_logic_vector(3 downto 0)
  );
end CAMLINK_HSB;


architecture RTL of CAMLINK_HSB is

  component RS232_UART
    port (
      RESET     : in  std_logic;
      CLOCK     : in  std_logic;
      DIN       : in  std_logic_vector(7 downto 0);
      BAUD_SEL  : in  std_logic_vector(3 downto 0);
      STOP_BITS : in  std_logic_vector(1 downto 0);
      RX        : in  std_logic;
      READ      : in  std_logic;
      WRITE     : in  std_logic;
      DOUT      : out std_logic_vector(7 downto 0);
      TX        : out std_logic;
      RX_EMPTY  : out std_logic;
      TX_FULL   : out std_logic;
      RX_COUNT  : out std_logic_vector(7 downto 0);
      TX_COUNT  : out std_logic_vector(7 downto 0));
  end component;

  signal FIFO_REG     : std_logic_vector(7 downto 0) := "00000000";

  signal E            : std_logic_vector(7 downto 0);
  signal EN           : std_logic_vector(7 downto 0);
  signal LC           : std_logic_vector(1 downto 0);
  signal LOAD_CTRL    : std_logic_vector(1 downto 0);
  signal LFN          : std_logic;
  signal LOAD_FIFO_NO : std_logic;
  signal LM           : std_logic;
  signal LOAD_MODE    : std_logic;
  signal LTX          : std_logic;
  signal LOAD_TX      : std_logic;
  signal LBD          : std_logic;
  signal LOAD_BD      : std_logic;
  signal RRX          : std_logic;
  signal READ_RX      : std_logic;

  signal READYc       : std_logic;
  signal REN_DELAY    : std_logic;
  signal WEN_DELAY    : std_logic;
  signal SINGLE_REN   : std_logic;
  signal SINGLE_WEN   : std_logic;

  signal UPDATE_COUNT : std_logic;
  signal UPDATE_DONE  : std_logic;
  signal CONT         : std_logic;

  signal BAUD_SEL     : std_logic_vector(3 downto 0);
  signal STOP_BITS    : std_logic_vector(1 downto 0);
  signal RS232_DATA   : std_logic_vector(7 downto 0);
  signal TX_FULL      : std_logic;
  signal RX_EMPTY     : std_logic;
  signal TX_COUNT     : std_logic_vector(7 downto 0);
  signal RX_COUNT     : std_logic_vector(7 downto 0);

  signal PIXELS       : std_logic_vector(7 downto 0);
  signal LINES        : std_logic_vector(7 downto 0);
  signal RS232        : std_logic_vector(7 downto 0);
  signal SIZE         : std_logic_vector(7 downto 0);

  signal BLOCK_SEL_WR : std_logic;
  signal BLOCK_SEL    : std_logic;
  signal BLOCK_REG    : std_logic_vector(7 downto 0);
  signal CAT1_CONST_WR: std_logic;
  signal CAT1_CONST_SEL : std_logic;
  signal CAT1_CONST_REG : std_logic_vector(7 downto 0);

  signal K_A1_CONST_WR  : std_logic;
  signal K_A1_CONST_SEL : std_logic;
  signal K_A1_CONST_REG : std_logic_vector(7 downto 0);
  signal K_A2_CONST_WR  : std_logic;
  signal K_A2_CONST_SEL : std_logic;
  signal K_A2_CONST_REG : std_logic_vector(7 downto 0);
  signal K_A3_CONST_WR  : std_logic;
  signal K_A3_CONST_SEL : std_logic;
  signal K_A3_CONST_REG : std_logic_vector(7 downto 0);
  signal K_A4_CONST_WR  : std_logic;
  signal K_A4_CONST_SEL : std_logic;
  signal K_A4_CONST_REG : std_logic_vector(7 downto 0);
  signal K_A5_CONST_WR  : std_logic;
  signal K_A5_CONST_SEL : std_logic;
  signal K_A5_CONST_REG : std_logic_vector(7 downto 0);
  signal K_B1_CONST_WR  : std_logic;
  signal K_B1_CONST_SEL : std_logic;
  signal K_B1_CONST_REG : std_logic_vector(7 downto 0);
  signal K_B2_CONST_WR  : std_logic;
  signal K_B2_CONST_SEL : std_logic;
  signal K_B2_CONST_REG : std_logic_vector(7 downto 0);
  signal K_B3_CONST_WR  : std_logic;
  signal K_B3_CONST_SEL : std_logic;
  signal K_B3_CONST_REG : std_logic_vector(7 downto 0);
  signal K_B4_CONST_WR  : std_logic;
  signal K_B4_CONST_SEL : std_logic;
  signal K_B4_CONST_REG : std_logic_vector(7 downto 0);
  signal K_B5_CONST_WR  : std_logic;
  signal K_B5_CONST_SEL : std_logic;
  signal K_B5_CONST_REG : std_logic_vector(7 downto 0);
  signal K_C1_CONST_WR  : std_logic;
  signal K_C1_CONST_SEL : std_logic;
  signal K_C1_CONST_REG : std_logic_vector(7 downto 0);
  signal K_C2_CONST_WR  : std_logic;
  signal K_C2_CONST_SEL : std_logic;
  signal K_C2_CONST_REG : std_logic_vector(7 downto 0);
  signal K_C3_CONST_WR  : std_logic;
  signal K_C3_CONST_SEL : std_logic;
  signal K_C3_CONST_REG : std_logic_vector(7 downto 0);
  signal K_C4_CONST_WR  : std_logic;
  signal K_C4_CONST_SEL : std_logic;
  signal K_C4_CONST_REG : std_logic_vector(7 downto 0);
  signal K_C5_CONST_WR  : std_logic;
  signal K_C5_CONST_SEL : std_logic;
  signal K_C5_CONST_REG : std_logic_vector(7 downto 0);
  signal K_D1_CONST_WR  : std_logic;
  signal K_D1_CONST_SEL : std_logic;
  signal K_D1_CONST_REG : std_logic_vector(7 downto 0);
  signal K_D2_CONST_WR  : std_logic;
  signal K_D2_CONST_SEL : std_logic;
  signal K_D2_CONST_REG : std_logic_vector(7 downto 0);
  signal K_D3_CONST_WR  : std_logic;
  signal K_D3_CONST_SEL : std_logic;
  signal K_D3_CONST_REG : std_logic_vector(7 downto 0);
  signal K_D4_CONST_WR  : std_logic;
  signal K_D4_CONST_SEL : std_logic;
  signal K_D4_CONST_REG : std_logic_vector(7 downto 0);
  signal K_D5_CONST_WR  : std_logic;
  signal K_D5_CONST_SEL : std_logic;
  signal K_D5_CONST_REG : std_logic_vector(7 downto 0);
  signal K_E1_CONST_WR  : std_logic;
  signal K_E1_CONST_SEL : std_logic;
  signal K_E1_CONST_REG : std_logic_vector(7 downto 0);
  signal K_E2_CONST_WR  : std_logic;
  signal K_E2_CONST_SEL : std_logic;
  signal K_E2_CONST_REG : std_logic_vector(7 downto 0);
  signal K_E3_CONST_WR  : std_logic;
  signal K_E3_CONST_SEL : std_logic;
  signal K_E3_CONST_REG : std_logic_vector(7 downto 0);
  signal K_E4_CONST_WR  : std_logic;
  signal K_E4_CONST_SEL : std_logic;
  signal K_E4_CONST_REG : std_logic_vector(7 downto 0);
  signal K_E5_CONST_WR  : std_logic;
  signal K_E5_CONST_SEL : std_logic;
  signal K_E5_CONST_REG : std_logic_vector(7 downto 0);
  signal SHIFT_SEL      : std_logic;
  signal SHIFT_WR       : std_logic;
  signal SHIFT_REG      : std_logic_vector(3 downto 0);
  signal PERF_SEL       : std_logic;
  signal CLEAR_PERF     : std_logic;
  signal CLEAR_HOLD     : std_logic;
  signal CLEAR_DEL1     : std_logic;
  signal CLEAR_DEL2     : std_logic;
  signal FrameCount     : std_logic_vector(15 downto 0);

begin

  SEND_MSG  <= '0';
  CE        <= '0';
  SEND_ID   <= '0';
  LAST_BYTE <= '0';

  OUTFIFO_SEL <= FIFO_REG(5 downto 0);

  process(ADDR(1 downto 0), FIRST_PIXEL, LAST_PIXEL, ROI_VALID)
  begin
    case ADDR(1 downto 0) is
      when "00"   => PIXELS <= FIRST_PIXEL(7 downto 0);
      when "01"   => PIXELS <= ROI_VALID & "000" & FIRST_PIXEL(11 downto 8);
      when "10"   => PIXELS <= LAST_PIXEL(7 downto 0);
      when "11"   => PIXELS <= ROI_VALID & "000" & LAST_PIXEL(11 downto 8);
      when others => PIXELS <= FIRST_PIXEL(7 downto 0);
    end case;
  end process;

  process(ADDR(1 downto 0), FIRST_LINE, LAST_LINE, ACTIVE)
  begin
    case ADDR(1 downto 0) is
      when "00"   => LINES <= FIRST_LINE(7 downto 0);
      when "01"   => LINES <= ACTIVE & FIRST_LINE(11 downto 8);
      when "10"   => LINES <= LAST_LINE(7 downto 0);
      when "11"   => LINES <= ACTIVE & LAST_LINE(11 downto 8);
      when others => LINES <= FIRST_LINE(7 downto 0);
    end case;
  end process;

  process(ADDR(1 downto 0), TX_COUNT, RX_COUNT, RS232_DATA)
  begin
    case ADDR(1 downto 0) is
      when "01"   => RS232 <= TX_COUNT;
      when "10"   => RS232 <= RS232_DATA;
      when "11"   => RS232 <= RX_COUNT;
      when others => RS232 <= TX_COUNT;
    end case;
  end process;

  process(ADDR(1 downto 0), PIXEL_TOTAL, LINE_TOTAL)
  begin
    case ADDR(1 downto 0) is
      when "00"   => SIZE <= PIXEL_TOTAL(7 downto 0);
      when "01"   => SIZE <= "0000" & PIXEL_TOTAL(11 downto 8);
      when "10"   => SIZE <= LINE_TOTAL(7 downto 0);
      when "11"   => SIZE <= "0000" & LINE_TOTAL(11 downto 8);
      when others => SIZE <= PIXEL_TOTAL(7 downto 0);
    end case;
  end process;

  process(ADDR(4 downto 2), PIXELS, LINES, RS232, SIZE, FrameCount)
  begin
    case ADDR(4 downto 2) is
      when "000"  => DOUT <= PIXELS;
      when "001"  => DOUT <= LINES;
      when "011"  => DOUT <= RS232;
      when "100"  => DOUT <= SIZE;
      when "101"  => DOUT <= FrameCount(7 downto 0);
      when "110"  => DOUT <= FrameCount(15 downto 8);
      when others => DOUT <= PIXELS;
    end case;
  end process;

  -- Decode address & output mux
  process(ADDR)
  begin
    E   <= (others=>'0');
    LC  <= (others=>'0');
    LFN <= '0';
    LM  <= '0';
    LTX <= '0';
    LBD <= '0';
    RRX <= '0';
    CAT1_CONST_SEL <= '0';
    BLOCK_SEL      <= '0';
    PERF_SEL       <= '0';
    K_A1_CONST_SEL <= '0';
    K_A2_CONST_SEL <= '0';
    K_A3_CONST_SEL <= '0';
    K_A4_CONST_SEL <= '0';
    K_A5_CONST_SEL <= '0';
    K_B1_CONST_SEL <= '0';
    K_B2_CONST_SEL <= '0';
    K_B3_CONST_SEL <= '0';
    K_B4_CONST_SEL <= '0';
    K_B5_CONST_SEL <= '0';
    K_C1_CONST_SEL <= '0';
    K_C2_CONST_SEL <= '0';
    K_C3_CONST_SEL <= '0';
    K_C4_CONST_SEL <= '0';
    K_C5_CONST_SEL <= '0';
    K_D1_CONST_SEL <= '0';
    K_D2_CONST_SEL <= '0';
    K_D3_CONST_SEL <= '0';
    K_D4_CONST_SEL <= '0';
    K_D5_CONST_SEL <= '0';
    K_E1_CONST_SEL <= '0';
    K_E2_CONST_SEL <= '0';
    K_E3_CONST_SEL <= '0';
    K_E4_CONST_SEL <= '0';
    K_E5_CONST_SEL <= '0';
    SHIFT_SEL      <= '0';
    case ADDR is
      when "00000000" => E(0)  <= '1';
      when "00000001" => E(1)  <= '1';
      when "00000010" => E(2)  <= '1';
      when "00000011" => E(3)  <= '1';
      when "00000100" => E(4)  <= '1';
      when "00000101" => E(5)  <= '1';
      when "00000110" => E(6)  <= '1';
      when "00000111" => E(7)  <= '1';
      when "00001000" => LC(0) <= '1';
      when "00001001" => LC(1) <= '1';
      when "00001010" => LFN   <= '1';
      when "00001011" => LM    <= '1';
      when "00001100" => LBD   <= '1';
      when "00001101" => LTX   <= '1';
      when "00001110" => RRX   <= '1';
      when "00010001" => BLOCK_SEL      <= '1';
      when "00010010" => CAT1_CONST_SEL <= '1';
      when "00010011" => K_A1_CONST_SEL <= '1';
      when "00010100" => K_A2_CONST_SEL <= '1';
      when "00010101" => K_A3_CONST_SEL <= '1';
      when "00010110" => K_A4_CONST_SEL <= '1';
      when "00010111" => K_A5_CONST_SEL <= '1';
      when "00011000" => K_B1_CONST_SEL <= '1'; PERF_SEL <= '1';
      when "00011001" => K_B2_CONST_SEL <= '1';
      when "00011010" => K_B3_CONST_SEL <= '1';
      when "00011011" => K_B4_CONST_SEL <= '1';
      when "00011100" => K_B5_CONST_SEL <= '1';
      when "00011101" => K_C1_CONST_SEL <= '1';
      when "00011110" => K_C2_CONST_SEL <= '1';
      when "00011111" => K_C3_CONST_SEL <= '1';
      when "00100000" => K_C4_CONST_SEL <= '1';
      when "00100001" => K_C5_CONST_SEL <= '1';
      when "00100010" => K_D1_CONST_SEL <= '1';
      when "00100011" => K_D2_CONST_SEL <= '1';
      when "00100100" => K_D3_CONST_SEL <= '1';
      when "00100101" => K_D4_CONST_SEL <= '1';
      when "00100110" => K_D5_CONST_SEL <= '1';
      when "00100111" => K_E1_CONST_SEL <= '1';
      when "00101000" => K_E2_CONST_SEL <= '1';
      when "00101001" => K_E3_CONST_SEL <= '1';
      when "00101010" => K_E4_CONST_SEL <= '1';
      when "00101011" => K_E5_CONST_SEL <= '1';
      when "00101100" => SHIFT_SEL      <= '1';
      when others     => null;
    end case;
  end process;

  SHIFT_WR      <= SHIFT_SEL AND WEN;
  BLOCK_SEL_WR  <= BLOCK_SEL AND WEN;
  CAT1_CONST_WR <= CAT1_CONST_SEL AND WEN;
  K_A1_CONST_WR <= K_A1_CONST_SEL AND WEN;
  K_A2_CONST_WR <= K_A2_CONST_SEL AND WEN;
  K_A3_CONST_WR <= K_A3_CONST_SEL AND WEN;
  K_A4_CONST_WR <= K_A4_CONST_SEL AND WEN;
  K_A5_CONST_WR <= K_A5_CONST_SEL AND WEN;
  K_B1_CONST_WR <= K_B1_CONST_SEL AND WEN;
  K_B2_CONST_WR <= K_B2_CONST_SEL AND WEN;
  K_B3_CONST_WR <= K_B3_CONST_SEL AND WEN;
  K_B4_CONST_WR <= K_B4_CONST_SEL AND WEN;
  K_B5_CONST_WR <= K_B5_CONST_SEL AND WEN;
  K_C1_CONST_WR <= K_C1_CONST_SEL AND WEN;
  K_C2_CONST_WR <= K_C2_CONST_SEL AND WEN;
  K_C3_CONST_WR <= K_C3_CONST_SEL AND WEN;
  K_C4_CONST_WR <= K_C4_CONST_SEL AND WEN;
  K_C5_CONST_WR <= K_C5_CONST_SEL AND WEN;
  K_D1_CONST_WR <= K_D1_CONST_SEL AND WEN;
  K_D2_CONST_WR <= K_D2_CONST_SEL AND WEN;
  K_D3_CONST_WR <= K_D3_CONST_SEL AND WEN;
  K_D4_CONST_WR <= K_D4_CONST_SEL AND WEN;
  K_D5_CONST_WR <= K_D5_CONST_SEL AND WEN;
  K_E1_CONST_WR <= K_E1_CONST_SEL AND WEN;
  K_E2_CONST_WR <= K_E2_CONST_SEL AND WEN;
  K_E3_CONST_WR <= K_E3_CONST_SEL AND WEN;
  K_E4_CONST_WR <= K_E4_CONST_SEL AND WEN;
  K_E5_CONST_WR <= K_E5_CONST_SEL AND WEN;

  EN(0) <= E(0) AND WEN;
  EN(1) <= E(1) AND WEN;
  EN(2) <= E(2) AND WEN;
  EN(3) <= E(3) AND WEN;
  EN(4) <= E(4) AND WEN;
  EN(5) <= E(5) AND WEN;
  EN(6) <= E(6) AND WEN;
  EN(7) <= E(7) AND WEN;

  LOAD_CTRL(0) <= LC(0) AND WEN;
  LOAD_CTRL(1) <= LC(1) AND WEN;

  LOAD_FIFO_NO <= LFN AND WEN;

  LOAD_MODE <= LM AND WEN;

  LOAD_TX <= LTX AND SINGLE_WEN;

  LOAD_BD <= LBD AND WEN;

  READ_RX <= RRX AND SINGLE_REN;

  CLEAR_PERF <= PERF_SEL AND SINGLE_REN;

  process (RESET, CLOCK)
  begin
    if RESET='1' then
      REN_DELAY  <= '0';
      WEN_DELAY  <= '0';
      SINGLE_REN <= '0';
      SINGLE_WEN <= '0';
    elsif rising_edge(CLOCK) then
      REN_DELAY  <= REN;
      WEN_DELAY  <= WEN;
      SINGLE_REN <= '0';
      SINGLE_WEN <= '0';
      if REN_DELAY='1' and REN='0' then
        SINGLE_REN <= '1';
      end if;
      if WEN_DELAY='1' and WEN='0' then
        SINGLE_WEN <= '1';
      end if;
    end if;
  end process;

  -- DATA_REG
  process (CLOCK)
  begin
    if rising_edge(CLOCK) then
      if LOAD_FIFO_NO='1' then
        FIFO_REG <= DIN;
      end if;
    end if;
  end process;

  -- READY
  READYc <= (REN AND (NOT (RRX AND RX_EMPTY))) OR
            (WEN AND (NOT (LTX AND TX_FULL)));

  process (RESET, CLOCK)
  begin
    if RESET='1' then
      READY <= '1';
    elsif rising_edge(CLOCK) then
      READY <= READYc;
    end if;
  end process;

  -- Pixel start position
  process(RESET, CLOCK)
  begin
    if RESET='1' then
      START_PIXEL <= (others=>'0');
    elsif rising_edge(CLOCK) then
      if EN(0)='1' then
        START_PIXEL(7 downto 0)  <= DIN;
      end if;
      if EN(1)='1' then
        START_PIXEL(11 downto 8) <= DIN(3 downto 0);
      end if;
    end if;
  end process;

  -- Pixel stop position
  process(RESET, CLOCK)
  begin
    if RESET='1' then
      STOP_PIXEL <= "000001111111";
    elsif rising_edge(CLOCK) then
      if EN(2)='1' then
        STOP_PIXEL(7 downto 0)  <= DIN;
      end if;
      if EN(3)='1' then
        STOP_PIXEL(11 downto 8) <= DIN(3 downto 0);
      end if;
    end if;
  end process;

  -- Line start position
  process(RESET, CLOCK)
  begin
    if RESET='1' then
      START_LINE <= (others=>'0');
    elsif rising_edge(CLOCK) then
      if EN(4)='1' then
        START_LINE(7 downto 0)  <= DIN;
      end if;
      if EN(5)='1' then
        START_LINE(11 downto 8) <= DIN(3 downto 0);
      end if;
    end if;
  end process;

  -- Line stop position
  process(RESET, CLOCK)
  begin
    if RESET='1' then
      STOP_LINE <= "000001111111";
    elsif rising_edge(CLOCK) then
      if EN(6)='1' then
        STOP_LINE(7 downto 0)  <= DIN;
      end if;
      if EN(7)='1' then
        STOP_LINE(11 downto 8) <= DIN(3 downto 0);
      end if;
    end if;
  end process;

  -- Number of Frames control
  process(RESET, CLOCK)
  begin
    if RESET='1' then
      UPDATE_COUNT <= '0';
    elsif rising_edge(CLOCK) then
      UPDATE_COUNT <= '0';
      if (LC(0)='1' and WEN='1') or (UPDATE_COUNT='1' and UPDATE_DONE='0') then
        UPDATE_COUNT <= '1';
      end if;
    end if;
  end process;

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if (LC(0)='1' and WEN='1') then
        FRAMES <= DIN(3 downto 0);
      end if;
    end if;
  end process;

  process(RESET, PIXEL_CLOCK)
  begin
    if RESET='1' then
      UPDATE_DONE <= '0';
      LOAD        <= '0';
    elsif rising_edge(PIXEL_CLOCK) then
      UPDATE_DONE <= UPDATE_COUNT;
      LOAD        <= UPDATE_DONE;
      CONTINUOUS  <= CONT;
    end if;
  end process;

  -- General control bits
  process(RESET, CLOCK)
  begin
    if RESET='1' then
      CONT    <= '0';
      M4_X_8  <= '1';
      M2_X_16 <= '0';
      M1_X_32 <= '0';
      BIT_SEL <= "00";
      CP_SEL  <= '0';
    elsif rising_edge(CLOCK) then
      if LOAD_CTRL(0)='1' then
        CONT    <= DIN(4);
      end if;
      if LOAD_MODE='1' then
        M1_X_32 <= DIN(0);
        M2_X_16 <= DIN(1);
        M4_X_8  <= DIN(2);
        BIT_SEL <= DIN(5 downto 4);
        CP_SEL  <= DIN(7);
      end if;
    end if;
  end process;

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if LOAD_CTRL(1)='1' then
        CAM_INPUTS <= DIN(3 downto 0);
        ODD_ONLY   <= DIN(4);
        POLARITY   <= DIN(5);
        USE_DVAL   <= DIN(6);
        AUTO_RES   <= DIN(7);
      end if;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET = '1' then
      BLOCK_REG <= "00000000";
    elsif rising_edge(CLOCK) then
      if BLOCK_SEL_WR = '1' then
        BLOCK_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;

  process(CLOCK, RESET)
  begin
    if RESET = '1' then
      SHIFT_REG <= "0000";
    elsif rising_edge(CLOCK) then
      if SHIFT_WR = '1' then
        SHIFT_REG <= DIN(3 downto 0);
      end if;
    end if;
  end process;

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if CAT1_CONST_WR = '1' then
        CAT1_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;

  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_A1_CONST_WR = '1' then
        K_A1_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_A2_CONST_WR = '1' then
        K_A2_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_A3_CONST_WR = '1' then
        K_A3_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_A4_CONST_WR = '1' then
        K_A4_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_A5_CONST_WR = '1' then
        K_A5_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_B1_CONST_WR = '1' then
        K_B1_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_B2_CONST_WR = '1' then
        K_B2_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_B3_CONST_WR = '1' then
        K_B3_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_B4_CONST_WR = '1' then
        K_B4_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_B5_CONST_WR = '1' then
        K_B5_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_C1_CONST_WR = '1' then
        K_C1_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_C2_CONST_WR = '1' then
        K_C2_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_C3_CONST_WR = '1' then
        K_C3_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_C4_CONST_WR = '1' then
        K_C4_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_C5_CONST_WR = '1' then
        K_C5_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_D1_CONST_WR = '1' then
        K_D1_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_D2_CONST_WR = '1' then
        K_D2_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_D3_CONST_WR = '1' then
        K_D3_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_D4_CONST_WR = '1' then
        K_D4_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_D5_CONST_WR = '1' then
        K_D5_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_E1_CONST_WR = '1' then
        K_E1_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_E2_CONST_WR = '1' then
        K_E2_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_E3_CONST_WR = '1' then
        K_E3_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_E4_CONST_WR = '1' then
        K_E4_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;
  process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if K_E5_CONST_WR = '1' then
        K_E5_CONST_REG <= DIN(7 downto 0);
      end if;
    end if;
  end process;

  K_A1 <= K_A1_CONST_REG;
  K_A2 <= K_A2_CONST_REG;
  K_A3 <= K_A3_CONST_REG;
  K_A4 <= K_A4_CONST_REG;
  K_A5 <= K_A5_CONST_REG;
  K_B1 <= K_B1_CONST_REG;
  K_B2 <= K_B2_CONST_REG;
  K_B3 <= K_B3_CONST_REG;
  K_B4 <= K_B4_CONST_REG;
  K_B5 <= K_B5_CONST_REG;
  K_C1 <= K_C1_CONST_REG;
  K_C2 <= K_C2_CONST_REG;
  K_C3 <= K_C3_CONST_REG;
  K_C4 <= K_C4_CONST_REG;
  K_C5 <= K_C5_CONST_REG;
  K_D1 <= K_D1_CONST_REG;
  K_D2 <= K_D2_CONST_REG;
  K_D3 <= K_D3_CONST_REG;
  K_D4 <= K_D4_CONST_REG;
  K_D5 <= K_D5_CONST_REG;
  K_E1 <= K_E1_CONST_REG;
  K_E2 <= K_E2_CONST_REG;
  K_E3 <= K_E3_CONST_REG;
  K_E4 <= K_E4_CONST_REG;
  K_E5 <= K_E5_CONST_REG;
  SHIFT <= SHIFT_REG;
  CAT1_CONST <= CAT1_CONST_REG;

  IMAGE_BLOCK_SEL <= BLOCK_REG;

  -------------------------------------------------------------
  --
  --  RS232 UART
  --
  --  Baud Rate    Register Setting (BAUD_SEL)
  --
  --     4800                0000
  --     9600                0001
  --    19200                0010
  --    38400                0011
  --   115200                0100
  --
  process (CLOCK)
  begin
    if rising_edge(CLOCK) then
      if LOAD_BD='1' then
        BAUD_SEL  <= DIN(3 downto 0);
        STOP_BITS <= DIN(5 downto 4);
      end if;
    end if;
  end process;

  iRS232_UART : RS232_UART
    port map (
      RESET     => RESET,
      CLOCK     => CLOCK,
      DIN       => DIN,
      BAUD_SEL  => BAUD_SEL,
      STOP_BITS => STOP_BITS,
      RX        => RX,
      READ      => READ_RX,
      WRITE     => LOAD_TX,
      DOUT      => RS232_DATA,
      TX        => TX,
      RX_EMPTY  => RX_EMPTY,
      TX_FULL   => TX_FULL,
      RX_COUNT  => RX_COUNT,
      TX_COUNT  => TX_COUNT );

  process(RESET, PIXEL_CLOCK)
  begin
    if RESET='1' then
      FrameCount <= (others=>'0');
    elsif rising_edge(PIXEL_CLOCK) then
      if CLEAR_DEL2='1' then
        FrameCount <= (others=>'0');
      else
        if EOF_A='1' then
          FrameCount <= FrameCount + 1;
        end if;
      end if;
    end if;
  end process;

  process (RESET, CLOCK)
  begin
    if RESET='1' then
      CLEAR_HOLD <= '0';
    elsif rising_edge(CLOCK) then
      CLEAR_HOLD <= '0';
      if CLEAR_PERF='1' or (CLEAR_HOLD='1' and CLEAR_DEL2='0') then
        CLEAR_HOLD <= '1';
      end if;
    end if;
  end process;

  process (PIXEL_CLOCK)
  begin
    if rising_edge(PIXEL_CLOCK) then
      CLEAR_DEL1 <= CLEAR_HOLD;
      CLEAR_DEL2 <= CLEAR_DEL1;
    end if;
  end process;

end RTL;
