文章目录

  • 1 乘法器
  • 2 部分积的产生
    • 2.1 波兹(Booth)编码
    • 2.2 改进的波兹编码
  • 3 部分积的累加
    • 3.1 阵列乘法器
    • 3.2 进位保留乘法器
    • 3.3 Wallace 树形乘法器
  • 4 Verilog 实现
    • 4.1 普通阵列乘法器
    • 4.2 Booth 乘法器
    • 4.3 Wallace 乘法器
  • 5 总结
  • 参考

1 乘法器

M和N位宽输入的乘法,采用一个N加法器需要M个周期。

利用移位和相加将M个部分积(partial product)加在一起。部分积的计算位相乘本质上是与逻辑。

         101010       被乘数×    1011       乘数———————————101010   \101010     |  部分积000000      |+ 101010      /—————————————111001110

2 部分积的产生

2.1 波兹(Booth)编码

乘数 8’b0111_1110 可以转换成 8’b1000_0000 - 8’b0000_0010 。这里用8’b1000_00I0 表示(I表示 -1 )。

这可以减少非0行的数量,使得部分积的数目至少可以减少原来的一半。部分积数目的减少意味着相加次数的减少,从而加快了运算速度并减少了面积。

保证了在每两个连续位中最多只有一个是 1 或者 -1 。形式上相当于把乘数变换成一个四进制形式。8’b1000_00I0 = (2,0,0,-2)(四进制)

问题:与{0,1}相乘等效于AND,但是与{-2,-1,0,1,2}相乘还需要反向逻辑和移位逻辑,大小不同的部分积阵列对乘法器设计不合理。

2.2 改进的波兹编码

改进的波兹编码(modified Booth’s recoding)乘数由最高有效位(msb)到最低有效位(lsb)进行,按3位一组进行划分,相互重叠一位,编码表:

乘数位 编码位 编码
000 0 00
001 +被乘数 01
010 +被乘数 01
011 +2×被乘数 10
100 -2×被乘数 I0
101 -被乘数 0I
110 -被乘数 0I
111 0 00

本质是从msb到lsb检查乘数中1的字串,用一个以1开头或以-1结尾的字符串代替他们。
例子:
011 :一串1的开始,所以用一个开头的1代替(100)
110 :一串1的结尾,所以用一个结尾的-1代替(0I0)

8’b0111_1110,从msb到lsb,分成3位一组首尾重叠的4组:01(1),11(1),11(1),10(0)。编码后为10,00,00,I0,这与上述的编码是吻合的。

3 部分积的累加

对部分积相加是一个多操作数的加法,一个直接累加的部分积方法是用许多加法器形成阵列,所以被称为 阵列乘法器(array multiplier)。

一个更为先进的方法与树结构的形式完成加法。

3.1 阵列乘法器

AND 门产生部分积,加法器阵列实现相加。

所有关键路径都具有相同的长度。

上述乘法器只能进行无符号数相乘。

3.2 进位保留乘法器

如果进位向下沿而不是向左,可以得到一个更有效的实现。进位不是立即相加,而是传递给下一级加法器,在最后一级在一个快速进位传播(如超前进位)加法器中合并。

代价:需要一个额外的加法器,被称为向量合并(vector-merging)加法器。由此得到的乘法器被称为进位保留乘法器。

优点:在最坏情形下关键路径最短且唯一确定。

拓扑优化后的结构:

这种结构可以更好的映射到硅片上。

3.3 Wallace 树形乘法器

部分积加法器可以设计成树形,可以减少关键路径和所需的加法器单元数目。

上面的4个4位部分积,只有第3bit需要加 4 个。

第一步,第3列和低4列引入2个半加器,如图b所示,压缩后得到图c。
第二步,第3、4、5列引入3个全加器,第2列引入1个半加器,得到图d。
第三步,使用简单的两输入加法器。

前两步一共使用了3个全加器、3个半加器。原来的进位保留乘法器结构需要6个全加器、6个半加器。

全加器3个输入两个输出,所以运算过程中又称为压缩器。

优点:

  • 节省了较大乘法器所需硬件,减少了传播延时。

缺点:

  • 不规则,高质量版图设计任务变复杂。

4 Verilog 实现

4.1 普通阵列乘法器

以 8bit 无符号数相乘为例,注意这里的设计没有考虑性能。

array_multiplier.v:

`timescale 1ns/1ps  module array_multiplier ( input               I_sys_clk,input               I_reset_n,input               I_valid,input      [7:0]    I_a,input      [7:0]    I_b,output reg          O_valid,output reg [15:0]   O_c
);//--- Main body of code ---
always @(posedge I_sys_clk or negedge I_reset_n)
beginif(~I_reset_n) beginO_valid <= 1'b0;O_c     <= 16'b0;end elsebeginO_valid <= I_valid;O_c     <= (({8{I_b[0]}} & I_a)     ) + (({8{I_b[1]}} & I_a) << 1) + (({8{I_b[2]}} & I_a) << 2) + (({8{I_b[3]}} & I_a) << 3) + (({8{I_b[4]}} & I_a) << 4) + (({8{I_b[5]}} & I_a) << 5) + (({8{I_b[6]}} & I_a) << 6) + (({8{I_b[7]}} & I_a) << 7)  ;end
endendmodule

testbench array_multiplier_tb.sv:

`timescale 1ns/1psmodule array_multiplier_tb();parameter T = 5;  reg           I_sys_clk;
reg           I_reset_n;
reg           I_valid  ;
reg  [7:0]    I_a      ;
reg  [7:0]    I_b      ;
wire          O_valid  ;
wire [15:0]   O_c      ;initial beginI_sys_clk <= 'b0;I_reset_n <= 'b0;I_valid   <= 'b0; I_a       <= 'b0; I_b       <= 'b0; #(T*20)  I_reset_n <= 'b1;#(T*20)  data_gen();$finish();
endalways #(T/2) I_sys_clk <= ~I_sys_clk;array_multiplier array_multiplier_u ( .I_sys_clk(I_sys_clk),.I_reset_n(I_reset_n),.I_valid  (I_valid  ),.I_a      (I_a      ),.I_b      (I_b      ),.O_valid  (O_valid  ),.O_c      (O_c      )
);task data_gen();for (int i = 0; i < 256; i++) beginI_valid   <= 'b1; I_a       <= i; I_b       <= i;$display("%d x %d = %d", i, i, i*i);@(posedge I_sys_clk);I_valid   <= 'b0;end
endtaskendmodule

sim.do 文件:

cd D:/prj/modelsim_prj/multiplier/array_multiplier/
vlib work
vlog array_multiplier.v  array_multiplier_tb.sv
vsim -novopt work.array_multiplier_tb

sim.bat 文件:

vsim -do sim.do

所有文件放在相同路径下,双击批处理文件即可开始Modelsim仿真。

仿真结果:

4.2 Booth 乘法器

Verilog 设计,注意,这个代码只是描述算法,需要进行符号位拓展、乘换成与逻辑、以及将乘2的幂转换为移位处理。

`timescale 1ns/1psmodule booth_multiplier (input               I_sys_clk,input               I_reset_n,input               I_valid  ,input      [7:0]    I_a      ,input      [7:0]    I_b      ,output reg          O_valid  ,output reg [15:0]   O_c
);//--- Main body of code ---
wire [8:0] W_b;
wire [15:0] W_a_n;
wire [2:0] W_booth_code_pre [0:3];
reg       R_valid                ;
reg signed [15:0] R_partial_product [0:3];assign W_b = {I_b, 1'b0};
assign W_a_n = -{{8{I_a[7]}}, I_a};genvar gen_i;
for (gen_i = 0; gen_i < 4; gen_i = gen_i + 1) begin assign W_booth_code_pre[gen_i] = W_b[gen_i*2 +: 3];always @(posedge I_sys_clk or negedge I_reset_n)beginif(~I_reset_n) beginR_partial_product[gen_i] <= 1'b0;end elsebegincase (W_booth_code_pre[gen_i])3'b000: R_partial_product[gen_i] <= 9'b0;3'b001: R_partial_product[gen_i] <= $signed(I_a) *  1 * 2**(gen_i*2) ;3'b010: R_partial_product[gen_i] <= $signed(I_a) *  1 * 2**(gen_i*2) ;3'b011: R_partial_product[gen_i] <= $signed(I_a) *  2 * 2**(gen_i*2) ;3'b100: R_partial_product[gen_i] <= $signed(I_a) * -2 * 2**(gen_i*2) ;3'b101: R_partial_product[gen_i] <= $signed(I_a) * -1 * 2**(gen_i*2) ;3'b110: R_partial_product[gen_i] <= $signed(I_a) * -1 * 2**(gen_i*2) ;3'b111: R_partial_product[gen_i] <= 9'b0;default: R_partial_product[gen_i] <= 9'b0;endcaseendend
endalways @(posedge I_sys_clk or negedge I_reset_n)
beginif(~I_reset_n) beginR_valid <= 1'b0;end elsebeginR_valid <= I_valid;end
endalways @(posedge I_sys_clk or negedge I_reset_n)
beginif(~I_reset_n) beginO_valid <= 1'b0;O_c     <= 16'b0;end elsebeginO_valid <= R_valid;O_c     <= R_partial_product[0] + R_partial_product[1] + R_partial_product[2] + R_partial_product[3]  ;end
endendmodule

testchech:

`timescale 1ns/1psmodule booth_multiplier_tb();parameter T = 5;  reg           I_sys_clk;
reg           I_reset_n;
reg           I_valid  ;
reg  [7:0]    I_a      ;
reg  [7:0]    I_b      ;
wire          O_valid  ;
wire [15:0]   O_c      ;// reference model signal
reg [7:0]    R_i ;
reg [7:0]    R1_i ;
reg [7:0]    R2_i ;initial beginI_sys_clk <= 'b0;I_reset_n <= 'b0;I_valid   <= 'b0; I_a       <= 'b0; I_b       <= 'b0; #(T*20)  I_reset_n <= 'b1;#(T*20)  data_gen();$finish();
endalways #(T/2) I_sys_clk <= ~I_sys_clk;booth_multiplier booth_multiplier_u ( .I_sys_clk(I_sys_clk),.I_reset_n(I_reset_n),.I_valid  (I_valid  ),.I_a      (I_a      ),.I_b      (I_b      ),.O_valid  (O_valid  ),.O_c      (O_c      )
);task data_gen();for (int i = 0; i < 256; i++) beginI_valid   <= 'b1; I_a       <= i; I_b       <= i;R_i <= i;R1_i <= R_i;R2_i <= R1_i;// reference modelif (O_valid)begin$display("i=%d, O_c=%d, check=%d", $signed(R2_i), $signed(O_c), $signed(O_c) == $signed(R2_i) * $signed(R2_i));end@(posedge I_sys_clk);I_valid   <= 'b0;end
endtaskendmodule

Modilsim do文件做对应修改,sim.do:

cd D:/prj/modelsim_prj/multiplier/booth_multiplier/
vlib work
vlog booth_multiplier.v  booth_multiplier_tb.sv
vsim -novopt work.booth_multiplier_tb 

仿真结果:

4.3 Wallace 乘法器

以4bit×4bit为例,按照结构把线连起来就行:
wallace_multiplier.v:

`timescale 1ns/1psmodule wallace_multiplier (input               I_sys_clk,input               I_reset_n,input               I_valid  ,input      [3:0]    I_a      ,input      [3:0]    I_b      ,output reg          O_valid  ,output reg [7:0]    O_c
);reg       R_valid ;
reg [3:0] R_partial_product [0:3];  wire [1:0] W_level1_c,W_level1_carry;
wire [3:0] W_level2_c,W_level2_carry;
wire [6:0] W_level3[0:1];genvar gen_i;
generatefor (gen_i = 0; gen_i < 4; gen_i = gen_i + 1) beginalways @(posedge I_sys_clk or negedge I_reset_n)beginif(~I_reset_n) beginR_partial_product[gen_i] = 4'd0;end elsebeginR_partial_product[gen_i] = {4{I_b[gen_i]}} & I_a;endendend
endgenerate// level1
adder_half adder_half_u1 (.I_a    (R_partial_product[2][1]),.I_b    (R_partial_product[3][0]),.O_c    (W_level1_c[0]),.O_carry(W_level1_carry[0])
);
adder_half adder_half_u2 (.I_a    (R_partial_product[1][3]),.I_b    (R_partial_product[2][2]),.O_c    (W_level1_c[1]),.O_carry(W_level1_carry[1])
);// level2
adder_half adder_half_u3 (.I_a    (R_partial_product[1][1]),.I_b    (R_partial_product[2][0]),.O_c    (W_level2_c[0]    ),.O_carry(W_level2_carry[0])
);
adder adder_u1 (.I_a     (R_partial_product[0][3]),.I_b     (R_partial_product[1][2]),.I_carry (W_level1_c[0]          ),.O_c     (W_level2_c[1]          ),.O_carry (W_level2_carry[1]      )
);
adder adder_u2 (.I_a     (R_partial_product[1][3]),.I_b     (W_level1_c[1]          ),.I_carry (W_level1_carry[0]      ),.O_c     (W_level2_c[2]          ),.O_carry (W_level2_carry[2]      )
);
adder adder_u3 (.I_a     (R_partial_product[2][3]),.I_b     (R_partial_product[3][2]),.I_carry (W_level1_carry[1]       ),.O_c     (W_level2_c[3]          ),.O_carry (W_level2_carry[3]      )
);assign W_level3[0] = {R_partial_product[3][3], W_level2_c[3:1], R_partial_product[0][2:0]};
assign W_level3[1] = {W_level2_carry[3:0], W_level2_c[0], R_partial_product[1][0], 1'b0};always @(posedge I_sys_clk or negedge I_reset_n)
beginif(~I_reset_n) beginR_valid <= 1'b0;O_valid <= 1'd0;O_c     <= 8'd0;end elsebeginR_valid <= I_valid;O_valid <= R_valid;O_c     <= W_level3[0] + W_level3[1]; end
endendmodulemodule adder_half (input  I_a,input  I_b,output O_c,output O_carry
);assign O_c = I_a ^ I_b;
assign O_carry = I_a & I_b;endmodulemodule adder (input  I_a,input  I_b,input  I_carry,output O_c,output O_carry
);assign O_c = I_a ^ I_b ^ I_carry;
assign O_carry = (I_a & I_b) | ((I_a ^ I_b) & I_carry);endmodule

仿真结果:

5 总结

数字集成电路设计可能对加法器的面积和版图有较高的要求。对于FPGA设计,可能基本阵列加法器用着还更简单顺手。主要看的的题目可能问的是与一个常数相乘的设计,这个时候要参考 Booth 编码的思想,因为不是实时乘数的话,预编码之后确实还是节省资源的。

参考

数字集成电路-电路、系统与设计(第二版)

乘法器的实现(阵列、Booth、Wallace)相关推荐

  1. 计算机组成原理带符号的阵列乘法器,计算机组成原理阵列乘法器课程设计报告精选.doc...

    计算机组成原理阵列乘法器课程设计报告精选 编 号: 学 号: XXX 课 程 设 计 教 学 院计算机学院课程名称计算机组成原理题 目阵列乘法器专 业计算机科学与技术班 级2011级计科(X)班姓 名 ...

  2. Booth乘法器和wallace树乘法器的理解

    <span style="font-family: FangSong_GB2312; color: rgb(51, 51, 51);"><span style=& ...

  3. 【HDL系列】乘法器(6)——Radix-4 Booth乘法器

    目录 一.Radix-4 Booth乘法器原理 二.Verilog设计 一.Radix-4 Booth乘法器原理 上文中介绍了基2 Booth乘法器,本文继续介绍基4 Booth乘法器. 对于N比特数 ...

  4. Wallace 和 Radix-4 Booth-Wallace乘法器性能分析

    对于Booth乘法器和Wallace乘法器对比 这篇文章提到: 综合结果表明,与radix-4 Booth-Wallace乘法器相比,Wallace乘法器的延迟降低了17%,功耗降低了70%. 华莱士 ...

  5. 乘法器——Wallace树型乘法器

    文章转自https://www.cnblogs.com/wangkai2019/p/11153887.html,在此保存一下 博主最近在看乘法器相关的知识,发现现在用的比较多的是booth编码的乘法器 ...

  6. 不带符号的阵列乘法器_与非门-8:阵列乘法器,门的千军万马

    坐那想,想自己去哪,就琢磨西安是B类地区,再往脸跟前摊本组成原理,装出在看无符号数阵列乘法器的样子,一堆堆的全加器简直是繁若星辰烦的我要死,脑子就跑到兵马俑的千军万马去了. 去过兵马俑一回,完全没感觉 ...

  7. 乘法器——booth编码

    博主最近在学习加法器.乘法器.IEEE的浮点数标准,作为数字IC的基础.当看到booth编码的乘法器时,对booth编码不是很理解,然后在网上找各种理解,终于豁然开朗.现将一个很好的解释分享给大家,希 ...

  8. verilog乘法器以及booth编码改进

    第一章 整数乘法器 1.1 整数的概念 整数在IEEE 的规定上有,短整数short integer , 中整数integer 和 长整数long integer ,它们之间的关系如下: 整数 字节空 ...

  9. 【数字IC/FPGA】Wallace乘法器

    Wallace乘法器原理 为了简单起见,本文以4x4乘法器为例.如下图所示 Wallace乘法器的基本思想就是对输入进行3-2压缩,它采用的是一个类似全加器的结构:输入为三个数,输出为两个数,并且在逻 ...

  10. 【HDL系列】乘法器(2)——阵列乘法器

    目录 一.阵列乘法器 二.Verilog设计 一.阵列乘法器 将上文中的AB两数相乘的例子: 4比特的AB两数相乘的竖式计算表示成如下,为了区分,方便在阵列格式中看出差异,图中标记了不同的颜色,每组颜 ...

最新文章

  1. 关于学习Python的一点学习总结(6->元组)
  2. 关于站在主管的角度来看企业用人的一些规则
  3. spring配置文件中分别使用多个properties文件
  4. 成功解决Building wheels for collected packages: dlib Running setup.py bdist_wheel for dlib ... error
  5. 使用Vue构建中(大)型应用
  6. Snipaste在Window运行后遇到提示计算机中丢失 api-ms-win-crt-runtime-l1-1-0.dll 错误
  7. 企业数字化转型热潮下,IT技术领导者的10大使命
  8. 【OpenCV】图像旋转详解,边缘用黑色填充
  9. snabbdom vdom 框架
  10. 添加halcon图像显示控件_Halcon的C#二次开发及经验分享
  11. 商城管理系统源码 商城APP源码 电子商城源码
  12. 问卷设计:量表到底是要用5级还是6级?
  13. word批量替换向下箭头为回车符号、批量删除空行、批量空格与空行
  14. python说句心里话a_python第一周作业
  15. 你知道如何从零开始学c++游戏编程吗
  16. SSH 端口转发与 SOCKS 代理
  17. vue同一项目搭建PC端和移动端
  18. 矩阵旋转(左旋,右旋)
  19. 坑一:canal 的一处TODO 引发的一地华子
  20. 网站建设在网页界面设计中该如何做到简约

热门文章

  1. 【LaTex】3.2 数据结构(TikZ)
  2. 2021年全球与中国重型泥浆泵行业市场规模及发展前景分析
  3. IOT物联网的九大通信协议
  4. 使用 Laravel Sail 和 Laravel Octane 开发高性能 PHP 项目
  5. 给2016域用户限制登录时间并创建和删除一个OU
  6. 经典论文-MobileNetV3论文及实践
  7. 工作介绍xml书包文件
  8. 56282-36-1,Thiol-PEG3-alcohol巯基与马来酰亚胺、OPSS、乙烯砜和过渡金属表面反应
  9. android进度条随时间走,每天一点Android干货-时间与日期、进度条
  10. mysql数据库学习(keep update)