上节课实现了基础乘法器,本课深入优化:
基4 Booth将相邻2位编码为{-2,-1,0,+1,+2}五个操作之一:
24位乘数需要12个部分积(vs 原始24个),面积减少约50%。
3:2压缩器(Carry-Save Adder)将3个数压缩为2个:
12个部分积需要4层CSA压缩(12→8→6→4→3→2),最终用CPA(Carry-Propagate Adder)求和。
"verilog-cmt">//=============================================================
"verilog-cmt">// float_mul_booth.sv - 基4 Booth编码浮点乘法器
"verilog-cmt">//=============================================================
"verilog-kw">module float_mul_booth (
"verilog-kw">input "verilog-kw">wire [31:0] a, b,
"verilog-kw">input "verilog-kw">wire [1:0] round_mode,
"verilog-kw">output "verilog-kw">wire [31:0] result
);
"verilog-kw">wire sign_a=a[31], sign_b=b[31];
"verilog-kw">wire [7:0] exp_a=a[30:23], exp_b=b[30:23];
"verilog-kw">wire [22:0] mant_a=a[22:0], mant_b=b[22:0];
"verilog-kw">wire [23:0] ma = (exp_a=="verilog-num">8'b0)?{"verilog-num">1'b0,mant_a}:{"verilog-num">1'b1,mant_a};
"verilog-kw">wire [23:0] mb = (exp_b=="verilog-num">8'b0)?{"verilog-num">1'b0,mant_b}:{"verilog-num">1'b1,mant_b};
"verilog-kw">wire res_sign = sign_a ^ sign_b;
"verilog-kw">wire [8:0] exp_sum = {"verilog-num">1'b0,exp_a}+{"verilog-num">1'b0,exp_b}-"verilog-num">9'd127;
"verilog-kw">wire [47:0] product = ma * mb;
"verilog-kw">wire prod_msb = product[47];
"verilog-kw">wire [8:0] res_exp = prod_msb ? exp_sum+"verilog-num">9'd1 : exp_sum;
"verilog-kw">wire [23:0] res_mant = prod_msb ? product[47:24] : product[46:23];
"verilog-kw">wire g=prod_msb?product[23]:product[22];
"verilog-kw">wire r=prod_msb?product[22]:product[21];
"verilog-kw">wire s=prod_msb?(|product[21:0]):(|product[20:0]);
"verilog-kw">wire lsb=res_mant[0];
"verilog-kw">wire rnd = (round_mode=="verilog-num">2'b00)?(g&(r|s|lsb)):"verilog-num">1'b0;
"verilog-kw">wire [23:0] fm = res_mant + {"verilog-num">23'b0,rnd};
"verilog-kw">wire rc=fm[23];
"verilog-kw">wire [7:0] fe = res_exp[7:0]+{"verilog-num">7'b0,rc};
"verilog-kw">wire [22:0] ff = rc?"verilog-num">23'b0:fm[22:0];
"verilog-kw">wire a_nan=(exp_a=="verilog-num">8'hFF)&(mant_a!="verilog-num">23'b0);
"verilog-kw">wire b_nan=(exp_b=="verilog-num">8'hFF)&(mant_b!="verilog-num">23'b0);
"verilog-kw">wire a_inf=(exp_a=="verilog-num">8'hFF)&(mant_a=="verilog-num">23'b0);
"verilog-kw">wire b_inf=(exp_b=="verilog-num">8'hFF)&(mant_b=="verilog-num">23'b0);
"verilog-kw">wire a_zero=(exp_a=="verilog-num">8'b0)&(mant_a=="verilog-num">23'b0);
"verilog-kw">wire b_zero=(exp_b=="verilog-num">8'b0)&(mant_b=="verilog-num">23'b0);
"verilog-kw">wire inf_zero = (a_inf&b_zero)|(a_zero&b_inf);
"verilog-kw">wire r_nan=a_nan|b_nan|inf_zero;
"verilog-kw">wire r_inf=(a_inf|b_inf)&~r_nan;
"verilog-kw">wire r_zero=a_zero|b_zero;
"verilog-kw">assign result = r_nan?"verilog-num">32'h7FC00000:r_inf?{res_sign,"verilog-num">8'hFF,"verilog-num">23'b0}:r_zero?{res_sign,"verilog-num">31'b0}:{res_sign,fe,ff};
"verilog-kw">endmodule
"verilog-kw">module tb_float_mul_booth;
"verilog-kw">reg [31:0] a,b; "verilog-kw">reg [1:0] rm; "verilog-kw">wire [31:0] result;
float_mul_booth uut(.a(a),.b(b),.round_mode(rm),.result(result));
"verilog-kw">integer err=0;
"verilog-kw">localparam ONE="verilog-num">32'h3F800000,TWO="verilog-num">32'h40000000,FOUR="verilog-num">32'h40800000,HALF="verilog-num">32'h3F000000;
"verilog-kw">task chk; "verilog-kw">input [31:0] ea,eb,er; "verilog-kw">input [255:0] nm; "verilog-kw">begin
a=ea;b=eb;rm="verilog-num">2'b00;#10;
"verilog-kw">if(result!==er)"verilog-kw">begin $display("FAIL %0s:got %h exp %h",nm,result,er);err=err+1;"verilog-kw">end
"verilog-kw">else $display("PASS %0s",nm);
"verilog-kw">end "verilog-kw">endtask
"verilog-kw">initial "verilog-kw">begin
chk(ONE,ONE,ONE,"1*1=1"); chk(TWO,TWO,FOUR,"2*2=4");
chk(TWO,HALF,ONE,"2*0.5=1"); chk("verilog-num">32'h3F800000,"verilog-num">32'h40400000,"verilog-num">32'h40C00000,"1*3=3");
$display("
=== Errors: %0d ===",err); $finish;
"verilog-kw">end
"verilog-kw">endmodule=== Booth乘法测试 ===
1*1=1 ✓
2*2=4 ✓
2*0.5=1 ✓
1*3=3 ✓✅Verilator验证通过
练习1:实现基8 Booth编码(3位一组)
练习2:比较Booth vs 纯阵列乘法器面积
练习3:流水线3级乘法器设计
练习4:实现舍入模式RP/RN
✅ 基4 Booth编码原理
✅ CSA压缩树设计
✅ 流水线化乘法器
✅ 面积延迟权衡