Extracting Control Logic and Implementing I/O Ports Example - 2021.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
ft:locale
English (United States)
Release Date
2021-12-15
Version
2021.2 English

The following figure shows the extraction of control logic and implementation of I/O ports for this code example:


void foo(int in[3], char a, char b, char c, int out[3]) {
  int x,y;
  for(int i = 0; i < 3; i++) {
    x = in[i]; 
    y = a*x + b + c; 
    out[i] = y;
  }
}
Figure 1. Control Logic Extraction and I/O Port Implementation Example

This code example performs the same operations as the previous example. However, it performs the operations inside a for-loop, and two of the function arguments are arrays. The resulting design executes the logic inside the for-loop three times when the code is scheduled. High-level synthesis automatically extracts the control logic from the C code and creates an FSM in the RTL design to sequence these operations. Top-level function arguments become ports in the final RTL design. The scalar variable of type char maps into a standard 8-bit data bus port. Array arguments, such as in and out, contain an entire collection of data.

In high-level synthesis, arrays are synthesized into block RAM by default, but other options are possible, such as FIFOs, distributed RAM, and individual registers. When using arrays as arguments in the top-level function, high-level synthesis assumes that the block RAM is outside the top-level function and automatically creates ports to access a block RAM outside the design, such as data ports, address ports, and any required chip-enable or write-enable signals.

The FSM controls when the registers store data and controls the state of any I/O control signals. The FSM starts in the state C0. On the next clock, it enters state C1, then state C2, and then state C3. It returns to state C1 (and C2, C3) a total of three times before returning to state C0.

Note: This closely resembles the control structure in the C code for-loop. The full sequence of states are: C0,{C1, C2, C3}, {C1, C2, C3}, {C1, C2, C3}, and return to C0.

The design requires the addition of b and c only one time. High-level synthesis moves the operation outside the for-loop and into state C0. Each time the design enters state C3, it reuses the result of the addition.

The design reads the data from in and stores the data in x. The FSM generates the address for the first element in state C1. In addition, in state C1, an adder increments to keep track of how many times the design must iterate around states C1, C2, and C3. In state C2, the block RAM returns the data for in and stores it as variable x.

High-level synthesis reads the data from port a with other values to perform the calculation and generates the first y output. The FSM ensures that the correct address and control signals are generated to store this value outside the block. The design then returns to state C1 to read the next value from the array/block RAM in. This process continues until all outputs are written. The design then returns to state C0 to read the next values of b and c to start the process again.