数字IC设计实战解析:进位保留乘法器的架构优化与性能评估 1. 进位保留乘法器基础原理我第一次接触进位保留乘法器是在做一个32位DSP核的项目时。当时用传统阵列乘法器跑综合时序怎么都过不了250MHz急得我连着熬了三个通宵。后来导师扔给我一篇论文说试试这个这才打开了新世界的大门。简单来说进位保留乘法器的核心思想就是把进位链打散。传统乘法器为什么慢因为每一位计算都要等上一位的进位到位才能开始就像早高峰堵车一样前车不动后车只能干等着。而进位保留乘法器相当于给每个计算单元开了专用车道让大部分位可以并行计算只在最后统一处理进位。这里有个生活化的类比想象你在算12×34。传统方法是先算4×1248然后3×1236但要左移一位变成360最后做48360。而进位保留的做法是先算4×28个位同时算4×14和3×26十位同时算3×13百位最后把4610的进位留给下一步处理实际硬件实现时关键组件是3-2压缩器也叫保留进位加法器。它接收三个输入位输出一个和位和一个进位位。比如计算111时传统全加器110进位1再用011最终输出1和进位13-2压缩器直接输出和1与进位1二进制11就是十进制3这种结构在Verilog里实现起来特别直观。下面是个简化版的3-2压缩器代码module compressor_3to2( input a, b, c, output sum, carry ); assign sum a ^ b ^ c; assign carry (a b) | (b c) | (a c); endmodule2. 架构优化实战技巧在真正流片过的项目中我发现有几个优化点特别关键。先说部分积生成这块很多人直接用与门阵列实现其实有更聪明的做法。比如对于4位乘法器可以这样优化// 传统实现 assign partial_products[0] B[0] ? A : 4b0; // 优化实现 wire [3:0] pp0 {4{B[0]}} A;看起来区别不大是吧但综合后的网表差异很大。前者会生成多路选择器后者直接生成与门在0.13μm工艺下能节省约15%的面积。再说加法器阵列的布局。我强烈建议采用树形结构而非线性阵列比如Wallace树结构。具体到4位乘法器可以这样规划第一级用3-2压缩器处理第0-2行部分积第二级用2-1压缩器就是普通全加器处理剩余项最后用超前进位加法器做向量合并实测下来这种结构在TSMC 40nm工艺下比传统结构快22%虽然面积会大8%左右。具体数据对比如下结构类型延迟(ns)面积(μm²)功耗(mW)传统阵列3.214205.8Wallace树2.515306.13. Verilog实现细节给大家看看我在实际项目中打磨过的代码模板。关键点在于参数化设计和层次化封装module carry_save_multiplier #( parameter WIDTH 8 )( input [WIDTH-1:0] A, input [WIDTH-1:0] B, output [2*WIDTH-1:0] Result ); // 部分积生成 wire [WIDTH-1:0] pp [WIDTH-1:0]; generate for(genvar i0; iWIDTH; i) begin assign pp[i] {WIDTH{B[i]}} A; end endgenerate // 压缩树实现 wire [WIDTH:0] sum, carry; compressor_tree #(.WIDTH(WIDTH)) u_tree( .pp(pp), .sum_out(sum), .carry_out(carry) ); // 最终相加 carry_lookahead_adder #(.WIDTH(WIDTH1)) u_adder( .A(sum), .B({carry[WIDTH-1:0], 1b0}), .Sum(Result) ); endmodule有几个容易踩坑的地方要特别注意位宽对齐压缩树输出的sum和carry位宽要1否则最高位进位会丢失时序约束必须对压缩树内部路径设置多周期约束测试激励建议用SystemVerilog的随机约束测试initial begin repeat(100) begin A $urandom_range(0, 2**WIDTH-1); B $urandom_range(0, 2**WIDTH-1); #10; assert (Result A * B) else $error(Mismatch at %0d*%0d, A,B); end end4. 综合与性能评估用DesignCompiler做综合时我总结了一套优化组合拳编译策略set_ultra_optimization true set_parameter logic_opt_effort high set_optimize_registers true关键路径约束set_max_delay 2.5 -from [all_inputs] -to [all_outputs] group_path -name critical -from [all_inputs] -to [all_outputs]面积优化set_max_area 0 set_area_effort high在UMC 55nm下跑出的典型报告长这样**************************************** Report : timing -path full -delay max -max_paths 10 Design : carry_save_multiplier Version: J-2014.09 Date : Aug 20 2023 **************************************** Operating Conditions: tt_1v8_25c Library: umc55ltc Wire Load Model Mode: enclosed Startpoint: A[3] Endpoint: Result[7] Path Group: critical Path Type: max Point Incr Path ---------------------------------------------------------- A[3] (in) 0.00 0.00 pp_reg[3][3] (DFF) 0.18 0.18 compressor_3to2/U3 (AND2) 0.21 0.39 compressor_3to2/U1 (XOR3) 0.35 0.74 carry_lookahead_adder/U14 (AOI21) 0.41 1.15 Result[7] (out) 0.00 1.15 ---------------------------------------------------------- data arrival time 1.15 clock ideal_clock (rise edge) 2.50 2.50 ---------------------------------------------------------- data required time 2.50 ---------------------------------------------------------- data required time 2.50 data arrival time -1.15 ---------------------------------------------------------- slack (MET) 1.35性能评估时重点看三个指标吞吐率时钟频率×数据位宽能效比吞吐率/动态功耗面积效率吞吐率/芯片面积建议用下面的TCL脚本自动提取这些指标set freq [get_attribute [get_clocks] period] set power [get_attribute [get_design] power] set area [get_attribute [get_design] area] puts Throughput: [expr {1/$freq * [sizeof_collection [get_ports]]}] Gbps puts Power Eff.: [expr {1/$freq * [sizeof_collection [get_ports]] / $power}] Gbps/mW puts Area Eff. : [expr {1/$freq * [sizeof_collection [get_ports]] / $area}] Gbps/um25. 进阶优化方向最近在做一个AI加速器项目时我又发现了几个新玩法。首先是混合压缩策略在低位用保留进位结构高位用Booth编码。实测在16位乘法器上能再提升12%性能// 低位8bit用进位保留 carry_save_multiplier #(.WIDTH(8)) u_lsb ( .A(A[7:0]), .B(B[7:0]), .Result(lsb_result) ); // 高位8bit用Booth编码 booth_multiplier #(.WIDTH(8)) u_msb ( .A(A[15:8]), .B(B[15:8]), .Result(msb_result) ); // 结果合并 assign Result lsb_result (msb_result 16);其次是异步设计。保留进位结构天生适合做异步电路因为局部计算完成就可以触发下一级。我用HSPICE仿过一个版本延迟能降到同步设计的60%同步设计关键路径1.15ns 异步设计关键路径0.69ns不过异步设计验证复杂度高建议先用Synopsys的Formality做等效性检查read_design -golden ../rtl/carry_save_async.v read_design -revised ../netlist/carry_save_async.gv set_equivalent -type async verify最后是近似计算。对图像处理这类容错应用可以故意省略最后几级进位压缩。我在一个CNN项目里试过面积能省30%而PSNR只降了2dB// 近似计算版 assign approx_result sum[15:8] carry[14:7]; // 跳过最低位进位