-- ==============================================================
-- FILE : USER_AP1.VHD  -  MUST be modified by the USER
-- ==============================================================
--
-- This file is part of the Image Processing Demo, for the HERON-
-- FPGA14 module.
--
-- This file must be modified by the user.
--
-- ==============================================================
--
--  Date        : 06/04/2006
--  Author      : R. Williams
--  Description : User code section
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     R. Williams    06-04-06    Taken from FPGA12 Example.
--  3.0     R. Williams    12-06-06    Source file reorganisation.
--  3.1     R. Williams    07-09-07    Changes to CamLink_IF.vhd
--                                     to ensure correct operation
--                                     under ISE9.1.
--  3.2     R. Williams    28-04-08    Improved timing margin of
--                                     camera clock signal for low
--                                     frequency option by using
--                                     an IDELAY component to
--                                     control clock timing.
--
-- ==============================================================



-- ==============================================================
--   Package : CONFIG
-- ==============================================================
--
-- This package allow users to set up the different clock domains
-- of the application (FIFO interfaces) in the top level.
-- Please refer to the HUNT documentation for more details.
--
-- ==============================================================

package CONFIG is

  -- To use the low frequency De-Serialiser logic, set TRUE
  -- The low frequency De-Serialiser will work with pixel clocks below 24MHz.
  -- To use the high frequency De-Serialiser logic, set FALSE
  -- The high frequency De-Serialiser will work with pixel clocks above 24MHz.
  constant USE_LOW_FREQ_DESERIALISER : boolean := TRUE;

  -- CONVOLUTION
  -- To use 3x3 convolution functions, set USE_5X5_CONVOLUTION = FALSE
  -- To use 5x5 convolution functions, set USE_5X5_CONVOLUTION = TRUE
  constant USE_5X5_CONVOLUTION       : boolean := TRUE;

  -- FIFO CLOCK
  -- ==========

--   --------------------------------------------------------------------
--   Normally you will use the same clock source for the input and output
--   HERON FIFOs. In that case you need a single clock domain.
--   Then you drive SRC_FCLK_G with the frequency you want, which for the
--   HEPC9/HECPCI9/HERON_BASE2 must be >=60Mhz and <= 100Mhz.
--   The clock you use in your design is then FCLK_G which has the corrct
--   phase relative to the FIFO data.
--   In this case set FCLK_G_DOMAIN = TRUE

--   If however you want to use different clocks for the input and output
--   HERON FIFOs, you have seperate clock domains.
--   Now you drive the signals SRC_FCLK_RD and SRC_FCLK_WR with the frequencies
--   you want, (still probably >60Mhz and <100Mhz) and your design must use
--   FCLK_RD to deal with input FIFO data but FCLK_WR to deal with output FIFO data.
--   In this case set FCLK_G_DOMAIN = FALSE

  -- To use a single common FIFO clock, set FCLK_G_DOMAIN = TRUE
  constant FCLK_G_DOMAIN : boolean := TRUE;

end CONFIG;


-- ==============================================================
--   Module : USER_AP
-- ==============================================================

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;
  use WORK.CONFIG.all;

--pragma translate_off
library sim_lib;
  use sim_lib.all;

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

entity USER_AP is
  port (
    RESET             : in  std_logic;                      -- Asynchronous reset active high
    CONFIG            : in  std_logic;                      -- System wide Config signal
-- CLOCK IO
    OSC0              : in  std_logic;                      -- Xtal OSC0
    OSC3              : in  std_logic;                      -- Xtal OSC3 factory default fitted with 100Mhz
-- MISCELLANEOUS IO
    UDPRES            : out std_logic;                      -- reset the carrier (high if NOT used)
    LED               : out std_logic_vector(4 downto 0);   -- LEDs
    MOD_HAS_PROC      : out std_logic;
    CID               : in  std_logic_vector(3 downto 0);   -- Carrier ID
    MID               : in  std_logic_vector(3 downto 0);   -- Module ID
-- UMIs
    UMI_IN            : in  std_logic_vector(3 downto 0);
    UMI_OUT           : out std_logic_vector(3 downto 0);
    UMI_EN            : out std_logic_vector(3 downto 0);
-- READ FIFO CLK
    FCLK_RD           : in  std_logic;                      -- FIFO_IN clock to be used in this module (only when FCLK_G_DOMAIN=FALSE)
    SRC_FCLK_RD       : out std_logic;                      -- FIFO_IN clock source for the top level  (only when FCLK_G_DOMAIN=FALSE)
-- WRITE FIFO CLK
    FCLK_WR           : in  std_logic;                      -- FIFO_OUT clock to be used in this module (only when FCLK_G_DOMAIN=FALSE)
    SRC_FCLK_WR       : out std_logic;                      -- FIFO_OUT clock source for the top level  (only when FCLK_G_DOMAIN=FALSE)
-- COMMON FIFO CLK
    FCLK_G            : in  std_logic;                      -- Common FIFO clock to be used in this module (only when FCLK_G_DOMAIN=TRUE)
    SRC_FCLK_G        : out std_logic;                      -- Common FIFO clock source for the top level  (only when FCLK_G_DOMAIN=TRUE)
-- FIFO IN / HE_RD_6F interface
    INFIFO_READ_REQ   : out std_logic_vector(5 downto 0);   -- FIFO_IN Read Request
    INFIFO_DVALID     : in  std_logic_vector(5 downto 0);   -- FIFO_IN Data Valid
    INFIFO_SINGLE     : in  std_logic_vector(5 downto 0);   -- FIFO_IN Single data item available
    INFIFO_BURST      : in  std_logic_vector(5 downto 0);   -- FIFO_IN Block of data available
    INFIFO0_D         : in  std_logic_vector(31 downto 0);  -- FIFO_IN Data for FIFO 0
    INFIFO1_D         : in  std_logic_vector(31 downto 0);  -- FIFO_IN Data for FIFO 1
    INFIFO2_D         : in  std_logic_vector(31 downto 0);  -- FIFO_IN Data for FIFO 2
    INFIFO3_D         : in  std_logic_vector(31 downto 0);  -- FIFO_IN Data for FIFO 3
    INFIFO4_D         : in  std_logic_vector(31 downto 0);  -- FIFO_IN Data for FIFO 4
    INFIFO5_D         : in  std_logic_vector(31 downto 0);  -- FIFO_IN Data for FIFO 5
-- FIFO OUT / HE_WR_6F interface
    OUTFIFO_READY     : in  std_logic_vector(5 downto 0);   -- FIFO_OUT Ready Flag
    OUTFIFO_WRITE     : out std_logic_vector(5 downto 0);   -- FIFO_OUT Write Command
    OUTFIFO_D         : out std_logic_vector(31 downto 0);  -- FIFO_OUT Data
-- SERIAL BUS / HE_USER Message interface
    MSG_CLK           : out std_logic;                      -- HSB clock source for the top level
    MSG_DIN           : in  std_logic_vector(7 downto 0);   -- data received from HSB
    MSG_ADDR          : in  std_logic_vector(7 downto 0);   -- HSB address
    MSG_AEN           : in  std_logic;                      -- address enable
    MSG_WEN           : in  std_logic;                      -- write access
    MSG_REN           : in  std_logic;                      -- read access
    MSG_DONE          : in  std_logic;                      -- message successfully transmitted
    MSG_COUNT         : in  std_logic;                      -- user's counter enable
    MSG_CLEAR         : in  std_logic;                      -- user's counter clear
    MSG_READY         : out std_logic;                      -- to acknowledge an access
    MSG_SEND_MSG      : out std_logic;                      -- message send command
    MSG_CE            : out std_logic;                      -- to control speed operation
    MSG_DOUT          : out std_logic_vector(7 downto 0);   -- data sent to HSB
    MSG_SEND_ID       : out std_logic;                      -- ID information send command
    MSG_LAST_BYTE     : out std_logic;                      -- to indicate when the last byte is presented
-- CONNECTOR DIGITAL IO
    CAM_CLK           : in  std_logic;                      -- Camera Link Clock
    CAM_DATA          : in  std_logic_vector(3 downto 0);   -- Camera Link Data
    CAM_CTRL          : out std_logic_vector(3 downto 0);   -- Camera Link Control
    CAM_SER_TC        : out std_logic;                      -- Camera Link Serial Out
    CAM_SER_TFG       : in  std_logic;                      -- Camera Link Serial In
    CONN_A_IN         : in  std_logic_vector(29 downto 22); -- Data input on Connector A
    CONN_A_OUT        : out std_logic_vector(29 downto 22); -- Data output on Connector A
    CONN_A_EN         : out std_logic_vector(29 downto 22); -- Output enables for Connector A
    CONN_B_IN         : in  std_logic_vector(29 downto 0);  -- Data input on Connector B
    CONN_B_OUT        : out std_logic_vector(29 downto 0);  -- Data output on Connector B
    CONN_B_EN         : out std_logic_vector(29 downto 0);  -- Output enables for Connector B
    CONN_C_IN         : in  std_logic_vector(29 downto 0);  -- Data input on Connector C
    CONN_C_OUT        : out std_logic_vector(29 downto 0);  -- Data output on Connector C
    CONN_C_EN         : out std_logic_vector(29 downto 0);  -- Output enables for Connector C
    CONN_D_IN         : in  std_logic_vector(29 downto 0);  -- Data input on Connector D
    CONN_D_OUT        : out std_logic_vector(29 downto 0);  -- Data output on Connector D
    CONN_D_EN         : out std_logic_vector(29 downto 0);  -- Output enables for Connector D
    CONN_E_IN         : in  std_logic_vector(29 downto 0);  -- Data input on Connector E
    CONN_E_OUT        : out std_logic_vector(29 downto 0);  -- Data output on Connector E
    CONN_E_EN         : out std_logic_vector(29 downto 0);  -- Output enables for Connector E
    CONN_F_IN         : in  std_logic_vector(29 downto 0);  -- Data input on Connector F
    CONN_F_OUT        : out std_logic_vector(29 downto 0);  -- Data output on Connector F
    CONN_F_EN         : out std_logic_vector(29 downto 0);  -- Output enables for Connector F
-- DDR User Clock A
    DDR_A_USER_CLK    : out std_logic;                      -- DDR Port A Clock source
-- DDR User Reset A
    DDR_A_USER_RST    : out std_logic;                      -- DDR Port A Data Count Reset
-- DDR Data Count
    DDR_A_DATA_COUNT  : in  std_logic_vector(31 downto 0);  -- DDR Port A Data Count
-- DDR Write Port A
    DDR_A_WR_DATA     : out std_logic_vector(71 downto 0);  -- DDR Port A Write Data
    DDR_A_WR_ADDR     : out std_logic_vector(24 downto 0);  -- DDR Port A Write Address
    DDR_A_WR_ADDR_WEN : out std_logic;                      -- DDR Port A Wr-Address Enable
    DDR_A_WR_ADDR_FF  : in  std_logic;                      -- DDR Port A Wr-Address Full Flag
    DDR_A_WR_ADDR_AF  : in  std_logic;                      -- DDR Port A Wr-Address Almost Full
    DDR_A_WR_RISE_WEN : out std_logic;                      -- DDR Port A Rising Data Enable
    DDR_A_WR_RISE_FF  : in  std_logic;                      -- DDR Port A Rising Data Full Flag
    DDR_A_WR_RISE_AF  : in  std_logic;                      -- DDR Port A Rising Data Almost Full
    DDR_A_WR_FALL_WEN : out std_logic;                      -- DDR Port A Falling Data Enable
    DDR_A_WR_FALL_FF  : in  std_logic;                      -- DDR Port A Falling Data Full Flag
    DDR_A_WR_FALL_AF  : in  std_logic;                      -- DDR Port A Falling Data Almost Full
    DDR_A_WR_DM_WEN   : out std_logic;                      -- DDR Port A Data Mask Enable
    DDR_A_WR_DM_FF    : in  std_logic;                      -- DDR Port A Data Mask Full Flag
    DDR_A_WR_DM_AF    : in  std_logic;                      -- DDR Port A Data Mask Almost Full
-- DDR Read Port A
    DDR_A_RD_DATA     : in  std_logic_vector(63 downto 0);  -- DDR Port A Read Data
    DDR_A_RD_ADDR     : out std_logic_vector(24 downto 0);  -- DDR Port A Read Address
    DDR_A_RD_ADDR_WEN : out std_logic;                      -- DDR Port A Rd-Address Enable
    DDR_A_RD_ADDR_FF  : in  std_logic;                      -- DDR Port A Rd-Address Full Flag
    DDR_A_RD_ADDR_AF  : in  std_logic;                      -- DDR Port A Rd-Address Almost Full
    DDR_A_RD_RISE_REN : out std_logic;                      -- DDR Port A Rising Data Enable
    DDR_A_RD_RISE_EF  : in  std_logic;                      -- DDR Port A Rising Data Empty Flag
    DDR_A_RD_RISE_AE  : in  std_logic;                      -- DDR Port A Rising Data Almost Empty
    DDR_A_RD_FALL_REN : out std_logic;                      -- DDR Port A Falling Data Enable
    DDR_A_RD_FALL_EF  : in  std_logic;                      -- DDR Port A Falling Data Empty Flag
    DDR_A_RD_FALL_AE  : in  std_logic                       -- DDR Port A Falling Data Almost Empty
  );
end USER_AP;


architecture EXAMPLE1 of USER_AP is

  component CAM_DEMO
    generic (
      Use_Low_Freq_Deserialiser : boolean := TRUE;
      Use_5x5_Convolution       : boolean := TRUE
    );
    port (
      -- Clock and Reset
      RESET          : in  std_logic;
      HSB_CLOCK      : in  std_logic;
      -- CameraLink interface
      CAM_CLK        : in  std_logic;
      CAM_DATA       : in  std_logic_vector(3 downto 0);
      CAM_CTRL       : out std_logic_vector(3 downto 0);
      CAM_SER_TC     : out std_logic;
      CAM_SER_TFG    : in  std_logic;
      -- HERON Output FIFO interface
      FCLK_G         : in  std_logic;
      OUTFIFO_READY  : in  std_logic_vector(5 downto 0);
      OUTFIFO_WRITE  : out std_logic_vector(5 downto 0);
      OUTFIFO_D      : out std_logic_vector(31 downto 0);
      -- User Message interface
      MSG_DIN        : in  std_logic_vector(7 downto 0);
      MSG_ADDR       : in  std_logic_vector(7 downto 0);
      MSG_AEN        : in  std_logic;
      MSG_WEN        : in  std_logic;
      MSG_REN        : in  std_logic;
      MSG_DONE       : in  std_logic;
      MSG_COUNT      : in  std_logic;
      MSG_CLEAR      : in  std_logic;
      MSG_READY      : out std_logic;
      MSG_SEND_MSG   : out std_logic;
      MSG_CE         : out std_logic;
      MSG_DOUT       : out std_logic_vector(7 downto 0);
      MSG_SEND_ID    : out std_logic;
      MSG_LAST_BYTE  : out std_logic;
      -- DDR interface
      DDR_A_USER_CLK    : out std_logic;
      DDR_A_USER_RST    : out std_logic;
      DDR_A_DATA_COUNT  : in  std_logic_vector(31 downto 0);
      DDR_A_WR_DATA     : out std_logic_vector(71 downto 0);
      DDR_A_WR_ADDR     : out std_logic_vector(24 downto 0);
      DDR_A_WR_ADDR_WEN : out std_logic;
      DDR_A_WR_ADDR_FF  : in  std_logic;
      DDR_A_WR_ADDR_AF  : in  std_logic;
      DDR_A_WR_RISE_WEN : out std_logic;
      DDR_A_WR_RISE_FF  : in  std_logic;
      DDR_A_WR_RISE_AF  : in  std_logic;
      DDR_A_WR_FALL_WEN : out std_logic;
      DDR_A_WR_FALL_FF  : in  std_logic;
      DDR_A_WR_FALL_AF  : in  std_logic;
      DDR_A_WR_DM_WEN   : out std_logic;
      DDR_A_WR_DM_FF    : in  std_logic;
      DDR_A_WR_DM_AF    : in  std_logic;
      DDR_A_RD_DATA     : in  std_logic_vector(63 downto 0);
      DDR_A_RD_ADDR     : out std_logic_vector(24 downto 0);
      DDR_A_RD_ADDR_WEN : out std_logic;
      DDR_A_RD_ADDR_FF  : in  std_logic;
      DDR_A_RD_ADDR_AF  : in  std_logic;
      DDR_A_RD_RISE_REN : out std_logic;
      DDR_A_RD_RISE_EF  : in  std_logic;
      DDR_A_RD_RISE_AE  : in  std_logic;
      DDR_A_RD_FALL_REN : out std_logic;
      DDR_A_RD_FALL_EF  : in  std_logic;
      DDR_A_RD_FALL_AE  : in  std_logic
    );
  end component;

  -- BUFG primitive
  component BUFG
    port(
      I : in  std_logic;
      O : out std_logic
    );
  end component;

  signal MCLK         : std_logic;  -- Main clock
  signal HSB_CLK      : std_logic;  -- HSB clock source
  signal HSB_CLOCK    : std_logic;  -- HSB clock
  signal LEDcount     : std_logic_vector(24 downto 0);

  signal OSC3_CLK     : std_logic;

begin

  -- ==========================================================
  -- ==========================================================
  --       <<<<<<<   INSERT YOUR CODE HERE    >>>>>>>>>
  -- ==========================================================
  -- ==========================================================


  -------------------------------------------------------------
  -- Main clock to be used in this example

  iOSC3_BUFG : BUFG port map (I=>OSC3, O=>OSC3_CLK);

  MCLK <= OSC3_CLK;

  -------------------------------------------------------------
  -- Drive the UDP-RESET high (inactive)

  UDPRES <= '1';

  -------------------------------------------------------------
  -- Drive the module has processor signal high (inactive)

   MOD_HAS_PROC <= '1';

  -------------------------------------------------------------
  -- Drive unused signals

  UMI_OUT <= (others=>'0');
  UMI_EN  <= (others=>'1');

  -------------------------------------------------------------
  -- FIFOs

  SRC_FCLK_RD <= '0';   -- clock source for READ FIFO
  SRC_FCLK_WR <= '0';   -- clock source for WRITE FIFO
  SRC_FCLK_G  <= MCLK;  -- global clock source for both FIFOs

  -------------------------------------------------------------
  -- Camera Demo logic

  iCAM_DEMO : CAM_DEMO
    generic map (
      Use_Low_Freq_Deserialiser => USE_LOW_FREQ_DESERIALISER,
      Use_5x5_Convolution       => USE_5X5_CONVOLUTION )
    port map (
      -- Clock and Reset
      RESET          => RESET,
      HSB_CLOCK      => HSB_CLOCK,
      -- CameraLink interface
      CAM_CLK        => CAM_CLK,
      CAM_DATA       => CAM_DATA,
      CAM_CTRL       => CAM_CTRL,
      CAM_SER_TC     => CAM_SER_TC,
      CAM_SER_TFG    => CAM_SER_TFG,
      -- HERON Output FIFO interface
      FCLK_G         => FCLK_G,
      OUTFIFO_READY  => OUTFIFO_READY,
      OUTFIFO_WRITE  => OUTFIFO_WRITE,
      OUTFIFO_D      => OUTFIFO_D,
      -- User Message interface
      MSG_DIN        => MSG_DIN,
      MSG_ADDR       => MSG_ADDR,
      MSG_AEN        => MSG_AEN,
      MSG_WEN        => MSG_WEN,
      MSG_REN        => MSG_REN,
      MSG_DONE       => MSG_DONE,
      MSG_COUNT      => MSG_COUNT,
      MSG_CLEAR      => MSG_CLEAR,
      MSG_READY      => MSG_READY,
      MSG_SEND_MSG   => MSG_SEND_MSG,
      MSG_CE         => MSG_CE,
      MSG_DOUT       => MSG_DOUT,
      MSG_SEND_ID    => MSG_SEND_ID,
      MSG_LAST_BYTE  => MSG_LAST_BYTE,
      -- DDR interface
      DDR_A_USER_CLK    => DDR_A_USER_CLK,
      DDR_A_USER_RST    => DDR_A_USER_RST,
      DDR_A_DATA_COUNT  => DDR_A_DATA_COUNT,
      DDR_A_WR_DATA     => DDR_A_WR_DATA,
      DDR_A_WR_ADDR     => DDR_A_WR_ADDR,
      DDR_A_WR_ADDR_WEN => DDR_A_WR_ADDR_WEN,
      DDR_A_WR_ADDR_FF  => DDR_A_WR_ADDR_FF,
      DDR_A_WR_ADDR_AF  => DDR_A_WR_ADDR_AF,
      DDR_A_WR_RISE_WEN => DDR_A_WR_RISE_WEN,
      DDR_A_WR_RISE_FF  => DDR_A_WR_RISE_FF,
      DDR_A_WR_RISE_AF  => DDR_A_WR_RISE_AF,
      DDR_A_WR_FALL_WEN => DDR_A_WR_FALL_WEN,
      DDR_A_WR_FALL_FF  => DDR_A_WR_FALL_FF,
      DDR_A_WR_FALL_AF  => DDR_A_WR_FALL_AF,
      DDR_A_WR_DM_WEN   => DDR_A_WR_DM_WEN,
      DDR_A_WR_DM_FF    => DDR_A_WR_DM_FF,
      DDR_A_WR_DM_AF    => DDR_A_WR_DM_AF,
      DDR_A_RD_DATA     => DDR_A_RD_DATA,
      DDR_A_RD_ADDR     => DDR_A_RD_ADDR,
      DDR_A_RD_ADDR_WEN => DDR_A_RD_ADDR_WEN,
      DDR_A_RD_ADDR_FF  => DDR_A_RD_ADDR_FF,
      DDR_A_RD_ADDR_AF  => DDR_A_RD_ADDR_AF,
      DDR_A_RD_RISE_REN => DDR_A_RD_RISE_REN,
      DDR_A_RD_RISE_EF  => DDR_A_RD_RISE_EF,
      DDR_A_RD_RISE_AE  => DDR_A_RD_RISE_AE,
      DDR_A_RD_FALL_REN => DDR_A_RD_FALL_REN,
      DDR_A_RD_FALL_EF  => DDR_A_RD_FALL_EF,
      DDR_A_RD_FALL_AE  => DDR_A_RD_FALL_AE );

  -------------------------------------------------------------
  -- Serial Bus

  HSB_bufg : bufg port map(i => HSB_CLK, o => HSB_CLOCK);

  MSG_CLK <= HSB_CLOCK;  -- clock for Message Interface

  process (OSC3)
  begin
    if rising_edge(OSC3) then
      HSB_CLK <= NOT HSB_CLK;
    end if;
  end process;

  -------------------------------------------------------------
  -- Connector Digital IO (not used in this example)

  CONN_A_OUT <= (others=>'0');
  CONN_A_EN  <= (others=>'1');

  CONN_B_OUT <= (others=>'0');
  CONN_B_EN  <= (others=>'1');

  CONN_C_OUT <= (others=>'0');
  CONN_C_EN  <= (others=>'1');

  CONN_D_OUT <= (others=>'0');
  CONN_D_EN  <= (others=>'1');

  CONN_E_OUT <= (others=>'0');
  CONN_E_EN  <= (others=>'1');

  CONN_F_OUT <= (others=>'0');
  CONN_F_EN  <= (others=>'1');

  -------------------------------------------------------------
  -- Led Flasher : dividing F_CLKG clock by 2**24

  process(RESET, FCLK_G)
  begin
    if RESET='1' then
      LEDcount <= (others=>'0');
    elsif rising_edge(FCLK_G) then
      LEDcount <= LEDcount + 1;
    end if;
  end process;

  LED(4) <= LEDcount(24);

  -- Drive LEDs high (inactive)
  LED(3 downto 0) <= (others=>'1');

end EXAMPLE1;
