32位Booth乘法器的原理和Verilog代码 25位 【转】
(2012-05-31 21:26:42)
标签:
杂谈 |
分类: FPGA信号处理 |
Booth算法就是对乘数从低位开始判断,根据两个数据位的情况决定进行加法、减法还是仅仅移位操作。判断的两个数据位位当前位及其右边的位(初始化需要增加一个辅助位0),移位操作是向右移动。当二进制数第一次遇到1时,可以用减法取代一串的1,而当遇到最后一个1后面的0时,再加上被乘数。
假设X、Y都是用补码形式表示的机器数,[X]补和[Y]补=Ys.Y1Y2…Yn,都是任意符号表示的数。比较法求新的部分积,取决于两个比较位的数位,即Yi+1Yi的状态。布斯乘法规则归纳如下:
首先设置附加位Yn+1=0,部分积初值[Z0]补=0。
l 当n≠0时,判YnYn+1,
l 当n=0时,判YnYn+1(对应于Y0Y1),运算规则同(1)只是不移位。即在运算的最后一步,乘积不再右移。
注意:
(A)比较法中不管乘数为正为负,符号位都参加运算,克服了校正法的缺点
(B)运算过程中采用变形补码运算(双符号位)
(C)算法运算时的关键是YnYn+1的状态:后者(Yn+1)减前者(Yn),判断是加减(+/-X)
module mul32(
);
//
endmodule
module test_mul32_v;
// Inputs
reg [31:0] a;
reg [31:0] b;
reg start;
reg clk;
// Outputs
wire done;
wire [63:0] c;
// Instantiate the Unit Under Test
(UUT)
mul32 uut (
.done(done),
.c(c),
.a(a),
.b(b),
.start(start),
.clk(clk)
);
initial begin
// Initialize
Inputs
a = 0;
b = 0;
start = 0;
clk = 0;
// Wait 100 ns for global
reset to finish
#100;
// Add stimulus
here
start=1;
//
b=32'h00_00_00_0d;
//
a=32'h00_00_00_0b;
//
b=32'h00_00_00_09;
//
a=32'hff_ff_ff_fb;
//0*0
a=32'h00_00_00_00;
b=32'h00_00_00_00;
//
//1*1
//
a=32'h00_00_00_01;
//
b=32'h00_00_00_01;
//
//1*(-1)
//
a=32'h00_00_00_01;
//
b=32'hff_ff_ff_ff;
//
//(-1)*1
//
b=32'h00_00_00_01;
//
a=32'hff_ff_ff_ff;
//
//(-1)*(-1)
//
a=32'hff_ff_ff_ff;
//
b=32'hff_ff_ff_ff;
//
//255*255
//
a=32'h00_00_00_ff;
//
b=32'h00_00_00_ff;
//
//255*(-255)
//
a=32'h00_00_00_ff;
//
b=32'hff_ff_ff_01;
//
//255*(-255)
//
a=32'h00_00_00_ff;
//
b=32'hff_ff_ff_01;
//
//(-255)*255
//
b=32'h00_00_00_ff;
//
a=32'hff_ff_ff_01;
//
//(-255)*(-255)
//
a=32'hff_ff_ff_01;
//
b=32'hff_ff_ff_01;
//
//255*0
//
a=32'h00_00_00_ff;
//
b=32'h00_00_00_00;
//
//0*255
//
b=32'h00_00_00_ff;
//
a=32'h00_00_00_00;
//
//-255*0
//
a=32'hff_ff_ff_01;
//
b=32'h00_00_00_00;
//
//0*-255
//
b=32'hff_ff_ff_01;
//
a=32'h00_00_00_00;
end
always #10
clk=~clk;
endmodule
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
endmodule
25位的booth乘法器可以用于32位单精度IEEE754
FPU的小数计算(23位小数+1位整数):最高位置0表示正数,后24位为乘数和被乘数,结果取后24位,最高位必然为1,所以取最后23位即可成为32位单精度IEEE754格式的尾数部分.
module mul25(
done,
c,
a,
b,
start,
clk
);
parameter N=25;
output done;
output [N*2-1:0]c;
input [N-1:0]a;
input [N-1:0]b;
input start;
input clk;
reg [4:0]index_i;
reg [N:0]z;
reg [N:0]x_c;
reg [N:0]x;
reg [N:0]y;
reg finished;
reg
[1:0]current_state,next_state;
parameter
Init=0,Ready=1,Acc=2,Done=3;
always @(posedge clk or negedge
start)
if (!start)
current_state<=Init;
else
current_state<=next_state;
always @(current_state or
index_i)
case (current_state )
Init
:
begin
next_state=Ready;
end
Ready:
begin
next_state=Acc;
end
Acc
:
begin
if(index_i==5'h18)
begin
next_state=Done;
end
end
endcase
always @(current_state or
index_i)
case (current_state)
Init:
begin
finished=0;
end
Ready:
begin
x={a[N-1],a[N-1:0]};
x_c=~{a[N-1],a[N-1:0]}+1;
y[N:0]={b[N-1:0],1'b0};
z=0;
$display("x=%b,x_c=%b,y=%b,z=%b",x,x_c,y,z);
end
Acc:
begin
case
(y[1:0])
2'b01:
begin
$display("case
01");
$display("Before:z=%b,y=%b",z,y);
z=z+x;
{z[N:0],y[N:0]}={z[N],z[N:0],y[N:1]};
$display("After:z=%b,y=%b",z,y);
end
2'b10:
begin
$display("case
10");
$display("Before:z=%b,y=%b",z,y);
z=z+x_c;
{z[N:0],y[N:0]}={z[N],z[N:0],y[N:1]};
$display("After:z=%b,y=%b",z,y);
end
default:
begin
$display("case 00 or
11");
$display("Before:z=%b,y=%b",z,y);
{z[N:0],y[N:0]}={z[N],z[N:0],y[N:1]};
$display("After:z=%b,y=%b",z,y);
end
endcase
$display("z=%b,y=%b",z,y);
end
default:
begin
finished=1;
$display("c=%b",c);
end
endcase
always @(posedge clk)
if (current_state==Acc)
index_i<=index_i+1;
else
index_i<=0;
assign done=finished;
assign
c[N*2-1:0]={z[N-1:0],y[N:1]};
endmodule
module mul25(
);
endmodule

加载中…