The next step is to perform the vertical convolution shown in the following figure.
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
dstto 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.