--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- WR2RF_VME core
-- https://ohwr.org/project/vme-rf-wr-bobr
--------------------------------------------------------------------------------
--
-- unit name:   wr2rf_regs_core
--
-- description:
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN (home.cern)
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------

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

use work.wishbone_pkg.all;
use work.RFFrameTransceiver_pkg.all;

entity wr2rf_regs_core is

    generic (
        g_svec_mockup   : boolean := false );

    port (
        clk_sys_i      : in  std_logic;
        rst_sys_n_i    : in  std_logic;

        clk_ref_i      : in  std_logic;
        rst_ref_n_i    : in  std_logic;

        clk125_i       : in  std_logic;
        rst_clk125_n_i : in  std_logic;

        --  Top-level wishbone port (from VME)
        wb_vme_i           : in    t_wishbone_slave_in;
        wb_vme_o           : out   t_wishbone_slave_out;

        --  Wishbone port for WR core
        wb_wrc_i           : in    t_wishbone_master_in;
        wb_wrc_o           : out   t_wishbone_master_out;

        --  Wishbone port for the VTUs
        wb_rf1_vtus_i      : in    t_wishbone_master_in;
        wb_rf1_vtus_o      : out   t_wishbone_master_out;

        wb_rf2_vtus_i      : in    t_wishbone_master_in;
        wb_rf2_vtus_o      : out   t_wishbone_master_out;

        wb_rfframerxtx_i   : in    t_wishbone_master_in;
        wb_rfframerxtx_o   : out   t_wishbone_master_out;

        wb_rf1_rfnco_i     : in    t_wishbone_master_in;
        wb_rf1_rfnco_o     : out   t_wishbone_master_out;

        wb_rf2_rfnco_i     : in    t_wishbone_master_in;
        wb_rf2_rfnco_o     : out   t_wishbone_master_out;

        rf1_iqdac_phase_update_o : out std_logic;
        rf2_iqdac_phase_update_o : out std_logic;
        rf1_iqdac_igain_arm_o  : out std_logic_vector(15 downto 0);
        rf1_iqdac_qgain_arm_o  : out std_logic_vector(15 downto 0);
        rf2_iqdac_igain_arm_o  : out std_logic_vector(15 downto 0);
        rf2_iqdac_qgain_arm_o  : out std_logic_vector(15 downto 0);
        rf1_iqdac_igain_i  : in  std_logic_vector(15 downto 0);
        rf1_iqdac_qgain_i  : in  std_logic_vector(15 downto 0);
        rf2_iqdac_igain_i  : in  std_logic_vector(15 downto 0);
        rf2_iqdac_qgain_i  : in  std_logic_vector(15 downto 0);

        rf1_iqdac_ctrl_o   : out std_logic_vector(15 downto 0);
        rf2_iqdac_ctrl_o   : out std_logic_vector(15 downto 0);

        iqdac_ram_addr_o  : out   std_logic_vector(15 downto 0);
        iqdac_ram_data_o  : out   std_logic_vector(15 downto 0);
        iqdac_ram_write_o : out   std_logic_vector(15 downto 0);
        iqdac_ram_play_o  : out   std_logic_vector(15 downto 0);

        rf1_dds_ftw_valid_o : out std_logic;
        rf1_dds_ftw_o       : out std_logic_vector(47 downto 0);
        rf2_dds_ftw_valid_o : out std_logic;
        rf2_dds_ftw_o       : out std_logic_vector(47 downto 0);

        mmcm_locked_i    : in  std_logic;
        clk_sel_o        : out std_logic;
        clk_sys_reset_o  : out std_logic;
        wrcore_reset_n_o : out std_logic;
        iodelay_reset_o  : out std_logic;

        reconfigure_o    : out std_logic;

        mmcm_shift_incdec_o : out std_logic;
        mmcm_shift_en_o     : out std_logic;
        mmcm_shift_busy_i   : in  std_logic;

        tmg_clk_term_en_o      : out std_logic_vector(2 downto 1);
        tmg_io_term_en_o       : out std_logic_vector(4 downto 1);
        tmg_clk_oe_o           : out std_logic_vector(1 downto 0);
        tmg_io_oe_o            : out std_logic_vector(4 downto 1);

        rf1_t1_start_sel_o : out std_logic_vector(6 downto 1);
        rf1_t2_start_sel_o : out std_logic_vector(6 downto 1);
        rf2_t1_start_sel_o : out std_logic_vector(6 downto 1);
        rf2_t2_start_sel_o : out std_logic_vector(6 downto 1);
        rf1_t1_stop_sel_o  : out std_logic_vector(6 downto 1);
        rf1_t2_stop_sel_o  : out std_logic_vector(6 downto 1);
        rf2_t1_stop_sel_o  : out std_logic_vector(6 downto 1);
        rf2_t2_stop_sel_o  : out std_logic_vector(6 downto 1);

        tmgio1_osel_o     : out std_logic_vector(13 downto 0);
        tmgio2_osel_o     : out std_logic_vector(13 downto 0);
        tmgio3_osel_o     : out std_logic_vector(13 downto 0);
        tmgio4_osel_o     : out std_logic_vector(13 downto 0);
        tmgclk1_osel_o    : out std_logic_vector(13 downto 0);
        tmgclk2_osel_o    : out std_logic_vector(13 downto 0);

        lemo_gpio_o       : out std_logic_vector(2 downto 1);
        lemo_ext_sel_o    : out std_logic_vector(6 downto 1);
        softstart_sel_o   : out std_logic_vector(3 downto 0);
        softstop_sel_o    : out std_logic_vector(3 downto 0);

        ext_10m_dir_o     : out std_logic;
        ext_pps_dir_o     : out std_logic;

        dds_cs_n_o        : out std_logic;
        rf1_iqdac_cs_n_o  : out std_logic;
        rf2_iqdac_cs_n_o  : out std_logic;
        rf_sclk_o         : out std_logic;
        rf_sdi_o          : out std_logic;
        rf_sdo_i          : in  std_logic;

        dds_reset_o       : out std_logic;
        dds_ioupdate_o    : out std_logic;
        dds_profile_o     : out std_logic_vector(2 downto 0);
        dds_ioupdate_fdelay_o : out std_logic_vector(3 downto 0);
        dds_ioupdate_odelay_o : out std_logic_vector(4 downto 0);
        dds_sync_error_i  : in  std_logic;

        ocxo_enabled_o    : out std_logic;
        ocxo_uptime_i     : in  std_logic_vector(15 downto 0);

        pll_main_cs_n_o   : out std_logic;
        pll_main_sclk_o   : out std_logic;
        pll_main_sdi_o    : out std_logic;
        pll_main_sdo_i    : in  std_logic;

        pll_main_error_i  : in  std_logic;
        pll_main_locked_i : in  std_logic;
        pll_main_sync_o   : out std_logic;

        wr2rfsd_nco_azimuthal_o  : out std_logic_vector(47 downto 0);
        wr2rfsd_nco_cabledelay_o : out std_logic_vector(47 downto 0);
        wr2rfsd_nco_hb_o         : out std_logic_vector(9  downto 0);
        loc_nco_ctrl_reset_o     : out std_logic;
        loc_nco_h1_ftw_o         : out std_logic_vector(47 downto 0);
        loc_nco_h1_prog_o        : out std_logic_vector(47 downto 0);
        loc_nco_update_valid_o   : out std_logic;
        loc_or_wrs_params_sel_o  : out std_logic;

        -- monitor WR link for RF frames
        wrs_frame_last_ftw_i           : in  std_logic_vector (47 downto 0);
        wrs_frame_last_ctrl_i          : in  std_logic_vector (15 downto 0);
        wrs_frame_last_rxwrtimestamp_i : in  std_logic_vector (31 downto 0);
        wrs_frame_last_txwrtimestamp_i : in  std_logic_vector (31 downto 0);
        wrs_frame_last_rftimestamp_i   : in  std_logic_vector (31 downto 0);
        wrs_frame_counter_i            : in  std_logic_vector (15 downto 0);
        rfframe_ts_update_o            : out std_logic;
        rfframe_nco_reset_tai_i        : in  std_logic_vector(39 downto 0); 
        rfframe_nco_reset_cycles_i     : in  std_logic_vector(27 downto 0);
        rfframe_tai_i                  : in  std_logic_vector(39 downto 0);
        rfframe_cycles_i               : in  std_logic_vector(27 downto 0);
        
        -- registers to ctrl/cfg the svec_wr2rf_vme mockup card
        svec_mup_gpio_sel_o       : out std_logic_vector(3 downto 0);
        svec_mup_led_sel_o        : out std_logic_vector(3 downto 0);
        svec_mup_bclk_rfclk_sel_o : out std_logic;
        svec_mup_ila_sel_o        : out std_logic;

        svec_mup_rftrig_t1stop_o  : out std_logic;
        svec_mup_rftrig_t1start_o : out std_logic;
        svec_mup_rftrig_t2stop_o  : out std_logic;
        svec_mup_rftrig_t2start_o : out std_logic;

        svec_mup_fmc1_term_o : out std_logic_vector(4 downto 0);
        svec_mup_fmc1_oe_n_o : out std_logic_vector(4 downto 0);
        svec_mup_fmc1_led_o  : out std_logic_vector(1 downto 0);
        svec_mup_fmc2_term_o : out std_logic_vector(4 downto 0);
        svec_mup_fmc2_oe_n_o : out std_logic_vector(4 downto 0);
        svec_mup_fmc2_led_o  : out std_logic_vector(1 downto 0);

        nco_reset_dds_mask_o       : out std_logic;
        nco_reset_rfnco_ch1_mask_o : out std_logic;
        nco_reset_rfnco_ch2_mask_o : out std_logic;
        nco_reset_rf1_trig1_mask_o : out std_logic;
        nco_reset_rf2_trig1_mask_o : out std_logic;
        nco_reset_soft_o           : out std_logic;

        --  RF 1
        rf1_mux_sel_o        : out std_logic_vector(1 downto 0);
        rf1_mixer_en_o       : out std_logic;
        rf1_iqdac_reset_o    : out   std_logic;


        rf1_t1_delay_oen_o   : out std_logic;
        rf1_t1_mux_sel_o     : out std_logic;
        rf1_t1_rst_o         : out std_logic;
        rf1_t1_delay_latch_o : out std_logic;

        rf1_t2_delay_oen_o   : out std_logic;
        rf1_t2_mux_sel_o     : out std_logic;
        rf1_t2_rst_o         : out std_logic;
        rf1_t2_delay_latch_o : out std_logic;
        rf1_start_lpbk_o     : out std_logic;
        rf1_rst_cdelay_offset_o  : out std_logic_vector(6 downto 0);
        rf1_t1_sync_cdelay_o : out std_logic_vector(6 downto 0);
        rf1_t1_sync_fdelay_o : out std_logic_vector(3 downto 0);
        rf1_t1_sync_odelay_o : out std_logic_vector(4 downto 0);

        rf1_t1_vtu_start_p_i : in std_logic;
        rf1_t2_vtu_start_p_i : in std_logic;

        --  RF 2
        rf2_mux_sel_o        : out std_logic_vector(1 downto 0);
        rf2_mixer_en_o       : out std_logic;
        rf2_iqdac_reset_o    : out std_logic;

        rf2_t1_delay_oen_o   : out std_logic;
        rf2_t1_mux_sel_o     : out std_logic;
        rf2_t1_rst_o         : out std_logic;
        rf2_t1_delay_latch_o : out std_logic;

        rf2_t2_delay_oen_o   : out std_logic;
        rf2_t2_mux_sel_o     : out std_logic;
        rf2_t2_rst_o         : out std_logic;
        rf2_t2_delay_latch_o : out std_logic;
        rf2_start_lpbk_o     : out std_logic;
        rf2_rst_cdelay_offset_o  : out std_logic_vector(6 downto 0);
        rf2_t1_sync_cdelay_o : out std_logic_vector(6 downto 0);
        rf2_t1_sync_fdelay_o : out std_logic_vector(3 downto 0);
        rf2_t1_sync_odelay_o : out std_logic_vector(4 downto 0);

        rf2_t1_vtu_start_p_i : in std_logic;
        rf2_t2_vtu_start_p_i : in std_logic;

        rf_trig_ff_delay_o   : out std_logic_vector(9 downto 0);

        flash_cs_n_o         : out  std_logic;
        flash_mosi_o         : out  std_logic;
        flash_miso_i         : in   std_logic;
        flash_sck_o          : out std_logic;

        xadc_wb_i            : in t_wishbone_master_in;
        xadc_wb_o            : out t_wishbone_master_out;
    
        tm_tai_i            : in  std_logic_vector(39 downto 0);
        tm_cycles_i         : in  std_logic_vector(27 downto 0);
        tm_linkup_i         : in  std_logic;
        tm_time_valid_i     : in  std_logic;
        pps_i               : in  std_logic := '0';

        txframe_payload_o    : out  t_RFmFramePayload;

        bmctrl_rfframe_status_fifo_rdy_i :     std_logic;
        bmctrl_rfframe_ctrl_reset_o      : out std_logic;
        bmctrl_rfframe_ctrl_en_o         : out std_logic;
        bmctrl_rfframe_ctrl_update_o     : out std_logic;

        ila_sigs_o           : out std_logic_vector(7 downto 0) );

    attribute keep_hierarchy : string;
    attribute keep_hierarchy of wr2rf_regs_core : entity is "yes";
    attribute shreg_extract  : string;
    attribute shreg_extract  of wr2rf_regs_core : entity is "no";

end;

architecture arch of wr2rf_regs_core is

    signal wb_pll_spi_in          : t_wishbone_master_in;
    signal wb_pll_spi_out         : t_wishbone_master_out;

    signal wb_rf_spi_in           : t_wishbone_master_in;
    signal wb_rf_spi_out          : t_wishbone_master_out;

    signal wb_rf_in               : t_wishbone_master_in;
    signal wb_rf_out              : t_wishbone_master_out;

    signal wb16_wrpc_in           : t_wishbone_master_in;
    signal wb16_wrpc_out          : t_wishbone_master_out;

    signal wb_wrc_out             : t_wishbone_master_out;

    signal wb_fw_update_in        : t_wishbone_master_in;
    signal wb_fw_update_out       : t_wishbone_master_out;

    signal wb16_framerxtx_in  : t_wishbone_master_in;
    signal wb16_framerxtx_out : t_wishbone_master_out;
    signal wb_framerxtx_in  : t_wishbone_master_in;
    signal wb_framerxtx_out : t_wishbone_master_out;

    signal wb16_rf1_rfnco_in     : t_wishbone_master_in;
    signal wb16_rf1_rfnco_out    : t_wishbone_master_out;
    signal wb_rf1_rfnco_in       : t_wishbone_master_in;
    signal wb_rf1_rfnco_out      : t_wishbone_master_out;

    signal wb16_rf2_rfnco_in     : t_wishbone_master_in;
    signal wb16_rf2_rfnco_out    : t_wishbone_master_out;
    signal wb_rf2_rfnco_in       : t_wishbone_master_in;
    signal wb_rf2_rfnco_out      : t_wishbone_master_out;

    signal rf_trigger_ff_delay  : std_logic_vector(15 downto 0);

    signal rf1_dds_ftw_valid : std_logic_vector(15 downto 0);
    signal rf1_dds_ftw       : std_logic_vector(63 downto 0);
    signal rf2_dds_ftw_valid : std_logic_vector(15 downto 0);
    signal rf2_dds_ftw       : std_logic_vector(63 downto 0);

    signal wrc_page_0, wrc_page_1, wrc_page : std_logic_vector(31 downto 0);
    signal txframe_payload       :    t_RFmFramePayload;
    signal txframe_payload_r     :    t_RFmFramePayload;
    signal txframe_ftw_h1_main   :    std_logic_vector(63 downto 0);
    signal txframe_ftw_h1_prog   :    std_logic_vector(63 downto 0);
    signal txframe_ftw_h1_on     :    std_logic_vector(63 downto 0);
    signal txframe_dftw_h1_slip1 :    std_logic_vector(31 downto 0);
    signal txframe_dftw_h1_slip2 :    std_logic_vector(31 downto 0);
    signal txframe_setpoint1     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint2     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint3     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint4     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint5     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint6     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint7     :    std_logic_vector(31 downto 0);
    signal txframe_setpoint8     :    std_logic_vector(31 downto 0);
    signal txframe_noise         :    std_logic_vector(31 downto 0);
    signal txframe_control       :    std_logic_vector(15 downto 0);

    signal bmctrl_rfframe_ctrl_update : std_logic;
    signal bmctrl_rfframe_ctrl_wr : std_logic;

    signal reconfigure_wr  : std_logic;
    signal reconfigure_key : std_logic_vector(15 downto 0);

--    attribute keep_hierarchy of inst_wr2rf_regs : label is "yes";
    attribute shreg_extract  of inst_wr2rf_regs : label is "no";

begin

    inst_wr2rf_regs: entity work.wr2rf_vme_regs
      port map (
        rst_n_i          => rst_sys_n_i,
        clk_i            => clk_sys_i,
        wb_i             => wb_vme_i,
        wb_o             => wb_vme_o,

        init_hwinfo_serialNumber_i => (others => '0'),
        init_hwinfo_ident_jtagRemoteDisable_i => '1',
        init_hwinfo_ident_extendedID_i => "0000000",
        init_hwinfo_ident_cardID_i => x"56",
        init_hwinfo_firmwareVersion_i => x"0000_19_02",
        init_hwinfo_memMapVersion_i   => x"0000_19_00",
        init_hwinfo_echo_echo_o       => open,

        init_fw_update_i => wb_fw_update_in,
        init_fw_update_o => wb_fw_update_out,

        init_reconfigure_wr_o => reconfigure_wr,
        init_reconfigure_o    => reconfigure_key,

        init_clock_status_mmcm_locked_i => mmcm_locked_i,
        init_clock_ctrl_clk_sel_o       => clk_sel_o,
        init_clock_ctrl_mmcm_reset_o    => clk_sys_reset_o,

        init_wrcore_ctrl_reset_n_o      => wrcore_reset_n_o,
        init_iodelay_ctrl_reset_o       => iodelay_reset_o,

        init_mmcm_shift_incdec_o        => mmcm_shift_incdec_o,
        init_mmcm_shift_wr_o            => mmcm_shift_en_o,
        init_clock_status_shift_busy_i  => mmcm_shift_busy_i,

        init_tmg_io_term_o          => tmg_io_term_en_o,
        init_tmg_clk_term_o         => tmg_clk_term_en_o,
        init_tmg_clk_oe_o           => tmg_clk_oe_o,
        init_tmg_io_oe_o            => tmg_io_oe_o,
        init_lemo_rf1_t1_start_sel_o => rf1_t1_start_sel_o,
        init_lemo_rf1_t2_start_sel_o => rf1_t2_start_sel_o,
        init_lemo_rf2_t1_start_sel_o => rf2_t1_start_sel_o,
        init_lemo_rf2_t2_start_sel_o => rf2_t2_start_sel_o,
        init_lemo_rf1_t1_stop_sel_o  => rf1_t1_stop_sel_o,
        init_lemo_rf1_t2_stop_sel_o  => rf1_t2_stop_sel_o,
        init_lemo_rf2_t1_stop_sel_o  => rf2_t1_stop_sel_o,
        init_lemo_rf2_t2_stop_sel_o  => rf2_t2_stop_sel_o,
        init_tmgio1_osel_o  => tmgio1_osel_o,
        init_tmgio2_osel_o  => tmgio2_osel_o,
        init_tmgio3_osel_o  => tmgio3_osel_o,
        init_tmgio4_osel_o  => tmgio4_osel_o,
        init_tmgclk1_osel_o => tmgclk1_osel_o,
        init_tmgclk2_osel_o => tmgclk2_osel_o,

        init_lemo_gpio_o     => lemo_gpio_o,
        init_lemo_ext_sel_o  => lemo_ext_sel_o,
        init_lemo_pulse_ext_o => open,
        init_softstart_sel_o => softstart_sel_o,
        init_softstop_sel_o  => softstop_sel_o,

        init_pin_ctrl_ext_10m_dir_o => ext_10m_dir_o,
        init_pin_ctrl_ext_pps_dir_o => ext_pps_dir_o,

        init_dds_ctrl_reset_o        => dds_reset_o,
        init_dds_ctrl_ioupdate_o     => dds_ioupdate_o,
        init_dds_ctrl_profile_o      => dds_profile_o,
        init_dds_ioupdate_fdelay_o   => dds_ioupdate_fdelay_o,
        init_dds_ioupdate_odelay_o   => dds_ioupdate_odelay_o,
        init_dds_status_sync_error_i => dds_sync_error_i,

        init_ocxo_ctrl_enable_o      => ocxo_enabled_o,
        init_ocxo_uptime_val_i       => ocxo_uptime_i,

        init_wrc_page0_o     => wrc_page_0,
        init_wrc_page1_o     => wrc_page_1,

        init_pll_status_error_i  => pll_main_error_i,
        init_pll_status_locked_i => pll_main_locked_i,
        init_pll_ctrl_sync_o     => pll_main_sync_o,

        init_nco_azimuthal_value_o       => wr2rfsd_nco_azimuthal_o,
        init_nco_cabledelay_value_o      => wr2rfsd_nco_cabledelay_o,
        init_nco_hb_value_o              => wr2rfsd_nco_hb_o,
        init_nco_h1_ftw_value_o          => loc_nco_h1_ftw_o,
        init_nco_h1_prog_value_o         => loc_nco_h1_prog_o,
        init_nco_ctrl_reset_nco_o        => loc_nco_ctrl_reset_o,
        init_nco_ctrl_reset_slip_o       => open,
        init_nco_ctrl_reset_fsk_o        => open,
        init_nco_ctrl_rate_o             => open,
        init_nco_update_valid_o          => loc_nco_update_valid_o,
        init_nco_loc_or_wrs_params_sel_o => loc_or_wrs_params_sel_o,

        init_svec_mup_ctrl_gpio_sel_o       => svec_mup_gpio_sel_o,
        init_svec_mup_ctrl_led_sel_o        => svec_mup_led_sel_o,
        init_svec_mup_ctrl_bclk_rfclk_sel_o => svec_mup_bclk_rfclk_sel_o,
        init_svec_mup_ctrl_ila_sel_o        => svec_mup_ila_sel_o,

        init_svec_mup_rftrig_t1stop_o  => svec_mup_rftrig_t1stop_o,
        init_svec_mup_rftrig_t1start_o => svec_mup_rftrig_t1start_o,
        init_svec_mup_rftrig_t2stop_o  => svec_mup_rftrig_t2stop_o,
        init_svec_mup_rftrig_t2start_o => svec_mup_rftrig_t2start_o,

        init_svec_mup_fmc1_term_o => svec_mup_fmc1_term_o,
        init_svec_mup_fmc1_oe_n_o => svec_mup_fmc1_oe_n_o,
        init_svec_mup_fmc1_led_o  => svec_mup_fmc1_led_o,
        init_svec_mup_fmc2_term_o => svec_mup_fmc2_term_o,
        init_svec_mup_fmc2_oe_n_o => svec_mup_fmc2_oe_n_o,
        init_svec_mup_fmc2_led_o  => svec_mup_fmc2_led_o,

        init_wrc_tai_value_i         => tm_tai_i,
        init_wrc_cycles_value_i      => tm_cycles_i,
        init_wrc_status_linkup_i     => tm_linkup_i,
        init_wrc_status_time_valid_i => tm_time_valid_i,

        init_wrs_rxframe_ftw_value_i => wrs_frame_last_ftw_i,
        init_wrs_rxframe_ctrl_i      => wrs_frame_last_ctrl_i,
        init_wrs_rxframe_rxwrtimestamp_i => wrs_frame_last_rxwrtimestamp_i,
        init_wrs_rxframe_txwrtimestamp_i => wrs_frame_last_txwrtimestamp_i,
        init_wrs_rxframe_rftimestamp_i => wrs_frame_last_rftimestamp_i,
        init_wrs_rxframe_counter_i   => wrs_frame_counter_i,
        init_wrs_rxframe_rfframe_ts_update_o    => rfframe_ts_update_o,
        init_wrs_rxframe_nco_reset_tai_val_i    => rfframe_nco_reset_tai_i, 
        init_wrs_rxframe_nco_reset_cycles_val_i => rfframe_nco_reset_cycles_i,
        init_wrs_rxframe_tai_val_i              => rfframe_tai_i,
        init_wrs_rxframe_cycles_val_i           => rfframe_cycles_i,
        
        init_txframe_ftw_h1_main_o   => txframe_ftw_h1_main,
        init_txframe_ftw_h1_prog_o   => txframe_ftw_h1_prog,
        init_txframe_ftw_h1_on_o     => txframe_ftw_h1_on,
        init_txframe_dftw_h1_slip1_o => txframe_dftw_h1_slip1,
        init_txframe_dftw_h1_slip2_o => txframe_dftw_h1_slip2,
        init_txframe_setpoint1_o     => txframe_setpoint1,
        init_txframe_setpoint2_o     => txframe_setpoint2,
        init_txframe_setpoint3_o     => txframe_setpoint3,
        init_txframe_setpoint4_o     => txframe_setpoint4,
        init_txframe_setpoint5_o     => txframe_setpoint5,
        init_txframe_setpoint6_o     => txframe_setpoint6,
        init_txframe_setpoint7_o     => txframe_setpoint7,
        init_txframe_setpoint8_o     => txframe_setpoint8,
        init_txframe_noise_o         => txframe_noise,
        init_txframe_control_o       => txframe_control,

        init_pll_spi_i => wb_pll_spi_in,
        init_pll_spi_o => wb_pll_spi_out,

        init_rf_spi_i => wb_rf_spi_in,
        init_rf_spi_o => wb_rf_spi_out,

        init_rf_i => wb_rf_in,
        init_rf_o => wb_rf_out,

        init_framerxtx_i => wb16_framerxtx_in,
        init_framerxtx_o => wb16_framerxtx_out,

        init_xadc_i => xadc_wb_i,
        init_xadc_o => xadc_wb_o,

        init_bmctrl_rfframe_ctrl_update_i => '0',
        init_bmctrl_rfframe_status_fifo_rdy_i => bmctrl_rfframe_status_fifo_rdy_i,
        init_bmctrl_rfframe_ctrl_reset_o => bmctrl_rfframe_ctrl_reset_o,
        init_bmctrl_rfframe_ctrl_en_o => bmctrl_rfframe_ctrl_en_o,
        init_bmctrl_rfframe_ctrl_update_o => bmctrl_rfframe_ctrl_update,
        init_bmctrl_rfframe_ctrl_wr_o => bmctrl_rfframe_ctrl_wr,

        init_wrpc_i => wb16_wrpc_in,
        init_wrpc_o => wb16_wrpc_out,

        ctrl_rf1_vtus_i  => wb_rf1_vtus_i,
        ctrl_rf1_vtus_o  => wb_rf1_vtus_o,
        ctrl_rf2_vtus_i  => wb_rf2_vtus_i,
        ctrl_rf2_vtus_o  => wb_rf2_vtus_o,
        ctrl_rf1_rfnco_i => wb16_rf1_rfnco_in,
        ctrl_rf1_rfnco_o => wb16_rf1_rfnco_out,
        ctrl_rf2_rfnco_i => wb16_rf2_rfnco_in,
        ctrl_rf2_rfnco_o => wb16_rf2_rfnco_out,

        ctrl_rf1_iqdac_phase_update_valid_o => rf1_iqdac_phase_update_o,
        ctrl_rf2_iqdac_phase_update_valid_o => rf2_iqdac_phase_update_o,
        ctrl_rf1_iqdac_igain_arm_o          => rf1_iqdac_igain_arm_o,
        ctrl_rf1_iqdac_qgain_arm_o          => rf1_iqdac_qgain_arm_o,
        ctrl_rf2_iqdac_igain_arm_o          => rf2_iqdac_igain_arm_o,
        ctrl_rf2_iqdac_qgain_arm_o          => rf2_iqdac_qgain_arm_o,
        ctrl_rf1_iqdac_igain_i => rf1_iqdac_igain_i,
        ctrl_rf1_iqdac_qgain_i => rf1_iqdac_qgain_i,
        ctrl_rf2_iqdac_igain_i => rf2_iqdac_igain_i,
        ctrl_rf2_iqdac_qgain_i => rf2_iqdac_qgain_i,
        ctrl_rf1_iqdac_ctrl_o  => rf1_iqdac_ctrl_o,
        ctrl_rf2_iqdac_ctrl_o  => rf2_iqdac_ctrl_o,

        ctrl_rf1_iqdac_phase_o => open,
        ctrl_rf2_iqdac_phase_o => open,

        ctrl_iqdac_ram_addr_o  => iqdac_ram_addr_o,
        ctrl_iqdac_ram_data_o  => iqdac_ram_data_o,
        ctrl_iqdac_ram_write_o => iqdac_ram_write_o,
        ctrl_iqdac_ram_play_o  => iqdac_ram_play_o,

        ctrl_rf1_dds_ftw_valid_o => rf1_dds_ftw_valid,
        ctrl_rf1_dds_ftw_o       => rf1_dds_ftw,
        ctrl_rf2_dds_ftw_valid_o => rf2_dds_ftw_valid,
        ctrl_rf2_dds_ftw_o       => rf2_dds_ftw,

        ctrl_nco_reset_ctrl_mask_dds_o       => nco_reset_dds_mask_o,
        ctrl_nco_reset_ctrl_mask_rfnco_ch1_o => nco_reset_rfnco_ch1_mask_o,
        ctrl_nco_reset_ctrl_mask_rfnco_ch2_o => nco_reset_rfnco_ch2_mask_o,
        ctrl_nco_reset_ctrl_mask_rf1_trig1_o => nco_reset_rf1_trig1_mask_o,
        ctrl_nco_reset_ctrl_mask_rf2_trig1_o => nco_reset_rf2_trig1_mask_o,
        ctrl_nco_reset_ctrl_soft_o           => nco_reset_soft_o,
        
        ctrl_gbl_status_rf1_t1_start_i => rf1_t1_vtu_start_p_i,
        ctrl_gbl_status_rf1_t2_start_i => rf1_t2_vtu_start_p_i,
        ctrl_gbl_status_rf2_t1_start_i => rf2_t1_vtu_start_p_i,
        ctrl_gbl_status_rf2_t2_start_i => rf2_t2_vtu_start_p_i
        );

    rf1_dds_ftw_valid_o <= rf1_dds_ftw_valid(0);
    rf1_dds_ftw_o       <= rf1_dds_ftw(47 downto 0);
    rf2_dds_ftw_valid_o <= rf2_dds_ftw_valid(0);
    rf2_dds_ftw_o       <= rf2_dds_ftw(47 downto 0);

    txframe_payload <= (
      FTW_H1_main  => txframe_ftw_h1_main(47 downto 0),
      FTW_H1_prog  => txframe_ftw_h1_prog(47 downto 0),
      FTW_H1_on    => txframe_ftw_h1_on(47 downto 0),
      dFTW_H1_slip1  => txframe_dftw_h1_slip1,
      dFTW_H1_slip2  => txframe_dftw_h1_slip2,
      setpoint1  => txframe_setpoint1,
      setpoint2  => txframe_setpoint2,
      setpoint3  => txframe_setpoint3,
      setpoint4  => txframe_setpoint4,
      setpoint5  => txframe_setpoint5,
      setpoint6  => txframe_setpoint6,
      setpoint7  => txframe_setpoint7,
      setpoint8  => txframe_setpoint8,
      noise      => txframe_noise,
      control    => txframe_control );

    process (clk_sys_i) is
    begin
       if rising_edge(clk_sys_i) then
          txframe_payload_r <= txframe_payload;
       end if;
    end process;

    txframe_payload_o <= txframe_payload_r;

    --  Update is a pulse.
    bmctrl_rfframe_ctrl_update_o <= bmctrl_rfframe_ctrl_update and bmctrl_rfframe_ctrl_wr;


    inst_rf_spi: entity work.xwb_spi16
      generic map (
        g_interface_mode => CLASSIC,
        g_divider_len    => 8,
        g_max_char_len   => 128,
        g_num_slaves     => 3
      )
      port map (
        clk_sys_i        => clk_sys_i,
        rst_n_i          => rst_sys_n_i,
        slave_i          => wb_rf_spi_out,
        slave_o          => wb_rf_spi_in,
        int_o            => open,  --  TODO: interrupt
        pad_cs_o (0)     => dds_cs_n_o,
        pad_cs_o (1)     => rf1_iqdac_cs_n_o,
        pad_cs_o (2)     => rf2_iqdac_cs_n_o,
        pad_sclk_o       => rf_sclk_o,
        pad_mosi_o       => rf_sdi_o,
        pad_miso_i       => rf_sdo_i
      );

    inst_pll_spi: entity work.xwb_spi16
      generic map (
        g_interface_mode => CLASSIC,
        g_divider_len    => 8,
        g_max_char_len   => 16,
        g_num_slaves     => 1
      )
      port map (
        clk_sys_i        => clk_sys_i,
        rst_n_i          => rst_sys_n_i,
        slave_i          => wb_pll_spi_out,
        slave_o          => wb_pll_spi_in,
        int_o            => open,  --  TODO: interrupt
        pad_cs_o (0)     => pll_main_cs_n_o,
        pad_sclk_o       => pll_main_sclk_o,
        pad_mosi_o       => pll_main_sdi_o,
        pad_miso_i       => pll_main_sdo_i
      );

     my_inst: entity work.wr2rf_init_rf_regs
      port map (
        clk_i                      => clk_sys_i,
        rst_n_i                    => rst_sys_n_i,
        wb_i                       => wb_rf_out,
        wb_o                       => wb_rf_in,
        rf_trigger_ff_delay_o      => rf_trigger_ff_delay,
        rf1_common_mixer_en_o      => rf1_mixer_en_o,
        rf1_common_mux_sel_o       => rf1_mux_sel_o,
        rf1_common_iqdac_reset_o   => rf1_iqdac_reset_o,
        rf1_common_start_lpbk_o    => rf1_start_lpbk_o,
        rf1_rst_cdelay_offset_o    => rf1_rst_cdelay_offset_o,
        rf1_t1_sync_progdelay_cdelay_o => rf1_t1_sync_cdelay_o,
        rf1_t1_sync_progdelay_fdelay_o => rf1_t1_sync_fdelay_o,
        rf1_t1_sync_progdelay_odelay_o => rf1_t1_sync_odelay_o,
        rf1_ch_0_csr_delay_oen_o   => rf1_t1_delay_oen_o,
        rf1_ch_0_csr_mux_sel_o     => rf1_t1_mux_sel_o,
        rf1_ch_0_csr_trig_rst_o    => rf1_t1_rst_o,
        rf1_ch_0_csr_delay_latch_o => rf1_t1_delay_latch_o,
        rf1_ch_1_csr_delay_oen_o   => rf1_t2_delay_oen_o,
        rf1_ch_1_csr_mux_sel_o     => rf1_t2_mux_sel_o,
        rf1_ch_1_csr_trig_rst_o    => rf1_t2_rst_o,
        rf1_ch_1_csr_delay_latch_o => rf1_t2_delay_latch_o,
        rf2_common_mixer_en_o      => rf2_mixer_en_o,
        rf2_common_mux_sel_o       => rf2_mux_sel_o,
        rf2_common_iqdac_reset_o   => rf2_iqdac_reset_o,
        rf2_common_start_lpbk_o    => rf2_start_lpbk_o,
        rf2_rst_cdelay_offset_o    => rf2_rst_cdelay_offset_o,
        rf2_t1_sync_progdelay_cdelay_o => rf2_t1_sync_cdelay_o,
        rf2_t1_sync_progdelay_fdelay_o => rf2_t1_sync_fdelay_o,
        rf2_t1_sync_progdelay_odelay_o => rf2_t1_sync_odelay_o,
        rf2_ch_0_csr_delay_oen_o   => rf2_t1_delay_oen_o,
        rf2_ch_0_csr_mux_sel_o     => rf2_t1_mux_sel_o,
        rf2_ch_0_csr_trig_rst_o    => rf2_t1_rst_o,
        rf2_ch_0_csr_delay_latch_o => rf2_t1_delay_latch_o,
        rf2_ch_1_csr_delay_oen_o   => rf2_t2_delay_oen_o,
        rf2_ch_1_csr_mux_sel_o     => rf2_t2_mux_sel_o,
        rf2_ch_1_csr_trig_rst_o    => rf2_t2_rst_o,
        rf2_ch_1_csr_delay_latch_o => rf2_t2_delay_latch_o );

    rf_trig_ff_delay_o <= rf_trigger_ff_delay(9 downto 0);
    --process(clk_sys_i)
    --begin
    --  if rising_edge(clk_sys_i) then
    --    if rf1_t1_delay_wr    = '1' then
    --      rf_delay_o <= rf1_t1_delay_data(9 downto 0);
    --    elsif rf1_t2_delay_wr = '1' then
    --      rf_delay_o <= rf1_t2_delay_data(9 downto 0);
    --    elsif rf1_t2_delay_wr = '1' then
    --      rf_delay_o <= rf2_t1_delay_data(9 downto 0);
    --    elsif rf1_t2_delay_wr = '1' then
    --      rf_delay_o <= rf2_t2_delay_data(9 downto 0);
    --    else
    --      rf_delay_o <= (others => '0');
    --    end if;
    --    rf1_t1_delay_latch_o <= rf1_t1_delay_wr;
    --    rf1_t2_delay_latch_o <= rf1_t2_delay_wr;
    --    rf2_t1_delay_latch_o <= rf2_t1_delay_wr;
    --    rf2_t2_delay_latch_o <= rf2_t2_delay_wr;
    --  end if;
    --end process;

    inst_wrc_wb16x32: entity work.wb16_to_wb32
      port map (
        clk_i   => clk_sys_i,
        rst_n_i => rst_sys_n_i,
        wb16_i  => wb16_wrpc_out,
        wb16_o  => wb16_wrpc_in,
        wb32_i  => wb_wrc_i,
        wb32_o  => wb_wrc_out );

    wrc_page <= wrc_page_0 when wb_wrc_out.adr(12) = '0' else wrc_page_1;

    --  Remap the wrc address to target only peripherals.
    wb_wrc_o <= (cyc => wb_wrc_out.cyc,
                 stb => wb_wrc_out.stb,
                 adr => (wb_wrc_out.adr and x"0000_0fff") or (wrc_page and x"ffff_f000"),
                 sel => wb_wrc_out.sel,
                 we  => wb_wrc_out.we,
                 dat => wb_wrc_out.dat);

    g_not_svec_mockup : if (g_svec_mockup = false) generate

       inst_wb_fw_update: entity work.xwb_xc7_fw_update_v2
          port map (
             clk_i        => clk_sys_i,
             rst_n_i      => rst_sys_n_i,
             wb_i         => wb_fw_update_out,
             wb_o         => wb_fw_update_in,
             flash_cs_n_o => flash_cs_n_o,
             flash_mosi_o => flash_mosi_o,
             flash_miso_i => flash_miso_i,
             flash_sck_o  => flash_sck_o );

    end generate;

   --  RF Frame
   inst_framerxtx_wb16x32: entity work.wb16_to_wb32
      port map (
        clk_i   => clk_sys_i,
        rst_n_i => rst_sys_n_i,
        wb16_i  => wb16_framerxtx_out,
        wb16_o  => wb16_framerxtx_in,
        wb32_i  => wb_framerxtx_in,
        wb32_o  => wb_framerxtx_out );

   inst_framerxtx_cross: entity work.xwb_clock_bridge
      generic map (
         g_SLAVE_PORT_WB_MODE  => CLASSIC,
         g_MASTER_PORT_WB_MODE => CLASSIC,
         g_SIZE                => 2)
      port map (
         slave_clk_i    => clk_sys_i,
         slave_rst_n_i  => rst_sys_n_i,
         slave_i        => wb_framerxtx_out,
         slave_o        => wb_framerxtx_in,
         master_clk_i   => clk_ref_i,
         master_rst_n_i => rst_ref_n_i,
         master_i       => wb_rfframerxtx_i,
         master_o       => wb_rfframerxtx_o );

   inst_rf1_rfnco_wb16x32: entity work.wb16_to_wb32
      port map (
        clk_i   => clk_sys_i,
        rst_n_i => rst_sys_n_i,
        wb16_i  => wb16_rf1_rfnco_out,
        wb16_o  => wb16_rf1_rfnco_in,
        wb32_i  => wb_rf1_rfnco_in,
        wb32_o  => wb_rf1_rfnco_out );

    inst_rf1_rfnco_cross: entity work.xwb_clock_bridge
       generic map (
          g_SLAVE_PORT_WB_MODE  => CLASSIC,
          g_MASTER_PORT_WB_MODE => CLASSIC,
          g_SIZE                => 2)
       port map (
          slave_clk_i    => clk_sys_i,
          slave_rst_n_i  => rst_sys_n_i,
          slave_i        => wb_rf1_rfnco_out,
          slave_o        => wb_rf1_rfnco_in,
          master_clk_i   => clk125_i,
          master_rst_n_i => rst_clk125_n_i,
          master_i       => wb_rf1_rfnco_i,
          master_o       => wb_rf1_rfnco_o );

   inst_rf2_rfnco_wb16x32: entity work.wb16_to_wb32
      port map (
        clk_i   => clk_sys_i,
        rst_n_i => rst_sys_n_i,
        wb16_i  => wb16_rf2_rfnco_out,
        wb16_o  => wb16_rf2_rfnco_in,
        wb32_i  => wb_rf2_rfnco_in,
        wb32_o  => wb_rf2_rfnco_out );

    inst_rf2_rfnco_cross: entity work.xwb_clock_bridge
       generic map (
          g_SLAVE_PORT_WB_MODE  => CLASSIC,
          g_MASTER_PORT_WB_MODE => CLASSIC,
          g_SIZE                => 2)
       port map (
          slave_clk_i    => clk_sys_i,
          slave_rst_n_i  => rst_sys_n_i,
          slave_i        => wb_rf2_rfnco_out,
          slave_o        => wb_rf2_rfnco_in,
          master_clk_i   => clk125_i,
          master_rst_n_i => rst_clk125_n_i,
          master_i       => wb_rf2_rfnco_i,
          master_o       => wb_rf2_rfnco_o );

    process (clk_sys_i) is
    begin
      if rising_edge(clk_sys_i) then
        if reconfigure_wr = '1' and reconfigure_key = x"a37c" then
          reconfigure_o <= '1';
        else
          reconfigure_o <= '0';
        end if;
      end if;
    end process;

    -- dbg
    ila_sigs_o(0) <= wb16_rf1_rfnco_out.stb;
    ila_sigs_o(1) <= wb16_rf1_rfnco_out.we;
    ila_sigs_o(2) <= wb16_rf1_rfnco_in.ack;
    ila_sigs_o(3) <= '0';
    ila_sigs_o(4) <= wb_rf1_rfnco_out.stb;
    ila_sigs_o(5) <= wb_rf1_rfnco_out.we;
    ila_sigs_o(6) <= wb_rf1_rfnco_in.ack;
    ila_sigs_o(7) <= '0';

end arch;
