Tool Command Language (Tcl)
Tcl (Tool Command Language) is the standard language used to control Vivado® programmatically. Virtually any operation performed within the graphical user interface has a corresponding Tcl command, displayed in the Vivado console.
Getting started
In Tcl, everything is a string. Procedures are called with the procedure name followed by the list of arguments, separated by white spaces:
set a 1
The command set
assigns the value 1
to the variable a
.
The value of a
can be accessed with the dollar-sign $
:
set b hello$a
# The variable `b` now contains the value `hello1`.
Procedure are defined with the following syntax:
proc concat {x y} {
return $x$y
}
set c [concat $a $b]
# The variable `c` contains the value `1hello1`.
The brackets notation []
tells the intepreter to substitute [concat $a $b]
with the result of the command concat $a $b
.
On the contrary, the brace notation {}
can be used to prevent substitution:
set d {concat $a $b}
# The variable `d` contains the value `concat $a $b`.
Mathematical expressions are computed with the command expr
:
proc add10 {x} {
return [expr $x + 10]
}
set thirty [add10 20]
Helper procedures
Helper procedures ease the creation of Vivado block design.
View these procedures on GitHub in fpga/lib/utilities.tcl
.
Instantiate, Configure and Interconnect IP cores
cell
from Pavel Demin
cell xilinx.com:ip:c_counter_binary:12.0 counter {
CE true
} {
CLK adc_dac/adc_clk
}
Instantiates a binary counter from the Xilinx library with the "clock enable" option and connect its clock to the ADC clock.
The command is equivalent to:
create_bd_cell -type ip -vlnv xilinx.com:ip:c_counter_binary:12.0 counter
set_property CONFIG.CE true [get_bd_cells counter]
connect_bd_net [get_bd_pins counter/CLK] [get_bd_pins adc_dac/adc_clk]
Connect cell pins when IP core already exists
connect_cell
# Connects the output of the binary counter to the `count` pin of the status register
connect_cell counter {
Q [sts_pin count]
}
(see sts_pin
procedure below).
Connect two pins
connect_pins pin_name1 pin_name2
connect_pins counter/Q [sts_pin count]
Retrieve data from the configuration file
Get a parameter defined in config.yml
set n_adc [get_parameter n_adc]
Get info about a memory mapped region
set memory_name config
set range [get_memory_range $memory_name] ;# 4K
set offset [get_memory_offset $memory_name] ;# 0x60000000
set depth [get_memory_depth $memory_name] ;# 1024
set width [get_memory_addr_width $memory_name] ;# 10
Procedures that return a pin name
Theses procedures take pin names as inputs and output pin names, allowing to chain IP creation.
Get control/status pins defined in config.yml
ctl_pin name
, sts_pin name
# Connect DAC to config and ADC to status
for {set i 0} {$i < $n_adc} {incr i} {
connect_pins [ctl_pin dac$i] adc_dac/dac[expr $i+1]
connect_pins [sts_pin adc$i] adc_dac/adc[expr $i+1]
}
Slice a pin
get_slice_pin pin_name from to
# Connect the 8 least significant bits of the `led` control register to the port `led_o`:
connect_bd_net [get_bd_ports led_o] [get_bd_pins [get_slice_pin [ctl_pin led] 7 0]]
Create a constant
get_constant_pin value width
# Set the first DAC to 0
connect_pins adc_dac/dac0 [get_constant_pin 0 [get_parameter dac_width]]
Concatenate a list of pins
get_concat_pin pin_list
# Equivalent to bitshift: adc1 << 2
set pin [get_concat_pin [list [get_constant_pin 0 2] adc_dac/adc1]]
Perform logical operations on pins
set and_pin [get_and_pin pin1 pin2]
set or_pin [get_or_pin pin1 pin2]
set nor_pin [get_nor_pin pin1 pin2]
set not_pin [get_not_pin pin1]
Compare two pins
set ge_pin [get_GE_pin pin1 pin2] ;# pin1 >= pin2
set gt_pin [get_GT_pin pin1 pin2] ;# pin1 > pin2
set le_pin [get_LE_pin pin1 pin2] ;# pin1 <= pin2
set lt_pin [get_LT_pin pin1 pin2] ;# pin1 < pin2
set eq_pin [get_EQ_pin pin1 pin2] ;# pin1 == pin2
set ne_pin [get_NE_pin pin1 pin2] ;# pin1 != pin2