--==============================================================================
-- CERN (BE-CO-HT)
-- CONV-TTL-RS485 PTS top-level file
--==============================================================================
--
-- author: Theodor Stana (t.stana@cern.ch)
--
-- date of creation: 2014-10-30
--
-- version: 1.0
--
--    Top-level file of the HDL for the CONV-TTL-RS485 front-module PTS. All the
--    modules used within the PTS are instantiated and connected here. The logic
--    implemented here will work together with the PTS (Python) software.
--
-- dependencies:
--    - converter board common gateware [1]
--    - general-cores repository [2]
--    - White Rabbit core collection [3]
--
-- references:
--    [1] Converter board common gateware on OHWR,
--        http://www.ohwr.org/projects/conv-common-gw/repository
--    [2] Platform-independent core collection on OHWR,
--        http://www.ohwr.org/projects/general-cores/repository
--    [3] White Rabbit Core Collection on OHWR,
--        http://www.ohwr.org/projects/wr-cores/repository
--
--==============================================================================
-- GNU LESSER GENERAL PUBLIC LICENSE
--==============================================================================
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--==============================================================================
-- last changes:
--    2014-10-30   Theodor Stana     File created
--==============================================================================
-- TODO: -
--==============================================================================

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

library unisim;
use unisim.vcomponents.all;

use work.conv_common_gw_pkg.all;

use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.genram_pkg.all;
use work.wr_fabric_pkg.all;
use work.wrcore_pkg.all;
use work.endpoint_pkg.all;

entity pts is
  port
  (
    -- Clocks
    clk_20_i                : in  std_logic;
    clk_125_p_i             : in  std_logic;
    clk_125_n_i             : in  std_logic;

    -- I2C interface
    scl_i                   : in  std_logic;
    scl_o                   : out std_logic;
    scl_en_o                : out std_logic;
    sda_i                   : in  std_logic;
    sda_o                   : out std_logic;
    sda_en_o                : out std_logic;

    -- VME interface
    vme_sysreset_n_i        : in  std_logic;
    vme_ga_i                : in  std_logic_vector(4 downto 0);
    vme_gap_i               : in  std_logic;

    -- Channel enable
    global_oen_o           : out std_logic;
    ttl_oen_o              : out std_logic;
    inv_oen_o              : out std_logic;
    rs485_oen_o            : out std_logic;

    -- Front panel channels
    ttl_n_i                 : in  std_logic_vector(5 downto 0);
    ttl_o                   : out std_logic_vector(5 downto 0);
    inv_n_i                 : in  std_logic_vector(3 downto 0);
    inv_o                   : out std_logic_vector(3 downto 0);

    -- Rear panel channels
    rs485_n_i               : in  std_logic_vector(5 downto 0);
    rs485_fs_n_i            : in  std_logic_vector(5 downto 0);
    rs485_o                 : out std_logic_vector(5 downto 0);

    -- Rear input and output termination lines
    iterm_en_o              : out std_logic_vector(5 downto 0);
    oterm_en_o              : out std_logic_vector(5 downto 0);

    -- Channel leds
    led_front_o             : out std_logic_vector(5 downto 0);
    led_inv_o               : out std_logic_vector(3 downto 0);
    led_rear_n_o            : out std_logic_vector(5 downto 0);

    -- SPI interface to on-board flash chip
    flash_cs_n_o            : out std_logic;
    flash_sclk_o            : out std_logic;
    flash_mosi_o            : out std_logic;
    flash_miso_i            : in  std_logic;

    -- PLL DACs
    -- 20 MHz VCXO control
    dac_20_din_o            : out std_logic;
    dac_20_sclk_o           : out std_logic;
    dac_20_sync_n_o         : out std_logic;
    -- 125 MHz clock generator control
    dac_125_din_o           : out std_logic;
    dac_125_sclk_o          : out std_logic;
    dac_125_sync_n_o        : out std_logic;

    -- SFP lines
    sfp_los_i               : in    std_logic;
    sfp_present_i           : in    std_logic;
    sfp_rate_select_o       : out   std_logic;
    sfp_scl_b               : inout std_logic;
    sfp_sda_b               : inout std_logic;
    sfp_tx_disable_o        : out   std_logic;
    sfp_tx_fault_i          : in    std_logic;

    -- FPGA MGT lines
    mgt_clk0_p_i            : in    std_logic;
    mgt_clk0_n_i            : in    std_logic;
    mgt_sfp_rx0_p_i         : in    std_logic;
    mgt_sfp_rx0_n_i         : in    std_logic;
    mgt_sfp_tx0_p_o         : out   std_logic;
    mgt_sfp_tx0_n_o         : out   std_logic;

    -- Thermometer data port
    thermometer_b           : inout std_logic;

    -- Switches
    sw_gp_n_i               : in   std_logic_vector(7 downto 0);
    sw_multicast_n_i        : in   std_logic_vector(3 downto 0);

    -- RTM lines
    rtmm_i                  : in  std_logic_vector(2 downto 0);
    rtmp_i                  : in  std_logic_vector(2 downto 0);

    -- Front panel bicolor LEDs
    led_ctrl0_o             : out std_logic;
    led_ctrl0_oen_o         : out std_logic;
    led_ctrl1_o             : out std_logic;
    led_ctrl1_oen_o         : out std_logic;
    led_gp_2_4_o            : out std_logic;
    led_gp_1_3_o            : out std_logic;
    led_oterm_wr_o          : out std_logic;
    led_iterm_syserror_o    : out std_logic;
    led_gf_syspw_o          : out std_logic;
    led_ttl_i2c_o           : out std_logic
  );
end entity pts;


architecture arch of pts is

  --============================================================================
  -- Type declarations
  --============================================================================
  -- Pulse counter register and load value types
  type t_pcr is array (15 downto 0) of unsigned(31 downto 0);
  type t_pcr_ldval is array (15 downto 0) of std_logic_vector(31 downto 0);
  type t_pulse_led_cnt is array(9 downto 0) of unsigned(18 downto 0);

  --============================================================================
  -- Constant declarations
  --============================================================================
  -- Board ID constant
  constant c_board_id         : std_logic_vector(31 downto 0) := x"54343835";
  -- Number of Wishbone masters and slaves, for wb_crossbar
  constant c_nr_masters       : natural :=  1;
  constant c_nr_slaves        : natural :=  11;

  -- slave order definitions
  constant c_slv_pts_regs      : natural :=  0;
  constant c_slv_onewire_mst   : natural :=  1;
  constant c_slv_dac_spi_125   : natural :=  2;
  constant c_slv_dac_spi_20    : natural :=  3;
  constant c_slv_clk_info_125  : natural :=  4;
  constant c_slv_clk_info_20   : natural :=  5;
  constant c_slv_sfp_i2c       : natural :=  6;
  constant c_slv_minic         : natural :=  7;
  constant c_slv_endpoint      : natural :=  8;
  constant c_slv_dpram         : natural :=  9;
  constant c_slv_pulse_cntrs   : natural := 10;

  -- base address definitions
  constant c_addr_pts_regs     : t_wishbone_address := x"00000000";
  constant c_addr_onewire_mst  : t_wishbone_address := x"00000010";
  constant c_addr_dac_spi_125  : t_wishbone_address := x"00000020";
  constant c_addr_dac_spi_20   : t_wishbone_address := x"00000080";
  constant c_addr_clk_info_125 : t_wishbone_address := x"00000100";
  constant c_addr_clk_info_20  : t_wishbone_address := x"00000120";
  constant c_addr_sfp_i2c      : t_wishbone_address := x"00000140";
  constant c_addr_endpoint     : t_wishbone_address := x"00000200";
  constant c_addr_minic        : t_wishbone_address := x"00000400";
  constant c_addr_dpram        : t_wishbone_address := x"00000800";
  constant c_addr_pulse_cntrs  : t_wishbone_address := x"00000c00";

  -- address mask definitions
  constant c_mask_pts_regs     : t_wishbone_address := x"00000ff0";
  constant c_mask_onewire_mst  : t_wishbone_address := x"00000ff0";
  constant c_mask_dac_spi_125  : t_wishbone_address := x"00000fe0";
  constant c_mask_dac_spi_20   : t_wishbone_address := x"00000fe0";
  constant c_mask_clk_info_125 : t_wishbone_address := x"00000f60";
  constant c_mask_clk_info_20  : t_wishbone_address := x"00000f60";
  constant c_mask_sfp_i2c      : t_wishbone_address := x"00000f60";
  constant c_mask_endpoint     : t_wishbone_address := x"00000e00";
  constant c_mask_minic        : t_wishbone_address := x"00000c00";
  constant c_mask_dpram        : t_wishbone_address := x"00000c00";
  constant c_mask_pulse_cntrs  : t_wishbone_address := x"00000c00";

  -- addresses constant for Wishbone crossbar
  constant c_addresses  : t_wishbone_address_array(c_nr_slaves-1 downto 0)
                        := (
                             c_slv_pts_regs     => c_addr_pts_regs,
                             c_slv_onewire_mst  => c_addr_onewire_mst,
                             c_slv_dac_spi_125  => c_addr_dac_spi_125,
                             c_slv_clk_info_125 => c_addr_clk_info_125,
                             c_slv_dac_spi_20   => c_addr_dac_spi_20,
                             c_slv_clk_info_20  => c_addr_clk_info_20,
                             c_slv_sfp_i2c      => c_addr_sfp_i2c,
                             c_slv_endpoint     => c_addr_endpoint,
                             c_slv_minic        => c_addr_minic,
                             c_slv_dpram        => c_addr_dpram,
                             c_slv_pulse_cntrs  => c_addr_pulse_cntrs
                           );

  -- masks constant for Wishbone crossbar
  constant c_masks      : t_wishbone_address_array(c_nr_slaves-1 downto 0)
                        := (
                             c_slv_pts_regs     => c_mask_pts_regs,
                             c_slv_onewire_mst  => c_mask_onewire_mst,
                             c_slv_dac_spi_125  => c_mask_dac_spi_125,
                             c_slv_clk_info_125 => c_mask_clk_info_125,
                             c_slv_dac_spi_20   => c_mask_dac_spi_20,
                             c_slv_clk_info_20  => c_mask_clk_info_20,
                             c_slv_sfp_i2c      => c_mask_sfp_i2c,
                             c_slv_endpoint     => c_mask_endpoint,
                             c_slv_minic        => c_mask_minic,
                             c_slv_dpram        => c_mask_dpram,
                             c_slv_pulse_cntrs  => c_mask_pulse_cntrs
                           );

  -- MiniNIC log2 of memory size
  constant c_minic_memsize_log2 : natural := 10;

  --============================================================================
  -- Component declarations
  --============================================================================
  -- Regs to test I2C operation
  component pts_regs is
    port (
      rst_n_i                                  : in     std_logic;
      clk_sys_i                                : in     std_logic;
      wb_adr_i                                 : in     std_logic_vector(1 downto 0);
      wb_dat_i                                 : in     std_logic_vector(31 downto 0);
      wb_dat_o                                 : out    std_logic_vector(31 downto 0);
      wb_cyc_i                                 : in     std_logic;
      wb_sel_i                                 : in     std_logic_vector(3 downto 0);
      wb_stb_i                                 : in     std_logic;
      wb_we_i                                  : in     std_logic;
      wb_ack_o                                 : out    std_logic;
      wb_stall_o                               : out    std_logic;
  -- Port for std_logic_vector field: 'ID register bits' in reg: 'BIDR'
      pts_bidr_i                               : in     std_logic_vector(31 downto 0);
  -- Port for BIT field: 'Front pulse LED enable' in reg: 'CSR'
      pts_csr_chledt_o                         : out    std_logic;
  -- Port for BIT field: 'Status LED enable' in reg: 'CSR'
      pts_csr_stledt_o                         : out    std_logic;
  -- Port for BIT field: 'Rear pulse LED enable' in reg: 'CSR'
      pts_csr_rledt_o                          : out    std_logic;
  -- Port for BIT field: 'TTL test enable' in reg: 'CSR'
      pts_csr_ttlpt_o                          : out    std_logic;
  -- Port for BIT field: 'RS485 pulse enable' in reg: 'CSR'
      pts_csr_rearpt_o                         : out    std_logic;
  -- Port for BIT field: 'RS485 tester card VCC' in reg: 'CSR'
      pts_csr_tstcvcc_o                        : out    std_logic;
  -- Port for BIT field: 'RS485 tester card MUX enable' in reg: 'CSR'
      pts_csr_tstcmuxen_o                      : out    std_logic;
  -- Port for BIT field: 'RS485 tester card MUX S0 line' in reg: 'CSR'
      pts_csr_tstcs0_o                         : out    std_logic;
  -- Port for BIT field: 'RS485 tester card MUX S1 line' in reg: 'CSR'
      pts_csr_tstcs1_o                         : out    std_logic;
  -- Ports for BIT field: 'Reset unlock bit' in reg: 'CSR'
      pts_csr_rst_unlock_o                     : out    std_logic;
      pts_csr_rst_unlock_i                     : in     std_logic;
      pts_csr_rst_unlock_load_o                : out    std_logic;
  -- Ports for BIT field: 'Reset bit' in reg: 'CSR'
      pts_csr_rst_o                            : out    std_logic;
      pts_csr_rst_i                            : in     std_logic;
      pts_csr_rst_load_o                       : out    std_logic;
  -- Port for std_logic_vector field: 'switches' in reg: 'CSR'
      pts_csr_switch_i                         : in     std_logic_vector(7 downto 0);
  -- Port for std_logic_vector field: 'RTM' in reg: 'CSR'
      pts_csr_rtm_i                            : in     std_logic_vector(5 downto 0);
  -- Ports for BIT field: 'I2C communication error' in reg: 'CSR'
      pts_csr_i2c_err_o                        : out    std_logic;
      pts_csr_i2c_err_i                        : in     std_logic;
      pts_csr_i2c_err_load_o                   : out    std_logic;
  -- Ports for BIT field: 'I2C communication watchdog timeout error' in reg: 'CSR'
      pts_csr_i2c_wdto_o                       : out    std_logic;
      pts_csr_i2c_wdto_i                       : in     std_logic;
      pts_csr_i2c_wdto_load_o                  : out    std_logic;
  -- Port for std_logic_vector field: 'Front panel channel input state' in reg: 'LSR'
      pts_lsr_front_i                          : in     std_logic_vector(5 downto 0);
  -- Port for std_logic_vector field: 'Front panel INV-TTL input state' in reg: 'LSR'
      pts_lsr_frontinv_i                       : in     std_logic_vector(3 downto 0);
  -- Port for std_logic_vector field: 'Rear panel input state' in reg: 'LSR'
      pts_lsr_rear_i                           : in     std_logic_vector(5 downto 0);
  -- Port for std_logic_vector field: 'Front panel input failsafe state' in reg: 'LSR'
      pts_lsr_frontfs_i                        : in     std_logic_vector(5 downto 0);
  -- Port for std_logic_vector field: 'Front panel inverter input failsafe state' in reg: 'LSR'
      pts_lsr_frontinvfs_i                     : in     std_logic_vector(3 downto 0);
  -- Port for std_logic_vector field: 'Rear panel input failsafe state' in reg: 'LSR'
      pts_lsr_rearfs_i                         : in     std_logic_vector(5 downto 0);
  -- Port for std_logic_vector field: 'Input termination enable' in reg: 'TER'
      pts_ter_iterm_o                          : out    std_logic_vector(5 downto 0);
  -- Port for std_logic_vector field: 'Output termination enable' in reg: 'TER'
      pts_ter_oterm_o                          : out    std_logic_vector(5 downto 0)
    );
  end component pts_regs;

  -- General-purpose pulse generator
  component pulse_gen_gp is
    port
    (
      -- Input clock and active-low reset
      clk_i    : in  std_logic;
      rst_n_i  : in  std_logic;

      -- Active high enable signal
      en_i     : in  std_logic;

      -- Delay, pulse width and frequency inputs, in number of clk_i cycles
      delay_i  : in  std_logic_vector(31 downto 0);
      pwidth_i : in  std_logic_vector(31 downto 0);
      per_i    : in  std_logic_vector(31 downto 0);

      -- Output pulse signal
      pulse_o  : out std_logic
    );
  end component pulse_gen_gp;

  component pulse_cnt_wb is
    port (
      rst_n_i                                  : in     std_logic;
      clk_sys_i                                : in     std_logic;
      wb_adr_i                                 : in     std_logic_vector(4 downto 0);
      wb_dat_i                                 : in     std_logic_vector(31 downto 0);
      wb_dat_o                                 : out    std_logic_vector(31 downto 0);
      wb_cyc_i                                 : in     std_logic;
      wb_sel_i                                 : in     std_logic_vector(3 downto 0);
      wb_stb_i                                 : in     std_logic;
      wb_we_i                                  : in     std_logic;
      wb_ack_o                                 : out    std_logic;
      wb_stall_o                               : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH1OCR'
      pulse_cnt_ttlch1o_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch1o_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch1o_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH1ICR'
      pulse_cnt_ttlch1i_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch1i_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch1i_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH2OCR'
      pulse_cnt_ttlch2o_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch2o_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch2o_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH2ICR'
      pulse_cnt_ttlch2i_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch2i_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch2i_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH3OCR'
      pulse_cnt_ttlch3o_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch3o_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch3o_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH3ICR'
      pulse_cnt_ttlch3i_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch3i_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch3i_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH4OCR'
      pulse_cnt_ttlch4o_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch4o_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch4o_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH4ICR'
      pulse_cnt_ttlch4i_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch4i_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch4i_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH5OCR'
      pulse_cnt_ttlch5o_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch5o_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch5o_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH5ICR'
      pulse_cnt_ttlch5i_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch5i_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch5i_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH6OCR'
      pulse_cnt_ttlch6o_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch6o_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch6o_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'TTLCH6ICR'
      pulse_cnt_ttlch6i_o                      : out    std_logic_vector(31 downto 0);
      pulse_cnt_ttlch6i_i                      : in     std_logic_vector(31 downto 0);
      pulse_cnt_ttlch6i_load_o                 : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHAOCR'
      pulse_cnt_invttlchao_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchao_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchao_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHAICR'
      pulse_cnt_invttlchai_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchai_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchai_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHBOCR'
      pulse_cnt_invttlchbo_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchbo_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchbo_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHBICR'
      pulse_cnt_invttlchbi_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchbi_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchbi_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHCOCR'
      pulse_cnt_invttlchco_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchco_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchco_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHCICR'
      pulse_cnt_invttlchci_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchci_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchci_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHDOCR'
      pulse_cnt_invttlchdo_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchdo_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchdo_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'INVTTLCHDICR'
      pulse_cnt_invttlchdi_o                   : out    std_logic_vector(31 downto 0);
      pulse_cnt_invttlchdi_i                   : in     std_logic_vector(31 downto 0);
      pulse_cnt_invttlchdi_load_o              : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH1OCR'
      pulse_cnt_rearch1o_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch1o_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch1o_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH1ICR'
      pulse_cnt_rearch1i_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch1i_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch1i_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH2OCR'
      pulse_cnt_rearch2o_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch2o_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch2o_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH2ICR'
      pulse_cnt_rearch2i_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch2i_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch2i_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH3OCR'
      pulse_cnt_rearch3o_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch3o_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch3o_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH3ICR'
      pulse_cnt_rearch3i_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch3i_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch3i_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH4OCR'
      pulse_cnt_rearch4o_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch4o_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch4o_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH4ICR'
      pulse_cnt_rearch4i_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch4i_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch4i_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH5OCR'
      pulse_cnt_rearch5o_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch5o_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch5o_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH5ICR'
      pulse_cnt_rearch5i_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch5i_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch5i_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH6OCR'
      pulse_cnt_rearch6o_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch6o_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch6o_load_o                : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'REARCH6ICR'
      pulse_cnt_rearch6i_o                     : out    std_logic_vector(31 downto 0);
      pulse_cnt_rearch6i_i                     : in     std_logic_vector(31 downto 0);
      pulse_cnt_rearch6i_load_o                : out    std_logic
    );
  end component pulse_cnt_wb;

  -- Incremental counter component
  -- use: DAC, PLL & VCXO test
  component incr_counter is
    generic
    (
      width             : integer := 32 -- default size
    );
    port
    (
      -- INPUTS
      -- Signals from the clk_rst_manager
      clk_i             : in std_logic;
      rst_i             : in std_logic;

      -- Signals from any unit
      counter_top_i     : in std_logic_vector(width-1 downto 0); -- max value to be counted; when reached
                                                                 -- counter stays at it, until a reset
      counter_incr_en_i : in std_logic;   -- enables counting

     -- OUTPUTS
     -- Signals to any unit
      counter_o         : out std_logic_vector(width-1 downto 0);
      counter_is_full_o : out std_logic
    ); -- counter reahed counter_top_i value
  end component incr_counter;

  -- Clock info component
  -- use: DAC, PLL & VCXO test
  component clk_info_wb_slave is
    port
    (
      -- WISHBONE slave signals
      wb_clk_i          : in  std_logic;
      rst_i             : in  std_logic;
      wb_cyc_i          : in  std_logic;
      wb_stb_i          : in  std_logic;
      wb_addr_i         : in  std_logic_vector( 2 downto 0);
      wb_data_i         : in  std_logic_vector(31 downto 0);
      wb_we_i           : in  std_logic;
      wb_data_o         : out std_logic_vector(31 downto 0);
      wb_ack_o          : out std_logic;
       -- Clock info signals
      counter_is_full_i : in std_logic;
      counter_now_i     : in std_logic_vector (31 downto 0);
      counter_top_o     : out std_logic_vector (31 downto 0);
      counter_rst_o     : out std_logic;
      counter_en_o      : out std_logic;
      oe_clk_o          : out std_logic
    );
  end component clk_info_wb_slave;

  -- GTP component
  component wr_gtp_phy_spartan6
    generic (
      g_simulation      : integer;
      g_force_disparity : integer;
      g_enable_ch0      : integer;
      g_enable_ch1      : integer);
    port (
      gtp_clk_i          : in  std_logic;
      ch0_ref_clk_i      : in  std_logic                    := '0';
      ch0_tx_data_i      : in  std_logic_vector(7 downto 0) := "00000000";
      ch0_tx_k_i         : in  std_logic                    := '0';
      ch0_tx_disparity_o : out std_logic;
      ch0_tx_enc_err_o   : out std_logic;
      ch0_rx_rbclk_o     : out std_logic;
      ch0_rx_data_o      : out std_logic_vector(7 downto 0);
      ch0_rx_k_o         : out std_logic;
      ch0_rx_enc_err_o   : out std_logic;
      ch0_rx_bitslide_o  : out std_logic_vector(3 downto 0);
      ch0_rst_i          : in  std_logic                    := '0';
      ch0_loopen_i       : in  std_logic                    := '0';
      ch1_ref_clk_i      : in  std_logic                    := '0';
      ch1_tx_data_i      : in  std_logic_vector(7 downto 0) := "00000000";
      ch1_tx_k_i         : in  std_logic                    := '0';
      ch1_tx_disparity_o : out std_logic;
      ch1_tx_enc_err_o   : out std_logic;
      ch1_rx_data_o      : out std_logic_vector(7 downto 0);
      ch1_rx_rbclk_o     : out std_logic;
      ch1_rx_k_o         : out std_logic;
      ch1_rx_enc_err_o   : out std_logic;
      ch1_rx_bitslide_o  : out std_logic_vector(3 downto 0);
      ch1_rst_i          : in  std_logic                    := '0';
      ch1_loopen_i       : in  std_logic                    := '0';
      pad_txn0_o         : out std_logic;
      pad_txp0_o         : out std_logic;
      pad_rxn0_i         : in  std_logic                    := '0';
      pad_rxp0_i         : in  std_logic                    := '0';
      pad_txn1_o         : out std_logic;
      pad_txp1_o         : out std_logic;
      pad_rxn1_i         : in  std_logic                    := '0';
      pad_rxp1_i         : in  std_logic                    := '0');
  end component;

  --============================================================================
  -- Signal declarations
  --============================================================================
  -- Clock signals
  signal clk_125                : std_logic;

  -- Reset signals
  signal rst_20_n               : std_logic;
  signal rst_20                 : std_logic;
  signal rst_125_n              : std_logic;
  signal rst_ext                : std_logic;

  -- I2C bridge signals
  signal i2c_addr               : std_logic_vector(6 downto 0);
  signal i2c_tip                : std_logic;
  signal i2c_err_p              : std_logic;
  signal i2c_wdto_p             : std_logic;

  -- Wishbone crossbar signals
  signal xbar_slave_in          : t_wishbone_slave_in_array(c_nr_masters-1 downto 0);
  signal xbar_slave_out         : t_wishbone_slave_out_array(c_nr_masters-1 downto 0);
  signal xbar_master_in         : t_wishbone_master_in_array(c_nr_slaves-1 downto 0);
  signal xbar_master_out        : t_wishbone_master_out_array(c_nr_slaves-1 downto 0);

  -- LED signals
  signal cnt_halfsec            : unsigned(23 downto 0);
  signal led_seq                : unsigned(4 downto 0);
  signal pulse_led_en           : std_logic;
  signal stat_led_en            : std_logic;
  signal pulse_led_en_d0        : std_logic;
  signal stat_led_en_d0         : std_logic;
  signal front_led_en_risedge_p : std_logic;
  signal stat_led_en_risedge_p  : std_logic;
  signal front_led_seq          : std_logic_vector( 5 downto 0);
  signal inv_led                : std_logic_vector( 3 downto 0);
  signal inv_led_seq            : std_logic_vector( 3 downto 0);
  signal front_led              : std_logic_vector( 9 downto 0);
  signal front_led_cnt          : t_pulse_led_cnt;
  signal bicolor_led_state      : std_logic_vector(23 downto 0);
  signal rear_led_seq           : std_logic_vector( 5 downto 0);
  signal rear_led               : std_logic_vector( 5 downto 0);
  signal rear_led_cnt           : t_pulse_led_cnt;

  -- Signals to/from PTS regs component
  signal rst_unlock_ld          : std_logic;
  signal rst_unlock_ldval       : std_logic;
  signal rst_unlock             : std_logic;
  signal rst_bit_ld             : std_logic;
  signal rst_bit_ldval          : std_logic;
  signal rst_bit                : std_logic;
  signal i2c_wdto_bit           : std_logic;
  signal i2c_wdto_bit_rst       : std_logic;
  signal i2c_wdto_bit_rst_ld    : std_logic;
  signal i2c_err_bit            : std_logic;
  signal i2c_err_bit_rst        : std_logic;
  signal i2c_err_bit_rst_ld     : std_logic;
  signal rtm_lines              : std_logic_vector(5 downto 0);
  signal switches               : std_logic_vector(7 downto 0);
  signal line_front             : std_logic_vector(5 downto 0);
  signal line_inv               : std_logic_vector(3 downto 0);
  signal line_rear              : std_logic_vector(5 downto 0);
  signal line_rear_fs           : std_logic_vector(5 downto 0);

  -- PLL & DAC test signals
  signal cnt_125                : std_logic_vector(31 downto 0);
  signal cnt_125_top            : std_logic_vector(31 downto 0);
  signal cnt_125_en             : std_logic;
  signal cnt_125_rst            : std_logic;
  signal cnt_125_full           : std_logic;
  signal cnt_125_a              : std_logic_vector(31 downto 0);
  signal cnt_125_top_a          : std_logic_vector(31 downto 0);
  signal cnt_125_en_a           : std_logic;
  signal cnt_125_rst_a          : std_logic;
  signal cnt_125_full_a         : std_logic;
  signal cnt_125_actual_rst     : std_logic;
  signal dac_125_sync_n         : std_logic_vector(7 downto 0);

  signal cnt_20                 : std_logic_vector(31 downto 0);
  signal cnt_20_top             : std_logic_vector(31 downto 0);
  signal cnt_20_en              : std_logic;
  signal cnt_20_rst             : std_logic;
  signal cnt_20_full            : std_logic;
  signal cnt_20_actual_rst      : std_logic;
  signal dac_20_sync_n          : std_logic_vector(7 downto 0);

  -- SFP EEPROM signals
  signal i2c_scl_fr_sfp         : std_logic;
  signal i2c_scl_to_sfp         : std_logic;
  signal i2c_sfp_scl_en         : std_logic;

  signal i2c_sda_fr_sfp         : std_logic;
  signal i2c_sda_to_sfp         : std_logic;
  signal i2c_sfp_sda_en         : std_logic;

  -- SFP signals
  signal clk_gtp                : std_logic;

  signal minic_mem_data_out     : std_logic_vector(31 downto 0);
  signal minic_mem_addr_out     : std_logic_vector(c_minic_memsize_log2-1 downto 0);
  signal minic_mem_data_in      : std_logic_vector(31 downto 0);
  signal minic_mem_wr           : std_logic;
  signal minic_src_out          : t_wrf_source_out;
  signal minic_src_in           : t_wrf_source_in;
  signal minic_snk_out          : t_wrf_sink_out;
  signal minic_snk_in           : t_wrf_sink_in;

  signal phy_rst                : std_logic;
  signal phy_loopen             : std_logic;
  signal phy_tx_d               : std_logic_vector(15 downto 0);
  signal phy_tx_k               : std_logic_vector( 1 downto 0);
  signal phy_tx_disparity       : std_logic;
  signal phy_tx_error           : std_logic;
  signal phy_rx_d               : std_logic_vector(15 downto 0);
  signal phy_rx_clk             : std_logic;
  signal phy_rx_k               : std_logic_vector( 1 downto 0);
  signal phy_rx_error           : std_logic;
  signal phy_rx_bitslide        : std_logic_vector( 4 downto 0);

  signal dpram_we               : std_logic;
  signal dpram_ack              : std_logic;

  -- one-wire master signals
  signal owr_pwren              : std_logic_vector(0 downto 0);
  signal owr_en                 : std_logic_vector(0 downto 0);
  signal owr_in                 : std_logic_vector(0 downto 0);

  -- TTL pulse test signals
  signal front_pulse_en         : std_logic;
  signal front_trigs_a          : std_logic_vector(9 downto 0);
  signal front_trigs            : std_logic_vector(9 downto 0);
  signal front_trigs_redge_p    : std_logic_vector(9 downto 0);
  signal front_pulses           : std_logic_vector(9 downto 0);
  signal front_pulses_d0        : std_logic_vector(9 downto 0);
  signal front_pulses_redge_p   : std_logic_vector(9 downto 0);

  -- Rear panel test signals
  signal tester_vcc             : std_logic;
  signal tester_mux_en          : std_logic;
  signal tester_s0              : std_logic;
  signal tester_s1              : std_logic;
  signal tester_ctrl            : std_logic_vector(3 downto 0);
  signal rear_pulse_en          : std_logic;
  signal rear_pulses            : std_logic_vector(5 downto 0);
  signal rear_pulses_d0         : std_logic_vector(5 downto 0);
  signal rear_pulses_redge_p    : std_logic_vector(5 downto 0);
  signal rear_trigs_a           : std_logic_vector(5 downto 0);
  signal rear_trigs             : std_logic_vector(5 downto 0);
  signal rear_trigs_redge_p     : std_logic_vector(5 downto 0);
	signal rs485_fs               : std_logic_vector(5 downto 0);

  -- Pulse counter register signals
  signal ipcr_ld                : std_logic_vector(15 downto 0);
  signal ipcr_ldval             : t_pcr_ldval;
  signal ipcr                   : t_pcr;
  signal opcr_ld                : std_logic_vector(15 downto 0);
  signal opcr_ldval             : t_pcr_ldval;
  signal opcr                   : t_pcr;

--==============================================================================
--  architecture begin
--==============================================================================
begin

  --============================================================================
  -- Differential input buffer for 125 MHz clock
  --============================================================================
  cmp_clk_125_buf : IBUFGDS
    generic map (
      DIFF_TERM    => true,  -- Differential Termination
      IBUF_LOW_PWR => true,  -- Low power (TRUE) vs. performance (FALSE) setting
                             -- for referenced I/O standards
      IOSTANDARD   => "DEFAULT")
    port map
    (
      O  => clk_125,
      I  => clk_125_p_i,
      IB => clk_125_n_i
    );

  --============================================================================
  -- Internal reset generation
  --============================================================================
  -- External reset input to reset generator
  rst_ext <= rst_bit or (not vme_sysreset_n_i);

  -- Configure reset generator for 100ms reset
  cmp_reset_gen : conv_reset_gen
    generic map
    (
      -- Reset time: 50ns * 2 * (10**6) = 100 ms
      g_reset_time => 2*(10**6)
    )
    port map
    (
      clk_i   => clk_20_i,
      rst_i   => rst_ext,
      rst_n_o => rst_20_n
    );

  -- Create an active-high reset signal
  rst_20 <= not rst_20_n;

  -- Create a reset signal in the 125-MHz clock domain
  cmp_rst_125_sync : gc_sync_ffs
    port map
    (
      clk_i    => clk_125,
      rst_n_i  => '1',
      data_i   => rst_20_n,
      synced_o => rst_125_n
    );

  --============================================================================
  -- I2C bridge logic
  --============================================================================
  -- Set the I2C address signal according to ELMA protocol [2]
  i2c_addr <= "10" & vme_ga_i;

  -- Instantiate I2C bridge component
  --
  -- FSM watchdog timeout timer:
  -- * consider bit period of 30 us
  -- * 10 bits / byte transfer => 300 us
  -- * 40 bytes in one transfer => 12000 us
  -- * clk_i period = 50 ns => g_fsm_wdt = 12000 us / 50 ns = 240000
  -- * multiply by two for extra safety => g_fsm_wdt = 480000
  -- * Time to watchdog timeout: 480000 * 50ns = 24 ms
  cmp_i2c_bridge : wb_i2c_bridge
    generic map
    (
      g_fsm_wdt => 480000
    )
    port map
    (
      -- Clock, reset
      clk_i      => clk_20_i,
      rst_n_i    => rst_20_n,

      -- I2C lines
      scl_i      => scl_i,
      scl_o      => scl_o,
      scl_en_o   => scl_en_o,
      sda_i      => sda_i,
      sda_o      => sda_o,
      sda_en_o   => sda_en_o,

      -- I2C address and status
      i2c_addr_i => i2c_addr,

      -- TIP and ERR outputs
      tip_o      => i2c_tip,
      err_p_o    => i2c_err_p,
      wdto_p_o   => i2c_wdto_p,

      -- Wishbone master signals
      wbm_stb_o  => xbar_slave_in(0).stb,
      wbm_cyc_o  => xbar_slave_in(0).cyc,
      wbm_sel_o  => xbar_slave_in(0).sel,
      wbm_we_o   => xbar_slave_in(0).we,
      wbm_dat_i  => xbar_slave_out(0).dat,
      wbm_dat_o  => xbar_slave_in(0).dat,
      wbm_adr_o  => xbar_slave_in(0).adr,
      wbm_ack_i  => xbar_slave_out(0).ack,
      wbm_rty_i  => xbar_slave_out(0).rty,
      wbm_err_i  => xbar_slave_out(0).err
    );

  -- Register for the I2C_WDTO bit in the SR, cleared by writing a '1'
  p_sr_wdto_bit : process(clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        i2c_wdto_bit <= '0';
      elsif (i2c_wdto_p = '1') then
        i2c_wdto_bit <= '1';
      elsif (i2c_wdto_bit_rst_ld = '1') and (i2c_wdto_bit_rst = '1') then
        i2c_wdto_bit <= '0';
      end if;
    end if;
  end process p_sr_wdto_bit;

  -- Register for the I2C_ERR bit in the SR
  p_i2c_err_led : process(clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        i2c_err_bit <= '0';
      elsif (i2c_err_p = '1') then
        i2c_err_bit <= '1';
      elsif (i2c_err_bit_rst_ld = '1') and (i2c_err_bit_rst = '1') then
        i2c_err_bit <= '0';
      end if;
    end if;
  end process p_i2c_err_led;

  --============================================================================
  -- Instantiation and connection of the main Wishbone crossbar
  --============================================================================
  cmp_wb_crossbar : xwb_crossbar
    generic map
    (
      g_num_masters => c_nr_masters,
      g_num_slaves  => c_nr_slaves,
      g_registered  => false,
      g_address     => c_addresses,
      g_mask        => c_masks
    )
    port map
    (
      clk_sys_i => clk_20_i,
      rst_n_i   => rst_20_n,
      slave_i   => xbar_slave_in,
      slave_o   => xbar_slave_out,
      master_i  => xbar_master_in,
      master_o  => xbar_master_out
    );

  --============================================================================
  -- PTS registers
  --============================================================================
  -- RTM lines combo
  rtm_lines <= rtmp_i & rtmm_i;
  switches  <= not sw_gp_n_i;

  -- LSR signals
  line_front   <= not (ttl_n_i);
  line_inv     <= not (inv_n_i);
  line_rear    <= not (rs485_n_i);
  line_rear_fs <= rs485_fs;

  -- Regs to test I2C operation
  cmp_pts_regs : pts_regs
    port map
    (
      rst_n_i        => rst_20_n,
      clk_sys_i      => clk_20_i,
      wb_adr_i       => xbar_master_out(c_slv_pts_regs).adr(3 downto 2),
      wb_dat_i       => xbar_master_out(c_slv_pts_regs).dat,
      wb_dat_o       => xbar_master_in(c_slv_pts_regs).dat,
      wb_cyc_i       => xbar_master_out(c_slv_pts_regs).cyc,
      wb_sel_i       => xbar_master_out(c_slv_pts_regs).sel,
      wb_stb_i       => xbar_master_out(c_slv_pts_regs).stb,
      wb_we_i        => xbar_master_out(c_slv_pts_regs).we,
      wb_ack_o       => xbar_master_in(c_slv_pts_regs).ack,
      wb_stall_o     => xbar_master_in(c_slv_pts_regs).stall,

      -- Board ID register
      pts_bidr_i     => c_board_id,

      -- PTS control register
      pts_csr_chledt_o          => pulse_led_en,
      pts_csr_stledt_o          => stat_led_en,
      pts_csr_rledt_o           => open,
      pts_csr_ttlpt_o           => front_pulse_en,
      pts_csr_rearpt_o          => rear_pulse_en,
      pts_csr_tstcvcc_o         => tester_vcc,
      pts_csr_tstcmuxen_o       => tester_mux_en,
      pts_csr_tstcs0_o          => tester_s0,
      pts_csr_tstcs1_o          => tester_s1,
      pts_csr_rst_unlock_o      => rst_unlock_ldval,
      pts_csr_rst_unlock_i      => rst_unlock,
      pts_csr_rst_unlock_load_o => rst_unlock_ld,
      pts_csr_rst_o             => rst_bit_ldval,
      pts_csr_rst_i             => rst_bit,
      pts_csr_rst_load_o        => rst_bit_ld,
      pts_csr_switch_i          => switches,
      pts_csr_rtm_i             => rtm_lines,
      pts_csr_i2c_err_o         => i2c_err_bit_rst,
      pts_csr_i2c_err_i         => i2c_err_bit,
      pts_csr_i2c_err_load_o    => i2c_err_bit_rst_ld,
      pts_csr_i2c_wdto_o        => i2c_wdto_bit_rst,
      pts_csr_i2c_wdto_i        => i2c_wdto_bit,
      pts_csr_i2c_wdto_load_o   => i2c_wdto_bit_rst_ld,
      pts_lsr_front_i           => line_front,
      pts_lsr_frontinv_i        => line_inv,
      pts_lsr_rear_i            => line_rear,
      pts_lsr_frontfs_i         => (others => '0'),
      pts_lsr_frontinvfs_i      => (others => '0'),
      pts_lsr_rearfs_i          => line_rear_fs,
      pts_ter_iterm_o           => iterm_en_o,
      pts_ter_oterm_o           => oterm_en_o
    );

  -- Implement the RST_UNLOCK bit
  p_rst_unlock : process (clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        rst_unlock <= '0';
      elsif (rst_unlock_ld = '1') then
        if (rst_unlock_ldval = '1') then
          rst_unlock <= '1';
        else
          rst_unlock <= '0';
        end if;
      end if;
    end if;
  end process p_rst_unlock;

  -- Implement the reset bit register
  -- The register can only be set when the RST_UNLOCK bit is '1'.
  p_rst_fr_reg : process (clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        rst_bit <= '0';
      elsif (rst_bit_ld = '1') and (rst_bit_ldval = '1') and (rst_unlock = '1') then
        rst_bit <= '1';
      else
        rst_bit <= '0';
      end if;
    end if;
  end process p_rst_fr_reg;

  --============================================================================
  -- PLL test logic
  -- * test 20MHz VCXO
  -- * test 125MHz PLL from TI
  -- * test Analog Devices AD5662 DACs used to control operation of the two
  -- oscillators
  --============================================================================
  -----------------------------------------------------------------------------
  -- 20-MHz VCXO test
  -----------------------------------------------------------------------------
  -- First, create the reset signal for the 20-MHz clock counter
  cnt_20_actual_rst <= cnt_20_rst or rst_20;

  -- Instantiate clock info slave
  cmp_clk_info_20 : clk_info_wb_slave
    port map
    (
      wb_clk_i          => clk_20_i,
      rst_i             => rst_20,

      wb_cyc_i          => xbar_master_out(c_slv_clk_info_20).cyc,
      wb_stb_i          => xbar_master_out(c_slv_clk_info_20).stb,
      wb_addr_i         => xbar_master_out(c_slv_clk_info_20).adr(4 downto 2),
      wb_data_i         => xbar_master_out(c_slv_clk_info_20).dat,
      wb_we_i           => xbar_master_out(c_slv_clk_info_20).we,
      wb_data_o         => xbar_master_in(c_slv_clk_info_20).dat,
      wb_ack_o          => xbar_master_in(c_slv_clk_info_20).ack,

      counter_is_full_i => cnt_20_full,
      counter_now_i     => cnt_20,
      counter_top_o     => cnt_20_top,
      counter_rst_o     => cnt_20_rst,
      counter_en_o      => cnt_20_en,
      oe_clk_o          => open
    );

  -- Then, instantiate increment counter for 20-MHz clock
  cmp_incr_counter_20 : incr_counter
    generic map
    (
      width => 32
    )
    port map
    (
      clk_i             => clk_20_i,
      rst_i             => cnt_20_actual_rst,
      counter_top_i     => cnt_20_top,
      counter_incr_en_i => cnt_20_en,
      counter_o         => cnt_20,
      counter_is_full_o => cnt_20_full
    );

  -- Instantate a Wishbone SPI module to control 20-MHz DAC operation
  cmp_dac_20_spi : wb_spi
    generic map
    (
      g_interface_mode      => CLASSIC,
      g_address_granularity => WORD
    )
    port map
    (
      clk_sys_i  => clk_20_i,
      rst_n_i    => rst_20_n,

      wb_adr_i   => xbar_master_out(c_slv_dac_spi_20).adr(6 downto 2),
      wb_dat_i   => xbar_master_out(c_slv_dac_spi_20).dat,
      wb_dat_o   => xbar_master_in(c_slv_dac_spi_20).dat,
      wb_sel_i   => xbar_master_out(c_slv_dac_spi_20).sel,
      wb_stb_i   => xbar_master_out(c_slv_dac_spi_20).stb,
      wb_cyc_i   => xbar_master_out(c_slv_dac_spi_20).cyc,
      wb_we_i    => xbar_master_out(c_slv_dac_spi_20).we,
      wb_ack_o   => xbar_master_in(c_slv_dac_spi_20).ack,
      wb_err_o   => xbar_master_in(c_slv_dac_spi_20).err,
      wb_int_o   => xbar_master_in(c_slv_dac_spi_20).int,
      wb_stall_o => xbar_master_in(c_slv_dac_spi_20).stall,

      pad_cs_o   => dac_20_sync_n,
      pad_sclk_o => dac_20_sclk_o,
      pad_mosi_o => dac_20_din_o,
      pad_miso_i => '0'
    );

  -- Finally, assign the SYNC_N output to the DAC
  dac_20_sync_n_o <= dac_20_sync_n(0);

  -----------------------------------------------------------------------------
  -- 125-MHz PLL test
  -----------------------------------------------------------------------------
  -- Instantiate clock info slave
  cmp_clk_info_125 : clk_info_wb_slave
    port map
    (
      wb_clk_i          => clk_20_i,
      rst_i             => rst_20,

      wb_cyc_i          => xbar_master_out(c_slv_clk_info_125).cyc,
      wb_stb_i          => xbar_master_out(c_slv_clk_info_125).stb,
      wb_addr_i         => xbar_master_out(c_slv_clk_info_125).adr(4 downto 2),
      wb_data_i         => xbar_master_out(c_slv_clk_info_125).dat,
      wb_we_i           => xbar_master_out(c_slv_clk_info_125).we,
      wb_data_o         => xbar_master_in(c_slv_clk_info_125).dat,
      wb_ack_o          => xbar_master_in(c_slv_clk_info_125).ack,

      counter_is_full_i => cnt_125_full,
      counter_now_i     => cnt_125_a,
      counter_top_o     => cnt_125_top_a,
      counter_rst_o     => cnt_125_rst_a,
      counter_en_o      => cnt_125_en_a,
      oe_clk_o          => open
    );

  -- Sync FIFO for counter top value
  cmp_cnt_top_20_to_125 : generic_async_fifo
    generic map
    (
      g_data_width => 32,
      g_size => 4
    )
    port map
    (
      rst_n_i    => rst_20_n,
      clk_wr_i   => clk_20_i,
      d_i        => cnt_125_top_a,
      we_i       => '1',
      clk_rd_i   => clk_125,
      q_o        => cnt_125_top,
      rd_i       => '1'
    );

  -- Sync FF chain for 125-MHz clock counter reset signal
  cmp_cnt_125_rst_sync : gc_sync_ffs
    port map
    (
      clk_i    => clk_125,
      rst_n_i  => rst_125_n,
      data_i   => cnt_125_rst_a,
      synced_o => cnt_125_rst
    );

  -- Sync FF chain for 125-MHz clock counter enable signal
  cmp_cnt_125_en_sync : gc_sync_ffs
    port map
    (
      clk_i    => clk_125,
      rst_n_i  => rst_125_n,
      data_i   => cnt_125_en_a,
      synced_o => cnt_125_en
    );

  -- Sync FIFO for current counter value
  cmp_cnt_125_to_20 : generic_async_fifo
    generic map
    (
      g_data_width => 32,
      g_size => 8
    )
    port map
    (
      rst_n_i    => rst_20_n,
      clk_wr_i   => clk_125,
      d_i        => cnt_125,
      we_i       => '1',
      clk_rd_i   => clk_20_i,
      q_o        => cnt_125_a,
      rd_i       => '1'
    );

  -- Create a reset signal for the 125-MHz clock counter
  cnt_125_actual_rst <= cnt_125_rst or (not rst_125_n);

  -- Instantiate increment counter for 125-MHz clock
  cmp_incr_counter_125 : incr_counter
    generic map
    (
      width => 32
    )
    port map
    (
      clk_i             => clk_125,
      rst_i             => cnt_125_actual_rst,
      counter_top_i     => cnt_125_top,
      counter_incr_en_i => cnt_125_en,
      counter_o         => cnt_125,
      counter_is_full_o => cnt_125_full
    );

  -- Instantate a Wishbone SPI module to control 125-MHz DAC operation
  cmp_dac_125_spi : wb_spi
    generic map
    (
      g_interface_mode      => CLASSIC,
      g_address_granularity => WORD
    )
    port map
    (
      clk_sys_i  => clk_20_i,
      rst_n_i    => rst_20_n,

      wb_adr_i   => xbar_master_out(c_slv_dac_spi_125).adr(6 downto 2),
      wb_dat_i   => xbar_master_out(c_slv_dac_spi_125).dat,
      wb_dat_o   => xbar_master_in(c_slv_dac_spi_125).dat,
      wb_sel_i   => xbar_master_out(c_slv_dac_spi_125).sel,
      wb_stb_i   => xbar_master_out(c_slv_dac_spi_125).stb,
      wb_cyc_i   => xbar_master_out(c_slv_dac_spi_125).cyc,
      wb_we_i    => xbar_master_out(c_slv_dac_spi_125).we,
      wb_ack_o   => xbar_master_in(c_slv_dac_spi_125).ack,
      wb_err_o   => xbar_master_in(c_slv_dac_spi_125).err,
      wb_int_o   => xbar_master_in(c_slv_dac_spi_125).int,
      wb_stall_o => xbar_master_in(c_slv_dac_spi_125).stall,

      pad_cs_o   => dac_125_sync_n,
      pad_sclk_o => dac_125_sclk_o,
      pad_mosi_o => dac_125_din_o,
      pad_miso_i => '0'
    );

  -- Finally, assign the SYNC_N output to the DAC
  dac_125_sync_n_o <= dac_125_sync_n(0);

  --============================================================================
  -- SFP EEPROM test logic
  -- * test SFP I2C EEPROM with an I2C master
  --============================================================================
  -- First, instantiate an I2C master to handle SFP communication
  cmp_sfp_eeprom_i2c : wb_i2c_master
    generic map
    (
      g_interface_mode      => CLASSIC,
      g_address_granularity => WORD
    )
    port map
    (
      clk_sys_i    => clk_20_i,
      rst_n_i      => rst_20_n,
      wb_adr_i     => xbar_master_out(c_slv_sfp_i2c).adr(6 downto 2),
      wb_dat_i     => xbar_master_out(c_slv_sfp_i2c).dat,
      wb_we_i      => xbar_master_out(c_slv_sfp_i2c).we,
      wb_stb_i     => xbar_master_out(c_slv_sfp_i2c).stb,
      wb_sel_i     => xbar_master_out(c_slv_sfp_i2c).sel,
      wb_cyc_i     => xbar_master_out(c_slv_sfp_i2c).cyc,
      wb_ack_o     => xbar_master_in(c_slv_sfp_i2c).ack,
      wb_int_o     => xbar_master_in(c_slv_sfp_i2c).int,
      wb_dat_o     => xbar_master_in(c_slv_sfp_i2c).dat,
      scl_pad_i    => i2c_scl_fr_sfp,
      scl_pad_o    => i2c_scl_to_sfp,
      scl_padoen_o => i2c_sfp_scl_en,
      sda_pad_i    => i2c_sda_fr_sfp,
      sda_pad_o    => i2c_sda_to_sfp,
      sda_padoen_o => i2c_sfp_sda_en
    );

  -- and assign the ports and tri-state buffers
  sfp_scl_b      <= i2c_scl_to_sfp when (i2c_sfp_scl_en = '0') else 'Z';
  i2c_scl_fr_sfp <= sfp_scl_b;
  sfp_sda_b      <= i2c_sda_to_sfp when (i2c_sfp_sda_en = '0') else 'Z';
  i2c_sda_fr_sfp <= sfp_sda_b;

  --============================================================================
  -- SFP loopback test logic
  -- * test J1 SFP connector using an SFP loopback module
  --============================================================================
  -- First, instantiate an IBUFGDS for MGT clock
  cmp_mgt_clk_ibufds : IBUFDS
    generic map
    (
      DIFF_TERM    => true,
      IBUF_LOW_PWR => false,
      IOSTANDARD   => "DEFAULT"
    )
    port map
    (
      I  => mgt_clk0_p_i,
      IB => mgt_clk0_n_i,
      O  => clk_gtp
    );

  -- Connect the MINIC module to the crossbar
  cmp_sfp_minic : xwr_mini_nic
    generic map
    (
      g_interface_mode       => CLASSIC,
      g_address_granularity  => BYTE,
      g_memsize_log2         => c_minic_memsize_log2,
      g_buffer_little_endian => true
    )
    port map
    (
      clk_sys_i           => clk_20_i,
      rst_n_i             => rst_20_n,
      mem_data_o          => minic_mem_data_out,
      mem_addr_o          => minic_mem_addr_out,
      mem_data_i          => minic_mem_data_in,
      mem_wr_o            => minic_mem_wr,
      src_o               => minic_src_out,
      src_i               => minic_src_in,
      snk_o               => minic_snk_out,
      snk_i               => minic_snk_in,
      txtsu_port_id_i     => "00000",
      txtsu_frame_id_i    => x"0000",
      txtsu_tsval_i       => x"00000000",
      txtsu_tsincorrect_i => '0',
      txtsu_stb_i         => '0',
      wb_i                => xbar_master_out(c_slv_minic),
      wb_o                => xbar_master_in(c_slv_minic)
    );

  -- Connect the endpoint buffer RAM
  cmp_sfp_dpram : generic_dpram
    generic map
    (
      g_data_width       => 32,
      g_size             => 2**c_minic_memsize_log2,
      g_with_byte_enable => false,
      g_dual_clock       => false
    )
    port map
    (
      rst_n_i => rst_20_n,
      clka_i  => clk_20_i,
      bwea_i  => "0000",
      wea_i   => dpram_we,
      aa_i    => xbar_master_out(c_slv_dpram).adr(c_minic_memsize_log2+1 downto 2),
      da_i    => xbar_master_out(c_slv_dpram).dat,
      qa_o    => xbar_master_in(c_slv_dpram).dat,
      clkb_i  => clk_20_i,
      bweb_i  => "0000",
      web_i   => minic_mem_wr,
      ab_i    => minic_mem_addr_out,
      db_i    => minic_mem_data_out,
      qb_o    => minic_mem_data_in
    );

  -- associate WE to first port of the RAM to WB signals
  dpram_we <= xbar_master_out(c_slv_dpram).cyc and xbar_master_out(c_slv_dpram).stb and
              xbar_master_out(c_slv_dpram).we;

  -- ACK logic for DPRAM
  xbar_master_in(c_slv_dpram).ack <= dpram_ack;
  xbar_master_in(c_slv_dpram).err <= '0';

  p_ram_ack : process (clk_20_i) is
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        dpram_ack <= '0';
      else
        dpram_ack <= '0';
        if (xbar_master_out(c_slv_dpram).stb = '1') and
           (xbar_master_out(c_slv_dpram).cyc = '1') then
          dpram_ack <= '1';
        end if;
      end if;
    end if;
  end process p_ram_ack;


  -- Connect the Endpoint module to the crossbar
  cmp_sfp_endpoint : xwr_endpoint
    generic map
    (
      g_interface_mode      => CLASSIC,
      g_address_granularity => BYTE,
      g_simulation          => false,
      g_tx_force_gap_length => 0,
      g_pcs_16bit           => false,
      g_rx_buffer_size      => 1024,
      g_with_rx_buffer      => true,
      g_with_flow_control   => false,
      g_with_timestamper    => true,
      g_with_dpi_classifier => false,
      g_with_vlans          => false,
      g_with_rtu            => false,
      g_with_leds           => false,
      g_with_dmtd           => false
    )
    port map
    (
      clk_ref_i          => clk_125,
      clk_sys_i          => clk_20_i,
      clk_dmtd_i         => clk_125,
      rst_n_i            => rst_20_n,
      pps_csync_p1_i     => '0',
      pps_valid_i        => '0',
      phy_rst_o          => phy_rst,
      phy_loopen_o       => phy_loopen,
      phy_ref_clk_i      => clk_125,
      phy_tx_data_o      => phy_tx_d,
      phy_tx_k_o         => phy_tx_k,
      phy_tx_disparity_i => phy_tx_disparity,
      phy_tx_enc_err_i   => phy_tx_error,
      phy_rx_data_i      => phy_rx_d,
      phy_rx_clk_i       => phy_rx_clk,
      phy_rx_k_i         => phy_rx_k,
      phy_rx_enc_err_i   => phy_rx_error,
      phy_rx_bitslide_i  => phy_rx_bitslide,

      src_o => minic_snk_in,
      src_i => minic_snk_out,
      snk_o => minic_src_in,
      snk_i => minic_src_out,

      wb_i => xbar_master_out(c_slv_endpoint),
      wb_o => xbar_master_in(c_slv_endpoint)
    );

  -- Finally, connect the GTP transceiver to the endpoint signals
  cmp_gtp_xceiver : wr_gtp_phy_spartan6
    generic map
    (
      g_simulation      => 0,
      g_force_disparity => 1,
      g_enable_ch0      => 1,
      g_enable_ch1      => 0
    )
    port map
    (
      gtp_clk_i          => clk_gtp,
      ch0_ref_clk_i      => clk_125,
      ch0_tx_data_i      => phy_tx_d(7 downto 0),
      ch0_tx_k_i         => phy_tx_k(0),
      ch0_tx_disparity_o => phy_tx_disparity,
      ch0_tx_enc_err_o   => phy_tx_error,
      ch0_rx_rbclk_o     => phy_rx_clk,
      ch0_rx_data_o      => phy_rx_d(7 downto 0),
      ch0_rx_k_o         => phy_rx_k(0),
      ch0_rx_enc_err_o   => phy_rx_error,
      ch0_rx_bitslide_o  => phy_rx_bitslide(3 downto 0),
      ch0_rst_i          => phy_rst,
      ch0_loopen_i       => phy_loopen,
      pad_txn0_o         => mgt_sfp_tx0_n_o,
      pad_txp0_o         => mgt_sfp_tx0_p_o,
      pad_rxn0_i         => mgt_sfp_rx0_n_i,
      pad_rxp0_i         => mgt_sfp_rx0_p_i
    );

  --============================================================================
  -- Thermometer test logic
  --============================================================================
  -- The one-wire master component is used to control the on-board DS18B20
  -- thermometer
  cmp_onewire_master : wb_onewire_master
    generic map
    (
      g_interface_mode      => CLASSIC,
      g_address_granularity => WORD,
      g_num_ports           => 1,
      g_ow_btp_normal       => "5.0",
      g_ow_btp_overdrive    => "1.0"
    )
    port map
    (
      clk_sys_i   => clk_20_i,
      rst_n_i     => rst_20_n,

      wb_cyc_i    => xbar_master_out(c_slv_onewire_mst).cyc,
      wb_sel_i    => xbar_master_out(c_slv_onewire_mst).sel,
      wb_stb_i    => xbar_master_out(c_slv_onewire_mst).stb,
      wb_we_i     => xbar_master_out(c_slv_onewire_mst).we,
      wb_adr_i    => xbar_master_out(c_slv_onewire_mst).adr(4 downto 2),
      wb_dat_i    => xbar_master_out(c_slv_onewire_mst).dat,
      wb_dat_o    => xbar_master_in(c_slv_onewire_mst).dat,
      wb_ack_o    => xbar_master_in(c_slv_onewire_mst).ack,
      wb_int_o    => open,
      wb_stall_o  => xbar_master_in(c_slv_onewire_mst).stall,

      owr_pwren_o => owr_pwren,
      owr_en_o    => owr_en,
      owr_i       => owr_in
    );

  -- Generate tri-state buffer for thermometer
  thermometer_b <= '0' when (owr_en(0) = '1') else
                   'Z';
  owr_in(0)     <= thermometer_b;

  --============================================================================
  -- TTL pulse test logic
  --============================================================================
  -- Channel enable outputs
  global_oen_o <= '1';
  ttl_oen_o    <= front_pulse_en;
  inv_oen_o    <= front_pulse_en or tester_vcc;

  -- First, instantiate a general-purpose pulse generator to generate the output
  -- pulse from CH1 to CH2
  --
  -- 1-us pulses are generated twice a second.
  cmp_first_pulse_gen : pulse_gen_gp
    port map (
      -- Input clock and active-low reset
      clk_i    => clk_20_i,
      rst_n_i  => rst_20_n,

      -- Active high enable signal
      en_i     => front_pulse_en,

      -- Delay, pulse width and frequency inputs, in number of clk_i cycles
      delay_i  => x"00000000",
      pwidth_i => x"00000014",
      per_i    => x"00989680",

      -- Output pulse signal
      pulse_o  => front_pulses(0)
    );

  -- Assign the TTL, INV-TTL inputs to internal signals
  front_trigs_a(5 downto 0) <= not ttl_n_i;
  front_trigs_a(9 downto 6) <= not inv_n_i;

  -- Synchronize these signals in the 20-MHz clock domain
gen_ttl_sync_chains : for i in 0 to 9 generate
  cmp_ttl_sync_chain : gc_sync_ffs
    port map
    (
      clk_i    => clk_20_i,
      rst_n_i  => rst_20_n,
      data_i   => front_trigs_a(i),
      synced_o => front_trigs(i),
      ppulse_o => front_trigs_redge_p(i)
    );
end generate gen_ttl_sync_chains;

  -- Now, generate nine pulse generator blocks connected to the TTL outputs
  -- and with the TTL inputs as triggers.
  --
  -- External to the FPGA, the inputs of CH2 are expected to be connected to CH1,
  -- which generates pulses for the daisy-chain, then CH2 outputs to CH3, CH3 to
  -- CH4 and so on, until the last INV_TTL output, which is expected to
  -- be connected back to the input of CH1.
  --
  -- The pulse generator is configured for fixed-width pulses of 1us.
gen_front_pulse_gens : for i in 1 to 9 generate
  cmp_pulse_gens : conv_pulse_gen
    generic map
    (
      g_with_fixed_pwidth => true,
      g_pwidth            => 20,
      g_duty_cycle_div    => 5
    )
    port map
    (
      clk_i         => clk_20_i,
      rst_n_i       => rst_20_n,

      gf_en_n_i     => '1',

      en_i          => front_pulse_en,

      trig_a_i      => front_trigs(i),

      pulse_err_p_o => open,

      pulse_o       => front_pulses(i)
    );
end generate gen_front_pulse_gens;

  -- Assign the FPGA outputs for the TTL channels
  ttl_o <= front_pulses(5 downto 0);
  inv_o <= front_pulses(9 downto 6) when (front_pulse_en = '1') else
           tester_ctrl;

  -- Implement the pulse counter registers for the TTL channels
gen_other_front_pulse_logic : for i in 0 to 9 generate
  -- First, some rising-edge detectors for output pulses
  p_front_pulse_redge : process(clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        front_pulses_d0(i) <= '0';
        front_pulses_redge_p(i) <= '0';
      else
        front_pulses_d0(i) <= front_pulses(i);
        front_pulses_redge_p(i) <= front_pulses(i) and (not front_pulses_d0(i));
      end if;
    end if;
  end process p_front_pulse_redge;

  -- Now, the actual I/O pulse counters
  p_front_pulse_cnt : process(clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        opcr(i) <= (others => '0');
        ipcr(i) <= (others => '0');
      else
        if (opcr_ld(i) = '1') then
          opcr(i) <= unsigned(opcr_ldval(i));
        elsif (front_pulses_redge_p(i) = '1') then
          opcr(i) <= opcr(i) + 1;
        end if;

        if (ipcr_ld(i) = '1') then
          ipcr(i) <= unsigned(ipcr_ldval(i));
        elsif (front_trigs_redge_p(i) = '1') then
          ipcr(i) <= ipcr(i) + 1;
        end if;
      end if;
    end if;
  end process p_front_pulse_cnt;

  -- Process to flash pulse LED when a pulse is output
  -- LED flash length: 26 ms
  p_front_led : process (clk_20_i) is
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        front_led_cnt(i) <= (others => '0');
        front_led(i)     <= '0';
      else
        case front_led(i) is
          when '0' =>
            if (front_pulses_redge_p(i) = '1') then
              front_led(i) <= '1';
            end if;
          when '1' =>
            front_led_cnt(i) <= front_led_cnt(i) + 1;
            if (front_led_cnt(i) = (front_led_cnt(i)'range => '1')) then
              front_led(i) <= '0';
            end if;
          when others =>
            front_led(i) <= '0';
        end case;
      end if;
    end if;
  end process p_front_led;
end generate gen_other_front_pulse_logic;

  --============================================================================
  -- Rear panel pulse test logic
  --============================================================================
  -- Compose the tester control lines out of the PTS reg bits
  tester_ctrl <= tester_s1 & tester_s0 & tester_mux_en & tester_vcc;

  -- Generate the logic for six pulse rep channels
gen_rear_test_logic : for i in 0 to 5 generate

  -- Assign rear panel inputs to local signals
  rs485_fs(i) <= rs485_n_i(i) nor rs485_fs_n_i(i);
  rear_trigs_a(i) <= (not rs485_n_i(i)) when (rs485_fs(i) = '0') else
                     '0';

  -- Synchronize the inputs to the 20-MHz clock domain
  cmp_rear_sync_chain : gc_sync_ffs
    port map
    (
      clk_i    => clk_20_i,
      rst_n_i  => rst_20_n,
      data_i   => rear_trigs_a(i),
      synced_o => rear_trigs(i),
      ppulse_o => rear_trigs_redge_p(i)
    );

  -- Instantiate general-purpose pulse generators to generate the output pulses
  -- 1-us pulses are generated twice a second.
  cmp_rear_pulse_gen : pulse_gen_gp
    port map (
      -- Input clock and active-low reset
      clk_i    => clk_20_i,
      rst_n_i  => rst_20_n,

      -- Active high enable signal
      en_i     => rear_pulse_en,

      -- Delay, pulse width and frequency inputs, in number of clk_i cycles
      delay_i  => x"00000050",
      pwidth_i => x"00000014",
      per_i    => x"00989680",

      -- Output pulse signal
      pulse_o  => rear_pulses(i)
    );

  -- Implement some rising-edge detectors for the output pulses
  p_rear_pulse_redge : process(clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        rear_pulses_d0(i) <= '0';
        rear_pulses_redge_p(i) <= '0';
      else
        rear_pulses_d0(i) <= rear_pulses(i);
        rear_pulses_redge_p(i) <= rear_pulses(i) and (not rear_pulses_d0(i));
      end if;
    end if;
  end process p_rear_pulse_redge;

  -- Process to flash pulse LED when a pulse is output
  -- LED flash length: 26 ms
  p_rear_led : process (clk_20_i) is
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        rear_led_cnt(i) <= (others => '0');
        rear_led(i)     <= '0';
      else
        case rear_led(i) is
          when '0' =>
            if (rear_pulses_redge_p(i) = '1') then
              rear_led(i) <= '1';
            end if;
          when '1' =>
            rear_led_cnt(i) <= rear_led_cnt(i) + 1;
            if (rear_led_cnt(i) = (rear_led_cnt(i)'range => '1')) then
              rear_led(i) <= '0';
            end if;
          when others =>
            rear_led(i) <= '0';
        end case;
      end if;
    end if;
  end process p_rear_led;

  -- Implement the pulse counters for the rear panel channels
  -- Note: pulse counters for rear panel channels are indexes 10..15 of signal
  p_rear_pulse_cnt : process(clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        opcr(i+10) <= (others => '0');
        ipcr(i+10) <= (others => '0');
      else
        if (opcr_ld(i+10) = '1') then
          opcr(i+10) <= unsigned(opcr_ldval(i+10));
        elsif (rear_pulses_redge_p(i) = '1') then
          opcr(i+10) <= opcr(i+10) + 1;
        end if;

        if (ipcr_ld(i+10) = '1') then
          ipcr(i+10) <= unsigned(ipcr_ldval(i+10));
        elsif (rear_trigs_redge_p(i) = '1') then
          ipcr(i+10) <= ipcr(i+10) + 1;
        end if;
      end if;
    end if;
  end process p_rear_pulse_cnt;

end generate gen_rear_test_logic;

  -- Finally, assign the outputs
  rs485_oen_o <= rear_pulse_en;
  rs485_o     <= rear_pulses;

  --============================================================================
  -- Pulse counter registers, retaining values for pulse counters of both RS-485
  -- and TTL pulse repetition tests.
  --============================================================================
  cmp_pulse_cnt_regs : pulse_cnt_wb
    port map (
      rst_n_i                     => rst_20_n,
      clk_sys_i                   => clk_20_i,
      wb_adr_i                    => xbar_master_out(c_slv_pulse_cntrs).adr(6 downto 2),
      wb_dat_i                    => xbar_master_out(c_slv_pulse_cntrs).dat,
      wb_dat_o                    => xbar_master_in(c_slv_pulse_cntrs).dat,
      wb_cyc_i                    => xbar_master_out(c_slv_pulse_cntrs).cyc,
      wb_sel_i                    => xbar_master_out(c_slv_pulse_cntrs).sel,
      wb_stb_i                    => xbar_master_out(c_slv_pulse_cntrs).stb,
      wb_we_i                     => xbar_master_out(c_slv_pulse_cntrs).we,
      wb_ack_o                    => xbar_master_in(c_slv_pulse_cntrs).ack,
      wb_stall_o                  => xbar_master_in(c_slv_pulse_cntrs).stall,

      pulse_cnt_ttlch1o_o         => opcr_ldval(0),
      pulse_cnt_ttlch1o_i         => std_logic_vector(opcr(0)),
      pulse_cnt_ttlch1o_load_o    => opcr_ld(0),
      pulse_cnt_ttlch1i_o         => ipcr_ldval(0),
      pulse_cnt_ttlch1i_i         => std_logic_vector(ipcr(0)),
      pulse_cnt_ttlch1i_load_o    => ipcr_ld(0),
      pulse_cnt_ttlch2o_o         => opcr_ldval(1),
      pulse_cnt_ttlch2o_i         => std_logic_vector(opcr(1)),
      pulse_cnt_ttlch2o_load_o    => opcr_ld(1),
      pulse_cnt_ttlch2i_o         => ipcr_ldval(1),
      pulse_cnt_ttlch2i_i         => std_logic_vector(ipcr(1)),
      pulse_cnt_ttlch2i_load_o    => ipcr_ld(1),
      pulse_cnt_ttlch3o_o         => opcr_ldval(2),
      pulse_cnt_ttlch3o_i         => std_logic_vector(opcr(2)),
      pulse_cnt_ttlch3o_load_o    => opcr_ld(2),
      pulse_cnt_ttlch3i_o         => ipcr_ldval(2),
      pulse_cnt_ttlch3i_i         => std_logic_vector(ipcr(2)),
      pulse_cnt_ttlch3i_load_o    => ipcr_ld(2),
      pulse_cnt_ttlch4o_o         => opcr_ldval(3),
      pulse_cnt_ttlch4o_i         => std_logic_vector(opcr(3)),
      pulse_cnt_ttlch4o_load_o    => opcr_ld(3),
      pulse_cnt_ttlch4i_o         => ipcr_ldval(3),
      pulse_cnt_ttlch4i_i         => std_logic_vector(ipcr(3)),
      pulse_cnt_ttlch4i_load_o    => ipcr_ld(3),
      pulse_cnt_ttlch5o_o         => opcr_ldval(4),
      pulse_cnt_ttlch5o_i         => std_logic_vector(opcr(4)),
      pulse_cnt_ttlch5o_load_o    => opcr_ld(4),
      pulse_cnt_ttlch5i_o         => ipcr_ldval(4),
      pulse_cnt_ttlch5i_i         => std_logic_vector(ipcr(4)),
      pulse_cnt_ttlch5i_load_o    => ipcr_ld(4),
      pulse_cnt_ttlch6o_o         => opcr_ldval(5),
      pulse_cnt_ttlch6o_i         => std_logic_vector(opcr(5)),
      pulse_cnt_ttlch6o_load_o    => opcr_ld(5),
      pulse_cnt_ttlch6i_o         => ipcr_ldval(5),
      pulse_cnt_ttlch6i_i         => std_logic_vector(ipcr(5)),
      pulse_cnt_ttlch6i_load_o    => ipcr_ld(5),
      pulse_cnt_invttlchao_o      => opcr_ldval(6),
      pulse_cnt_invttlchao_i      => std_logic_vector(opcr(6)),
      pulse_cnt_invttlchao_load_o => opcr_ld(6),
      pulse_cnt_invttlchai_o      => ipcr_ldval(6),
      pulse_cnt_invttlchai_i      => std_logic_vector(ipcr(6)),
      pulse_cnt_invttlchai_load_o => ipcr_ld(6),
      pulse_cnt_invttlchbo_o      => opcr_ldval(7),
      pulse_cnt_invttlchbo_i      => std_logic_vector(opcr(7)),
      pulse_cnt_invttlchbo_load_o => opcr_ld(7),
      pulse_cnt_invttlchbi_o      => ipcr_ldval(7),
      pulse_cnt_invttlchbi_i      => std_logic_vector(ipcr(7)),
      pulse_cnt_invttlchbi_load_o => ipcr_ld(7),
      pulse_cnt_invttlchco_o      => opcr_ldval(8),
      pulse_cnt_invttlchco_i      => std_logic_vector(opcr(8)),
      pulse_cnt_invttlchco_load_o => opcr_ld(8),
      pulse_cnt_invttlchci_o      => ipcr_ldval(8),
      pulse_cnt_invttlchci_i      => std_logic_vector(ipcr(8)),
      pulse_cnt_invttlchci_load_o => ipcr_ld(8),
      pulse_cnt_invttlchdo_o      => opcr_ldval(9),
      pulse_cnt_invttlchdo_i      => std_logic_vector(opcr(9)),
      pulse_cnt_invttlchdo_load_o => opcr_ld(9),
      pulse_cnt_invttlchdi_o      => ipcr_ldval(9),
      pulse_cnt_invttlchdi_i      => std_logic_vector(ipcr(9)),
      pulse_cnt_invttlchdi_load_o => ipcr_ld(9),
      pulse_cnt_rearch1o_o        => opcr_ldval(10),
      pulse_cnt_rearch1o_i        => std_logic_vector(opcr(10)),
      pulse_cnt_rearch1o_load_o   => opcr_ld(10),
      pulse_cnt_rearch1i_o        => ipcr_ldval(10),
      pulse_cnt_rearch1i_i        => std_logic_vector(ipcr(10)),
      pulse_cnt_rearch1i_load_o   => ipcr_ld(10),
      pulse_cnt_rearch2o_o        => opcr_ldval(11),
      pulse_cnt_rearch2o_i        => std_logic_vector(opcr(11)),
      pulse_cnt_rearch2o_load_o   => opcr_ld(11),
      pulse_cnt_rearch2i_o        => ipcr_ldval(11),
      pulse_cnt_rearch2i_i        => std_logic_vector(ipcr(11)),
      pulse_cnt_rearch2i_load_o   => ipcr_ld(11),
      pulse_cnt_rearch3o_o        => opcr_ldval(12),
      pulse_cnt_rearch3o_i        => std_logic_vector(opcr(12)),
      pulse_cnt_rearch3o_load_o   => opcr_ld(12),
      pulse_cnt_rearch3i_o        => ipcr_ldval(12),
      pulse_cnt_rearch3i_i        => std_logic_vector(ipcr(12)),
      pulse_cnt_rearch3i_load_o   => ipcr_ld(12),
      pulse_cnt_rearch4o_o        => opcr_ldval(13),
      pulse_cnt_rearch4o_i        => std_logic_vector(opcr(13)),
      pulse_cnt_rearch4o_load_o   => opcr_ld(13),
      pulse_cnt_rearch4i_o        => ipcr_ldval(13),
      pulse_cnt_rearch4i_i        => std_logic_vector(ipcr(13)),
      pulse_cnt_rearch4i_load_o   => ipcr_ld(13),
      pulse_cnt_rearch5o_o        => opcr_ldval(14),
      pulse_cnt_rearch5o_i        => std_logic_vector(opcr(14)),
      pulse_cnt_rearch5o_load_o   => opcr_ld(14),
      pulse_cnt_rearch5i_o        => ipcr_ldval(14),
      pulse_cnt_rearch5i_i        => std_logic_vector(ipcr(14)),
      pulse_cnt_rearch5i_load_o   => ipcr_ld(14),
      pulse_cnt_rearch6o_o        => opcr_ldval(15),
      pulse_cnt_rearch6o_i        => std_logic_vector(opcr(15)),
      pulse_cnt_rearch6o_load_o   => opcr_ld(15),
      pulse_cnt_rearch6i_o        => ipcr_ldval(15),
      pulse_cnt_rearch6i_i        => std_logic_vector(ipcr(15)),
      pulse_cnt_rearch6i_load_o   => ipcr_ld(15)
    );

  --============================================================================
  -- LED test logic
  -- * test bicolor LEDs and its driving circuit
  -- * test front panel LED logic and driving circuit
  --============================================================================
  -- Rising edge detector for pulse LED enable signal
  p_pulse_led_en_risedge : process (clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        pulse_led_en_d0      <= '0';
        front_led_en_risedge_p <= '0';
      else
        pulse_led_en_d0        <= pulse_led_en;
        front_led_en_risedge_p <= '0';
        if (pulse_led_en_d0 = '0') and (pulse_led_en = '1') then
          front_led_en_risedge_p <= '1';
        end if;
      end if;
    end if;
  end process p_pulse_led_en_risedge;

  -- Rising edge detector for status LED enable signal
  p_stat_led_en_risedge : process (clk_20_i)
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') then
        stat_led_en_d0      <= '0';
        stat_led_en_risedge_p <= '0';
      else
        stat_led_en_d0      <= stat_led_en;
        stat_led_en_risedge_p <= '0';
        if (stat_led_en_d0 = '0') and (stat_led_en = '1') then
          stat_led_en_risedge_p <= '1';
        end if;
      end if;
    end if;
  end process p_stat_led_en_risedge;

  -- Process to control the LED sequence counter

  p_led_seq : process (clk_20_i) is
  begin
    if rising_edge(clk_20_i) then
      if (rst_20_n = '0') or (stat_led_en_risedge_p = '1')
                          or (front_led_en_risedge_p = '1') then
        cnt_halfsec <= (others => '0');
        led_seq     <= (others => '0');
      elsif (pulse_led_en = '1') or (stat_led_en = '1') then
        cnt_halfsec <= cnt_halfsec + 1;
        if (cnt_halfsec = 9999999) then
          cnt_halfsec <= (others => '0');
          led_seq     <= led_seq + 1;
          if (led_seq = 24) then
            led_seq   <= (others => '0');
          end if;
        end if;
      end if;
    end if;
  end process p_led_seq;

  -- Light each LED red and green in a sequence, based on the sequence counter.
  --
  -- The colors are set via the LED state vector (two bits per LED) as follows:
  --    state(1..0)     color
  --        00           OFF
  --        01           RED
  --        10          GREEN
  bicolor_led_state <= "000000000001000000000000" when (stat_led_en = '1') and (led_seq =  1) else
                       "000000000100000000000000" when (stat_led_en = '1') and (led_seq =  2) else
                       "000000010000000000000000" when (stat_led_en = '1') and (led_seq =  3) else
                       "000001000000000000000000" when (stat_led_en = '1') and (led_seq =  4) else
                       "000000000000000001000000" when (stat_led_en = '1') and (led_seq =  5) else
                       "000000000000000000010000" when (stat_led_en = '1') and (led_seq =  6) else
                       "000000000000000000000100" when (stat_led_en = '1') and (led_seq =  7) else
                       "000000000000000000000001" when (stat_led_en = '1') and (led_seq =  8) else
                       "000000000000000100000000" when (stat_led_en = '1') and (led_seq =  9) else
                       "000000000000010000000000" when (stat_led_en = '1') and (led_seq = 10) else
                       "000100000000000000000000" when (stat_led_en = '1') and (led_seq = 11) else
                       "010000000000000000000000" when (stat_led_en = '1') and (led_seq = 12) else
                       "000000000010000000000000" when (stat_led_en = '1') and (led_seq = 13) else
                       "000000001000000000000000" when (stat_led_en = '1') and (led_seq = 14) else
                       "000000100000000000000000" when (stat_led_en = '1') and (led_seq = 15) else
                       "000010000000000000000000" when (stat_led_en = '1') and (led_seq = 16) else
                       "000000000000000010000000" when (stat_led_en = '1') and (led_seq = 17) else
                       "000000000000000000100000" when (stat_led_en = '1') and (led_seq = 18) else
                       "000000000000000000001000" when (stat_led_en = '1') and (led_seq = 19) else
                       "000000000000000000000010" when (stat_led_en = '1') and (led_seq = 20) else
                       "000000000000001000000000" when (stat_led_en = '1') and (led_seq = 21) else
                       "000000000000100000000000" when (stat_led_en = '1') and (led_seq = 22) else
                       "001000000000000000000000" when (stat_led_en = '1') and (led_seq = 23) else
                       "100000000000000000000000" when (stat_led_en = '1') and (led_seq = 24) else
                       "000000000000000000000000";

  -- Sequence the front-panel LEDs based on the sequence counter
  front_led_seq <= "000001" when (pulse_led_en = '1') and (led_seq =  1) else
                   "000010" when (pulse_led_en = '1') and (led_seq =  2) else
                   "000100" when (pulse_led_en = '1') and (led_seq =  3) else
                   "001000" when (pulse_led_en = '1') and (led_seq =  4) else
                   "010000" when (pulse_led_en = '1') and (led_seq =  5) else
                   "100000" when (pulse_led_en = '1') and (led_seq =  6) else
                   "000001" when (pulse_led_en = '1') and (led_seq = 11) else
                   "000010" when (pulse_led_en = '1') and (led_seq = 12) else
                   "000100" when (pulse_led_en = '1') and (led_seq = 13) else
                   "001000" when (pulse_led_en = '1') and (led_seq = 14) else
                   "010000" when (pulse_led_en = '1') and (led_seq = 15) else
                   "100000" when (pulse_led_en = '1') and (led_seq = 16) else
                   "000000";

  -- Sequence the inverter LEDs
  inv_led_seq <= "0001" when (pulse_led_en = '1') and (led_seq =  7) else
                 "0010" when (pulse_led_en = '1') and (led_seq =  8) else
                 "0100" when (pulse_led_en = '1') and (led_seq =  9) else
                 "1000" when (pulse_led_en = '1') and (led_seq = 10) else
                 "0001" when (pulse_led_en = '1') and (led_seq = 17) else
                 "0010" when (pulse_led_en = '1') and (led_seq = 18) else
                 "0100" when (pulse_led_en = '1') and (led_seq = 19) else
                 "1000" when (pulse_led_en = '1') and (led_seq = 20) else
                 "0000";

  -- Sequence the rear-panel LEDs based on the sequence counter
  rear_led_seq <= "000001" when (pulse_led_en = '1') and (led_seq =  1) else
                  "000010" when (pulse_led_en = '1') and (led_seq =  2) else
                  "000100" when (pulse_led_en = '1') and (led_seq =  3) else
                  "001000" when (pulse_led_en = '1') and (led_seq =  4) else
                  "010000" when (pulse_led_en = '1') and (led_seq =  5) else
                  "100000" when (pulse_led_en = '1') and (led_seq =  6) else
                  "000001" when (pulse_led_en = '1') and (led_seq =  7) else
                  "000010" when (pulse_led_en = '1') and (led_seq =  8) else
                  "000100" when (pulse_led_en = '1') and (led_seq =  9) else
                  "001000" when (pulse_led_en = '1') and (led_seq = 10) else
                  "010000" when (pulse_led_en = '1') and (led_seq = 11) else
                  "100000" when (pulse_led_en = '1') and (led_seq = 12) else
                  "000001" when (pulse_led_en = '1') and (led_seq = 13) else
                  "000010" when (pulse_led_en = '1') and (led_seq = 14) else
                  "000100" when (pulse_led_en = '1') and (led_seq = 15) else
                  "001000" when (pulse_led_en = '1') and (led_seq = 16) else
                  "010000" when (pulse_led_en = '1') and (led_seq = 17) else
                  "100000" when (pulse_led_en = '1') and (led_seq = 18) else
                  "000001" when (pulse_led_en = '1') and (led_seq = 19) else
                  "000010" when (pulse_led_en = '1') and (led_seq = 20) else
                  "000100" when (pulse_led_en = '1') and (led_seq = 21) else
                  "001000" when (pulse_led_en = '1') and (led_seq = 22) else
                  "010000" when (pulse_led_en = '1') and (led_seq = 23) else
                  "100000" when (pulse_led_en = '1') and (led_seq = 24) else
                  "000000";

  -- Then, we instantiate the LED controller and control it via the LED state
  -- vector.
  cmp_bicolor_led_ctrl : gc_bicolor_led_ctrl
    generic map
    (
      g_NB_COLUMN    => 6,
      g_NB_LINE      => 2,
      g_clk_freq     => 20000000,
      g_refresh_rate => 250
    )
    port map
    (
      clk_i           => clk_20_i,
      rst_n_i         => rst_20_n,
      led_intensity_i => "1111111",
      led_state_i     => bicolor_led_state,
      column_o(0)     => led_ttl_i2c_o,
      column_o(1)     => led_oterm_wr_o,
      column_o(2)     => led_iterm_syserror_o,
      column_o(3)     => led_gf_syspw_o,
      column_o(4)     => led_gp_2_4_o,
      column_o(5)     => led_gp_1_3_o,
      line_o(0)       => led_ctrl0_o,
      line_o(1)       => led_ctrl1_o,
      line_oen_o(0)   => led_ctrl0_oen_o,
      line_oen_o(1)   => led_ctrl1_oen_o
    );

  --============================================================================
  -- Drive pulse LEDs
  --============================================================================
  led_front_o   <= front_led_seq when (pulse_led_en = '1') else
                   front_led(5 downto 0);
  led_inv_o     <= inv_led_seq when (pulse_led_en = '1') else
                   tester_ctrl when (tester_vcc = '1') else
                   front_led(9 downto 6);
  led_rear_n_o  <= not rear_led_seq when (pulse_led_en = '1') else
                   not rear_led(5 downto 0);

  --============================================================================
  -- Drive unused outputs with safe values
  --============================================================================
  flash_cs_n_o <= '1';
  flash_mosi_o <= '0';
  flash_sclk_o <= '0';

  -- SFP lines all open-drain, set to high-impedance
  sfp_rate_select_o <= 'Z';
  sfp_tx_disable_o  <= 'Z';

end architecture arch;
--==============================================================================
--  architecture end
--==============================================================================
