Verilog实战:手把手教你实现基2-Booth乘法器(附完整代码与仿真)

张开发
2026/4/11 22:34:02 15 分钟阅读

分享文章

Verilog实战:手把手教你实现基2-Booth乘法器(附完整代码与仿真)
Verilog实战从零构建高效基2-Booth乘法器的五个关键突破点在数字电路设计中乘法器的性能往往决定着整个系统的吞吐量。当我在第一个FPGA项目中使用传统阵列乘法器时时钟频率始终无法突破100MHz的瓶颈直到发现了Booth算法这个游戏规则改变者。本文将分享如何用Verilog实现一个经过实战检验的基2-Booth乘法器特别针对初学者容易踩坑的五个核心环节进行深度解析。1. Booth算法本质补码运算的优雅解法Booth算法的精妙之处在于将乘法转化为移位和加减操作的组合。与普通二进制乘法不同它通过观察乘数相邻位的组合B[i]和B[i-1]来决定操作类型这种设计天然适合补码运算。三种基本操作情形2b00或2b11保持当前值不变2b01加上被乘数A2b10减去被乘数-A理解这个核心机制后我们可以用Verilog构建一个状态机来控制系统流程。以下是关键状态定义localparam STATE_IDLE 2b00; // 空闲状态 localparam STATE_CALC 2b01; // 计算阶段 localparam STATE_SHIFT 2b10; // 移位阶段 localparam STATE_END 2b11; // 输出结果2. 硬件架构设计数据通路的精妙平衡基2-Booth乘法器的硬件实现需要精心设计数据通路。核心寄存器array的位宽设计尤为关键它需要容纳部分积寄存器Qn位乘数Bn位附加位B[-1]1位对于4位乘法器完整的Verilog声明如下reg signed [2*size:0] array; // 总位宽2n1 reg [size-1:0] M; // 被乘数寄存器 reg [size-1:0] Q; // 乘数寄存器 reg [1:0] count; // 迭代计数器注意array使用有符号类型(signed)声明至关重要这确保了算术右移时符号位能正确扩展这是许多初学者容易忽略的关键点。3. 状态机实现精准控制计算流程一个健壮的状态机是Booth乘法器的大脑。在我的实现中采用三段式状态机设计当前状态寄存器、次态逻辑、输出逻辑这是FPGA设计中的最佳实践。计算阶段核心代码always (posedge clk or negedge rst_n) begin if(!rst_n) begin state STATE_IDLE; end else begin case(state) STATE_CALC: begin case({array[1:0]}) 2b01: array array {M,{(size1){1b0}}}; 2b10: array array - {M,{(size1){1b0}}}; default: array array; endcase end STATE_SHIFT: begin array array 1; // 算术右移 if(count ! 0) count count - 1; end endcase end end这个设计将计算和移位操作分离到不同时钟周期虽然牺牲了一些速度但大幅提高了代码可读性和调试便利性——这对初学者来说是非常有价值的折衷。4. 仿真验证Modelsim实战技巧完整的testbench是验证设计正确性的关键。下面是一个针对4位乘法器的测试框架包含两个测试用例module Top_tb; // ... 端口声明 initial begin clk 0; rst_n 0; #100 rst_n 1; // 测试用例17 * (-5) -35 multiplicand_i 4b0111; // 7 multiplier_i 4b1011; // -5 valid_i 1; #20 valid_i 0; wait(ready_o); receive_i 1; // 测试用例25 * (-7) -35 multiplicand_i 4b0101; // 5 multiplier_i 4b1001; // -7 valid_i 1; #1000 $stop; end always #10 clk ~clk; endmodule在Modelsim中运行时要特别注意观察以下信号array寄存器的变化过程状态机state的跳转时序最终result_o的输出值5. 性能优化从基础实现到工业级设计当基本功能验证通过后可以考虑以下几个优化方向流水线设计将计算过程划分为多个阶段每个时钟周期处理一部分工作提高吞吐量并行计算对状态机进行优化合并计算和移位阶段位宽扩展参数化设计使得模块可配置不同位宽一个简单的流水线改进方案是插入寄存器缓存中间结果always (posedge clk) begin if(state STATE_CALC) begin calc_result array {{size{M[size-1]}}, M, 1b0}; end end在实际项目中我发现在Xilinx Artix-7 FPGA上优化后的设计可以达到200MHz以上的时钟频率比基础实现提升近2倍性能。

更多文章