Verilog--乘法器Booth算法

更新时间:2023-07-22 19:39:10 阅读: 评论:0

Verilog--乘法器Booth 算法
Verilog – 乘法器Booth 算法
@(知识点汇总)
⽂章⽬录
1. 原理
Booth算法的原理其实⼩学初中就学过,⽐如下⾯这道题:
简便计算:随便抓个娃娃来都知道应该这么算:
我们都知道在⼗进制⾥,10的倍数的乘法很容易,就是后⾯加⼏个0的事情,⽽上⾯这种简便计算都有个特点,就是会有999,1001,997,1002这种数,0和9出现的次数很多,这样就可以通过变为化简变为简单的乘法和加减法。
**对于⼆进制数,这种简便计算的情况往往更多。**因为计算机中为了计算⽅便,往往将数据转换为补码的形式,⽽补码形式在计算时会扩展符号位,⽐如有符号数补码5’b10110 = -10,在计算与⼀个8位数相
加时会扩展为8‘b11110110,可以发现,这种数往往会有很多连续的1出现,这跟上⾯的简便计算的例⼦⾮常相似。⽐如:
这就是booth算法分解乘数的基本原理。
2. ⼀般化推论
假设A和B是乘数和被乘数,且有:山东济南旅游景点有哪些
KaTeX par error: No such environment: align at position 8: \begin{a l i g n } A &= a_{n-1}a_…
最后的Val(A)的表达式实际上就是补码A表⽰的原码。
3. 实际算法
上⾯的公式推导了booth乘法对乘数的分解原理,实际上在编码时只需要公式3,可以做如下的编码表:
操作0
00⽆1
0-1减B 1
10⽆011加B
举个栗⼦:
⾸先计算-B的补码(算法中要⽤到):以及A的补码:硬件计算过程如下:
⾸先初始化p空间:.[A]和[Q]是两个寄存器。其中[Q]是N+1位的。
8754×998=?
8754×998=8754×1000−8754×2
0011110=0100000−0000010=2−521
a i
a i −1a −i −1a i N =7,B =22=(0010110),A =2−34=−(0100010)2
=−B (1101010)2
=A (1011110)2
p =2N +1
白组词1. ⾸先将乘数A的补码放到[Q]的⾼N位上,Q的最低为默认为0.(这步是为了时,让。
2. 在Q中检查,得00,查表得⽆操作,直接将[A]和[Q]合起来右移(算数移位)
3. 在Q中检查,得10,查表得减B,相当于加-B的补码,在[A]寄存器中加上-B的补码,之后右移
美国代理服务器4. …
最后的结果11110100010100就是结果的补码,也就是:
算法跟公式的匹配:
实际上,对于公式中的每⼀项都对应实际算法中的每⼀步。决定了B的系数,右移操作因为作⽤在[A]
[Q]寄存器上,所以实际上是相当于将积右移,等价于B左移,所以这⼀步对应操作。加减B的操作都作⽤在[A]寄存器上,保证了后的B能够作⽤在正确的位上。
4. Verilog 代码
深圳买房资格
这⾥只放⼀种状态机实现的时序逻辑电路,计算过程基本跟上⾯的算法⼀样。
参考了
的代码,提供者fanhu, fh_
`timescale 1ns/1ps
module booth_fsm
# (parameter DATAWIDTH = 8)
(劳动合同下载
input                        clk,
input                        rstn,
input                        en,
input        [DATAWIDTH-1:0] multiplier,
input        [DATAWIDTH-1:0] multiplicand,
output reg                  done,
output reg [2*DATAWIDTH-1:0] product
);
parameter  IDLE  = 2'b00,
ADD    = 2'b01,
SHIFT  = 2'b11,
OUTPUT = 2'b10;
reg  [1:0]              current_state, next_state;  // state registers.
reg  [2*DATAWIDTH+1:0]  a_reg,s_reg,p_reg,sum_reg;  // computational values.
reg  [DATAWIDTH-1:0]    iter_cnt;                  // iteration count for determining when done.
wire [DATAWIDTH:0]      multiplier_neg;            // negative value of multiplier
always @(podge clk or negedge rstn)
if (!rstn) current_state = IDLE;
el current_state <= next_state;
// state transform
always @(*) begin
next_state = 2'bx;
ca (current_state)
IDLE  : if (en) next_state = ADD;
el    next_state = IDLE;
ADD  : next_state = SHIFT;
SHIFT : if (iter_cnt==DATAWIDTH) next_state = OUTPUT;
el            next_state = ADD;
OUTPUT: next_state = IDLE;
endca锲而不舍怎么读
i =0a =−10a −i −1a i a −i −1a i B ×A ==11110100010100(10001011101100)=原−74810
(a −i −1a )×i B ×2i (a −i −1a )i ×2i ×2i
endca
end
// negative value of multiplier.
assign multiplier_neg = -{multiplier[DATAWIDTH-1],multiplier};
// algorithm implemenation details.
always @(podge clk or negedge rstn) begin
if (!rstn) begin
{a_reg,s_reg,p_reg,iter_cnt,done,sum_reg,product} <= 0;
end el begin
ca (current_state)
IDLE :  begin
a_reg    <= {multiplier[DATAWIDTH-1],multiplier,{(DATAWIDTH+1){1'b0}}};
s_reg    <= {multiplier_neg,{(DATAWIDTH+1){1'b0}}};
p_reg    <= {{(DATAWIDTH+1){1'b0}},multiplicand,1'b0};
iter_cnt <= 0;
done    <= 1'b0;
end
ADD  :  begin
ca (p_reg[1:0])
2'b01      : sum_reg <= p_reg+a_reg; // + multiplier
2'b10      : sum_reg <= p_reg+s_reg; // - multiplier
2'b00,2'b11 : sum_reg <= p_reg;      // nop
endca
iter_cnt <= iter_cnt + 1;
end
SHIFT :  begin
p_reg <= {sum_reg[2*DATAWIDTH+1],sum_reg[2*DATAWIDTH+1:1]}; // right shift    end
OUTPUT : begin
product <= p_reg[2*DATAWIDTH:1];
done <= 1'b1;
end
endca
end
end
endmodule
testbench:
`timescale 1ns/1ps
// Basic exhaustive lf checking test bench.
`define TEST_WIDTH 10
module booth_fsm_tb;
reg clk;
reg rstn;
笔记本有蓝牙吗reg en;
integer multiplier1;
integer multiplicand1;
reg [`TEST_WIDTH-1:0] multiplier;
reg [`TEST_WIDTH-1:0] multiplicand;
wire    done;
//输⼊:要定义有符号和符号,输出:⽆要求
wire signed [2*`TEST_WIDTH-1:0] product;
wire signed [`TEST_WIDTH-1:0]                m1_in;
wire signed [`TEST_WIDTH-1:0]                m2_in;
reg  signed [2*`TEST_WIDTH-1:0] product_ref;
reg  [2*`TEST_WIDTH-1:0] product_ref_u;
assign m1_in = multiplier[`TEST_WIDTH-1:0];
assign m2_in = multiplicand[`TEST_WIDTH-1:0];
assign m2_in = multiplicand[`TEST_WIDTH-1:0];
booth_fsm #(.DATAWIDTH(`TEST_WIDTH)) booth
(
.clk(clk),
.
rstn(rstn),
.en(en),
.multiplier(multiplier),
.multiplicand(multiplicand),
.done  (done),
.product(product)
);
always #1 clk = ~clk;
integer num_good;
integer i;
initial begin
clk = 1;
en = 0;剧情片
rstn = 1;
#2 rstn = 0; #2 rstn = 1;
num_good = 0;
multiplier=0;
multiplicand=0;
#8;
for(i=0;i<4;i=i+1) begin
en = 1;
multiplier=10'b10000_00000+i;
multiplicand=10'b00000_00010+i;
wait (done == 0);
wait (done == 1);
product_ref=m1_in*m2_in;
product_ref_u=m1_in*m2_in;
if (product_ref !== product)
$display("multiplier = %d multiplicand = %d proudct =%d",m1_in,m2_in,product);        @(podge clk);
end
$display("sim done. num good = %d",num_good);
end
initial begin
$fsdbDumpvars();
$fsdbDumpMDA();
$dumpvars();
#1000 $finish;
end
endmodule
仿真波形:

本文发布于:2023-07-22 19:39:10,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1111377.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:补码   计算   算法   右移
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图