verilog |
您所在的位置:网站首页 › verilog位宽不一致带符号乘法 › verilog |
作为博客小白,这是我的第一篇帖子。我就分享一下今天浪费了我一早上获得的小知识点。 先看下面的代码: wire[43:0] sc[6:0]; wire[55:0] c[6:0]; wire[55:0] c1[6:0]; wire[55:0] c2,c3; assign c1[0]=720*sc[0]; assign c1[1]=80*sc[1]; assign c1[2]=240*$signed(sc[2]); assign c1[3]=6 *sc[3]; assign c1[4]=10*$signed(sc[4]); assign c1[5]=16*$signed(sc[5]); assign c1[6]=720*sc[6]; assign c2=c1[0]+c1[1]+c1[2]-c1[3]-c1[4]-c1[5]+c1[6]; assign c3=720*sc[0]+80*sc[1]+240*$signed(sc[2])-6 *sc[3]-10*$signed(sc[4])-16*$signed(sc[5])+720*sc[6]; 按理说的得到的c2和c3值应该是相等的,但是事实上并不是这样的。如果上面所涉及到的数字都是正数的话得到的值是相等的,但是一旦涉及到负数,结果就会不一样。为了区别两种计算方法,我将字体的颜色分别设置为红色和蓝色。红色部分的计算方式不管是正数或者负数,计算的结果都会是正确的。但是蓝色部分计算负数时却会出错,这是因为这个长的赋值运算的计算顺序是先将各个乘法结果计算出来,然后再相加,最后才会进行符号位的扩展使结果满足其位宽限制,这时如果进行乘法后得到的结果是负数,其符号位扩展为1,但是由于这种计算方式到最后一步只对最终的运算结果扩展,所以计算会出错。红色部分计算方法之所以不会出错是因为它是分布计算乘法的,计算的结果位宽和最终所要得到的c2的位宽是一致的,所以最后相加肯定没有问题。
发现这个问题后我就开始修改,最初的修改方法是对每一个常数进行位宽限制,即把720写成12'd720的方式,但是仿真结果还是错误,最终的修改方式是将sc[6:0] 的位宽直接定义成56位,这样虽然相乘之后位宽大于56,赋值的过程会进行截取,但是因为实质上相乘的值位宽是在56位之内的,截取之后仍然会是正确的值,所以这种修改方式是可取的,而且我的仿真结果也对了。。 以上就是我今天改bug发现的知识,特来分享,以后会坚持更的。
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |