verilog booth编码乘法器
Booth编码
首先介绍一下波斯编码,可以通过理解下面的等式:
可以证明的是,这三个公式是相等的,一个有符号的二进制数的补码用公式1来表示,可以等价地写成公式2和公式3。公式2其实就对应的2位一组的booth编码,公式3对应的3位一组的booth编码
这个过程就是对Y进行编码的过程。编码之后,乘数Y中的位被划分为不同的组, 每一组包括3位,这些组互相交叠。
Booth编码可以减少部分积的数目(即减少乘数中1的个数),用来计算有符号乘法,提高乘法运算的速度。

如上图所示为二进制乘法的过程,也是符合我们正常计算时的逻辑,我们假设有一个8位乘数(Multiplier),它的二进制值为0111_1110,它将产生6行非零的部分积,因为它有6个非零值(即1)。如果我们利用公式2:
将这个二进制值改为1000_00-10,其中低四位中的-1表示负1,可以证明两个值是相等的。
这个变换过程可以这样简单理解,那就是在原值的末尾加辅助位0,变为0111_1110_0,然后利用低位减去高位,就对应-yn-1+yn-2,即得到1000_00-10。其实也对应公式2的对应编码,这样一变换可以减少0的数目,从而减少加的次数,我们只需相加两个部分积,但是最终的加法器必须也能执行减法。这种形式的变换称为booth encoding(即booth编码),它保证了在每两个连续位中最多只有一个是1或-1。部分积数目的减少意味着相加次数的减少,从而加快了运算速度(并减少了面积)。从形式上来说,这一变换相当于把乘数变换成一个四进制形式。波斯编码过程如下:

我们以6*14为例,对booth乘法运算进行举例:6的有符号二进制表示为00110,14的有符号二进制表示为01110,01110的booth编码表示为100-10,乘累加结果表示为P:

对应的verilog 代码如下:
`timescale 1ns / 1p module booth_mult#(parameter D_IN=8)( input clk, input rst_n, input start, input [D_IN-1:0]mul_A, input [D_IN-1:0]mul_B, output reg done, output reg [2*D_IN-1:0]Product ); reg [1:0] state; reg [2*D_IN-1:0] mult_A; // result of mul_A reg [D_IN:0] mult_B; // result of mul_A reg [2*D_IN-1:0] inv_A; // reverse result of mul_A reg [2*D_IN-1:0] result_tmp; // operation register wire [1:0] booth_code; assign booth_code = mult_B[1:0]; assign stop=(~|mult_B)||(&mult_B); always @ ( posedge clk or negedge rst_n ) if( !rst_n ) begin state <= 0; mult_A <= 0; inv_A <= 0; result_tmp <= 0; done <= 0; Product<=0; end else if( start ) case( state ) 0: begin mult_A <= {{D_IN{mul_A[D_IN-1]}},mul_A}; inv_A <= ~{{D_IN{mul_A[D_IN-1]}},mul_A} + 1'b1 ; result_tmp <= 0; mult_B <= {mul_B,1'b0}; state <= state + 1'b1; end 1: begin if(~stop) begin case(booth_code) 2'b01 : result_tmp <= result_tmp + mult_A; 2'b10 : result_tmp <= result_tmp + inv_A; default: result_tmp <= result_tmp; endcase mult_A <= {mult_A[14:0],1'b0}; inv_A <= {inv_A[14:0],1'b0}; mult_B <= {mult_B[8],mult_B[8:1]}; end else state <= state + 1'b1; end 2:begin done<=1'b1; Product<= result_tmp; state <= state+1; end 3: begin done<=1'b0; state<=0; end endcase endmodule
下面是仿真对应的testbench:
`timescale 1ns / 1ps module tb_multi_seq(); reg clk; reg rst_n; reg start; reg [7:0]mul_A; reg [7:0]mul_B; wire done; wire [15:0]Product; always #10 clk = ~clk; initial begin rst_n = 0; clk = 1; #10; rst_n = 1; end booth_mult#(.D_IN(8)) U1 ( .clk(clk), .rst_n(rst_n), .start(start), .mul_A(mul_A), .mul_B(mul_B), .done(done), .Product(Product) ); /***********************************/ reg [3:0]i; always @ ( posedge clk or negedge rst_n ) if( !rst_n ) begin i <= 4'd0; start <= 1'b0; mul_A <= 8'd0; mul_B <= 8'd0; end else case( i ) 0: // mul_A = 10 , mul_B = 2 if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin mul_A <= 8'd10; mul_B <= 8'd2; start <= 1'b1; end 1: // mul_A = 2 , mul_B = 10 if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin mul_A <= 8'd2; mul_B <= 8'd10; start <= 1'b1; end 2: // mul_A = 11 , mul_B = -5 if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin mul_A <= 8'd11; mul_B <= 8'b11111011; start <= 1'b1; end 3: // mul_A = -5 , mul_B = -11 if( done ) begin start <= 1'b0; i <= i + 1'b1; end else begin mul_A <= 8'b11111011; mul_B <= 8'b11110101; start <= 1'b1; end 4: begin i <= 4'd4; end endcase endmodule
以及仿真波形图
2bit编码比较简单,接下来可以继续进行3bit 编码的booth编码乘法器。

浙公网安备 33010602011771号