做FPGA图像采集这些年,我接触最多的外部器件就是CMOS摄像头和中小尺寸液晶屏,这两类设备有一个共同特点:接口几乎都是MIPI DPHY。而Xilinx的7系列FPGA引脚并不原生支持MIPI标准,两者之间要接起来,硬件上有坑,逻辑上也有不少细节。这篇文章我会从MIPI DPHY的电气特性讲起,对比三种常见电平转换方案,再把手写接收链路的核心步骤和调试经验完整拆开,尽量让新手能照着走通,也让老手在电平匹配和问题排查上有所参考。
1. 项目整体思路与方案选型
1.1 为什么MIPI DPHY不是标准LVDS
很多人第一次打开MIPI摄像头的数据手册,看到差分信号、1.2V逻辑、同轴线缆,第一反应就是“这不就是LVDS吗”。这个直觉有一半对,但另一半会让你设计完板子后悔。
MIPI DPHY的物理层和LVDS有几个关键差异。第一,MIPI DPHY工作模式分两种:HS(High Speed)和LP(Low Power)。HS模式才是高速差分传输,典型差分摆幅只有140mV到270mV,共模电压约200mV;LP模式则是单端1.2V逻辑,用来传握手、消隐、总线控制等低频信息。第二,MIPI DPHY严格遵守源同步,数据和时钟lane都是独立差分对,没有主时钟,接收端要靠时钟lane的边沿来采样。第三,MIPI DPHY的时钟是DDR双沿采样,一个字节在时钟的上升沿和下降沿各采4bit,所以扛数据率做到1Gbps时,时钟频率只需要500MHz。
用生活类比来看,MIPI DPHY的通信方式像极了两个人既要谈重要结论,又要快速传递大段材料:LP模式是一张张递纸条,速度快不了但随时能停下来等;HS模式是投影仪连续放PPT,要讲究时序和持续流。两种状态切换还有专门的进出序列。
1.2 Xilinx 7系列IO资源能不能直接吃下DPHY
搞清楚MIPI DPHY的特性后,接下来的问题就是Xilinx 7系列的普通IO到底能不能接。7系列IO分为HP Bank和HR Bank两类,HP Bank支持1.2V到1.8V VCCO,HR Bank支持1.2V到3.3V VCCO。我们常用的Artix-7以HR Bank为主,Kintex-7、Virtex-7则大多带HP Bank。
关键点在于,7系列IO可以直接实例化LVDS25、LVCMOS12、SSTL12等电平标准,也有ISERDESE2、IDELAYE2、BUFIO、BUFR这类专门用于高速IO解析的硬核资源。ISERDESE2可以做到1:8的串并转换,IDELAYE2提供了可调的tap延迟,BUFIO用于把外部高速时钟直接送到IO逻辑。也就是说,如果只是接收HS差分数据和把LP信号按1.2V逻辑读进来,FPGA本身具备条件。
但不能回避几个限制。一是HR Bank的LVDS接收速率上限约1.0Gbps,HP Bank能做到1.25Gbps,这和MIPI摄像头的高数据率需求存在余量问题。二是MIPI HS共模电压大约200mV,而标准LVDS接收器共模范围虽然覆盖0到2.4V左右,但直接接会牺牲很大的噪声余量。三是MIPI的LP和HS在同一对差分线上分时复用,FPGA端必须同时兼顾两种模式的检测,不能简单只当差分信号处理。
所以最终方案选型,基本决定了后续逻辑的复杂度和稳定性。我个人建议:如果只是为了把摄像头数据采回来做处理,优先考虑用HP Bank直连HS差分信号,同时把LP信号通过电平转换或分压网络接到普通单端IO;如果板卡只能把MIPI放到HR Bank,或者数据率逼近1Gbps甚至更高,那就要认真考虑外部缓冲芯片了。
2. 电平转换方案对比与硬件设计
2.1 方案A:FPGA引脚直连,低成本路线
直连方案最大的诱惑是省钱、省面积,调试阶段尤其方便。具体接法通常是:MIPI差分对的正负端直接进FPGA的一对差分引脚,IO电平标准设为LVDS25,同时在该差分对内、靠近FPGA侧并联一个100Ω电阻;LP信号通过电阻分压把1.2V摆幅映射到合适范围,再接普通单端IO,IO标准可以设成LVCMOS12,但前提是所在Bank的VCCO必须正确供电。
这套方案在400Mbps~800Mbps每lane的数据率下,很多板卡实测是可以稳定工作的。原因是MIPI HS的差分摆幅虽然有140mV到270mV,但和LVDS接收器的±100mV阈值相比仍然有正余量;只要走线短、过孔少、阻抗匹配到位,FPGA内再用IDELAYE2微调采样相位,就能正常恢复数据。
但有几个坑必须提醒。第一,如果传感器输出的HS差分信号共模点不在LVDS接收器推荐范围内,容易在温度变化后出现错位或CRC错误,我遇到过一次白天正常、晚上产线一来料就偶发花屏的情况,最后定位到就是共模偏置不足。第二,HS和LP复用同一对差分线,直连方案里LP信号很容易通过共模电压波动干扰HS采样,所以建议在原理图上预留串阻和滤波电容位置,不要直接焊死。第三,HR Bank的LVDS速率上到1Gbps后余量很小,板长超过三四厘米就可能出现眼图闭合,这种场景不适合直连。
2.2 方案B:三极管和MOS管电平转换,针对LP信号
如果决定把LP信号和HS信号彻底分开处理,大多数工程师会选择在LP信号线上加电平转换。LP信号本质是1.2V的单端数字信号,频率不高,只出现在初始化、HS进出和总线控制等低频阶段,所以转换电路不追求高速,可靠性才是重点。
最常见的电路是NMOS双向电平转换,典型芯片如TXS0108、SN74AVC4T245,原理上用NMOS管实现双向传输,栅极接低电平基准,源极和漏极分别接VCC和VCCIO。手工搭BSS138这样的MOS管也能实现,只是上拉电阻要根据速度选,10kΩ用在几百kHz没问题,如果LP状态切换频率到了几兆赫兹,建议换成2.2kΩ左右。
三极管方案也很多,共射极反相电路最简单,但需要注意输出反相的问题;推挽结构的两个三极管可以做成同相,但调试时候容易因为上下管导通不对称导致波形畸变。我的建议是,量不大的情况下直接用现成电平转换芯片,比手工搭电路省心得多。LP信号一旦转成FPGA Bank能够接受的1.8V或2.5V电平,后面逻辑就没什么压力了。
2.3 方案C:专用桥接芯片,稳妥但是贵
如果项目周期紧、现场可靠性要求高,或者FPGA选型时没有预留高速IO资源,那么方案C最值得考虑。常见的做法是在MIPI信号和FPGA之间加一颗MIPI转LVDS、MIPI转并行或者MIPI桥接芯片。
具代表性的有TC358743(MIPI CSI-2转HDMI/LVDS)、DS90CR288(转LVDS并串)、THine THCV231/233系列(MIPI转LVDS或反之)、Lattice的CrossLink系列也常被拿来当协议桥。这类芯片内部集成了完整的DPHY PHY、LP控制逻辑和协议解析,FPGA端只需要接收并行RGB或LVDS信号,开发难度大大降低。
代价也很明显:芯片成本高、供货周期长、板级面积变大,而且部分桥接芯片需要额外配置I2C寄存器才能进入透传模式,这个过程本身又是一轮调试。所以方案C一般用于偏量产的项目,原型验证阶段除非MIPI速率实在超过FPGA承受范围,否则我建议优先用方案A加方案B的组合,先把数据流打通再说。
2.4 三种方案对比与选择建议
为了便于做方案评审,我把三种路线的关键差异整理成一个表:
| 方案 | 成本 | 逻辑复杂度 | 最大数据率 | 可靠性 | 适用场景 |
|---|---|---|---|---|---|
| A:FPGA引脚直连 | 低 | 高 | HR Bank约1.0Gbps,HP Bank约1.25Gbps | 中,依赖走线和工艺 | 原型验证、短距离、低速图像 |
| B:LP信号电平转换 | 低 | 中 | 取决于HS信号怎么处理 | 中高 | 绝大多数CSI-2摄像头接入 |
| C:专用桥接芯片 | 高 | 低 | 取决于芯片规格 | 高 | 量产、高速率、长期稳定要求 |
选择逻辑很直白:先看MIPI总体数据率,再看FPGA Bank类型,最后看项目阶段。800Mbps以下、走线距离短的,方案A完全可行;800Mbps以上或者板卡布局受限,建议至少加外部LVDS缓冲器;一旦数据率超过1.2Gbps,老老实实上桥接芯片,不要拿FPGA IO去赌。
3. 核心接收链路逻辑实现
3.1 引脚约束与时钟网络
硬件方案定下来后,FPGA内部就要开始处理真正的DPHY信号了。MIPI DPHY接收端一般包含一个时钟lane和若干数据lane,时钟lane的差分时钟频率是数据率的一半。以1080p30、4lane、每lane 800Mbps为例,时钟lane是400MHz,数据lane用DDR方式在每个时钟边沿采2bit,持续得到8bit数据流。
在Vivado工程里,时钟lane的差分输入应该用IBUFDS或IBUFDS_DIFF_OUT原语,然后接到BUFIO,BUFIO只能驱动IO逻辑和ISERDESE2,不能直接进全局时钟网络;同时用BUFR或MMCM做分频,得到字节时钟如100MHz,供后续逻辑使用。数据lane则用IDELAYE2加上ISERDESE2完成延迟调整和串并转换。
引脚约束需要留意IO标准。如果用LVDS25接收HS,约束文件里应写set_property IOSTANDARD LVDS_25 [get_ports {clk_p}],同时把差分端接属性DIFF_TERM设置为TRUE或外接100Ω电阻。LP信号引脚一般用LVCMOS12或经过转换后的LVCMOS18,这取决于Bank VCCO。
3.2 ISERDESE2实例化与数据对齐
ISERDESE2是接收链路的核心,它能把DDR串行数据转成并行字。7系列一个ISERDESE2最多支持1:8,而且1:8模式下需要Master和Slave两个原语拼接。下图是我工程里数据lane的典型实例化逻辑,相关端口已经简化,便于阅读:
ISERDESE2 #( .DATA_WIDTH(8), .DATA_RATE("DDR"), .INTERFACE_TYPE("NETWORKING"), .NUM_CE(1) ) iserdes_master ( .D(data_p), .DDLY(data_dly), .CE1(1'b1), .CE2(1'b1), .CLK(clk_io), .CLKB(~clk_io), .RST(rst), .Q1(q1), .Q2(q2), .Q3(q3), .Q4(q4), .Q5(q5), .Q6(q6), .Q7(q7), .Q8(q8) );注意ISERDESE2的CLK和CLKB必须接BUFIO输出的源同步时钟,不能拿系统的全局时钟替代,否则建立保持时间完全对不上。并行数据出来后,紧接着要做的是字节对齐。MIPI DPHY每一个HS burst都会先发送一个SoT序列,二进制是00011101,也就是0xB8,接收端通过检测这个固定图案,利用bitslip功能调整输出字节的起始位置,让多个lane的数据字保持一致。
对齐状态机可以这样写:每个字节时钟周期检查并行数据是否等于0xB8,连续出现两个周期以上就认为该lane对齐成功;如果长时间检测不到SoT,说明IDELAY相位不对或者极性反了,就要去重新调整延迟。
3.3 CSI-2包解析与ECC、CRC校验
数据lane对齐之后,就会看到一条连续的CSI-2协议流,数据被包装成长包和短包。长包结构是:包头由Data Identifier、Word Count、ECC组成,后面跟着Payload,最后是CRC16校验和。Data Identifier高6位是Data Type,低2位是Virtual Channel。
ECC是24bit汉明码(SEC-DED),它覆盖Data Identifier和Word Count的24位数据,校验位可以纠正1bit错误、检测2bit错误。CRC16是CCITT标准,多项式x^16 + x^12 + x^5 + 1,初值0xFFFF。调试阶段要把ECC和CRC错误计数寄存器引到ILA,一旦出现持续递增的错误,基本可以判定是采样相位或端接电阻问题。
实际代码里我习惯把包解析做成两个状态机:第一级负责从字节流中剥离包头和包尾,第二级负责按Data Type把Payload重组为AXI-Stream格式。RAW10格式的像素数据在MIPI链路里不是简简单单每个像素占10bit,而是5个像素打包成4个字节(50bit对应5个10bit像素),解析时要做位拼接,这一步最容易出错,一定要对照CSI-2规范仔细核对。
多lane数据还需要同步。CSI-2规范允许通道间存在少量歪斜,FPGA端需要用一个小FIFO吸收。最简单的做法是等待所有lane都检测到各自SoT后,再以第一个检测到SoT的时刻为准对齐各lane的字节流。这个过程我称为“组同步等待”,它能有效消除PCB走线长度差异带来的歪斜。
3.4 跨时钟域与AXI-Stream输出
字节解析完成后,数据还在源同步时钟域,比如100MHz,而下游图像处理或HDMI发送可能工作在150MHz甚至更高。这里必须用异步FIFO跨时钟域。FIFO深度建议至少512字节,否则在带宽抖动时容易丢数。
输出侧用标准AXI-Stream接口最方便,tdata按像素位宽拼接,tuser标记帧起始,tlast标记行结束。ISP模块、VDMA、HDMI控制器都能直接对接,省去自定义接口的适配成本。
AXI-Stream的握手规则要处理好,特别是tready拉低时,上游必须保持数据不能乱动。很多新手在这里只做了valid信号,忘了考虑ready反压,导致丢行或图像撕裂,这属于低级但高频的错误。
4. 现场调试与常见问题排查实录
4.1 用ILA抓关键信号定位问题
MIPI信号都是1Gbps级别的串行数据,ILA不能直接在管脚上高频采样,但可以在ISERDESE2输出后的并行数据域上观察。调试建议先从时钟lane入手,抓clk_io分频后的字节时钟频率是否正确;再抓每个lane的word_data,看能否捕获到连续0xB8;最后抓包解析后的包头和CRC错误标志。
如果ILA一直抓不到任何并行数据变化,优先检查三件事:MIPI传感器是否配置成持续HS模式、FPGA引脚约束是否锁对了引脚和IO标准、IDELAYE2的延迟值是否落在有效窗口内。传感器输出如果还是LP模式,FPGA这边自然看到的是静止电平,很容易产生“MIPI根本没信号”的错觉。
我在调试一块OV5640摄像头板时,曾经花了两天才发现配置脚本里把I2C寄存器地址的字节序搞反了,导致相机始终没有进入HS模式。所以调试MIPI前,先用示波器确认传感器已经在发HS突发,再动FPGA代码,这一条能省下大量无效操作。
4.2 相位、极性、端接三座大山
很多看起来“随机花屏”的问题,根源其实就三个:采样相位偏了、lane极性反了、端接电阻没到位。
相位问题是MIPI调试里最磨人的。MIPI HS数据率和时钟率是固定倍数关系,理论上时钟边沿应该正好落在数据眼的中心,但实际中走线延迟会让数据相对于时钟偏移。解决办法是扫描IDELAYE2的tap值,从0到31逐个尝试,记录每个tap下CRC错误包的个数,选择错误最少的一段作为工作点。7系列IDELAYE2的分辨率大约78ps,足够覆盖几个UI的窗口。
极性反了的表现是每个字节数据整体取反,SoT永远对不上。用ILA看到固定波形但就是解析不出0xB8,可以先检查一下硬件上是否把差分正负接反,或者干脆在逻辑里加一个极性反转开关。端接电阻则直接影响信号完整性,100Ω差分电阻缺失时,HS信号反射严重,眼图会很差。
| 现象 | 常见原因 | 排查动作 |
|---|---|---|
| ILA看不到任何数据 | 传感器未进入HS模式 | 示波器抓HS时序,查I2C配置 |
| 花屏且CRC错误持续 | 采样相位偏移 | 扫描IDELAYE2 tap,找错误最低窗口 |
| 长时间无SoT | 极性接反 | 检查差分输入极性,或加逻辑反相 |
| 偶尔掉一行 | 异步FIFO溢出 | 增加FIFO深度,降低上游阻塞 |
| LP状态读不出来 | 电平转换电路速度不足 | 查MOS管上拉电阻,或换电平转换芯片 |
| 图像上下颠倒、左右反 | 传感器镜像寄存器配错 | 对照sensor datasheet设置BGR/scan方向 |
4.3 DSI输出方向:给做屏幕的兄弟提个醒
文章开头主要讲CSI-2摄像头接收,但很多人做的是MIPI DSI屏幕点亮,逻辑方向正好相反。MIPI DSI发送端要自己产生LP状态机,完成从LP-11到LP-01再到LP-00最后进入HS的切换,这个进出序列如果时序不对,屏幕大概率直接黑屏。
屏幕初始化说到底还是通过DSI包下发命令,比如ST7701S这类常见驱动IC,竖屏改横屏通常就是修改地址0x36的BIT5和BIT6来控制扫描方向和RGB顺序。我见过不少工程师在FPGA里纠结DPHY时序,结果最后发现只是初始化命令参数没改对。
DSI的吞吐量需求经常被低估。同样的分辨率,RGB888和RGB565的带宽差1.5倍,而MIPI DSI是单向高速突发,每帧还要给HFP、HBP、VSA、VBP留出空白时间。如果你把MIPI屏直接挂在FPGA的HR Bank上,还把每lane速度推到接近上限,屏幕刷新率稍高一点就花屏,这时候增加lane数或者降低帧率比继续调代码更有效。
5. 写在最后
这套MIPI DPHY接口方案,我在多个基于7系列FPGA的项目里验证过。从最初的直连方案一路调到外部偏置网络,再踩过无数次CRC错误的坑,最大的体会是:MIPI的难点不在协议本身,而在硬件余量和时序细节,前者决定能不能稳定,后者决定能不能跑通。如果你手头正好有板卡在手,建议先按方案A把数据采通,再根据波形慢慢优化硬件,不要一开始就追求用专用芯片绕开所有问题,那样反而会丢失对DPHY底层原理的理解。后面有机会再单独写一篇实时图像链路的带宽估算,可以把帧率、lane数和时钟频率的账一次算清楚。