The handling of clocks in accelerator cards has evolved to support multiple platform clocks and clock frequencies. The kernels can have any number of independent and edge-aligned clocks, and platforms can have multiple kernels running at different clock frequencies under user-control. A platform can have scalable clocks and fixed clocks.
- Scalable Clocks
-
An Alveo™ platform provides a frequency scalable kernel clock with ID 0 that drives all XRT managed kernels. XRT can set the clock frequency of this clock according to the meta-data contained in the xclbin file, when loading the file. An Alveo platform also provides a second scalable clock with ID 1 that is XRT also controllable based on xclbin meta-data. You do not need to provide an option to connect to scalable clocks, but you can specify the clock frequency during
v++
linking using the--kernel_frequency
command, as described in v++ General Options. For example, thev++
linker will automatically wire kernel clocksap_clk
to clock ID 0, andap_clk2
to clock ID 1.Tip: In practice,ap_clk2
is primarily found on RTL kernels, because Vitis HLS does not generate kernels with multiple clocks. - Fixed Clocks
-
You can generate any number of derived fixed clocks that are not controllable by XRT. The
v++
linker provides the --clock Options for users to specify which kernel clock pins should be connected to which clocks, and to define clock frequencies that are not defined on the platform. Fixed clocks are more commonly used for embedded platforms and RTL kernels.Specifying the
--clock
options directsv++
to use the fixed clocks of a platform, rather then the scalable clocks. For HLS kernels, the clock ID 0 is always used. For RTL kernels with one clock, clock ID 0 is used by default, but you can select a different clock.
Scalable clocks can be used to scale the clock itself whereas fixed clocks are used to add MMCMs to generate frequencies other than the frequencies defined on the platform. For example, if you choose to specify clock frequencies: 60, 200, and 450, Vitis will add all the necessary logic to generated the required clocks.
If Vivado place and route tools
are unable to meet the frequency specification, the tools can scale the clock frequency
to an achievable frequency if the scalable clock has been used (--kernel_frequency
). If a fixed clock is used (--clock
), then you will need to re-run the implementation
to update the frequency target.
platforminfo
command. For example, the following
command returns verbose information related to a newer shell for the U250 platform:
platforminfo -v -p xilinx_u250_gen3x16_xdma_3_1_202020_1 -o pfmClocks.txt
=================
Clock Information
=================
Default Clock Index: 0
Default Clock Frequency: 300.000000
Default Clock Pretty Name: PL 0
Clock Index: 0
Frequency: 300.000000
Name: ss_ucs_aclk_kernel_00
Pretty Name: PL 0
Inst Ref: ss_ucs
Comp Ref: shell_ucs_subsystem
Period: 3.333333
Normalized Period: .003333
Status: scalable
Clock Index: 1
Frequency: 500.000000
Name: ss_ucs_aclk_kernel_01
Pretty Name: PL 1
Inst Ref: ss_ucs
Comp Ref: shell_ucs_subsystem
Period: 2.000000
Normalized Period: .002000
Status: scalable
Clock Index: 2
Frequency: 50.000000
Name: ii_level1_wire_ulp_m_aclk_ctrl_00
Pretty Name: PL 2
Inst Ref: ii_level1_wire
Comp Ref: ii_level1_wire
Period: 20.000000
Normalized Period: .020000
Status: fixed
Clock Index: 3
Frequency: 250.000000
Name: ii_level1_wire_ulp_m_aclk_pcie_user_00
Pretty Name: PL 3
Inst Ref: ii_level1_wire
Comp Ref: ii_level1_wire
Period: 4.000000
Normalized Period: .004000
Status: fixed
Clock Index: 4
Frequency: 100.000000
Name: ii_level1_wire_ulp_m_aclk_freerun_ref_00
Pretty Name: PL 4
Inst Ref: ii_level1_wire
Comp Ref: ii_level1_wire
Period: 10.000000
Normalized Period: .010000
Status: fixed
The following are some examples of clock management using the --clock Options in increasing order of precedence:
- In absence of any
--clock
option, a scalable default clock will be applied. For kernels with two clocks clock ID 0 will be assigned to ap_clk, and clock ID 1 will be assigned to ap_clk_2. - Specifying
--clock.defaultId=<id>
overrides the platform default. The specified clock <id> will be used as a reference clock for all pins on all CUs, unless additional--clock
options are specified. - Specifying
--clock.defaultFreq=<Hz>
overrides platform default with a clock of the specified frequency. The default clock will be assigned to all pins on all CUs, unless additional--clock
options are specified. - Specifying
--clock.id=<id>:<cu>
assigns the specified ID to all clock pins on the specified CU. - Specifying
--clock.id=<id>:<cu>.<clk0>
assigns the specified ID to the specified clock pin on the specified CU.
There are a couple of high-level considerations in practice. Scalable clocks help you to achieve timing without having to regenerate the .xclbin file, by allowing the tool to scale the clock as needed to achieve a specific frequency or to meet timing.
Designs requiring different kernels to run at different clock rates, e.g., to
close timing or to meet performance targets require the --clock
directive that targets fixed clocks. Similarly, RTL kernels
requiring multiple clocks, in general, require the --clock
directives. For most serious designs, the expectation is that the
user will at some point know what their achievable frequency targets are, and will need
to specify these (fixed clocks) when they exceed the scalable clock frequencies (scaling
will not increase a scaled clock frequency above the platform default).