Board logo

标题: 32位Booth乘法器的原理和Verilog代码 [打印本页]

作者: awetman    时间: 2010-1-22 06:46     标题: 32位Booth乘法器的原理和Verilog代码

假设X、Y都是用补码形式表示的机器数,[X]补和[Y]补=Ys.Y1Y2…Yn,都是任意符号表示的数。比较法求新的部分积,取决于两个比较位的数位,即Yi+1Yi的状态。
布斯乘法规则归纳如下:
首先设置附加位Yn+1=0,部分积初值[Z0]补=0。
l       当n≠0时,判YnYn+1,
        若YnYn+1=00或11,即相邻位相同时,上次部分积右移一位,直接得部分积。
        若YnYn+1=01,上次部分积加[X]补,然后右移一位得新部分积。
        若YnYn+1=10,上次部分积加[-X]补,然后右移一位得新部分积。
l       当n=0时,判YnYn+1(对应于Y0Y1),运算规则同(1)只是不移位。即在运算的最后一步,乘积不再右移。
注意:
(A)比较法中不管乘数为正为负,符号位都参加运算,克服了校正法的缺点
(B)运算过程中采用变形补码运算(双符号位)
(C)算法运算时的关键是YnYn+1的状态:后者(Yn+1)减前者(Yn),判断是加减(+/-X)

module mul32(
        done,
        c,
        a,
        b,
        start,
        clk
);
        parameter N=32;
        output done;
        output [N*2-1:0]c;
        input [N-1:0]a;
        input [N-1:0]b;
        input start;
        input clk;
       
        reg [5: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==6'h1f)
//                        if(index_i==6'h20)
                                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
作者: awetman    时间: 2010-1-22 06:48

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
作者: awetman    时间: 2010-1-22 07:08

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
作者: dbx12358    时间: 2011-7-12 21:51

很不错.非常感谢.




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0