

--=================================================================================================
--                                       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 masterfip_pts is  
port(
    -- Clock and reset
    clk_i              : in    std_logic;   -- 100 MHz clock
    rst_i              : in    std_logic;   

    -- 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_n_o    : out std_logic;     -- transceiver output enable
    ext_sync_io        : inout std_logic;      -- sync pulse

    -- FielDrive
    fd_rxcdn_i         : in    std_logic;
    fd_txer_i          : in    std_logic;
    fd_wdgn_i          : in    std_logic;
    fd_txd_corrupt_o   : out   std_logic;

    -- WISHBONE classic bus interface
    slave_i             : in  t_wishbone_slave_in;
    slave_o             : out t_wishbone_slave_out
);  
end masterfip_pts;


--=================================================================================================
--                                    architecture declaration
--=================================================================================================
architecture rtl of masterfip_pts is

    -- resets
    signal  rst_n                            : std_logic;
    
    signal  core_rst, 
            core_rst_n,
            core_rst_tmp                    : std_logic;

    
    -- ext pulse
    signal  ext_sync_p, 
            ext_sync_oe,
            ext_sync_iodir,
            ext_sync_out_val,
            ext_sync_dir                    : std_logic;

    -- FielDrive output monitoring
    signal  fd_cnt_reinit,
            fd_wdgn_sync,
            fd_wdgn_latch,
            fd_txer_p,
            fd_rxcdn_p                      : std_logic;
    
    signal  fd_txer_cnt,
            fd_rxcdn_cnt                    : std_logic_vector (32-1 downto 0);


    -- signals that should be driven by masterfip core
    -- not sure if removing them will work
    signal  fd_host_rstn                    : std_logic;
    signal  macrocyc_load_p                 : std_logic;


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


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

    core_rst        <= core_rst_tmp or rst_i;
    core_rst_n      <= not core_rst;

    macrocyc_load_p <= '0';
    fd_host_rstn    <= '1';


---------------------------------------------------------
---- External synchronisation IO
---------------------------------------------------------
    -- FPGA IO direction is controlled by ext_sync_iodir line
    -- external bidirectional buffer is controlled by other line
    -- during normal operation direction should be the same
    -- but for PTS directions are controlled separately
    ext_sync_io     <= ext_sync_out_val when ext_sync_iodir = '1' else 'Z';
    ext_sync_dir_o  <= '1' when ext_sync_dir = '1' else 'Z';

    -- since external line oe_n is active low and wbregs default value is zero
    -- register is called oe and its value is negated here
    ext_sync_oe_n_o <= '1' when ext_sync_oe = '0' else 'Z';



---------------------------------------------------------------------------------------------------
--                                       FielDrive TXERR, WDGN                                   --
---------------------------------------------------------------------------------------------------
  -- synchronisation of the fd_wdgn_i signal
    cmp_fd_wdgn_i_pulse_detect: gc_sync_ffs
    generic map(
        g_sync_edge => "positive"
    )
    port map(
        clk_i    => clk_i,
        rst_n_i  => rst_n,
        data_i   => fd_wdgn_i,
        synced_o => fd_wdgn_sync
    );


    -- process that registers the activation of fd_wdgn_i
    -- the signals are reset upon a core_rst_n or a fd_host_rstn
    p_fd_wdgn_capture : process(clk_i)
    begin
        if rising_edge(clk_i) then
            if(core_rst = '1' or fd_host_rstn = '0') then
                fd_wdgn_latch      <= '1';
            else
                if fd_wdgn_sync = '0' then
                    fd_wdgn_latch    <= '0';
                end if;
            end if;
        end if;
    end process;

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
    
    fd_cnt_reinit <=    '1' when    core_rst_n = '0' or 
                                    macrocyc_load_p = '1' or 
                                    fd_host_rstn = '0' else 
                        '0';

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

    -- counter counting the number of fd_wdgn_p
    cmp_fd_txer_cnt:incr_counter
    generic map(
        g_counter_lgth => 32
    )
    port map(
        clk_i             => clk_i,
        counter_incr_i    => fd_txer_p,
        counter_reinit_i  => fd_cnt_reinit,
        counter_is_full_o => open,
        counter_o         => fd_txer_cnt
    );

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

    -- counter counting the number of fd_rxcdn_p
    cmp_fd_cdn_cnt:incr_counter
    generic map(
        g_counter_lgth => 32
    )
    port map(
        clk_i             => clk_i,
        counter_incr_i    => fd_rxcdn_p,
        counter_reinit_i  => fd_cnt_reinit,
        counter_is_full_o => open,
        counter_o         => fd_rxcdn_cnt
    );

    
---------------------------------------------------------------------------------------------------
--                                           REGISTERS                                           --
---------------------------------------------------------------------------------------------------
    cmp_masterfip_csr: entity work.masterfip_pts_csr
    port map (   
    -- wishbone
    rst_n_i                     => rst_n,
    clk_sys_i                   => clk_i,
    wb_adr_i                    => slave_i.adr(4 downto 2),
    wb_dat_i                    => slave_i.dat,
    wb_dat_o                    => slave_o.dat,
    wb_cyc_i                    => slave_i.cyc,
    wb_sel_i                    => slave_i.sel,
    wb_stb_i                    => slave_i.stb,
    wb_we_i                     => slave_i.we,
    wb_ack_o                    => slave_o.ack,
    wb_stall_o                  => slave_o.stall,
    
    -- resets
    mfpts_rst_core_o                => core_rst_tmp,        -- reset has to be confirmed with lock word mf_rstn_lock_o

    -- external sync pulse
    mfpts_ext_sync_term_en_o           => ext_sync_term_en_o,
    mfpts_ext_sync_dir_o               => ext_sync_dir,
    mfpts_ext_sync_oe_o                => ext_sync_oe,
    mfpts_ext_sync_output_value_o      => ext_sync_out_val,
    mfpts_ext_sync_fpga_io_dir_o       => ext_sync_iodir,
    mfpts_ext_sync_raw_input_i         => ext_sync_io,
    

    mfpts_tx_corrupt_enable_o          => fd_txd_corrupt_o,

    mfpts_fd_wdgn_i                    => fd_wdgn_i,      -- FIELDRIVE watchdog, signal comes from the FIELDRIVE
    mfpts_fd_wdgn_latch_i              => fd_wdgn_latch,

    mfpts_fd_cd_n_i                    => fd_rxcdn_i,
    mfpts_fd_rxcdn_cnt_i               => fd_rxcdn_cnt,

    mfpts_fd_txer_i                    => fd_txer_i,      -- FIELDRIVE txerr,    signal comes from the FIELDRIVE
    mfpts_fd_txerr_cnt_i               => fd_txer_cnt
    );

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