在FPGA中,经常使用定点数表示小数,在进行各种运算时,定点数的位宽会发生变化,并且需要在适当地时候对数据的位宽进行截取。
运算要求和引起的位宽变化
假设存在两个数A、B,假定A位宽为m,小数位宽为a,B位宽为n,小数位宽为b。
无符号数加法:A+B,需要先将A和B的小数点对齐,再将整数位和小数位都扩展至较大的位宽,最终结果的位宽为拓展后的位宽+1。
有符号数加法:A+B,无需注意A、B符号位,可直接相加,同样需要先将A和B的小数点对齐,再将整数位和小数位都扩展至较大的位宽,最终结果的位宽为拓展后的位宽+1。
无符号数减法:A-B,需要先将A和B的小数点对齐,再将整数位和小数位都扩展至较大的位宽,最终结果的位宽为拓展后的位宽+1。
有符号数减法:A-B,无需注意A、B符号位,可直接相减,同样需要先将A和B的小数点对齐,再将整数位和小数位都扩展至较大的位宽,最终结果的位宽为拓展后的位宽+1。
无符号数乘法:A*B,无需对齐,无需注意A、B符号位,可直接相乘,最终结果的位宽为m+n。
有符号数乘法:A*B,无需对齐,无需注意A、B符号位,可直接相乘,最终结果的位宽为m+n-1。其实最终结果位宽原本为m+n,其中包含两位符号位,当符号位为10和01时,表明运算结果溢出,符号位为00和11时,去掉最高位
位宽截取
在乘法运算中,会成倍的增加位宽,因此在FPGA算法实现的过程中,常常需要对数据的位宽进行截取,常用的位宽截取方法有以下几种。
2.1 截断(tu)
2.2 四舍五入
“舍入”舍入到最邻近的可表示数字。如果出现结值,则舍入:
将正数朝正无穷方向舍入到最邻近的可表示数字。
将负数朝负无穷方向舍入到最邻近的可表示数字。
因此:
负值样本会引入小的负偏置。
对于具有均匀分布的正值和负值的样本,不会引入偏置。
对正值样本引入小的正偏置。

使用verilog编程时,假设要将m位数据截断为n位数据,需要将要截断的数据+{符号位取反,m-n-1{符号位}}再右移m-n位。以verilog为例,假定一64位有符号数要截断为一32位有符号数,程序如下。
reg signed [31:0] dataout;
wire signed [63:0] datain;
always@(posedge clk)begin
dataout <= (datain + {~datain[63],31{datain[63]}}) >> 32;
end