博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二叉树乘法器
阅读量:7015 次
发布时间:2019-06-28

本文共 2819 字,大约阅读时间需要 9 分钟。

      对于两个N位数相乘 P=AB,之前的移位累加乘法器是先将B装载于一个2N位的寄存器中,然后B逐次移位,再根据A的各位情况累加。

      现在我们将A按权展开:                               

      以两个8位数相乘为例:

           

       首先我们可以写一个函数实现1位数和8位数的相乘,以得到上面的八个相加的数;

       然后我们可以将这八个数分组两两相加,第一次相加后得到4个中间结果,再将4个数分组两两相加,得到2个中间结果,最后再将这两个数相加得到最终结果。这样增加了芯片资源的耗用,但是可以提升速度。

      在《数字系统设计与Verilog HDL》中对于8位二叉树(加法树)乘法器有如下代码:

module add_tree(out,a,b,clk); output [15:0] out; input [7:0] a,b; input clk; wire  [15:0] out; wire  [14:0] out1,c1; wire  [12:0] out2; wire  [10:0] out3,c2; wire  [8:0] out4; reg [14:0] temp0; reg [13:0] temp1; reg [12:0] temp2; reg [11:0] temp3; reg [10:0] temp4; reg [9:0] temp5; reg [8:0] temp6; reg [7:0] temp7; //该函数实现8x1乘法 function [7:0] mult8x1; input [7:0] operand; input sel; begin       mult8x1=(sel)?(operand):8'b00000000;    end   endfunction  //调用函数实现b各位与a相乘 always @ ( posedge clk ) begin    temp7<=mult8x1(a,b[0]);    temp6<=(mult8x1(a,b[1])<<1);    temp5<=(mult8x1(a,b[2])<<2);    temp4<=(mult8x1(a,b[3])<<3);    temp3<=(mult8x1(a,b[4])<<4);    temp2<=(mult8x1(a,b[5])<<5);    temp1<=(mult8x1(a,b[6])<<6);    temp0<=(mult8x1(a,b[7])<<7); end   assign out1=temp0+temp1; assign out2=temp2+temp3; assign out3=temp4+temp5; assign out4=temp6+temp7; assign c1=out1+out2; assign c2=out3+out4; assign out=c1+c2; endmodule

     上面代码在调用函数的时候,左移k位是为了实现公式中2的k次方这个权系数。

      其实该代码其实是有错的,以temp6+temp7为例,temp6为9位,temp7为8位,相加的结果out4它定义为9位,如果两数相加结果为9位,则不会出现问题;

如果两数相加产生进位,则进位将丢失,得不到正确结果。该代码的前仿真结果如下:

     由此可以看到,255×255时结果错误,就是因为有进位丢失。

     现在我们修改上述中间变量的位宽。由于两个8位数相乘结果最多为16位,因此如果我们将所有中间变量都改为16位的,结果肯定不会出问题,但是这样比较浪费资源。

     所以这里我们将temp6(9b)+temp7(8b)的结果out4设为10位,temp4(11b)+temp5(10b)的结果out3设为12位,temp2(13b)+temp3(12b)的结果out2设为14位,temp0(15b)+temp1(14b)的结果out1设为16位。

     然后将out3(12b)+out4(10b)的结果c2设为13位,out1(16b)+out2(14b)的结果c1设为16位,这里就不用考虑进位丢失了,因此最终结果最多为16位。

     修改的这部分代码如下: 

wire  [15:0] out; wire  [15:0] out1,c1; wire  [13:0] out2; wire  [11:0] out3; wire  [12:0] c2; wire  [9:0] out4;

    现在再仿真的结果如下:(可以看到结果正确了)

    该乘法器能在一个时钟周期内完成乘法运算。但是它不能插入流水线,因为后面的分组加法运算是组合逻辑实现的。我们可以看一下用XST综合的时序报告:

   (位宽有问题的代码的综合结果)

   Minimum input arrival time before clock: 3.687ns

   Maximum output required time after clock: 16.068ns

   现在我们将加法运算也放入always块内,在此需要先将wire型变量改为reg型,assign语句删除。always块如下:(位宽没改)

always @ ( posedge clk ) begin    temp7<=mult8x1(a,b[0]);    temp6<=(mult8x1(a,b[1])<<1);    temp5<=(mult8x1(a,b[2])<<2);    temp4<=(mult8x1(a,b[3])<<3);    temp3<=(mult8x1(a,b[4])<<4);    temp2<=(mult8x1(a,b[5])<<5);    temp1<=(mult8x1(a,b[6])<<6);    temp0<=(mult8x1(a,b[7])<<7);    out1<=temp0+temp1;    out2<=temp2+temp3;    out3<=temp4+temp5;    out4<=temp6+temp7;    c1<=out1+out2;    c2<=out3+out4;    out<=c1+c2; end

    由代码分析可知道从第一个数据输入到第一个数据输出有3个时钟周期延迟,仿真如下:

    

    但是我们再看一下综合报告:

    Minimum input arrival time before clock: 3.687ns

    Maximum output required time after clock: 6.216ns

    与之前的对比可知,建立时间一样,但是保持时间小多了,因此时钟周期也小多了。并且,该实现方式可以在加法器之间插入寄存器以实现流水线,从而再次提高时钟频率。

 

转载于:https://www.cnblogs.com/haigege/archive/2011/10/19/2218158.html

你可能感兴趣的文章
012 字典
查看>>
CentOS7配置Mysql热备份
查看>>
java.lang.IllegalArgumentException: No enum constant org.apache.ws.commons.schema.XmlSchemaForm.
查看>>
解读90后关键词 新生的红利市场在哪?
查看>>
SQL Server实际执行计划COST"欺骗"案例
查看>>
在EF Core里面如何使用以前EntityFramework的DbContext.Database.SqlQuery<SomeModel>自定义查询...
查看>>
Android Camera2 参数调节关键字翻译集合,常用关键字解析
查看>>
docker的使用
查看>>
【转】OPPO A77保持应用后台运行方法
查看>>
Linux下*.tar.gz文件解压缩命令
查看>>
京都之行
查看>>
枚举NT系统用户
查看>>
任务,过程,和线程
查看>>
(原創) 令人期待的C# 3.0/LINQ (.NET) (C#)
查看>>
delphi 通过线程实现Windows服务
查看>>
育儿:自制身高仪和照片墙
查看>>
QT槽和信号机制介绍
查看>>
[例程]string.trim().length()的用法
查看>>
电子书下载:Microsoft Windows Identity Foundation Cookbook
查看>>
ORACLE修改表空间方法
查看>>