分享

对特权同学的16位乘法器代码的理解与修正

 昵称7877870 2011-10-11

标签: 特权  16位乘法器  理解  修正  

标签: 特权  16位乘法器  理解  修正  

对特权同学的16位乘法器代码的理解与修正

首先声明一下本人在FPGA这条道路上走了还不到一个星期,对于很多FPGA硬件软件方面的知识理解还很不到位,所以下文必然会有很多漏洞,还希望大家多多指正,共同学习。


本文所用代码基于特权乘法器设计实验一节,代码见下面链接:

http://group./1375/21236.aspx



在看特权大哥16位乘法器视频的时候,一直没有弄明白最关键的乘法操作的两句话,红色标记如下:

else if(i > 5'd0 && i < 5'd16) 

begin

if(areg[i-1]) yout_r = {1'b0,yout[30:15]+breg,yout_r[14:1]}; //累加并移位

else yout_r <= yout_r>>1; //移位不累加

end

else if(i == 5'd16 && areg[15]) yout_r[31:16] <= yout_r[31:16]+breg; //累加不移位

刚开始是对乘法以为的原理不太懂,后来在草稿纸上退到之后基本明白了,先以两个4位二进制数为例,将推导思路解释一下:


根据这个竖式,可以总结出这样一个规律:

4位二进制乘数的最位乘以被乘数时,得出的结果最高只可能出现在第7位上(从广义上说就是结果的次高位上),所以第八位(广义上说就是最高位)只是用来准备存放进位的。

如果读者能够明白这样一个规律的话,那么我们接着就以特权的代码进行分析:

首先要搞清楚在代码{1'b0,yout[30:15]+breg,yout_r[14:1]}[14:1][30:15]指的是原来数的这些位 而它们对应的 现在这个数的位数又分别是[13:0][29:14],所以这里其实就实现了右移操作。

对于第31位刚开始始终不用,每次都把结果存放在第[29:14]位之中,15个右移后,最终将真正个位数移到了最低位(0位)。

这里有个问题需要说明一下:

细心的读者估计已经发现{1'b0,yout[30:15]+breg,yout_r[14:1]}这条语句中位数怎么算都是31位啊,明明应该是32位的嘛(视频里也说是32位的啊)为什么会出现这个bug呢?

这里,有些网友是这样解释的yout[30:15]+breg 这两个16位数相加如果足够大,肯定是会产生进位的,所以就成了17位。呵呵,现在刚好17+14+1=32位了吧。

但是这个解释有一个很明显的bug:那要是没有进位呢?不还是16位的吗?

笔者认真考虑了一个晚上想了很多解释最终觉得以下两个解释,虽然自己也不是很有信心,但勉强可以支撑一下这个算法:

1,对于verilog语言“+”会产生一个一个加法器,而加法器都是会带进位位的,所以yout[30:15]+breg会自动产生一个进位位,变成17位。

2,即使上面一个说法不成立,那么当{...}中不足32位时应该会在最高位自动补0或者X吧,这样最终依然是32位。并且不影响后面的计算结果。

对于这样两种猜想,由于本人能力有限,且刚刚接触FPGA所以不敢保证不是谬论,还希望高手们要多多指教。

上面啰嗦了这么多,其实只是对特权大哥代码的一个解读,真正有问题的是下一句:

根据上面总结出的那个规律,最高位只是用来进位用的那么这句代码:

yout_r[31:16] <= yout_r[31:16]+breg;

就明显有问题了,如果两个加数相加产生进位该怎么办呢?

所以我认为这一句应该是需要这么写的:

else if(i == 5'd16 && areg[15]) yout_r[31:15] <= yout_r[30:15]+breg; 

呵呵,在我写此文的时候,发现特权的博客上已经有前辈这么提出来了,果然论坛上还是有高手的,这里只是思路相同,没有抄袭之想法还请高手看到此文章后别误会。

下面是通过Modelsim仿真出来的结果:


(图一,为特权代码的仿真结果)




(图二,为修改后代码的仿真结果)




(图三为正确答案)



后记

在笔者写这篇文章的时候同时还看到了有人这样修改了代码:

else if(i > 5'd0 && i < 5'd16) begin
    if(areg[i-1]) yout_r = {1'b0,yout[31:15]+{1'b0,breg},yout_r[14:1]}; 
     else yout_r <= yout_r>>1; 
    end
   else 

if(i == 5'd16 && areg[15]) yout_r[31:15] <= yout_r[31:15]+{1'b0,breg};  

应该说思路是一样的,这位网友强制加了一位作为进位位,纠正了进位位的丢失。对于这个代码我也随即抽了几个数做了一下仿真,结果完全正确。

结果如下:





最后

特别鸣谢:特权大哥还有论坛上的那些提供意见和代码的高手们。

首先声明一下本人在FPGA这条道路上走了还不到一个星期,对于很多FPGA硬件软件方面的知识理解还很不到位,所以下文必然会有很多漏洞,还希望大家多多指正,共同学习。


本文所用代码基于特权乘法器设计实验一节,代码见下面链接:

http://group./1375/21236.aspx



在看特权大哥16位乘法器视频的时候,一直没有弄明白最关键的乘法操作的两句话,红色标记如下:

else if(i > 5'd0 && i < 5'd16) 

begin

if(areg[i-1]) yout_r = {1'b0,yout[30:15]+breg,yout_r[14:1]}; //累加并移位

else yout_r <= yout_r>>1; //移位不累加

end

else if(i == 5'd16 && areg[15]) yout_r[31:16] <= yout_r[31:16]+breg; //累加不移位

刚开始是对乘法以为的原理不太懂,后来在草稿纸上退到之后基本明白了,先以两个4位二进制数为例,将推导思路解释一下:


根据这个竖式,可以总结出这样一个规律:

4位二进制乘数的最位乘以被乘数时,得出的结果最高只可能出现在第7位上(从广义上说就是结果的次高位上),所以第八位(广义上说就是最高位)只是用来准备存放进位的。

如果读者能够明白这样一个规律的话,那么我们接着就以特权的代码进行分析:

首先要搞清楚在代码{1'b0,yout[30:15]+breg,yout_r[14:1]}[14:1][30:15]指的是原来数的这些位 而它们对应的 现在这个数的位数又分别是[13:0][29:14],所以这里其实就实现了右移操作。

对于第31位刚开始始终不用,每次都把结果存放在第[29:14]位之中,15个右移后,最终将真正个位数移到了最低位(0位)。

这里有个问题需要说明一下:

细心的读者估计已经发现{1'b0,yout[30:15]+breg,yout_r[14:1]}这条语句中位数怎么算都是31位啊,明明应该是32位的嘛(视频里也说是32位的啊)为什么会出现这个bug呢?

这里,有些网友是这样解释的yout[30:15]+breg 这两个16位数相加如果足够大,肯定是会产生进位的,所以就成了17位。呵呵,现在刚好17+14+1=32位了吧。

但是这个解释有一个很明显的bug:那要是没有进位呢?不还是16位的吗?

笔者认真考虑了一个晚上想了很多解释最终觉得以下两个解释,虽然自己也不是很有信心,但勉强可以支撑一下这个算法:

1,对于verilog语言“+”会产生一个一个加法器,而加法器都是会带进位位的,所以yout[30:15]+breg会自动产生一个进位位,变成17位。

2,即使上面一个说法不成立,那么当{...}中不足32位时应该会在最高位自动补0或者X吧,这样最终依然是32位。并且不影响后面的计算结果。

对于这样两种猜想,由于本人能力有限,且刚刚接触FPGA所以不敢保证不是谬论,还希望高手们要多多指教。

上面啰嗦了这么多,其实只是对特权大哥代码的一个解读,真正有问题的是下一句:

根据上面总结出的那个规律,最高位只是用来进位用的那么这句代码:

yout_r[31:16] <= yout_r[31:16]+breg;

就明显有问题了,如果两个加数相加产生进位该怎么办呢?

所以我认为这一句应该是需要这么写的:

else if(i == 5'd16 && areg[15]) yout_r[31:15] <= yout_r[30:15]+breg; 

呵呵,在我写此文的时候,发现特权的博客上已经有前辈这么提出来了,果然论坛上还是有高手的,这里只是思路相同,没有抄袭之想法还请高手看到此文章后别误会。

下面是通过Modelsim仿真出来的结果:


(图一,为特权代码的仿真结果)




(图二,为修改后代码的仿真结果)




(图三为正确答案)



后记

在笔者写这篇文章的时候同时还看到了有人这样修改了代码:

else if(i > 5'd0 && i < 5'd16) begin
    if(areg[i-1]) yout_r = {1'b0,yout[31:15]+{1'b0,breg},yout_r[14:1]}; 
     else yout_r <= yout_r>>1; 
    end
   else 

if(i == 5'd16 && areg[15]) yout_r[31:15] <= yout_r[31:15]+{1'b0,breg};  

应该说思路是一样的,这位网友强制加了一位作为进位位,纠正了进位位的丢失。对于这个代码我也随即抽了几个数做了一下仿真,结果完全正确。

结果如下:





最后

特别鸣谢:特权大哥还有论坛上的那些提供意见和代码的高手们。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多