在《CMOS VLSI Design A Circuit and System Perspective》一书中对booth算法进行了说明,但是在描述无符号数乘法的符号处理部分采用了一个S符号,对我们理解造成一定的困惑,另一方面在booth编码对被乘数处理的时候的细节只是举了个例子,这里细化了部分积处理的示意图,同时通过编码实现了部分积处理的方法,加法部分没有采用Dadda树,后续再进一步优化。
下图为8bit无符号数的部分积示意图
下图为16bit无符号数的部分积示意图
从上面两图可以看出其符号的使用,即每个部分积的符号(即部分积正负)体现的位置
下面看一下booth编码的映射关系,和《CMOS VLSI Design A Circuit and System Perspective》书中描述一致。
我们用verilog实现一个部分积的编码
module mul_pp #( parameter DW=16 )
(
input logic [DW-1:0] a,
input logic [2:0] b,
output logic [DW:0] pp,
output logic so
);
always_comb@*
case(b)
3'b000 : pp = {DW+1{1'b0}};
3'b001 : pp = {1'b0, a};
3'b010 : pp = {1'b0, a};
3'b011 : pp = {a, 1'b0};
3'b100 : pp = ~{a, 1'b0};
3'b101 : pp = ~{1'b0, a};
3'b110 : pp = ~{1'b0, a};
default : pp = {DW+1{1'b1}};
endcase
assign so = b[2];
endmodule
有了上述部分积编码,以及部分积和符号的组合,那么乘法器的实现如下:
module mul #( parameter DW=8 )
(
input logic clk,
input logic rstn,
input logic [DW-1:0] a,
input logic [DW-1:0] b,
input logic [DW*2-1:0] p
)
logic [DW/2:0] so;
logic [DW/2:0][DW:0] pp;
logic [DW/2:0][DW*2:0] ppp;
logic [DW/2:0][DW*2:0] pppp;
logic [DW+2:0] multiplier;
assign multiplier = {2'b0, b, 1'b0};
for(genvar i=0;i<=DW/2;i=i+1) begin: GEN_PP
mul _pp #(.DW(DW)) u_mul_pp (.a(a), .b(multiplier[i*2+:3]), .pp(pp[i]), .so(so[i]));
if(i==0) begin
assign ppp[i] = {~so[i], so[i], so[i], pp[i]};
end else if(i==DW/2)begin
assign ppp[i] = {pp[i], 1'b0, so[i-1]};
end else begin
assign ppp[i] = {1'b1, ~so[i], pp[i], 1'b0, so[i-1]};
end
end
always_comb@* begin
pppp[0] = ppp[0] + ppp[1];
pppp[1] = ppp[2] + (ppp[3]<<2);
pppp[2] = (pppp[1]<<2)+ pppp[0];
pppp[3] = (ppp[4]<<6) + pppp[2];
end
assign p = pppp[3];
endmodule
这里部分积加法没有优化,后续再补充