Vertical Convolution - Vertical Convolution - 2021.2 English - UG1399

Vitis High-Level Synthesis User Guide (UG1399)

Document_ID
UG1399
Release_Date
2021-12-15
Version
2021.2 English

The next step is to perform the vertical convolution shown in the following figure.

Figure 1. Vertical Convolution

The process for the vertical convolution is similar to the horizontal convolution. A set of K data samples is required to convolve with the convolution coefficients, Vcoeff in this case. After the first output is created using the first K samples in the vertical direction, the next set K values are used to create the second output. The process continues down through each column until the final output is created.

After the vertical convolution, the image is now smaller then the source image src due to both the horizontal and vertical border effect.

The code for performing these operations is:

Clear_Dst:for(int i = 0; i < height * width; i++){
 dst[i]=0;
}
// Vertical convolution 
VconvH:for(int col = border_width; col < height - border_width; col++){
 VconvW:for(int row = 0; row < width; row++){
   int pixel = col * width + row;
   Vconv:for(int i = - border_width; i <= border_width; i++){
     int offset = i * width;
     dst[pixel] += local[pixel + offset] * vcoeff[i + border_width];
 }
 }
}

This code highlights similar issues to those already discussed with the horizontal convolution code.

  • Many clock cycles are spent to set the values in the output image dst to zero. In this case, approximately another 2 million cycles for a 1920*1080 image size.
  • There are multiple accesses per pixel to re-read data stored in array local.
  • There are multiple writes per pixel to the output array/port dst.

Another issue with the code above is the access pattern into array local. The algorithm requires the data on row K to be available to perform the first calculation. Processing data down the rows before proceeding to the next column requires the entire image to be stored locally. In addition, because the data is not streamed out of array local, a FIFO cannot be used to implement the memory channels created by DATAFLOW optimization. If DATAFLOW optimization is used on this design, this memory channel requires a ping-pong buffer: this doubles the memory requirements for the implementation to approximately 4 million data samples all stored locally on the FPGA.