尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

022、Xilinx/AMD FPGA ISP:软硬件可编程ISP流水线设计与时序收敛实战

022、Xilinx/AMD FPGA ISP:软硬件可编程ISP流水线设计与时序收敛实战 022、Xilinx/AMD FPGA ISP软硬件可编程ISP流水线设计与时序收敛实战开篇一个让我熬夜到凌晨三点的时序违例去年做的一个车载环视项目用的Xilinx ZU7EVISP流水线跑在300MHz逻辑分析仪抓出来的图像在暗部区域出现横向条纹。一开始怀疑是sensor噪声换了三块板子问题依旧。最后用Vivado的Timing Summary一看——setup违例0.3ns路径从AXI-Lite配置寄存器到ISP的Gamma LUT地址译码逻辑。这0.3ns让Gamma查表在特定地址切换时出现亚稳态导致输出像素值偶发跳变。当时真想砸了仿真器。FPGA ISP和ASSP ISP的本质差异你手里是块白板不是印好的书高通Spectra、海思ISP这些ASSP方案硬件流水线是固定的你调的是寄存器参数。FPGA ISP不一样你是在用Verilog/VHDL“画”流水线。这意味着你可以把去马赛克、降噪、色彩校正按任意顺序排列甚至把某个模块拆成两半中间插一个自定义的边缘检测。但代价是——所有时序问题都得自己扛。我见过太多从ASSP转过来的工程师上来就写一个超级大的always块把整个ISP流水线塞进去。综合出来频率只有80MHz还抱怨Xilinx不行。兄弟这不是芯片不行是你把组合逻辑路径搞得太长了。FPGA ISP设计的核心思维是把流水线拆成细粒度的小段每段之间用寄存器打拍让每一级的组合逻辑延迟控制在2-3ns以内。流水线架构设计从sensor raw到RGB888的“传送带”设计以我常用的ZU系列为例一个典型的ISP流水线分这么几级第一级MIPI CSI-2 RX把串行数据转成并行像素流。这里有个坑——MIPI的字节打包格式RAW10和RAW12的位宽不一样如果你用固定的移位寄存器去解包遇到RAW12就会多出两个bit的偏移。别问我怎么知道的问就是改过三版代码。第二级黑电平校正和坏点校正。这两个模块可以合并因为都是对像素值做加减法。但注意坏点校正需要周围像素的缓存所以会引入行延迟。如果你把黑电平校正放在坏点之后那黑电平的offset也要跟着延迟对齐否则图像边缘会出现一行偏亮一行偏暗的“拉链效应”。第三级去马赛克。这是整个流水线里最吃资源也最影响画质的模块。我建议用双线性插值加边缘方向判断不要一上来就上双三次卷积——在FPGA里实现双三次DSP48和BRAM的消耗会让你怀疑人生。而且去马赛克模块的输出是RGB但后续的降噪和色彩校正其实更喜欢在YUV域处理所以这里要做一个RGB到YUV的转换这个矩阵乘法用三个DSP48就能搞定别用LUT搭乘法器。第四级到第六级降噪、色彩校正、Gamma。这三个模块可以共享一组行缓存因为它们的处理窗口都是3x3或者5x5。我习惯把这三个模块的流水线深度做成一样的这样在调试的时候信号对齐会省很多事。时序收敛实战那些Vivado报错背后的真实原因时序收敛是FPGA ISP最磨人的环节。Vivado的时序报告会告诉你哪条路径违例但不会告诉你为什么。我总结了几类高频问题第一类BRAM输出到逻辑的路径过长。比如Gamma LUT用BRAM实现地址从AXI-Lite寄存器来经过两级译码逻辑再进BRAM输出又经过两级逻辑才到像素流。这条路径在300MHz下必违例。解法是把地址译码逻辑提前一拍在AXI-Lite写寄存器的时候就把地址算好存到BRAM旁边的寄存器里。这样BRAM的地址输入直接来自寄存器省掉两级逻辑。第二类多bit信号跨时钟域。ISP里经常有sensor的像素时钟和AXI-Lite的配置时钟两个时钟域之间传递配置参数。如果你用两级触发器同步单bit信号没问题。但如果是8bit的增益值直接同步就会出错。正确做法是用异步FIFO或者把参数先存到BRAM再用像素时钟域去读。这里踩过坑——用两级触发器同步8bit信号结果在温度变化时偶尔出现增益跳变排查了三天。第三类DSP48的级联。做色彩校正矩阵时三个通道的乘加运算如果串行用DSP48路径会很长。应该用DSP48的预加器和后加器把乘法结果直接级联到下一个DSP48的输入这样组合逻辑被DSP48内部的寄存器切断了。Vivado的IP核生成器里有“Flow Control”选项选“Pipelined”模式会自动插入寄存器。第四类复位策略。这是最容易被忽视的。FPGA ISP里像素数据流是连续不断的如果你用全局复位信号去复位流水线里的所有寄存器那复位释放的瞬间各个模块的复位释放时间可能差几个周期导致数据流错位。我的做法是像素数据流模块不用复位信号只在上电时用initial语句初始化或者用AXI-Lite写一个“软复位”寄存器只复位状态机不复位数据通路。这个技巧让我少了很多莫名其妙的图像错位问题。调试工具链ILA不是万能的但不用ILA是万万不能的调试FPGA ISPILA集成逻辑分析仪是必备的。但别傻乎乎地把整个流水线的信号都拉出来那会占用大量BRAM和布线资源反而影响时序。我的习惯是在关键节点拉信号——MIPI解包后的像素值、去马赛克前后的RGB、Gamma输出。每个节点只拉一个像素通道比如只拉G通道配合行场同步信号就能判断问题出在哪一级。还有一个技巧用Vivado的“Mark Debug”属性标记信号综合后这些信号会保留在网表里方便ILA连接。但注意不要标记太多信号否则综合器为了保留这些信号会打乱优化导致时序变差。我一般控制在20个信号以内。产线校准和FPGA ISP的“软”调优FPGA ISP的好处是你可以把一些调优参数做成运行时可写的。比如色彩校正矩阵的9个系数放在BRAM里通过AXI-Lite接口由ARM核或者上位机写入。产线校准时用色卡拍一张图上位机分析色差自动计算新的矩阵系数写回BRAM。这个过程不需要重新编译FPGA只需要更新寄存器值。但这里有个坑BRAM的写端口和读端口如果同时访问会冲突。我的做法是用双端口BRAM一个端口给像素流读另一个端口给AXI-Lite写。写的时候先写一个“影子寄存器”等像素流读到帧边界时再一次性切换。这样不会在图像中间出现半行新参数半行旧参数的“撕裂”现象。个人经验如果你要开始做FPGA ISP这几件事先想清楚第一别追求“全功能”。FPGA ISP的定位是灵活和快速迭代不是跟ASSP拼功耗和面积。你不可能在FPGA里实现一个跟高通Spectra一样强大的ISP但你可以实现一个针对特定场景比如车载夜视、工业检测的专用流水线而且能在两周内改版。第二时序收敛要“前置”。不要等代码写完了再去做时序分析。我在写每个模块的时候就会估算组合逻辑的级数如果超过8级就主动插入流水线寄存器。这样综合后的时序报告基本不会有大问题。第三多利用Xilinx的IP核但别盲信。比如MIPI CSI-2 RX IP它自带时序约束但如果你在它后面接了自己的逻辑一定要检查输出端的时序余量。IP核的输出时序是基于它自己的时钟域如果你的后续逻辑跨了时钟域要加异步FIFO。第四调试时先看波形再看图像。图像有问题先抓行场同步信号确认数据流没断。然后抓像素值看是整体偏暗还是局部异常。最后才去查算法逻辑。这个顺序能帮你省一半的调试时间。最后说一句FPGA ISP这行没有捷径就是一遍遍看时序报告一遍遍改代码。但当你看到自己写的流水线在示波器上跑出稳定的图像时那种成就感比用ASSP调参爽多了。
返回列表