--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- White Rabbit Trigger Distribution
-- https://ohwr-gitlab.cern.ch/projects/wrtd
--------------------------------------------------------------------------------
--
-- unit name:   wrtd_ref_svec_tdc_fd
--
-- description: Top entity for WRTD reference design
--
-- Top level design of the SVEC-based WRTD node, with
-- an FMC TDC in slot 1 and an FMC Fine Delay in slot 2.
--
-- This is the standard pulse-in/pulse-out WRTD node, with the FMC TDC
-- injecting pulses into the WR network in the form of WRTD messages and
-- the FMC Fine Delay converting those messages back to pulses at the
-- destination.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-2019
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.mt_mqueue_pkg.all;
use work.mock_turtle_pkg.all;
use work.wr_board_pkg.all;
use work.wr_fabric_pkg.all;

library unisim;
use unisim.vcomponents.all;

entity wrtd_ref_svec_tdc_fd is
  generic (
    g_WRPC_INITF    : string  := "../../../dependencies/wr-cores/bin/wrpc/wrc_phy8.bram";
    g_MT_CPU0_INITF : string  := "../../../software/firmware/tdc/wrtd-rt-tdc.bram";
    g_MT_CPU1_INITF : string  := "../../../software/firmware/fd/wrtd-rt-fd.bram";
    -- Simulation-mode enable parameter. Set by default (synthesis) to 0, and
    -- changed to non-zero in the instantiation of the top level DUT in the
    -- testbench. Its purpose is to reduce some internal counters/timeouts
    -- to speed up simulations.
    g_SIMULATION     : integer := 0);
  port (
    ---------------------------------------------------------------------------
    -- Clocks/resets
    ---------------------------------------------------------------------------

    -- Reset from system fpga
    rst_n_i : in std_logic;

    -- Local oscillators
    clk_20m_vcxo_i : in std_logic;  -- 20MHz VCXO clock

    clk_125m_pllref_p_i : in std_logic;  -- 125 MHz PLL reference
    clk_125m_pllref_n_i : in std_logic;

    clk_125m_gtp_n_i : in std_logic;  -- 125 MHz GTP reference
    clk_125m_gtp_p_i : in std_logic;

    ---------------------------------------------------------------------------
    -- VME interface
    ---------------------------------------------------------------------------

    vme_write_n_i    : in    std_logic;
    vme_sysreset_n_i : in    std_logic;
    vme_retry_oe_o   : out   std_logic;
    vme_retry_n_o    : out   std_logic;
    vme_lword_n_b    : inout std_logic;
    vme_iackout_n_o  : out   std_logic;
    vme_iackin_n_i   : in    std_logic;
    vme_iack_n_i     : in    std_logic;
    vme_gap_i        : in    std_logic;
    vme_dtack_oe_o   : out   std_logic;
    vme_dtack_n_o    : out   std_logic;
    vme_ds_n_i       : in    std_logic_vector(1 downto 0);
    vme_data_oe_n_o  : out   std_logic;
    vme_data_dir_o   : out   std_logic;
    vme_berr_o       : out   std_logic;
    vme_as_n_i       : in    std_logic;
    vme_addr_oe_n_o  : out   std_logic;
    vme_addr_dir_o   : out   std_logic;
    vme_irq_o        : out   std_logic_vector(7 downto 1);
    vme_ga_i         : in    std_logic_vector(4 downto 0);
    vme_data_b       : inout std_logic_vector(31 downto 0);
    vme_am_i         : in    std_logic_vector(5 downto 0);
    vme_addr_b       : inout std_logic_vector(31 downto 1);

    ---------------------------------------------------------------------------
    -- SPI interfaces to DACs
    ---------------------------------------------------------------------------

    pll20dac_din_o    : out std_logic;
    pll20dac_sclk_o   : out std_logic;
    pll20dac_sync_n_o : out std_logic;
    pll25dac_din_o    : out std_logic;
    pll25dac_sclk_o   : out std_logic;
    pll25dac_sync_n_o : out std_logic;

    ---------------------------------------------------------------------------
    -- SFP I/O for transceiver
    ---------------------------------------------------------------------------

    sfp_txp_o         : out   std_logic;
    sfp_txn_o         : out   std_logic;
    sfp_rxp_i         : in    std_logic;
    sfp_rxn_i         : in    std_logic;
    sfp_mod_def0_i    : in    std_logic;  -- sfp detect
    sfp_mod_def1_b    : inout std_logic;  -- scl
    sfp_mod_def2_b    : inout std_logic;  -- sda
    sfp_rate_select_o : out   std_logic;
    sfp_tx_fault_i    : in    std_logic;
    sfp_tx_disable_o  : out   std_logic;
    sfp_los_i         : in    std_logic;

    ---------------------------------------------------------------------------
    -- Carrier I2C EEPROM
    ---------------------------------------------------------------------------

    carrier_scl_b : inout std_logic;
    carrier_sda_b : inout std_logic;

    ---------------------------------------------------------------------------
    -- PCB version
    ---------------------------------------------------------------------------
    pcbrev_i : in std_logic_vector(4 downto 0);

    ---------------------------------------------------------------------------
    -- Onewire interface
    ---------------------------------------------------------------------------

    onewire_b : inout std_logic;

    ---------------------------------------------------------------------------
    -- UART
    ---------------------------------------------------------------------------

    uart_rxd_i : in  std_logic;
    uart_txd_o : out std_logic;

    ---------------------------------------------------------------------------
    -- SPI (flash is connected to SFPGA and routed to AFPGA
    -- once the boot process is complete)
    ---------------------------------------------------------------------------

    spi_sclk_o : out std_logic;
    spi_ncs_o  : out std_logic;
    spi_mosi_o : out std_logic;
    spi_miso_i : in  std_logic;

    ---------------------------------------------------------------------------
    -- Carrier front panel LEDs and IOs
    ---------------------------------------------------------------------------

    fp_led_line_oen_o : out std_logic_vector(1 downto 0);
    fp_led_line_o     : out std_logic_vector(1 downto 0);
    fp_led_column_o   : out std_logic_vector(3 downto 0);

    fp_gpio1_b      : out std_logic;  -- PPS output
    fp_gpio2_b      : out std_logic;  -- not used
    fp_gpio3_b      : in  std_logic;  -- ext 10MHz clock input
    fp_gpio4_b      : in  std_logic;  -- ext PPS input
    fp_term_en_o    : out std_logic_vector(4 downto 1);
    fp_gpio1_a2b_o  : out std_logic;
    fp_gpio2_a2b_o  : out std_logic;
    fp_gpio34_a2b_o : out std_logic;

    ---------------------------------------------------------------------------
    -- FMC slot 1 pins (TDC mezzanine)
    ---------------------------------------------------------------------------

    -- TDC1 PLL AD9516 and DAC AD5662 interface
    fmc0_tdc_pll_sclk_o       : out std_logic;
    fmc0_tdc_pll_sdi_o        : out std_logic;
    fmc0_tdc_pll_cs_n_o       : out std_logic;
    fmc0_tdc_pll_dac_sync_n_o : out std_logic;
    fmc0_tdc_pll_sdo_i        : in  std_logic;
    fmc0_tdc_pll_status_i     : in  std_logic;
    fmc0_tdc_125m_clk_p_i     : in  std_logic;
    fmc0_tdc_125m_clk_n_i     : in  std_logic;
    fmc0_tdc_acam_refclk_p_i  : in  std_logic;
    fmc0_tdc_acam_refclk_n_i  : in  std_logic;

    -- TDC1 ACAM timing interface
    fmc0_tdc_start_from_fpga_o : out std_logic;
    fmc0_tdc_err_flag_i        : in  std_logic;
    fmc0_tdc_int_flag_i        : in  std_logic;
    fmc0_tdc_start_dis_o       : out std_logic;
    fmc0_tdc_stop_dis_o        : out std_logic;

    -- TDC1 ACAM data interface
    fmc0_tdc_data_bus_io : inout std_logic_vector(27 downto 0);
    fmc0_tdc_address_o   : out   std_logic_vector(3 downto 0);
    fmc0_tdc_cs_n_o      : out   std_logic;
    fmc0_tdc_oe_n_o      : out   std_logic;
    fmc0_tdc_rd_n_o      : out   std_logic;
    fmc0_tdc_wr_n_o      : out   std_logic;
    fmc0_tdc_ef1_i       : in    std_logic;
    fmc0_tdc_ef2_i       : in    std_logic;

    -- TDC1 Input Logic
    fmc0_tdc_enable_inputs_o : out std_logic;
    fmc0_tdc_term_en_1_o     : out std_logic;
    fmc0_tdc_term_en_2_o     : out std_logic;
    fmc0_tdc_term_en_3_o     : out std_logic;
    fmc0_tdc_term_en_4_o     : out std_logic;
    fmc0_tdc_term_en_5_o     : out std_logic;

    -- TDC1 1-wire UniqueID & Thermometer
    fmc0_tdc_one_wire_b : inout std_logic;

    -- TDC1 EEPROM I2C
    fmc0_tdc_scl_b : inout std_logic;
    fmc0_tdc_sda_b : inout std_logic;

    -- TDC1 LEDs
    fmc0_tdc_led_status_o : out std_logic;
    fmc0_tdc_led_trig1_o  : out std_logic;
    fmc0_tdc_led_trig2_o  : out std_logic;
    fmc0_tdc_led_trig3_o  : out std_logic;
    fmc0_tdc_led_trig4_o  : out std_logic;
    fmc0_tdc_led_trig5_o  : out std_logic;

    fmc0_prsnt_m2c_n_i : in std_logic;

    fmc0_scl_b : inout std_logic;
    fmc0_sda_b : inout std_logic;

    ---------------------------------------------------------------------------
    -- FMC slot 2 pins (FDELAY mezzanine)
    ---------------------------------------------------------------------------

    fmc1_fd_tdc_start_p_i : in std_logic;
    fmc1_fd_tdc_start_n_i : in std_logic;

    fmc1_fd_clk_ref_p_i : in std_logic;
    fmc1_fd_clk_ref_n_i : in std_logic;

    fmc1_fd_trig_a_i         : in    std_logic;
    fmc1_fd_tdc_cal_pulse_o  : out   std_logic;
    fmc1_fd_tdc_d_b          : inout std_logic_vector(27 downto 0);
    fmc1_fd_tdc_emptyf_i     : in    std_logic;
    fmc1_fd_tdc_alutrigger_o : out   std_logic;
    fmc1_fd_tdc_wr_n_o       : out   std_logic;
    fmc1_fd_tdc_rd_n_o       : out   std_logic;
    fmc1_fd_tdc_oe_n_o       : out   std_logic;
    fmc1_fd_led_trig_o       : out   std_logic;
    fmc1_fd_tdc_start_dis_o  : out   std_logic;
    fmc1_fd_tdc_stop_dis_o   : out   std_logic;
    fmc1_fd_spi_cs_dac_n_o   : out   std_logic;
    fmc1_fd_spi_cs_pll_n_o   : out   std_logic;
    fmc1_fd_spi_cs_gpio_n_o  : out   std_logic;
    fmc1_fd_spi_sclk_o       : out   std_logic;
    fmc1_fd_spi_mosi_o       : out   std_logic;
    fmc1_fd_spi_miso_i       : in    std_logic;
    fmc1_fd_delay_len_o      : out   std_logic_vector(3 downto 0);
    fmc1_fd_delay_val_o      : out   std_logic_vector(9 downto 0);
    fmc1_fd_delay_pulse_o    : out   std_logic_vector(3 downto 0);

    fmc1_fd_dmtd_clk_o    : out std_logic;
    fmc1_fd_dmtd_fb_in_i  : in  std_logic;
    fmc1_fd_dmtd_fb_out_i : in  std_logic;

    fmc1_fd_pll_status_i : in  std_logic;
    fmc1_fd_ext_rst_n_o  : out std_logic;

    fmc1_fd_onewire_b : inout std_logic;

    fmc1_prsnt_m2c_n_i : in std_logic;

    fmc1_scl_b : inout std_logic;
    fmc1_sda_b : inout std_logic);

end entity wrtd_ref_svec_tdc_fd;

architecture arch of wrtd_ref_svec_tdc_fd is

  -----------------------------------------------------------------------------
  -- Constants
  -----------------------------------------------------------------------------

  -- WRTD Node identification (WTN2)
  constant c_WRTD_NODE_ID : std_logic_vector(31 downto 0) := x"5754_4E02";

  -- Number of masters attached to the primary wishbone crossbar
  constant c_NUM_WB_MASTERS : integer := 1;

  -- Number of slaves attached to the primary wishbone crossbar
  constant c_NUM_WB_SLAVES : integer := 4;

  -- Primary Wishbone master(s) offsets
  constant c_WB_MASTER_VME : integer := 0;

  -- Primary Wishbone slave(s) offsets
  constant c_WB_SLAVE_METADATA : integer := 0;
  constant c_WB_SLAVE_FDL      : integer := 1;
  constant c_WB_SLAVE_TDC      : integer := 2;
  constant c_WB_SLAVE_MT       : integer := 3;

  -- Convention metadata base address
  constant c_METADATA_ADDR : t_wishbone_address := x"0000_2000";

  -- Primary wishbone crossbar layout
  constant c_WB_LAYOUT_ADDR :
    t_wishbone_address_array(c_NUM_WB_SLAVES - 1 downto 0) := (
      c_WB_SLAVE_METADATA => c_METADATA_ADDR,
      c_WB_SLAVE_FDL      => x"0000_8000",
      c_WB_SLAVE_TDC      => x"0001_0000",
      c_WB_SLAVE_MT       => x"0002_0000");

  constant c_WB_LAYOUT_MASK :
    t_wishbone_address_array(c_NUM_WB_SLAVES - 1 downto 0) := (
      c_WB_SLAVE_METADATA => x"0003_ffc0",  --    0x40 bytes
      c_WB_SLAVE_FDL      => x"0003_f800",  --   0x800 bytes
      c_WB_SLAVE_TDC      => x"0003_0000",  -- 0x10000 bytes
      c_WB_SLAVE_MT       => x"0002_0000"); -- 0x20000 bytes

  constant c_FMC_MUX_ADDR : t_wishbone_address_array(0 downto 0) :=
    (0 => x"00000000");
  constant c_FMC_MUX_MASK : t_wishbone_address_array(0 downto 0) :=
    (0 => x"10000000");

  constant c_MT_CONFIG : t_mt_config :=
    (
      app_id                        => c_WRTD_NODE_ID,
      cpu_count                     => 2,
      cpu_config                    => (
        0 | 1                       => (
          memsize                   => 8192,
          hmq_config                => (
            slot_count              => 1,
            slot_config             => (
              0                     => (
                entries_bits        => 4,
                width_bits          => 7,
                header_bits         => 2,
                endpoint_id         => x"0000_0000",
                enable_config_space => FALSE),
              others                => c_DUMMY_MT_MQUEUE_SLOT)),
          rmq_config                => (
            slot_count              => 1,
            slot_config             => (
              0                     => (
                entries_bits        => 4,
                width_bits          => 7,
                header_bits         => 4,
                endpoint_id         => x"0000_0000",
                enable_config_space => TRUE),
              others                => c_DUMMY_MT_MQUEUE_SLOT))),
        others                      => (
          0, c_MT_DEFAULT_MQUEUE_CONFIG, c_MT_DEFAULT_MQUEUE_CONFIG)),
      shared_mem_size               => 256
      );

  -----------------------------------------------------------------------------
  -- Signals
  -----------------------------------------------------------------------------

  -- Wishbone buse(s) from masters attached to crossbar
  signal cnx_master_out : t_wishbone_master_out_array(c_NUM_WB_MASTERS-1 downto 0);
  signal cnx_master_in  : t_wishbone_master_in_array(c_NUM_WB_MASTERS-1 downto 0);

  -- Wishbone buse(s) to slaves attached to crossbar
  signal cnx_slave_out : t_wishbone_slave_out_array(c_NUM_WB_SLAVES-1 downto 0);
  signal cnx_slave_in  : t_wishbone_slave_in_array(c_NUM_WB_SLAVES-1 downto 0);

  -- clock and reset
  signal areset_n         : std_logic;
  signal clk_sys_62m5     : std_logic;
  signal rst_sys_62m5_n   : std_logic;
  signal clk_ref_125m     : std_logic;
  signal clk_ext_ref      : std_logic;
  signal tdc_clk_125m     : std_logic;
  signal dcm1_clk_ref_0   : std_logic;
  signal dcm1_clk_ref_180 : std_logic;

  attribute keep                   : string;
  attribute keep of tdc_clk_125m   : signal is "TRUE";
  attribute keep of dcm1_clk_ref_0 : signal is "TRUE";

  -- I2C EEPROM
  signal eeprom_sda_in  : std_logic;
  signal eeprom_sda_out : std_logic;
  signal eeprom_scl_in  : std_logic;
  signal eeprom_scl_out : std_logic;

  -- VME
  signal vme_data_b_out    : std_logic_vector(31 downto 0);
  signal vme_addr_b_out    : std_logic_vector(31 downto 1);
  signal vme_lword_n_b_out : std_logic;
  signal vme_data_dir_int  : std_logic;
  signal vme_addr_dir_int  : std_logic;
  signal vme_ga            : std_logic_vector(5 downto 0);
  signal vme_berr_n        : std_logic;
  signal vme_irq_n         : std_logic_vector(7 downto 1);
  signal vme_access_led    : std_logic;

  -- SFP
  signal sfp_sda_in  : std_logic;
  signal sfp_sda_out : std_logic;
  signal sfp_scl_in  : std_logic;
  signal sfp_scl_out : std_logic;

  -- LEDs and GPIO
  signal pps         : std_logic;
  signal pps_led     : std_logic;
  signal pps_ext_in  : std_logic;
  signal svec_led    : std_logic_vector(15 downto 0);
  signal wr_led_link : std_logic;
  signal wr_led_act  : std_logic;

  -- Interrupts
  signal irq_vector : std_logic_vector(5 downto 0);

  --  MT endpoints
  signal rmq_endpoint_out : t_mt_rmq_endpoint_iface_out;
  signal rmq_endpoint_in  : t_mt_rmq_endpoint_iface_in;
  signal rmq_src_in       : t_mt_stream_source_in;
  signal rmq_src_out      : t_mt_stream_source_out;
  signal rmq_src_cfg_in   : t_mt_stream_config_in;
  signal rmq_src_cfg_out  : t_mt_stream_config_out;
  signal rmq_snk_in       : t_mt_stream_sink_in;
  signal rmq_snk_out      : t_mt_stream_sink_out;
  signal rmq_snk_cfg_in   : t_mt_stream_config_in;
  signal rmq_snk_cfg_out  : t_mt_stream_config_out;

  --  MT fabric.
  signal eth_tx_out : t_wrf_source_out;
  signal eth_tx_in  : t_wrf_source_in;
  signal eth_rx_out : t_wrf_sink_out;
  signal eth_rx_in  : t_wrf_sink_in;

  -- MT Dedicated WB interfaces to FMCs
  signal fmc_dp_wb_out : t_wishbone_master_out_array(0 to 1);
  signal fmc_dp_wb_in  : t_wishbone_master_in_array(0 to 1);

  -- Muxed Host and MT WB interface to FMC1
  signal fmc1_mux_wb_out : t_wishbone_master_out;
  signal fmc1_mux_wb_in  : t_wishbone_master_in;

  -- WRPC TM interface and aux clocks
  signal tm_link_up         : std_logic;
  signal tm_tai             : std_logic_vector(39 downto 0);
  signal tm_cycles          : std_logic_vector(27 downto 0);
  signal tm_time_valid      : std_logic;
  signal tm_clk_aux_lock_en : std_logic_vector(1 downto 0);
  signal tm_clk_aux_locked  : std_logic_vector(1 downto 0);
  signal tm_dac_value       : std_logic_vector(23 downto 0);
  signal tm_dac_wr          : std_logic_vector(1 downto 0);

  -- MT TM interface
  signal tm : t_mt_timing_if;

  -- Misc FMC signals
  signal fmc1_fd_tdc_start  : std_logic;
  signal ddr1_pll_reset     : std_logic;
  signal ddr1_pll_locked    : std_logic;
  signal fmc1_fd_pll_status : std_logic;

  signal fmc1_fd_tdc_data_out : std_logic_vector(27 downto 0);
  signal fmc1_fd_tdc_data_in  : std_logic_vector(27 downto 0);
  signal fmc1_fd_tdc_data_oe  : std_logic;

  signal fmc1_fd_owr_en, fmc1_fd_owr_in  : std_logic;

  attribute iob        : string;
  attribute iob of pps : signal is "FORCE";

begin  -- architecture arch

  areset_n <= vme_sysreset_n_i and rst_n_i;

  cmp_xwb_metadata : entity work.xwb_metadata
    generic map (
      g_VENDOR_ID    => x"0000_10DC",
      g_DEVICE_ID    => c_WRTD_NODE_ID,
      g_VERSION      => x"0100_0000",
      g_CAPABILITIES => x"0000_0000",
      g_COMMIT_ID    => (others => '0'))
    port map (
      clk_i   => clk_sys_62m5,
      rst_n_i => rst_sys_62m5_n,
      wb_i    => cnx_slave_in(c_WB_SLAVE_METADATA),
      wb_o    => cnx_slave_out(c_WB_SLAVE_METADATA));

  inst_svec_base : entity work.svec_base_wr
    generic map (
      g_WITH_VIC           => TRUE,
      g_WITH_ONEWIRE       => FALSE,
      g_WITH_SPI           => FALSE,
      g_WITH_WR            => TRUE,
      g_WITH_DDR4          => FALSE,
      g_WITH_DDR5          => FALSE,
      g_APP_OFFSET         => c_METADATA_ADDR,
      g_NUM_USER_IRQ       => 6,
      g_DPRAM_INITF        => g_WRPC_INITF,
      g_AUX_CLKS           => 2,
      g_FABRIC_IFACE       => plain,
      g_SIMULATION         => g_SIMULATION,
      g_VERBOSE            => FALSE)
    port map (
      rst_n_i              => areset_n,
      clk_125m_pllref_p_i  => clk_125m_pllref_p_i,
      clk_125m_pllref_n_i  => clk_125m_pllref_n_i,
      clk_20m_vcxo_i       => clk_20m_vcxo_i,
      clk_125m_gtp_n_i     => clk_125m_gtp_n_i,
      clk_125m_gtp_p_i     => clk_125m_gtp_p_i,
      clk_aux_i(0)         => tdc_clk_125m,
      clk_aux_i(1)         => dcm1_clk_ref_0,
      clk_10m_ext_i        => clk_ext_ref,
      pps_ext_i            => pps_ext_in,
      vme_write_n_i        => vme_write_n_i,
      vme_sysreset_n_i     => vme_sysreset_n_i,
      vme_retry_oe_o       => vme_retry_oe_o,
      vme_retry_n_o        => vme_retry_n_o,
      vme_lword_n_b        => vme_lword_n_b,
      vme_iackout_n_o      => vme_iackout_n_o,
      vme_iackin_n_i       => vme_iackin_n_i,
      vme_iack_n_i         => vme_iack_n_i,
      vme_gap_i            => vme_gap_i,
      vme_dtack_oe_o       => vme_dtack_oe_o,
      vme_dtack_n_o        => vme_dtack_n_o,
      vme_ds_n_i           => vme_ds_n_i,
      vme_data_oe_n_o      => vme_data_oe_n_o,
      vme_data_dir_o       => vme_data_dir_o,
      vme_berr_o           => vme_berr_o,
      vme_as_n_i           => vme_as_n_i,
      vme_addr_oe_n_o      => vme_addr_oe_n_o,
      vme_addr_dir_o       => vme_addr_dir_o,
      vme_irq_o            => vme_irq_o,
      vme_ga_i             => vme_ga_i,
      vme_data_b           => vme_data_b,
      vme_am_i             => vme_am_i,
      vme_addr_b           => vme_addr_b,
      fmc0_scl_b           => fmc0_scl_b,
      fmc0_sda_b           => fmc0_sda_b,
      fmc1_scl_b           => fmc1_scl_b,
      fmc1_sda_b           => fmc1_sda_b,
      fmc0_prsnt_m2c_n_i   => fmc0_prsnt_m2c_n_i,
      fmc1_prsnt_m2c_n_i   => fmc1_prsnt_m2c_n_i,
      onewire_b            => onewire_b,
      carrier_scl_b        => carrier_scl_b,
      carrier_sda_b        => carrier_sda_b,
      spi_sclk_o           => spi_sclk_o,
      spi_ncs_o            => spi_ncs_o,
      spi_mosi_o           => spi_mosi_o,
      spi_miso_i           => spi_miso_i,
      uart_rxd_i           => uart_rxd_i,
      uart_txd_o           => uart_txd_o,
      plldac_sclk_o        => pll20dac_sclk_o,
      plldac_din_o         => pll20dac_din_o,
      pll20dac_din_o       => pll20dac_din_o,
      pll20dac_sclk_o      => pll20dac_sclk_o,
      pll20dac_sync_n_o    => pll20dac_sync_n_o,
      pll25dac_din_o       => pll25dac_din_o,
      pll25dac_sclk_o      => pll25dac_sclk_o,
      pll25dac_sync_n_o    => pll25dac_sync_n_o,
      sfp_txp_o            => sfp_txp_o,
      sfp_txn_o            => sfp_txn_o,
      sfp_rxp_i            => sfp_rxp_i,
      sfp_rxn_i            => sfp_rxn_i,
      sfp_mod_def0_i       => sfp_mod_def0_i,
      sfp_mod_def1_b       => sfp_mod_def1_b,
      sfp_mod_def2_b       => sfp_mod_def2_b,
      sfp_rate_select_o    => sfp_rate_select_o,
      sfp_tx_fault_i       => sfp_tx_fault_i,
      sfp_tx_disable_o     => sfp_tx_disable_o,
      sfp_los_i            => sfp_los_i,
      pcbrev_i             => pcbrev_i,
      clk_sys_62m5_o       => clk_sys_62m5,
      rst_sys_62m5_n_o     => rst_sys_62m5_n,
      clk_ref_125m_o       => clk_ref_125m,
      rst_ref_125m_n_o     => open,
      irq_user_i           => irq_vector,
      wrf_src_o            => eth_rx_in,
      wrf_src_i            => eth_rx_out,
      wrf_snk_o            => eth_tx_in,
      wrf_snk_i            => eth_tx_out,
      tm_link_up_o         => tm_link_up,
      tm_time_valid_o      => tm_time_valid,
      tm_tai_o             => tm_tai,
      tm_cycles_o          => tm_cycles,
      tm_dac_value_o       => tm_dac_value,
      tm_dac_wr_o          => tm_dac_wr,
      tm_clk_aux_lock_en_i => tm_clk_aux_lock_en,
      tm_clk_aux_locked_o  => tm_clk_aux_locked,
      pps_p_o              => pps,
      pps_led_o            => pps_led,
      link_ok_o            => open,
      led_link_o           => wr_led_link,
      led_act_o            => wr_led_act,
      app_wb_o             => cnx_master_out(c_WB_MASTER_VME),
      app_wb_i             => cnx_master_in(c_WB_MASTER_VME));

  -----------------------------------------------------------------------------
  -- Primary wishbone Crossbar
  -----------------------------------------------------------------------------

  cmp_sdb_crossbar : xwb_crossbar
    generic map (
      g_VERBOSE     => FALSE,
      g_NUM_MASTERS => c_NUM_WB_MASTERS,
      g_NUM_SLAVES  => c_NUM_WB_SLAVES,
      g_REGISTERED  => TRUE,
      g_ADDRESS     => c_WB_LAYOUT_ADDR,
      g_MASK        => c_WB_LAYOUT_MASK)
    port map (
      clk_sys_i => clk_sys_62m5,
      rst_n_i   => rst_sys_62m5_n,
      slave_i   => cnx_master_out,
      slave_o   => cnx_master_in,
      master_i  => cnx_slave_out,
      master_o  => cnx_slave_in);

  cmp_vme_led_extend : gc_extend_pulse
    generic map (
      g_width => 5000000)
    port map (
      clk_i      => clk_sys_62m5,
      rst_n_i    => rst_sys_62m5_n,
      pulse_i    => cnx_slave_in(c_WB_MASTER_VME).cyc,
      extended_o => vme_access_led);

  -----------------------------------------------------------------------------
  -- Mock Turtle (WB Slave)
  -----------------------------------------------------------------------------

  cmp_mock_turtle : entity work.mock_turtle_core
    generic map (
      g_CONFIG            => c_MT_CONFIG,
      g_CPU0_IRAM_INITF   => g_MT_CPU0_INITF,
      g_CPU1_IRAM_INITF   => g_MT_CPU1_INITF,
      g_WITH_WHITE_RABBIT => TRUE)
    port map (
      clk_i          => clk_sys_62m5,
      rst_n_i        => rst_sys_62m5_n,
      sp_master_o    => open,
      sp_master_i    => c_DUMMY_WB_MASTER_IN,
      dp_master_o    => fmc_dp_wb_out,
      dp_master_i    => fmc_dp_wb_in,
      rmq_endpoint_o => rmq_endpoint_out,
      rmq_endpoint_i => rmq_endpoint_in,
      host_slave_i   => cnx_slave_in(c_WB_SLAVE_MT),
      host_slave_o   => cnx_slave_out(c_WB_SLAVE_MT),
      clk_ref_i      => clk_ref_125m,
      tm_i           => tm,
      hmq_in_irq_o   => irq_vector(2),
      hmq_out_irq_o  => irq_vector(3),
      notify_irq_o   => irq_vector(5),
      console_irq_o  => irq_vector(4));

  tm.cycles                 <= tm_cycles;
  tm.tai                    <= tm_tai;
  tm.time_valid             <= tm_time_valid;
  tm.link_up                <= tm_link_up;
  tm.aux_locked(1 downto 0) <= tm_clk_aux_locked;
  tm.aux_locked(7 downto 2) <= (others => '0');

  cmp_eth_endpoint : entity work.mt_ep_ethernet_single
    port map (
      clk_i            => clk_sys_62m5,
      rst_n_i          => rst_sys_62m5_n,
      rmq_src_i        => rmq_src_in,
      rmq_src_o        => rmq_src_out,
      rmq_src_config_i => rmq_snk_cfg_out,
      rmq_src_config_o => rmq_snk_cfg_in,
      rmq_snk_i        => rmq_snk_in,
      rmq_snk_o        => rmq_snk_out,
      rmq_snk_config_i => rmq_src_cfg_out,
      rmq_snk_config_o => rmq_src_cfg_in,
      eth_src_o        => eth_tx_out,
      eth_src_i        => eth_tx_in,
      eth_snk_o        => eth_rx_out,
      eth_snk_i        => eth_rx_in);

  p_rmq_assign : process (rmq_endpoint_out, rmq_snk_cfg_in, rmq_snk_out,
                          rmq_src_cfg_in, rmq_src_out) is
  begin

    rmq_endpoint_in <= c_MT_RMQ_ENDPOINT_IFACE_IN_DEFAULT_VALUE;

    -- WR->MT (RX, to MT CPU1)
    rmq_src_in                          <= rmq_endpoint_out.snk_out(1)(0);
    rmq_endpoint_in.snk_in(1)(0)        <= rmq_src_out;
    rmq_snk_cfg_out                     <= rmq_endpoint_out.snk_config_out(1)(0);
    rmq_endpoint_in.snk_config_in(1)(0) <= rmq_snk_cfg_in;

    -- MT->WR (TX, from MT CPU0)
    rmq_snk_in                          <= rmq_endpoint_out.src_out(0)(0);
    rmq_endpoint_in.src_in(0)(0)        <= rmq_snk_out;
    rmq_src_cfg_out                     <= rmq_endpoint_out.src_config_out(0)(0);
    rmq_endpoint_in.src_config_in(0)(0) <= rmq_src_cfg_in;

  end process p_rmq_assign;

  -----------------------------------------------------------------------------
  -- FMC TDC (SVEC slot #1)
  -----------------------------------------------------------------------------

  U_TDC_Core : entity work.fmc_tdc_wrapper
    generic map (
      g_SIMULATION          => f_int2bool(g_SIMULATION),
      g_PULSE_WIDTH_FILTER  => FALSE,
      g_USE_FIFO_READOUT    => FALSE,
      g_USE_DMA_READOUT     => FALSE,
      g_WITH_DIRECT_READOUT => TRUE)
    port map (
      clk_sys_i            => clk_sys_62m5,
      rst_sys_n_i          => rst_sys_62m5_n,
      rst_n_a_i            => rst_sys_62m5_n,
      pll_sclk_o           => fmc0_tdc_pll_sclk_o,
      pll_sdi_o            => fmc0_tdc_pll_sdi_o,
      pll_cs_o             => fmc0_tdc_pll_cs_n_o,
      pll_dac_sync_o       => fmc0_tdc_pll_dac_sync_n_o,
      pll_sdo_i            => fmc0_tdc_pll_sdo_i,
      pll_status_i         => fmc0_tdc_pll_status_i,
      tdc_clk_125m_p_i     => fmc0_tdc_125m_clk_p_i,
      tdc_clk_125m_n_i     => fmc0_tdc_125m_clk_n_i,
      acam_refclk_p_i      => fmc0_tdc_acam_refclk_p_i,
      acam_refclk_n_i      => fmc0_tdc_acam_refclk_n_i,
      start_from_fpga_o    => fmc0_tdc_start_from_fpga_o,
      err_flag_i           => fmc0_tdc_err_flag_i,
      int_flag_i           => fmc0_tdc_int_flag_i,
      start_dis_o          => fmc0_tdc_start_dis_o,
      stop_dis_o           => fmc0_tdc_stop_dis_o,
      data_bus_io          => fmc0_tdc_data_bus_io,
      address_o            => fmc0_tdc_address_o,
      cs_n_o               => fmc0_tdc_cs_n_o,
      oe_n_o               => fmc0_tdc_oe_n_o,
      rd_n_o               => fmc0_tdc_rd_n_o,
      wr_n_o               => fmc0_tdc_wr_n_o,
      ef1_i                => fmc0_tdc_ef1_i,
      ef2_i                => fmc0_tdc_ef2_i,
      enable_inputs_o      => fmc0_tdc_enable_inputs_o,
      term_en_1_o          => fmc0_tdc_term_en_1_o,
      term_en_2_o          => fmc0_tdc_term_en_2_o,
      term_en_3_o          => fmc0_tdc_term_en_3_o,
      term_en_4_o          => fmc0_tdc_term_en_4_o,
      term_en_5_o          => fmc0_tdc_term_en_5_o,
      tdc_led_status_o     => fmc0_tdc_led_status_o,
      tdc_led_trig1_o      => fmc0_tdc_led_trig1_o,
      tdc_led_trig2_o      => fmc0_tdc_led_trig2_o,
      tdc_led_trig3_o      => fmc0_tdc_led_trig3_o,
      tdc_led_trig4_o      => fmc0_tdc_led_trig4_o,
      tdc_led_trig5_o      => fmc0_tdc_led_trig5_o,
      mezz_scl_i           => '0',
      mezz_sda_i           => '0',
      mezz_scl_o           => open,
      mezz_sda_o           => open,
      mezz_one_wire_b      => fmc0_tdc_one_wire_b,
      tm_link_up_i         => tm_link_up,
      tm_time_valid_i      => tm_time_valid,
      tm_cycles_i          => tm_cycles,
      tm_tai_i             => tm_tai,
      tm_clk_aux_lock_en_o => tm_clk_aux_lock_en(0),
      tm_clk_aux_locked_i  => tm_clk_aux_locked(0),
      tm_clk_dmtd_locked_i => '1',
      tm_dac_value_i       => tm_dac_value,
      tm_dac_wr_i          => tm_dac_wr(0),
      direct_slave_i       => fmc_dp_wb_out(0),
      direct_slave_o       => fmc_dp_wb_in(0),
      slave_i              => cnx_slave_in(c_WB_SLAVE_TDC),
      slave_o              => cnx_slave_out(c_WB_SLAVE_TDC),
      irq_o                => irq_vector(0),
      clk_125m_tdc_o       => tdc_clk_125m);

  -----------------------------------------------------------------------------
  -- FMC FDELAY (SVEC slot #2)
  -----------------------------------------------------------------------------

  cmp_fd_tdc_start1 : IBUFDS
    generic map (
      DIFF_TERM    => TRUE,
      IBUF_LOW_PWR => FALSE)
    port map (
      O  => fmc1_fd_tdc_start,
      I  => fmc1_fd_tdc_start_p_i,
      IB => fmc1_fd_tdc_start_n_i);

  U_DDR_PLL1 : entity work.fd_ddr_pll
    port map (
      RST       => ddr1_pll_reset,
      LOCKED    => ddr1_pll_locked,
      CLK_IN1_P => fmc1_fd_clk_ref_p_i,
      CLK_IN1_N => fmc1_fd_clk_ref_n_i,
      CLK_OUT1  => dcm1_clk_ref_0,
      CLK_OUT2  => dcm1_clk_ref_180);

  ddr1_pll_reset     <= not fmc1_fd_pll_status_i;
  fmc1_fd_pll_status <= fmc1_fd_pll_status_i and ddr1_pll_locked;

  U_FineDelay_Core : entity work.fine_delay_core
    generic map (
      g_FMC_SLOT_ID         => 1,
      g_WITH_WR_CORE        => TRUE,
      g_SIMULATION          => f_int2bool(g_SIMULATION),
      g_INTERFACE_MODE      => PIPELINED,
      g_ADDRESS_GRANULARITY => BYTE)
    port map (
      clk_ref_0_i          => dcm1_clk_ref_0,
      clk_ref_180_i        => dcm1_clk_ref_180,
      clk_sys_i            => clk_sys_62m5,
      clk_dmtd_i           => '0',
      rst_n_i              => rst_sys_62m5_n,
      dcm_reset_o          => open,
      dcm_locked_i         => ddr1_pll_locked,
      trig_a_i             => fmc1_fd_trig_a_i,
      tdc_cal_pulse_o      => fmc1_fd_tdc_cal_pulse_o,
      tdc_start_i          => fmc1_fd_tdc_start,
      dmtd_fb_in_i         => fmc1_fd_dmtd_fb_in_i,
      dmtd_fb_out_i        => fmc1_fd_dmtd_fb_out_i,
      dmtd_samp_o          => fmc1_fd_dmtd_clk_o,
      led_trig_o           => fmc1_fd_led_trig_o,
      ext_rst_n_o          => fmc1_fd_ext_rst_n_o,
      pll_status_i         => fmc1_fd_pll_status,
      acam_d_o             => fmc1_fd_tdc_data_out,
      acam_d_i             => fmc1_fd_tdc_data_in,
      acam_d_oen_o         => fmc1_fd_tdc_data_oe,
      acam_emptyf_i        => fmc1_fd_tdc_emptyf_i,
      acam_alutrigger_o    => fmc1_fd_tdc_alutrigger_o,
      acam_wr_n_o          => fmc1_fd_tdc_wr_n_o,
      acam_rd_n_o          => fmc1_fd_tdc_rd_n_o,
      acam_start_dis_o     => fmc1_fd_tdc_start_dis_o,
      acam_stop_dis_o      => fmc1_fd_tdc_stop_dis_o,
      spi_cs_dac_n_o       => fmc1_fd_spi_cs_dac_n_o,
      spi_cs_pll_n_o       => fmc1_fd_spi_cs_pll_n_o,
      spi_cs_gpio_n_o      => fmc1_fd_spi_cs_gpio_n_o,
      spi_sclk_o           => fmc1_fd_spi_sclk_o,
      spi_mosi_o           => fmc1_fd_spi_mosi_o,
      spi_miso_i           => fmc1_fd_spi_miso_i,
      delay_len_o          => fmc1_fd_delay_len_o,
      delay_val_o          => fmc1_fd_delay_val_o,
      delay_pulse_o        => fmc1_fd_delay_pulse_o,
      tm_link_up_i         => tm_link_up,
      tm_time_valid_i      => tm_time_valid,
      tm_cycles_i          => tm_cycles,
      tm_utc_i             => tm_tai,
      tm_clk_aux_lock_en_o => tm_clk_aux_lock_en(1),
      tm_clk_aux_locked_i  => tm_clk_aux_locked(1),
      tm_clk_dmtd_locked_i => '1',
      tm_dac_value_i       => tm_dac_value,
      tm_dac_wr_i          => tm_dac_wr(1),
      owr_en_o             => fmc1_fd_owr_en,
      owr_i                => fmc1_fd_owr_in,
      i2c_scl_oen_o        => open,
      i2c_scl_i            => '0',
      i2c_sda_oen_o        => open,
      i2c_sda_i            => '0',
      fmc_present_n_i      => '0',
      wb_adr_i             => fmc1_mux_wb_out.adr,
      wb_dat_i             => fmc1_mux_wb_out.dat,
      wb_dat_o             => fmc1_mux_wb_in.dat,
      wb_sel_i             => fmc1_mux_wb_out.sel,
      wb_cyc_i             => fmc1_mux_wb_out.cyc,
      wb_stb_i             => fmc1_mux_wb_out.stb,
      wb_we_i              => fmc1_mux_wb_out.we,
      wb_ack_o             => fmc1_mux_wb_in.ack,
      wb_stall_o           => fmc1_mux_wb_in.stall,
      wb_irq_o             => irq_vector(1));

  cmp_fmc1_wb_mux : xwb_crossbar
    generic map (
      g_VERBOSE     => FALSE,
      g_NUM_MASTERS => 2,
      g_NUM_SLAVES  => 1,
      g_REGISTERED  => TRUE,
      g_ADDRESS     => c_FMC_MUX_ADDR,
      g_MASK        => c_FMC_MUX_MASK)
    port map (
      clk_sys_i   => clk_sys_62m5,
      rst_n_i     => rst_sys_62m5_n,
      slave_i(0)  => fmc_dp_wb_out(1),
      slave_i(1)  => cnx_slave_in(c_WB_SLAVE_FDL),
      slave_o(0)  => fmc_dp_wb_in(1),
      slave_o(1)  => cnx_slave_out(c_WB_SLAVE_FDL),
      master_i(0) => fmc1_mux_wb_in,
      master_o(0) => fmc1_mux_wb_out);

  fmc1_mux_wb_in.err <= '0';
  fmc1_mux_wb_in.rty <= '0';

  -- tristate buffer for the TDC data bus:
  fmc1_fd_tdc_d_b     <= fmc1_fd_tdc_data_out when fmc1_fd_tdc_data_oe = '1' else (others => 'Z');
  fmc1_fd_tdc_oe_n_o  <= '1';
  fmc1_fd_tdc_data_in <= fmc1_fd_tdc_d_b;

  fmc1_fd_onewire_b <= '0' when fmc1_fd_owr_en = '1' else 'Z';
  fmc1_fd_owr_in    <= fmc1_fd_onewire_b;

  -----------------------------------------------------------------------------
  -- Carrier front panel LEDs and LEMOs
  -----------------------------------------------------------------------------

  cmp_led_controller : gc_bicolor_led_ctrl
    generic map(
      g_NB_COLUMN    => 4,
      g_NB_LINE      => 2,
      g_CLK_FREQ     => 62500000,  -- in Hz
      g_REFRESH_RATE => 250        -- in Hz
      )
    port map(
      rst_n_i => rst_sys_62m5_n,
      clk_i   => clk_sys_62m5,

      led_intensity_i => "1100100",  -- in %

      led_state_i => svec_led,

      column_o   => fp_led_column_o,
      line_o     => fp_led_line_o,
      line_oen_o => fp_led_line_oen_o);

  -- LED 4
  svec_led(1 downto 0)   <= c_LED_GREEN     when wr_led_link = '1'          else c_LED_RED;
  -- LED 3
  svec_led(3 downto 2)   <= c_LED_GREEN     when tm_clk_aux_locked(1) = '1' else c_LED_RED;
  -- LED 2
  svec_led(5 downto 4)   <= c_LED_GREEN     when tm_time_valid = '1'        else c_LED_RED;
  -- LED 1
  svec_led(7 downto 6)   <= c_LED_RED_GREEN when vme_access_led = '1'       else c_LED_OFF;
  -- LED 8
  svec_led(9 downto 8)   <= c_LED_RED_GREEN when wr_led_act = '1'           else c_LED_OFF;
  -- LED 7
  svec_led(11 downto 10) <= c_LED_GREEN     when tm_clk_aux_locked(0) = '1' else c_LED_RED;
  -- LED 6
  svec_led(13 downto 12) <= c_LED_OFF;
  -- LED 5
  svec_led(15 downto 14) <= c_LED_GREEN     when pps_led = '1'              else c_LED_OFF;

  -- Front panel IO configuration
  fp_gpio1_b      <= pps;
  fp_gpio2_b      <= '0';
  clk_ext_ref     <= fp_gpio3_b;
  pps_ext_in      <= fp_gpio4_b;
  fp_term_en_o    <= (others => '0');
  fp_gpio1_a2b_o  <= '1';
  fp_gpio2_a2b_o  <= '1';
  fp_gpio34_a2b_o <= '0';

end architecture arch;
