初衷
回想起来,我的技术路径经历了从算法到 RTL,再到两者融合的过程。构建这座双向互译的桥梁,最终目标是做到'写算法时心中有电路,写 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)。看到算法里的卷积,脑子里浮现的不是矩阵乘法,而是滑动窗口的数据流图;看到硬件里的流水线延迟,能立刻映射到算法里的帧缓冲需求。这种'双向翻译'能力,才是本课程要给你的元技能。
最大的价值在于培养 System Architect 视角——既能在 MATLAB/C/Python 里调参,又能在 Xilinx Vivado 里看 RTL、Timing Report 和 Place & Routing,还能算清楚带宽和功耗。这种人才在工业相机、医疗影像、车载视觉领域极其稀缺。
方法论
我们聚焦方法论本身——如何在'算法思维'与'硬件思维'之间建立转换通道。这是一个跨界翻译课程:把数学语言翻译成电路语言,把流水线思维反哺给算法设计。
核心:三级跳工作流
MATLAB 浮点原型(验证算法正确性)
↓
C 定点模型(验证数值精度/范围)
↓
Verilog/RTL(验证硬件可行性/资源)
这里有个关键点:C 定点化不是过渡,而是精度验证的黄金标准。MATLAB 算对的,C 算不对,一定是定点化错了;C 算对的,RTL 算不对,一定是时序错了。
思维架构的碰撞与感知
模块 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 信号如何传递。
实战中,设计一个'流式直方图均衡'(理论上需要全图统计)vs'流式自适应阈值'(局部窗口即可),就能理解哪些算法天然适合流式,哪些必须帧缓存。


