Booth算法的推倒表示看不懂,举例说明:算法的计算过程。
求M*Q的值 M=5,Q=6
按二进制分解M和Q :M3M2M1M0×Q3Q2Q1Q0:
0110×0101
(有符号数用补码表示,最高位表示正负)
1、添加辅助位:A=0000 Q-1=0
2、控制逻辑判断:
Q0Q-1=01
时:A=A+M 然后 A、Q、Q-1算术右移
(AQQ-1整体右移 如:表中的第一次右移AQQ-1=1010 0101 0,符号位填1
A=1101,Q=0010,Q-1=1)
Q0Q-1=10 时:A=A-M
然后 A、Q、Q-1算术右移
补码加减:(A-M)补码=A补码+(-M)补码
Q0Q-1=00或11 时:A、Q、Q-1算术右移
补码右移:空位填1
3、Q有几位就做几次右移运算。(如:01000×011,做3次右移结束)
4、结果即为AQ(0001 1110,即 6×5=30)。
运算过程和结果
A
Q
Q-1
M
初值
0000
0101
0
0110
A-M
1010
0101
0
0110
A,Q,Q-1右移
1101
0010
1
0110
A+M
0011
0010
1
0110
A,Q,Q-1右移
0001
1001
0
0110
A-M
1011
1001
0
0110
A,Q,Q-1右移
1101
1100
1
0110
A+M
0011
1100
1
0110
A,Q,Q-1右移
0001
1110
0
0110
verilog算法过程:
`timescale 1ns/1ps
//-----------------------------//
//----有符号数乘法
//-----------------------------//
module Booth_mult #(
parameter DW = 8
)(
input clk,
input rst_n,
input data_i_en,
input [DW-1:0] mult_a,
input [DW-1:0] mult_b,
output reg data_o_en,
output reg [DW+DW-1:0] result
);
parameter S_IDLE = 3'd0;
parameter S_JUDGE = 3'd1;
parameter S_01_ADD_SHIF = 3'd2;
parameter S_10_SUB_SHIF = 3'd3;
parameter S_00_11_SHIF = 3'd4;
parameter S_DONE = 3'd5;
reg [DW-1:0] mult_a_r;
reg [DW-1:0] mult_b_r;
reg [DW-1:0] assist_data = 'b0;
reg assist_bit = 0;
reg [DW-1:0] shift_count = 0;
wire [1:0] ctrl_bits;
assign ctrl_bits = {mult_b_r[0],assist_bit};
reg [2:0] state_nxt,state_cur;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
state_cur <= 3'b0;
else
state_cur <= state_nxt;
end
wire is_s_idle = state_cur == 3'b0;
wire is_s_judge = state_cur == 3'b1;
wire is_s_01_add_shif = state_cur == 3'd2;
wire is_s_10_sub_shif = state_cur == 3'd3;
wire is_s_00_11_shif = state_cur == 3'd4;
wire is_s_done = state_cur == 3'd5;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
mult_a_r <= 'b0;
else if(data_i_en)
mult_a_r <= mult_a;
else
mult_a_r <= mult_a_r;
end
always @(*) begin
case(state_cur)
S_IDLE : if(data_i_en == 1'b1)
state_nxt = S_JUDGE;
else
state_nxt = S_IDLE;
S_JUDGE : begin
if(shift_count == DW)
state_nxt = S_DONE;
else if(ctrl_bits == 2'b01)
state_nxt = S_01_ADD_SHIF;
else if(ctrl_bits == 2'b10)
state_nxt = S_10_SUB_SHIF;
else if(ctrl_bits == 2'b00 || ctrl_bits == 2'b11)
state_nxt = S_00_11_SHIF;
else
state_nxt = S_JUDGE;
end
S_01_ADD_SHIF : state_nxt = S_JUDGE;
S_10_SUB_SHIF : state_nxt = S_JUDGE;
S_00_11_SHIF : state_nxt = S_JUDGE;
S_DONE : state_nxt = S_IDLE;
default : state_nxt = 3'd0;
endcase
end
//------------shift_count移位计数器------------------//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
shift_count <= 0;
else if(is_s_idle)
shift_count <= 0;
else if(is_s_judge)
shift_count <= shift_count + 'b1;
else
shift_count <= shift_count;
end
//--------assist_data reg 也就是辅助位A----------------//
wire [DW-1:0] ass_add_multa = is_s_01_add_shif ? (assist_data +
mult_a_r) : 0;
wire [DW-1:0] ass_sub_multa = is_s_10_sub_shif ? (assist_data -
mult_a_r) : 0;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
assist_data <= 'b0;
else if(is_s_done)
assist_data <= 'b0;
else if(is_s_01_add_shif)
assist_data <= {ass_add_multa[DW-1],ass_add_multa[DW-1:1]};
else if(is_s_10_sub_shif)
assist_data <= {ass_sub_multa[DW-1],ass_sub_multa[DW-1:1]};
else if(is_s_00_11_shif)
assist_data <= {assist_data[DW-1],assist_data[DW-1:1]};
else
assist_data <= assist_data;
end
//------------------mult_b_r 也就是Q
--------------------------------//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
mult_b_r <= 'b0;
else if(is_s_done)
mult_b_r <= 'b0;
else if(data_i_en)
mult_b_r <= mult_b;
else if(is_s_01_add_shif)
mult_b_r <= {ass_add_multa[0],mult_b_r[DW-1:1]};
else if(is_s_10_sub_shif)
mult_b_r <= {ass_sub_multa[0],mult_b_r[DW-1:1]};
else if(is_s_00_11_shif)
mult_b_r <= {assist_data[0],mult_b_r[DW-1:1]};
else
mult_b_r <= mult_b_r;
end
//-------------assist_bit
也就是Qn-1------------------------------------------------------------------//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
assist_bit <= 1'b0;
else if(is_s_done)
assist_bit <= 1'b0;
else if(is_s_01_add_shif || is_s_10_sub_shif ||
is_s_00_11_shif)
assist_bit <= mult_b_r[0];
else
assist_bit <= assist_bit;
end
//---------------乘积={A,Q} =
{assist_data,mult_b_r}-------------------------//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
result <= 'd0;
else if(is_s_done)
result <= {assist_data,mult_b_r};
else
result <= result;
end
//-----------------输出有效---------------------------------------------//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
data_o_en <= 1'b0;
else if(is_s_idle)
data_o_en <= 1'b0;
else if(is_s_done)
data_o_en <= 1'b1;
else
data_o_en <= data_o_en;
end
endmodule
测试平台:
`timescale 1ns/1ps
`define BIT_DW 8 //8位乘法器
`define RANDOM_BS 2**(`BIT_DW-1)
module Booth_mult_tb;
reg clk,rst_n,data_i_en;
reg [5:0] mult_dw;
reg [`BIT_DW-1:0]mult_a,mult_b;
wire data_o_en;
wire [`BIT_DW+`BIT_DW-1:0] result;
always #5 clk = ~clk;
initial begin
clk = 0;
rst_n = 0;
mult_a = 0;
mult_b = 0;
data_i_en = 0;
#60 @(posedge clk);
rst_n = 1;
while(1) begin
data_i_en = 1;
mult_a = $random%`RANDOM_BS;
mult_b = $random%`RANDOM_BS;
@(posedge clk)
data_i_en = 0;
wait(data_o_en == 1'b1);
@(posedge clk)
if($signed(result) == $signed(mult_a)*$signed(mult_b))
begin
$display("mult_a = %d,mult_b = %d,result =
%d",$signed(mult_a),$signed(mult_b),$signed(result));
$display("\n test pass \n");
end
else begin
$display("mult_a = %d,mult_b = %d,result =
%d",$signed(mult_a),$signed(mult_b),$signed(result));
$display("\n test error \n");
#20;
$stop;
end
end
end
Booth_mult #(`BIT_DW) u_Booth_mult(
.clk(clk),
.rst_n(rst_n),
.data_i_en(data_i_en),
.mult_a(mult_a),
.mult_b(mult_b),
.data_o_en(data_o_en),
.result(result)
);
endmodule