RTL Kernel Wizard

The RTL kernel wizard automates some of the steps you need to take to ensure that the RTL IP is packaged into a kernel object (XO) file that can be used by the Vitis™ compiler. The RTL Kernel wizard:

  • Steps you through the process of specifying the interface requirements for your RTL kernel, and generates a top-level RTL wrapper based on the provided information.
  • Automatically generates an AXI4-Lite interface module including the control logic and register file, included in the top level wrapper.
  • Includes an example kernel IP module in the top-level wrapper that you can replace with your own RTL IP design, after ensuring correct connectivity between your RTL IP and the wrapper.
  • Automatically generates a kernel.xml file to match the kernel specification from the wizard.
  • Generates a simple simulation test bench for the generated RTL kernel wrapper.
  • Generates an example host program to run and debug the RTL kernel.

The RTL Kernel wizard can be accessed from the Vitis IDE, or from the Vivado® IP catalog. In either case it creates a Vivado project containing an example design to act as a template for defining your own RTL kernel.

The example design consists of a simple RTL IP adder, called VADD, that you can use to guide you through the process of mapping your own RTL IP into the generated top-level wrapper. The connections include clock(s), reset(s), s_axilite control interface, m_axi interfaces, and optionally axis streaming interfaces.

The Wizard also generates a simple test bench for the generated RTL kernel wrapper, and a sample host code to exercise the example RTL kernel. This example test bench and host code must be modified to test the your RTL IP design accordingly.

Launch the RTL Kernel Wizard

The RTL Kernel Wizard can be launched from the Vitis IDE, or from the Vivado IDE.

TIP: Running the wizard from the Vitis IDE automatically imports the generated RTL kernel, and example host code, into the current application project when the process is complete.

To launch the RTL Kernel Wizard from within the Vitis IDE, select the Xilinx > RTL Kernel Wizard menu item from an open application project. For details on working with the GUI, refer to Using the Vitis IDE.

To launch the RTL Kernel Wizard from the Vivado IDE:

  1. Create a new Vivado project, select the target platform when choosing a board for the project.
  2. In the Flow Navigator, click the IP catalog command.
  3. Type RTL Kernel in the IP catalog search box.
  4. Double-click RTL Kernel Wizard to launch the wizard.

Using the RTL Kernel Wizard

The RTL Kernel wizard is organized into multiple pages that break down the process of defining an RTL kernel. The pages of the wizard include:

  1. General Settings
  2. Scalars
  3. Global Memory
  4. Streaming Interfaces
  5. Summary

To navigate between pages, click Next and Back as needed.

To finalize the kernel and build a project based on the kernel specification, click OK on the Summary page.

General Settings

The following figure shows the three settings in the General Settings page.

Figure 1: RTL Kernel Wizard General Settings Page

The following are three settings in the General Settings page.

Kernel Identification

Kernel name
The kernel name. This will be the name of the IP, top-level module name, kernel, and C/C++ functional model. This identifier shall conform to C and Verilog identifier naming rules. It must also conform to Vivado IP integrator naming rules, which prohibits underscores except when placed in between alphanumeric characters.
Kernel vendor
The name of the vendor. Used in the Vendor/Library/Name/Version (VLNV) format described in the Vivado Design Suite User Guide: Designing with IP (UG896).
Kernel library
The name of the library. Used in the VLNV. Must conform to the same identifier rules.

Kernel options

Kernel type
The RTL Kernel wizard currently supports two types of kernels: RTL, and Block Design.
RTL
The RTL type kernel consists of a Verilog RTL top-level module with a Verilog control register module and a Verilog kernel example inside the top-level module.
Block Design
The block design type kernel also delivers a Verilog top-level module, but instead it instantiates an IP integrator block diagram inside of the top-level. The block design consists of a MicroBlaze™ subsystem that uses a block RAM exchange memory to emulate the control registers. Example MicroBlaze software is delivered with the project to demonstrate using the MicroBlaze to control the kernel.
Kernel control interface
There are three types of control interfaces available for the RTL kernel. ap_ctrl_hs, ap_ctrl_chain, and ap_ctrl_none. This defines the hwControlProtocol for the <kernel> tag as described in RTL Kernel XML File.

Clock and Reset options

Number of clocks
Sets the number of clocks used by the kernel. Every RTL kernel has one primary clock called ap_clk and an optional reset called ap_rst_n. All AXI interfaces on the kernel are driven with this clock.

When setting Number of clocks to 2, a secondary clock and optional reset are provided to be used by the kernel internally. The secondary clock and reset are called ap_clk_2 and ap_rst_n_2. This secondary clock supports independent frequency scaling and is independent from the primary clock. The secondary clock is useful if the kernel clock needs to run at a faster or slower rate than the AXI4 interfaces, which must be clocked on the primary clock.

IMPORTANT: When designing with multiple clocks, proper clock domain crossing techniques must be used to ensure data integrity across all clock frequency scenarios. Refer to UltraFast Design Methodology Guide for Xilinx FPGAs and SoCs (UG949) for more information.
Has reset
Specifies whether to include a top-level reset input port to the kernel. Omitting a reset can be useful to improve routing congestion of large designs. Any registers that would normally have a reset in the design should have proper initial values to ensure correctness. If enabled, there is a reset port included with each clock. Block Design type kernels must have a reset input.

Scalars

Scalar arguments are used to pass control type information to the kernels. Scalar arguments cannot be read back from the host. For each argument that is specified, a corresponding register is created to facilitate passing the argument from software to hardware. See the following figure.

Figure 2: RTL Kernel Wizard Scalars Page
Number of scalar kernel input arguments
Specifies the number of scalar input arguments to pass to the kernel. For each number specified, a table row is generated that allows customization of the argument name and argument type. There is no required minimum number of scalars and the maximum allowed by the wizard is 64.

The following is the scalar input argument definition:

Argument name
The argument name is used in the generated Verilog control register module as an output signal. Each argument is assigned an ID value. This ID value is used to access the argument from the host software. The ID value assignments can be found on the summary page of this wizard. To ensure maximum compatibility, the argument name follows the same identifier rules as the kernel name.
Argument type
Specifies the data type, and hence bit-width, of the argument. This affects the register width in the generated RTL kernel module. The data types available are limited to the ones specified by the OpenCL C Specification Version 2.0 in "6.1.1 Built-in Scalar Data Types" section. The specification provides the associated bit-widths for each data type. The RTL wizard reserves 64 bits for all scalars in the register map regardless of their argument type. If the argument type is 32 bits or less, the RTL Wizard sets the upper 32 bits (of the 64 bits allocated) as a reserved address location. Data types that represent a bit width greater than 32 bits require two write operations to the control registers.

Global Memory

Figure 3: RTL Kernel Wizard Global Memory Page

Global memory is accessed by the kernel through AXI4 master interfaces. Each AXI4 interface operates independently of each other, and each AXI4 interface can be connected to one or more memory controllers to off-chip memory such as DDR4. Global memory is primarily used to pass large data sets to and from the kernel from the host. It can also be used to pass data between kernels. For recommendations on how to design these interfaces for optimal performance, see Memory Performance Optimizations for AXI4 Interface.

TIP: For each interface, the RTL Kernel wizard generates example AXI master logic in the top-level wrapper to provide a starting point that can be discarded if not needed.
Number of AXI master interfaces
Specify the number of interfaces present on the kernel. The maximum is 16 interfaces. For each interface, you can customize an interface name, data width, and the number of associated arguments. Each interface contains all read and write channels. The default names proposed by the RTL kernel wizard are m00_axi and m01_axi. If not changed, these names will have to be used when assigning an interface to global memory as described in Mapping Kernel Ports to Memory.

AXI master definition (table columns)

Interface name
Specifies the name of the interface. To ensure maximum compatibility, the argument name follows the same identifier rules as the kernel name.
Width (in bytes)
Specifies the data width of the AXI data channels. Xilinx recommends matching to the native data width of the memory controller AXI4 slave interface. The memory controller slave interface is typically 64 bytes (512 bits) wide.
Number of arguments
Specifies the number of arguments to associate with this interface. Each argument represents a data pointer to global memory that the kernel can access.

Argument definition

Interface
Specifies the name of the AXI Interface. This value is copied from the interface name defined in the table, and cannot be modified here.
Argument name
Specifies the name of the pointer argument as it appears on the function prototype signature. Each argument is assigned an ID value. This ID value is used to access the argument from the host software as described in Host Programming. The ID value assignments can be found on the summary page of this wizard. To ensure maximum compatibility, the argument name follows the same identifier rules as the kernel name. The argument name is used in the generated RTL kernel control register module as an output signal.

Streaming Interfaces

The streaming interfaces page allows configuration of AXI4-Stream interfaces on the kernel. Streaming interfaces are only available on select platforms and if the chosen platform does not support streaming, then the page does not appear. Streaming interfaces are used for direct host-to-kernel and kernel-to-host communication, as well as continuously operating kernels as described in Streaming Data Transfers.

Figure 4: RTL Kernel Wizard Streaming Interfaces Page
Number of AXI4-Stream interfaces
Specifies the number of AXI4-Stream interfaces that exist on the kernel. A maximum of 32 interfaces can be enabled per kernel. Xilinx recommends keeping the number of interfaces as low as possible to reduce the amount of area consumed.
Name
Specifies the name of the interface. To ensure maximum compatibility, the argument name follows the same identifier rules as the kernel name.
Mode
Specifies whether the interface is a master or slave interface. An AXI4-Stream slave interface is a read-only interface, and the RTL kernel can be sent data with the clWriteStream API from the host program. An AXI4-Stream master interface is a write-only interface, and the host program can receive data through the interface with the clReadStream API.
Width (bytes)
Specifies the TDATA width (in bytes) of the AXI4-Stream interface. This interface width is limited to 1 to 64 bytes in powers of 2.

The streaming interface uses the TDATA/TKEEP/TLAST signals of the AXI4-Stream protocol. Stream transactions consists of a series of transfers where the final transfer is terminated with the assertion of the TLAST signal. Stream transfers must adhere to the following:

  • AXI4-Stream transfer occurs when TVALID/TREADY are both asserted.
  • TDATA must be 8, 16, 32, 64, 128, 256, or 512 bits wide.
  • TKEEP (per byte) must be all 1s when TLAST is 0.
  • TKEEP can be used to signal a ragged tail when TLAST is 1. For example, on a 4-byte interface, TKEEP can only be 0b0001, 0b0011, 0b0111, or 0b1111 to specify the last transfer is 1-byte, 2 bytes, 3 bytes, or 4 bytes in size, respectively.
  • TKEEP cannot be all zeros (even if TLAST is 1).
  • TLAST must be asserted at the end of a packet.
  • TREADY input/TVALID output should be low if kernel is not started to avoid lost transfers.

Summary

This section summarizes the VLNV for the RTL kernel IP, the software function prototype, and hardware control registers created from options selected in the previous pages. The function prototype conveys what a kernel call would be like if it was a C function. See the host code generated example of how to set the kernel arguments for the kernel call. The register map shows the relationship between the host software ID, argument name, hardware register offset, type, and associated interface. Review this section for correctness before proceeding to generate the kernel.

Figure 5: Kernel Wizard Summary Page

Click OK to generate the top-level wrapper for the RTL kernel, the VADD temporary RTL kernel IP, the kernel.xml file, the simulation test bench, and the example host.cpp code. After these files are created, the RTL Kernel wizard opens a project in the Vivado Design Suite to let you complete kernel development.

Using the RTL Kernel Project in Vivado IDE

If you launched the RTL Kernel wizard from the Vitis IDE, after clicking OK on the Summary page, the Vivado Design Suite open with an example IP project to let you complete your RTL kernel code.

If you launched the RTL Kernel wizard from within the Vivado IP catalog, after clicking OK on the Summary page, an RTL Kernel Wizard IP is instantiated into your current project. From there you must take the following steps:

  1. When the Generate Output Products dialog box appears, click Skip to close it.
  2. Right-click the <kernel_name>.xci file that is added to the Sources view, and select Open IP Example Design.
  3. In the Open Example Design dialog box, specify the Example project directory, or accept the default value, and click OK.
    TIP: An example project is created for the RTL kernel IP. This example IP project is the same as the example project created if you launch the RTL Kernel wizard from the Vitis IDE, and is where you will complete the development work for your kernel.
  4. You can now close the original Vivado project from which you launched the RTL Kernel wizard.

Depending on the Kernel Type you selected for the kernel options, the example IP project is populated with a top-level RTL kernel file that contains either a Verilog example and control registers as described in RTL Type Kernel Project, or an instantiated IP integrator block design as described in Block Design Type Kernel Project. The top-level Verilog file contains the expected input/output signals and parameters. These top-level ports are matched to the kernel specification file (kernel.xml) and can be combined with your RTL code, or /block design, to complete the RTL kernel.

The AXI4 interfaces defined in the top-level file contain a minimum subset of AXI4 signals required to generate an efficient, high throughput interface. Signals that are not present inherit optimized defaults when connected to the rest of the AXI system. These optimized defaults allow the system to omit AXI features that are not required, saving area and reducing complexity. If your RTL code or block design contains AXI signals that were omitted, you can add these signals to the ports in the top-level RTL kernel file, and the IP packager will adapt to them appropriately.

The next step in the process customizes the contents of the kernel and then packages those contents into a Xilinx Object (xo) file.

RTL Type Kernel Project

The RTL type kernel delivers a top-level Verilog design consisting of control register and the Vadd sub-modules example design. The following figure illustrates the top-level design configured with two AXI4-master interfaces. Care should be taken if the Control Register module is modified to ensure that it still aligns with the kernel.xml file located in the imports directory of the Vivado kernel project. The example block can be replaced with your custom logic or used as a starting point for your design.

Figure 6: Kernel Type RTL Top

The Vadd example block, shown in the following figure, consists of a simple adder function, an AXI4 read master, and an AXI4 write master. Each defined AXI4 interface has independent example adder code. The first associated argument of each interface is used as the data pointer for the example. Each example reads 16 KB of data, performs a 32-bit add one operation, and then writes out 16 KB of data back in place (the read and write address are the same).

Figure 7: Kernel Type RTL Example

The following table describes some important files in the example IP project, relative to the root of the Vivado project for the kernel, where <kernel_name> is the name of the kernel you specified in the RTL Kernel wizard.

Table 1. RTL Kernel Wizard Source and Test Bench File
Filename Description Delivered with Kernel Type
<kernel_name>_ex.xpr Vivado project file All
imports directory
<kernel_name>.v Kernel top-level module All
<kernel_name>_control_s_axi.v RTL control register module RTL
<kernel_name>_example.sv RTL example block RTL
<kernel_name>_example_vadd.sv RTL example AXI4 vector add block RTL
<kernel_name>_example_axi_read_master.sv RTL example AXI4 read master RTL
<kernel_name>_example_axi_write_master.sv RTL example AXI4 write master RTL
<kernel_name>_example_adder.sv RTL example AXI4-Stream adder block RTL
<kernel_name>_example_counter.sv RTL example counter RTL
<kernel_name>_exdes_tb_basic.sv Simulation test bench All
<kernel_name>_cmodel.cpp Software C-Model example for software emulation. All
<kernel_name>_ooc.xdc Out-of-context Xilinx constraints file All
<kernel_name>_user.xdc Xilinx constraints file for kernel user constraints. All
kernel.xml Kernel description file All
package_kernel.tcl Kernel packaging script proc definitions All
post_synth_impl.tcl Tcl post-implementation file All
exports directory
src/host_example.cpp Host code example All
makefile Makefile example All

Block Design Type Kernel Project

The block design type kernel delivers an IP integrator block design (.bd) at the top-level of the example project. A MicroBlaze processor subsystem is used to sample the control registers and to control the flow of the kernel. The MicroBlaze processor system uses a block RAM as an exchange memory between the host and the kernel instead of a register file.

Figure 8: Block Design Type Kernel

For each AXI interface, a DMA and math operation sub-blocks are created to provide an example of how to control the kernel execution. The example uses the MicroBlaze AXI4-Stream interfaces to control the AXI Data Mover IP to create an example identical to the one in the RTL kernel type. Also, included is a Vitis IDE project to compile and link an ELF file for the MicroBlaze core. This ELF file is loaded into the Vivado kernel project and initialized directly into the MicroBlaze instruction memory.

The following steps can be used to modify the MicroBlaze processor program:

  1. If the design has been updated, you might need to run the Export Hardware option. The option can be found in the File > Export > Export Hardware menu location. When the Export Hardware dialog opens, click OK.
  2. The core development kit application can now be invoked. Select Tools > Launch Vitis from the main menu.
  3. When the Vitis IDE opens, click X just to the right of the text on the Welcome tab to close the welcome dialog box. This shows an already loaded Vitis IDE project underneath.
  4. From the Project Explorer, the source files are under the <Kernel Name>_control/src section. Modify these as appropriate.
  5. When updates are complete, compile the source by selecting the menu option Project > Build All > Check for errors/warnings and resolve if necessary. The ELF file is automatically updated in the IDE.
  6. Run simulation to test the updated program and debug if necessary.

Simulation Test Bench

A SystemVerilog test bench is generated for simulating the example IP project. This test bench exercises the RTL kernel to ensure its operation is correct. It is populated with the checker function to verify the add one operation.

This generated test bench can be used as a starting point in verifying the kernel functionality. It writes/reads from the control registers and executes the kernel multiple times while also including a simple reset test. It is also useful for debugging AXI issues, reset issues, bugs during multiple iterations, and kernel functionality. Compared to hardware emulation, it executes a more rigorous test of the hardware corner cases, but does not test the interaction between host code and kernel.

To run a simulation, click Vivado Flow Navigator > Run Simulation located on the left hand side of the GUI and select Run Behavioral Simulation. If behavioral simulation is working as expected, a post-synthesis functional simulation can be run to ensure that synthesis results are matched with the behavioral model.

Out-of-Context Synthesis

The Vivado kernel project is configured to run synthesis and implementation in out-of-context (OOC) mode. A Xilinx Design Constraints (XDC) file is populated in the design to provide default clock frequencies for this purpose.

You should always synthesize the RTL kernel before packaging it with the package_xo command. Running synthesis is useful to determine whether the kernel synthesizes without errors. It also provides estimates of resource utilization and operating frequency. Without pre-synthesizing the RTL kernel you could encounter errors during the v++ linking process, and it could be much harder to debug the cause.

To run OOC synthesis, click Run Synthesis from the Vivado Flow Navigator > Synthesis menu.

The synthesized outputs can also be used to package the RTL kernel with a netlist source, instead of RTL source.

IMPORTANT: A block design type kernel must be packaged as a netlist using the package_xo command.

Software Model and Host Code Example

A C++ software model of the add one example operation,<kernel_name>_cmodel.cpp, is provided in the ./imports directory. This software model can also be modified to model the function of your kernel. When running package_xo, this model can be included with the kernel source files to enable software emulation for the kernel. The hardware emulation and system builds always use the RTL description of the kernel.

In the ./exports/src directory, an example host program is provided and is called host_example.cpp. The host program takes the binary container as an argument to the program. The host code loads the binary as part of the init function. The host code instantiates the kernel, allocates the buffers, sets the kernel arguments, executes the kernel, and then collects and checks the results for the example add one function.

For information on using the host program and kernel code in an application, refer to Creating a Vitis IDE Project.

Generate RTL Kernel

After the kernel is designed and tested in the example IP project in the Vivado IDE, the final step is to generate the RTL kernel object (XO) file for use by the Vitis compiler.

Click the Generate RTL Kernel command from the Vivado Flow Navigator > Project Manager menu. The Generate RTL Kernel dialog box opens with three main packaging options:

Sources only kernel
Packages the kernel using the RTL design sources directly.
Pre-synthesized kernel
Packages the kernel with the RTL design sources with a synthesized cached output that can be used later on in the flow to avoid re-synthesizing. If the target platform changes, the packaged kernel might fall back to the RTL design sources instead of using the cached output.
Netlist (DCP) based kernel
Packages the kernel as a block box, using the netlist generated by the synthesized output of the kernel. This output can be optionally encrypted if necessary. If the target platform changes, the kernel might not be able to re-target the new device and it must be regenerated from the source. If the design contains a block design, the netlist (DCP) based kernel is the only packaging option available.

Optionally, the Software Emulation Sources field lets you specify a software model for your kernel that can be used during software emulation. If the software model contains multiple files, provide a space in between each file in the Source files list, or use the GUI to select multiple files using the CTRL key when selecting the file.

After you click OK, the kernel output products are generated. If the pre-synthesized kernel or netlist kernel option is chosen, then synthesis can run. If synthesis has previously run, it uses those outputs, regardless if they are stale. The kernel Xilinx Object (XO) file is generated in the exports directory of the Vivado kernel project.

At this point, you can close the Vivado kernel project. If the Vivado kernel project was invoked from the Vitis IDE, the example host code called host_example.cpp and kernel Xilinx Object (XO) files are automatically imported into the ./src folder of the application project in the Vitis IDE.

Modifying an Existing RTL Kernel Generated from the Wizard

From the Vitis IDE, you can modify an existing RTL kernel by selecting it from the ./src folder of an application project where it is in use. Right-click the XO file in the Project Explorer view, and select RTL Kernel Wizard. The Vitis IDE attempts to open the Vivado project for the selected RTL kernel.

TIP: If the Vitis IDE is unable to find the Vivado project, it returns an error and does not let you edit the RTL kernel.

A dialog box opens displaying two options to edit an existing RTL kernel. Selecting Edit Existing Kernel Contents re-opens the Vivado Project, letting you modify and regenerate the kernel contents. Selecting Re-customize Existing Kernel Interfaces opens the RTL Kernel wizard. Options other than the Kernel Name can be modified, and the previous Vivado project is replaced.

IMPORTANT: All files and changes in the previous Vivado project are lost when the updated RTL kernel project is created.