1.booth乘法器原理
對(duì)于一個(gè)n位的有符號(hào)二進(jìn)制數(shù)B,首位是0則B可以表示為:
首位是1,B[n-2:0]是實(shí)際數(shù)字的補(bǔ)碼,所以可以得到
。
可以得到合并的公式如下所示:
將公式展開:
除了n-1項(xiàng)外的每一項(xiàng)乘2之后再減去本身:
根據(jù)2^i重構(gòu)公式:
為了統(tǒng)一形式,添加一項(xiàng)B[-1],初始值為0.注意這里的B[-1]是一個(gè)單獨(dú)的寄存器,與B并沒有關(guān)系則B可以修改為
2.乘法器模塊設(shè)計(jì)
對(duì)于上一章節(jié)的B的公式我們可以看出,實(shí)際關(guān)注的是B中相鄰兩位的大小,所以可以對(duì)B進(jìn)行移位處理即可每次只關(guān)注B[0]B[-1],同時(shí)A乘的2的i次方也是對(duì)A進(jìn)行移位。綜上我們可以構(gòu)建一個(gè)新的向量array,用來移位和計(jì)算累加和。
從i=0開始計(jì)算累加和,對(duì)累加和的計(jì)算總共有三種情況:
{ B[i],B[i-1] } = 2'b00或2'b11 :B[i-1]-B[i] = 0,無操作
{ B[i],B[i-1] } = 2'b01 :B[i-1]-B[i] = 1,相加
{ B[i],B[i-1]} = 2'b10 :B[i-1]-B[i] = -1,相減
不妨設(shè)計(jì)算兩個(gè)四位的二進(jìn)制數(shù)相乘,首先定義一個(gè)四位的寄存器Q用來計(jì)算累加和。在這里可能會(huì)有個(gè)疑問,四位二進(jìn)制數(shù)相加結(jié)果應(yīng)該是五位的數(shù),為什么這里只需要設(shè)四位。
所以array的實(shí)際組成是array = {Q,B,B[-1]};Q和B[-1]的初始值都是0.每次計(jì)算都是先根據(jù)B[0]B[-1]的結(jié)果,計(jì)算Q的值,然后進(jìn)行算術(shù)右移。并定義一個(gè)計(jì)數(shù)器用來計(jì)算執(zhí)行次數(shù),總次數(shù)即為B的位數(shù)。
我們可以發(fā)現(xiàn)第一次計(jì)算的Q到最后是移位到了最末端,這種計(jì)算方式和普通移位的區(qū)別是,普通方法是將2^i,左移i次,而本節(jié)的方式是將數(shù)從高位右移,實(shí)際結(jié)果相同。
下面給出7*(-5)的例子作為參考
-----------------------------------------初始化------------------------------------------
設(shè)4-bit A , 4-bit B , 4-bit Q ,1-bit B[-1]
A = 0111(7);
-A = 1001;
B = 1011(-5);
Q = 0000;
B[-1] = 0;
B[0]B[-1] = 10;
{Q,B,B[-1]} = 0000_1011_0;
-----------------------------------------count = 3---------------------------------------
----------------------------------------計(jì)算累加和---------------------------------------
B = 1011;
B[-1] = 0;
B[0]B[-1] = 10;
Q = Q - A = 1001;
{Q,B,B[-1]} = 1001_1011_0
--------------------------------------------移位-----------------------------------------
{Q,B,B[-1]} = 1100_1101_1
-----------------------------------------count = 2---------------------------------------
-----------------------------------------計(jì)算累加和-------------------------------------
Q = 1100;
B = 1101;
B[-1] = 1;
B[0]B[-1] = 11;無操作
Q = Q = 1100;
{Q,B,B[-1]} = 1100_1101_1
--------------------------------------------移位-----------------------------------------
{Q,B,B[-1]} = 1110_0110_1
-----------------------------------------count = 1---------------------------------------
-----------------------------------------計(jì)算累加和-------------------------------------
Q = 1110;
B = 0110;
B[-1] = 1;
B[0]B[-1] = 01;相加
Q = Q + A = 1110 + 0111 = 0101;
{Q,B,B[-1]} = 0101_0110_1
--------------------------------------------移位-----------------------------------------
{Q,B,B[-1]} = 0010_1011_0
-----------------------------------------count = 0---------------------------------------
-----------------------------------------計(jì)算累加和-------------------------------------
Q = 0010;
B = 1011;
B[-1] = 0;
B[0]B[-1] = 10;相減
Q = Q - A = 0010 + 1001 = 1011;
{Q,B,B[-1]} = 1011_1011_1;
--------------------------------------------移位-----------------------------------------
{Q,B,B[-1]} = 1101_1101_1;
--------------------------------------------輸出-----------------------------------------
CO = 1101_1101;
3.verilog代碼與testbench
3.1 verilog代碼
module boothmultiplier_radix2#(
parameter size = 4
)
(
clk,
rst_n,
valid_i,
receive_i,
multiplicand_i,
multiplier_i,
busy_o,
ready_o,
result_o
);
input wire clk;
input wire rst_n;
input wire valid_i;
input wire receive_i;
input wire signed [size-1:0] multiplicand_i;
input wire signed [size-1:0] multiplier_i;
output reg busy_o;
output reg ready_o;
output wire signed [2*size-1:0] result_o;
reg signed [2*size:0] array;
reg [size-1:0] M;
reg [size-1:0] Q;
reg [1:0] count;
localparam STATE_IDLE = 2'b00;
localparam STATE_CALC = 2'b01;
localparam STATE_SHIFT = 2'b10;
localparam STATE_END = 2'b11;
reg [1:0] state,next_state;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state <= STATE_IDLE;
end else begin
state <= next_state;
end
end
always@(*)begin
if(!rst_n)begin
next_state = STATE_IDLE;
end else begin
case (state)
STATE_IDLE: begin
if(valid_i)begin
next_state = STATE_CALC;
end else begin
next_state = STATE_IDLE;
end
end
STATE_CALC: begin
next_state = STATE_SHIFT;
end
STATE_SHIFT: begin
if(count == 0)begin
next_state = STATE_END;
end else begin
next_state = STATE_CALC;
end
end
STATE_END: begin
if(receive_i)begin
next_state = STATE_IDLE;
end else begin
next_state = STATE_END;
end
end
default: next_state = STATE_IDLE;
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
array <= 'b0;
M <= 'b0;
Q <= 'b0;
ready_o <= 1;
busy_o <= 0;
count <= 0;
end else begin
case(state)
STATE_IDLE: begin
if(valid_i)begin
ready_o <= 0;
busy_o <= 1;
M <= multiplicand_i;
Q <= multiplier_i;
count <= 2'd3;
array <= {4'b0,multiplier_i,1'b0};
end else begin
array <= 'b0;
M <= 'b0;
Q <= 'b0;
ready_o <= 1;
busy_o <= 0;
count <= 2'b0;
end
end
STATE_CALC: begin
case({array[1:0]})
2'b00,2'b11:begin
array <= array;
end
2'b01:begin
array <= (array + {M[size-1:0],{(size+1){1'b0}}});
end
2'b10:begin
array <= (array - {M[size-1:0],{(size+1){1'b0}}});
end
endcase
end
STATE_SHIFT: begin
if(count != 0)begin
count <= count -1;
end else begin
count <= 2'd3;
busy_o <= 0;
ready_o <= 1;
end
array <= array >>> 1;
end
STATE_END: begin
if(receive_i)begin
busy_o <= 0;
ready_o <= 1;
end else begin
busy_o <= 1;
ready_o <= 0;
end
end
default: begin
array <= 'b0;
M <= 'b0;
Q <= 'b0;
busy_o <= 0;
count <= 2'd3;
end
endcase
end
end
assign result_o = (state == STATE_END)?array[8:1]:0;
endmodule
3.2 testbench
module Top_tb
();
reg clk;
reg rst_n;
reg valid_i;
reg signed [3:0] multiplicand_i;
reg signed [3:0] multiplier_i;
reg receive_i;
wire [3:0]result_o;
wire ready_o;
wire busy_o;
boothmultiplier_radix2#(
.size(4)
)
UUT(
.clk(clk),
.rst_n(rst_n),
.valid_i(valid_i),
.receive_i(receive_i),
.multiplicand_i(multiplicand_i),
.multiplier_i(multiplier_i),
.busy_o(busy_o),
.ready_o(ready_o),
.result_o(result_o)
);
initial begin
clk = 0;
rst_n = 0;
#100
rst_n = 1;
#100
wait(clk);
multiplicand_i = 4'b0111;
multiplier_i = 4'b1011;
valid_i = 1;
#20
valid_i = 0;
wait(ready_o);
receive_i = 1;
multiplicand_i = 4'b0101;
multiplier_i = 4'b1001;
valid_i = 1;
#1000
$stop;
end
always #10 clk = ~clk;
endmodule
4.評(píng)價(jià)與展望
1、由于計(jì)算和移位在同一周期內(nèi)實(shí)現(xiàn)并不是很好寫,也為了更加直觀,代碼中將計(jì)算和移位分在兩個(gè)周期中完成,導(dǎo)致計(jì)算速度會(huì)將近降了一倍。
2、輸出result_o采用的是wire類型輸出,也可修改為reg輸出,更加穩(wěn)定。
3、后續(xù)可加入流水線,增加數(shù)據(jù)吞吐量。文章來源:http://www.zghlxwxcb.cn/news/detail-775379.html
4、testbench并不完整,只是給了個(gè)框架,有興趣的朋友可以完善一下。文章來源地址http://www.zghlxwxcb.cn/news/detail-775379.html
到了這里,關(guān)于基2-booth乘法器原理及verilog代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!