--==============================================================================
-- CERN (BE-CO-HT)
-- Top level entity of CONV-TTL-BLO
-- http://www.ohwr.org/projects/conv-ttl-blo
--==============================================================================
--
-- author: Theodor Stana (t.stana@cern.ch)
--         Carlos-Gil-Soriano
--
-- version: 1.0
--
-- description:
--    This is the top-level file for the CONV-TTL-BLO board. It instantiates all
--    components needed in the design and generates the necessary logic for
--    pulse conversion to occur on each channel.
--
--    Details about the HDL design can be found by reading the HDL guide of the
--    project in the doc/ folder.
--
-- dependencies:
--    general-cores repository [1]
--
-- references:
--   [1] Platform-independent core collection webpage on OHWR,
--       http://www.ohwr.org/projects/general-cores/repository
--   [2] ELMA, Access to board data using SNMP and I2C
--       http://www.ohwr.org/documents/227
--
--==============================================================================
-- 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:
--   26-11-2013   Theodor Stana       Changed file header
--==============================================================================
-- TODO: -
--==============================================================================
library ieee;
library unisim;

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use unisim.vcomponents.all;

use work.bicolor_led_ctrl_pkg.all;
use work.wishbone_pkg.all;
use work.gencores_pkg.all;
use work.genram_pkg.all;

entity conv_ttl_blo is
  generic
  (
    g_nr_ttl_chan : natural := 6;
    g_nr_inv_chan : natural := 4;
    g_sim         : boolean := false
  );
  port
  (
    -- Clocks
    -- 20 MHz from VCXO
    clk_20_vcxo_i           : in  std_logic;
    -- 125 MHz from clock generator
    fpga_clk_p_i           : in  std_logic;
    fpga_clk_n_i           : in  std_logic;

    -- 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_multicast_2_0_o    : out std_logic;
    led_multicast_3_1_o    : out std_logic;
    led_wr_gmt_ttl_ttln_o  : out std_logic;
    led_wr_link_syserror_o : out std_logic;
    led_wr_ok_syspw_o      : out std_logic;
    led_wr_ownaddr_i2c_o   : out std_logic;

    -- I/Os for pulses
    pulse_front_led_n_o    : out std_logic_vector(g_nr_ttl_chan downto 1);
    pulse_rear_led_n_o     : out std_logic_vector(g_nr_ttl_chan downto 1);
    fpga_input_ttl_n_i     : in  std_logic_vector(g_nr_ttl_chan downto 1);
    fpga_out_ttl_o         : out std_logic_vector(g_nr_ttl_chan downto 1);
    fpga_blo_in_i          : in  std_logic_vector(g_nr_ttl_chan downto 1);
    fpga_trig_blo_o        : out std_logic_vector(g_nr_ttl_chan downto 1);
    inv_in_n_i             : in  std_logic_vector(g_nr_inv_chan downto 1);
    inv_out_o              : out std_logic_vector(g_nr_inv_chan downto 1);

    -- Output enable lines
    fpga_oe_o              : out std_logic;
    fpga_blo_oe_o          : out std_logic;
    fpga_trig_ttl_oe_o     : out std_logic;
    fpga_inv_oe_o          : out std_logic;

    --TTL/INV_TTL_N
    ttl_switch_n_i         : in  std_logic;

    extra_switch_n_i       : in  std_logic_vector(7 downto 1);

    -- Lines for the i2c_slave
    scl_i                  : in  std_logic;
    scl_o                  : out std_logic;
    scl_oe_o               : out std_logic;
    sda_i                  : in  std_logic;
    sda_o                  : out std_logic;
    sda_oe_o               : out std_logic;
    fpga_ga_i              : in  std_logic_vector(4 downto 0);
    fpga_gap_i             : in  std_logic;

    -- Flash memory lines
    fpga_prom_cclk_o       : out std_logic;
    fpga_prom_cso_b_n_o    : out std_logic;
    fpga_prom_mosi_o       : out std_logic;
    fpga_prom_miso_i       : in  std_logic;

    -- Blocking power supply reset line
    mr_n_o                 : out std_logic;

    -- Thermometer line
    thermometer_b          : inout std_logic;

    -- PLL DACs
    -- DAC1: 20 MHz VCXO control
    fpga_plldac1_din_o     : out std_logic;
    fpga_plldac1_sclk_o    : out std_logic;
    fpga_plldac1_sync_n_o  : out std_logic;
    -- DAC2: 125 MHz clock generator control
    fpga_plldac2_din_o     : out std_logic;
    fpga_plldac2_sclk_o    : out std_logic;
    fpga_plldac2_sync_n_o  : out std_logic;

    -- SFP lines
    fpga_sfp_los_i         : in    std_logic;
    fpga_sfp_mod_def0_i    : in    std_logic;
    fpga_sfp_rate_select_o : out   std_logic;
    fpga_sfp_mod_def1_b    : inout std_logic;
    fpga_sfp_mod_def2_b    : inout std_logic;
    fpga_sfp_tx_disable_o  : out   std_logic;
    fpga_sfp_tx_fault_i    : in    std_logic;

    -- RTM identifiers, should match with the expected values
    fpga_rtmm_n_i          : in std_logic_vector(2 downto 0);
    fpga_rtmp_n_i          : in std_logic_vector(2 downto 0)
  );
end conv_ttl_blo;


architecture behav of conv_ttl_blo is

  --============================================================================
  -- Type declarations
  --============================================================================
  type t_ttlbar_nosig_cnt is array (1 to g_nr_ttl_chan) of unsigned(10 downto 0);
  type t_pulse_led_cnt is array (1 to g_nr_ttl_chan) of unsigned(18 downto 0);
  type t_pulse_cnt is array (1 to g_nr_ttl_chan) of unsigned(31 downto 0);
  type t_ch_pcr is array (1 to g_nr_ttl_chan) of std_logic_vector(31 downto 0);

  --============================================================================
  -- Function and procedure declarations
  --============================================================================
  function f_reset_width return positive is
    variable retval : positive;
  begin
    retval := 2*(10**6);
    if g_sim then
      retval := 20;
    end if;
    assert false report "Reset width: " & integer'image(retval) 
                        & "*50ns" severity Note;
    return retval;
  end function f_reset_width;

  --============================================================================
  -- Constant declarations
  --============================================================================
  -- Board ID - ASCII string "TBLO"
  constant c_board_id : std_logic_vector(31 downto 0) := x"54424c4f";

  -- Gateware version
  --    - format: M.m
  --    - M: major version hex number (e.g.  1)
  --    - m: minor version hex number (e.g. 13)
  --    - example: first major release      v1.0  c_gwvers = x"10";
  --               next minor release       v1.1  c_gwvers = x"11";
  --               13 minor releases later  v1.14 c_gwvers = x"1e";
  --               next major release       v2.0  c_gwvers = x"20";
  constant c_gwvers          : std_logic_vector(7 downto 0) := x"22";

  -- Number of Wishbone masters and slaves, for wb_crossbar
  constant c_nr_masters      : natural :=  1;
  constant c_nr_slaves       : natural :=  3;

  ------------------------------------------------------------------------------
  -- Memory map
  -- * all registers are word-addressable
  -- * all registers are word-aligned
  ------------------------------------------------------------------------------
  --    CONV_REGS       [000-020]
  --    MULTIBOOT       [040-050]
  --    ONEWIRE         [080-084]
  ------------------------------------------------------------------------------
  -- slave order definitions
  constant c_slv_conv_regs    : natural := 0;
  constant c_slv_multiboot    : natural := 1;
  constant c_slv_onewire_mst  : natural := 2;

  -- base address definitions
  constant c_addr_conv_regs   : t_wishbone_address := x"00000000";
  constant c_addr_multiboot   : t_wishbone_address := x"00000040";
  constant c_addr_onewire_mst : t_wishbone_address := x"00000080";

  -- address mask definitions
  constant c_mask_conv_regs   : t_wishbone_address := x"00000fc0";
  constant c_mask_multiboot   : t_wishbone_address := x"00000fc0";
  constant c_mask_onewire_mst : t_wishbone_address := x"00000fe0";

  -- addresses constant for Wishbone crossbar
  constant c_addresses : t_wishbone_address_array(c_nr_slaves-1 downto 0)
                  := (
                       c_slv_conv_regs   => c_addr_conv_regs,
                       c_slv_multiboot   => c_addr_multiboot,
                       c_slv_onewire_mst => c_addr_onewire_mst
                     );

  -- masks constant for Wishbone crossbar
  constant c_masks : t_wishbone_address_array(c_nr_slaves-1 downto 0)
                  := (
                       c_slv_conv_regs   => c_mask_conv_regs,
                       c_slv_multiboot   => c_mask_multiboot,
                       c_slv_onewire_mst => c_mask_onewire_mst
                     );

  ------------------------------------------------------------------------------
  -- Pulse generator glitch filter length
  ------------------------------------------------------------------------------
  constant c_pulse_gen_pwidth         : positive :=  24;
  constant c_pulse_gen_duty_cycle_div : positive := 200;
  constant c_pulse_gen_gf_len         : positive :=   1;

  ------------------------------------------------------------------------------
  -- Pulse time-tag ring buffer constants
  ------------------------------------------------------------------------------
  -- data width:  40 -- TAI
  --              28 -- cycles
  --               1 -- WRPRES bit
  --              xx -- channel mask
  constant c_tb_data_width    : positive := 40 + 28 + 1 + g_nr_ttl_chan;

  -- size in number of (data width)-sized samples
  constant c_tb_size          : positive := 128;
  -- <<<< NOTE >>>> Also change USEDW size in conv_regs.vhd <<<< NOTE >>>>
  -- <<<< NOTE >>>> See README.txt in modules/Release/      <<<< NOTE >>>>

  --============================================================================
  -- Component declarations
  --============================================================================
  ------------------------------------------------------------------------------
  -- Reset generator component
  -- (use: global reset generation, output reset generation)
  ------------------------------------------------------------------------------
  component reset_gen is
    generic
    (
      -- Reset time in number of clk_i cycles
      g_reset_time : positive := 2_000_000
    );
    port
    (
      clk_i   : in  std_logic;
      rst_i   : in  std_logic;
      rst_n_o : out std_logic
    );
  end component reset_gen;

  ------------------------------------------------------------------------------
  -- Pulse generator component
  -- (use: output pulse generation, pulse status LEDs)
  ------------------------------------------------------------------------------
  component ctblo_pulse_gen is
    generic
    (
      -- Pulse width, in number of clk_i cycles
      -- Default pulse width (20 MHz clock): 1.2 us
      -- Minimum allowable pulse width (20 MHz clock): 1 us
      -- Maximum allowable pulse width (20 MHz clock): 2 us
      g_pwidth         : natural range 20 to 40 := 24;

      -- Duty cycle divider: D = 1/g_duty_cycle_div
      g_duty_cycle_div : natural := 5
    );
    port
    (
      -- Clock and active-low reset inputs
      clk_i         : in  std_logic;
      rst_n_i       : in  std_logic;

      -- Glitch filter enable input
      -- '1' - Glitch filter disabled (glitch-sensitive, no output jitter)
      -- '0' - Glitch filter enabled (glitch-insensitive, with output jitter)
      gf_en_n_i     : in  std_logic;

      -- Enable input, pulse generation is enabled when '1'
      en_i          : in  std_logic;

      -- Trigger input, has to be '1' to assure pulse output with delay no greater
      -- than internal gate delays.
      trig_a_i      : in  std_logic;

      -- Pulse error output, pulses high for one clock cycle when a pulse arrives
      -- within a pulse period
      pulse_err_p_o : out std_logic;

      -- Pulse output, active-high
      -- latency:
      --    glitch filter disabled: none
      --    glitch filter enabled: glitch filter length + 5 clk_i cycles
      pulse_o       : out std_logic
    );
  end component ctblo_pulse_gen;

  ------------------------------------------------------------------------------
  -- RTM detector component
  -- (use: detect the presence of an RTM/P module)
  ------------------------------------------------------------------------------
  component rtm_detector is
    port
    (
      rtmm_i    : in std_logic_vector(2 downto 0);
      rtmp_i    : in std_logic_vector(2 downto 0);
      rtmm_ok_o : out std_logic;
      rtmp_ok_o : out std_logic
    );
  end component rtm_detector;

  ------------------------------------------------------------------------------
  -- Converter board control registers
  ------------------------------------------------------------------------------
  component conv_regs is
    port (
      rst_n_i                                  : in     std_logic;
      clk_sys_i                                : in     std_logic;
      wb_adr_i                                 : in     std_logic_vector(3 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'
      reg_bidr_i                               : in     std_logic_vector(31 downto 0);
  -- Port for std_logic_vector field: 'Gateware version' in reg: 'SR'
      reg_sr_gwvers_i                          : in     std_logic_vector(7 downto 0);
  -- Port for std_logic_vector field: 'Status of on-board switches' in reg: 'SR'
      reg_sr_switches_i                        : in     std_logic_vector(7 downto 0);
  -- Port for std_logic_vector field: 'RTM detection lines~\cite{rtm-det}' in reg: 'SR'
      reg_sr_rtm_i                             : in     std_logic_vector(5 downto 0);
  -- Ports for BIT field: 'I2C communication watchdog timeout error' in reg: 'SR'
      reg_sr_i2c_wdto_o                        : out    std_logic;
      reg_sr_i2c_wdto_i                        : in     std_logic;
      reg_sr_i2c_wdto_load_o                   : out    std_logic;
  -- Port for BIT field: 'White Rabbit present' in reg: 'SR'
      reg_sr_wrpres_i                          : in     std_logic;
  -- Ports for BIT field: 'I2C communication error' in reg: 'SR'
      reg_sr_i2c_err_o                         : out    std_logic;
      reg_sr_i2c_err_i                         : in     std_logic;
      reg_sr_i2c_err_load_o                    : out    std_logic;
  -- Ports for BIT field: 'Pulse missed error' in reg: 'SR'
      reg_sr_pmisse_o                          : out    std_logic;
      reg_sr_pmisse_i                          : in     std_logic;
      reg_sr_pmisse_load_o                     : out    std_logic;
  -- Ports for BIT field: 'Reset unlock bit' in reg: 'CR'
      reg_cr_rst_unlock_o                      : out    std_logic;
      reg_cr_rst_unlock_i                      : in     std_logic;
      reg_cr_rst_unlock_load_o                 : out    std_logic;
  -- Ports for BIT field: 'Reset bit' in reg: 'CR'
      reg_cr_rst_o                             : out    std_logic;
      reg_cr_rst_i                             : in     std_logic;
      reg_cr_rst_load_o                        : out    std_logic;
  -- Ports for PASS_THROUGH field: 'Manual Pulse Trigger' in reg: 'CR'
      reg_cr_mpt_o                             : out    std_logic_vector(7 downto 0);
      reg_cr_mpt_wr_o                          : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'CH1PCR'
      reg_ch1pcr_o                             : out    std_logic_vector(31 downto 0);
      reg_ch1pcr_i                             : in     std_logic_vector(31 downto 0);
      reg_ch1pcr_load_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'CH2PCR'
      reg_ch2pcr_o                             : out    std_logic_vector(31 downto 0);
      reg_ch2pcr_i                             : in     std_logic_vector(31 downto 0);
      reg_ch2pcr_load_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'CH3PCR'
      reg_ch3pcr_o                             : out    std_logic_vector(31 downto 0);
      reg_ch3pcr_i                             : in     std_logic_vector(31 downto 0);
      reg_ch3pcr_load_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'CH4PCR'
      reg_ch4pcr_o                             : out    std_logic_vector(31 downto 0);
      reg_ch4pcr_i                             : in     std_logic_vector(31 downto 0);
      reg_ch4pcr_load_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'CH5PCR'
      reg_ch5pcr_o                             : out    std_logic_vector(31 downto 0);
      reg_ch5pcr_i                             : in     std_logic_vector(31 downto 0);
      reg_ch5pcr_load_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'Pulse counter value' in reg: 'CH6PCR'
      reg_ch6pcr_o                             : out    std_logic_vector(31 downto 0);
      reg_ch6pcr_i                             : in     std_logic_vector(31 downto 0);
      reg_ch6pcr_load_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'TAI seconds counter bits 31..0' in reg: 'TVLR'
      reg_tvlr_o                               : out    std_logic_vector(31 downto 0);
      reg_tvlr_i                               : in     std_logic_vector(31 downto 0);
      reg_tvlr_load_o                          : out    std_logic;
  -- Port for std_logic_vector field: 'TAI seconds counter bits 39..32' in reg: 'TVHR'
      reg_tvhr_o                               : out    std_logic_vector(7 downto 0);
      reg_tvhr_i                               : in     std_logic_vector(7 downto 0);
      reg_tvhr_load_o                          : out    std_logic;
  -- Port for std_logic_vector field: 'Channel mask' in reg: 'TBMR'
      reg_tbmr_chan_i                          : in     std_logic_vector(5 downto 0);
  -- Port for BIT field: 'White Rabbit present' in reg: 'TBMR'
      reg_tbmr_wrtag_i                         : in     std_logic;
  -- Tag buffer read request, asserted when reading from TBMR
      reg_tb_rd_req_p_o                        : out    std_logic;
  -- Port for std_logic_vector field: 'Cycles counter' in reg: 'TBCYR'
      reg_tbcyr_i                              : in     std_logic_vector(27 downto 0);
  -- Port for std_logic_vector field: 'Lower part of TAI seconds counter' in reg: 'TBTLR'
      reg_tbtlr_i                              : in     std_logic_vector(31 downto 0);
  -- Port for std_logic_vector field: 'Upper part of TAI seconds counter' in reg: 'TBTHR'
      reg_tbthr_i                              : in     std_logic_vector(7 downto 0);
  -- Port for std_logic_vector field: 'Buffer counter' in reg: 'TBCSR'
      reg_tbcsr_usedw_i                        : in     std_logic_vector(6 downto 0);
  -- Port for BIT field: 'Buffer full' in reg: 'TBCSR'
      reg_tbcsr_full_i                         : in     std_logic;
  -- Port for BIT field: 'Buffer empty' in reg: 'TBCSR'
      reg_tbcsr_empty_i                        : in     std_logic;
  -- Ports for BIT field: 'Clear tag buffer' in reg: 'TBCSR'
      reg_tbcsr_clr_o                          : out    std_logic;
      reg_tbcsr_clr_i                          : in     std_logic;
      reg_tbcsr_clr_load_o                     : out    std_logic
    );
  end component conv_regs;

  ------------------------------------------------------------------------------
  -- MultiBoot component
  -- use: remotely reprogram the FPGA
  ------------------------------------------------------------------------------
  component wb_xil_multiboot is
    port
    (
      -- Clock and reset input ports
      clk_i   : in  std_logic;
      rst_n_i : in  std_logic;

      -- Wishbone ports
      wbs_i   : in  t_wishbone_slave_in;
      wbs_o   : out t_wishbone_slave_out;

      -- SPI ports
      spi_cs_n_o : out std_logic;
      spi_sclk_o : out std_logic;
      spi_mosi_o : out std_logic;
      spi_miso_i : in  std_logic
    );
  end component wb_xil_multiboot;

  ------------------------------------------------------------------------------
  -- Manual pulse trigger component
  ------------------------------------------------------------------------------
  component conv_man_trig is
    generic
    (
      -- Number of conversion channels
      g_nr_chan : positive := 6;

      -- Length of pulse generator glitch filter, needed to generate a long
      -- enough pulse
      g_gf_len  : positive := 1
    );
    port
    (
      -- Clock, active-low inputs
      clk_i     : in  std_logic;
      rst_n_i   : in  std_logic;

      -- Control inputs from conv_regs
      reg_ld_i : in  std_logic;
      reg_i    : in  std_logic_vector(7 downto 0);

      -- One-clock pulse output
      trig_o   : out std_logic_vector(g_nr_chan downto 1)
    );
  end component conv_man_trig;

  ------------------------------------------------------------------------------
  -- Pulse time-tagging component
  ------------------------------------------------------------------------------
  component conv_pulse_timetag is
    generic
    (
    -- Frequency in Hz of the clk_i signal
      g_clk_rate : positive := 125000000;

    -- Number of repetition channels
      g_nr_chan  : positive := 6
    );
    port
    (
    -- Clock and active-low reset
      clk_i            : in  std_logic;
      rst_n_i          : in  std_logic;

    -- Asynchronous pulse input
      pulse_a_i        : in  std_logic_vector(g_nr_chan downto 1);

    -- Time inputs from White Rabbit
      wr_tm_cycles_i   : in  std_logic_vector(27 downto 0);
      wr_tm_tai_i      : in  std_logic_vector(39 downto 0);
      wr_tm_valid_i    : in  std_logic;

    -- Timing inputs from Wishbone-mapped registers
      wb_tm_tai_l_i    : in  std_logic_vector(31 downto 0);
      wb_tm_tai_l_ld_i : in  std_logic;
      wb_tm_tai_h_i    : in  std_logic_vector( 7 downto 0);
      wb_tm_tai_h_ld_i : in  std_logic;

    -- Timing outputs
      tm_cycles_o      : out std_logic_vector(27 downto 0);
      tm_tai_o         : out std_logic_vector(39 downto 0);
      tm_wrpres_o      : out std_logic;
      chan_o           : out std_logic_vector(g_nr_chan downto 1);

    -- Ring buffer I/O
      buf_wr_req_p_o  : out std_logic
    );
  end component conv_pulse_timetag;

  ------------------------------------------------------------------------------
  -- Ring buffer component
  -- use: buffer time stamps generated by the conv_pulse_timetag component
  ------------------------------------------------------------------------------
  component conv_ring_buf is
    generic
    (
      g_data_width : positive;
      g_size       : positive
    );
    port
    (
      -- Clocks and reset
      clk_rd_i       : in  std_logic;
      clk_wr_i       : in  std_logic;
      rst_n_a_i      : in  std_logic;

      -- Buffer inputs
      buf_dat_i      : in  std_logic_vector(g_data_width-1 downto 0);
      buf_rd_req_i   : in  std_logic;
      buf_wr_req_i   : in  std_logic;
      buf_clr_i      : in  std_logic;

      -- Buffer outputs
      buf_dat_o      : out std_logic_vector(g_data_width-1 downto 0);
      buf_count_o    : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
      buf_full_o     : out std_logic;
      buf_empty_o    : out std_logic
    );
  end component conv_ring_buf;

  --============================================================================
  -- Signal declarations
  --============================================================================
  -- Internal clock signals
  signal clk_125              : std_logic;

  -- Reset signals
  signal rst_20_n             : std_logic;
  signal rst_unlock           : std_logic;
  signal rst_unlock_bit       : std_logic;
  signal rst_unlock_bit_ld    : std_logic;
  signal rst_bit              : std_logic;
  signal rst_bit_ld           : std_logic;
  signal rst_fr_reg           : std_logic;
  signal rst_125_n            : 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);

  -- Signals to/from converter system registers component
  signal rtm_lines            : std_logic_vector(5 downto 0);
  signal switches_n           : std_logic_vector(7 downto 0);
  signal i2c_wdto_bit         : std_logic;
  signal i2c_wdto_bit_rst     : std_logic;
  signal i2c_wdto_bit_rst_ld  : std_logic;
  signal pmisse_bit           : std_logic;
  signal pmisse_bit_rst       : std_logic;
  signal pmisse_bit_rst_ld    : std_logic;
  signal pulse_cnt            : t_pulse_cnt;
  signal ch_pcr               : t_ch_pcr;
  signal ch_pcr_ld            : std_logic_vector(g_nr_ttl_chan downto 1);
  signal mpt_ld               : std_logic;
  signal mpt                  : std_logic_vector( 7 downto 0);
  signal tvlr                 : std_logic_vector(31 downto 0);
  signal tvlr_ld              : std_logic;
  signal tvhr                 : std_logic_vector( 7 downto 0);
  signal tvhr_ld              : std_logic;
  signal wrpres               : std_logic;
  signal i2c_err_bit          : std_logic;
  signal i2c_err_bit_rst      : std_logic;
  signal i2c_err_bit_rst_ld   : std_logic;

  -- Signals for pulse generation triggers
  signal trig_a               : std_logic_vector(g_nr_ttl_chan downto 1);
  signal trig_ttl_a           : std_logic_vector(g_nr_ttl_chan downto 1);
  signal trig_blo_a           : std_logic_vector(g_nr_ttl_chan downto 1);
  signal trig_synced          : std_logic_vector(g_nr_ttl_chan downto 1);
  signal trig_degl            : std_logic_vector(g_nr_ttl_chan downto 1);
  signal trig_chan            : std_logic_vector(g_nr_ttl_chan downto 1);
  signal trig_man             : std_logic_vector(g_nr_ttl_chan downto 1);
  signal pgen_trig            : std_logic_vector(g_nr_ttl_chan downto 1);
  signal pcnt_trig_p          : std_logic_vector(g_nr_ttl_chan downto 1);
  signal pmiss_p              : std_logic_vector(g_nr_ttl_chan downto 1);

  -- TTL-BAR lack of signal counter
  signal ttlbar_nosig_cnt     : t_ttlbar_nosig_cnt;
  signal ttlbar_nosig_n       : std_logic_vector(g_nr_ttl_chan downto 1);

  -- Temporary signals for blocking and TTL pulse outputs
  signal pulse_outp           : std_logic_vector(g_nr_ttl_chan downto 1);
  signal pulse_outp_d0        : std_logic_vector(g_nr_ttl_chan downto 1);
  signal pulse_outp_r_edge_p  : std_logic_vector(g_nr_ttl_chan downto 1);

  signal blo_ch_en            : std_logic_vector(g_nr_ttl_chan downto 1);

  -- Pulse status LED signals
  signal pulse_leds           : std_logic_vector(g_nr_ttl_chan downto 1);
  signal pulse_led_cnt        : t_pulse_led_cnt;

  -- Output enable signals
  signal oe, ttl_oe           : std_logic;
  signal blo_oe, inv_oe       : std_logic;

  -- Signal for controlling the bicolor LED matrix
  signal bicolor_led_state    : std_logic_vector(23 downto 0);

  -- I2C bridge signals
  signal i2c_tip              : std_logic;
  signal i2c_err_p            : std_logic;
  signal i2c_wdto_p           : std_logic;
  signal i2c_addr             : std_logic_vector(6 downto 0);
  signal led_i2c              : std_logic;
  signal led_i2c_clkdiv       : unsigned(18 downto 0);
  signal led_i2c_cnt          : unsigned( 2 downto 0);
  signal led_i2c_blink        : std_logic;

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

  -- Time-tagging component signals
  signal tm_cycles            : std_logic_vector(27 downto 0);
  signal tm_tai               : std_logic_vector(39 downto 0);

  signal buf_wr_req_p         : std_logic;
  signal buf_rd_req_p         : std_logic;
  signal buf_count            : std_logic_vector(f_log2_size(c_tb_size)-1 downto 0);
  signal buf_full             : std_logic;
  signal buf_empty            : std_logic;
  signal buf_chan             : std_logic_vector(g_nr_ttl_chan downto 1);
  signal buf_wrtag            : std_logic;
  signal buf_clr_bit          : std_logic;
  signal buf_clr_bit_ld       : std_logic;
  signal buf_clr_p            : std_logic;
  signal buf_dat_in           : std_logic_vector(c_tb_data_width-1 downto 0);
  signal buf_dat_out          : std_logic_vector(c_tb_data_width-1 downto 0);

--==============================================================================
--  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  => fpga_clk_p_i,
      IB => fpga_clk_n_i
      );


  --============================================================================
  -- Internal and external reset generation
  --============================================================================
  -- Configure reset generator for 100ms power-on reset
  cmp_reset_gen : reset_gen
    generic map
    (
      -- Reset time: 50ns * 2 * (10**6) = 100 ms
      g_reset_time => f_reset_width
    )
    port map
    (
      clk_i   => clk_20_vcxo_i,
      rst_i   => rst_fr_reg,
      rst_n_o => rst_20_n
    );

  -- Set the blocking power supply reset output with this reset
  mr_n_o <= rst_20_n;

  -- And synchronize the 20 MHz domain reset into the 125 MHz domain
  cmp_sync_rst : gc_sync_ffs
   generic map
   (
     g_sync_edge => "positive"
   )
   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" & fpga_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_vcxo_i,
      rst_n_i    => rst_20_n,

      -- I2C lines
      scl_i      => scl_i,
      scl_o      => scl_o,
      scl_en_o   => scl_oe_o,
      sda_i      => sda_i,
      sda_o      => sda_o,
      sda_en_o   => sda_oe_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
    );

  -- Process to blink the LED when an I2C transfer is in progress
  -- blinks four times per transfer
  -- blink width : 20 ms
  -- blink period: 40 ms
  p_i2c_blink : process(clk_20_vcxo_i)
  begin
    if rising_edge(clk_20_vcxo_i) then
      if (rst_20_n = '0') then
        led_i2c_clkdiv <= (others => '0');
        led_i2c_cnt    <= (others => '0');
        led_i2c        <= '0';
        led_i2c_blink  <= '0';
      else
        case led_i2c_blink is

          when '0' =>
            led_i2c <= '0';
            if (i2c_tip = '1') then
              led_i2c_blink <= '1';
            end if;

          when '1' =>
            led_i2c_clkdiv <= led_i2c_clkdiv + 1;
            if (led_i2c_clkdiv = 399999) then
              led_i2c_clkdiv <= (others => '0');
              led_i2c_cnt    <= led_i2c_cnt + 1;
              led_i2c        <= not led_i2c;
              if (led_i2c_cnt = 7) then
                led_i2c_cnt <= (others => '0');
                led_i2c_blink <= '0';
              end if;
            end if;

          when others =>
            led_i2c_blink <= '0';

        end case;
      end if;
    end if;
  end process p_i2c_blink;

  -- Register for the I2C_WDTO bit in the SR, cleared by writing a '1'
  p_sr_wdto_bit : process (clk_20_vcxo_i)
  begin
    if rising_edge(clk_20_vcxo_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_vcxo_i) is
  begin
    if rising_edge(clk_20_vcxo_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_vcxo_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
  );

  --============================================================================
  -- Converter board registers
  --============================================================================
  -- Set SWITCH and RTM fields
  switches_n <= ttl_switch_n_i & extra_switch_n_i(7 downto 1);
  rtm_lines  <= (not fpga_rtmp_n_i) & (not fpga_rtmm_n_i);

  -- Then, instantiate the component
  cmp_conv_regs : conv_regs
    port map (
      rst_n_i                  => rst_20_n,
      clk_sys_i                => clk_20_vcxo_i,

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

      reg_bidr_i               => c_board_id,

      reg_sr_gwvers_i          => c_gwvers,
      reg_sr_switches_i        => switches_n,
      reg_sr_rtm_i             => rtm_lines,
      reg_sr_i2c_wdto_o        => i2c_wdto_bit_rst,
      reg_sr_i2c_wdto_i        => i2c_wdto_bit,
      reg_sr_i2c_wdto_load_o   => i2c_wdto_bit_rst_ld,
      reg_sr_wrpres_i          => wrpres,
      reg_sr_i2c_err_o         => i2c_err_bit_rst,
      reg_sr_i2c_err_i         => i2c_err_bit,
      reg_sr_i2c_err_load_o    => i2c_err_bit_rst_ld,
      reg_sr_pmisse_o          => pmisse_bit_rst,
      reg_sr_pmisse_i          => pmisse_bit,
      reg_sr_pmisse_load_o     => pmisse_bit_rst_ld,

      reg_cr_rst_unlock_o      => rst_unlock_bit,
      reg_cr_rst_unlock_i      => rst_unlock,
      reg_cr_rst_unlock_load_o => rst_unlock_bit_ld,
      reg_cr_rst_o             => rst_bit,
      reg_cr_rst_i             => rst_fr_reg,
      reg_cr_rst_load_o        => rst_bit_ld,
      reg_cr_mpt_o             => mpt,
      reg_cr_mpt_wr_o          => mpt_ld,

      reg_ch1pcr_o             => ch_pcr(1),
      reg_ch1pcr_i             => std_logic_vector(pulse_cnt(1)),
      reg_ch1pcr_load_o        => ch_pcr_ld(1),
      reg_ch2pcr_o             => ch_pcr(2),
      reg_ch2pcr_i             => std_logic_vector(pulse_cnt(2)),
      reg_ch2pcr_load_o        => ch_pcr_ld(2),
      reg_ch3pcr_o             => ch_pcr(3),
      reg_ch3pcr_i             => std_logic_vector(pulse_cnt(3)),
      reg_ch3pcr_load_o        => ch_pcr_ld(3),
      reg_ch4pcr_o             => ch_pcr(4),
      reg_ch4pcr_i             => std_logic_vector(pulse_cnt(4)),
      reg_ch4pcr_load_o        => ch_pcr_ld(4),
      reg_ch5pcr_o             => ch_pcr(5),
      reg_ch5pcr_i             => std_logic_vector(pulse_cnt(5)),
      reg_ch5pcr_load_o        => ch_pcr_ld(5),
      reg_ch6pcr_o             => ch_pcr(6),
      reg_ch6pcr_i             => std_logic_vector(pulse_cnt(6)),
      reg_ch6pcr_load_o        => ch_pcr_ld(6),

      reg_tvlr_o               => tvlr,
      reg_tvlr_i               => tm_tai(31 downto 0),
      reg_tvlr_load_o          => tvlr_ld,
      reg_tvhr_o               => tvhr,
      reg_tvhr_i               => tm_tai(39 downto 32),
      reg_tvhr_load_o          => tvhr_ld,

      reg_tbmr_chan_i          => buf_dat_out( 5 downto  0),
      reg_tbmr_wrtag_i         => buf_dat_out( 6),
      reg_tb_rd_req_p_o        => buf_rd_req_p,
      reg_tbcyr_i              => buf_dat_out(34 downto  7),
      reg_tbtlr_i              => buf_dat_out(66 downto 35),
      reg_tbthr_i              => buf_dat_out(74 downto 67),
      reg_tbcsr_clr_o          => buf_clr_bit,
      reg_tbcsr_clr_i          => '0',
      reg_tbcsr_clr_load_o     => buf_clr_bit_ld,
      reg_tbcsr_usedw_i        => buf_count,
      reg_tbcsr_full_i         => buf_full,
      reg_tbcsr_empty_i        => buf_empty
    );

  -- Implement the RST_UNLOCK bit
  p_rst_unlock : process (clk_20_vcxo_i)
  begin
    if rising_edge(clk_20_vcxo_i) then
      if (rst_20_n = '0') then
        rst_unlock <= '0';
      elsif (rst_unlock_bit_ld = '1') then
        if (rst_unlock_bit = '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_vcxo_i)
  begin
    if rising_edge(clk_20_vcxo_i) then
      if (rst_20_n = '0') then
        rst_fr_reg <= '0';
      elsif (rst_bit_ld = '1') and (rst_bit = '1') and (rst_unlock = '1') then
        rst_fr_reg <= '1';
      else
        rst_fr_reg <= '0';
      end if;
    end if;
  end process p_rst_fr_reg;

  -- Synchronize WR valid signal to implement the WRPRES bit
  cmp_wrpres_sync : gc_sync_ffs
    generic map
    (
      g_sync_edge => "positive"
    )
    port map
    (
      clk_i    => clk_20_vcxo_i,
      rst_n_i  => rst_20_n,
      data_i   => buf_wrtag,
      synced_o => wrpres
    );

  -- Implement the TBCSR.CLR bit
  p_tbcsr_clr : process (clk_20_vcxo_i)
  begin
    if rising_edge(clk_20_vcxo_i) then
      if (rst_20_n = '0') then
        buf_clr_p <= '0';
      else
        buf_clr_p <= '0';
        if (buf_clr_bit_ld = '1') and (buf_clr_bit = '1') then
          buf_clr_p <= '1';
        end if;
      end if;
    end if;
  end process p_tbcsr_clr;

  -- Register for the PMISS bit in the SR, set by ANY channel missing a pulse,
  -- cleared by writing a '1' to it
  p_sr_pmisse_bit : process (clk_20_vcxo_i)
  begin
    if rising_edge(clk_20_vcxo_i) then
      if (rst_20_n = '0') then
        pmisse_bit <= '0';
      elsif not (pmiss_p = (pmiss_p'range => '0')) then
        pmisse_bit <= '1';
      elsif (pmisse_bit_rst_ld = '1') and (pmisse_bit_rst = '1') then
        pmisse_bit <= '0';
      end if;
    end if;
  end process p_sr_pmisse_bit;

  --============================================================================
  -- Output enable logic
  --============================================================================
  fpga_oe_o          <= '1';
  fpga_blo_oe_o      <= '1';
  fpga_trig_ttl_oe_o <= '1';
  fpga_inv_oe_o      <= '1';

  --============================================================================
  -- TTL and blocking pulse generation logic
  --============================================================================
  ------------------------------------------------------------------------------
  -- Pulse time-tagging logic after input channel MUX
  ------------------------------------------------------------------------------
  cmp_pulse_timetag : conv_pulse_timetag
    generic map
    (
    -- Frequency in Hz of the clk_i signal
      g_clk_rate => 125000000,
    -- Number of repetition channels
      g_nr_chan  => g_nr_ttl_chan
    )
    port map
    (
    -- Clock and active-low reset
      clk_i            => clk_125,
      rst_n_i          => rst_125_n,

    -- Asynchronous pulse input
      pulse_a_i        => trig_chan,

    -- Time inputs from White Rabbit
      wr_tm_cycles_i   => (others => '0'),
      wr_tm_tai_i      => (others => '0'),
      wr_tm_valid_i    => '0',

    -- Timing inputs from Wishbone-mapped registers
      wb_tm_tai_l_i    => tvlr,
      wb_tm_tai_l_ld_i => tvlr_ld,
      wb_tm_tai_h_i    => tvhr,
      wb_tm_tai_h_ld_i => tvhr_ld,

    -- Timing outputs
      tm_cycles_o      => tm_cycles,
      tm_tai_o         => tm_tai,
      tm_wrpres_o      => buf_wrtag,
      chan_o           => buf_chan,

    -- Ring buffer I/O
      buf_wr_req_p_o   => buf_wr_req_p
    );

  -- Assign ring buffer component inputs
  buf_dat_in( 5 downto  0) <= buf_chan;
  buf_dat_in( 6)           <= buf_wrtag;
  buf_dat_in(34 downto  7) <= tm_cycles;
  buf_dat_in(74 downto 35) <= tm_tai;

  -- Instantiate the ring buffer
  cmp_ring_buf : conv_ring_buf
    generic map
    (
      g_data_width => c_tb_data_width,
      g_size       => c_tb_size
    )
    port map
    (
      -- Clocks and reset
      clk_rd_i       => clk_20_vcxo_i,
      clk_wr_i       => clk_125,
      rst_n_a_i      => rst_20_n,

      -- Buffer inputs
      buf_dat_i      => buf_dat_in,
      buf_rd_req_i   => buf_rd_req_p,
      buf_wr_req_i   => buf_wr_req_p,
      buf_clr_i      => buf_clr_p,

      -- Buffer outputs
      buf_dat_o      => buf_dat_out,
      buf_full_o     => buf_full,
      buf_empty_o    => buf_empty,
      buf_count_o    => buf_count
    );

  ------------------------------------------------------------------------------
  -- Manual trigger
  ------------------------------------------------------------------------------
  cmp_man_trig : conv_man_trig
    generic map
    (
      g_nr_chan => g_nr_ttl_chan,
      g_gf_len  => c_pulse_gen_gf_len
    )
    port map
    (
      -- Clock, active-low inputs
      clk_i    => clk_20_vcxo_i,
      rst_n_i  => rst_20_n,

      -- Control inputs from conv_regs
      reg_ld_i => mpt_ld,
      reg_i    => mpt,

      -- One-clock pulse output
      trig_o   => trig_man
    );

  ------------------------------------------------------------------------------
  -- Generate pulse repetition logic
  ------------------------------------------------------------------------------
  gen_pulse_logic : for i in 1 to g_nr_ttl_chan generate

    -- First, the "no signal detect" blocks
    --
    -- If the signal line is high for 100 us, the ttlbar_nosig_n lines disable
    -- the input to the TTL side MUX and the OR gate.
    --
    -- The counter is disabled if the switch is set for TTL signals, to avoid
    -- unnecessary power consumption by the counter.
    p_ttlbar_nosig : process(clk_20_vcxo_i)
    begin
      if rising_edge(clk_20_vcxo_i) then
        if (rst_20_n = '0') or (fpga_input_ttl_n_i(i) = '0') then
          ttlbar_nosig_n(i)   <= '1';
          ttlbar_nosig_cnt(i) <= (others => '0');
        elsif (ttl_switch_n_i = '1') then
          ttlbar_nosig_cnt(i) <= ttlbar_nosig_cnt(i) + 1;
          if (ttlbar_nosig_cnt(i) = 1999) then
            ttlbar_nosig_n(i)   <= '0';
            ttlbar_nosig_cnt(i) <= (others => '0');
          end if;
        end if;
      end if;
    end process p_ttlbar_nosig;

    -- The first OR gate at the channel inputs
    trig_ttl_a(i) <= not fpga_input_ttl_n_i(i) when (ttl_switch_n_i = '0') else
                     fpga_input_ttl_n_i(i) and ttlbar_nosig_n(i);
    trig_blo_a(i) <= fpga_blo_in_i(i);
    trig_a(i)     <= trig_ttl_a(i) or trig_blo_a(i);

    -- Then, synchronize the asynchronous trigger input into the 20 MHz clock
    -- domain before passing it to the glitch filter
    --
    -- Reset value is '1' to avoid pulses being counted by pulse counter on
    -- startup, when the board is in TTL-BAR repetition mode.
    cmp_trig_sync : gc_sync_ffs
      generic map
      (
        g_sync_edge => "positive"
      )
      port map
      (
        clk_i    => clk_20_vcxo_i,
        rst_n_i  => '1',
        data_i   => trig_a(i),
        synced_o => trig_synced(i)
      );

    -- Deglitch synchronized trigger signal
    --
    -- Reset value is '1' to avoid pulses being counted by pulse counter on
    -- startup, when the board is in TTL-BAR repetition mode.
    cmp_inp_glitch_filt : gc_glitch_filt
      generic map
      (
        g_len => c_pulse_gen_gf_len
      )
      port map
      (
        clk_i   => clk_20_vcxo_i,
        rst_n_i => '1',
        dat_i   => trig_synced(i),
        dat_o   => trig_degl(i)
      );

    -- Now that we have a deglitched signal, generate the MUX to select between
    -- deglitched and direct channel input
    trig_chan(i) <= trig_a(i) when (extra_switch_n_i(1) = '1') else
                    trig_degl(i);

    -- Now, sync this channel trigger signal before passing it to the counters
    --
    -- Reset value is '1' to avoid pulses being counted by pulse counter on
    -- startup, when the board is in TTL-BAR repetition mode.
    --
    -- NOTE: glitch-filtered signal is also synced in 20MHz clock domain, but
    -- another sync chain here avoids extra logic complication and has no
    -- influence on the correctness of the pulse counter value considering the
    -- max expected pulse frequency
    cmp_sync_ffs : gc_sync_ffs
      port map
      (
        clk_i    => clk_20_vcxo_i,
        rst_n_i  => '1',
        data_i   => trig_chan(i),
        ppulse_o => pcnt_trig_p(i)
      );

    -- Then, generate the input pulse counters
    p_pulse_cnt : process (clk_20_vcxo_i)
    begin
      if rising_edge(clk_20_vcxo_i) then
        if (rst_20_n = '0') then
          pulse_cnt(i) <= (others => '0');
        elsif (ch_pcr_ld(i) = '1') then
          pulse_cnt(i) <= unsigned(ch_pcr(i));
        elsif (pcnt_trig_p(i) = '1') then
          pulse_cnt(i) <= pulse_cnt(i) + 1;
        end if;
      end if;
    end process p_pulse_cnt;

    -- FINALLY, the trigger input to the pulse generator block
    pgen_trig(i) <= trig_chan(i) or trig_man(i);

    -- Output pulse generators
    cmp_pulse_gen : ctblo_pulse_gen
      generic map
      (
        g_pwidth         => c_pulse_gen_pwidth,
        g_duty_cycle_div => c_pulse_gen_duty_cycle_div
      )
      port map
      (
        clk_i         => clk_20_vcxo_i,
        rst_n_i       => rst_20_n,
        en_i          => '1',
        gf_en_n_i     => extra_switch_n_i(1),
        trig_a_i      => pgen_trig(i),
        pulse_err_p_o => pmiss_p(i),
        pulse_o       => pulse_outp(i)
      );

    -- Process to flash pulse LED when a pulse is output
    -- LED flash length: 26 ms
    p_pulse_led : process (clk_20_vcxo_i) is
    begin
      if rising_edge(clk_20_vcxo_i) then
        if (rst_20_n = '0') then
          pulse_outp_d0(i)       <= '0';
          pulse_outp_r_edge_p(i) <= '0';
          pulse_led_cnt(i)       <= (others => '0');
          pulse_leds(i)          <= '0';
        else
          pulse_outp_d0(i)       <= pulse_outp(i);
          pulse_outp_r_edge_p(i) <= pulse_outp(i) and (not pulse_outp_d0(i));
          case pulse_leds(i) is
            when '0' =>
              if (pulse_outp_r_edge_p(i) = '1') then
                pulse_leds(i) <= '1';
              end if;
            when '1' =>
              pulse_led_cnt(i) <= pulse_led_cnt(i) + 1;
              if (pulse_led_cnt(i) = (pulse_led_cnt(i)'range => '1')) then
                pulse_leds(i) <= '0';
              end if;
            when others =>
              pulse_leds(i) <= '0';
          end case;
        end if;
      end if;
    end process;
  end generate gen_pulse_logic;

  ------------------------------------------------------------------------------
  -- Pulse and LED outputs assignment
  ------------------------------------------------------------------------------
  -- TTL and blocking outputs
  fpga_out_ttl_o  <= pulse_outp when (ttl_switch_n_i = '0') else
                     not pulse_outp;
  fpga_trig_blo_o <= pulse_outp;

  -- General-purpose INV-TTL outputs
  inv_out_o <= inv_in_n_i;

  -- Pulse status LED output assignments
  pulse_front_led_n_o <= not pulse_leds;
  pulse_rear_led_n_o  <= not pulse_leds;

  --============================================================================
  -- MultiBoot logic
  --============================================================================
  cmp_multiboot : wb_xil_multiboot
    port map
    (
      clk_i   => clk_20_vcxo_i,
      rst_n_i => rst_20_n,

      wbs_i   => xbar_master_out(c_slv_multiboot),
      wbs_o   => xbar_master_in(c_slv_multiboot),

      spi_cs_n_o => fpga_prom_cso_b_n_o,
      spi_sclk_o => fpga_prom_cclk_o,
      spi_mosi_o => fpga_prom_mosi_o,
      spi_miso_i => fpga_prom_miso_i
    );

  --============================================================================
  -- On-board DS18B20 Thermometer 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_vcxo_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 => open,
      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;

  --============================================================================
  -- Bicolor LED matrix logic
  --============================================================================
  -- Bicolor LED controls, corresponding to the column orders on the
  -- bicolor_led_ctrl unit.

  -- WR address
  bicolor_led_state( 1 downto  0) <= c_LED_OFF;

  -- WR GMT
  bicolor_led_state( 3 downto  2) <= c_LED_OFF;

  -- WR link
  bicolor_led_state( 5 downto  4) <= c_LED_OFF;

  -- WR OK
  bicolor_led_state( 7 downto  6) <= c_LED_OFF;

  -- MULTICAST 0
  bicolor_led_state( 9 downto  8) <= c_LED_OFF;

  -- MULTICAST 1
  bicolor_led_state(11 downto 10) <= c_LED_OFF;


  -- I2C
  bicolor_led_state(13 downto 12) <= c_LED_GREEN when (led_i2c = '1') else
                                     c_LED_OFF;

  -- State of TTL/TTL_N switch
  bicolor_led_state(15 downto 14) <= c_LED_GREEN when (ttl_switch_n_i = '0') else
                                     c_LED_OFF;

  -- System error
  bicolor_led_state(17 downto 16) <= c_LED_RED when (pmisse_bit = '1') or
                                                    (i2c_err_bit = '1') or
                                                    (i2c_wdto_bit = '1') else
                                     c_LED_OFF;

  -- System power
  bicolor_led_state(19 downto 18) <= c_LED_GREEN;

  -- MULTICAST 2
  bicolor_led_state(21 downto 20) <= c_LED_OFF;

  -- MULTICAST 3
  bicolor_led_state(23 downto 22) <= c_LED_OFF;

  cmp_bicolor_led_ctrl : 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_vcxo_i,
      rst_n_i         => rst_20_n,
      led_intensity_i => "1111111",
      led_state_i     => bicolor_led_state,
      column_o(0)     => led_wr_ownaddr_i2c_o,
      column_o(1)     => led_wr_gmt_ttl_ttln_o,
      column_o(2)     => led_wr_link_syserror_o,
      column_o(3)     => led_wr_ok_syspw_o,
      column_o(4)     => led_multicast_2_0_o,
      column_o(5)     => led_multicast_3_1_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 unused outputs with safe values
  --============================================================================
  -- DAC outputs: enables to '1' (disable DAC comm interface) and SCK, DIN to '0'
  fpga_plldac1_sync_n_o <= '1';
  fpga_plldac1_din_o    <= '0';
  fpga_plldac1_sclk_o   <= '0';
  fpga_plldac2_sync_n_o <= '1';
  fpga_plldac2_din_o    <= '0';
  fpga_plldac2_sclk_o   <= '0';

  -- SFP lines all open-drain, set to high-impedance
  fpga_sfp_rate_select_o <= 'Z';
  fpga_sfp_mod_def1_b    <= 'Z';
  fpga_sfp_mod_def2_b    <= 'Z';
  fpga_sfp_tx_disable_o  <= 'Z';

end behav;
--==============================================================================
--  architecture end
--==============================================================================
