Search code examples
fixed-pointtrigonometryvivado-hls

How to use a fixed point sin function in Vivado HLS


I am calculating the intersection point of two lines given in the polar coordinate system:

typedef ap_fixed<16,3,AP_RND> t_lines_angle;
typedef ap_fixed<16,14,AP_RND> t_lines_rho;

bool get_intersection(
        hls::Polar_< t_lines_angle, t_lines_rho>* lineOne,
        hls::Polar_< t_lines_angle, t_lines_rho>* lineTwo,
        Point* point)
{
    float angleL1 = lineOne->angle.to_float();
    float angleL2 = lineTwo->angle.to_float();
    t_lines_angle rhoL1 = lineOne->rho.to_float();
    t_lines_angle rhoL2 = lineTwo->rho.to_float();
    t_lines_angle ct1=cosf(angleL1);
    t_lines_angle st1=sinf(angleL1);
    t_lines_angle ct2=cosf(angleL2);
    t_lines_angle st2=sinf(angleL2);
    t_lines_angle d=ct1*st2-st1*ct2;

    // we make sure that the lines intersect
    // which means that parallel lines are not possible
    point->X = (int)((st2*rhoL1-st1*rhoL2)/d);
    point->Y = (int)((-ct2*rhoL1+ct1*rhoL2)/d);

    return true;
}

After synthesis for our FPGA I saw that the 4 implementations of the float sine (and cos) take 4800 LUTs per implementation, which sums up to 19000 LUTs for these 4 functions. I want to reduce the LUT count by using a fixed point sine. I already found a implementation of CORDIC but I am not sure how to use it. The input of the function is an integer but i have a ap_fixed datatype. How can I map this ap_fixed to integer? and how can I map my 3.13 fixed point to the required 2.14 fixed point?


Solution

  • With the help of one of my colleagues I figured out a quite easy solution that does not require any hand written implementations or manipulation of the fixed point data:

    use #include "hls_math.h" and the hls::sinf() and hls::cosf() functions.

    It is important to say that the input of the functions should be ap_fixed<32, I> where I <= 32. The output of the functions can be assigned to different types e.g., ap_fixed<16, I>

    Example:

    void CalculateSomeTrig(ap_fixed<16,5>* angle, ap_fixed<16,5>* output)
    {
        ap_fixed<32,5> functionInput = *angle;
        *output = hls::sinf(functionInput);
    }
    

    LUT consumption:

    In my case the consumption of LUT was reduced to 400 LUTs for each implementation of the function.