pragma HLS interface

Description

In C based design, all input and output operations are performed, in zero time, through formal function arguments. In an RTL design these same input and output operations must be performed through a port in the design interface and typically operate using a specific I/O (input-output) protocol. For more information, refer to "Managing Interfaces" in the Vivado Design Suite User Guide: High-Level Synthesis (UG902).

The INTERFACE pragma specifies how RTL ports are created from the function definition during interface synthesis.

The ports in the RTL implementation are derived from:

  • Any function-level protocol that is specified.
  • Function arguments.
  • Global variables accessed by the top-level function and defined outside its scope.

Function-level protocols, also called block-level I/O protocols, provide signals to control when the function starts operation, and indicate when function operation ends, is idle, and is ready for new inputs. The implementation of a function-level protocol:

  • Is specified by the <mode> values ap_ctrl_none, ap_ctrl_hs or ap_ctrl_chain. The ap_ctrl_hs block-level I/O protocol is the default.
  • Are associated with the function name.

Each function argument can be specified to have its own port-level (I/O) interface protocol, such as valid handshake (ap_vld) or acknowledge handshake (ap_ack). Port Level interface protocols are created for each argument in the top-level function and the function return, if the function returns a value. The default I/O protocol created depends on the type of C argument. After the block-level protocol has been used to start the operation of the block, the port-level IO protocols are used to sequence data into and out of the block.

If a global variable is accessed, but all read and write operations are local to the design, the resource is created in the design. There is no need for an I/O port in the RTL. If the global variable is expected to be an external source or destination, specify its interface in a similar manner as standard function arguments. See the examples below.

When the INTERFACE pragma is used on sub-functions, only the register option can be used. The <mode> option is not supported on sub-functions.

Tip: Vivado HLS automatically determines the I/O protocol used by any sub-functions. You cannot control these ports except to specify whether the port is registered.

Syntax

Place the pragma within the boundaries of the function.
#pragma HLS interface <mode> port=<name> bundle=<string> \
register register_mode=<mode> depth=<int> offset=<string> \
clock=<string> name=<string> \
num_read_outstanding=<int> num_write_outstanding=<int> \
max_read_burst_length=<int> max_write_burst_length=<int>
Where:
  • <mode>: Specifies the interface protocol mode for function arguments, global variables used by the function, or the block-level control protocols. For detailed descriptions of these different modes see "Interface Synthesis Reference" in the Vivado Design Suite User Guide: High-Level Synthesis (UG902). The mode can be specified as one of the following:
    • ap_none: No protocol. The interface is a data port.
    • ap_stable: No protocol. The interface is a data port. Vivado HLS assumes the data port is always stable after reset, which allows internal optimizations to remove unnecessary registers.
    • ap_vld: Implements the data port with an associated valid port to indicate when the data is valid for reading or writing.
    • ap_ack: Implements the data port with an associated acknowledge port to acknowledge that the data was read or written.
    • ap_hs: Implements the data port with associated valid and acknowledge ports to provide a two-way handshake to indicate when the data is valid for reading and writing and to acknowledge that the data was read or written.
    • ap_ovld: Implements the output data port with an associated valid port to indicate when the data is valid for reading or writing.
      Important: Vivado HLS implements the input argument or the input half of any read/write arguments with mode ap_none.
    • ap_fifo: Implements the port with a standard FIFO interface using data input and output ports with associated active-Low FIFO empty and full ports.
      Note: You can only use this interface on read arguments or write arguments. The ap_fifo mode does not support bidirectional read/write arguments.
    • ap_bus: Implements pointer and pass-by-reference ports as a bus interface.
    • ap_memory: Implements array arguments as a standard RAM interface. If you use the RTL design in Vivado IP integrator, the memory interface appears as discrete ports.
    • bram: Implements array arguments as a standard RAM interface. If you use the RTL design in Vivado IP integrator, the memory interface appears as a single port.
    • axis: Implements all ports as an AXI4-Stream interface.
    • s_axilite: Implements all ports as an AXI4-Lite interface. Vivado HLS produces an associated set of C driver files during the Export RTL process.
    • m_axi: Implements all ports as an AXI4 interface. You can use the config_interface command to specify either 32-bit (default) or 64-bit address ports and to control any address offset.
    • ap_ctrl_none: No block-level I/O protocol.
      Note: Using the ap_ctrl_none mode might prevent the design from being verified using the C/RTL co-simulation feature.
    • ap_ctrl_hs: Implements a set of block-level control ports to start the design operation and to indicate when the design is idle, done, and ready for new input data.
      Note: The ap_ctrl_hs mode is the default block-level I/O protocol.
    • ap_ctrl_chain: Implements a set of block-level control ports to start the design operation, continue operation, and indicate when the design is idle, done, and ready for new input data.
      Note: The ap_ctrl_chain interface mode is similar to ap_ctrl_hs but provides an additional input signal ap_continue to apply back pressure. Xilinx recommends using the ap_ctrl_chain block-level I/O protocol when chaining Vivado HLS blocks together.
  • port=<name>: Specifies the name of the function argument, function return, or global variable which the INTERFACE pragma applies to.
    Tip: Block-level I/O protocols (ap_ctrl_none, ap_ctrl_hs, or ap_ctrl_chain) can be assigned to a port for the function return value.
  • bundle=<string>: Groups function arguments into AXI interface ports. By default, Vivado HLS groups all function arguments specified as an AXI4-Lite (s_axilite) interface into a single AXI4-Lite port. Similarly, all function arguments specified as an AXI4 (m_axi) interface are grouped into a single AXI4 port. This option explicitly groups all interface ports with the same bundle=<string> into the same AXI interface port and names the RTL port the value specified by <string>.
  • register: An optional keyword to register the signal and any relevant protocol signals, and causes the signals to persist until at least the last cycle of the function execution. This option applies to the following interface modes:
    • ap_none
    • ap_ack
    • ap_vld
    • ap_ovld
    • ap_hs
    • ap_stable
    • axis
    • s_axilite
    Tip: The -register_io option of the config_interface command globally controls registering all inputs/outputs on the top function. Refer to Vivado Design Suite User Guide: High-Level Synthesis (UG902) for more information.
  • register_mode= <forward|reverse|both|off>: Used with the register keyword, this option specifies if registers are placed on the forward path (TDATA and TVALID), the reverse path (TREADY), on both paths (TDATA, TVALID, and TREADY), or if none of the port signals are to be registered (off). The default register_mode is both. AXI-Stream (axis) side-channel signals are considered to be data signals and are registered whenever the TDATA is registered.
  • depth=<int>: Specifies the maximum number of samples for the test bench to process. This setting indicates the maximum size of the FIFO needed in the verification adapter that Vivado HLS creates for RTL co-simulation.
    Tip: While depth is usually an option, it is required for m_axi interfaces.
  • offset=<string>: Controls the address offset in AXI4-Lite (s_axilite) and AXI4 (m_axi) interfaces.
    • For the s_axilite interface, <string> specifies the address in the register map.
    • For the m_axi interface, <string> specifies on of the following values:
      • direct: Generate a scalar input offset port.
      • slave: Generate an offset port and automatically map it to an AXI4-Lite slave interface.
      • off: Do not generate an offset port.
      Tip: The -m_axi_offset option of the config_interface command globally controls the offset ports of all M_AXI interfaces in the design.
  • clock=<name>: Optionally specified only for interface mode s_axilite. This defines the clock signal to use for the interface. By default, the AXI-Lite interface clock is the same clock as the system clock. This option is used to specify a separate clock for the AXI-Lite (s_axilite) interface.
    Tip: If the bundle option is used to group multiple top-level function arguments into a single AXI-Lite interface, the clock option need only be specified on one of the bundle members.
  • num_read_outstanding=<int>: For AXI4 (m_axi) interfaces, this option specifies how many read requests can be made to the AXI4 bus, without a response, before the design stalls. This implies internal storage in the design, a FIFO of size: num_read_outstanding*max_read_burst_length*word_size.
  • num_write_outstanding=<int>: For AXI4 (m_axi) interfaces, this option specifies how many write requests can be made to the AXI4 bus, without a response, before the design stalls. This implies internal storage in the design, a FIFO of size: num_write_outstanding*max_write_burst_length*word_size
  • max_read_burst_length=<int>: For AXI4 (m_axi) interfaces, this option specifies the maximum number of data values read during a burst transfer.
  • max_write_burst_length=<int>: For AXI4 (m_axi) interfaces, this option specifies the maximum number of data values written during a burst transfer.
  • name=<string>: This option is used to rename the port based on your own specification. The generated RTL port will use this name.

Example 1

In this example, both function arguments are implemented using an AXI4-Stream interface:

void example(int A[50], int B[50]) {
  //Set the HLS native interface types
  #pragma HLS INTERFACE axis port=A
  #pragma HLS INTERFACE axis port=B
  int i;
  for(i = 0; i < 50; i++){
    B[i] = A[i] + 5;
  }
}

Example 2

The following turns off block-level I/O protocols, and is assigned to the function return value:

#pragma HLS interface ap_ctrl_none port=return

The function argument InData is specified to use the ap_vld interface, and also indicates the input should be registered:

#pragma HLS interface ap_vld register port=InData

This exposes the global variable lookup_table as a port on the RTL design, with an ap_memory interface:

pragma HLS interface ap_memory port=lookup_table

Example 3

This example defines the INTERFACE standards for the ports of the top-level transpose function. Notice the use of the bundle= option to group signals.

// TOP LEVEL - TRANSPOSE
void transpose(int* input, int* output) {
	#pragma HLS INTERFACE m_axi port=input offset=slave bundle=gmem0
	#pragma HLS INTERFACE m_axi port=output offset=slave bundle=gmem1

	#pragma HLS INTERFACE s_axilite port=input bundle=control
	#pragma HLS INTERFACE s_axilite port=output bundle=control
	#pragma HLS INTERFACE s_axilite port=return bundle=control

	#pragma HLS dataflow

See Also