二进制乘法器的主要操作就是加发法操作和移位操作。

我们知道计算机存储数据都是以二进制形式进行存储的,以4位数为例解释一下被乘数和乘数如何操作,首先把被乘数扩展成2倍的位宽,高4位为0,低4位为被乘数,结果为8为0,

先检测乘数的最低位,如果是1,则被乘数和结果想加,然后乘数右移,被乘数左移,如果是0,则被乘数左移,乘数右移。依次类推。

如下图:开始,product=00000000,Mcand=00000110,

Mer[0]==1,product==product+Mcand==00000110;Mer=0010,Mcand==00001100;

Mer[0]==0,Mer==0001,Mcand==00011000;

Mer[0]==1,product==product+Mcand==00011110;Mer=0000,Mcand==00110000;

Mer[0]==0,Mcand==01100000,Mer==0000;

end,product==00011110

代码入下:

module multiplier (clk,rst_n,multiplier,multiplicand,start,done,product);

input clk;//50M

input rst_n;

input [7:0]multiplier;

input [7:0]multiplicand;

input start;

output done;

output [15:0]product;

reg [2:0]i;

reg isdone;

reg [15:0]temp;

reg isneg;

reg [7:0]Mer;

reg [15:0]Mcand;

reg [2:0]cnt;

always @ (posedge clk or negedge rst_n)

if(!rst_n)

begin

i<=1'b0;

isdone<=1'b0;

temp<=16'd0;

Mer<=8'd0;

Mcand<=1'b0;

isneg<=1'b0;

cnt<=1'b0;

end

else if (start)

case

(i)

0:

begin i<=i+1'b1;

isneg<=multiplier[7]^multiplicand[7];

Mer<=multiplier[7]?(~multiplier+1'b1):multiplier;

Mcand<={multiplicand[7]?(~multiplicand+1'b1):multiplicand}&16'h00ff;

temp<=16'd0;

cnt<=1'b0;

end

1:

if(cnt==6)

i<=3'd3;

else if

(Mer[0]) begin temp<=temp+Mcand;

i<=i+1'b1;

end

else

i<=i+1'b1;

2:  begin

Mer<=Mer>>1;

Mcand<=Mcand<<1;

i<=i-1'b1;

cnt<=cnt+1'b1;

end

3:begin isdone<=1'b1;

i<=i+1'b1;

end

4:begin isdone<=1'b0;

i<=1'b0;

end

default

:i<=3'b000;

endcase

assign done=isdone;

assign product=isneg?(~temp+1'b1):temp;

endmodule

加粗行用于执行加法操作,斜体部分用于执行移位操作。

测试代码:

`timescale 1 ns/ 1

ps

module multiplier_vlg_tst();

reg clk;

reg [7:0] multiplicand;

reg [7:0] multiplier;

reg rst_n;

reg start;

wire done;

wire [15:0] product;

multiplier i1 (

.clk(clk),

.done(done),

.multiplicand(multiplicand),

.multiplier(multiplier),

.product(product),

.rst_n(rst_n),

.start(start)

);

initial

begin

rst_n=0;

#30;

rst_n=1;

clk=1;

forever #10 clk=~clk;

end

reg [3:0]i;

always @(posedge clk or negedge rst_n)

if (!rst_n)

begin i<=4'd0;

start<=1'b0;

multiplier<=8'd0;

multiplicand<=8'd0;

end

else

case(i)

0:

if (done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd2;

multiplicand<=8'd10;

start<=1'b1;

end

1:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd10;

multiplicand<=8'd2;

start<=1'b1;

end

2:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd20;

multiplicand<=8'd5;

start<=1'b1;

end

3:

if

(done)

begin

start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd2;

multiplicand<=8'b11110110;

//-10

start<=1'b1;

end

4:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11111110;

//-2

multiplicand<=8'd10;

start<=1'b1;

end

5:

if

(done)

begin

start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11110110;

//-10

multiplicand<=8'd2;

start<=1'b1;

end

6:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11111110;

//-2

multiplicand<=8'b11110110;

//-10

start<=1'b1;

end

7:

if (done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11110110;

//-10

multiplicand<=8'b11111110;

//-2

start<=1'b1;

end

8:i<=4'd8;

default:i<=4'd8;

endcase

endmodule

仿真结果:

结果看出:8位有符号的数,7位标志数的大小,一位符号位,所以每一位数据都要进行加和移操作耗2个时钟周期,共消耗2*7=14个时钟周期。所以无论8位多大的数都消耗14个时钟周期用于计算。

修改之后二进制乘法器

module multiplier

(clk,rst_n,multiplier,multiplicand,start,done,product);

input

clk;//50M​

​ input rst_n;

input

[7:0]multiplier;

input [7:0]multiplicand;

input start;

output done;

output [15:0]product;

reg [1:0]i;

reg isdone;

reg [15:0]temp;

reg isneg;

reg [7:0]Mer;

reg [15:0]Mcand;

reg [2:0]cnt;

always @ (posedge clk or negedge rst_n)

if(!rst_n) begin

i<=1'b0;

isdone<=1'b0;

temp<=16'd0;

Mer<=8'd0;

Mcand<=1'b0;

isneg<=1'b0;

cnt<=1'b0;

end

else if (start)

case (i)

0:

begin

i<=i+1'b1;

isneg<=multiplier[7]^multiplicand[7];

Mer<=multiplier[7]?(~multiplier+1'b1):multiplier;

Mcand<={multiplicand[7]?(~multiplicand+1'b1):multiplicand}&16'h00ff;

temp<=16'd0;

cnt<=1'b0;

end

1:​

if(cnt==6)

i<=2'd2;

else if

(Mer[0]) begin temp<=temp+Mcand;

Mer<=Mer>>1;

Mcand<=Mcand<<1;

cnt<=cnt+1'b1;

end

else

begin

Mer<=Mer>>1;

Mcand<=Mcand<<1;

cnt<=cnt+1'b1;

end

2:

begin

isdone<=1'b1;

​55

i<=i+1'b1;

​end

3:begin

isdone<=1'b0;

i<=1'b0;

end

default

:i<=2'b00;

endcase

assign done=isdone;

assign

product=isneg?(~temp+1'b1):temp;

endmodule​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

行把加法和移位放在一起。​

测试代码无变化,如下:

`timescale 1 ns/ 1 ps

module multiplier_vlg_tst();

reg clk;

reg [7:0] multiplicand;

reg [7:0] multiplier;

reg rst_n;

reg start;

wire done;

wire [15:0] product;

multiplier i1 (

.clk(clk),

.done(done),

.multiplicand(multiplicand),

.multiplier(multiplier),

.product(product),

.rst_n(rst_n),

.start(start)

);

initial

begin

rst_n=0;

#30;

rst_n=1;

clk=1;

forever #10 clk=~clk;

end

reg [3:0]i;

always @(posedge clk or negedge rst_n)

if (!rst_n)

begin i<=4'd0;

start<=1'b0;

multiplier<=8'd0;

multiplicand<=8'd0;

end

else

case(i)

0:

if (done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd2;

multiplicand<=8'd10;

start<=1'b1;

end

1:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd10;

multiplicand<=8'd2;

start<=1'b1;

end

2:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd20;

multiplicand<=8'd5;

start<=1'b1;

end

3:

if

(done)

begin

start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'd2;

multiplicand<=8'b11110110;

//-10

start<=1'b1;

end

4:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11111110;

//-2

multiplicand<=8'd10;

start<=1'b1;

end

5:

if

(done)

begin

start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11110110;

//-10

multiplicand<=8'd2;

start<=1'b1;

end

6:

if

(done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11111110;

//-2

multiplicand<=8'b11110110;

//-10

start<=1'b1;

end

7:

if (done)

begin start<=1'b0;

i<=i+1'b1;

end

else

begin

multiplier<=8'b11110110;

//-10

multiplicand<=8'b11111110;

//-2

start<=1'b1;

end

8:i<=4'd8;

default:i<=4'd8;

endcase

endmodule

仿真结果:

从结果中可以看出只消耗了7个时钟周期用于计算,比前面的二进制加法器的用于计算消耗的时钟周期少了一倍。

Booth乘法器

它是对乘数重新编码,以减少乘法运算所需要的加法运算次数,他是只对乘数重新编码,而被乘数保持不变。得到的形式称为基4重新编码或比特对编码。使用booth乘法可以对两个数直接相乘,不需要考虑正数和负数。

具体操作:以8位为例

Product定义为17为用于保存结果,初始为product={8’b0,乘数,1’b0}

定义两个8位寄存器:A和B,A=被乘数,B=被乘数取反加1;

如果product最低两位为,01,product高8位加A,然后product右移一位;

如果product最低两位为10,product高8位加B,然后product右移一位;

如果product最低两位为11或00, product右移一位;

直到8位右移结束。

booth乘法器 c语言,二进制乘法器的FPGA实现(常规和Booth乘法器)相关推荐

  1. c语言4位二进制乘法器设计,四位二进制乘法器 c语言.doc

    <四位二进制乘法器 c语言.doc>由会员分享,提供在线免费全文阅读可下载,此文档格式为doc,更多相关<四位二进制乘法器 c语言.doc>文档请在天天文库搜索. 1.//四 ...

  2. vhdl语言入门_从当初汇编、C语言入手,到如今FPGA开发已然十年,总结出“三多”!...

    从大学时代第一次接触FPGA至今已有10多年的时间,至今记得当初第一次在EDA实验平台上完成数字秒表.抢答器.密码锁等实验时那个兴奋劲.当时由于没有接触到HDL硬件描述语言,设计都是在MAX+plus ...

  3. 基于vivado(语言Verilog)的FPGA学习(3)——FPGA理论知识

    基于vivado(语言Verilog)的FPGA学习(3)--FPGA理论知识 文章目录 基于vivado(语言Verilog)的FPGA学习(3)--FPGA理论知识 1. FPGA介绍 1.1.F ...

  4. C语言二进制转换为八进制(附完整源码)

    C语言二进制转换为八进制 C语言二进制转换为八进制完整源码 C语言二进制转换为八进制完整源码 #include <stdio.h>// Function that returns the ...

  5. C语言二进制转换为十六进制(附完整源码)

    C语言二进制转换为十六进制 C语言二进制转换为十六进制完整源码 C语言二进制转换为十六进制完整源码 #include <stdio.h>int main() {long int binar ...

  6. c语言二进制转十进制(附完整源码)

    c语言二进制转十进制 c语言二进制转十进制完整源码 c语言二进制转十进制完整源码 #include <stdio.h>int main() {int remainder, number = ...

  7. C语言---二进制和文本文件的备份

    C语言-二进制和文本文件的备份 学习参考: https://www.cnblogs.com/jackytang/p/9011127.html 代码: #include <stdio.h> ...

  8. c语言 二进制压缩算法_使用C ++解释的二进制搜索算法

    c语言 二进制压缩算法 by Pablo E. Cortez 由Pablo E.Cortez 使用C ++解释的二进制搜索算法 (Binary Search Algorithms Explained ...

  9. C语言二进制求数集子集

    C语言二进制求数集子集 题目:编写一个程序,对输入的正整数n,输出{0,1,-,n-1}的所有子集.例如,输入3时,输出如下: {}, {0}, {1}, {0,1}, {2}, {0,2}, {2, ...

最新文章

  1. 深入浅出聚类算法!如何对王者英雄聚类分析,探索英雄之间的秘密
  2. 使用C++基于Socket编程实现文件下载(改进-封装成类)
  3. 鸟哥的Linux私房菜10.16 vim程序编辑器
  4. SQLServer 2012 报表服务部署配置(1)
  5. scala------------:: , +:, :+, :::, +++的区别
  6. Handler延迟事件使用
  7. HttpURLConnection简单用法
  8. SpringMVC工作原理 1
  9. javascript 设计模式_用英雄联盟的方式讲解JavaScript设计模式(二)
  10. dlut-KFQ人工智能导论答案1
  11. 2014,都要好好的~
  12. 设计模式笔记之六:生产消费者模式
  13. 十分钟一起学会ResNet残差网络
  14. 安装SQL server 提示重新启动计算机失败
  15. 怎么查看ofd格式电子发票? 2种简单方法免费查看
  16. ARCGIS 给面文件“挖洞”——Erase的用法
  17. 计算机磁盘管理分盘可以撤销吗,电脑磁盘出现随便分盘不合理,怎么样重新分盘...
  18. 现在有哪些好用的企业报表软件?
  19. 摄像机码流平滑参数解析
  20. Linux攻关之基础模块十 特殊权限

热门文章

  1. flutter不支持热更新_在iOS原生项目中使用Flutter,热更新
  2. 信息收集之查找GitHub作者邮箱
  3. 12:企业规范约束-MySQL
  4. 疗效预测中的影像组学特征提取
  5. socket监听端口实现实时通讯
  6. 一个类的例子--员工工资
  7. 山东大学软件学院高级语言课程设计JAVA课程设计-学生在线考试系统平台
  8. Android 启动广告页
  9. EP06-局域网和广域网通信原理
  10. VHDL学习笔记-(1)Generic类属