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;
}