Packaging the RTL Code as a Vitis XO - 2023.2 English

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

Document ID
UG1393
Release Date
2023-12-13
Version
2023.2 English
Important: The RTL IP should first be thoroughly verified with traditional RTL verification methods before being packaged as a kernel.

As discussed in Kernel Interface Requirements, the RTL kernel must be packaged with the following required interfaces:

  • The AXI4-Lite interface name must be packaged as S_AXI_CONTROL, but the underlying AXI ports can be named differently.
  • Any memory-mapped AXI4 interfaces must be packaged as AXI4 master endpoints with 64-bit address support.
  • You can also implement the AXI4-Stream interface.
  • At least one clock is required for the kernel, though it can support multiple clocks.
    • Each clock must have an associated Bus Interface identifying it as a clock.
    • Each clock can have an optional active-Low reset, specified by the ASSOCIATED_RESET property on the clock.
    • A clock must be associated with each AXI4-Lite, AXI4, and AXI4-Stream interface on the kernel.

To package the IP, use the following steps:

  1. Create and package a new IP.
    1. From a Vivado project, with your RTL source files added, select Tools > Create and Package New IP.
    2. Select Package your current project, and click Next.
    3. Specify the location for your packaged IP. You can select the default location, or choose a different location.
    4. Review the Summary page and click Finish to open the Package IP window.

    The Package IP window opens to display the Identification page. For details on working with the IP packager in the Vivado tool, refer to the Vivado Design Suite User Guide: Creating and Packaging Custom IP (UG1118).

  2. Select Compatibility under the Packaging Steps. This displays the Compatibility view as shown in the following figure.

    1. Select the Package for Vitis check box to enable the process of packaging the RTL IP as an XO for use in the Vitis environment.
    2. Select the Control Protocol for the RTL Kernel. This determines the control mechanism used to operate the kernel. The choices are:
      • user_managed: Defines a SW-controllable kernel, that is user-managed rather than XRT-managed. This is the preferred option. Refer to Creating User-Managed RTL Kernels for additional information.
      • ap_ctrl_hs: This is the default, and specifies the simple sequential execution model for XRT -managed kernels as described in SW-Controllable Kernels.
      • ap_ctrl_chain: Specifies a pipelined execution model for XRT-managed kernels.
      • ap_ctrl_none: Indicates no control protocol as described in Data Driven Kernels.
    3. Check to ensure that both Package for IPI and Ignore Freq_Hz are enabled as well.

    Enabling these check boxes enables design rule checks (DRC) that the ipx::check_integrity command runs prior to packaging the IP and generating the XO. The DRCs include checks for required signals as described in Requirements of an RTL Kernel, and checks for control protocols and registers for XRT-managed kernels . As shown in the preceding figure, any issues are reported to the Package IP tool as they are encountered.

  3. Associate the clock to the AXI interfaces.

    Select the Ports and Interfaces step of the Package IP window, you can associate the primary kernel clock with the AXI4 interfaces, and reset signal if needed.

    1. Right-click an AXI4 interface, and select Associate Clocks.

      This opens the Associate Clocks dialog box which lists any identified clock signals.

    2. Select the appropriate clock and click OK to associate it with the interface.
    3. Ensure to repeat this step to a clock signal with each of the AXI interfaces.
  4. Click the Addressing and Memory step to add control registers and offsets.

    XRT-managed kernels using the ap_ctrl_hs or ap_ctrl_chain control protocol require control registers as discussed in Control Requirements for XRT-Managed Kernels. The following table shows a list of the required registers.

    Tip: While ap_ctrl_none and user_managed control protocols do not require control registers, they can still use them if an s_axilite interface is included as part of the RTL design. In this case, the specific registers can differ from the following table, but the process of assigning names, offsets, and widths is the same.
    Table 1. Address Map
    Register Name Description Address Offset Size
    CTRL Control Signals as described in Control Requirements for XRT-Managed Kernels. 0x000 32
    GIER Global Interrupt Enable Register. Used to enable interrupt to the host. 0x004 32
    IP_IER IP Interrupt Enable Register. Used to control which IP generated signal are used to generate an interrupt. 0x008 32
    IP_ISR IP Interrupt Status Register. Provides interrupt status. 0x00C 32
    <kernel_args> This includes a separate entry for each kernel argument as needed on the software function interface. All user-defined registers must begin at location 0x10; locations below this are reserved. 0x010 32/64

    Scalar arguments are 32-bits wide.m_axi and axis interfaces are 64 bits wide.

    1. To create the address map described in the table, right-click in the Address Blocks and select the Add Register command.

      This opens the Add Register view in which you can enter one of the register names from the table above.

      Important: The Range value under Address Blocks specifies the address range for the s_axilite interface. You can modify this value to change the range for the kernel.
    2. Repeat as needed to add all required registers.
      This creates a Registers table in the Addressing and Memory section. You can edit the table to add the Description, Address Offset, and Size to each register. The Registers table should look similar to the following example.

      Tip: The Tcl commands for each step of this process are written to the Tcl Console. You can use this fact to execute the process, and then use the Tcl transcript to create scripts to automate the process for future iterations.
    3. Finally, select the register for each of the pointer arguments from your table, right-click and select the Add Register Parameter command. Enter the name ASSOCIATED_BUSIF into the dialog box that opens, and click OK.

      This lets you define an association between the register and the AXI4 Interface. In the value field of the added parameter, enter the name of the m_axi interface assigned to the specific argument you are defining. In the example above, the argument A uses the m00_axi interface, and the argument B uses the m01_axi interface.

  5. At this point you should be ready to package your IP.
    1. Select the Review and Package section of the Package IP view, review the Summary and After Packaging sections, and make whatever changes are needed.
      Important: You must enable the generation of an IP archive file. If the After Packaging section indicates An archive will not be generated, you must select the Edit packaging settings link and enable the Create archive of IP setting.
    2. When you are ready, click Package IP.

      The Vivado tool packages your kernel IP, automatically runs the package_xo command as needed to produce the XO file, and opens a dialog box to inform you of success.

      The generated XO file for the RTL kernel can be used by the Vitis compiler during the linking process to connect to other HLS or RTL kernels, and for linking with the target platform to complete the system. Refer to Building and Running the System for more information.

    3. If your RTL kernel has some custom features that are not standard for the package_xo command that is run automatically, you can run the command manually to regenerate the XO file and kernel with custom settings. Refer to package_xo Command for details of the command. Some specific reasons why you might need to manually run the package_xo command include:
      • Specify a different IP directory or XO path
      • Output a copy of the kernel.xml file to modify it and repackage
      • Include a C-model using the package_xo -kernel_files option to enable software emulation for your RTL kernel as described in Adding C-Models to RTL Kernels
  6. Optional: Test the Packaged IP.

    To test if the RTL kernel is packaged correctly for the IP integrator, try to instantiate the packaged kernel IP into a block design in the IP integrator. For information on the tool, refer to Vivado Design Suite User Guide: Designing IP Subsystems Using IP Integrator (UG994).

    The kernel IP should show the various interfaces described above. Examine the IP in the canvas view. The properties of the AXI interface can be viewed by selecting the interface on the canvas. Then in the Block Interface Properties view, select the Properties tab and expand the CONFIG table entry. If an interface is to be read-only or write-only, the unused AXI channels can be removed and the READ_WRITE_MODE is set to read-only or write-only.

  7. Optional: Configure Design Constraints.

    If the RTL kernel has design constraints (.xdc) which refer to elements of the static region of the platform, such as clocks, then the constraint file needs to be marked as late processing order to ensure RTL kernel constraints are correctly applied.

    There are two methods to mark constraints for late processing:

    1. If the constraints are given in a .ttcl file, add <: setFileProcessingOrder "late" :> to the .ttcl preamble section of the file as follows:
      <: set ComponentName [getComponentNameString] :>
      <: setOutputDirectory "./" :>
      <: setFileName $ComponentName :>
      <: setFileExtension ".xdc" :>
      <: setFileProcessingOrder "late" :>
      
    2. If constraints are defined in an .xdc file, then add the following four lines starting at <spirit:define> in the component.xml. The four lines in the component.xml need to be next to the area where the .xdc file is called. In the following example, my_ip_constraint.xdc file is being called with the subsequent late processing order defined.
      <spirit:file>
              <spirit:name>ttcl/my_ip_constraint.xdc</spirit:name>
              <spirit:userFileType>ttcl</spirit:userFileType>
              <spirit:userFileType>USED_IN_implementation</spirit:userFileType>
              <spirit:userFileType>USED_IN_synthesis</spirit:userFileType>
              <spirit:define>
                   <spirit:name>processing_order</spirit:name>
                   <spirit:value>late</spirit:value>
              </spirit:define>
      </spirit:file>