FPGA接MIPI接口从入门到实战:电平转换方案与调试经验总结 做视频采集或者屏幕驱动的时候最容易被卡住的就是MIPI接口。这个接口在手机、摄像头、显示屏上到处都是但到了Xilinx 7系列FPGA上却不像UART、SPI那样直接就能用。我最早接手MIPI DPHY项目的时候也被折腾得不轻查协议、看电平、调时序踩了一圈坑才把CSI-2摄像头数据稳定采进来。这篇就把我整个实现过程、电平转换方案对比、调试经验都整理出来给后面要做类似项目的朋友一条能直接走的路。这篇内容主要面向两类人一类是在FPGA上做MIPI CSI-2图像采集、或者MIPI DSI屏幕驱动的硬件/逻辑工程师另一类是手里有7系列FPGA开发板、想自己动手把MIPI接口跑起来的学习者。阅读之前最好对Verilog、7系列FPGA的IO资源IBUFDS、IDELAY、ISERDES有基础了解就算不太熟我也会把关键原理讲清楚。1. 为什么MIPI DPHY会在FPGA项目里这么棘手1.1 MIPI DPHY到底“特殊”在哪MIPI DPHY是一种物理层协议常见于CSI-2摄像头和DSI显示屏接口。它和LVDS、SubLVDS、TMDS这些差分接口不太一样同一个引脚上要传两种完全不同的信号状态高速HS模式和低速LP模式。HS模式下时钟和数据都是差分信号典型差分摆幅只有200mV左右共模电压大概200mV速率从80Mbps到1.5Gbps甚至更高。这个状态用于传输真正的图像数据差分对上的信号极性就是标准差分对的样子。LP模式下两条线各自独立工作0V表示低电平1.2V表示高电平用来传指令、同步信号和总线控制信息。对FPGA来说最麻烦的就是这个LP模式——它既不是差分信号也没有固定极性。所以一个MIPI DPHY接口物理上看起来就是一对时钟差分线和一到四对数据差分线但电气上却要同时兼容高速差分和低速单端两种形态。FPGA的普通差分输入引脚可不会自动做这种切换这也是为什么不能直接把MIPI接到LVDS引脚上就完事。1.2 7系列FPGA的IO资源能不能直接兼容Xilinx 7系列FPGA的IO分为HPHigh Performance和HRHigh Range两种bank。HP bank支持1.2V-1.8V电压HR bank支持1.8V-3.3V。把MIPI信号接到这些bank上会面临几个现实问题。首先是LP信号的解码问题。LP状态下的1.2V高电平和0V低电平是标准的单端CMOS电平理论上可以用普通单端输入引脚读取。但HS状态下差分摆幅只有200mV普通单端输入根本识别不了。所以同一个引脚必须能同时处理两种电平这就要在外部硬件上做文章。其次是HS信号的接收问题。200mV的差分摆幅在1.2V或1.8V的bank上如果直接用IBUFDS这种差分缓冲器理论上是可以采到的。但问题是当总线处于LP状态时两条线的电压可能都是1.2V或者都是0V这会让差分缓冲器输出一个不确定的电平直接干扰后级逻辑。还有一个更实际的问题7系列FPGA的HP bank输入引脚并不能保证在MIPI的高速率下都满足建立时间/保持时间要求。高速MIPI信号往往需要配合IDELAY做逐bit延迟调节才能把每个lane的数据对齐到时钟上。所以结论是7系列FPGA确实有实现MIPI的底层资源IBUFDS、IDELAY、ISERDES、BUFIO但需要在电气接口上先解决LP/HS共存的问题。这就是电平转换方案要做的核心工作。1.3 一个典型的应用场景摄像头采集我常用FPGA做车载或者工业相机的图像采集。传感器输出MIPI CSI-2信号FPGA要把它接收下来然后做ISP处理或者转成并行RGB输出给后端。传感器端的MIPI输出一般是1.2V电平FPGA这边需要把HS差分信号整理成可采样的差分对同时把LP状态信息提取出来。整个链路大概是传感器MIPI输出 - 电平转换/信号调理 - FPGA HP Bank - IBUFDS接收HS数据 - IDELAY调相位 - ISERDES DDR采样 - 字节对齐 - 协议解析 - 图像数据输出。2. 电平转换方案横向对比选型前先把账算清楚这个部分是整个项目的核心难点之一我先说结论没有哪种方案是万能的不同速率、不同方向接收还是发送、不同量产规模对应的最优解都不一样。2.1 方案一1.8V直连HP Bank看起来最省事坑也最多网上很多方案说MIPI可以直接接到7系列的HP bank上理由是MIPI HS差分摆幅200mV、共模200mVHP bank的差分输入阈值可以覆盖。这个说法只对了一半。直连方案在接收高速信号时确实有可行性。把MIPI差分对直接接到HP bank的P/N引脚上使用IBUFDS接收同时用另一对引脚监测LP状态。这里的关键问题是LP状态时两条线的电压都是1.2VIBUFDS的输出会变成不定态所以必须在逻辑层面对LP状态进行屏蔽。也就是说只有当检测到HS状态开始时才让数据采样通路工作。这个方案的难点在于HP bank的输入共模范围。7系列HP bank的输入共模电压范围是0V到VccoMIPI HS共模虽然低于Vcco1.8V或1.5V理论上是满足的。但实际MIPI信号经过PCB走线、连接器、线缆之后共模电压会有偏移和噪声很容易超过输入范围。我实测过短距离板级直连、速率在1Gbps以下时直连方案可能能跑通但稍微拉长一点走线或者速率上去之后误码率就明显上升。另外直连只解决HS数据接收LP信令还是要靠额外的电阻网络或者专用电路处理。对于MIPI DSI驱动屏幕这种需要FPGA主动发送HS信号的场景直连基本不可行因为FPGA输出引脚无法产生MIPI那种低摆幅差分加LP单端切换的复合信号。2.2 方案二电阻分压网络低成本但只能单向有一个看起来很聪明的做法在MIPI差分对上串电阻、对地并电阻把1.2V电平转换成FPGA HP bank能接受的1.8V或者2.5V电平。这个方案在低速、单向的信号上确实能用。比如把MIPI时钟单端1.2V信号通过分压网络升到1.8V送给FPGA的普通输入引脚。但MIPI是差分信号分压网络会同时影响共模和差模而且电阻的寄生电容会衰减高频分量。我没有见过用纯电阻分压能把MIPI 1Gbps以上信号保真传好的案例。信号完整性问题在这个方案里特别突出所以电阻分压比较适合处理LP状态信号不适合处理HS高速数据。如果非要尝试电阻分压处理HS数据建议用低阻值电阻几十欧姆级别并且计算好与FPGA输入引脚寄生电容形成的RC带宽。7系列HP bank引脚寄生电容大概在几pF量级和50欧姆电阻组合起来3dB带宽大概也就1GHz上下勉强够1Gbps速率但完全没有裕量。温度变化、批次差异都会让眼图变差。2.3 方案三二极管钳位紧急替代不推荐量产还有用二极管钳位电路的思路是把MIPI信号通过二极管接到某个参考电压上把高压部分钳制住。这个方案的问题非常明显二极管结电容会严重影响高速信号而且钳位电压随温度漂移1.2V系统里的200mV差分信号稍微被二极管非线性搞一下眼图就没了。我在实验室救急的时候用过一次当时只是确认MIPI有没有波形并不追求长时间稳定传输。如果要跑完整的数据流二极管钳位方案可以直接放弃省下来的时间用来选型更划算。2.4 方案四专用电平转换/redriver芯片稳定可靠的主流选择最终我推荐的是专用MIPI DPHY信号调理芯片。这类芯片有几大类适用于不同场景一类是MIPI Redriver像TI的SN65DPHY440、SN65DPHY445、Diodes的PI3HDX1204这类。它们的作用是接收MIPI信号重新整形后输出能把LP/HS状态检测、电平转换、均衡都处理掉。FPGA这边只需要接输出端的差分信号。SN65DPHY440是4 lane DPHY redriver支持CSI-2/DSI输入侧兼容1.2V MIPI输出侧可以配置成1.8V差分正好适配FPGA的HP bank。这是接收场景最稳妥的选择。另一类是MIPI转并行接口的桥接芯片比如东芝的TC358746CSI-2转并行、TC358748、TC358870并行转DSI还有很久以前的SN9C、OV系列搭配的解串器。这类芯片直接把MIPI协议解析成并行数据FPGA只需要接并行总线。缺点是灵活性差但开发速度最快。还有一类是SerDes芯片比如TI DS90UB913/914、DS90UB953/954它们把MIPI转换成私有串行格式通过同轴线或者屏蔽双绞线传输接收端再恢复成MIPI或并行数据。如果项目涉及远距离传输这类芯片是最合适的。2.5 各方案对比表与选型建议方案适用方向速率上限成本可靠性开发难度直连HP Bank接收HS数据需软件屏蔽LP1Gbps以下板级短走线可试最低中低共模偏移敏感中电阻分压网络单向LP电平转换低速不适合HS低低低二极管钳位应急测试极低低极低低Redriver芯片接收/发送双向均可可达1.5Gbps中高中桥接芯片接收或发送转并行取决于芯片中高高低SerDes芯片远距离传输取决于芯片高高中我个人的选型建议很简单如果只是FPGA接收MIPI CSI-2摄像头且PCB空间允许优先选SN65DPHY440或同等级redriver然后接FPGA HP bank。如果项目要快速出原型直接上TC358746这种桥接芯片FPGA侧做并行接口。如果是FPGA驱动MIPI DSI屏幕则用TC358870这类并行转DSI芯片或者用带MIPI DSI输出的FPGA专用bridge。有一个很重要的点是redriver输出到FPGA的走线要尽量短而且建议把redriver输出侧的共模电压配置成接近FPGA Vcco的1.8V同时保留交流耦合电容这样FPGA侧可以用标准的LVDS/HS差分输入来接收。3. 用7系列FPGA实现DPHY的完整流程3.1 先把物理层说清楚HS传输和LP信令MIPI DPHY的物理层状态机用两条线Dp/Dn的电压组合来表示。HS模式是差分传输LP模式用两条线的单端电平表示四种状态LP-00、LP-01、LP-10、LP-11。数据传输前发送端会先发一个SoTStart of Transmission序列从LP-11 - LP-01 - LP-00 - HS-Zero然后开始HS时钟和数据结束后发EoTEnd of Transmission回LP状态。FPGA侧如果直接采样LP电平作为状态判断需要为每个lane的Dp/Dn各加一个单端输入缓冲把LP状态提取出来然后交给状态机判断SoT/EoT。Redriver或桥接芯片通常会把这些状态转换逻辑做好FPGA就不用自己管LP状态机。自己用FPGA直连实现时LP状态提取是必须做的而且要用专门的异步状态机来处理不能简单地用打拍同步的方式去采样因为LP状态变化的时机和HS时钟是完全异步的。3.2 引脚分配与bank约束HS高速对建议放在同一个HP bank并且优先使用相邻的引脚对。7系列FPGA的ISERDES在同一个IO tile里时钟和数据引脚必须满足BUFIO/BUFR的时钟走线要求。通常我把MIPI时钟对放到一个MRCC引脚对数据lane放到同一bank的普通差分对。bank电压设置也要注意。如果用redriver输出1.8V差分信号Vcco就设1.8V。如果直连MIPI1.2V共模Vcco设1.5V会更稳妥但这时其他GPIO也只能跑1.5V。bank电压一旦确定整个bank上所有IO的电平标准就确定了所以规划引脚时要提前把MIPI lane集中到独立bank里。XDC约束示例set_property PACKAGE_PIN R4 [get_ports mipi_clk_p] set_property PACKAGE_PIN R5 [get_ports mipi_clk_n] set_property IOSTANDARD LVDS_25 [get_ports mipi_clk_p] set_property PACKAGE_PIN R6 [get_ports mipi_d0_p] set_property PACKAGE_PIN R7 [get_ports mipi_d0_n] set_property IOSTANDARD LVDS_25 [get_ports mipi_d0_p]注意这里IO电平标准我用了LVDS_25还是LVDS_18取决于redriver输出配置。如果redriver输出是1.8V就用LVDS_18或者DIFF_SSTL18如果HP bank Vcco是1.8V用LVDS_18即可。直连MIPI的场景如果Vcco是1.5V可以尝试DIFF_SSTL15但这个需要非常小心地看IBIS模型和眼图。3.3 差分输入缓冲与时钟恢复进入FPGA的差分信号首先经过IBUFDS变成单端然后MIPI时钟信号直接进BUFIO驱动ISERDES的CLK同时经过BUFR分频后给FPGA逻辑做同步。数据lane的ISERDES使用与时钟lane相同的BUFIO时钟在DDR模式下每个时钟沿采集一个bit。这里有一个常见误区MIPI时钟和数据lane的skew并不固定所以不能只靠ISERDES本身的DDR采样就完事。每个数据lane需要独立的IDELAY来调节输入延迟保证每个bit都正好落在采样窗口中心。IDELAY的调节精度和范围需要计算。7系列FPGA的IDELAY参考时钟通常是200MHz每个tap约78ps。MIPI 1Gbps对应bit周期1ns半个bit窗口就是500ps大约6.4个tap。所以至少要保证IDELAY的调节步进在78ps以下并且有足够的范围覆盖lane间skew。通常IDELAY范围是0-31个tap约2.4ns对板级MIPI来说够用。如果时钟速率更高比如1.5GbpsIDELAY的tap精度可能不够就需要考虑在FPGA外部用redriver自带的均衡功能来压缩skew。3.4 字节对齐与per-lane deskewISERDES输出的并行数据是bit流但MIPI协议里的字节边界不在固定位置。每个lane需要在SoT之后插入的同步序列中找到字节边界。MIPI DPHY的SoT序列后会有固定的同步码型FPGA逻辑通过移位搜索这个码型确定从哪个bit开始算作一个字节。做完字节对齐还要做lane deskew。MIPI CSI-2把数据分发在多个lane上每条lane的字节流在发送端被顺序拆分接收端必须把各lane对齐到同一时刻。具体做法是协议头部有line start和frame start的同步码接收逻辑检测到之后用FIFO或者寄存器对每个lane做延迟补偿直到所有lane的同步码出现在同一拍。我实现的时候先用一个简单的训练序列比如摄像头输出全0xFF的数据来验证每条lane的字节边界和skew然后再切换正常数据流。这样可以把对齐问题和图像内容解耦排查起来会快很多。3.5 协议层解析与数据打包物理层对齐做完之后就是CSI-2或者DSI协议层的解析。CSI-2包结构短包Short Packet用于帧开始/结束、行开始/结束长包Long Packet用于图像数据包含数据包头Data ID、字计数、ECC、数据负荷、CRC校验。FPGA里实现协议解析建议直接用一个状态机WAIT_FS、WAIT_SHORT、WAIT_HEADER、RECEIVE_DATA、CHECK_CRC。不要在一个大状态里做所有事MIPI数据流中间有各种空闲期和同步包状态拆细一点出错时容易定位。对于图像数据一般从CSI-2长包里剥掉头部把像素数据按需要的格式拼接成RGB565、RAW10、YUV422等再打上帧同步和行同步信号输出。代码层面没有太多捷径但有一个建议尽量把协议解析和图像处理分成两个独立模块中间用FIFO隔离。否则协议解析模块的时序收敛问题会拖累整个图像处理链路。4. 调试实录示波器、眼图与常见问题排查4.1 时钟信号示波器波形怎么看调试MIPI最先用的工具一定是示波器但普通示波器看MIPI有讲究。MIPI HS时钟频率可能是几十MHz到几百MHz差分摆幅200mV。用探头测量时最好用差分探头或者用两个通道做数学减法。带宽至少1GHz否则波形边缘被滤掉眼图完全失真。MIPI时钟信号示波器波形正常情况应该看到稳定的方波高电平约300-400mV相对地低电平约0V且没有明显的振铃。如果波形上有很大的过冲说明PCB走线阻抗不匹配或者探头地线太长。如果波形幅度明显低于200mV那可能信号在传输链路里衰减过大需要考虑redriver或者缩短走线。另外如果想看LP状态下的时序要切换到长时基观察HS/LP切换瞬间的波形。这里最容易发现的问题是SoT序列里的LP-00到HS-Zero切换不干净导致FPGA状态机误判。4.2 建立时间/保持时间与IDELAY调校7系列FPGA内部触发器的建立时间和保持时间要求可以在数据手册里查到但实际调试时更关心的是IDELAY怎么调才能满足这些要求。我的调校方法是先给固定IDELAY值让摄像头输出静态图像上位机或者FPGA内部统计图像是否花屏然后扫IDELAY 0到31找出所有能正常出图的tap范围取中间值。这个过程可以写一个小逻辑自动做通过AXI或者UART把tap值下发不用每次重新综合。有一种情况需要特别留意温度变化会导致IDELAY的tap延迟漂移所以扫出来的有效窗口如果很窄比如只有两三个tap那说明信号裕量不足不能通过继续调IDELAY解决。这时候要回头查硬件可能是电平转换芯片配置不对或者PCB走线有问题。靠软件调延迟只能掩盖一部分硬件问题不能硬抗。4.3 常见故障速查表现象可能原因排查方法完全无信号FPGA检测不到SoT电平转换芯片未工作/配置错示波器看转换芯片输入输出波形查PDN引脚、I2C配置时钟有波形数据lane采不到数据lane deskew未对齐检查每条lane的字节边界是否找到看word align标志图像花屏/有斜纹行同步对齐错误或IDELAY未调好扫IDELAY看数据lane之间skew是否过大图像颜色不对像素格式解析错误确认CSI-2 Data ID和位深设置检查RGB位宽映射偶发帧丢失状态机收到未预期的短包抓状态机跳转记录查看错误包类型长时间运行后失锁温度漂移导致延迟裕量不足加宽有效窗口或改用redriver提高信号裕量4.4 几个实用避坑技巧第一个坑是不要把MIPI差分对交叉接反。MIPI DPHY不像USB那样自动识别极性P/N接反会导致完全没数据。画PCB时一定要标清楚制板回来后用万用表量一下连接器到FPGA引脚之间的连通性确认没有交叉。第二个坑是地平面。MIPI是高速信号参考地平面必须连续。如果走线跨了分割地眼图会明显变差。我踩过一次测试的时候发现某个lane的误码率一直降不下来最后发现是信号线从一层换到另一层时换层旁边的地过孔没打回流路径绕了一大圈。第三个坑是redriver芯片的初始化。SN65DPHY440这类芯片很多需要上电顺序和配置引脚设置出厂默认不一定适合所有FPGA。参考手册里的上电时序复位引脚要拉低足够时间配置引脚要用电阻设置正确的模式。不要想当然认为芯片上电就能干活。第四个坑是和Xilinx工具的版本有关。早期Vivado版本对IDELAY的时序约束有bug在7系列上偶尔会出现“提示IDELAY路径不收敛”的情况。遇到这种问题先升级Vivado到较新版本并且在网上搜一下已知issue。还有Xilinx SDK 2015.4这类老版本工具已经很少用了如果是为了配合旧工程记得装到专用环境里避免和最新Vivado冲突。5. 一个具体的接收链路实例以我最近做的一个CSI-2摄像头采集项目为例用的是OV5640传感器RAW10格式2 lane1Gbps per laneFPGA是Artix-7 XC7A35T。硬件链路上我选了SN65DPHY440做redriver输入接OV5640的MIPI输出输出接FPGA的HP bankVcco设1.8V。SN65DPHY440的I2C地址默认是0x50配置成4 lane模式但实际上只用了2 lane另外两路用电阻拉默认状态。SN65DPHY440的PDN引脚接FPGA的GPIO开机时先拉低复位再拉高使能。FPGA内部时钟通道CLK_P/N经IBUFDS后直接接BUFIO然后送两个ISERDES一个用于DDR采样一个用于bit slip。数据通道每lane的D0、D1各接一个ISERDESD0和D1的ISERDES共用BUFIO时钟但各自有独立的IDELAY。ISERDES配置成DDR模式宽度8位。意味着每个时钟周期采8个bit两个lane就是16bit。CSI-2 2 lane RAW10格式下每帧每行数据量是固定的协议解析模块按照short packet的line start信息把两个lane的字节流重新拼成RAW10像素。这个项目在调试时遇到过一个问题图像偶尔出现一行偏移。排查了一天最后定位到是IDELAY在温度变化后的漂移方向不一致导致两个lane的skew慢慢变大。后来我改成每隔一段时间重新校准一次IDELAY问题就消失了。所以量产设计里要么用redriver的固定均衡来降低对IDELAY的依赖要么在FPGA里做一个周期性的自动校准逻辑。6. 发送方向怎么做FPGA驱动MIPI DSI屏幕接收方向讲得比较多但很多项目其实是FPGA驱动MIPI DSI屏幕比如做仪表显示、HUD。这个方向更麻烦因为FPGA要主动产生符合MIPI规范的HS低摆幅差分信号同时还要正确控制LP状态切换。直接用FPGA IO产生MIPI HS信号基本不现实。FPGA的普通输出引脚是CMOS推挽结构输出高电平是Vcco没法生成200mV摆幅的差分信号。就算串联电阻衰减LP状态也无法模拟正确。所以这里几乎只能依赖专用桥接芯片。我的做法是FPGA输出并行RGB565或者RGB888加行场同步接TC358870XBG由TC358870内部完成并行到MIPI DSI的转换。TC358870的关键配置项包括输入像素时钟频率、数据格式、lane数、DSI视频模式burst mode / non-burst with sync pulse等。这里有一个和热词里提到的“linux 适配 mipi转lvds”“st7701s mipi”相关的经验驱动MIPI屏幕时FPGA侧的配置不仅要匹配屏幕上电时序还要匹配屏幕的初始化序列。很多MIPI DSI屏幕需要主机发送初始化命令才能点亮这些命令就是LP模式下通过I2C或者DSI命令发送的。TC358870这类芯片一般支持通过I2C下发命令FPGA只负责图像数据流。如果必须用FPGA直接产生LP状态可以在数据lane上额外接一个三态缓冲或者模拟开关HS数据由FPGA内部SERDES产生LP状态由另一个单端IO控制。这样做的复杂度很高因为HS和LP在时间上是交替的切换瞬间的时序必须和协议严格对齐。我做过一版实验性质的勉强能点亮屏幕但信号质量不稳定不推荐实际产品使用。7. 一些实测数据和经验总结说几个我实测过的数字供参考。用SN65DPHY440加Artix-72 lane CSI-21Gbps per lane走线长度从传感器到FPGA大概8厘米经过一个FPC连接器整个链路的眼图余量在温度25度时大概是0.35UI左右环境温度升到60度后降到0.22UI左右。如果不用redriver直接连常温还有一点余量60度时基本已经闭合了。这个测试让我彻底放弃了直连方案。IDELAY的tap值在长时间运行中观察到会有2-3个tap的漂移对应大约160-240ps。所以调试的时候扫出来的有效tap窗口至少要保留5个tap以上的裕量否则高温老化后就会出现偶发花屏。还有一个经验是关于PCB走线的MIPI差分对间距控制好一般设计4mil线宽、4mil间距配合参考地平面特征阻抗100欧姆差分。但真正决定信号质量的往往是连接器。很多MIPI连接器本身信号完整性一般如果项目允许尽量选用经过验证的型号或者直接使用板对板连接器别用质量太差的FPC。调试工具方面示波器带宽至少1GHz最好带MIPI协议解码。没有协议解码的话就靠FPGA内部逻辑抓状态机也能定位问题但效率低一些。逻辑分析仪对MIPI这类高速信号不太合适除非有专门的MIPI探头。我个人在实际操作中还有一个体会MIPI调试最忌讳一次性改很多变量。要改就一次改一个点改完看结果。比如先保证时钟lane有波形再保证数据lane的字节对齐然后才去调IDELAY。如果一上来就同时又换redriver配置又改FPGA逻辑出了问题根本不知道是哪里引起的。最后分享一个小技巧在FPGA里加一个简单的误码率测试模块让传感器输出已知的测试图案比如全0xAAFPGA接收后统计错误bit数通过UART或者LED显示。这个模块在整个调试过程中非常有用比用肉眼盯图像靠谱得多。后续做自动化测试的时候也可以直接把这个模块扩展成在线的链路质量监测功能。