当前位置: 首页 > news >正文

从小学数学竖式到FPGA硬件:图解4位乘法器是如何‘搭’出来的

从小学数学竖式到FPGA硬件:图解4位乘法器是如何‘搭’出来的

记得小学三年级第一次接触乘法竖式时,老师用粉笔在黑板上画出的那些错位相加的格子吗?当时我们或许不会想到,这些看似简单的计算步骤,竟与当今最先进的芯片设计有着惊人的相似性。本文将带您穿越数字世界的时空隧道,从最熟悉的十进制乘法出发,逐步拆解二进制乘法器的硬件实现奥秘,最终在FPGA的可编程逻辑单元中"搭建"出一个真实的4位乘法电路。

1. 乘法竖式:跨越千年的计算智慧

当我们计算12×34时,大脑会自动执行以下步骤:

1 2 × 3 4 ----- 4 8 (12×4) 3 6 (12×3,左移一位) ----- 4 0 8

这个过程中隐藏着三个关键计算原则:

  1. 部分积生成:分别计算被乘数与乘数每一位的乘积
  2. 位权对齐:根据乘数位的权重进行左移
  3. 累加求和:将所有部分积相加得到最终结果

在二进制世界中,这个过程变得更加简洁。以4位二进制数1011(11) × 1101(13)为例:

1 0 1 1 × 1 1 0 1 --------- 1 0 1 1 (×1) 0 0 0 0 (×0,左移1位) 1 0 1 1 (×1,左移2位) 1 0 1 1 (×1,左移3位) --------- 1 0 0 0 1 1 1 1 (143)

二进制乘法的简化之处在于:

  • 部分积只有两种可能:被乘数本身或全0
  • 不需要真正的"乘法"运算,只需条件复制和移位

提示:硬件设计中的乘法器本质上就是将这些纸面计算步骤转化为永久性的电路连接

2. 从算法到电路:二进制乘法的硬件映射

2.1 部分积的硬件实现

在FPGA中,每个部分积可以通过简单的与门阵列生成。对于4位乘法器A×B:

// 部分积生成示例 wire [3:0] pp0 = {4{B[0]}} & A; // A×B[0] wire [3:0] pp1 = {4{B[1]}} & A; // A×B[1]左移1位 wire [3:0] pp2 = {4{B[2]}} & A; // A×B[2]左移2位 wire [3:0] pp3 = {4{B[3]}} & A; // A×B[3]左移3位

实际硬件中,这部分对应FPGA的可编程逻辑单元(LUT)配置。Xilinx 7系列FPGA中,每个SLICE包含4个6输入LUT,可以灵活实现各种逻辑功能。

2.2 加法器阵列:硬件中的竖式计算

将部分积相加的传统方法称为"行波进位加法器阵列",其结构直接对应小学数学竖式:

PP3[3] PP3[2] PP3[1] PP3[0] 0 0 0 PP2[3] PP2[2] PP2[1] PP2[0] 0 0 PP1[3] PP1[2] PP1[1] PP1[0] 0 PP0[3] PP0[2] PP0[1] PP0[0] ----------------------------------------

硬件实现时需要三个主要组件:

  1. 全加器(FA):处理1位加法并产生和与进位
  2. 进位链:将低位进位传递到高位
  3. 布线资源:连接各个计算单元

Xilinx FPGA中的CARRY4原语专门优化了进位链传播,每个CARRY4可以处理4位加法。下图展示了一个4位乘法器的加法器阵列布局:

3. FPGA实战:三种乘法器架构对比

3.1 直接实现法(组合逻辑乘法器)

直接使用Verilog的乘法运算符:

module direct_multiplier ( input [3:0] a, input [3:0] b, output [7:0] p ); assign p = a * b; endmodule

资源消耗(以Xilinx Artix-7为例):

资源类型使用量占比
LUT325%
CARRY4312%

特点

  • 单周期完成计算
  • 延迟约3.2ns(100MHz时钟)
  • 资源消耗较大

3.2 移位相加法(时序逻辑乘法器)

module shift_add_multiplier ( input clk, input [3:0] a, input [3:0] b, output reg [7:0] p ); reg [7:0] accum; reg [2:0] count; always @(posedge clk) begin if (reset) begin accum <= 0; count <= 0; end else if (count < 4) begin accum <= accum + (b[count] ? a << count : 0); count <= count + 1; end p <= (count == 4) ? accum : 0; end endmodule

性能对比表

指标直接实现法移位相加法
最大频率312MHz250MHz
计算周期数14
LUT使用量3212
能效比1x3.2x

3.3 华莱士树压缩法

这是一种优化方案,通过减少加法器级数来提高速度:

module wallace_multiplier ( input [3:0] a, input [3:0] b, output [7:0] p ); // 部分积生成 wire [3:0] pp0 = {4{b[0]}} & a; wire [3:0] pp1 = {4{b[1]}} & a; wire [3:0] pp2 = {4{b[2]}} & a; wire [3:0] pp3 = {4{b[3]}} & a; // 第一级压缩 wire [3:0] s1, c1; full_adder fa1_0 (pp0[1], pp1[0], 0, s1[0], c1[0]); full_adder fa1_1 (pp0[2], pp1[1], pp2[0], s1[1], c1[1]); // ...更多加法器实例化 // 最终相加 assign p = {2'b0, pp3, 1'b0} + {c2, s2, 1'b0}; endmodule

华莱士树优势

  • 加法器层级从O(n)降至O(log n)
  • 4位乘法仅需2级加法
  • 关键路径延迟减少约40%

4. 现代FPGA中的DSP硬核

现代FPGA通常集成了专用DSP Slice,如Xilinx的DSP48E1:

module dsp_multiplier ( input [3:0] a, input [3:0] b, output [7:0] p ); DSP48E1 #( .USE_DPORT("TRUE"), .MREG(0) ) dsp_inst ( .A({10'b0, a}), .B({10'b0, b}), .P(p), // 其他信号连接 ); endmodule

DSP硬核 vs 逻辑实现

特性DSP硬核逻辑实现
时钟周期1-21-4
功耗0.5mW/MHz1.2mW/MHz
最大频率500MHz+300MHz
可定制性有限完全可编程

在Vivado中,可以通过综合指令控制实现方式:

(* use_dsp48 = "yes" *) wire [7:0] result = a * b;
http://www.jsqmd.com/news/780759/

相关文章:

  • 基于MediaPipe的人体姿态估计:从原理到创意交互实践
  • 告别VMWare!用VirtualBox 7.0.6给CentOS 7.6装个桌面,保姆级避坑指南
  • 基于MCP协议构建海运智能体:从数据整合到自动化监控实战
  • AI辅助无障碍设计:从WCAG标准到工程实践的全流程指南
  • 基于RAG与LangChain构建智能数据查询助手:从自然语言到SQL的工程实践
  • 工业级实战:C# + YOLO26打造食品包装生产线喷码识别与漏喷检测系统
  • MongoDB 慢查询日志深度剖析:配置、源码与性能优化实践
  • 告别串口不够用!手把手教你用RP2040的PIO扩展出8个串口(基于Arduino-Pico库)
  • 基于RAG架构的AI知识库构建:从原理到工程实践
  • 2026年热门的箱房门框成型机公司选择指南 - 品牌宣传支持者
  • ARM926EJ-S处理器勘误解析与解决方案
  • 小米TTS引擎接入OpenAI API标准接口:实现中文语音合成的本地化部署与生态兼容
  • Letter-Shell 3.x移植踩坑实录:从“空格退格就重启”到稳定运行的避坑指南
  • 开发者记忆增强工具Mnemosyne:本地优先的知识管理与高效检索实践
  • 保姆级教程:用D435i IMU给Velodyne VLP16激光雷达做运动畸变校正(附ROS/Eigen代码)
  • AI驱动的DeFi交易机器人:Gladiator Bot实战指南与策略开发
  • 基于搜索的日志降噪工具:从信息过载到精准过滤的工程实践
  • VS Code侧边栏卡顿优化:CSS渲染性能分析与修复方案
  • 搭建 k8s 集群时通常会遇到哪些常见问题?
  • CL4R1T4S:基于大语言模型的智能代码审查助手实战指南
  • 保姆级教程:用R语言复现HIV药物经济学Markov模型(附完整代码与数据)
  • 项目介绍 MATLAB实现基于BAG-LSTM 装袋集成(BAG)结合长短期记忆网络(LSTM)进行股票价格预测(含模型描述及部分示例代码)专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励
  • Qwik 首屏加载优化:代码分割、懒加载与预加载完整方案
  • Keil调试STM32报‘Not a genuine ST Device’?别慌,两步搞定非官方ST-LINK的警告
  • Rust 高性能代码格式化工具 bfc:设计原理与工程实践
  • 巧妙运用访问者模式:解决复杂对象结构遍历与操作难题
  • 保姆级教程:用IDA Pro和IL2CppDumper搞定Unity IL2CPP游戏的逆向修改(附完整工具链)
  • 开源音乐技能库OpenClaw-SongSee:音频识别与元数据自动化处理指南
  • macOS原生AI客户端macai:整合ChatGPT、Claude、Ollama等,打造统一高效桌面工作流
  • Kotlin 内部机制:内存模型、垃圾回收与并发原语全解析