The first thought was that it was very cool and I could never do that again. Time passed, articles were read, methods were studied, and I looked for examples of how to implement this, but to my chagrin, nothing concrete was found on the network. Once I stumbled upon the calculations of trigonometric functions using the CORDIC algorithms, I decided to try creating my own image rotator on the FPGA.
CORDIC
So, CORDIC is an abbreviation for CO ordinate R otation D Igital C omputer. ')
It is a powerful tool for calculating hyperbolic and trigonometric functions. Most CORDIC algorithms work in a sequential approximation method and are not very difficult to implement in both high-level programming languages and HDL. I will not focus on the math method, the reader can read it on the network or on the links below.
In free access, I came across this implementation of the CORDIC algorithm in verilog. This core works in 2 modes: Rotate and Vector . Rotate mode is suitable for our purposes. It allows you to calculate the values of the functions sin and cos from a given angle in radians or degrees. The library can be configured both in the pipeline and in the combination version. For our purposes, the pipeline is suitable, it has the largest Fmax . It will produce sine and cosine values with a delay of 16 cycles.
In the RTL Viewer-e CORDIC module is displayed consisting of 16 blocks of the same type:
Each of which accepts input from the previous one and outputs connected to the inputs of the next. It looks like this:
The library core works only in the first quadrant, and this means that we will have to calculate the remaining three by subtracting pi / 2 and changing the sign.
The approach I have chosen is not very correct. The quality of the rotated image leaves much to be desired. This is due to the calculation of coordinates on the fly, without the use of additional data buffering and sequential calculation of coordinates for several passes, as is done in Shear .
The first instance of our rotator is the block for calculating the quadrant and the angle of rotation. The rotation angle is incremented by each new frame by 1 degree. Upon reaching an angle of 90 degrees, the quadrant changes to the next one in turn, and the angle is either reset to zero or decremented by 1 degree each new frame.
Further, it is not difficult to guess that the calculation of the coordinates of each subsequent pixel will be made using the formula:
x '= cos (angle) * x - sin (angle) * y; y '= sin (angle) * x + cos (angle) * y;
If you leave everything in this form, then the rotation will be centered at the origin. This rotation does not suit us, we need the image to rotate around its axis with the center in the middle of the image. To do this, we need to conduct calculations relative to the center of the image.
As I mentioned above, this approach has many drawbacks. Because of the calculation error, holes appear in the output image; the larger the angle of rotation, the larger the holes. This also happens by the fact that the size of the new image is larger than that of the original. This effect will be aliasing and there are methods of dealing with it, for example, the median filter reviewed in my previous article .
Before each subsequent frame it would not hurt to clean the memory from the previous frame so that the new image is obtained on a clean background, but it takes time and you have to skip one frame.
The only advantage of the method is the ease of implementation and processing speed, since coordinates are calculated on-the-fly.