# SPDX-License-Identifier: Apache-2.0 # Bitstream build for the energy-landscape engine. Vivado batch mode: # vivado -mode batch -source landscape.tcl -tclargs [FREQ ] [TAG ] [JOBS ] [CORES ] [LINK emio|axi] # The part and board are data: PART and BOARD below. There is no programmable-logic I/O: the # processing system provides the clock and the link. LINK axi (the default on one engine) gives an # AXI-Lite register port, a write-list DMA from DDR and an in-fabric chain sequencer # (rtl/landscape_axi.v); LINK emio carries register accesses over the EMIO GPIO lines, and is the # only link of the multi-core build. Every block below is the vendor's no-charge processing-system # configuration or AXI infrastructure; no licensed IP. The tool and block versions are the ones this # design was built and measured with, and a different tool stops the build: set ANY_TOOL to go on, # and expect a different bitstream. set part xck26-sfvc784-2LV-c set board xilinx.com:kv260_som:part0:2.0 proc arg {name dflt} { global argv set i [lsearch $argv $name] if {$i >= 0 && [llength $argv] > $i + 1} { return [lindex $argv [expr {$i + 1}]] } return $dflt } set freq [arg FREQ 100] set tag [arg TAG landscape] set jobs [arg JOBS 4] set cores [arg CORES 1] set link [arg LINK [expr {$cores > 1 ? "emio" : "axi"}]] if {$cores > 1 && $link ne "emio"} { error "the multi-core build has the EMIO link only" } set tool 2026.1 if {[version -short] ne $tool && ![info exists ::env(ANY_TOOL)]} { error "this design was built and measured with Vivado $tool, not [version -short]: set ANY_TOOL to build anyway" } # Each block by its exact version. proc block {name version} { set d [get_ipdefs -all xilinx.com:ip:$name:$version] if {$d eq ""} { error "no $name $version in this tool" } return [lindex $d 0] } set here [file dirname [file normalize [info script]]] puts "BUILD: tag=$tag freq=$freq jobs=$jobs cores=$cores link=$link here=$here" create_project ev_$tag ./ev_$tag -part $part -force set_property board_part $board [current_project] create_bd_design sys create_bd_cell -type ip -vlnv [block zynq_ultra_ps_e 3.5] ps apply_bd_automation -rule xilinx.com:bd_rule:zynq_ultra_ps_e -config {apply_board_preset 1} [get_bd_cells ps] set_property -dict [list \ CONFIG.PSU__FPGA_PL0_ENABLE {1} \ CONFIG.PSU__CRL_APB__PL0_REF_CTRL__FREQMHZ $freq \ CONFIG.PSU__USE__M_AXI_GP0 {0} CONFIG.PSU__USE__M_AXI_GP1 {0} CONFIG.PSU__USE__M_AXI_GP2 {0} \ CONFIG.PSU__GPIO_EMIO__PERIPHERAL__ENABLE {1} \ CONFIG.PSU__GPIO_EMIO__PERIPHERAL__IO {95} \ ] [get_bd_cells ps] create_bd_port -dir O -from 94 -to 0 emio_o create_bd_port -dir I -from 94 -to 0 emio_i connect_bd_net [get_bd_pins ps/emio_gpio_o] [get_bd_ports emio_o] connect_bd_net [get_bd_pins ps/emio_gpio_i] [get_bd_ports emio_i] create_bd_port -dir O -type clk pl_clk0 connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_ports pl_clk0] if {$link eq "axi"} { # The two port widths are the ones this board's boot leaves set (src/axi.rs, ps_ports): loading # a bitstream through the FPGA manager does not change them, so the design meets them as they # are and writes no processor register. M_AXI_HPM0_FPD (128-bit) -> width converter -> protocol # converter -> LITE (32-bit) at 0xA000_0000, 256 KiB. DMA (AXI4, 64-bit) -> width converter -> # S_AXI_HP0_FPD (128-bit) -> DDR. The reset is the fabric's own (aresetn). set_property -dict [list CONFIG.PSU__USE__M_AXI_GP0 {1} CONFIG.PSU__MAXIGP0__DATA_WIDTH {128} \ CONFIG.PSU__USE__S_AXI_GP2 {1} CONFIG.PSU__SAXIGP2__DATA_WIDTH {128}] [get_bd_cells ps] connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins ps/maxihpm0_fpd_aclk] connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins ps/saxihp0_fpd_aclk] create_bd_port -dir I -type rst aresetn set dw [block axi_dwidth_converter 2.1] create_bd_cell -type ip -vlnv $dw down create_bd_cell -type ip -vlnv $dw up set_property -dict [list CONFIG.SI_DATA_WIDTH {128} CONFIG.MI_DATA_WIDTH {32}] [get_bd_cells down] set_property -dict [list CONFIG.SI_DATA_WIDTH {64} CONFIG.MI_DATA_WIDTH {128}] [get_bd_cells up] create_bd_cell -type ip -vlnv [block axi_protocol_converter 2.1] conv set_property -dict [list CONFIG.SI_PROTOCOL {AXI4} CONFIG.MI_PROTOCOL {AXI4LITE} CONFIG.DATA_WIDTH {32}] [get_bd_cells conv] foreach c {down up} { connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins $c/s_axi_aclk] connect_bd_net [get_bd_ports aresetn] [get_bd_pins $c/s_axi_aresetn] } connect_bd_net [get_bd_pins ps/pl_clk0] [get_bd_pins conv/aclk] connect_bd_net [get_bd_ports aresetn] [get_bd_pins conv/aresetn] connect_bd_intf_net [get_bd_intf_pins ps/M_AXI_HPM0_FPD] [get_bd_intf_pins down/S_AXI] connect_bd_intf_net [get_bd_intf_pins down/M_AXI] [get_bd_intf_pins conv/S_AXI] create_bd_intf_port -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 LITE set_property -dict [list CONFIG.PROTOCOL {AXI4LITE} CONFIG.ADDR_WIDTH {32} CONFIG.DATA_WIDTH {32}] [get_bd_intf_ports LITE] connect_bd_intf_net [get_bd_intf_pins conv/M_AXI] [get_bd_intf_ports LITE] create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 DMA set_property -dict [list CONFIG.PROTOCOL {AXI4} CONFIG.ADDR_WIDTH {49} CONFIG.DATA_WIDTH {64} CONFIG.ID_WIDTH {0} \ CONFIG.HAS_REGION {0} CONFIG.HAS_QOS {0} CONFIG.HAS_LOCK {0}] [get_bd_intf_ports DMA] connect_bd_intf_net [get_bd_intf_ports DMA] [get_bd_intf_pins up/S_AXI] connect_bd_intf_net [get_bd_intf_pins up/M_AXI] [get_bd_intf_pins ps/S_AXI_HP0_FPD] set_property CONFIG.ASSOCIATED_BUSIF {LITE:DMA} [get_bd_ports pl_clk0] set_property CONFIG.ASSOCIATED_RESET {aresetn} [get_bd_ports pl_clk0] assign_bd_address set lite [get_bd_addr_segs -of_objects [get_bd_addr_spaces ps/Data] -filter {NAME =~ *LITE*}] set_property offset 0xA0000000 $lite set_property range 256K $lite foreach seg [get_bd_addr_segs -of_objects [get_bd_addr_spaces ps/Data]] { puts "ADDR $seg [get_property offset $seg] [get_property range $seg]" } } validate_bd_design make_wrapper -files [get_files sys.bd] -top -import generate_target all [get_files sys.bd] if {$cores > 1} { add_files [list $here/rtl/landscape_top_multi.v $here/rtl/landscape_multi.v $here/rtl/landscape_core.v] set_property verilog_define [list LANDSCAPE_K=$cores] [current_fileset] } elseif {$link eq "axi"} { add_files [list $here/rtl/landscape_top_axi.v $here/rtl/landscape_axi.v $here/rtl/landscape_core.v] } else { add_files [list $here/rtl/landscape_top.v $here/rtl/landscape_port.v $here/rtl/landscape_core.v] } add_files -fileset constrs_1 $here/rtl/landscape.xdc set_property top design_top [current_fileset] update_compile_order -fileset sources_1 launch_runs impl_1 -to_step write_bitstream -jobs $jobs wait_on_run impl_1 puts "IMPL_STATUS: [get_property STATUS [get_runs impl_1]] PROGRESS: [get_property PROGRESS [get_runs impl_1]]" open_run impl_1 report_utilization -file ev_$tag.util.rpt report_timing_summary -max_paths 5 -file ev_$tag.timing.rpt puts "BITSTREAM: [glob -nocomplain ./ev_$tag/ev_$tag.runs/impl_1/*.bit]"