Block-Level Control Protocols - 2023.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
Release Date
2023.1 English

The execution mode of a Vitis kernel or Vivado IP is defined by the block-level control protocol and the structure of sub-functions within the HLS design. For control-driven TLP the ap_ctrl_chain and ap_ctrl_hs protocols support both sequential or pipelined execution. For data-driven TLP ap_ctrl_none is the required control protocol.

The ap_ctrl_chain control protocol is the default for the Vitis kernel flow as explained in Interfaces for Vitis Kernel Flow. The ap_ctrl_hs block-level control protocol is the default for the Vivado IP flow as described in Interfaces for Vivado IP Flow. However, you should use ap_ctrl_chain when chaining HLS designs together to better support pipelined execution.

You can specify the block-level control protocol on the function return using the INTERFACE pragma or directive. If the C/C++ code does not return a value, you can still specify the control protocol on the function return. If the C/C++ code uses a function return, Vitis HLS creates an output port ap_return for the return value.
Tip: When the function return is specified as an AXI4-Lite interface (s_axilite) all the ports in the control protocol are bundled into the s_axilite interface. This is a common practice for software-controllable kernels or IP when an application or software driver is used to configure and control when the block starts and stops operation. This is a requirement of XRT and the Vitis kernel flow.


The following figure shows the behavior of the block-level handshake signals created by the ap_ctrl_chain control protocol for a sequential execution. In the following figure, the first transaction of the HLS design completes, and the second transaction starts immediately because ap_continue is High when ap_done is High. However, the design halts at the end of the second transaction until ap_continue is asserted High.

Figure 1. Behavior of ap_ctrl_chain Interface
The timing diagram displays the following behavior after reset occurs:
  1. The block waits for ap_start to go High before it begins operation.
  2. Output ap_idle goes Low immediately to indicate the design is no longer idle.
  3. The ap_start signal must remain High until ap_ready goes High. Once ap_ready goes High:
    • If ap_start remains High the design will start the next transaction.
    • If ap_start is taken Low, the design will complete the current transaction and halt operation.
  4. Data can be read on the input ports.
  5. Data can be written to the output ports.
    Note: The input and output ports can also specify a port-level I/O protocol that is independent of the control protocol. For details, see Port-Level Protocols for Vivado IP Flow.
  6. Output ap_done goes High when the block completes operation.
    Note: If there is an ap_return port, the data on this port is valid when ap_done is High. Therefore, the ap_done signal also indicates when the data on output ap_return is valid.
  7. The ap_ctrl_chain control protocol provides an active-High ap_continue signal that indicates when the downstream block that consumes the output data is ready for new data inputs. This allows the downstream block to provide back-pressure to prevent the flow of data.
    • If the ap_continue signal is High when ap_done is High, the design continues operating.
    • If the downstream block is not able to consume new data inputs, the ap_continue signal is Low. If the ap_continue signal is Low when ap_done is High, the design stops operating, the ap_done signal remains High waiting for ap_continue to go High.
  8. When the design is ready to accept new inputs, the ap_ready signal is pulsed High for one clock cycle. The ap_ready port of a downstream block can directly drive the ap_continue port. Following is additional information about the ap_ready signal:
    • The ap_ready signal is inactive until the design starts operation.
    • In non-pipelined designs, the ap_ready signal is asserted at the same time as ap_done.
    • In pipelined designs, the ap_ready signal might go High at any cycle after ap_start is sampled High. This depends on how the design is pipelined.
    • If ap_start remains high after ap_ready goes high, the next transaction starts immediately.
    • When ap_start goes low right after ap_ready goes high, the design keeps executing until ap_done is high and then stops operation, unless ap_start goes high again in the meantime, which starts a new transaction.
  9. The ap_idle signal indicates when the design is idle and not operating. Following is additional information about the ap_idle signal:
    • If the ap_start signal is Low when ap_ready is High, the design stops operation, and the ap_idle signal goes High one cycle after ap_done.
    • If the ap_start signal is High when ap_ready is High, the design continues to operate, and the ap_idle signal remains Low.


The ap_ctrl_hs control protocol has the same signals as ap_ctrl_chain, but sets the ap_continue signal to 1 so it remains high. This control protocol supports sequential and pipelined execution modes, but does not offer back-pressure from downstream design modules to control the flow of data.


ap_ctrl_none also has the same signals as ap_ctrl_chain, but the handshake signal ports (ap_start, ap_idle, ap_ready, and ap_done) are set high and optimized away.

An ap_ctrl_none region, or one or more hls::tasks, can be instantiated in one of two ways:

  • Either with only ap_ctrl_none regions all the way to the top, including the top (i.e. no sequential FSM or non-ap_ctrl_none dataflow anywhere above, even due to a coding mistake),
  • Or in a dataflow region where:
    • its input streams are produced by one or more non-ap_ctrl_none processes or regions that are called before it
    • its output streams are consumed by one or more non-ap_ctrl_none processes or regions that are called after it

The former enables the elimination of the ap_start/ap_ready/ap_done/ap_continue handshakes all the way to the top. The latter enables the generation of the ap_start/ap_ready handshake for the dataflow region above by the predecessor processes or regions, and of the ap_done/ap_continue handshake by the successor processes or regions.

Important: If you use the ap_ctrl_none control protocol in your design, you must meet at least one of the conditions for C/RTL co-simulation as described in Interface Synthesis Requirements to verify the RTL design. If at least one of these conditions is not met, C/RTL co-simulation halts with the following message:
@E [SIM-345] Cosim only supports the following 'ap_ctrl_none' designs: (1) 
combinational designs; (2) pipelined design with task interval of 1; (3) designs with 
array streaming or hls_stream ports.
@E [SIM-4] *** C/RTL co-simulation finished: FAIL ***