Identifying Platform Clocks - 2022.1 English

Vitis Unified Software Platform Documentation: Application Acceleration Development (UG1393)

Document ID
UG1393
Release Date
2022-05-25
Version
2022.1 English

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 Vitis Compiler General Options. For example, the v++ linker will automatically wire kernel clocks ap_clk to clock ID 0, and ap_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 directs v++ 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.

Tip: You cannot mix fixed and scalable clocks on a single kernel, but these can be mixed across different kernels within a single .xclbin file.

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.

You can determine the clocks available in the target platform by using the 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
The information reported in the output file includes the following clock details:
=================
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).