电子说
布斯算法介绍
Booth 的算法检查有符号二的补码表示中 'N'位乘数 Y 的相邻位对,包括低于最低有效位 y−1 = 0 的隐式位。对于每个位 yi,对于从 0 到 N − 1 的 i,考虑位 yi 和 yi−1。当这两个位相等时,乘积累加器P保持不变。其中 yi = 0 且 yi−1 = 1,乘以 2i 添加到 P;其中 yi = 1 且 yi−1 = 0,则从 P 中减去乘以 2i。P 的最终值为有符号结果。
未指定乘数和乘积的表示形式;通常,这些也都在二的补码表示中,就像乘数一样,但是任何支持加法和减法的数字系统也可以工作。如此处所述,步骤的顺序尚未确定。通常,它从LSB到MSB,从i = 0开始;然后乘以2i通常被P累加器在步长之间向右的增量移位所取代;低位可以移出,然后可以在P的最高N位上进行后续的加法和减法。
该算法通常被描述为将乘数中 1 的字符串转换为字符串末端的高阶 +1 和低阶 −1。当字符串通过 MSB 运行时,没有高阶 +1,并且净效应被解释为相应值的负数。
计算步骤
使用的寄存器:A,M,Q,Qres(Qres是Q右移后的残余位),n(计数器)
第1步: 加载寄存器的初始值。
A = 0(累加器),Qres = 0,M = 乘法,Q = 乘法器,n是等于乘法器位数的计数值。
第2步: 检查 {Q0,Qres} 的值。如果为 00 或 11,请转到步骤 5。如果为01,转到步骤3。如果为 10,转到步骤 4。
第3步: 执行 A = A + M,转到步骤 5。
第4步: 执行 A = A - M。
第5步: 执行 {A,Q,Qres} 的算术位移和递减计数。
第6步: 检查计数器值 n 是否为零。如果是,请转到下一步。否则转到步骤 2。
第7步: 停止计算,输出计算结果。
计算流程图
以下是布斯计算的流程图,从图中可以清楚的看出计算的过程,简单的来说就是判定乘数的最低位和次低位,如果两位相同则直接执行移位操作,如果两者不同,如为“10”则将原始值减去被乘数,如为“01”则将原始值加上被乘数。
举个栗子
下面就以被乘数为6,乘数为-4为例,做一个计算过程的举例。
Verilog 实现
设计思想
总的来说和上面提到的计算步骤是一致的,利用三段状态机实现,分别为空闲状态、计算状态和完成状态,其中空闲状态等待开始计算信号的到来,计算状态完成布斯计算步骤,完成状态输出结果数据以及同步的有效标志信号。
Verilog 代码
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*Engineer : Linest-5
/*File : booth_multiple.v
/*Create : 2022-08-27 16:40:34
/*Revise : 2022-08-27 16:40:34
/*Module Name : booth_multiple
/*Description : 基于布斯算法的乘法器设计
/*Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
modulebooth_multiple(
inputclk,
inputrst,
inputstart,
inputsigned [3:0] X,
inputsigned [3:0] Y,
outputreg signed [7:0] Z,
outputvalid
);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*参数和信号申明 */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
parameterIDLE = 3'b001;
parameterCACULATE = 3'b010;
parameterFINISH = 3'b100;
reg[2:0] state;
reg[2:0] next_state;
reg[1:0] q_reg; //右移最后两位寄存
reg[2:0] cnt; //右移次数计数信号
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*三段状态机 */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//状态机第一段,状态初始化,时序逻辑非阻塞赋值
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
//状态机第二段,状态跳转,组合逻辑阻塞赋值
always @(*) begin
next_state = state;
case(state)
IDLE: begin
if (start) begin
next_state = CACULATE;
end
else begin
next_state = IDLE;
end
end
CACULATE: begin
if (cnt == 'd3) begin
next_state = FINISH;
end
else begin
next_state = CACULATE;
end
end
FINISH: begin
next_state = IDLE;
end
endcase
end
//状态机第三段,结果输出,时序逻辑非阻塞赋值
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt <= 'd0;
q_reg <= 'd0;
Z <= 'd0;
end
else begin
case(state)
IDLE: begin
cnt <= 'd0;
q_reg <= {Y[cnt],1'b0};
Z <= {4'b0000,Y};
end
CACULATE: begin
cnt <= cnt + 'd1;
q_reg <= {Y[cnt+1],Y[cnt]};
case(q_reg)
2'b00,2'b11: begin
Z <= $signed(Z) > > >1;
end
2'b10: begin
Z <= $signed({Z[7:4]-X,Z[3:0]}) > > >1;
end
2'b01: begin
Z <= $signed({Z[7:4]+X,Z[3:0]}) > > >1;
end
endcase
end
FINISH: begin
cnt <= 'd0;
q_reg <= 'd0;
Z <= Z;
end
endcase
end
end
assign valid = (state==FINISH);
endmodule
TestBench 代码
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Engineer : Linest-5
/* File : tb_booth_multiple.v
/* Create : 2022-08-27 19:22:46
/* Revise : 2022-08-27 20:21:49
/* Module Name : tb_booth_multiple
/* Description : 基于布斯算法的乘法器仿真模块
/* Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
module tb_booth_multiple();
reg clk;
reg rst;
reg start;
reg signed [3:0] X;
reg signed [3:0] Y;
wire signed [7:0] Z;
wire valid;
initial begin
clk = 'd0;
rst = 'd1;
#20
rst = 'd0;
end
always #10 clk = ~clk;
initial begin
#20
X = 6;
Y = -4;
start = 'd0;
#50
start = 'd1;
#20
start = 'd0;
#200
X = 7;
Y = -5;
start = 'd1;
#20
start = 'd0;
#200
X = 7;
Y = 5;
start = 'd1;
#20
start = 'd0;
end
booth_multiple inst_booth_multiple (
.clk (clk),
.rst (rst),
.start (start),
.X (X),
.Y (Y),
.Z (Z),
.valid (valid)
);
endmodule
仿真波形
分别进行有符号的乘法,6和-4、7和-5、7和5,可以看到仿真波形中,正确的得到了计算结果,并且有效标志信号也同步输出。
验证成功!
全部0条评论
快来发表一下你的评论吧 !