Controlling Hardware - 2021.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2021-06-16
Version
2021.1 English
Tip: The example provided below demonstrates the ap_ctrl_hs block control protocol, which is the default for the Vivado IP flow. Refer to Block-Level Control Protocols for more information and a description of the ap_ctrl_chain protocol which is the default for the Vitis kernel flow.

In this example, the hardware header file xexample_hw.h provides a complete list of the memory mapped locations for the ports grouped into the AXI4-Lite slave interface, as described in S_AXILITE Control Register Map.

// 0x00 : Control signals
//        bit 0  - ap_start (Read/Write/SC)
//        bit 1  - ap_done (Read/COR)
//        bit 2  - ap_idle (Read)
//        bit 3  - ap_ready (Read)
//        bit 7  - auto_restart (Read/Write)
//        others - reserved
// 0x04 : Global Interrupt Enable Register
//        bit 0  - Global Interrupt Enable (Read/Write)
//        others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
// 0x0c : IP Interrupt Status Register (Read/TOW)
//        bit 0  - Channel 0 (ap_done)
//        others - reserved
// 0x10 : Data signal of a
//        bit 7~0 - a[7:0] (Read/Write)
//        others  - reserved
// 0x14 : reserved
// 0x18 : Data signal of b
//        bit 7~0 - b[7:0] (Read/Write)
//        others  - reserved
// 0x1c : reserved
// 0x20 : Data signal of c_i
//        bit 7~0 - c_i[7:0] (Read/Write)
//        others  - reserved
// 0x24 : reserved
// 0x28 : Data signal of c_o
//        bit 7~0 - c_o[7:0] (Read)
//        others  - reserved
// 0x2c : Control signal of c_o
//        bit 0  - c_o_ap_vld (Read/COR)
//        others - reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on 
Handshake)

To correctly program the registers in the s_axilite interface, you must understand how the hardware ports operate with the default port protocols, or the custom protocols as described in S_AXILITE and Port-Level Protocols.

For example, to start the block operation the ap_start register must be set to 1. The device will then proceed and read any inputs grouped into the AXI4-Lite slave interface from the register in the interface. When the block completes operation, the ap_done, ap_idle and ap_ready registers will be set by the hardware output ports and the results for any output ports grouped into the AXI4-Lite slave interface read from the appropriate register.

The implementation of function argument c in the example highlights the importance of some understanding how the hardware ports operate. Function argument c is both read and written to, and is therefore implemented as separate input and output ports c_i and c_o, as explained in S_AXILITE Example.

The first recommended flow for programing the s_axilite interface is for a one-time execution of the function:

  • Use the interrupt function standard API implementations provided in the C Driver Files to determine how you want the interrupt to operate.
  • Load the register values for the block input ports. In the above example this is performed using API functions XExample_Set_a, XExample_Set_b, and XExample_Set_c_i.
  • Set the ap_start bit to 1 using XExample_Start to start executing the function. This register is self-clearing as noted in the header file above. After one transaction, the block will suspend operation.
  • Allow the function to execute. Address any interrupts which are generated.
  • Read the output registers. In the above example this is performed using API functions XExample_Get_c_o_vld, to confirm the data is valid, and XExample_Get_c_o.
    Note: The registers in the s_axilite interface obey the same I/O protocol as the ports. In this case, the output valid is set to logic 1 to indicate if the data is valid.
  • Repeat for the next transaction.

The second recommended flow is for continuous execution of the block. In this mode, the input ports included in the AXI4-Lite interface should only be ports which perform configuration. The block will typically run much faster than a CPU. If the block must wait for inputs, the block will spend most of its time waiting:

  • Use the interrupt function to determine how you wish the interrupt to operate.
  • Load the register values for the block input ports. In the above example this is performed using API functions XExample_Set_a, XExample_Set_a and XExample_Set_c_i.
  • Set the auto-start function using API XExample_EnableAutoRestart.
  • Allow the function to execute. The individual port I/O protocols will synchronize the data being processed through the block.
  • Address any interrupts which are generated. The output registers could be accessed during this operation but the data may change often.
  • Use the API function XExample_DisableAutoRestart to prevent any more executions.
  • Read the output registers. In the above example this is performed using API functions XExample_Get_c_o and XExample_Set_c_o_vld.