0、初衷
构建起这座桥,双向互译!直到真正理解**'写算法时心中有电路,写 FPGA 时心中有算法。'**
回顾早期经历,我曾是算法的'原教旨主义者'。最早期,我和许多算法工程师一样,活在 MATLAB/Python/C 语言的抽象环境里。对我来说,图像就是 imread() 返回的那个完美矩阵,处理就是调用 conv2() 或 cv2.GaussianBlur() 等函数。数据是静止的、无限的、免费的——内存不够就加条 DIMM,算得慢就等几秒,边界处理?MATLAB 会帮我 padarray,Python 会帮我 cv2.BORDER_REFLECT。
当我第一次接触 FPGA 代码时,我是困惑甚至抗拒的:
- '什么?我要自己算地址?'
- '为什么不能有 for 循环遍历整张图?'
- '这个 always @(posedge clk) 是什么意思?我明明只是想做个滤波…'
我理解那种认知的撕裂感:你明明知道算法在数学上是对的,但面对硬件时,突然发现自己像个失语的翻译——你懂算法的'英语',但完全不懂硬件的'法语',更不知道如何将一个翻译成另一个。
直到我逼着自己写完第一个 Line Buffer,调通第一个图像空间滤波算法,我才突然顿悟:硬件不是在'实现'算法,硬件是在'演绎'数据流。深有成就感,然后在资源与带宽等 PPA(Power、Performance、Area)的优化中,感知 FPGA 实现的艺术。
现在,我能在 MATLAB 和 Vivado 之间自由穿梭,不是因为我会两种语言,而是因为我建立了一种'中间表示'(Intermediate Representation):当我看到算法里的卷积,我脑子里浮现的不是矩阵乘法,而是滑动窗口的数据流图(Line Buffer 接 Shift Register 接 MAC 树);当我看到硬件里的流水线延迟(Latency),我能立刻映射到算法里的帧缓冲需求;当我写 C 定点化代码时,我脑子里同时在跑 Verilog 的波形和 MATLAB 的浮点参考,确保每一级的误差都在预算内。
这种'双向翻译'能力,就是本课程要给你的元技能。最大的价值是培养 System Architect——既能在 MATLAB/C/Python 里调参,又能在 Xilinx Vivado 里看 RTL、Timing Report、place and routing,还能算清楚带宽和功耗的人。这种人才在工业相机、医疗影像、车载视觉领域极其稀缺。
1、方法论
我们聚焦方法论本身——如何在'算法思维'与'硬件思维'之间建立转换通道。这是一个'跨界翻译'课程:把数学语言翻译成电路语言,把流水线思维反哺给算法设计。
2、核心:三级跳工作流
MATLAB 浮点原型(验证算法正确性)
↓
C 定点模型(验证数值精度/范围)
↓
时序展开 Verilog/RTL(验证硬件可行性/资源)
关键洞察:C 定点化不是过渡,而是精度验证的黄金标准。MATLAB 算对的,C 算不对,一定是定点化错了;C 算对的,RTL 算不对,一定是时序错了。
3、思维架构的碰撞与感知,循序渐进
模块 1:两种思维方式的碰撞(建立认知框架)
算法人员的误区:'我先算完整张图的梯度,再做非极大值抑制'。 FPGA 人员的误区:'我只需要把公式里的乘加都用 DSP48 实现就行'。
正确认知:
- 空间域:图像是流,不是矩阵(除 DDR 缓存场景外)。
- 时间域:每个时钟周期必须产出结果(或满足吞吐率),不能有'迭代收敛'过程。
- 精度域:没有 float,只有 wire [N:0] 和 $signed() 的博弈。
对比实验:同一个 3×3 Sobel。
- 算法版本:卷积函数,边界补零,整帧计算。
- 硬件版本:Line Buffer+ 滑动窗口,边界复制,像素级流水。
模块 2:GAP 跨越——三大核心机制
2.1 数据流架构(Stream Processing)
相机的本质:CMOS 传感器通过 LVDS/MIPI 吐数据,是一维流,不是二维数组。
关键概念:
- Line Buffer:用 BRAM 缓存若干行,实现'垂直方向的时间换空间'。
- Kernel 对齐:如何让 3×3 窗口在流式数据上滑动(Valid 信号配合)。
- 乒乓与反压:当下游处理慢于上游时,TREADY 信号如何传递。


