# Proc to create Block Design
proc create_block_design { parentCell design_name target_path } {

    # Define design name
    set block_design_name $design_name
    write_msg "INFO: Creating block design $block_design_name" "1"
    create_bd_design $block_design_name

    # Get object for parentCell
    set parentObj [get_bd_cells $parentCell]

    # Save current instance; Restore later
    set oldCurInst [current_bd_instance .]

    # Set parent object as current
    current_bd_instance $parentObj

    # ################################
    # Interfaces
    # MGT Clock Interface
    set gtrefclk_in [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 gtrefclk_in ]
    set_property -dict [ list \
        CONFIG.FREQ_HZ {100000000} \
    ] $gtrefclk_in

    # SFP Interface
    set sfp [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:sfp_rtl:1.0 sfp ]

    # I2C Interfaces
    set i2c_wrflash [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:iic_rtl:1.0 i2c_wrflash ]
    set i2c_bckpl [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:iic_rtl:1.0 i2c_bckpl ]
    set i2c_emio [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:iic_rtl:1.0 i2c_emio ]

    # ################################
    # Ports
    # MoniMOD
    set f_rst_i [ create_bd_port -dir I f_rst_i ]
    set f_rst_o [ create_bd_port -dir O f_rst_o ]
    set f_rst_t [ create_bd_port -dir O f_rst_t ]
    set p_pres_i_0 [ create_bd_port -dir I -from 1 -to 0 p_pres_i_0 ]

    # PSU alert
    set psu_alert_i [ create_bd_port -dir I psu_alert_i ]

    # Power cycle request
    set pwr_cycle_req_o_0 [ create_bd_port -dir O pwr_cycle_req_o_0 ]

    # Clock selector
    set clk_src_sel_o [ create_bd_port -dir O -from 1 -to 0 clk_src_sel_o ]

    # Leds
    set pl_reset_led [ create_bd_port -dir O -type rst pl_reset_led ]
    set link_status_led [ create_bd_port -dir O link_status_led ]
    set link_sync_led [ create_bd_port -dir O link_sync_led ]
    set mdc_clk_led [ create_bd_port -dir O mdc_clk_led ]

    # Create ports backplane
    set bckpl_rst_n_o [ create_bd_port -dir O bckpl_rst_n_o ]
    set bckpl_servmod_i [ create_bd_port -dir I -from 7 -to 0 bckpl_servmod_i ]
    set bckpl_servmod_o [ create_bd_port -dir O -from 7 -to 0 bckpl_servmod_o ]
    set bckpl_servmod_t [ create_bd_port -dir O -from 7 -to 0 bckpl_servmod_t ]

    # SFP tx disable
    set tx_disable_o [ create_bd_port -dir O tx_disable_o ]

    # Create instance: axi_iic_0, and set properties
    set axi_iic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_iic axi_iic_0 ]
        set_property -dict [ list \
        CONFIG.C_SCL_INERTIAL_DELAY {5} \
        CONFIG.C_SDA_INERTIAL_DELAY {5} \
    ] $axi_iic_0

    # Create instance: axi_iic_1, and set properties
    set axi_iic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_iic axi_iic_1 ]
    set_property -dict [ list \
        CONFIG.C_SCL_INERTIAL_DELAY {5} \
        CONFIG.C_SDA_INERTIAL_DELAY {5} \
        CONFIG.IIC_FREQ_KHZ {100} \
    ] $axi_iic_1

    # Create instance: constants_and_slices, and set properties
    set constants_and_slices [ create_bd_cell -type module -reference constants constants_and_slices ]
    set_property -dict [ list \
        CONFIG.POLARITY {ACTIVE_HIGH} \
    ] [ get_bd_pins /constants_and_slices/reset_o ]

    # Create instance: gig_ethernet_pcs_pma_0, and set properties
    set gig_ethernet_pcs_pma_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:gig_ethernet_pcs_pma gig_ethernet_pcs_pma_0 ]
    set_property -dict [ list \
        CONFIG.Auto_Negotiation {true} \
        CONFIG.EMAC_IF_TEMAC {GEM} \
        CONFIG.Ext_Management_Interface {false} \
        CONFIG.GT_Location {X0Y3} \
        CONFIG.GTinEx {false} \
        CONFIG.LvdsRefClk {125} \
        CONFIG.Physical_Interface {Transceiver} \
        CONFIG.RefClkRate {125} \
        CONFIG.Standard {1000BASEX} \
        CONFIG.SupportLevel {Include_Shared_Logic_in_Core} \
        CONFIG.TransceiverControl {false} \
    ] $gig_ethernet_pcs_pma_0

    # RST PS CLK0
    set RST_PS_CLK0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset RST_PS_CLK0 ]

    # Create instance: lpd_axi_interconnect, and set properties
    set lpd_axi_interconnect [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect lpd_axi_interconnect ]
    set_property -dict [ list \
        CONFIG.NUM_MI {3} \
    ] $lpd_axi_interconnect

    source $target_path/tcl/ps_cfg.tcl

    # FPGA DEVICE
    set fpga_dev [ create_bd_cell -type module -reference fpga_device fpga_dev ]

    # Create interface connections
    connect_bd_intf_net [get_bd_intf_pins gig_ethernet_pcs_pma_0/gtrefclk_in] [get_bd_intf_ports gtrefclk_in]
    connect_bd_intf_net [get_bd_intf_pins gig_ethernet_pcs_pma_0/sfp] [get_bd_intf_ports sfp]
    connect_bd_intf_net [get_bd_intf_pins gig_ethernet_pcs_pma_0/gmii_gem_pcs_pma] [get_bd_intf_pins zynqmp_ps/GMII_ENET0]
    connect_bd_intf_net [get_bd_intf_pins gig_ethernet_pcs_pma_0/mdio_pcs_pma] [get_bd_intf_pins zynqmp_ps/MDIO_ENET0]

    # Connect LPD interconnect
    connect_bd_intf_net [get_bd_intf_pins lpd_axi_interconnect/S00_AXI] [get_bd_intf_pins zynqmp_ps/M_AXI_HPM0_LPD]
    connect_bd_intf_net [get_bd_intf_pins lpd_axi_interconnect/M00_AXI] [get_bd_intf_pins fpga_dev/S_AXI]
    connect_bd_intf_net [get_bd_intf_pins lpd_axi_interconnect/M01_AXI] [get_bd_intf_pins axi_iic_0/S_AXI]
    connect_bd_intf_net [get_bd_intf_pins lpd_axi_interconnect/M02_AXI] [get_bd_intf_pins axi_iic_1/S_AXI]

    # I2C Interfaces
    connect_bd_intf_net [get_bd_intf_pins axi_iic_0/IIC] [get_bd_intf_ports i2c_wrflash]
    connect_bd_intf_net [get_bd_intf_pins axi_iic_1/IIC] [get_bd_intf_ports i2c_bckpl]
    connect_bd_intf_net [get_bd_intf_pins zynqmp_ps/IIC_1] [get_bd_intf_ports i2c_emio]

    # PL RST CLK 0
    connect_bd_net -net pl_resetn0 [get_bd_ports pl_reset_led] [get_bd_pins constants_and_slices/pl_resetn_i] [get_bd_pins RST_PS_CLK0/ext_reset_in] \
    [get_bd_pins zynqmp_ps/pl_resetn0]
    connect_bd_net [get_bd_pins RST_PS_CLK0/interconnect_aresetn] [get_bd_pins lpd_axi_interconnect/ARESETN]
    connect_bd_net -net RST_PS_CLK0_peripheral_aresetn [get_bd_pins axi_iic_0/s_axi_aresetn] [get_bd_pins axi_iic_1/s_axi_aresetn] \
    [get_bd_pins lpd_axi_interconnect/M00_ARESETN] [get_bd_pins lpd_axi_interconnect/M01_ARESETN] [get_bd_pins lpd_axi_interconnect/M02_ARESETN] \
    [get_bd_pins lpd_axi_interconnect/S00_ARESETN] [get_bd_pins RST_PS_CLK0/peripheral_aresetn] [get_bd_pins fpga_dev/S_AXI_ARESETN]

    # PL CLK 0 DOMAIN
    connect_bd_net -net pl_clk0 [get_bd_pins axi_iic_0/s_axi_aclk] [get_bd_pins axi_iic_1/s_axi_aclk] [get_bd_pins constants_and_slices/pl_clk_i] \
    [get_bd_pins gig_ethernet_pcs_pma_0/independent_clock_bufg] [get_bd_pins lpd_axi_interconnect/ACLK] [get_bd_pins lpd_axi_interconnect/M00_ACLK] \
    [get_bd_pins lpd_axi_interconnect/M01_ACLK] [get_bd_pins lpd_axi_interconnect/M02_ACLK] [get_bd_pins lpd_axi_interconnect/S00_ACLK] \
    [get_bd_pins RST_PS_CLK0/slowest_sync_clk] [get_bd_pins zynqmp_ps/maxihpm0_lpd_aclk] [get_bd_pins zynqmp_ps/pl_clk0] [get_bd_pins fpga_dev/S_AXI_ACLK]

    # Constants and Slices connections
    connect_bd_net [get_bd_pins constants_and_slices/wrflash_i2c_irq_i] [get_bd_pins axi_iic_0/iic2intc_irpt]
    connect_bd_net [get_bd_pins constants_and_slices/bckpl_i2c_irq_i] [get_bd_pins axi_iic_1/iic2intc_irpt]
    connect_bd_net [get_bd_pins constants_and_slices/configuration_valid] [get_bd_pins gig_ethernet_pcs_pma_0/configuration_valid]
    connect_bd_net [get_bd_pins constants_and_slices/configuration_vector] [get_bd_pins gig_ethernet_pcs_pma_0/configuration_vector]
    connect_bd_net [get_bd_pins constants_and_slices/link_status_led] [get_bd_ports link_status_led]
    connect_bd_net [get_bd_pins constants_and_slices/link_sync_led] [get_bd_ports link_sync_led]
    connect_bd_net [get_bd_pins constants_and_slices/mdc_clk_led] [get_bd_ports mdc_clk_led]
    connect_bd_net [get_bd_pins constants_and_slices/phyaddr] [get_bd_pins gig_ethernet_pcs_pma_0/phyaddr]
    connect_bd_net [get_bd_pins constants_and_slices/signal_detect] [get_bd_pins gig_ethernet_pcs_pma_0/signal_detect]
    connect_bd_net [get_bd_pins constants_and_slices/an_config_o] [get_bd_pins gig_ethernet_pcs_pma_0/an_adv_config_val] [get_bd_pins gig_ethernet_pcs_pma_0/an_restart_config]
    connect_bd_net [get_bd_pins constants_and_slices/an_config_vec_o] [get_bd_pins gig_ethernet_pcs_pma_0/an_adv_config_vector]
    connect_bd_net [get_bd_pins constants_and_slices/bckpl_rst_n_o] [get_bd_ports bckpl_rst_n_o]
    connect_bd_net [get_bd_pins constants_and_slices/clk_src_sel_o] [get_bd_ports clk_src_sel_o]
    connect_bd_net [get_bd_pins constants_and_slices/ps_emio_o] [get_bd_pins zynqmp_ps/emio_gpio_i]
    connect_bd_net [get_bd_pins constants_and_slices/ps_irq_o] [get_bd_pins zynqmp_ps/pl_ps_irq0]
    connect_bd_net [get_bd_pins constants_and_slices/pwr_cycle_req_o] [get_bd_ports pwr_cycle_req_o_0]
    connect_bd_net [get_bd_pins constants_and_slices/reset_o] [get_bd_pins gig_ethernet_pcs_pma_0/reset]
    connect_bd_net [get_bd_pins constants_and_slices/tx_disable_o] [get_bd_ports tx_disable_o]
    connect_bd_net [get_bd_pins constants_and_slices/status_vector] [get_bd_pins gig_ethernet_pcs_pma_0/status_vector]
    connect_bd_net [get_bd_pins constants_and_slices/p_pres_i] [get_bd_ports p_pres_i_0]
    connect_bd_net [get_bd_pins constants_and_slices/psu_alert_i] [get_bd_ports psu_alert_i]
    connect_bd_net [get_bd_pins constants_and_slices/mdc_i] [get_bd_pins gig_ethernet_pcs_pma_0/mdc] [get_bd_pins zynqmp_ps/emio_enet0_mdio_mdc]
    connect_bd_net [get_bd_pins constants_and_slices/ps_emio_i] [get_bd_pins zynqmp_ps/emio_gpio_o]
    connect_bd_net [get_bd_pins constants_and_slices/ps_emio_t_i] [get_bd_pins zynqmp_ps/emio_gpio_t]
    connect_bd_net [get_bd_pins constants_and_slices/f_rst_i] [get_bd_ports f_rst_i]
    connect_bd_net [get_bd_pins constants_and_slices/f_rst_o] [get_bd_ports f_rst_o]
    connect_bd_net [get_bd_pins constants_and_slices/f_rst_t_o] [get_bd_ports f_rst_t]
    connect_bd_net [get_bd_pins constants_and_slices/bckpl_servmod_i] [get_bd_ports bckpl_servmod_i]
    connect_bd_net [get_bd_pins constants_and_slices/bckpl_servmod_o] [get_bd_ports bckpl_servmod_o]
    connect_bd_net [get_bd_pins constants_and_slices/bckpl_servmod_t_o] [get_bd_ports bckpl_servmod_t]

    # Create address segments
    assign_bd_address -offset 0x80000000 -range 0x00001000 -target_address_space [get_bd_addr_spaces zynqmp_ps/Data] [get_bd_addr_segs fpga_dev/S_AXI/reg0] -force
    assign_bd_address -offset 0x80001000 -range 0x00001000 -target_address_space [get_bd_addr_spaces zynqmp_ps/Data] [get_bd_addr_segs axi_iic_0/S_AXI/Reg] -force
    assign_bd_address -offset 0x80002000 -range 0x00001000 -target_address_space [get_bd_addr_spaces zynqmp_ps/Data] [get_bd_addr_segs axi_iic_1/S_AXI/Reg] -force

    # Restore current instance
    current_bd_instance $oldCurInst

    validate_bd_design
    save_bd_design
    close_bd_design $block_design_name
}
