ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

工业摄像头FPGA主控迁移:硬件复用与逻辑隔离实践

工业摄像头FPGA主控迁移:硬件复用与逻辑隔离实践 1. 同一款摄像头为什么非要换颗FPGA工业摄像头这个圈子有个挺尴尬的现实一款产品定型之后硬件方案、镜头、图像传感器、外壳、接口协议基本都锁死了客户验收通过、产线跑顺、固件版本号也稳定了。结果某天采购过来一句“这颗FPGA交期52周价格翻了三倍”整个项目组就得连夜开会。换传感器镜头后焦、色彩标定、驱动全要重来客户那边过不了。换接口主机端SDK、线缆、采集卡全得跟着动等于重新做一款产品。算下来唯一能相对低成本替换的就是那颗FPGA本身——外围电路尽量不动图像传感器不动接口协议不动只把主控换掉这就是我理解的“换药不换汤”。我前后经手过三款工业相机的主控迁移从Spartan-6挪到Artix-7又从Artix-7挪到Zynq-7000最近一次是把Kintex-7的方案改成Zynq UltraScale。每次迁移最花时间的从来不是写RTL而是搞清楚“哪些东西是摄像头设计的汤底、哪些是FPGA带来的变量”。这篇文章就想把这件事讲透同款工业摄像头如何基于不同的Xilinx FPGA实现硬件怎么尽量复用逻辑怎么隔离厂商特性约束和IP怎么管理上板之后图像质量怎么回归。适合正在做相机主控选型、遇到器件替代、或者单纯想了解工业视觉硬件架构的朋友看哪怕你只做过FPGA入门级的数码管动态显示这里面的工程思路也能迁移过去。核心的诉求其实就一句话让FPGA成为摄像头设计里“可替换的那一块”而不是“绑死整个产品的那一块”。做到了缺货、涨价、停产这些事就只是换颗芯片的问题做不到一款相机就可能因为一颗器件直接死掉。2. 拆解“汤底”与“药”工业摄像头里哪些能换、哪些不能换2.1 摄像头的“汤底”是什么先把一款典型工业摄像头的组成拆开看。图像传感器比如常见的1/1.8英寸、500万像素的CMOS负责光电转换输出来是Bayer格式的RAW数据镜头座和光学系统决定了视场角、后焦、畸变接口物理层可能是GigE Vision、USB3 Vision、Camera Link或者CoaXPress决定了主机怎么拿数据再往外是外壳、散热、供电接口、触发和闪光同步的IO。这些部分一旦定了型改动成本极高因为它们牵扯到模具、光学标定、主机端兼容性。而FPGA在里面干的事说白了是三件接住传感器的数据流、把RAW处理成好看的图像、把图像按协议送出去。接数据流靠的是MIPI CSI-2或者LVDS这类高速串行接口处理靠的是ISP流水线去马赛克、坏点校正、自动白平衡、自动曝光、gamma、色彩校正矩阵、色彩空间转换送数据靠的是协议栈比如GigE的UDP/IP硬件卸载或者USB3的FX3桥接。这三件事里接口物理层和协议栈是“汤底”的一部分因为它们决定了外部世界怎么看这台相机而用什么器件去实现它们才是那味“药”。所以“换药不换汤”的第一条原则就出来了凡是主机端能感知到的、凡是要过客户验收的全部保持不变凡是FPGA内部实现层面的全部允许重构。MIPI的lane数、线序、时钟频率不能变图像的分辨率、帧率、像素格式、色彩响应不能变对外接口的连接器定义、协议版本不能变。至于内部是用LUT搭的还是用硬核是用BRAM缓存还是用DDR缓存这些随FPGA走。2.2 换FPGA时真正被牵动的部分换一颗Xilinx器件具体牵动哪些东西我按影响从大到小排一下。第一是电源树不同器件的核心电压、辅助电压、Bank电压、上电时序要求都不一样Artix-7的VCCINT是1.0VZynq UltraScale的VCCINT可能是0.85V电源方案要重新算。第二是高速接口的物理实现MIPI D-PHY在某些器件上是硬核在另一些器件上得用SelectIO软核搭两者的时序约束、眼图表现、可支持的速率完全不同。第三是存储器接口如果原来用DDR3做帧缓存换到另一颗器件时MIG控制器的配置、引脚分配、时序都要重来。第四是配置电路QSPI Flash的型号、配置模式、JTAG链拓扑都可能变。而相对稳定的部分也有图像传感器的驱动时序、ISP算法本身的数学逻辑、对外协议的状态机、帧缓存的管理策略。这些如果一开始就写成了与厂商无关的纯RTL迁移时几乎不用动。我个人的习惯是把和Xilinx原语、IP核相关的代码全部封进独立的封装层上层业务逻辑只调用统一的接口。这样换器件时改的是封装层不是算法。2.3 用一张表把“能换”和“不能换”说清楚设计层级具体内容换FPGA时是否可变处理策略光学与机械镜头、后焦、外壳、散热不变完全锁死迁移时不碰图像传感器型号、驱动时序、寄存器配置不变驱动代码做成通用SPI/I2C控制器对外接口连接器、协议版本、引脚定义不变物理层封装协议栈与器件解耦高速接收MIPI/LVDS的lane与速率部分可变速率锁定实现方式随器件电源与时钟电压域、上电时序、参考时钟可变每次迁移重新核算ISP算法去马赛克、AWB、AE、CCM不变纯RTL实现与厂商无关帧缓存DDR控制器与带宽分配可变用MIG/硬核控制器重建配置电路QSPI、JTAG、启动模式可变按器件手册重新设计这张表就是迁移工作的检查清单。每次动手前我习惯把它打印出来贴在工位上迁移完一项划掉一项。它最大的价值是防止你“顺手”改了不该改的东西——比如觉得原来那个gamma曲线不好看迁移时调了一下结果客户对比测试时发现颜色不对那就麻烦了。3. Xilinx器件家族怎么选从Spartan到Zynq UltraScale3.1 主流器件家族的横向对比工业摄像头对FPGA的诉求其实挺明确的要有足够的高速收发能力接MIPI或LVDS要有足够的DSP和BRAM跑ISP要有DDR控制器做大帧缓存功耗要可控封装要小最好还能带上硬核处理器省一颗MCU。按这个标准过一遍Xilinx的家族大致是这样的格局。Spartan-6和Spartan-7属于入门级逻辑资源少没有高速收发器Spartan-7有部分型号带GTP做低分辨率、低帧率的相机勉强够用但跑MIPI和完整ISP比较吃力适合那种500万像素以下、帧率30以内的成本敏感型产品。Artix-7是中端主力逻辑资源适中功耗低有GTP收发器可以用SelectIO软核实现MIPI D-PHY也能跑得动完整的ISP很多中小型工业相机用的就是它。Kintex-7往上就是性能和带宽的天下DSP和BRAM丰富收发器速率高适合高分辨率、高帧率、多路传感器的场景但功耗和成本也上去了。Zynq-7000和Zynq UltraScale MPSoC的特殊之处在于它把ARM处理器和FPGA放在一颗芯片里。这对工业相机太有吸引力了图像处理流水线跑在PL可编程逻辑里协议栈、网络服务、参数管理、日志这些跑在PS处理系统里省掉一颗独立MCU还能跑Linux做上层应用。我最近一次迁移就是把Kintex-7加独立MCU的方案换成了Zynq UltraScale板子面积小了一圈BOM也降了。器件家族逻辑资源量级高速收发MIPI D-PHY硬核处理器典型适用相机Spartan-6/7低无/有限软件实现无低分辨率低成本Artix-7中GTPSelectIO软核无主流工业相机Kintex-7中高GTXSelectIO软核无高帧率高分辨率Zynq-7000中GTPSelectIO软核双核Cortex-A9带智能功能的相机Zynq UltraScale高GTH/GTY硬核D-PHY四核A53RPU高端智能相机3.2 选型时真正卡脖子的几个硬指标选型手册上参数一大堆但真正决定你能不能换的往往就几个点。第一个是MIPI D-PHY的实现方式。如果原方案用的是硬核D-PHY迁移到只有SelectIO的器件上速率上限和时序余量都会变原本跑1.5Gbps每lane的软核可能只能跑到1.0Gbps这时候要么降帧率要么改传感器配置客户未必接受。第二个是收发器数量。多路相机或者需要高速下行通道的场景收发器不够就直接出局。第三个是DDR控制器的位宽和速率。帧缓存带宽算不过来图像就会掉帧。第四个是封装和引脚间距。PCB已经画好了新器件的封装如果引脚间距、Bank划分差太多板子就得重画那“换药不换汤”的意义就少了一半。这里插一句很多人查资料喜欢直接搜“xilinx的选型手册”但手册给的是器件能力上限不是你的设计能跑到的实际值。真正靠谱的做法是拿你的具体设计去跑一遍综合和实现看时序收敛情况和资源占用这比看任何手册都准。3.3 用Tcl脚本把选型结论固化下来Vivado的工程配置如果全靠GUI点换器件时会非常痛苦。我的习惯是把器件型号、速度等级、封装这些写成Tcl变量工程创建脚本化。# create_project.tcl set device_family zynq set device_part xcZU3EG-SFVC784-1-e create_project camera_top ./camera_top -part $device_part -force set_property board_part_repo_paths ./board_files [current_project] add_files -fileset sources_1 [glob ./rtl/*.v] add_files -fileset constrs_1 [glob ./xdc/*.xdc]这样换器件时只改一行device_part其他流程不变。脚本化还有个好处迁移到新器件后能一键复现整个工程环境避免“这版工程是谁在什么时候用什么设置建的”这种扯皮。踩过的坑告诉我工程脚本化是FPGA迁移里性价比最高的一件事前期花两小时写脚本后期能省好几天。4. 硬件层面让PCB尽量一次设计多颗器件复用4.1 电源树的通用化设计工业相机PCB面积通常很紧张电源方案既要效率高又要纹波低还要能给多颗候选器件供电。我的做法是把电源设计成“可裁剪”的结构核心电压用一个可调的DC-DC通过反馈电阻分压设定比如输出能在0.85V到1.0V之间切换这样Artix-7和Zynq UltraScale都能喂饱Bank电压用独立的LDO方便按器件调整上电时序用一个小的电源管理芯片或者CPLD来控制时序参数可编程。这里有个实操细节Xilinx器件的上电时序通常要求VCCINT先上、VCCAUX后上中间还有最小间隔要求。换器件时如果时序要求变了电源管理芯片的配置就得重烧。我一般会预留一个I2C可编程的PMIC改时序只改寄存器不动硬件。实测下来这套做法让我的两次迁移都没有重画电源部分。注意VCCINT的纹波要求通常在几十毫伏以内换器件时一定要重新测纹波尤其是新器件电流需求更大时原来的电感可能就饱和了。4.2 时钟与MIPI差分通道的布局要点时钟是整个相机的“心跳”。图像传感器的参考时钟、MIPI的字节时钟、DDR的参考时钟、收发器的参考时钟每一路都要求低抖动。换FPGA时如果新器件的时钟输入引脚位置变了PCB就得改走线这是很多迁移项目最头疼的地方。我的应对办法是在设计初期就把时钟布线留出余量用零延迟缓冲器把一路参考时钟扇出到多个可能的位置迁移时只改缓冲器的输出使能。MIPI和LVDS的差分对布局更是要命。差分对的长度匹配、阻抗控制、参考平面完整性任何一项出问题都会导致图像花屏或丢包。换器件时如果差分引脚所在的Bank变了走线长度通常要重新匹配。我的经验是把MIPI的差分对走在同一层、同一Bank、尽量短的路径上并且在新器件约束里重新核对引脚分配别指望原来的约束能直接复用。4.3 配置电路与JTAG的兼容处理QSPI Flash这块不同器件的配置模式可能不同。比如有的支持单线SPI有的要四线有的还要考虑启动镜像的格式。换器件时Flash的容量、速率、命令集都要重新确认。JTAG链更是容易翻车的地方尤其是链上有多颗器件时拓扑顺序、IR长度都要重新计算。# 生成配置镜像时指定bitstream与器件 write_cfgmem -format MCS -size 128 -interface SPIx4 \ -loadbit up 0x00000000 ./camera_top.bit \ -force ./camera_top.mcs顺带说一个常被问到的现象有人在加载硬件驱动时遇到“windows无法加载这个硬件的设备驱动”本质上还是驱动签名或版本匹配问题跟设计本身无关但迁移到新器件后换了下载器固件版本时容易碰到。这类问题我一般直接去官网下最新驱动包重装别在某一个版本上死磕。5. 逻辑层面把厂商特性关进“小黑屋”5.1 原语与IP核的隔离封装这是整篇文章我最想强调的一点。Xilinx的RTL里经常直接调用原语比如IBUFDS、BUFG、IDELAYE2、ISERDESE2这些原语在不同家族里的名字、参数、行为都不完全一样。Artix-7的ISERDESE2到UltraScale就换成了ISERDESE3参数名也变了。如果业务代码里到处散布这些原语迁移时就是灾难。我的做法是给每一类原语做一个封装模块对外暴露统一的接口。比如解串器封装成serdes_wrapper内部根据ifdef选择具体原语上层只管调用。这样迁移时只改封装模块内部算法层一行不动。// serdes_wrapper.v module serdes_wrapper #( parameter DATA_WIDTH 8 )( input wire clk, input wire rst_n, input wire data_in_p, input wire data_in_n, output wire [DATA_WIDTH-1:0] data_out ); ifdef TARGET_ARTIX7 // 使用 ISERDESE2 实现 elsif TARGET_ULTRASCALE // 使用 ISERDESE3 实现 else // 行为级模型用于仿真 endif endmodule5.2 约束文件的模块化管理XDC约束同样要模块化。引脚约束和时序约束分开物理约束和逻辑约束分开。我的目录结构通常是xdc/pin_*.xdc、xdc/timing_*.xdc、xdc/clock_*.xdc换器件时只替换引脚和时钟相关的文件时序约束里的时序例外通常可以保留。引脚约束最容易出错因为不同器件的Bank划分和引脚位置完全不同。我一般会用Vivado的report_property和get_package_pins来自动核对把新器件的引脚分配生成出来对比。# 列出指定Bank的所有可用引脚便于重新分配 set pins [get_package_pins -filter BANK 34] foreach p $pins { puts $p [get_property PIN_FUNC $p] }5.3 自定义IP的复用与版本管理工业相机里通常会做一些自定义IP比如MIPI CSI-2的协议解析、ISP流水线、帧缓存控制器、GigE的UDP卸载。这些IP如果一开始就按“与器件无关”的原则写迁移时直接复用。但现实是很多IP里会调用厂商的FIFO Generator、Block Memory Generator这类核这些核在换器件后需要重新生成。我的建议是用IP的.xci文件配合Tcl脚本自动重新生成而不是把生成后的网表固化进工程。这样换器件时脚本一跑所有IP按新器件重新生成虽然需要重新综合但避免了手工替换的遗漏。逻辑模块与器件相关度迁移处理方式传感器驱动低直接复用ISP算法无直接复用解串器/串化器高封装层重写帧缓存控制器高重新生成MIG协议栈低直接复用FIFO/BRAM中重新生成IP时钟管理高重新配置MMCM/PLL6. 实操把一款相机工程从一颗器件迁移到另一颗6.1 迁移前的兼容性清单动手之前我一定会把这张清单过一遍任何一项不确定就先解决再开工。清单包括新器件的MIPI实现方式能否支持原速率收发器数量是否够用DDR带宽是否满足帧缓存需求电源方案是否需要改板时钟引脚位置是否兼容配置Flash是否兼容JTAG链是否要调整。清单里我最看重的是前两项因为它们直接决定图像能不能正常出来。还有一项容易被忽略编译时间。小器件编译十几分钟大器件可能要一两个小时。迁移初期频繁迭代时这个时间成本要提前有心理准备最好先用行为仿真跑通大部分逻辑减少上板试错次数。6.2 Vivado工程重建与Block Design重构工程重建我一般不全靠GUI而是用Tcl脚本走流程。先把RTL、约束、IP按照前面说的组织方式放好然后用脚本创建工程、添加文件、配置IP。Block Design如果用了ZynqPS的配置要按新器件重新做DDR型号、外设使能、时钟配置都要改。这一步看着繁琐但脚本化之后其实很快。# 配置Zynq PS的DDR和外设 set_property -dict [list \ CONFIG.PSU__DDRC__DEVICE_CAPACITY {4GB} \ CONFIG.PSU__UART0__PERIPHERAL__ENABLE {1} \ ] [get_bd_cells zynq_ps] regenerate_bd_layout validate_bd_design save_bd_design6.3 时序收敛与ISP流水线的重平衡换器件后时序收敛是最耗时的环节。同一段RTL在Artix-7上跑到200MHz可能很轻松换到资源更紧张或者速度等级更低的器件上就跑不到了。这时候要么降频要么优化关键路径。ISP流水线通常是关键路径的重灾区尤其是去马赛克和色彩校正矩阵里面乘法器多、组合逻辑深。我的优化套路是先看时序报告里的WNS和WHS定位到具体路径然后把深组合逻辑打拍插入流水线寄存器如果乘法器不够用就时分复用DSP用更高的时钟换资源。这里要注意时分复用会改变数据流的节拍帧缓存的控制逻辑要跟着改别只顾着时序把功能改坏了。// 把深组合逻辑打拍改善时序 always (posedge clk) begin if (!rst_n) begin stage1 0; stage2 0; end else begin stage1 a * b c; // 第一级 stage2 stage1 d; // 第二级切断关键路径 end end6.4 上板联调与图像质量回归上板之后的第一件事不是看图像而是确认电源、时钟、配置是否正常。我一般先用Vivado的硬件管理器看器件ID、温度、电压再跑一个简单的寄存器读写测试确认传感器通信正常。然后抓MIPI或者LVDS的原始数据用ILA看有没有对齐、有没有误码。最后才出图。图像质量回归是个细致活。换器件后即使功能正常色彩、噪声、对比度也可能有细微差别因为不同器件的时序余量不同可能导致采样点偏移。我一般会把迁移前后的图像用同一套标定流程跑一遍对比色卡、对比噪点、对比暗角确保客户看不出差异。这套回归测试通常要花一两天但绝对值得。注意图像质量的差异有时候不是FPGA造成的而是传感器寄存器在迁移过程中被改动了。回归前一定要把传感器的寄存器配置和原来逐条比对。7. 常见问题与排查速查7.1 图像异常类问题的排查思路换器件后图像出问题大致分三类花屏、掉帧、偏色。花屏一般是MIPI/LVDS的物理层问题可能是采样点不对、差分对没匹配好、或者参考时钟抖动太大排查时先用ILA抓原始数据看包头包尾对不对再看字节对齐。掉帧多半是带宽问题帧缓存不够或者DDR控制器配置不对用Vivado的AXI Performance Monitor看带宽占用。偏色则是ISP参数问题先确认去马赛克顺序对不对再检查白平衡和色彩矩阵。现象可能原因排查手段解决方向花屏/条纹采样点偏移、差分失配ILA抓原始数据调整IDELAY、重做差分约束掉帧帧缓存带宽不足AXI性能监控提DDR速率、优化访问偏色去马赛克顺序错误检查Bayer相位修正像素排列无图像时钟未锁定、配置失败查时钟、查配置状态核对时钟约束、重配偶发误码时序余量不足看眼图、查WNS降速、加裕量7.2 综合与实现阶段的高频报错迁移时综合报错里最常见的是原语不存在、IP版本不匹配、约束里的引脚找不到。原语问题前面说了靠封装层解决。IP版本问题用脚本重新生成。引脚找不到多半是新器件上没有那个引脚需要重新分配。还有一类报错是时序约束里的时钟定义不匹配换器件后MMCM的输出频率可能因为输入时钟不同而算不出来。这种时候我会先用report_clocks看实际生成的时钟再回头修约束。7.3 我踩过的几个坑第一个坑是电源时序。有次迁移后上电偶尔起不来查了半天发现是新器件要求的VCCINT和VCCAUX上电间隔比原来长PMIC配置没改导致有时候配置失败。第二个坑是QSPI Flash的速率。新器件默认的配置时钟比旧器件高Flash跟不上配置时好时坏后来把配置时钟降下来才稳。第三个坑是DDR的参考时钟。换器件后DDR的参考时钟引脚变了我图省事沿用了原来的约束结果跑起来偶尔校验错重新核对引脚后问题消失。这些坑的共同点是它们都不在设计逻辑里而在“设计之外”的硬件配置和约束里。所以我的经验是迁移时对每一处硬件相关的配置都要重新核对不要想当然地认为可以沿用。哪怕看起来一样也要跑一遍确认。8. 最后聊几句实在的做工业相机这些年我越来越觉得FPGA选型不是一锤子买卖而是一个持续管理的过程。器件会缺货、会停产、会涨价产品却要卖好几年。所以从设计的第一天起就要为“换药”留好接口把厂商特性关进小黑屋把硬件设计做得可裁剪把工程管理脚本化把图像质量回归流程化。做到这些换一颗FPGA就不再是伤筋动骨的大事而只是换个零件而已。我自己现在做新项目会习惯性地问一句“如果这颗器件明天买不到了我还能换哪颗”然后把这个答案写进设计文档。这个习惯帮我躲过了好几次供应链的突发状况也希望对你有点用。
返回列表