--_________________________________________________________________________________________________
--                                                                                                |
--                                           |TDC core|                                           |
--                                                                                                |
--                                         CERN,BE/CO-HT                                          |
--________________________________________________________________________________________________|

---------------------------------------------------------------------------------------------------
--                                                                                                |
--                                      fmc_masterFIP_core                                        |
--                                                                                                |
---------------------------------------------------------------------------------------------------
-- File         fmc_masterFIP_core.vhd                                                            |
--                                                                                                |
-- Description  The masterFIP_core instantiates all the modules needed to establish WorldFIP      |
--              communication. Figure 1 shows the modules of the core.                            |
--                                                                                                |
--         _      ________________________________________________________________                |
--        | |    |                                             fmc_masterFIP_core |               |
--        |W|    |   _________________    ____________    ____________    ______  |               |
--        |O|    |  |                 |  | macrocycle |  |  silence   |  |      | |               |
--        |R| <--|  |  masterfip_tx   |  | time cnt   |  |  time cnt  |  |      | |               |
--        |L|    |   _________________|  |____________|  |____________|  |      | |               |
--        |D|    |   _________________    ____________    ____________   | fmc  | |               |
--        |F| -->|  |                 |  | turnaround |  |            |  |master| | <-processor-> |
--        |I|    |  | masterfip_rx    |  |  time cnt  |  |   resets   |  | FIP  | |               |
--        |P|    |  |_________________|  |____________|  |____________|  | csr  | |               |
--        |_|    |                                                       |      | |               |
--               |   _________________                                   |      | |               |
-- sync pulse -->|  |  ext sync pulse |                                  |      | |               |
--               |  |_________________|                                  |      | |               |
--               |   _______                                             |      | |               |
--      LEDs  <--|  |  aux  |                                            |      | |               |
--               |  |_______|                                            |______| |               |
--               |________________________________________________________________|               |
--                                                Figure 1                                        |
--                                                                                                |
--              The fmc_masterfip_csr module establishes the interface with the processor, usually|
--              a Mock Turtle core. The module has been generated through the wbgen2 application. |
--              Please consult the fmc_masterfip_csr.htm for the registers map.                   |
--                                                                                                |
--              The masterfip_tx is placing a complete WorldFIP frame on the bus.                 |
--              The masterfip_tx is ignorant of the frame type (ID_DAT/RT_DAT/RP_MSG etc..) or the|
--              macrocycle sequence, as well as of timing issues (it does not for example measure |
--              internally the turnaround time after the delivery of an ID_DAT); the processor    |
--              (Mock Turtle for example) is responsible for managing all these issues and        |
--              for providing to the masterfip_tx (through the fmc_masterfip_csr) the data to     |
--              serialise and a start pulse. The communication between the processor (MT) and the |
--              masterfip_tx is through a set of control (from the MT) and status (from the       |
--              masterfip_tx) registers. Upon a rising edge on the tx_start control pulse, the    |
--              masterfip_tx is copying all the data registers (tx_data_ctrl,                     |
--              tx_data_reg1..tx_data_reg66) and then it initiates a WorldFIP frame, starting with|
--              the FSS, the tx_data_ctrl and then the number of data bytes indicated by the      |
--              tx_bytes_num register; it finally adds the CRC and FES and signals the processor  |
--              through the status bit tx_stop.                                                   |
--               ______________________________________________________________________________   |
--              |_____FSS_____|__Ctrl__|_____________tx_data______________|_____CRC____|__FES__|  |
--                                                                                                |
--              <-- 2 byes --><-1byte-><---------  tx_bytes_num  --------><-- 2 byes --><-1byte-> |
--                                                                                                |
--              The masterfip_rx is retrieving a WorldFIP frame from the bus.                     |
--              Similar to the masterfip_tx, the masterfip_rx has no intelligence regarding the   |
--              macrocycle sequence; it is controlled and monitored by the processor through the  |
--              fmc_masterfip_csr and a set of control and status registers.                      |
--              As long as it is not under reset, the masterfip_rx is looking at the WorldFIP bus |
--              trying to identify the FSS sequence of a WorldFIP frame. Upon the FSS detection   |
--              it signals the processor (MT) through the status bit fss_received and continues   |
--              with following the rest of the frame. It stores the first byte after the FSS to   |
--              the rx_data_ctrl register and the rest of the bytes to the registers              |
--              rx_data_reg1..rx_data_reg66. Upon the detection of a FES the masterfip_rx is      |
--              checking the CRC of the frame and enables the status bit rx_frame_ok or           |
--              rx_frame_error accordingly. Upon the rx_frame_ok, the status register             |
--              rx_bytes_num indicates the number of bytes that were in the frame (this indicates |
--              the number of rx_data_regs and the number of bytes inside the last rx_data_reg to |
--              be retrieved by the processor).                                                   |
--               ______________________________________________________________________________   |
--              |_____FSS_____|__Ctrl__|_____________rx_data______________|_____CRC____|__FES__|  |
--                                                                                                |
--              <-- 2 byes --><-1byte-><---------  rx_bytes_num  --------><-- 2 byes --><-1byte-> |
--                                                                                                |
--              The modules regarding the ext_sync_pulse are counting the number of rising-edge   |
--              pulses that are arriving to the ext_sync input of the board and provide the result|
--              to the dedicated fmc_masterfip_csr register to be accessed by the processor (MT). |
--                                                                                                |
--              The modules regarding the macrocycle are counting the time of a macrocycle using  |
--              the 10ns input clock as well as the number of macrocycles since the               |
--              startup/a reset. Dedicated registers in the fmc_masterfip_csr provide the counters|
--              values to the processor.                                                          |
--                                                                                                |
--              The modules regarding the turnaround and silence time are counting the respective |
--              time using the 10ns clock. Dedicated registers in the fmc_masterfip_csr provide   |
--              the counters values to the processor.                                             |
--                                                                                                |
-- Authors      Evangelia Gousiou (Evangelia.Gousiou@cern.ch)                                     |
-- Date         07/2014                                                                           |
-- Version      v1                                                                                |
-- Depends on                                                                                     |
--                                                                                                |
----------------                                                                                  |
-- Last changes                                                                                   |
--     07/2014  v1  EG  First version                                                             |
--                                                                                                |
---------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------
--                               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                     |
---------------------------------------------------------------------------------------------------

--=================================================================================================
--                                       Libraries & Packages
--=================================================================================================
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.masterFIP_pkg.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
-- use work.wrcore_pkg.all;
use work.genram_pkg.all;


--=================================================================================================
--                                Entity declaration for fmc_masterFIP_core
--=================================================================================================
entity fmc_masterFIP_core is
  generic
    (g_span             : integer := 32;     -- address span in bus interfaces
     g_width            : integer := 32;     -- data width in bus interfaces
     values_for_simul   : boolean := FALSE); -- this generic is set to TRUE when instantiated in a test-bench
  port
    (-- Clock and reset
     clk_i              : in    std_logic;   -- 40 MHz clock
     rst_i              : in    std_logic;   -- PoR or PCIe reset, synched with the clk_i

     -- Bus Speed                            -- 31.25 Kbps: speed_b1 = 0, speed_b0 = 0
     speed_b0_i         : in    std_logic;   -- 1 Mbps    : speed_b1 = 0, speed_b0 = 1
     speed_b1_i         : in    std_logic;   -- 2.5 Mbps  : speed_b1 = 1, speed_b0 = 0
                                             -- 5 Mbps    : speed_b1 = 1, speed_b0 = 1
     -- Bus termination
     bus_term_en_n_o    : out std_logic;     -- 150 Ohms termination of the bus -- check again

     -- External synchronisation pulse transceiver
     ext_sync_term_en_o : out std_logic;     -- enable 50 Ohms termination of the pulse
     ext_sync_dir_o     : out std_logic;     -- transceiver direction
     ext_sync_oe_o      : out std_logic;     -- transceiver output enable
     ext_sync_tst_n_o   : out std_logic;     -- emulation of the LEMO input
     ext_sync_i         : in std_logic;      -- sync pulse

     -- Power supplies for the ADC
     adc_1v8_shdn_n_o   : out std_logic;
     adc_m5v_shdn_n_o   : out std_logic;
     adc_5v_en_n_o      : out std_logic;
     adc_prim_conn_n_o  : out std_logic;
     adc_sec_conn_n_o   : out std_logic;

     -- FielDrive
     fd_rxcdn_i         : in    std_logic;
     fd_rxd_i           : in    std_logic;
     fd_txer_i          : in    std_logic;
     fd_wdgn_i          : in    std_logic;
     fd_rstn_o          : out   std_logic;
     fd_txck_o          : out   std_logic;
     fd_txd_o           : out   std_logic;
     fd_txena_o         : out   std_logic;

    -- WISHBONE classic bus interface
     wb_adr_i           : in    std_logic_vector(g_span-1 downto 0);
     wb_dat_i           : in    std_logic_vector(g_width-1 downto 0);
     wb_stb_i           : in    std_logic;
     wb_sel_i           : in    std_logic_vector(3 downto 0);
     wb_we_i            : in    std_logic;
     wb_cyc_i           : in    std_logic;
     wb_stall_o         : out   std_logic;
     wb_ack_o           : out   std_logic;
     wb_dat_o           : out   std_logic_vector(g_width-1 downto 0);

     -- Aux
     aux_o              : out std_logic_vector(7 downto 0));   -- group of 8 aux signals to pass to the higher levels
  end fmc_masterFIP_core;


--=================================================================================================
--                                    architecture declaration
--=================================================================================================
architecture rtl of fmc_masterFIP_core is

  -- resets
  constant c_RST_UNLOCK_VALUE : std_logic_vector(15 downto 0)    := x"cafe";
  signal rst_n, core_rst, core_rst_n                             : std_logic;
  signal core_rstn_tmp, fd_rstn_tmp, rstn_lock_wr, fd_host_rstn  : std_logic;
  signal core_host_rst, core_host_rstn                           : std_logic;
  signal rstn_lock                                               : std_logic_vector(15 downto 0);
  -- config
  signal speed                                                   : std_logic_vector(1 downto 0);
  -- ext pulse
  signal ext_sync_p, ext_sync_oe                                 : std_logic;
  signal ext_sync_p_cnt_rst, ext_sync_p_cnt_host_rst             : std_logic;
  signal ext_sync_p_cnt                                          : std_logic_vector(31 downto 0);
  -- counters
  signal macrocyc_load_p, turnar_load_p, silen_load_p            : std_logic;
  signal num_of_macrocyc_cnt                                     : std_logic_vector(31 downto 0);
  signal num_of_macrocyc_cnt_full, num_of_macrocyc_cnt_reinit    : std_logic;
  signal macrocyc_lgth, turnar_lgth, silen_lgth                  : std_logic_vector(30 downto 0);
  signal macrocyc_host_load, turnar_host_load, silen_host_load   : std_logic;
  signal macrocyc_host_load_p, turnar_host_load_p                : std_logic;
  signal silen_host_load_p                                       : std_logic;
  signal macrocyc_cnt, turnar_cnt, silen_cnt                     : std_logic_vector(30 downto 0);
  signal macrocyc_cnt_zero_p                                     : std_logic;
  -- tx
  signal tx_completed_p, tx_completed, tx_start, tx_start_p      : std_logic;
  signal tx_rst, tx_host_rst, tx_host_rst_p, fd_txd, fd_txck     : std_logic;
  signal tx_frame                                                : tx_frame_t;
  signal tx_ctrl_byte                                            : std_logic_vector(7 downto 0);
  signal tx_bytes_num, tx_byte_index                             : std_logic_vector(8 downto 0); -- up to 263 bytes
  -- rx
  signal rx_host_rst, rx_host_rst_p, rx_rst                      : std_logic;
  signal rx_fss_received_p, rx_fss_received                      : std_logic;
  signal rx_frame_ok_p, rx_frame_ok                              : std_logic;
  signal rx_crc_wrong_p, rx_crc_wrong, rx_byte_ready_p, fd_txena : std_logic;
  signal rx_frame                                                : rx_frame_t;
  signal rx_ctrl_byte, rx_byte                                   : std_logic_vector(7 downto 0);
  signal rx_byte_index, rx_bytes_num                             : std_logic_vector(8 downto 0); -- up to 263 bytes
  -- ADC
  signal adc_sec_conn_n, adc_prim_conn_n                         : std_logic;
  -- ext_sync
  signal ext_sync_tst_n                                          : std_logic;
  -- LEDs
  signal sync_led, out_of_sync_led                               : std_logic;
  -- debug
  signal mf_dbg                                                  : std_logic_vector(31 downto 0);
  signal mf_dbg_p, mf_dbg_p_ext                                  : std_logic;

  -- chipscope
   -- component chipscope_ila
     -- port (
       -- CONTROL : inout std_logic_vector(35 downto 0);
       -- CLK     : in    std_logic;
       -- TRIG0   : in    std_logic_vector(31 downto 0);
       -- TRIG1   : in    std_logic_vector(31 downto 0);
       -- TRIG2   : in    std_logic_vector(31 downto 0);
       -- TRIG3   : in    std_logic_vector(31 downto 0));
   -- end component;
   -- component chipscope_icon
     -- port (CONTROL0 : inout std_logic_vector(35 downto 0));
   -- end component;
   -- signal CONTROL : std_logic_vector(35 downto 0);
   -- signal CLK     : std_logic;
   -- signal TRIG0   : std_logic_vector(31 downto 0);
   -- signal TRIG1   : std_logic_vector(31 downto 0);
   -- signal TRIG2   : std_logic_vector(31 downto 0);
   -- signal TRIG3   : std_logic_vector(31 downto 0);


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

---------------------------------------------------------------------------------------------------
--                                           REGISTERS                                           --
---------------------------------------------------------------------------------------------------
  cmp_masterfip_csr: fmc_masterfip_csr
  port map
    -- wishbone
    (rst_n_i                     => rst_n,
     clk_sys_i                   => clk_i,
     wb_adr_i                    => wb_adr_i(9 downto 2),
     wb_dat_i                    => wb_dat_i,
     wb_dat_o                    => wb_dat_o,
     wb_cyc_i                    => wb_cyc_i,
     wb_sel_i                    => wb_sel_i,
     wb_stb_i                    => wb_stb_i,
     wb_we_i                     => wb_we_i,
     wb_ack_o                    => wb_ack_o,
     wb_stall_o                  => wb_stall_o,
     -- resets
     mf_rstn_core_o              => core_rstn_tmp, -- reset has to be confirmed with lock word mf_rstn_lock_o
     mf_rstn_fd_o                => fd_rstn_tmp,   -- reset has to be confirmed with lock word mf_rstn_lock_o
     mf_rstn_lock_o              => rstn_lock,
     mf_rstn_lock_wr_o           => rstn_lock_wr,
     --dbg
     mf_dbg_o                    => mf_dbg,
     -- adc supplies
     mf_adc_1v8_shdn_n_o         => adc_1v8_shdn_n_o,
     mf_adc_m5v_shdn_n_o         => adc_m5v_shdn_n_o,
     mf_adc_5v_en_n_o            => adc_5v_en_n_o,
     mf_adc_prim_conn_n_o        => adc_prim_conn_n,
     mf_adc_sec_conn_n_o         => adc_sec_conn_n,
     -- external sync pulse
     mf_ext_sync_term_en_o       => ext_sync_term_en_o,
     mf_ext_sync_dir_o           => ext_sync_dir_o,
     mf_ext_sync_oe_o            => ext_sync_oe,
     mf_ext_sync_tst_n_o         => ext_sync_tst_n,
     mf_ext_sync_p_cnt_rst_o     => ext_sync_p_cnt_host_rst,
     mf_ext_sync_p_cnt_i         => ext_sync_p_cnt,
     -- bus termination
     mf_bus_term_en_n_o          => bus_term_en_n_o,
     -- bus speed
     mf_speed_i(1)               => speed_b1_i,
     mf_speed_i(0)               => speed_b0_i,
     -- counters outputs
     mf_macrocyc_lgth_o          => macrocyc_lgth,
     mf_macrocyc_num_cnt_i       => num_of_macrocyc_cnt,
     mf_turnar_lgth_o            => turnar_lgth,
     mf_silen_lgth_o             => silen_lgth,
     mf_macrocyc_start_o         => macrocyc_host_load, -- optional counters loading through the host
     mf_turnar_start_o           => turnar_host_load,
     mf_silen_start_o            => silen_host_load,
     -- counters inputs
     mf_macrocyc_time_cnt_i      => macrocyc_cnt,
     mf_turnar_time_cnt_i        => turnar_cnt,
     mf_silen_time_cnt_i         => silen_cnt,
     -- tx control
     mf_tx_ctrl_rst_o            => tx_host_rst,    -- tx rst; then converted to 1-tick-long pulse
     mf_tx_ctrl_start_o          => tx_start,       -- tx start serializing a frame; then converted to 1-tick-long pulse
     mf_tx_ctrl_bytes_num_o      => tx_bytes_num,   -- number of bytes to serialize; sampled upon tx_start
     -- tx status
     mf_tx_stat_stop_i           => tx_completed,   -- 16x25ns long pulse upon the end of delivery of a frame
     mf_tx_stat_byte_index_i     => tx_byte_index,  -- index of current byte being serialized
     mf_tx_stat_ena_i            => fd_txena,       -- FIELDRIVE txena,    signal generated by the tx_serializer
     mf_fd_wdgn_i                => fd_wdgn_i,      -- FIELDRIVE watchdog, signal comes from the FIELDRIVE
     mf_fd_txer_i                => fd_txer_i,      -- FIELDRIVE txerr,    signal comes from the FIELDRIVE
     -- rx control/status
     mf_rx_ctrl_rst_o            => rx_host_rst,    -- note: this is not a pulse
     -- rx status
     mf_rx_stat_pream_ok_i       => rx_fss_received,
     mf_rx_stat_frame_ok_i       => rx_frame_ok,
     mf_rx_stat_frame_err_i      => rx_crc_wrong,
     mf_rx_stat_frame_err_code_i => "000",
     mf_rx_stat_bytes_num_i      => rx_bytes_num,
     -- rx data
     mf_rx_data_ctrl_i           => rx_ctrl_byte,
     mf_rx_data_reg1_i           => rx_frame(0),
     mf_rx_data_reg2_i           => rx_frame(1),
     mf_rx_data_reg3_i           => rx_frame(2),
     mf_rx_data_reg4_i           => rx_frame(3),
     mf_rx_data_reg5_i           => rx_frame(4),
     mf_rx_data_reg6_i           => rx_frame(5),
     mf_rx_data_reg7_i           => rx_frame(6),
     mf_rx_data_reg8_i           => rx_frame(7),
     mf_rx_data_reg9_i           => rx_frame(8),
     mf_rx_data_reg10_i          => rx_frame(9),
     mf_rx_data_reg11_i          => rx_frame(10),
     mf_rx_data_reg12_i          => rx_frame(11),
     mf_rx_data_reg13_i          => rx_frame(12),
     mf_rx_data_reg14_i          => rx_frame(13),
     mf_rx_data_reg15_i          => rx_frame(14),
     mf_rx_data_reg16_i          => rx_frame(15),
     mf_rx_data_reg17_i          => rx_frame(16),
     mf_rx_data_reg18_i          => rx_frame(17),
     mf_rx_data_reg19_i          => rx_frame(18),
     mf_rx_data_reg20_i          => rx_frame(19),
     mf_rx_data_reg21_i          => rx_frame(20),
     mf_rx_data_reg22_i          => rx_frame(21),
     mf_rx_data_reg23_i          => rx_frame(22),
     mf_rx_data_reg24_i          => rx_frame(23),
     mf_rx_data_reg25_i          => rx_frame(24),
     mf_rx_data_reg26_i          => rx_frame(25),
     mf_rx_data_reg27_i          => rx_frame(26),
     mf_rx_data_reg28_i          => rx_frame(27),
     mf_rx_data_reg29_i          => rx_frame(28),
     mf_rx_data_reg30_i          => rx_frame(29),
     mf_rx_data_reg31_i          => rx_frame(30),
     mf_rx_data_reg32_i          => rx_frame(31),
     mf_rx_data_reg33_i          => rx_frame(32),
     mf_rx_data_reg34_i          => rx_frame(33),
     mf_rx_data_reg35_i          => rx_frame(34),
     mf_rx_data_reg36_i          => rx_frame(35),
     mf_rx_data_reg37_i          => rx_frame(36),
     mf_rx_data_reg38_i          => rx_frame(37),
     mf_rx_data_reg39_i          => rx_frame(38),
     mf_rx_data_reg40_i          => rx_frame(39),
     mf_rx_data_reg41_i          => rx_frame(40),
     mf_rx_data_reg42_i          => rx_frame(41),
     mf_rx_data_reg43_i          => rx_frame(42),
     mf_rx_data_reg44_i          => rx_frame(43),
     mf_rx_data_reg45_i          => rx_frame(44),
     mf_rx_data_reg46_i          => rx_frame(45),
     mf_rx_data_reg47_i          => rx_frame(46),
     mf_rx_data_reg48_i          => rx_frame(47),
     mf_rx_data_reg49_i          => rx_frame(48),
     mf_rx_data_reg50_i          => rx_frame(49),
     mf_rx_data_reg51_i          => rx_frame(50),
     mf_rx_data_reg52_i          => rx_frame(51),
     mf_rx_data_reg53_i          => rx_frame(52),
     mf_rx_data_reg54_i          => rx_frame(53),
     mf_rx_data_reg55_i          => rx_frame(54),
     mf_rx_data_reg56_i          => rx_frame(55),
     mf_rx_data_reg57_i          => rx_frame(56),
     mf_rx_data_reg58_i          => rx_frame(57),
     mf_rx_data_reg59_i          => rx_frame(58),
     mf_rx_data_reg60_i          => rx_frame(59),
     mf_rx_data_reg61_i          => rx_frame(60),
     mf_rx_data_reg62_i          => rx_frame(61),
     mf_rx_data_reg63_i          => rx_frame(62),
     mf_rx_data_reg64_i          => rx_frame(63),
     mf_rx_data_reg65_i          => rx_frame(64),
     mf_rx_data_reg66_i          => rx_frame(65),
     -- tx data
     mf_tx_data_ctrl_o           => tx_ctrl_byte,
     mf_tx_data_reg1_o           => tx_frame(0),
     mf_tx_data_reg2_o           => tx_frame(1),
     mf_tx_data_reg3_o           => tx_frame(2),
     mf_tx_data_reg4_o           => tx_frame(3),
     mf_tx_data_reg5_o           => tx_frame(4),
     mf_tx_data_reg6_o           => tx_frame(5),
     mf_tx_data_reg7_o           => tx_frame(6),
     mf_tx_data_reg8_o           => tx_frame(7),
     mf_tx_data_reg9_o           => tx_frame(8),
     mf_tx_data_reg10_o          => tx_frame(9),
     mf_tx_data_reg11_o          => tx_frame(10),
     mf_tx_data_reg12_o          => tx_frame(11),
     mf_tx_data_reg13_o          => tx_frame(12),
     mf_tx_data_reg14_o          => tx_frame(13),
     mf_tx_data_reg15_o          => tx_frame(14),
     mf_tx_data_reg16_o          => tx_frame(15),
     mf_tx_data_reg17_o          => tx_frame(16),
     mf_tx_data_reg18_o          => tx_frame(17),
     mf_tx_data_reg19_o          => tx_frame(18),
     mf_tx_data_reg20_o          => tx_frame(19),
     mf_tx_data_reg21_o          => tx_frame(20),
     mf_tx_data_reg22_o          => tx_frame(21),
     mf_tx_data_reg23_o          => tx_frame(22),
     mf_tx_data_reg24_o          => tx_frame(23),
     mf_tx_data_reg25_o          => tx_frame(24),
     mf_tx_data_reg26_o          => tx_frame(25),
     mf_tx_data_reg27_o          => tx_frame(26),
     mf_tx_data_reg28_o          => tx_frame(27),
     mf_tx_data_reg29_o          => tx_frame(28),
     mf_tx_data_reg30_o          => tx_frame(29),
     mf_tx_data_reg31_o          => tx_frame(30),
     mf_tx_data_reg32_o          => tx_frame(31),
     mf_tx_data_reg33_o          => tx_frame(32),
     mf_tx_data_reg34_o          => tx_frame(33),
     mf_tx_data_reg35_o          => tx_frame(34),
     mf_tx_data_reg36_o          => tx_frame(35),
     mf_tx_data_reg37_o          => tx_frame(36),
     mf_tx_data_reg38_o          => tx_frame(37),
     mf_tx_data_reg39_o          => tx_frame(38),
     mf_tx_data_reg40_o          => tx_frame(39),
     mf_tx_data_reg41_o          => tx_frame(40),
     mf_tx_data_reg42_o          => tx_frame(41),
     mf_tx_data_reg43_o          => tx_frame(42),
     mf_tx_data_reg44_o          => tx_frame(43),
     mf_tx_data_reg45_o          => tx_frame(44),
     mf_tx_data_reg46_o          => tx_frame(45),
     mf_tx_data_reg47_o          => tx_frame(46),
     mf_tx_data_reg48_o          => tx_frame(47),
     mf_tx_data_reg49_o          => tx_frame(48),
     mf_tx_data_reg50_o          => tx_frame(49),
     mf_tx_data_reg51_o          => tx_frame(50),
     mf_tx_data_reg52_o          => tx_frame(51),
     mf_tx_data_reg53_o          => tx_frame(52),
     mf_tx_data_reg54_o          => tx_frame(53),
     mf_tx_data_reg55_o          => tx_frame(54),
     mf_tx_data_reg56_o          => tx_frame(55),
     mf_tx_data_reg57_o          => tx_frame(56),
     mf_tx_data_reg58_o          => tx_frame(57),
     mf_tx_data_reg59_o          => tx_frame(58),
     mf_tx_data_reg60_o          => tx_frame(59),
     mf_tx_data_reg61_o          => tx_frame(60),
     mf_tx_data_reg62_o          => tx_frame(61),
     mf_tx_data_reg63_o          => tx_frame(62),
     mf_tx_data_reg64_o          => tx_frame(63),
     mf_tx_data_reg65_o          => tx_frame(64),
     mf_tx_data_reg66_o          => tx_frame(65));

  adc_sec_conn_n_o  <= '0' when adc_sec_conn_n = '0'  else 'Z';
  adc_prim_conn_n_o <= '0' when adc_prim_conn_n = '0' else 'Z';
  ext_sync_tst_n_o  <= '0' when ext_sync_tst_n= '0'   else 'Z';


---------------------------------------------------------------------------------------------------
--                                             resets                                            --
---------------------------------------------------------------------------------------------------
  rst_n <= not rst_i;

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  -- reset generation
  p_host_reset : process(clk_i)
  begin
    if rising_edge(clk_i) then
      if(rst_n = '0') then
        core_host_rstn   <= '0';
        fd_host_rstn     <= '0';
      else
        -- protection against accidental write
        if(rstn_lock_wr = '1' and rstn_lock = c_RST_UNLOCK_VALUE) then
          core_host_rstn <= core_rstn_tmp;
          fd_host_rstn   <= fd_rstn_tmp;
        end if;
      end if;
    end if;
  end process;
  --  --  --  --  --  --  --  --  --  --  --
  core_host_rst <= not core_host_rstn;
  fd_rstn_o   <= fd_host_rstn;
  core_rst    <= core_host_rst or rst_i; -- combination of PoR, PCIe reset, reset from WRNC
  core_rst_n  <= not core_rst;


---------------------------------------------------------------------------------------------------
--                                         external sync                                         --
---------------------------------------------------------------------------------------------------
-- TODO: add antiglitch filter; maybe also disable the reception of a new pulse for some time after
-- the previous pulse

  -- synchronizer and edge detection
  cmp_ext_sync_p_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map
    (clk_i    => clk_i,
     rst_n_i  => core_rst_n,
     data_i   => ext_sync_i,
     ppulse_o => ext_sync_p);

  -- pulses counter
  cmp_ext_sync_p_cnt:incr_counter
  generic map(g_counter_lgth => 32)
  port map
    (clk_i            => clk_i,
     counter_incr_i   => ext_sync_p,
     counter_reinit_i => ext_sync_p_cnt_rst,
     counter_o        => ext_sync_p_cnt);
  --  --  --  --  --  --  --  --  --  --  --
     ext_sync_p_cnt_rst <= ext_sync_p_cnt_host_rst or core_rst;

--

---------------------------------------------------------------------------------------------------
--                                       macrocycle counter                                      --
---------------------------------------------------------------------------------------------------
  -- counter counting the macrocycle time
  cmp_macrocycle_time_cnt: decr_counter
  generic map(width   => 31)
  port map
    (clk_i             => clk_i,
     rst_i             => core_rst,
     counter_load_i    => macrocyc_load_p,
     counter_top_i     => macrocyc_lgth,
     counter_o         => macrocyc_cnt,
     counter_is_zero_o => macrocyc_cnt_zero_p);
  --  --  --  --  --  --  --  --  --  --  --
     macrocyc_load_p <= macrocyc_cnt_zero_p or macrocyc_host_load_p or ext_sync_p;

  -- edge detection of the macrocyc_host_load signal
  cmp_macrocyc_host_load_p_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map
    (clk_i    => clk_i,
     rst_n_i  => core_rst_n,
     data_i   => macrocyc_host_load,
     ppulse_o => macrocyc_host_load_p);

  -- in an application where an external synchronization pulse is expected for every macrocyle,
  -- the macrocyc_lgth is set slightly larger than the external synchronization period; therefore
  -- th macrocycle counter should not be reaching zero; if it reaches zero, it means that the
  -- external synchronization pulse did not arrive in time
  cmp_out_of_sync_led: gc_extend_pulse
  generic map
    (g_width    => 1000000)
  port map
    (clk_i      => clk_i,
     rst_n_i    => core_rst_n,
     pulse_i    => macrocyc_cnt_zero_p,
     extended_o => out_of_sync_led);


  cmp_sync_led: gc_extend_pulse
  generic map
    (g_width    => 1000000)
  port map
    (clk_i      => clk_i,
     rst_n_i    => core_rst_n,
     pulse_i    => ext_sync_p,
     extended_o => sync_led);

  -- counter counting the number of macrocycles; when it fills up it restarts
  cmp_macrocycles_cnt:incr_counter
  generic map(g_counter_lgth => 32)
  port map
    (clk_i             => clk_i,
     counter_incr_i    => macrocyc_cnt_zero_p,
     counter_reinit_i  => num_of_macrocyc_cnt_reinit,
     counter_is_full_o => num_of_macrocyc_cnt_full,
     counter_o         => num_of_macrocyc_cnt);

    num_of_macrocyc_cnt_reinit <= core_rst_n or num_of_macrocyc_cnt_full;
---------------------------------------------------------------------------------------------------
--                                       turnaround counter                                      --
---------------------------------------------------------------------------------------------------
  -- turnaround counter
  cmp_turnaround_cnt: decr_counter
  generic map(width   => 31)
  port map
    (clk_i             => clk_i,
     rst_i             => core_rst,
     counter_load_i    => turnar_load_p,
     counter_top_i     => turnar_lgth,
     counter_o         => turnar_cnt,
     counter_is_zero_o => open);
  --  --  --  --  --  --  --  --  --  --  --
     turnar_load_p <= tx_completed_p or rx_frame_ok_p or rx_crc_wrong_p or turnar_host_load_p;

  -- edge detection of the turnar_host_load signal
  cmp_turnar_host_load_p_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map
    (clk_i    => clk_i,
     rst_n_i  => core_rst_n,
     data_i   => turnar_host_load,
     ppulse_o => turnar_host_load_p);


--------------------------------------------------------------------------------------------------
--                                        silence counter                                       --
--------------------------------------------------------------------------------------------------
  -- silence time: maximum amount of time that the masterFIP waits for a response frame.
  -- the counting starts after an ID_DAT sent by the master (therefore loaded upon tx_completed_p)
  -- or by the FES of an RP_DAT_MSG as a RP_FIN is expected afterwards
  cmp_silence_cnt: decr_counter
  generic map(width   => 31)
  port map
    (clk_i             => clk_i,
     rst_i             => core_rst,
     counter_load_i    => silen_load_p,
     counter_top_i     => silen_lgth,
     counter_o         => silen_cnt,
     counter_is_zero_o => open);
  --  --  --  --  --  --  --  --  --  --  --
     silen_load_p <= tx_completed_p or rx_frame_ok_p or rx_crc_wrong_p or silen_host_load_p;

  -- edge detection of the silen_host_load signal
  cmp_silen_host_load_p_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map
    (clk_i    => clk_i,
     rst_n_i  => core_rst_n,
     data_i   => silen_host_load,
     ppulse_o => silen_host_load_p);


--------------------------------------------------------------------------------------------------
--                                        signals for tx                                        --
--------------------------------------------------------------------------------------------------
  -- edge detection on the tx_start signal
  cmp_tx_start_p_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map
    (clk_i    => clk_i,
     rst_n_i  => core_rst_n,
     data_i   => tx_start,
     ppulse_o => tx_start_p);


--------------------------------------------------------------------------------------------------
--                                        signals for rx                                        --
--------------------------------------------------------------------------------------------------
  -- edge detection on the rx_host_rst signal
   cmp_rx_host_rst_p_detect: gc_sync_ffs
   generic map(g_sync_edge => "positive")
   port map(
     clk_i    => clk_i,
     rst_n_i  => rst_n,
     data_i   => rx_host_rst,
     ppulse_o => rx_host_rst_p);
  --  --  --  --  --  --  --  --  --  --  --
     rx_rst <= rx_host_rst_p or fd_txena;

  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  -- registering the number of received bytes
  p_rx_bytes_num : process(clk_i)
  begin
    if rising_edge(clk_i) then
      if (core_rst_n = '0' or rx_rst = '1') then
        rx_bytes_num  <= (others => '0');
        rx_frame_ok   <= '0';
      else
        if rx_frame_ok_p = '1' then
          rx_frame_ok   <= rx_frame_ok_p;
          rx_bytes_num  <= rx_byte_index;
        end if;
      end if;
    end if;
  end process;

  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  -- extending the rx_fss_received_p until a core_rst or rx_rst is received
  p_rx_fss_received_extend : process(clk_i)
  begin
    if rising_edge(clk_i) then
      if(core_rst_n = '0' or rx_rst = '1') then
        rx_fss_received   <= '0';
      else
        if rx_fss_received_p = '1' then
          rx_fss_received <= '1';
        end if;
      end if;
    end if;
  end process;

  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  -- extending the rx_crc_wrong_p until a core_rst or rx_rst is received
  p_rx_crc_wrong_extend : process(clk_i)
  begin
    if rising_edge(clk_i) then
      if(core_rst_n = '0' or rx_rst = '1') then
        rx_crc_wrong   <= '0';
      else
        if rx_crc_wrong_p = '1' then
          rx_crc_wrong <= '1';
        end if;
      end if;
    end if;
  end process;

---------------------------------------------------------------------------------------------------
--                                               rx                                              --
---------------------------------------------------------------------------------------------------
  cmp_masterfip_rx: masterfip_rx
  port map
    (clk_i                 => clk_i,
     rst_i                 => core_rst,
     speed_i               => speed,
     fd_rxd_a_i            => fd_rxd_i,
     rx_rst_i              => rx_rst,        -- reset from the WRNC or reset while transmitting
  -------------------------------------------------------------
     rx_byte_index_o       => rx_byte_index, -- current amount of bytes (counting starts after the fss;
                                             -- includes ctrl, data, crc, fes fields)
     rx_ctrl_byte_o        => rx_ctrl_byte,
     rx_frame_o            => rx_frame,
     rx_byte_o             => rx_byte,
     rx_byte_ready_p_o     => rx_byte_ready_p,
     rx_fss_crc_fes_ok_p_o => rx_frame_ok_p,
     rx_fss_received_p_o   => rx_fss_received_p,
     rx_crc_wrong_p_o      => rx_crc_wrong_p);
  -------------------------------------------------------------

  speed <= speed_b1_i & speed_b0_i;



---------------------------------------------------------------------------------------------------
--                                               tx                                              --
---------------------------------------------------------------------------------------------------

  cmp_masterfip_tx: masterfip_tx
  port map
    (clk_i           => clk_i,
     rst_i           => tx_rst,
     speed_i         => speed,
     tx_bytes_num_i  => tx_bytes_num,
     tx_start_p_i    => tx_start_p,
     tx_frame_i      => tx_frame,
     tx_ctrl_byte_i  => tx_ctrl_byte,
  -------------------------------------------------------------
     tx_byte_index_o => tx_byte_index,
     tx_end_p_o      => tx_completed_p,
     tx_data_o       => fd_txd,
     tx_enable_o     => fd_txena,
     tx_clk_o        => fd_txck);
  -------------------------------------------------------------

  tx_rst     <= core_rst or tx_host_rst_p;
--  fd_txena_o <= fd_txena;
  fd_txd_o   <= fd_txd;
  fd_txck_o  <= fd_txck;

  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  -- delay for 1 cycle the fd_txena
  fd_txena_delay : process(clk_i)
  begin
    if rising_edge(clk_i) then
      if(tx_rst = '1') then
         fd_txena_o <= '0';
      else
         fd_txena_o <= fd_txena;
      end if;
    end if;
  end process;


--------------------------------------------------------------------------------------------------
--                                        signals for tx                                        --
--------------------------------------------------------------------------------------------------
  -- edge detection on the tx_host_rst signal
  cmp_tx_host_rst_pulse_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map
    (clk_i    => clk_i,
     rst_n_i  => rst_n,
     data_i   => tx_host_rst,
     ppulse_o => tx_host_rst_p);

  -- extension of the tx_completed_p so as to ensure capturing by the wrnc
  -- TODO: keep high and only reset upon reading from the MT
  cmp_tx_extend_p : gc_extend_pulse
  generic map (g_width => 32) -- 32 ticks long
  port map
    (clk_i      => clk_i,
     rst_n_i    => core_rst_n,
     pulse_i    => tx_completed_p,
     extended_o => tx_completed);


---------------------------------------------------------------------------------------------------
--                                              aux                                              --
---------------------------------------------------------------------------------------------------
  aux_o(7) <= out_of_sync_led;
  aux_o(6) <= mf_dbg_p_ext;--macrocyc_host_load_p;
  aux_o(5) <= mf_dbg(5);--macrocyc_load_p;
  aux_o(4) <= mf_dbg(4);--rx_byte_ready_p;
  aux_o(3) <= mf_dbg(3);--macrocyc_cnt_zero_p;
  aux_o(2) <= mf_dbg(2);--core_rst;--ext_sync_p;--tx_completed;
  aux_o(1) <= mf_dbg(1);--tx_start;
  aux_o(0) <= mf_dbg(0);--sync_led;

  ext_sync_oe_o <= ext_sync_oe;

  -- edge detection on the mf_dbg signal
  -- cmp_mf_dbg_pulse_detect: gc_sync_ffs
  -- generic map(g_sync_edge => "positive")
  -- port map
    -- (clk_i    => clk_i,
     -- rst_n_i  => rst_n,
     -- data_i   => mf_dbg,
     -- ppulse_o => mf_dbg_p);

  -- extension of the mf_dbg_p to capture it easier on the scope
  -- cmp_mf_dbg_p_extend : gc_extend_pulse
  -- generic map (g_width => 32) -- 32 ticks long
  -- port map
    -- (clk_i      => clk_i,
     -- rst_n_i    => core_rst_n,
     -- pulse_i    => mf_dbg_p,
     -- extended_o => mf_dbg_p_ext);


---------------------------------------------------------------------------------------------------
--                                           CHIPSCOPE                                           --
---------------------------------------------------------------------------------------------------

   -- chipscope_ila_1 : chipscope_ila
   -- port map (
     -- CONTROL => CONTROL,
     -- CLK     => clk_i,
     -- TRIG0   => TRIG0,
     -- TRIG1   => TRIG1,
     -- TRIG2   => TRIG2,
     -- TRIG3   => TRIG3);

  -- chipscope_icon_1 : chipscope_icon
   -- port map ( CONTROL0 => CONTROL);

  -- TRIG0(8 downto 0)   <= tx_bytes_num;
  -- TRIG0(9)            <= tx_start;
  -- TRIG0(10)           <= tx_start_p;
  -- TRIG0(18 downto 11) <= tx_ctrl_byte;
  -- TRIG0(27 downto 19) <= tx_byte_index;
  -- TRIG0(28)           <= tx_completed_p;
  -- TRIG0(29)           <= fd_txena;
  -- TRIG0(30)           <= fd_txd;
  -- TRIG0(31)           <= fd_txck;

  -- TRIG1               <= tx_frame(0);

  -- TRIG2(8 downto 0)   <= rx_byte_index;
  -- TRIG2(9)            <= rx_fss_received_p;
  -- TRIG2(10)           <= rx_byte_ready_p;
  -- TRIG2(18 downto 11) <= rx_byte;
  -- TRIG2(26 downto 19) <= rx_ctrl_byte;
  -- TRIG2(27)           <= rx_frame_ok_p;
  -- TRIG2(28)           <= rx_crc_wrong_p;

  -- TRIG2(29)           <= core_rst;
  -- TRIG2(31 downto 30) <= speed_b1_i & speed_b0_i;

  -- TRIG3               <= rx_frame(0);

  --TRIG0(17)           <= tx_start_p;
  --TRIG0(18)           <= rx_fss_crc_fes_ok_p;
  --TRIG0(19)           <= start_tx_p;

  --TRIG0(21)           <= rx_fss_crc_fes_ok_p;
  --TRIG0(22)           <= rx_fss_received_p;
  --TRIG0(23)           <= rx_crc_wrong_p;


  --TRIG1(15 downto 8)  <= rx_byte_index;
  --TRIG0(16)           <= start_from_fpga;
  --TRIG0(24 downto 17) <= retrig_nb_offset(7 downto 0);
  --TRIG0(31 downto 25) <= clk_i_cycles_offset(6 downto 0);


end rtl;
----------------------------------------------------------------------------------------------------
--  architecture ends
----------------------------------------------------------------------------------------------------
