多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Lattice CrosslinkNx上MIPI CSI-2图像采集实战笔记

Lattice CrosslinkNx上MIPI CSI-2图像采集实战笔记 前阵子我把一个 MIPI 接口的工业相机接进自己的图像处理板主控选的不是大厂旗舰 FPGA而是 Lattice 的 CrosslinkNx 系列 LIFCL-40。很多人一听 Lattice 就觉得只能做胶水逻辑实际上在视觉接口桥接这个细分场景这颗芯片比大逻辑器件好使得多。整条链路做下来从 MIPI D-PHY 硬核 IP 到 CSI-2 协议解析再到像素重组和板级调试我把过程中真正值钱的经验整理成这篇实战笔记。如果你是第一次在 CrosslinkNx 上跑 MIPI 图像采集或者已经踩过两三回坑还没摸清门道这篇内容应该能帮你省下不少弯路。1. 项目全景LIFCL-40 和 CrosslinkNx 为什么适合干这活1.1 桥接场景不是伪需求很多做视觉产品的人容易陷入一个惯性只要涉及 MIPI 图像输入就想着上大 FPGA 或者带 MIPI 接口的 SoC。但实际项目中大量存在“传感器 MIPI 输出、主控没有 MIPI 控制器”的尴尬局面比如一颗老的 ASIC 主控、一颗工业相机核心板、或者是自己做的一块只有并行接口的处理板。CrosslinkNx 这个系列本来就是 Lattice 针对视觉桥接场景定制的产品线LIFCL-40 属于其中中端偏上的一颗。它要做的事情很纯粹把 MIPI CSI-2 相机数据接进来解析成并行 RGB/YUV 数据再转成后端需要的接口格式比如并行 RGB、LVDS、千兆网、或者直接在片内做一部分 ISP 处理。说得直白一点它就是接口翻译官同时也兼着信号整形的活。这个场景不是伪需求。工业相机、医疗内窥镜、机器人视觉、AI 盒子几乎每个项目都会遇到“接口不匹配”的问题。带 MIPI 接口的 SoC 不一定选型合适而且为了一个接口去换整块主控代价太大。独立一颗桥接 FPGA 插在中间是行业里很成熟的玩法。LIFCL-40 的好处在于它不单单是接口转换还能利用片内逻辑做坏点校正、自动白平衡、格式转换等预处理给后端减负。以小博大的价值就在这里。1.2 硬核 D-PHY 让设计省掉一半的功夫CrosslinkNx 系列最大的卖点是片内集成了 MIPI D-PHY 硬核。这里“硬核”两个字特别关键。D-PHY 是物理层电路负责把高速差分信号从 sensor 上收下来包含阻抗匹配、高速时钟恢复、串并转换这些模拟前端电路。如果用普通 FPGA 的 IO 去实现 D-PHY理论上不是不行但传输速率和稳定性很难保证。普通 IO 做差分接收跑到几百 Mbps 就到头了而且对信号完整性的要求极其苛刻。可以用一个生活化的类比硬核 D-PHY 相当于你买回来的独立声卡软核方案相当于拿主板上的集成声卡去跑录音棚级别的编曲不是说不能用而是上限和稳定性都差了一大截。LIFCL-40 片上 D-PHY 硬核在规格上支持非常可观的速率单 lane 可以跑到 Gbps 级别常规 4-lane 配置完全能够承接 1080p 乃至 4K 级别的视频流。重点是这个 PHY 不占用 FPGA 普通的逻辑资源也不用你去写复杂的模拟接口逻辑只需要通过 IP 配置界面把参数填好生成一个 IP 模块然后示例化到顶层工程里就行。这也是 CrosslinkNx 和普通 FPGA 的核心差异点它把视觉应用最难的物理层给提前做好了。你不需要关心 D-PHY 的电平标准怎么实现不需要自己搭差分驱动器只需要关心 IP 怎么配、数据怎么拆。1.3 资源盘点LIFCL-40 能装下多少图像链路选型之前先对芯片资源有个数。LIFCL-40 大概有 39K 左右的逻辑单元片上存储资源足够放多组行缓冲和 FIFO还带 DSP 块可以做简单的算法处理外部可以挂 DDR3/LPDDR3 做帧缓存。对于图像桥接和轻量级 ISP 来说这个资源量是合适的。我见过有人拿它去跑复杂的神经网络算子那确实想多了。但做 1080p 的 YUV 转换、RAW 去马赛克、坏点校正这类任务LIFCL-40 的资源绰绰有余。它的功耗也比大 FPGA 低很多整颗芯片跑起来只有两三瓦在一些散热条件苛刻的工业产品里非常受欢迎。选型时还有一个需要留意的点CrosslinkNx 的 D-PHY 硬核位置是固定的分布在特定的 bank 上。这意味着你选封装和画 PCB 时必须把 sensor 的差分信号走线对准硬核所在的那几个引脚区域不能像普通 GPIO 那样到处乱摆。这个后面引脚分配时会细说。2. 开始动手Diamond 3.13 工程、D-PHY IP 和引脚2.1 先弄清楚 CSI-2 链路里谁是谁动手之前建议先把概念理顺。MIPI CSI-2 是分层协议从上到下是应用层、协议层和物理层。D-PHY 管的是物理层也就是那些差分线怎么驱动、怎么接收、怎么从 LP 状态切到 HS 高速状态。CSI-2 协议层管的是数据怎么打包、帧怎么切分、错误怎么校验。物理链路上有 Clock Lane 和 Data Lane 两类线。Clock Lane 提供 DDR 时钟也就是说接收端在时钟的上升沿和下降沿都会采数据。Data Lane 的数量通常是 1、2 或者 4每个 lane 上的数据位宽是 1 bit。一帧图像传下来字节会被打散轮流放在各个 lane 上接收端需要重新拼起来。协议层有两种包短包和长包。短包用来表示帧同步信号总共 32 bit内容是什么数据类型、哪一帧哪一行以及 8 bit 的 ECC 校验。长包才是真正的像素数据体先发 32 bit 包头发送数据类型和字节数再发像素主体最后发 16 bit CRC 校验。芒果都是这么做的。搞清楚这些再看 IP 就知道每个配置项是干什么用的了。例如“virtual channel”是指同一个物理链路上可以同时传多路摄像头的数据分辨数据属于哪一路例如“Data Type”是说明当前包是 RAW8、RAW10 还是 YUV422。如果这些概念模糊后续调试时连错误日志都看不懂。2.2 创建工程与版本选择的几个细节Lattice 的官方开发环境有 Diamond 和 Radiant 两套。CrosslinkNx 系列在后期的 Diamond 3.13 版本里已经支持了但 Lattice 现在主推的其实更偏向 Radiant。我这次用的是 Diamond 3.13原因是公司原有工程体系里大量旧模块都挂在 Diamond 下迁移成本高。如果你的项目是全新启动我建议优先考虑 Radiant编译速度和界面现代化程度都好很多。两套工具生成 IP 的方式有差异但核心逻辑是一致的。创建工程时器件选型要精确到具体封装否则后续引脚分配会出问题。选定 LIFCL-40 后Diamond 会加载对应的器件库。如果安装时没有勾选 CrosslinkNx 的器件支持工程是建不起来的。这一步最容易出问题的地方是 License 和器件库不匹配建议安装时把 Lattice 的 FPGA 库文件全部更新到最新。工程建好后先做一个 LED 翻转的测试设计把 bit 流下载进板子确认开发环境本身没问题。我习惯这样做不是浪费时间而是排除工具链问题。不然等你一路做到引脚约束才发现环境有问题排查起来非常痛苦。2.3 D-PHY 硬核 IP 参数配置与带宽估算在 Diamond 的 Clarity Designer 或者 Radiant 的 IP Catalog 里能找到 MIPI D-PHY IP这属于原厂提供的硬核封装。打开配置界面后需要决定方向是 RX接收还是 TX发送lane 数选多少HS data rate 多少Clock Lane 是不是连续模式。带宽估算没那么玄乎。拿 1920x108060fps RAW10 传感器举例子一帧的原始像素是 1920x1080x10bit约 20.7Mbit乘以 60 帧就是一秒的有效像素数据约 1.24Gbps。除以 4 个 lane每个 lane 的有效速率约 311Mbps。这个只是纯像素数据还得加上行消隐、帧消隐、包头和 CRC 等协议开销实际 lane 速率至少要按有效速率的 1.2 到 1.3 倍来选。也就是说 4-lane 配置下单 lane 至少要跑到 400Mbps 左右对应 HS Clock 200MHzDDR 双沿采样。我一般会在这个基础上再留 30% 余量选单 lane 600Mbps 左右的配置。余量是为了应对 PCB 信号质量不佳、电源噪声以及不同板卡批次之间的差异。D-PHY HS rate 配得越靠近硬核上限链路裕量越差后期出现偶发误码的概率越高。IP 配置界面里“连续时钟”和“非连续时钟”这个选项非常关键。很多传感器只在 HS 数据发送期间输出时钟属于非连续时钟模式。如果 IP 端配置成了连续时钟模式PHY 内部 PLL 会在没有时钟的间隙失锁重新锁定需要时间导致丢帧或者花屏。这个选项必须和 sensor 手册完全一致。2.4 引脚分配和 PCB 层面的配合引脚分配是整个环节里最容易被低估的一步。CrosslinkNx 的 D-PHY 硬核在芯片内部有固定物理位置对应的封装引脚也是固定的必须在这些引脚上接入 MIPI 信号不能随便用普通 IO 代替。在 Diamond 里做引脚分配时最好对照官方封装的引脚图把差分信号对按正负成对分配给硬核对应的引脚。MIPI 差分信号的命名一般是例如MIPI_RX_D0_P、MIPI_RX_D0_N这种形式Clock Lane 对应的就是MIPI_RX_CLK_P/N。PCB 层面有几个硬性要求这地方后期改板子代价极高必须一次做对差分走线阻抗控制在 100 欧姆尽量靠近源端。每个差分对内部等长误差控制在几十 mil 以内。不同 lane 之间也尽量等长尤其 4-lane 模式下 lane 间 skew 过大CSI-2 接收端即使有去偏斜逻辑也救不回来。MIPI 走线远离电源、时钟和其他高速信号避免串扰。我见过一个板子MIPI 走了 8 厘米还穿了两个过孔结果 1080p 下误码率高得吓人最后只能降速到 720p 才能勉强工作。这就是源头没控制好。3. CSI-2 协议解析与像素处理链路实现3.1 短包、长包帧结构拆解生成 D-PHY IP 和 CSI-2 Controller IP 之后FPGA 内部拿到的不再是原始差分信号而是一串带有包边界的数据序列。如果你用的官方 CSI-2 IP解包的大部分工作会自动完成它会输出包类型、数据类型、有效字节数、数据内容以及各种错误标志。但如果你想自己写解析逻辑或者需要调试异常就必须看得懂这些包的构成。短包结构很简单8 bit 的 Data Type、16 bit 的值比如帧号、行号外加 8 bit ECC。长包则是 32 bit 包头加数据体加 16 bit CRC。包头里的 Data Type 决定这个包是什么内容Word Count 表示数据体的字节数。常用 Data Type 值得记一下Data Type含义0x00帧起始 SoF0x01帧结束 EoF0x02行起始 SoL0x03行结束 EoL0x1EYUV420-80x2ARGB8880x2CRAW100x2ERAW80x2FRAW12调试时看 Data Type 能快速判断链路是不是正常的。比如你明明发的是 RAW10结果抓到的包一直是 0x2ERAW8说明 sensor 配置或者 IP 参数和实际不符。3.2 多通道数据对齐与 RAW10 像素重组4-lane 模式读取数据的时候字节并不是按照线性顺序排列在单根线上而是轮流分散到 4 个 lane 上。接收端需要先把每个 lane 上收到的字节重新拼接成完整的数据流这一步的关键是对齐机制。CSI-2 协议里帧起始短包SoF是所有 lane 对齐的基准。每个 lane 都会收到唯一的同步码接收端拿这个同步码找到各 lane 的起始位置再做 lane 间去偏斜。官方 IP 内部会做这件事前提是 IP 配置时使能了 lane alignment 功能。接下来就是像素重组。RAW10 格式在 MIPI 上打包是每 4 个像素占 5 个字节前 4 个字节分别存 4 个像素的高 8 位第 5 个字节拆成 4 份每份 2 bit分别作为 4 个像素的最低位。这个换算关系写错的话画面就是花的。很多人在这个细节上栽跟头我建议写一个专门的字节转像素模块并且用仿真把各种像素值都跑一遍再上板。3.3 帧缓冲策略为什么需要 FIFO 和双缓冲MIPI 的输入时钟和后续处理时钟通常不是同一个域。D-PHY 接收端出来的数据时钟由 PLL 从 MIPI HS clock 恢复出来而后续图像处理模块可能跑在系统时钟或者 DDR 时钟下跨时钟域处理必须要异步 FIFO。FIFO 的深度选择取决于你的处理架构。如果每行像素到达和处理同时进行只需要一行大小的缓冲如果后端处理是按帧进行的比如需要整帧图像做统计或者显示那至少要一帧的存储空间这个时候往往需要用到外部 DDR3/LPDDR3。我比较推荐使用双缓冲设计。A 帧正在被写入 DMA 到 DDRB 帧正在被后端模块读取两个 buffer 轮流倒。这个设计避免了“正在写帧的时候后端还在读同一帧”导致的数据撕裂。LIFCL-40 片内存储配合外部 DDR 完全可以支撑这种结构难点在 DDR 控制器的读写仲裁建议直接用 Lattice 官方内存接口 IP别自己造轮子。4. 约束、综合与 Reveal 调试实战4.1 约束文件别等最后再写很多人习惯把所有 RTL 写完了才开始写约束我建议反过来。创建工程后先根据设计预留的时钟结构把约束模板写好后面每加一个模块就同步更新约束这样能提前暴露问题。MIPI 链路里最重要的约束是输入时钟约束。MIPI 的 HS clock 是 DDR 双沿时钟频率等于 lane 数据率的一半。比如配了 600Mbps 的 lane rate那么 HS Clock 就是 300MHz。在约束文件中需要对时钟做 period 约束否则综合器不知道时钟周期时序分析的准确性无从谈起。引脚约束方面MIPI 专用引脚通常不需要手动指定 IO Standard因为硬核已经内置了对应的电气标准。但如果你在非专用引脚上留了普通 LVDS 或差分 IO则需要显式声明。这里我习惯把所有引脚约束集中放在一个.lpf或.ldc文件里方便版本管理。综合之后一定要看时序报告哪怕只有一条红色路径也要追根因。MIPI 链路常见的时序违例是跨时钟域信号没有做同步处理或者 FIFO 满/空信号逻辑过长导致路径变慢。这类问题大多数不是频率不够而是异步信号没处理好。4.2 Reveal Analyzer 抓 MIPI 信号的完整姿势Lattice 配套的调试工具是 Reveal Analyzer功能类似 Xilinx 的 ChipScope可以在 FPGA 上插入逻辑分析仪实时抓取内部信号波形。调试 MIPI 链路时Reveal 几乎是必备工具因为没有板级仪器可以直接看到 FPGA 内部的信号。Reveal 的使用流程不复杂在工程里插入一个 Reveal IP配置要观察的信号名称和触发条件综合布局布线后下载到板子Reveal Analyzer 会自动识别 JTAG 链路上的 FPGA开始采集波形。我常用的调试策略是先抓 CSI-2 Controller 输出的包类型和错误引脚比如 Data Type 信号、EoF/SoF 标志、CRC/ECC 错误标志。触发条件设为“帧结束信号上升沿”然后看一整帧数据里有没有错误标志拉高。如果错误持续存在再往下层抓 D-PHY 的 lane FIFO 状态信号判断是不是物理层的问题。这里有个细节Reveal 本身会占用片内 EBR 资源插入的观测信号越多占用的资源越多。调试阶段的工程资源使用率会比最终版本高不少属于正常现象。如果资源紧张可以分多次插入观察不同的信号一次抓 8 个左右就够用了。4.3 保留内部信号防止综合器“偷走”调试探针调试阶段最烦的问题之一就是你明明在 RTL 里写了一个有用的中间信号打开 Reveal 却发现它消失了。原因很简单综合器在处理综合结果时把没有扇出的逻辑优化掉了或者把某些信号与常量/等价信号合并了导致原始节点不再存在。这就是 Lattice Diamond 里“保留信号”要解决的问题。在 Diamond 的 Synplify 综合流程下可以用内嵌属性让综合器保留指定信号。常用写法是在信号声明处加属性(* syn_preserve true *) wire csi2_hs_active; (* syn_keep true *) reg [7:0] dbg_data_type;syn_preserve主要防止寄存器被复制或合并syn_keep则是强制保持网络连接不被综合器移除。如果你熟悉工具也可以在 Synthesis Options 里通过全局属性设置但按信号单独控制更精确。调试完成后这些探针信号和属性可以从代码中清掉避免占用资源和影响布局。保留信号这个功能很多人不太重视真到调试关键链路时才意识到它的重要性。我调试 D-PHY 和 CSI-2 之间的握手信号时就是靠syn_keep把几个关键状态机信号保留下来才定位到了是 IP 内部 ready 信号和外部控制逻辑之间的握手时序冲突。5. 高频问题速查与排障心得5.1 问题速查表项目调试过程中会遇到的问题不少整理成表格方便对照排查。现象可能原因对策抓不到 SoF/EoFsensor 输出配置和 IP 不一致检查 Data Type、lane 数、时钟模式链路锁定但数据全零D-PHY 接收端复位未释放检查复位时序确认 PHY ready 信号再处理数据偶发花屏、错行差分走线等长不够检查 PCB 走线降低 lane rate 验证ECC 错误持续增加电源噪声过大或者端接不良用示波器看 HS 眼图检查电源纹波首帧丢一半复位后没有等待 PHY 稳定增加稳定等待时间例如 10us 以上再使能接收Reveal 看不到信号综合优化把节点合并移除添加 syn_keep/syn_preserve 属性引脚分配错误分配到了普通 IO 而非 D-PHY 专用脚对照硬核位置重新分配引脚上面这张表是从实际项目中抽出来的高频项每一项背后对应的排查时间少则半小时多则两三天。5.2 我踩过的三个比较深的坑第一个坑是非连续时钟模式没配对。当时用的 sensor 只在数据突发期间输出 HS clockD-PHY IP 默认配置却是连续时钟模式。结果就是 config 时看着没问题数据偶尔能出但频率一高就频繁丢帧。最后查了 PHY 内部 PLL 锁定信号才发现没有输入时钟的时间段里 PLL 反复失锁等锁回来的时候已经丢了半个帧。第二个坑是引脚没有按硬核通道分配。开发板是现成的一开始我图省事把 MIPI 接到了普通 IO 上后来看数据手册才知道 CrosslinkNx 只有特定 bank 的特定引脚能接 D-PHY 硬核。那一次被迫重新画了转接板时间损失很大。做原理图之前一定要把器件的 D-PHY 引脚位置确认清楚。第三个坑是复位时序。MIPI IP 的复位不是简单地拉低再拉高就行官方推荐复位释放后要等一段时间让 PHY 内部 PLL 和校准稳定再去处理数据。我那时候直接在 FPGA 配置完成后立刻开始采样结果第一帧总是丢行。后来加了一个状态机等 PHY 的初始化完成信号拉高后再切换链路状态问题就消失了。5.3 还能往哪些方向扩展LIFCL-40 上跑通 MIPI 接收只是第一步这个平台的扩展空间比想象中大。最常见的是做接口转换CSI-2 转并行 RGB、转 LVDS、转千兆网这些都是现成的桥接需求Lattice 官方也提供大量参考设计。再往上可以加 ISP 功能。RAW 数据进来之后在片内做坏点校正、镜头阴影校正、自动白平衡、去马赛克然后把 RGB 数据输出给后端。这样 sensor 可以直接用便宜的 RAW 输出型号而不需要自带 ISP整体成本能降不少。多路 sensor 聚合也是一个方向。CrosslinkNx 支持将多个 CSI-2 输入转换成一路输出或者做虚拟通道复用把多路相机的数据流统统送到后端 SoC。智能摄像头、立体视觉这类的产品就这么做出来的。如果还想加人工智能前处理LIFCL-40 的逻辑资源略显紧张但轻量级的二值化、边缘检测这些算法还是可以塞进去。关键看你怎么平衡资源占用和处理延迟。最后分享一个经验这个项目做到后期我几乎不再怀疑 D-PHY 硬核本身的可靠性出问题的永远是配置、PCB 和复位这些外围因素。每次调试 MIPI 链路我都会先问自己三个问题时钟模式对不对引脚有没有走硬核通道复位等待时间够不够。把这三个查完八成问题已经解决了。这类专用桥接 FPGA 在视觉项目里真的值得多试试尤其是小批量、快速迭代的产品用好了能省一大半接口兼容的精力。
返回列表