作者: 猫叔,本文转载自: 傅里叶的猫微信公众号
在用FPGA做算法时,由于FPGA中一般都是使用定点数据,因此经常需要移位操作。比如一个16bit的信号经过滤波器后,由于滤波器的增益,输出结果肯定不是16bit,如果我们想保持输入输出的位宽是一致的,那就必须要进行移位。
我们常用的移位方式就是直接截取固定位,我们以DDC为例,假设输入信号是16bit的有符号数,NCO的位宽也是16bit有符号数,两个信号相乘后,就是一个32bit的有符号数。我们在之前的文章中讲到过,如果两个有符号数相乘,只有两个数同时为最小负数时,相乘结果的位宽才是两个数位宽的和。在这里,就是只要当两个乘数都是-32768时,输出结果位宽才是32bit,其他情况,输出结果的高两位都是符号位。我们只取1位即可。
因此,如果我们想输出16bit的数据,而且我们可以保证输入的数据不是满量程的,那么我们直接截取[30:15]位即可。但这样的话,跟floor的效果是一样的,即向下取整,会导致直流分量。如何避免这个问题呢?我们在截位时,可以使用round(即四舍五入)的方式。
首先来看在Verilog中如何进行round截位,假设相乘的结果是mul,那我们可以采用如下方式进行截位:
assign cbit = mul[31]?(mul[14] & (|mul[13:0])):mul[14]; assign mul_round = mul[30:15] + cbit;
如果是在System Generator中,这个问题就更简单了。可以采用如下方式:
其中,round模式可以直接在Shift3中选择:
这里多补充一点,使用System Generator完成常规的信号处理,确实是非常的好用,而且验证起来也很简单。