`timescale 1 ps / 1 ps

module top #
(
    parameter NUM_RX = 2
)
(   
    input  wire 		clk_200_n,
    input  wire 		clk_200_p,
    
    output wire         ddr_act_n,
    output wire [16:0]  ddr_adr,
    output wire [1:0]   ddr_ba,
    output wire [0:0]   ddr_bg,
    output wire [0:0]   ddr_ck_c,
    output wire [0:0]   ddr_ck_t,
    output wire [0:0]   ddr_cke,
    output wire [0:0]   ddr_cs_n,
    inout  wire [7:0]   ddr_dm_n,
    inout  wire [63:0]  ddr_dq,
    inout  wire [7:0]   ddr_dqs_c,
    inout  wire [7:0]   ddr_dqs_t,
    output wire [0:0]   ddr_odt,
    output wire         ddr_reset_n,	
    
    output wire 		mdc,
    inout  wire 		mdio,
    output wire 		phy_rst_n,
    
    input  wire  [3:0]	rgmii_rd,
    input  wire 		rgmii_rx_ctl,
    input  wire 		rgmii_rxc,
    output wire  [3:0]	rgmii_td,
    output wire 		rgmii_tx_ctl,
    output wire 		rgmii_txc,
    
    input  wire 		uart_rxd,
    output wire 		uart_txd,
    
    output wire  [3:0]  leds,
    output wire         fan_pwm,
    output wire         fmc_power_en,
    input  wire         pps,
    
    // I2C
    inout  wire         i2c_scl,
    inout  wire         i2c_sda,
    
    // RF Control
    output wire         tx0_rf_attn_sin,    //ADRF5730
    output wire         tx0_rf_attn_clk,    //ADRF5730
    output wire         tx0_rf_attn_le,     //ADRF5730
    output wire         tx1_rf_attn_sin,    //ADRF5730
    output wire         tx1_rf_attn_clk,    //ADRF5730
    output wire         tx1_rf_attn_le,     //ADRF5730
    output wire         txlo_drv_en,
    
    output wire         rx0_rf_attn_sin,    //ADRF5721
    output wire         rx0_rf_attn_clk,    //ADRF5721
    output wire         rx0_rf_attn_le,     //ADRF5721
    output wire         rx0_if_attn_sin,    //HMC624
    output wire         rx0_if_attn_clk,    //HMC624
    output wire         rx0_if_attn_le,     //HMC624
    output wire         rx0_lna_en,
    
    output wire         rx1_rf_attn_sin,    //ADRF5721   
    output wire         rx1_rf_attn_clk,    //ADRF5721   
    output wire         rx1_rf_attn_le,     //ADRF5721   
    output wire         rx1_if_attn_sin,    //HMC624     
    output wire         rx1_if_attn_clk,    //HMC624     
    output wire         rx1_if_attn_le,     //HMC624     
    output wire         rx1_lna_en,
        
    // Ethernet: SFP+
    input  wire       sfp0_rx_p,
    input  wire       sfp0_rx_n,
    output wire       sfp0_tx_p,
    output wire       sfp0_tx_n,
    input  wire       sfp1_rx_p,
    input  wire       sfp1_rx_n,
    output wire       sfp1_tx_p,
    output wire       sfp1_tx_n,
    input  wire       sfp2_rx_p,
    input  wire       sfp2_rx_n,
    output wire       sfp2_tx_p,
    output wire       sfp2_tx_n,
    input  wire       sfp3_rx_p,
    input  wire       sfp3_rx_n,
    output wire       sfp3_tx_p,
    output wire       sfp3_tx_n,
    input  wire       sfp_mgt_refclk_0_p,
    input  wire       sfp_mgt_refclk_0_n,
    output wire       sfp0_tx_disable_b,
    output wire       sfp1_tx_disable_b,
    output wire       sfp2_tx_disable_b,
    output wire       sfp3_tx_disable_b,
    
    // FMC AD9081
    // SPI0 - To AD9081
    // SPI1 - To Clk Gen HMC7044LP10BE
    inout  wire         fmc_spi0_mosi,
    inout  wire         fmc_spi0_miso,
    inout  wire         fmc_spi0_sck,
    inout  wire         fmc_spi0_ss,
    
    inout  wire         fmc_spi1_mosi,
    inout  wire         fmc_spi1_sck,
    inout  wire         fmc_spi1_ss,
    
    input  wire [7:0]   jesd_rxn_in,
    input  wire [7:0]   jesd_rxp_in,
    output wire [7:0]   jesd_txn_out,
    output wire [7:0]   jesd_txp_out,
    
    input  wire         jesd_sysref_p,
    input  wire         jesd_sysref_n,
    
    input  wire         jesd_sync_in_p,
    input  wire         jesd_sync_in_n,
    
    output wire         jesd_sync_out_p,
    output wire         jesd_sync_out_n,        
    
    input  wire         jesd_core_clk_p,
    input  wire         jesd_core_clk_n,  
//    input  wire         jesd_core_clk2_p,
//    input  wire         jesd_core_clk2_n,      
    
    input  wire         jesd_qpll0_refclk_p,
    input  wire         jesd_qpll0_refclk_n,
    
    output wire         resetb

);
    wire mdio_mdio_i;
    wire mdio_mdio_o;
    wire mdio_mdio_t;
    
    wire fmc_spi0_io0_i;
    wire fmc_spi0_io0_o;
    wire fmc_spi0_io0_t;
    wire fmc_spi0_io1_i;
    wire fmc_spi0_io1_o;
    wire fmc_spi0_io1_t;
    wire fmc_spi0_sck_i;
    wire fmc_spi0_sck_o;
    wire fmc_spi0_sck_t;  
    wire fmc_spi0_ss_i;
    wire fmc_spi0_ss_o;
    wire fmc_spi0_ss_t;
    
    wire fmc_spi1_io0_i;
    wire fmc_spi1_io0_o;
    wire fmc_spi1_io0_t;
    wire fmc_spi1_io1_i;
    wire fmc_spi1_io1_o;
    wire fmc_spi1_io1_t;
    wire fmc_spi1_sck_i;
    wire fmc_spi1_sck_o;
    wire fmc_spi1_sck_t;  
    wire [1:0]fmc_spi1_ss_i;
    wire [1:0]fmc_spi1_ss_o;
    wire fmc_spi1_ss_t;
    
    wire ddr_init_calib_complete;
    wire mb_axi_clk;
    wire mb_axi_aresetn;
    wire mb_axi_reset;
    
    wire common0_qpll1_lock_out;
    wire common1_qpll1_lock_out;
    
    wire jesd_axis_tx_aresetn;
    wire jesd_axis_rx_aresetn;
    wire [255:0]jesd_axis_rx_cmd_tdata;
    wire jesd_axis_rx_cmd_tready;
    wire [7:0]jesd_axis_rx_cmd_tuser;
    wire jesd_axis_rx_cmd_tvalid;
    wire jesd_axis_rx_tvalid;
    wire [255:0]jesd_axis_tx_cmd_tdata;
    wire jesd_axis_tx_cmd_tready;
    wire jesd_axis_tx_cmd_tvalid;
    wire jesd_axis_tx_tready;
    
    // 204C
    wire [511:0]jesd_axis_tx_tdata;
    wire [511:0]jesd_axis_rx_tdata;
    //204B
//    wire [255:0]jesd_axis_tx_tdata;
//    wire [255:0]jesd_axis_rx_tdata;

    wire jesd_rx_core_reset;
    wire jesd_rx_sys_reset;
    wire jesd_tx_core_reset;
    wire jesd_tx_sys_reset;
    wire jesd_core_clk;
    wire jesd_core_clk_in;
    wire jesd_core_clk2_in;
  
    wire [14:0] dac0_wf_bram_addr;
    wire        dac0_wf_bram_clk;
    wire [31:0] dac0_wf_bram_din;
    wire [31:0] dac0_wf_bram_dout;
    wire        dac0_wf_bram_en;
    wire        dac0_wf_bram_rst;
    wire [3:0]  dac0_wf_bram_we;    
    
    wire [14:0] dac1_wf_bram_addr;
    wire        dac1_wf_bram_clk;
    wire [31:0] dac1_wf_bram_din;
    wire [31:0] dac1_wf_bram_dout;
    wire        dac1_wf_bram_en;
    wire        dac1_wf_bram_rst;
    wire [3:0]  dac1_wf_bram_we;  

    wire [14:0] dac2_wf_bram_addr;
    wire        dac2_wf_bram_clk;
    wire [31:0] dac2_wf_bram_din;
    wire [31:0] dac2_wf_bram_dout;
    wire        dac2_wf_bram_en;
    wire        dac2_wf_bram_rst;
    wire [3:0]  dac2_wf_bram_we;  
    
    wire [14:0] dac3_wf_bram_addr;
    wire        dac3_wf_bram_clk;
    wire [31:0] dac3_wf_bram_din;
    wire [31:0] dac3_wf_bram_dout;
    wire        dac3_wf_bram_en;
    wire        dac3_wf_bram_rst;
    wire [3:0]  dac3_wf_bram_we;      
    
    wire start_of_cpi;
    wire start_of_pulse;

    wire [3:0] eth_clk;
    wire [3:0] eth_resetn;
    wire ext_reset_in_200;
    // ------------------------------
    // Buffers
    // ------------------------------
    IBUFDS #(
       .DIFF_TERM("TRUE"),       // Differential Termination
       .IBUF_LOW_PWR("FALSE"),     // Low power="TRUE", Highest performance="FALSE"
       .IOSTANDARD("LVDS")     // Specify the input I/O standard  
      ) core_clk_ibufds_c (
        .I     (jesd_core_clk_p),
        .IB    (jesd_core_clk_n),
        .O     (jesd_core_clk_in)
      );  
      
//    IBUFDS #(
//       .DIFF_TERM("TRUE"),       // Differential Termination
//       .IBUF_LOW_PWR("FALSE"),     // Low power="TRUE", Highest performance="FALSE"
//       .IOSTANDARD("LVDS")     // Specify the input I/O standard  
//      ) core_clk2_ibufds_c (
//        .I     (jesd_core_clk2_p),
//        .IB    (jesd_core_clk2_n),
//        .O     (jesd_core_clk2_in)
//      );        
      
    BUFG BUFG_inst (
       .O(jesd_core_clk), 
       .I(jesd_core_clk_in)
    );        
      
    wire jesd_core_clk_locked;
    
//    jesd_core_clk_wiz jesd_core_clk_wiz
//    (
//        .clk_out1(jesd_core_clk), 
////        .clk_in_sel(jesd_clk_sel),
//        .locked(jesd_core_clk_locked),       
////        .clk_in1_p(jesd_core_clk_p),  
////        .clk_in1_n(jesd_core_clk_n),
////        .clk_in2_p(jesd_core_clk2_p),  
////        .clk_in2_n(jesd_core_clk2_n)
//        .clk_in1(jesd_core_clk_in)
////        .clk_in2(jesd_core_clk2_in)         
//    );
    
      
      
    wire jesd_sync_in;
    IBUFDS #(
       .DIFF_TERM("TRUE"),       // Differential Termination
       .IBUF_LOW_PWR("FALSE"),     // Low power="TRUE", Highest performance="FALSE"
       .IOSTANDARD("LVDS")     // Specify the input I/O standard  
      ) jesd_sync_in_ibufds (
        .I     (jesd_sync_in_p),
        .IB    (jesd_sync_in_n),
        .O     (jesd_sync_in)
      );       
      
    wire jesd_sync_out;
    OBUFDS jesd_sync_out_ibufds (
        .O     (jesd_sync_out_p),
        .OB    (jesd_sync_out_n),
        .I     (jesd_sync_out)
      );          
      
    IOBUF mdio_mdio_iobuf
        (.I(mdio_mdio_o),
        .IO(mdio),
        .O(mdio_mdio_i),
        .T(mdio_mdio_t));
    
    IOBUF fmc_spi0_io0_iobuf
        (.I(fmc_spi0_io0_o),
         .IO(fmc_spi0_mosi),
         .O(fmc_spi0_io0_i),
         .T(fmc_spi0_io0_t));
    IOBUF fmc_spi0_io1_iobuf
        (.I(fmc_spi0_io1_o),
         .IO(fmc_spi0_miso),
         .O(fmc_spi0_io1_i),
         .T(fmc_spi0_io1_t));
    IOBUF fmc_spi0_sck_iobuf
        (.I(fmc_spi0_sck_o),
         .IO(fmc_spi0_sck),
         .O(fmc_spi0_sck_i),
         .T(fmc_spi0_sck_t));
    IOBUF fmc_spi0_ss_iobuf_0
        (.I(fmc_spi0_ss_o),
         .IO(fmc_spi0_ss),
         .O(fmc_spi0_ss_i),
         .T(fmc_spi0_ss_t));

    // This is 3 Wire Interface, Don't need MISO
    // Use extra slave select to manually control tristate pin
    // of MOSI, Xilinx driver doesn't support swapping tristate in the middle of
    // a transaction
    IOBUF fmc_spi1_io0_iobuf
        (.I(fmc_spi1_io0_o),
        .IO(fmc_spi1_mosi),
        .O(fmc_spi1_io0_i),
        .T(fmc_spi1_ss_o[1]));
    
    assign fmc_spi1_io1_i = fmc_spi1_io0_i;
    
    IOBUF fmc_spi1_sck_iobuf
        (.I(fmc_spi1_sck_o),
        .IO(fmc_spi1_sck),
        .O(fmc_spi1_sck_i),
        .T(fmc_spi1_sck_t));
    IOBUF fmc_spi1_ss_iobuf_0
        (.I(fmc_spi1_ss_o[0]),
        .IO(fmc_spi1_ss),
        .O(fmc_spi1_ss_i[0]),
        .T(fmc_spi1_ss_t));     

    
    // I2C For changing regulator voltage
    wire i2c_scl_i;
    wire i2c_scl_o;
    wire i2c_scl_t;
    wire i2c_sda_i;
    wire i2c_sda_o;
    wire i2c_sda_t;    
    
    IOBUF i2c_scl_iobuf
       (.I(i2c_scl_o),
        .IO(i2c_scl),
        .O(i2c_scl_i),
        .T(i2c_scl_t));
    IOBUF i2c_sda_iobuf
       (.I(i2c_sda_o),
        .IO(i2c_sda),
        .O(i2c_sda_i),
        .T(i2c_sda_t));
    
    
    // ------------------------------
    // BD
    // ------------------------------
    axi4l_intf # (
        .AXI_ADDR_WIDTH(32), 
        .AXI_DATA_WIDTH(32)
    ) 
    util_reg_if (
        .clk(mb_axi_clk),
        .resetn(mb_axi_aresetn)
    );
    
    axi4l_intf # (
        .AXI_ADDR_WIDTH(32), 
        .AXI_DATA_WIDTH(32)
    ) 
    timing_engine_if (
        .clk(mb_axi_clk),
        .resetn(mb_axi_aresetn)
    );    

    axi4l_intf # (
        .AXI_ADDR_WIDTH(32), 
        .AXI_DATA_WIDTH(32)
    ) 
    dig_rx_if[NUM_RX] (
        .clk(mb_axi_clk),
        .resetn(mb_axi_aresetn)
    );      

    axi4l_intf # (
        .AXI_ADDR_WIDTH(32), 
        .AXI_DATA_WIDTH(32)
    ) 
    wf_gen_if (
        .clk(mb_axi_clk),
        .resetn(mb_axi_aresetn)
    );     

    // axi4s_intf # (
    //     .AXI_DATA_WIDTH(64),
    //     .AXI_ID_WIDTH(1)
    // ) 
    // rx_udp_axis[NUM_RX] (
    //     .clk(eth_clk[0]),
    //     .resetn(eth_resetn[0])
    // );    

    axi4s_intf # (
        .AXI_DATA_WIDTH(64),
        .AXI_ID_WIDTH(1)
    ) 
    rx_udp_axis[NUM_RX] ();        
    
    axi4s_intf # (
        .AXI_DATA_WIDTH(64),
        .AXI_ID_WIDTH(1)
    ) 
    tx_udp_0_axis (
        .clk(eth_clk[0]),
        .resetn(eth_resetn[0])
    );           
    
    assign ext_reset_in_200 = 1;
    assign mb_axi_reset = !mb_axi_aresetn;
    wire qspi_flash_aresetn;
    
    
    reg [15:0] pps_pipe;
    reg pps_debounce;
    reg pps_q;
    reg pps_q2;
    reg pps_red;
   
    always @ (posedge mb_axi_clk) begin
        pps_pipe <= {pps_pipe[14:0], pps};
        pps_debounce = |pps_pipe;
        pps_q <= pps_debounce;
        pps_q2 <= pps_q;
        pps_red <= !pps_q2 & pps_q;
    end
    
    microblaze_bd microblaze_bd_i
    (
        .i2c_scl_i(i2c_scl_i),
        .i2c_scl_o(i2c_scl_o),
        .i2c_scl_t(i2c_scl_t),
        .i2c_sda_i(i2c_sda_i),
        .i2c_sda_o(i2c_sda_o),
        .i2c_sda_t(i2c_sda_t),
        
        .STARTUP_IO_cfgclk(),
        .STARTUP_IO_cfgmclk(),
        .STARTUP_IO_eos(),
        .STARTUP_IO_gsr(1'b0),
        .STARTUP_IO_gts(1'b0),
        .STARTUP_IO_keyclearb(1'b1),
        .STARTUP_IO_preq(),
        .STARTUP_IO_userdoneo(1'b1),
        .STARTUP_IO_usrclkts(1'b0),
        .STARTUP_IO_usrdonets(1'b1),
        
        .qspi_flash_aresetn(qspi_flash_aresetn),
        
        .pps(pps_red),
        
        .clk_200_in_clk_n(clk_200_n),
        .clk_200_in_clk_p(clk_200_p),
        .ddr_act_n(ddr_act_n),
        .ddr_adr(ddr_adr),
        .ddr_ba(ddr_ba),
        .ddr_bg(ddr_bg),
        .ddr_ck_c(ddr_ck_c),
        .ddr_ck_t(ddr_ck_t),
        .ddr_cke(ddr_cke),
        .ddr_cs_n(ddr_cs_n),
        .ddr_dm_n(ddr_dm_n),
        .ddr_dq(ddr_dq),
        .ddr_dqs_c(ddr_dqs_c),
        .ddr_dqs_t(ddr_dqs_t),
        .ddr_odt(ddr_odt),
        .ddr_reset_n(ddr_reset_n),		
        .ddr_init_calib_complete(ddr_init_calib_complete),
        .ext_reset_in_200(ext_reset_in_200),
        .mdio_mdc(mdc),
        .mdio_mdio_i(mdio_mdio_i),
        .mdio_mdio_o(mdio_mdio_o),
        .mdio_mdio_t(mdio_mdio_t),
        .phy_rst_n(phy_rst_n),
        .rgmii_rd(rgmii_rd),
        .rgmii_rx_ctl(rgmii_rx_ctl),
        .rgmii_rxc(rgmii_rxc),
        .rgmii_td(rgmii_td),
        .rgmii_tx_ctl(rgmii_tx_ctl),
        .rgmii_txc(rgmii_txc),
        .uart_rxd(uart_rxd),
        .uart_txd(uart_txd),
        .mb_axi_clk(mb_axi_clk),
        .mb_axi_aresetn(mb_axi_aresetn),
        .util_reg_axil_araddr(util_reg_if.araddr),
        .util_reg_axil_arprot(util_reg_if.arprot),
        .util_reg_axil_arready(util_reg_if.arready),
        .util_reg_axil_arvalid(util_reg_if.arvalid),
        .util_reg_axil_awaddr(util_reg_if.awaddr),
        .util_reg_axil_awprot(util_reg_if.awprot),
        .util_reg_axil_awready(util_reg_if.awready),
        .util_reg_axil_awvalid(util_reg_if.awvalid),
        .util_reg_axil_bready(util_reg_if.bready),
        .util_reg_axil_bresp(util_reg_if.bresp),
        .util_reg_axil_bvalid(util_reg_if.bvalid),
        .util_reg_axil_rdata(util_reg_if.rdata),
        .util_reg_axil_rready(util_reg_if.rready),
        .util_reg_axil_rresp(util_reg_if.rresp),
        .util_reg_axil_rvalid(util_reg_if.rvalid),
        .util_reg_axil_wdata(util_reg_if.wdata),
        .util_reg_axil_wready(util_reg_if.wready),
        .util_reg_axil_wstrb(util_reg_if.wstrb),
        .util_reg_axil_wvalid(util_reg_if.wvalid),
        
        .timing_engine_axil_araddr(timing_engine_if.araddr),
        .timing_engine_axil_arprot(timing_engine_if.arprot),
        .timing_engine_axil_arready(timing_engine_if.arready),
        .timing_engine_axil_arvalid(timing_engine_if.arvalid),
        .timing_engine_axil_awaddr(timing_engine_if.awaddr),
        .timing_engine_axil_awprot(timing_engine_if.awprot),
        .timing_engine_axil_awready(timing_engine_if.awready),
        .timing_engine_axil_awvalid(timing_engine_if.awvalid),
        .timing_engine_axil_bready(timing_engine_if.bready),
        .timing_engine_axil_bresp(timing_engine_if.bresp),
        .timing_engine_axil_bvalid(timing_engine_if.bvalid),
        .timing_engine_axil_rdata(timing_engine_if.rdata),
        .timing_engine_axil_rready(timing_engine_if.rready),
        .timing_engine_axil_rresp(timing_engine_if.rresp),
        .timing_engine_axil_rvalid(timing_engine_if.rvalid),
        .timing_engine_axil_wdata(timing_engine_if.wdata),
        .timing_engine_axil_wready(timing_engine_if.wready),
        .timing_engine_axil_wstrb(timing_engine_if.wstrb),
        .timing_engine_axil_wvalid(timing_engine_if.wvalid),      
        
        .dig_rx0_axil_araddr(dig_rx_if[0].araddr),
        .dig_rx0_axil_arprot(dig_rx_if[0].arprot),
        .dig_rx0_axil_arready(dig_rx_if[0].arready),
        .dig_rx0_axil_arvalid(dig_rx_if[0].arvalid),
        .dig_rx0_axil_awaddr(dig_rx_if[0].awaddr),
        .dig_rx0_axil_awprot(dig_rx_if[0].awprot),
        .dig_rx0_axil_awready(dig_rx_if[0].awready),
        .dig_rx0_axil_awvalid(dig_rx_if[0].awvalid),
        .dig_rx0_axil_bready(dig_rx_if[0].bready),
        .dig_rx0_axil_bresp(dig_rx_if[0].bresp),
        .dig_rx0_axil_bvalid(dig_rx_if[0].bvalid),
        .dig_rx0_axil_rdata(dig_rx_if[0].rdata),
        .dig_rx0_axil_rready(dig_rx_if[0].rready),
        .dig_rx0_axil_rresp(dig_rx_if[0].rresp),
        .dig_rx0_axil_rvalid(dig_rx_if[0].rvalid),
        .dig_rx0_axil_wdata(dig_rx_if[0].wdata),
        .dig_rx0_axil_wready(dig_rx_if[0].wready),
        .dig_rx0_axil_wstrb(dig_rx_if[0].wstrb),
        .dig_rx0_axil_wvalid(dig_rx_if[0].wvalid),         

        .dig_rx1_axil_araddr(dig_rx_if[1].araddr),
        .dig_rx1_axil_arprot(dig_rx_if[1].arprot),
        .dig_rx1_axil_arready(dig_rx_if[1].arready),
        .dig_rx1_axil_arvalid(dig_rx_if[1].arvalid),
        .dig_rx1_axil_awaddr(dig_rx_if[1].awaddr),
        .dig_rx1_axil_awprot(dig_rx_if[1].awprot),
        .dig_rx1_axil_awready(dig_rx_if[1].awready),
        .dig_rx1_axil_awvalid(dig_rx_if[1].awvalid),
        .dig_rx1_axil_bready(dig_rx_if[1].bready),
        .dig_rx1_axil_bresp(dig_rx_if[1].bresp),
        .dig_rx1_axil_bvalid(dig_rx_if[1].bvalid),
        .dig_rx1_axil_rdata(dig_rx_if[1].rdata),
        .dig_rx1_axil_rready(dig_rx_if[1].rready),
        .dig_rx1_axil_rresp(dig_rx_if[1].rresp),
        .dig_rx1_axil_rvalid(dig_rx_if[1].rvalid),
        .dig_rx1_axil_wdata(dig_rx_if[1].wdata),
        .dig_rx1_axil_wready(dig_rx_if[1].wready),
        .dig_rx1_axil_wstrb(dig_rx_if[1].wstrb),
        .dig_rx1_axil_wvalid(dig_rx_if[1].wvalid),               
        
        .wf_gen_axil_araddr(wf_gen_if.araddr),
        .wf_gen_axil_arprot(wf_gen_if.arprot),
        .wf_gen_axil_arready(wf_gen_if.arready),
        .wf_gen_axil_arvalid(wf_gen_if.arvalid),
        .wf_gen_axil_awaddr(wf_gen_if.awaddr),
        .wf_gen_axil_awprot(wf_gen_if.awprot),
        .wf_gen_axil_awready(wf_gen_if.awready),
        .wf_gen_axil_awvalid(wf_gen_if.awvalid),
        .wf_gen_axil_bready(wf_gen_if.bready),
        .wf_gen_axil_bresp(wf_gen_if.bresp),
        .wf_gen_axil_bvalid(wf_gen_if.bvalid),
        .wf_gen_axil_rdata(wf_gen_if.rdata),
        .wf_gen_axil_rready(wf_gen_if.rready),
        .wf_gen_axil_rresp(wf_gen_if.rresp),
        .wf_gen_axil_rvalid(wf_gen_if.rvalid),
        .wf_gen_axil_wdata(wf_gen_if.wdata),
        .wf_gen_axil_wready(wf_gen_if.wready),
        .wf_gen_axil_wstrb(wf_gen_if.wstrb),
        .wf_gen_axil_wvalid(wf_gen_if.wvalid),            
        
        .fmc_spi0_io0_i(fmc_spi0_io0_i),
        .fmc_spi0_io0_o(fmc_spi0_io0_o),
        .fmc_spi0_io0_t(fmc_spi0_io0_t),
        .fmc_spi0_io1_i(fmc_spi0_io1_i),
        .fmc_spi0_io1_o(fmc_spi0_io1_o),
        .fmc_spi0_io1_t(fmc_spi0_io1_t),
        .fmc_spi0_sck_i(fmc_spi0_sck_i),
        .fmc_spi0_sck_o(fmc_spi0_sck_o),
        .fmc_spi0_sck_t(fmc_spi0_sck_t),
        .fmc_spi0_ss_i(fmc_spi0_ss_i),
        .fmc_spi0_ss_o(fmc_spi0_ss_o),
        .fmc_spi0_ss_t(fmc_spi0_ss_t),    
        
        .fmc_spi1_io0_i(fmc_spi1_io0_i),
        .fmc_spi1_io0_o(fmc_spi1_io0_o),
        .fmc_spi1_io0_t(fmc_spi1_io0_t),
        .fmc_spi1_io1_i(fmc_spi1_io1_i),
        .fmc_spi1_io1_o(fmc_spi1_io1_o),
        .fmc_spi1_io1_t(fmc_spi1_io1_t),
        .fmc_spi1_sck_i(fmc_spi1_sck_i),
        .fmc_spi1_sck_o(fmc_spi1_sck_o),
        .fmc_spi1_sck_t(fmc_spi1_sck_t),
        .fmc_spi1_ss_i(fmc_spi1_ss_i),
        .fmc_spi1_ss_o(fmc_spi1_ss_o),
        .fmc_spi1_ss_t(fmc_spi1_ss_t),    
        
        .common0_qpll1_lock_out(common0_qpll1_lock_out),
        .common1_qpll1_lock_out(common1_qpll1_lock_out),
        .jesd_axis_tx_aresetn(jesd_axis_tx_aresetn),
        .jesd_axis_rx_aresetn(jesd_axis_rx_aresetn),
        .jesd_axis_rx_tdata(jesd_axis_rx_tdata),
        .jesd_axis_rx_tvalid(jesd_axis_rx_tvalid),
        .jesd_axis_tx_tdata(jesd_axis_tx_tdata),
        .jesd_axis_tx_tready(jesd_axis_tx_tready),
        .jesd_qpll0_refclk_clk_n(jesd_qpll0_refclk_n),
        .jesd_qpll0_refclk_clk_p(jesd_qpll0_refclk_p),
        .jesd_sysref_clk_n(jesd_sysref_n),
        .jesd_sysref_clk_p(jesd_sysref_p),
        .jesd_rx_core_reset(jesd_rx_core_reset),
        .jesd_rxn_in(jesd_rxn_in),
        .jesd_rxp_in(jesd_rxp_in),
        .jesd_tx_core_reset(jesd_tx_core_reset),
        .jesd_txn_out(jesd_txn_out),
        .jesd_txp_out(jesd_txp_out),
        .jesd_tx_sys_reset(jesd_tx_sys_reset),
        .jesd_rx_sys_reset(jesd_rx_sys_reset),
        .jesd_core_clk(jesd_core_clk),
        
        .jesd_axis_rx_cmd_tdata(jesd_axis_rx_cmd_tdata),
        .jesd_axis_rx_cmd_tready(jesd_axis_rx_cmd_tready),
        .jesd_axis_rx_cmd_tuser(jesd_axis_rx_cmd_tuser),
        .jesd_axis_rx_cmd_tvalid(jesd_axis_rx_cmd_tvalid),
        .jesd_axis_tx_cmd_tdata(jesd_axis_tx_cmd_tdata),
        .jesd_axis_tx_cmd_tready(jesd_axis_tx_cmd_tready),
        .jesd_axis_tx_cmd_tvalid(jesd_axis_tx_cmd_tvalid),
                
//        .jesd_tx_sync(jesd_sync_in),
//        .jesd_rx_sync(jesd_sync_out),
        
        .eth_clk(eth_clk[0]),
        .eth_resetn(eth_resetn[0]),
        .udp_rx_tdata(rx_udp_axis[0].tdata),
        .udp_rx_tready(rx_udp_axis[0].tready),
        .udp_rx_tvalid(rx_udp_axis[0].tvalid),
        .udp_rx_tlast(rx_udp_axis[0].tlast),
        
        .udp_tx_tdata(tx_udp_0_axis.tdata),
        .udp_tx_tkeep(tx_udp_0_axis.tkeep),
        .udp_tx_tlast(tx_udp_0_axis.tlast),
        .udp_tx_tready(tx_udp_0_axis.tready),
        .udp_tx_tvalid(tx_udp_0_axis.tvalid),        
        
        .dac0_wf_bram_addr(dac0_wf_bram_addr),
        .dac0_wf_bram_clk(dac0_wf_bram_clk),
        .dac0_wf_bram_din(dac0_wf_bram_din),
        .dac0_wf_bram_dout(dac0_wf_bram_dout),
        .dac0_wf_bram_en(dac0_wf_bram_en),
        .dac0_wf_bram_rst(dac0_wf_bram_rst),
        .dac0_wf_bram_we(dac0_wf_bram_we),
        
        .dac1_wf_bram_addr(dac1_wf_bram_addr),
        .dac1_wf_bram_clk(dac1_wf_bram_clk),
        .dac1_wf_bram_din(dac1_wf_bram_din),
        .dac1_wf_bram_dout(dac1_wf_bram_dout),
        .dac1_wf_bram_en(dac1_wf_bram_en),
        .dac1_wf_bram_rst(dac1_wf_bram_rst),
        .dac1_wf_bram_we(dac1_wf_bram_we),
        
        .dac2_wf_bram_addr(dac2_wf_bram_addr),
        .dac2_wf_bram_clk(dac2_wf_bram_clk),
        .dac2_wf_bram_din(dac2_wf_bram_din),
        .dac2_wf_bram_dout(dac2_wf_bram_dout),
        .dac2_wf_bram_en(dac2_wf_bram_en),
        .dac2_wf_bram_rst(dac2_wf_bram_rst),
        .dac2_wf_bram_we(dac2_wf_bram_we),
        
        .dac3_wf_bram_addr(dac3_wf_bram_addr),
        .dac3_wf_bram_clk(dac3_wf_bram_clk),
        .dac3_wf_bram_din(dac3_wf_bram_din),
        .dac3_wf_bram_dout(dac3_wf_bram_dout),
        .dac3_wf_bram_en(dac3_wf_bram_en),
        .dac3_wf_bram_rst(dac3_wf_bram_rst),
        .dac3_wf_bram_we(dac3_wf_bram_we)
            
    );

    // ------------------------------
    // Utility Registers
    // ------------------------------
    
    wire [31:0] gpi;
    wire [31:0] gpo;
    wire [15:0] packet_size;
    wire eth_reset;
    
    
    assign leds[1:0] = gpo[1:0];
    assign leds[2] = 0;
    assign leds[3] = jesd_core_clk_locked;
    assign fmc_power_en = gpo[4];
    assign resetb = gpo[5];
    assign jesd_rx_core_reset = gpo[6];
    assign jesd_tx_core_reset = gpo[7];
    assign jesd_rx_sys_reset = gpo[8];
    assign jesd_tx_sys_reset = gpo[9];    
    assign qspi_flash_aresetn = ~gpo[10];
    assign jesd_clk_sel = gpo[11];
    assign eth_reset = gpo[15];    
    
    assign gpi[31:4] = 0;
    // assign gpi[31] = start_of_cpi;
    // assign gpi[30] = start_of_pulse;
    assign gpi[3] = jesd_core_clk_locked;
    assign gpi[2] = common1_qpll1_lock_out;
    assign gpi[1] = common0_qpll1_lock_out;
    assign gpi[0] = ddr_init_calib_complete;
    
    util_reg util_reg_i
    (
        .ctrl_if(util_reg_if),
        
        .gpo(gpo),
        .gpi(gpi),
        .packet_size(packet_size),
        .fan_pwm(fan_pwm),
        
        .tx0_rf_attn_sin(tx0_rf_attn_sin),
        .tx0_rf_attn_clk(tx0_rf_attn_clk),
        .tx0_rf_attn_le(tx0_rf_attn_le),
        .tx1_rf_attn_sin(tx1_rf_attn_sin),
        .tx1_rf_attn_clk(tx1_rf_attn_clk),
        .tx1_rf_attn_le(tx1_rf_attn_le),
        
        .rx0_rf_attn_sin(rx0_rf_attn_sin),
        .rx0_rf_attn_clk(rx0_rf_attn_clk),
        .rx0_rf_attn_le(rx0_rf_attn_le),
        .rx0_if_attn_sin(rx0_if_attn_sin),
        .rx0_if_attn_clk(rx0_if_attn_clk),
        .rx0_if_attn_le(rx0_if_attn_le),
        
        .rx1_rf_attn_sin(rx1_rf_attn_sin),   
        .rx1_rf_attn_clk(rx1_rf_attn_clk),   
        .rx1_rf_attn_le(rx1_rf_attn_le),   
        .rx1_if_attn_sin(rx1_if_attn_sin),     
        .rx1_if_attn_clk(rx1_if_attn_clk),     
        .rx1_if_attn_le(rx1_if_attn_le)             
    );  
    
    // ------------------------------
    // 10G Ethernet
    // ------------------------------    
    axi4s_intf # (
        .AXI_DATA_WIDTH(64),
        .AXI_USER_WIDTH(16)
    ) 
    tx_udp_switch_out[NUM_RX] (); 

    axi4s_intf # (
        .AXI_DATA_WIDTH(64),
        .AXI_USER_WIDTH(16)
    ) 
    hdr_out[NUM_RX] ();      
    
    axi4s_intf # (
        .AXI_DATA_WIDTH(64),
        .AXI_USER_WIDTH(15)
    ) 
    rx_axis[NUM_RX] ();         

      
    // These are from the block design, not currently using this though
    assign tx_udp_0_axis.tuser = 1'b0;
    assign tx_udp_0_axis.tready = 1'b1; 

    // This one is not connected to block design
    assign rx_udp_axis[1].tready = 1;

    ethernet_top ethernet_top_i
    (
        .clk_freerun(mb_axi_clk),
        .reset(eth_reset),
        .eth_clk(eth_clk),
        .eth_resetn(eth_resetn),
        .packet_size(packet_size),

        .rx_udp_0(rx_udp_axis[0]),
        .tx_udp_0(tx_udp_switch_out[0]),

        .rx_udp_1(rx_udp_axis[1]),
        .tx_udp_1(tx_udp_switch_out[1]),        

        .sfp0_rx_p(sfp0_rx_p),
        .sfp0_rx_n(sfp0_rx_n),
        .sfp0_tx_p(sfp0_tx_p),
        .sfp0_tx_n(sfp0_tx_n),
        .sfp1_rx_p(sfp1_rx_p),
        .sfp1_rx_n(sfp1_rx_n),
        .sfp1_tx_p(sfp1_tx_p),
        .sfp1_tx_n(sfp1_tx_n),
        .sfp2_rx_p(sfp2_rx_p),
        .sfp2_rx_n(sfp2_rx_n),
        .sfp2_tx_p(sfp2_tx_p),
        .sfp2_tx_n(sfp2_tx_n),
        .sfp3_rx_p(sfp3_rx_p),
        .sfp3_rx_n(sfp3_rx_n),
        .sfp3_tx_p(sfp3_tx_p),
        .sfp3_tx_n(sfp3_tx_n),
        .sfp_mgt_refclk_0_p(sfp_mgt_refclk_0_p),
        .sfp_mgt_refclk_0_n(sfp_mgt_refclk_0_n),
        .sfp0_tx_disable_b(sfp0_tx_disable_b),
        .sfp1_tx_disable_b(sfp1_tx_disable_b),
        .sfp2_tx_disable_b(sfp2_tx_disable_b),
        .sfp3_tx_disable_b(sfp3_tx_disable_b)
    );

    genvar i;
    generate
        for (i = 0; i < NUM_RX; i = i + 1) begin

            assign tx_udp_switch_out[i].clk = eth_clk[i];
            assign tx_udp_switch_out[i].resetn = eth_resetn[i];

            assign rx_axis[i].clk = eth_clk[i];
            assign rx_axis[i].resetn = eth_resetn[i];
            
            assign hdr_out[i].clk = eth_clk[i];
            assign hdr_out[i].resetn = eth_resetn[i];      
            
            assign rx_udp_axis[i].clk = eth_clk[i];
            assign rx_udp_axis[i].resetn = eth_resetn[i];            
            

            // ------------------------------
            // RX Chain
            // ------------------------------  
            digital_rx_chain digital_rx_chain_i (
                .clk(jesd_core_clk),
             
                .ctrl_if(dig_rx_if[i]),
        
                .start_of_pulse(start_of_pulse),
             
                .in_tvalid(jesd_axis_rx_tvalid),
                .in_tdata_i(jesd_axis_rx_tdata[i*128+63  :i*128+0]),
                .in_tdata_q(jesd_axis_rx_tdata[i*128+127 :i*128+64]),    
//                .in_tdata_i(jesd_axis_rx_tdata[i*64+31 :i*64+0]),
//                .in_tdata_q(jesd_axis_rx_tdata[i*64+63 :i*64+32]),    
             
                .rx_out(rx_axis[i])
            );    


            axis_switch_0 axis_switch_i (
                .aclk(eth_clk[i]),                 
                .aresetn(eth_resetn[i]),           
                .s_axis_tvalid({hdr_out[i].tvalid, rx_axis[i].tvalid}),
                .s_axis_tready({hdr_out[i].tready, rx_axis[i].tready}),
                .s_axis_tdata({hdr_out[i].tdata, rx_axis[i].tdata}),   
                .s_axis_tlast({hdr_out[i].tlast, rx_axis[i].tlast}),   
                .s_axis_tuser({hdr_out[i].tuser, rx_axis[i].tuser}),   
                .s_axis_tdest({hdr_out[i].tdest, rx_axis[i].tdest}),   

                .m_axis_tvalid(tx_udp_switch_out[i].tvalid),
                .m_axis_tready(tx_udp_switch_out[i].tready),
                .m_axis_tdata(tx_udp_switch_out[i].tdata),  
                .m_axis_tlast(tx_udp_switch_out[i].tlast),  
                .m_axis_tuser(tx_udp_switch_out[i].tuser),  
                .m_axis_tdest(tx_udp_switch_out[i].tdest),  
                .s_req_suppress(2'b00),
                .s_decode_err()      
            );

            assign tx_udp_switch_out[i].tkeep = '1;

        end
    endgenerate

    // ------------------------------
    // Timing Engine
    // ------------------------------
    wire [7:0]   timing_pulses;
    
    assign txlo_drv_en = timing_pulses[0];
    assign rx0_lna_en = timing_pulses[1];
    assign rx1_lna_en = timing_pulses[2];
       
    timing_engine timing_engine_i
    (
        .clk(jesd_core_clk),    
        .pps(pps),
        
        .ctrl_if(timing_engine_if),
        
        .start_of_cpi(start_of_cpi),
        .start_of_pulse(start_of_pulse),
        .timing_pulses(timing_pulses),

        .hdr_out(hdr_out)
    );  

    // ------------------------------
    // TX Chain
    // ------------------------------  
    assign jesd_axis_rx_cmd_tready = 1'b1;
    assign jesd_axis_tx_cmd_tdata = 0;
    assign jesd_axis_tx_cmd_tvalid = 1'b1;

    waveform_gen waveform_gen_i (
        .clk(jesd_core_clk),
        
        .ctrl_if(wf_gen_if),

        .start_of_pulse(start_of_pulse),
        
        .dac0_wf_bram_addr(dac0_wf_bram_addr),
        .dac0_wf_bram_clk(dac0_wf_bram_clk),
        .dac0_wf_bram_din(dac0_wf_bram_din),
        .dac0_wf_bram_dout(dac0_wf_bram_dout),
        .dac0_wf_bram_en(dac0_wf_bram_en),
        .dac0_wf_bram_rst(dac0_wf_bram_rst),
        .dac0_wf_bram_we(dac0_wf_bram_we),
        
        .dac1_wf_bram_addr(dac1_wf_bram_addr),
        .dac1_wf_bram_clk(dac1_wf_bram_clk),
        .dac1_wf_bram_din(dac1_wf_bram_din),
        .dac1_wf_bram_dout(dac1_wf_bram_dout),
        .dac1_wf_bram_en(dac1_wf_bram_en),
        .dac1_wf_bram_rst(dac1_wf_bram_rst),
        .dac1_wf_bram_we(dac1_wf_bram_we),
        
        .dac2_wf_bram_addr(dac2_wf_bram_addr),
        .dac2_wf_bram_clk(dac2_wf_bram_clk),
        .dac2_wf_bram_din(dac2_wf_bram_din),
        .dac2_wf_bram_dout(dac2_wf_bram_dout),
        .dac2_wf_bram_en(dac2_wf_bram_en),
        .dac2_wf_bram_rst(dac2_wf_bram_rst),
        .dac2_wf_bram_we(dac2_wf_bram_we),
        
        .dac3_wf_bram_addr(dac3_wf_bram_addr),
        .dac3_wf_bram_clk(dac3_wf_bram_clk),
        .dac3_wf_bram_din(dac3_wf_bram_din),
        .dac3_wf_bram_dout(dac3_wf_bram_dout),
        .dac3_wf_bram_en(dac3_wf_bram_en),
        .dac3_wf_bram_rst(dac3_wf_bram_rst),
        .dac3_wf_bram_we(dac3_wf_bram_we),

        .jesd_tx(jesd_axis_tx_tdata)
    );        


endmodule
