HLS_2 数据精度处理

1.任意精度整数

对于C99编译器来说整数的精度只有16位。更进一步,C99标准对于整数只定义了4位宽度,那么下面两段代码得出的P值是等效的:

code1:
#include "inttypes.h"
uint16_t a = 0x4000;
uint16_t b = 0x4000;
//Danger! p depends on sizeof(int)
uint32_t p = a * b;
code2:
#include "inttypes.h"
//4.0 represented with 12 fractional bits
uint16_t a = 0x4000;
//4.0 represented with 12 fractional bits
uint16_t b = 0x4000;
//Danger! p depends on sizeof(int)
uint32_t p = (a*b) >> 12;

正确的代码

#include "inttypes.h"
uint16_t a = 0x4000;
uint16_t b = 0x4000;
//p is assigned to 0x10000000
uint32_t p = (uint32_t) a*(uint32_t) b;

等价于

#include "inttypes.h"
//4.0 represented with 12 fractional bits
uint16_t a = 0x4000;
//4.0 represented with 12 fractional bits
uint16_t b = 0x4000;
//Danger! p depends on sizeof(int)
uint32_t p = ((uint32_t) a*(uint32_t) b) >> 12;

综上所述,对于FPGA还是应该使用c++和Vivado HLS模板类ap_int<>, ap_uint<>, ap_ fixed<>, ap_ufixed<>来表示任意精度数据。ap_int<>和ap_uint<>模板类需要整数参数来定义他们的位宽。计算函数通常产生结果
的位宽足够宽,可以表示正确结果

#include "ap_int.h"
ap_uint<15> a = 0x4000;
ap_uint<15> b = 0x4000;
//p is assigned to 0x10000000
ap_uint<30> p = a*b;
#include "ap_fixed.h"
//4.0 represented with 12 fractional bits
ap_ufixed<15,12> a = 4.0;
//4.0 represented with 12 fractional bits
ap_ufixed<15,12> b = 4.0;
//p is assigned to 16.0 represented with 12 fractional bits
ap_ufixed<18,12> p = a*b;

注意:整数部分的位宽,数字相乘需要位宽相加。

2.浮点

float
浮点数计算sine(sin)和cosine(cos):

//The file cordic.h holds definitions for the data types and constant valuse

#include "cordic.h"

//The cordic_phase array holds the angle for the current rotation
THETA_TYPE cordic_phase[NUM_ITERATIONS] = {
    45, 26.56, 14.036, 7.125
    3.576, 1.790, 0.895, ...    
};

void
cordic(THETA_TYPE theta, COS_SIN_TYPE &s, COS_SIN_TYPE &c)
{
    //Set the initial vector that we will rotate
    //current_cos = I;current = Q
    COS_SIN_TYPE current_cos =0.60735;
    COS_SIN_TYPE current_sin = 0.0;

    //Factor is the 2^(-L) value
    COS_SIN_TYPE factor = 1.0;

    //This loop iteratively rotates the initial vector to find the
    //sine and cosine value corresponding to the input theta angle
    for(int j = 0; j < NUM_ITERATIONS; j++){
        //Determine if we are rotating by a positive or negative angle
        int sigma = (theta < 0) ? -1 : 1;

        //Save the current_cos,so that it can be used in the sine calculation
       COS_SIN_TYPE temp_cos = current_cos;

        //Perform the rotation
        current_cos = current_cos - current_sin * sigma * factor;
        current_sin = temp_cos * sigma * factor + current_sin;

        //Determine the new theta
        theta = theta - sigma * cordic_phase[j];

        //Calculata next 2^(-L) value
        factor = factor >> 1;
    }

    //Set the final sine and cosine values
    s = current_sin;c = current_cos;
}

定点数计算:

// The file cordic.h holds definitions for the data types and constant values 
#include ”cordic.h”

// The cordic phase array holds the angle for the current rotation 
// cordic_phase[0] =˜ 0.785 
// cordic_phase[1] =˜ 0.463

void cordic(THETA_TYPE theta, COS_SIN_TYPE &s, COS_SIN_TYPE &c) 
{ 
    // Set the initial vector that we will rotate 
    // current cos = I; current sin = Q 
    COS_SIN_TYPE current_cos = 0.60735; 
    COS_SIN_TYPE current_sin = 0.0;
    
    // This loop iteratively rotates the initial vector to find the 
    // sine and cosine values corresponding to the input theta angle 
    for (int j = 0; j < NUM_ITERATIONS; j++) { 
        // Multiply previous iteration by 2ˆ(−j). This is equivalent to 
        // a right shift by j on a fixed−point number. 
        COS_SIN_TYPE cos_shift = current_cos >> j; 
        COS_SIN_TYPE sin_shift = current_sin >> j;
        
        // Determine if we are rotating by a positive or negative angle 
        if(theta >= 0) { 
            // Perform the rotation 
            current_cos = current_cos − sin_shift; 
            current_sin = current_sin + cos_shift;
            
            // Determine the new theta theta = theta − cordic_phase[j]; 
        } else { 
            // Perform the rotation 
            current_cos = current_cos + sin_shift; 
            current_sin = current_sin − cos_shift;
            
            // Determine the new theta 
            theta = theta + cordic_phase[j];
        }
    }    
    // Set the final sine and cosine values 
    s = current_sin;
    c = current_cos;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风尘23187

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值