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

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

我们知道计算机存储数据都是以二进制形式进行存储的,以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

a4c26d1e5885305701be709a3d33442f.png

代码入下:

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

仿真结果:

a4c26d1e5885305701be709a3d33442f.png

结果看出: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

仿真结果:

a4c26d1e5885305701be709a3d33442f.png

从结果中可以看出只消耗了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位右移结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值