| |
引:不怎么做DSP方面的算法,所以其实我对于浮点和定点数据运算没有什么概念。但是今天在论坛上看到一段代码,这段代码倒是给我一些启发。乍一看好像不对,但是仔细分析来看,功能又是正确的。其实是利用verilog和芯片中关于定点和浮点的转变罢了。或许对于常年和这些概念打交道的人来说,小菜一碟,但是对于我,还挺有用的。好了,看看吧。
问题是这样的:
output [14:0] cound_add;
input [10:0] VA;
wire sign = VA[9:0] >10'b1000000000 ?1'b1: 1'b0;
wire [9:0] VA_TEMP = sign ? 0: (10'b1000000000 - VA[9:0]);
assign count_add_temp[14:0] = {3'b0,VA_TEMP,2'b0};
always @ (posedge mclk or negedge por_rstn) begin
if (!por_rstn)
count_add <=#dly 15'd0;
else
count_add <=#dly count_add_temp;
end
功能是: 当VA<0.5时候,count_add = (0.5-VA)*4096
问: (1)上面代码能否实现这个功能,
(2)上面代码综合需要加什么条件吗?
我的分析:
根据你的代码来分析的话,我想VA[10:0]这个数字,应该是这样的:
[10]bit是整数位,表示1点几,VA[9:0]是小数部分,表示0点几。这样的话VA的值应该是在>=1.0到<2之间。但是后面完全没有看到VA[10]有用。所以我们暂且不管它,那么VA[9:0]应该是:0.0<=VA[9:0]<1.0之间的范围。也就是说VA[9:0]全部是小数部分。
wire sign = VA[9:0] >10'b1000000000 ?1'b1: 1'b0;
这一行是在比较到底VA[9:0]和0.5之间谁大,应该是为下一行的计算准备。
wire [9:0] VA_TEMP = sign ? 0: (10'b1000000000 - VA[9:0]);
这一行通过利用上次比较VA[9:0]和0.5的结果,如果sign=1,也就是说VA[9:0]>0.5的话,输出VA_TEMP为0。反之,如果sign=0,也就是说VA[9:0] <= 0.5,那么VA_TEMP=0.5-VA[9:0],得到差值。
assign count_add_temp[14:0] = {3'b0,VA_TEMP,2'b0};
这个是做最后的计算了,下面的时序逻辑很简单,一级寄存器。所以就不做功能分析了。功能上,这已经是最后一行代码了。这个最后的计算,将刚才得到的VA_TEMP[9:0],后面接上2个bit0,然后赋值给输出count_add_temp[14:0]。
有个前提,输出的count_add_temp[14:0]所有的bit位都是整数(没有小数),如果这个前提正确的话。那么看看count_add_temp[14:0] = {VA_TEMP,2'b0} (高位的3‘b0不分析了,因为不影响结果) 代表什么意思呢。
首先VA_TEMP[9:0]中所有的10个bit都是小数(刚才上面分析过了),假设这个值转化成10进制下等于0.123好了。因为二进制没有小数点,所以想想一下这样的计算:
A = 0.123,假如你把小数点抹掉,那么A等于多少?是不是A=123,是不是相当于乘以1000了?
以此类推,如果count_add_temp[14:0] = VA_TEMP[9:0],这是不是代表着count_add_temp[14:0] = 小数下的VA_TEMP[9:0]乘以2的10次方(2**10),对不对?因为输出是整数,所以小数点抹掉了,对吧。那么这时候count_add_temp[14:0] = VA_TEMP[9:0] * (2**10),也就是乘以1024了,对不对?
好了,再在VA_TEMP[9:0]后面补上2'b0(两个bit0),是不是又相当于乘以4了?
综上所述:
assign count_add_temp[14:0] = {3'b0,VA_TEMP,2'b0};
这句话相当于把VA_TEMP乘以4096了。
所以,现在回答你的两个问题:
问: (1)上面代码能否实现这个功能,
(2)上面代码综合需要加什么条件吗?
答: 1. 上面的代码可以实现如果VA<0.5的话,用输出=(0.5-VA)*4096的功能。
2. 综合条件可以这样:输入delay,时钟mclk的频率、抖动等,输出delay,输出负载。应该可以了。
我想,分析的应该没错吧。