// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2020-2023 Analog Devices, Inc. All rights reserved.
//
// In this HDL repository, there are many different and unique modules, consisting
// of various HDL (Verilog or VHDL) components. The individual modules are
// developed independently, and may be accompanied by separate and unique license
// terms.
//
// The user should read each of these license terms, and understand the
// freedoms and responsibilities that he or she has by using this source/core.
//
// This core 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.
//
// Redistribution and use of source or resulting binaries, with or without modification
// of this file, are permitted under one of the following two license terms:
//
//   1. The GNU General Public License version 2 as published by the
//      Free Software Foundation, which can be found in the top level directory
//      of this repository (LICENSE_GPL2), and also online at:
//      <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
//
// OR
//
//   2. An ADI specific BSD license, which can be found in the top level directory
//      of this repository (LICENSE_ADIBSD), and also on-line at:
//      https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD
//      This will allow to generate bit files and not release the source code,
//      as long as it attaches to an ADI device.
//
// ***************************************************************************
// ***************************************************************************

`timescale 1ns/100ps

module system_top  #(
  parameter FPGA_REVISION_DATE = 32'h07152025, 
  parameter MINOR_REV = 8'h01,
  parameter TX_JESD_L = 8,
  parameter TX_NUM_LINKS = 1,
  parameter RX_JESD_L = 8,
  parameter RX_NUM_LINKS = 1,
  parameter SHARED_DEVCLK = 0,
  parameter JESD_MODE = "8B10B"
) (
//  input  [12:0] gpio_bd_i,
//  output [ 7:0] gpio_bd_o,
  input                               QSFP1_INTL_LS,
  input                               QSFP1_MODPRSL_LS,
  output                              QSFP1_RESETL_LS,
  input                               QSFP1_RX1_N,
  input                               QSFP1_RX1_P,
  input                               QSFP1_RX2_N,
  input                               QSFP1_RX2_P,
  input                               QSFP1_RX3_N,
  input                               QSFP1_RX3_P,
  input                               QSFP1_RX4_N,
  input                               QSFP1_RX4_P,
  input                               QSFP1_SI570_CLOCK_N,  //CLK2_N  
  input                               QSFP1_SI570_CLOCK_P,
  output                              QSFP1_TX1_N,
  output                              QSFP1_TX1_P,
  output                              QSFP1_TX2_N,
  output                              QSFP1_TX2_P,
  output                              QSFP1_TX3_N,
  output                              QSFP1_TX3_P,
  output                              QSFP1_TX4_N,
  output                              QSFP1_TX4_P,
  input                               QSFP4_INTL_LS,
  input                               QSFP4_MODPRSL_LS,
  output                              QSFP4_RESETL_LS,
  input                               QSFP4_RX1_N,
  input                               QSFP4_RX1_P,
  input                               QSFP4_RX2_N,
  input                               QSFP4_RX2_P,
  input                               QSFP4_RX3_N,
  input                               QSFP4_RX3_P,
  input                               QSFP4_RX4_N,
  input                               QSFP4_RX4_P,
  input                               QSFP4_SI570_CLOCK_N,//CLK0_N  
  input                               QSFP4_SI570_CLOCK_P,
  output                              QSFP4_TX1_N,
  output                              QSFP4_TX1_P,
  output                              QSFP4_TX2_N,
  output                              QSFP4_TX2_P,
  output                              QSFP4_TX3_N,
  output                              QSFP4_TX3_P,
  output                              QSFP4_TX4_N,
  output                              QSFP4_TX4_P,

  input                               QSFP2_SI570_CLOCK_N,//CLK3_N  
  input                               QSFP2_SI570_CLOCK_P,
  
  input                               QSFP3_SI570_CLOCK_N,//CLK1_N  
  input                               QSFP3_SI570_CLOCK_P,


  inout                               pll_scl,
  inout                               pll_sda,

  // FMC HPC IOs
  input  [1:0]                        agc0,   
  input  [1:0]                        agc1,   
  input  [1:0]                        agc2,   
  input  [1:0]                        agc3,   
  input                               clkin6_n,
  input                               clkin6_p,  
  input                               clkin10_n,
  input                               clkin10_p, 
  input                               clkin8_n,
  input                               clkin8_p, 
  input                               fpga_refclk_in_n,
  input                               fpga_refclk_in_p,   
  input  [RX_JESD_L*RX_NUM_LINKS-1:0] rx_data_n,
  input  [RX_JESD_L*RX_NUM_LINKS-1:0] rx_data_p,    
  output [TX_JESD_L*TX_NUM_LINKS-1:0] tx_data_n,
  output [TX_JESD_L*TX_NUM_LINKS-1:0] tx_data_p,    
  input                               fpga_syncin_0_n,
  input                               fpga_syncin_0_p,    
  inout                               fpga_syncin_1_n,
  inout                               fpga_syncin_1_p,    
  output                              fpga_syncout_0_n,
  output                              fpga_syncout_0_p,   
  inout                               fpga_syncout_1_n,
  inout                               fpga_syncout_1_p,   
  inout  [10:0]                       gpio,
  inout                               hmc_gpio1, 
  output                              hmc_sync,  
  input  [1:0]                        irqb,      
  output                              rstb,      
  output [1:0]                        rxen,      
  output                              spi0_csb,  
  input                               spi0_miso, 
  output                              spi0_mosi, 
  output                              spi0_sclk, 
  output                              spi1_csb,  
  output                              spi1_sclk, 
  inout                               spi1_sdio, 
  input                               sysref2_n, 
  input                               sysref2_p, 
  output [1:0]                        txen       
);

  // internal signals

  wire    [94:0]  gpio_i;
  wire    [94:0]  gpio_o;
  wire    [94:0]  gpio_t;
  wire    [ 2:0]  spi0_csn;

  wire    [ 2:0]  spi1_csn;
  wire            spi1_mosi;
  wire            spi1_miso;

  wire            ref_clk;
  wire            ref_clk_div2;
  wire            ref_clk_div2_bufg;
  wire            sysref;
  wire    [TX_NUM_LINKS-1:0]   tx_syncin;
  wire    [RX_NUM_LINKS-1:0]   rx_syncout;

  wire    [7:0]   rx_data_p_loc;
  wire    [7:0]   rx_data_n_loc;
  wire    [7:0]   tx_data_p_loc;
  wire    [7:0]   tx_data_n_loc;

  wire            clkin6;
  wire            clkin10;
  wire            clkin8;
  wire            clkin8_bufg;
  wire            tx_device_clk;
  wire            rx_device_clk_internal;
  wire            rx_device_clk;
  
  wire            clk_125;
  wire            clk_125_aresetn;

  wire            clk_250;
  wire            clk_250_aresetn;

  wire            vio_enable;
  wire            vio_rstb;
  wire            rstb_i;
//// 
  wire            rx_device_clk_1;
  wire            rx_device_clk_aresetn;

  wire   [255:0]  adc_rx_tdata_256b;
  wire            adc_rx_tvalid_256b;
  wire            adc_rx_tdata_256b_overflow;
  wire            adc_rx_fifo_tready_256b;
  wire  [31:0]    adc_rx_tvalid_256b_cnt;  
  
////
  wire            tx_device_clk_1;
  wire            tx_device_clk_aresetn;    

  wire  [255:0]   mem_xfer_tx_upload_tdata_256b; 
  wire            mem_xfer_tx_upload_tvalid_256b;
  wire            mem_xfer_tx_upload_tready_256b;
  reg   [31:0]    mem_xfer_tx_upload_tvalid_256b_cnt_r = 32'h0;

  wire  [255:0]   dac_tx_tdata_256b;
  wire            dac_tx_tvalid_256b;
  wire            dac_tx_tready_256b;

  wire   [255:0]  dac_tx_tdata_256b_pipe;
  wire            dac_tx_tvalid_256b_pipe;
  wire            dac_tx_tready_256b_pipe;

  reg   [31:0]    dac_tx_tvalid_256b_cnt_r = 32'h0; 

////   
  wire            qsfp1_capture_aclk;        
  wire            qsfp1_capture_aresetn;
  wire  [239:0]   qsfp1_capture_tdata_240b;
  wire            qsfp1_capture_tvalid_240b;

  wire  [31:0]    qsfp1_capture_tvalid_240b_cnt;
  wire  [31:0]    qsfp1_capture_fifo_aempty_512b_cnt;

  wire  [255:0]   tx_tdata_256b;                
  wire            tx_tvalid_256b;               
  wire            tx_tready_256b;                

  wire  [31:0]    tx_tvalid_256b_cnt;

  wire            qsfp1_capture_rx_data_ready; 
  wire  [31:0]    qsfp1_capture_rx_data_ready_cnt;

  wire  [31:0]    qsfp1_capture_overflow_240b_cnt;
////
  wire            qsfp4_playback_aclk; 
  wire            qsfp4_playback_aresetn; 
  wire  [239:0]   qsfp4_playback_tdata_240b; 
  wire            qsfp4_playback_tvalid_240b; 
  wire            qsfp4_playback_tready_240b;

  wire  [31:0]    qsfp4_playback_tvalid_256b_cnt;
  wire  [31:0]    qsfp4_playback_tvalid_240b_cnt;

  wire  [255:0]   dds_intfc_tdata_256b = 256'h0;                
  wire            dds_intfc_tvalid_256b = 1'b0;               
  wire            dds_intfc_tready_256b;                

  wire  [31:0]    slv_reg9;
  wire  [31:0]    slv_reg10;

  wire  [31:0]    slv_reg21;
  wire  [31:0]    slv_reg22;
  wire  [31:0]    slv_reg23;
  wire  [31:0]    slv_reg24;
  wire  [31:0]    slv_reg25;
  wire  [31:0]    slv_reg26;
  wire  [31:0]    slv_reg27;
  wire  [31:0]    slv_reg28;
  wire  [31:0]    slv_reg29;
  wire  [31:0]    slv_reg30;

  wire  [31:0]    slv_reg31;
  wire  [31:0]    slv_reg32;
  wire  [31:0]    slv_reg33;
  wire  [31:0]    slv_reg34;
  wire  [31:0]    slv_reg35;
  wire  [31:0]    slv_reg36;
  wire  [31:0]    slv_reg37;
  wire  [31:0]    slv_reg38;
  wire  [31:0]    slv_reg39;
  wire  [31:0]    slv_reg40;

  wire  [31:0]    slv_reg41;
  wire  [31:0]    slv_reg42;
  wire  [31:0]    slv_reg43;
  wire  [31:0]    slv_reg44;
  wire  [31:0]    slv_reg45;
  wire  [31:0]    slv_reg46;
  wire  [31:0]    slv_reg47;
  wire  [31:0]    slv_reg48;
  wire  [31:0]    slv_reg49;
  wire  [31:0]    slv_reg50;

  wire  [31:0]    slv_reg51;
  wire  [31:0]    slv_reg52;

  wire  [1:0]     dac_src_data_sel;
  wire  [1:0]     vio_dac_src_data_sel;
  wire  [1:0]     dac_src_data_sel_i;

  
  
  wire            chan1to4_mode_sel;
  wire            qsfp4_playback_path_data_enable_n;
  wire            vio_qsfp4_playback_path_data_enable_n;
  wire            qsfp4_playback_path_data_enable_n_i;

  wire            qsfp2_clk;
  wire            qsfp2_clk_bufg;
  
  wire            qsfp3_clk;
  wire            qsfp3_clk_bufg;
  
  wire            clk_100;
  wire            clk_100_aresetn;
  wire   [31:0]   M11_AXI_0_araddr;
  wire   [2:0]    M11_AXI_0_arprot;
  wire            M11_AXI_0_arready;
  wire            M11_AXI_0_arvalid;
  wire   [31:0]   M11_AXI_0_awaddr;
  wire   [2:0]    M11_AXI_0_awprot;
  wire            M11_AXI_0_awready;
  wire            M11_AXI_0_awvalid;
  wire            M11_AXI_0_bready;
  wire   [1:0]    M11_AXI_0_bresp;
  wire            M11_AXI_0_bvalid;
  wire   [31:0]   M11_AXI_0_rdata;
  wire            M11_AXI_0_rready;
  wire   [1:0]    M11_AXI_0_rresp;
  wire            M11_AXI_0_rvalid;
  wire   [31:0]   M11_AXI_0_wdata;
  wire            M11_AXI_0_wready;
  wire   [3:0]    M11_AXI_0_wstrb;
  wire            M11_AXI_0_wvalid;


  wire            sda_i;
  wire            sda_o;
  wire            sda_t;

  wire            scl_i;
  wire            scl_o;
  wire            scl_t;

  wire            dac_tx_tready_en;
  wire            vio_man_tx_tready;

////////////////////////////////////////////////////////////////

  // instantiations

  IBUFDS_GTE4 i_ibufds_ref_clk (
    .CEB                                  (1'd0),
    .I                                    (fpga_refclk_in_p),
    .IB                                   (fpga_refclk_in_n),
    .O                                    (ref_clk),
    .ODIV2                                (ref_clk_div2)
    );

  BUFG_GT i_bufgt_ref_clk (
    .I                                    (ref_clk_div2),
    .CE                                   (1'b1),
    .CEMASK                               (1'b0),
    .CLR                                  (1'b0),
    .CLRMASK                              (1'b0),
    .DIV                                  (3'b000),
    .O                                    (ref_clk_div2_bufg)
    );
    
////
  IBUFDS i_ibufds_sysref (
    .I                                    (sysref2_p),
    .IB                                   (sysref2_n),
    .O                                    (sysref)
    );
    
/////
  IBUFDS i_ibufds_clkin6 (
    .I                                    (clkin6_p),
    .IB                                   (clkin6_n),
    .O                                    (clkin6)
    );

  BUFG i_bufg_tx_device_clk (
    .I                                    (clkin6),
    .O                                    (tx_device_clk)
    );
    
////    
  IBUFDS i_ibufds_clkin10 (
    .I                                    (clkin10_p),
    .IB                                   (clkin10_n),
    .O                                    (clkin10)
    );
    
  BUFG i_bufg_rx_device_clk (
    .I                                    (clkin10),
    .O                                    (rx_device_clk)
    );
    
/////
  IBUFDS_GTE4 i_ibufds_clkin8 (
    .I                                    (clkin8_p),
    .IB                                   (clkin8_n),
    .CEB                                  (1'b0),
    .O                                    (),
    .ODIV2                                (clkin8)
    );

  BUFG_GT i_bufgt_clkin8 (
    .I                                    (clkin8),
    .CE                                   (1'b1),
    .CEMASK                               (1'b0),
    .CLR                                  (1'b0),
    .CLRMASK                              (1'b0),
    .DIV                                  (3'b000),
    .O                                    (clkin8_bufg)
    );
    
///    
  IBUFDS i_ibufds_syncin_0 (
    .I                                    (fpga_syncin_0_p),
    .IB                                   (fpga_syncin_0_n),
    .O                                    (tx_syncin[0])
    );

  OBUFDS i_obufds_syncout_0 (
    .I                                    (rx_syncout[0]),
    .O                                    (fpga_syncout_0_p),
    .OB                                   (fpga_syncout_0_n)
    );

//////////
  IBUFDS_GTE4 i_ibufds_qsfp2 (
    .I                                    (QSFP2_SI570_CLOCK_P),
    .IB                                   (QSFP2_SI570_CLOCK_N),
    .CEB                                  (1'b0),
    .O                                    (),
    .ODIV2                                (qsfp2_clk)
    );

  BUFG_GT i_bufgt_qsfp2 (
    .I                                    (qsfp2_clk),
    .CE                                   (1'b1),
    .CEMASK                               (1'b0),
    .CLR                                  (1'b0),
    .CLRMASK                              (1'b0),
    .DIV                                  (3'b000),
    .O                                    (qsfp2_clk_bufg)
    );

//////////
  IBUFDS_GTE4 i_ibufds_qsfp3 (
    .I                                    (QSFP3_SI570_CLOCK_P),
    .IB                                   (QSFP3_SI570_CLOCK_N),
    .CEB                                  (1'b0),
    .O                                    (),
    .ODIV2                                (qsfp3_clk)
    );

  BUFG_GT i_bufgt_qsfp3 (
    .I                                    (qsfp3_clk),
    .CE                                   (1'b1),
    .CEMASK                               (1'b0),
    .CLR                                  (1'b0),
    .CLRMASK                              (1'b0),
    .DIV                                  (3'b000),
    .O                                    (qsfp3_clk_bufg)
    );


  
//  assign rx_device_clk = SHARED_DEVCLK ? tx_device_clk : rx_device_clk_internal;

  // spi

  assign spi0_csb = spi0_csn[0];
  assign spi1_csb = spi1_csn[0];

  ad_3w_spi #(
    .NUM_OF_SLAVES                        (1)
    ) 
  i_spi (
    .spi_csn                              (spi1_csn[0]),
    .spi_clk                              (spi1_sclk),
    .spi_mosi                             (spi1_mosi),
    .spi_miso                             (spi1_miso),
    .spi_sdio                             (spi1_sdio),
    .spi_dir                              ()
    );

  // gpios

  ad_iobuf #(
    .DATA_WIDTH                           (12)
    ) 
  i_iobuf (
    .dio_t                                (gpio_t[43:32]),
    .dio_i                                (gpio_o[43:32]),
    .dio_o                                (gpio_i[43:32]),
    .dio_p                                ({hmc_gpio1,       // 43
                                            gpio[10:0]})     // 42-32
    );   

  assign gpio_i[44] = agc0[0];
  assign gpio_i[45] = agc0[1];
  assign gpio_i[46] = agc1[0];
  assign gpio_i[47] = agc1[1];
  assign gpio_i[48] = agc2[0];
  assign gpio_i[49] = agc2[1];
  assign gpio_i[50] = agc3[0];
  assign gpio_i[51] = agc3[1];
  assign gpio_i[52] = irqb[0];
  assign gpio_i[53] = irqb[1];

  assign hmc_sync   = gpio_o[54];
  assign rstb_i     = gpio_o[55];
  assign rxen[0]    = gpio_o[56];
  assign rxen[1]    = gpio_o[57];
  assign txen[0]    = gpio_o[58];
  assign txen[1]    = gpio_o[59];

  assign rstb       = rstb_i;
  
  generate
    if (TX_NUM_LINKS > 1 & JESD_MODE == "8B10B") 
    begin
      assign tx_syncin[1] = fpga_syncin_1_p;
    end 
    else 
    begin
      ad_iobuf #(
        .DATA_WIDTH                       (2)
        ) 
      i_syncin_iobuf (
        .dio_t                            (gpio_t[61:60]),
        .dio_i                            (gpio_o[61:60]),
        .dio_o                            (gpio_i[61:60]),
        .dio_p                            ({fpga_syncin_1_n,      // 61
                                            fpga_syncin_1_p}));   // 60
    end

    if (RX_NUM_LINKS > 1 & JESD_MODE == "8B10B") 
    begin
      assign fpga_syncout_1_p = rx_syncout[1];
      assign fpga_syncout_1_n = 0;
    end 
    else 
    begin
      ad_iobuf #(
        .DATA_WIDTH(2)
        ) 
      i_syncout_iobuf (
        .dio_t                            (gpio_t[63:62]),
        .dio_i                            (gpio_o[63:62]),
        .dio_o                            (gpio_i[63:62]),
        .dio_p                            ({fpga_syncout_1_n,      // 63
                                            fpga_syncout_1_p})     // 62
        );   
    end
  endgenerate
  /* Board GPIOS. Buttons, LEDs, etc... */
//  assign gpio_i[20: 8] = gpio_bd_i;
//  assign gpio_bd_o = gpio_o[7:0];
  
  vio_0   i_vio_0 (
    .clk                                  (clk_125),
    .probe_in0                            (gpio_o[7:0]),   // 8

    .probe_out0                           (gpio_i[20: 8]),  // 13
    .probe_out1                           (vio_enable),  // 1
    .probe_out2                           (vio_man_tx_tready),  // 1

    .probe_out3                           (vio_dac_src_data_sel),  // 2
    .probe_out4                           (vio_qsfp4_playback_path_data_enable_n)  // 1
    );

  assign dac_src_data_sel_i                   = (vio_enable == 1'b1) ? vio_dac_src_data_sel : dac_src_data_sel;
  assign qsfp4_playback_path_data_enable_n_i  = (vio_enable == 1'b1) ? vio_qsfp4_playback_path_data_enable_n : qsfp4_playback_path_data_enable_n;

 /*      
  ila_0 i_ila_0 ( 
    .clk                                  (clk_125),
    .probe0                               (rstb_i), 
    .probe1                               (spi0_csn[0]), 
    .probe2                               (spi0_miso), 
    .probe3                               (spi0_mosi), 
    .probe4                               (spi1_csn), 
    .probe5                               (spi0_sclk), 
    .probe6                               (spi1_miso),
    .probe7                               (spi1_mosi),
    .probe8                               (spi1_sclk)
    );
*/
  // Unused GPIOs
  assign gpio_i[59:54] = gpio_o[59:54];
  assign gpio_i[94:64] = gpio_o[94:64];
  assign gpio_i[31:21] = gpio_o[31:21];
  assign gpio_i[7:0] = gpio_o[7:0];

  system_wrapper i_system_wrapper (
    .gpio_i                               (gpio_i),
    .gpio_o                               (gpio_o),
    .gpio_t                               (gpio_t),
    .spi0_csn                             (spi0_csn),
    .spi0_miso                            (spi0_miso),
    .spi0_mosi                            (spi0_mosi),
    .spi0_sclk                            (spi0_sclk),
    .spi1_csn                             (spi1_csn),
    .spi1_miso                            (spi1_miso),
    .spi1_mosi                            (spi1_mosi),
    .spi1_sclk                            (spi1_sclk),
    // FMC HPC
    .rx_data_0_n                          (rx_data_n_loc[0]),
    .rx_data_0_p                          (rx_data_p_loc[0]),
    .rx_data_1_n                          (rx_data_n_loc[1]),
    .rx_data_1_p                          (rx_data_p_loc[1]),
    .rx_data_2_n                          (rx_data_n_loc[2]),
    .rx_data_2_p                          (rx_data_p_loc[2]),
    .rx_data_3_n                          (rx_data_n_loc[3]),
    .rx_data_3_p                          (rx_data_p_loc[3]),
    .rx_data_4_n                          (rx_data_n_loc[4]),
    .rx_data_4_p                          (rx_data_p_loc[4]),
    .rx_data_5_n                          (rx_data_n_loc[5]),
    .rx_data_5_p                          (rx_data_p_loc[5]),
    .rx_data_6_n                          (rx_data_n_loc[6]),
    .rx_data_6_p                          (rx_data_p_loc[6]),
    .rx_data_7_n                          (rx_data_n_loc[7]),
    .rx_data_7_p                          (rx_data_p_loc[7]),
    .tx_data_0_n                          (tx_data_n_loc[0]),
    .tx_data_0_p                          (tx_data_p_loc[0]),
    .tx_data_1_n                          (tx_data_n_loc[1]),
    .tx_data_1_p                          (tx_data_p_loc[1]),
    .tx_data_2_n                          (tx_data_n_loc[2]),
    .tx_data_2_p                          (tx_data_p_loc[2]),
    .tx_data_3_n                          (tx_data_n_loc[3]),
    .tx_data_3_p                          (tx_data_p_loc[3]),
    .tx_data_4_n                          (tx_data_n_loc[4]),
    .tx_data_4_p                          (tx_data_p_loc[4]),
    .tx_data_5_n                          (tx_data_n_loc[5]),
    .tx_data_5_p                          (tx_data_p_loc[5]),
    .tx_data_6_n                          (tx_data_n_loc[6]),
    .tx_data_6_p                          (tx_data_p_loc[6]),
    .tx_data_7_n                          (tx_data_n_loc[7]),
    .tx_data_7_p                          (tx_data_p_loc[7]),
    .ref_clk_q0                           (ref_clk),
    .ref_clk_q1                           (ref_clk),
    .rx_device_clk                        (rx_device_clk),
    .tx_device_clk                        (tx_device_clk),
    .rx_sync_0                            (rx_syncout),
    .tx_sync_0                            (tx_syncin),
    .rx_sysref_0                          (sysref),
    .tx_sysref_0                          (sysref),
    
    // these signals are sync to rx_device_clk
    .rx_device_clk_out                    (rx_device_clk_1),
    .rx_device_clk_aresetn_out            (rx_device_clk_aresetn),
    .packed_fifo_wr_data_out              (adc_rx_tdata_256b),             // out    ADC Rx Data
    .packed_fifo_wr_en_out                (adc_rx_tvalid_256b),            // out
    .packed_fifo_wr_overflow_out          (adc_rx_tdata_256b_overflow),    // out
    
    .tx_device_clk_out                    (tx_device_clk_1),
    .tx_device_clk_aresetn_out            (tx_device_clk_aresetn),    
    .mxfe_tx_data_offload_m_axis_tdata    (mem_xfer_tx_upload_tdata_256b),   // out    mem transfer from uP
    .mxfe_tx_data_offload_m_axis_tvalid   (mem_xfer_tx_upload_tvalid_256b),  // out
    .mxfe_tx_data_offload_m_axis_tready   (mem_xfer_tx_upload_tready_256b),  // in
    .mxfe_tx_data_offload_m_axis_tkeep    (),   // out
    .mxfe_tx_data_offload_m_axis_tlast    (),   // out
    
    .util_mxfe_upack_s_axis_tdata         (dac_tx_tdata_256b_pipe ),   // in    DAC Tx Data
    .util_mxfe_upack_s_axis_tvalid        (dac_tx_tvalid_256b_pipe),   // in
    .util_mxfe_upack_s_axis_tready        (dac_tx_tready_256b_pipe),   // out
            
    .sys_cpu_clk_out                      (clk_100),
    .sys_cpu_aresetn_out                  (clk_100_aresetn),
    .M11_AXI_0_araddr                     (M11_AXI_0_araddr),
    .M11_AXI_0_arprot                     (M11_AXI_0_arprot),
    .M11_AXI_0_arready                    (M11_AXI_0_arready),
    .M11_AXI_0_arvalid                    (M11_AXI_0_arvalid),
    .M11_AXI_0_awaddr                     (M11_AXI_0_awaddr),
    .M11_AXI_0_awprot                     (M11_AXI_0_awprot),
    .M11_AXI_0_awready                    (M11_AXI_0_awready),
    .M11_AXI_0_awvalid                    (M11_AXI_0_awvalid),
    .M11_AXI_0_bready                     (M11_AXI_0_bready),
    .M11_AXI_0_bresp                      (M11_AXI_0_bresp),
    .M11_AXI_0_bvalid                     (M11_AXI_0_bvalid),
    .M11_AXI_0_rdata                      (M11_AXI_0_rdata),
    .M11_AXI_0_rready                     (M11_AXI_0_rready),
    .M11_AXI_0_rresp                      (M11_AXI_0_rresp),
    .M11_AXI_0_rvalid                     (M11_AXI_0_rvalid),
    .M11_AXI_0_wdata                      (M11_AXI_0_wdata),
    .M11_AXI_0_wready                     (M11_AXI_0_wready),
    .M11_AXI_0_wstrb                      (M11_AXI_0_wstrb),
    .M11_AXI_0_wvalid                     (M11_AXI_0_wvalid),

    .pl_clk3_0                            (pl_clk3_0),
    .clk_250_out                          (clk_250),
    .clk_250_aresetn_out                  (clk_250_aresetn),

    .pl_clk2_clk125                       (clk_125),
    .pl_clk2_clk125_aresetn_out           (clk_125_aresetn)
    );

  assign rx_data_p_loc[RX_JESD_L*RX_NUM_LINKS-1:0] = rx_data_p[RX_JESD_L*RX_NUM_LINKS-1:0];
  assign rx_data_n_loc[RX_JESD_L*RX_NUM_LINKS-1:0] = rx_data_n[RX_JESD_L*RX_NUM_LINKS-1:0];

  assign tx_data_p[TX_JESD_L*TX_NUM_LINKS-1:0] = tx_data_p_loc[TX_JESD_L*TX_NUM_LINKS-1:0];
  assign tx_data_n[TX_JESD_L*TX_NUM_LINKS-1:0] = tx_data_n_loc[TX_JESD_L*TX_NUM_LINKS-1:0];

//  ila_1 i_ila_1 ( 
//    .clk    (rx_device_clk_1),
//    .probe0 (adc_rx_tdata_256b),     // 256
//    .probe1 (adc_rx_tvalid_256b),       // 1
//    .probe2 (adc_rx_tdata_256b_overflow)  // 1
//    );
   
///////////////////////////////////////////////////////////////////////////
  qsfp_intfc_v1_0  #(
    .FPGA_REVISION_DATE                       (FPGA_REVISION_DATE),
    .MINOR_REV                                (MINOR_REV),
    // Parameters of Axi Slave Bus Interface S00_AXI
    .C_S00_AXI_DATA_WIDTH                     (32),
    .C_S00_AXI_ADDR_WIDTH                     (8)
    )
  i_qsfp_intfc_v1_0 (
    .clk_125_in                               (clk_125),            
    .clk_125_reset_n_in                       (clk_125_aresetn),    

    .clk_250_in                               (clk_250),            
    .clk_250_reset_n_in                       (clk_250_aresetn),    

    .rx_device_clk_in                         (rx_device_clk_1),
    .tx_device_clk_in                         (tx_device_clk_1),

    .clkin8_in                                (clkin8_bufg),
//    .sysref_in                                (sysref),
    .ref_clk_div2_in                          (ref_clk_div2_bufg),
    .qsfp2_clk_in                             (qsfp2_clk_bufg),
    .qsfp3_clk_in                             (qsfp3_clk_bufg),
    .pl_clk3_0                                (pl_clk3_0),

    .QSFP1_INTL_LS                            (QSFP1_INTL_LS),
    .QSFP1_MODPRSL_LS                         (QSFP1_MODPRSL_LS),
    .QSFP1_RESETL_LS                          (QSFP1_RESETL_LS),
    .QSFP1_RX1_N                              (QSFP1_RX1_N),
    .QSFP1_RX1_P                              (QSFP1_RX1_P),
    .QSFP1_RX2_N                              (QSFP1_RX2_N),
    .QSFP1_RX2_P                              (QSFP1_RX2_P),
    .QSFP1_RX3_N                              (QSFP1_RX3_N),
    .QSFP1_RX3_P                              (QSFP1_RX3_P),
    .QSFP1_RX4_N                              (QSFP1_RX4_N),
    .QSFP1_RX4_P                              (QSFP1_RX4_P),
    .QSFP1_SI570_CLOCK_N                      (QSFP1_SI570_CLOCK_N),
    .QSFP1_SI570_CLOCK_P                      (QSFP1_SI570_CLOCK_P),
    .QSFP1_TX1_N                              (QSFP1_TX1_N),
    .QSFP1_TX1_P                              (QSFP1_TX1_P),
    .QSFP1_TX2_N                              (QSFP1_TX2_N),
    .QSFP1_TX2_P                              (QSFP1_TX2_P),
    .QSFP1_TX3_N                              (QSFP1_TX3_N),
    .QSFP1_TX3_P                              (QSFP1_TX3_P),
    .QSFP1_TX4_N                              (QSFP1_TX4_N),
    .QSFP1_TX4_P                              (QSFP1_TX4_P),
    .QSFP4_INTL_LS                            (QSFP4_INTL_LS),
    .QSFP4_MODPRSL_LS                         (QSFP4_MODPRSL_LS),
    .QSFP4_RESETL_LS                          (QSFP4_RESETL_LS),
    .QSFP4_RX1_N                              (QSFP4_RX1_N),
    .QSFP4_RX1_P                              (QSFP4_RX1_P),
    .QSFP4_RX2_N                              (QSFP4_RX2_N),
    .QSFP4_RX2_P                              (QSFP4_RX2_P),
    .QSFP4_RX3_N                              (QSFP4_RX3_N),
    .QSFP4_RX3_P                              (QSFP4_RX3_P),
    .QSFP4_RX4_N                              (QSFP4_RX4_N),
    .QSFP4_RX4_P                              (QSFP4_RX4_P),
    .QSFP4_SI570_CLOCK_N                      (QSFP4_SI570_CLOCK_N),
    .QSFP4_SI570_CLOCK_P                      (QSFP4_SI570_CLOCK_P),
    .QSFP4_TX1_N                              (QSFP4_TX1_N),
    .QSFP4_TX1_P                              (QSFP4_TX1_P),
    .QSFP4_TX2_N                              (QSFP4_TX2_N),
    .QSFP4_TX2_P                              (QSFP4_TX2_P),
    .QSFP4_TX3_N                              (QSFP4_TX3_N),
    .QSFP4_TX3_P                              (QSFP4_TX3_P),
    .QSFP4_TX4_N                              (QSFP4_TX4_N),
    .QSFP4_TX4_P                              (QSFP4_TX4_P),

    .qsfp1_capture_aclk_out                   (qsfp1_capture_aclk),           // QSFP Capture Port  
    .qsfp1_capture_aresetn_out                (qsfp1_capture_aresetn),
    .qsfp1_capture_tdata_240b_out             (qsfp1_capture_tdata_240b),    // out
    .qsfp1_capture_tvalid_240b_out            (qsfp1_capture_tvalid_240b),   // out
    .qsfp1_capture_rx_data_ready_in           (qsfp1_capture_rx_data_ready),

    .qsfp4_playback_aclk_out                  (qsfp4_playback_aclk),         // QSFP Playback Port 
    .qsfp4_playback_aresetn_out               (qsfp4_playback_aresetn), 
    .qsfp4_playback_tdata_240b_in             (qsfp4_playback_tdata_240b),    // in
    .qsfp4_playback_tvalid_240b_in            (qsfp4_playback_tvalid_240b),   // in
    .qsfp4_playback_tready_240b_out           (qsfp4_playback_tready_240b),   // out

    .qsfp1_capture_tvalid_240b_cnt_in         (qsfp1_capture_tvalid_240b_cnt),
    .qsfp1_capture_overflow_240b_cnt_in       (qsfp1_capture_overflow_240b_cnt),
    .qsfp1_capture_fifo_aempty_512b_cnt_in    (qsfp1_capture_fifo_aempty_512b_cnt),
    .qsfp1_capture_rx_data_ready_cnt_in       (qsfp1_capture_rx_data_ready_cnt),
    .tx_tvalid_128b_cnt_in                    (tx_tvalid_256b_cnt),
    .mem_xfer_tx_upload_tvalid_128b_cnt_in    (mem_xfer_tx_upload_tvalid_256b_cnt_r), 
    .dac_tx_tvalid_128b_cnt_in                (dac_tx_tvalid_256b_cnt_r),

    .adc_rx_tvalid_128b_cnt_in                (adc_rx_tvalid_256b_cnt),
    .qsfp4_playback_tvalid_128b_cnt_in        (qsfp4_playback_tvalid_256b_cnt),
    .qsfp4_playback_tvalid_240b_cnt_in        (qsfp4_playback_tvalid_240b_cnt),

    .cnt_reset_out                            (cnt_reset),

    .slv_reg9_out                             (slv_reg9),
    .slv_reg10_out                            (slv_reg10),

    .slv_reg21_out                            (slv_reg21),
    .slv_reg22_out                            (slv_reg22),
    .slv_reg23_out                            (slv_reg23),
    .slv_reg24_out                            (slv_reg24),
    .slv_reg25_out                            (slv_reg25),
    .slv_reg26_out                            (slv_reg26),
    .slv_reg27_out                            (slv_reg27),
    .slv_reg28_out                            (slv_reg28),
    .slv_reg29_out                            (slv_reg29),
    .slv_reg30_out                            (slv_reg30),

    .slv_reg31_out                            (slv_reg31),
    .slv_reg32_out                            (slv_reg32),
    .slv_reg33_out                            (slv_reg33),
    .slv_reg34_out                            (slv_reg34),
    .slv_reg35_out                            (slv_reg35),
    .slv_reg36_out                            (slv_reg36),
    .slv_reg37_out                            (slv_reg37),
    .slv_reg38_out                            (slv_reg38),
    .slv_reg39_out                            (slv_reg39),
    .slv_reg40_out                            (slv_reg40),

    .slv_reg41_out                            (slv_reg41),
    .slv_reg42_out                            (slv_reg42),
    .slv_reg43_out                            (slv_reg43),
    .slv_reg44_out                            (slv_reg44),
    .slv_reg45_out                            (slv_reg45),
    .slv_reg46_out                            (slv_reg46),
    .slv_reg47_out                            (slv_reg47),
    .slv_reg48_out                            (slv_reg48),
    .slv_reg49_out                            (slv_reg49),
    .slv_reg50_out                            (slv_reg50),

    .slv_reg51_out                            (slv_reg51),
    .slv_reg52_out                            (slv_reg52),

    .sys_cpu_clk_in                           (clk_100),
    .s00_axi_aresetn                          (clk_100_aresetn),
    .s00_axi_awaddr                           (M11_AXI_0_awaddr[7:0]),
    .s00_axi_awprot                           (M11_AXI_0_awprot), 
    .s00_axi_awvalid                          (M11_AXI_0_awvalid),
    .s00_axi_awready                          (M11_AXI_0_awready),
    .s00_axi_wdata                            (M11_AXI_0_wdata),
    .s00_axi_wstrb                            (M11_AXI_0_wstrb),
    .s00_axi_wvalid                           (M11_AXI_0_wvalid),
    .s00_axi_wready                           (M11_AXI_0_wready),
    .s00_axi_bresp                            (M11_AXI_0_bresp),
    .s00_axi_bvalid                           (M11_AXI_0_bvalid),
    .s00_axi_bready                           (M11_AXI_0_bready),
    .s00_axi_araddr                           (M11_AXI_0_araddr[7:0]),
    .s00_axi_arprot                           (M11_AXI_0_arprot),
    .s00_axi_arvalid                          (M11_AXI_0_arvalid),
    .s00_axi_arready                          (M11_AXI_0_arready),
    .s00_axi_rdata                            (M11_AXI_0_rdata), 
    .s00_axi_rresp                            (M11_AXI_0_rresp),
    .s00_axi_rvalid                           (M11_AXI_0_rvalid), 
    .s00_axi_rready                           (M11_AXI_0_rready)
    );
  
//assign  qsfp_loopback_en                  = slv_reg10[0];        //0x44a0_0028 
//assign                                    = slv_reg10[7:1];
  assign  dac_src_data_sel                  = slv_reg10[9:8];   
//assign                                    = slv_reg10[11:10];  
  assign  chan1to4_mode_sel                 = slv_reg10[12];
//assign                                    = slv_reg10[14:13]; 
//assign                                    = slv_reg10[15];
//assign                                    = slv_reg10[30:16];
  assign  qsfp4_playback_path_data_enable_n = slv_reg10[31];

///////////////////////////////
// ****>>>> FROM QSFP1 CAPTURE INTERFACE
  qsfp1_capture_intfc i_qsfp1_capture_intfc (
    .qsfp1_capture_aclk_in                          (qsfp1_capture_aclk),   
    .qsfp1_capture_aresetn_in                       (qsfp1_capture_aresetn),
    .qsfp1_capture_tdata_240b_in                    (qsfp1_capture_tdata_240b),
    .qsfp1_capture_tvalid_240b_in                   (qsfp1_capture_tvalid_240b),
    .qsfp1_capture_tvalid_240b_cnt_out              (qsfp1_capture_tvalid_240b_cnt),                      
    .qsfp1_capture_fifo_aempty_512b_cnt_out         (qsfp1_capture_fifo_aempty_512b_cnt),                 
    .qsfp1_capture_iq_240b_to_512b_overflow_cnt_out (qsfp1_capture_overflow_240b_cnt),               

    .qsfp1_capture_rx_data_ready_out                (qsfp1_capture_rx_data_ready),                              
    .qsfp1_capture_rx_data_ready_cnt_out            (qsfp1_capture_rx_data_ready_cnt),                          

    .tx_device_clk_in                               (tx_device_clk_1),
    .tx_device_clk_aresetn_in                       (tx_device_clk_aresetn),
    .tx_fifo_tdata_256b_out                         (tx_tdata_256b),     // out         
    .tx_fifo_tvalid_256b_out                        (tx_tvalid_256b),    // out         
    .tx_fifo_tready_256b_in                         (tx_tready_256b),        // in  
    .tx_fifo_tvalid_256b_cnt_out                    (tx_tvalid_256b_cnt),                   

    .chan1to4_mode_sel_in                           (chan1to4_mode_sel),
    .cnt_reset_in                                   (cnt_reset)
    );

///////////////////////////////////////////
////   to DAC - data source from DMA Tx axis data, QSFP1 and DDS_INTFC
/////////////////////////////////////////////    
  assign dac_tx_tdata_256b               = (dac_src_data_sel_i == 2'b00) ? mem_xfer_tx_upload_tdata_256b  : 
                                           (dac_src_data_sel_i == 2'b01) ? tx_tdata_256b       :
                                           (dac_src_data_sel_i == 2'b10) ? dds_intfc_tdata_256b           : 256'h0;

  assign dac_tx_tvalid_256b              = (dac_src_data_sel_i == 2'b00) ? mem_xfer_tx_upload_tvalid_256b : 
                                           (dac_src_data_sel_i == 2'b01) ? tx_tvalid_256b      :
                                           (dac_src_data_sel_i == 2'b10) ? dds_intfc_tvalid_256b          : 1'b0;
  
  assign mem_xfer_tx_upload_tready_256b  = (dac_src_data_sel_i == 2'b00) ? dac_tx_tready_256b : 1'b0;  
  assign tx_tready_256b                  = (dac_src_data_sel_i == 2'b01) ? dac_tx_tready_256b : 1'b0;
  assign dds_intfc_tready_256b           = (dac_src_data_sel_i == 2'b10) ? dac_tx_tready_256b : 1'b0;

  axis_register_slice_256b i_util_mxfe_upack_reg_slice_256b (
    .aclk                                 (tx_device_clk_1),                         // in
    .aresetn                              (tx_device_clk_aresetn),                   // in
    .s_axis_tdata                         (dac_tx_tdata_256b),            // in
    .s_axis_tvalid                        (dac_tx_tvalid_256b),           // in
    .s_axis_tready                        (dac_tx_tready_256b),           // out
    .m_axis_tdata                         (dac_tx_tdata_256b_pipe),       // out
    .m_axis_tvalid                        (dac_tx_tvalid_256b_pipe),      // out
    .m_axis_tready                        (dac_tx_tready_en)       // in
    );

  assign dac_tx_tready_en = (vio_man_tx_tready == 1'b0) ? dac_tx_tready_256b_pipe : vio_man_tx_tready;
  
///////////////////////////////
// ****>>>> TO QSFP4  PLAYBACK INTERFACE
   
  qsfp4_playback_intfc i_qsfp4_playback_intfc (
    .rx_device_clk_in                             (rx_device_clk_1),    
    .rx_device_clk_aresetn_in                     (rx_device_clk_aresetn), 
    .rx_tdata_256b_in                             (adc_rx_tdata_256b),
    .rx_tvalid_256b_in                            (adc_rx_tvalid_256b),
    .rx_tready_256b_out                           (adc_rx_fifo_tready_256b),
    .rx_tvalid_256b_cnt_out                       (adc_rx_tvalid_256b_cnt),     
    .rx_tvalid_256b_en_cnt_out                    (qsfp4_playback_tvalid_256b_cnt),
    .playback_data_path_enable_n_in               (qsfp4_playback_path_data_enable_n_i),

    .qsfp4_playback_aclk_in                       (qsfp4_playback_aclk),  
    .qsfp4_playback_aresetn_in                    (qsfp4_playback_aresetn), 
    .qsfp4_playback_tdata_240b_out                (qsfp4_playback_tdata_240b), 
    .qsfp4_playback_tvalid_240b_out               (qsfp4_playback_tvalid_240b),
    .qsfp4_playback_tready_240b_in                (qsfp4_playback_tready_240b),            
    .qsfp4_playback_tvalid_240b_cnt_out           (qsfp4_playback_tvalid_240b_cnt),               

    .cnt_reset_in                                 (cnt_reset)
    );
  
  always @(posedge tx_device_clk_1)  
  begin
    if (tx_device_clk_aresetn == 1'b0 || cnt_reset == 1'b1)
      mem_xfer_tx_upload_tvalid_256b_cnt_r   <= 32'h0;
    else if (mem_xfer_tx_upload_tvalid_256b == 1'b1 && mem_xfer_tx_upload_tready_256b == 1'b1)
      mem_xfer_tx_upload_tvalid_256b_cnt_r   <= mem_xfer_tx_upload_tvalid_256b_cnt_r + 1;
  end

  always @(posedge tx_device_clk_1)  
  begin
    if (tx_device_clk_aresetn == 1'b0 || cnt_reset == 1'b1)
      dac_tx_tvalid_256b_cnt_r   <= 32'h0;
    else if (dac_tx_tvalid_256b_pipe == 1'b1 && dac_tx_tready_en == 1'b1)
      dac_tx_tvalid_256b_cnt_r   <= dac_tx_tvalid_256b_cnt_r + 1;
  end

//////////////////////////
  si5332_wrapper i_si5332_wrapper ( 
    .clk_100_in                               (clk_100),
    .clk_100_areset_in                        (~clk_100_aresetn),

    .sda_in                                   (sda_i),                
    .sda_out                                  (sda_o),                
    .sda_t_out                                (sda_t),                

    .scl_in                                   (scl_i),
    .scl_out                                  (scl_o),
    .scl_t_out                                (scl_t),

    .qsfp2_clk_in                             (qsfp2_clk_bufg),  
    .qsfp3_clk_in                             (qsfp3_clk_bufg)       
    );

  IOBUF i_scl_iobuf (
    .O                                        (scl_i),
    .I                                        (scl_o),
    .IO                                       (pll_scl),
    .T                                        (scl_t)
    );

  IOBUF  i_sda_iobuf (
    .O                                        (sda_i),
    .I                                        (sda_o),
    .IO                                       (pll_sda),
    .T                                        (sda_t)
    );




endmodule
