
1. 为什么MIPI DPHY在FPGA上值得认真做一遍MIPI DPHY这个接口做图像和视频采集的同行应该都不陌生。手机摄像头、车载摄像头、工业相机模组绝大多数用的都是MIPI CSI-2协议而CSI-2的物理层就是MIPI DPHY。它用差分信号传数据一对时钟通道加一到四对数据通道速率从几十Mbps到每通道2.5Gbps都有。问题在于大部分MCU和低端SoC原生不带MIPI DPHY控制器或者带了但灵活性不够这时候FPGA就成了一个很自然的选择。用Xilinx FPGA实现MIPI DPHY核心要解决两件事一是硬件层面差分对的阻抗匹配、走线等长、电平标准选择这些直接决定信号能不能被正确采样二是逻辑层面DPHY的HS高速模式和LP低功耗模式切换、时钟恢复、数据对齐、字节解析每一步都有坑。我见过不少人硬件焊好了逻辑也写了但图像就是出不来最后发现是HS模式下差分端接电阻没加对或者IDELAY校准没做。这篇内容适合谁看如果你手上有Xilinx 7系列或者UltraScale系列的FPGA想接一个MIPI摄像头做图像采集或者你正在评估用FPGA做MIPI DPHY接收的可行性那这篇东西应该能帮你省不少时间。我会从硬件设计讲到软件解析把每个环节的关键参数和实操细节都摊开说。前提是你对FPGA开发有基本概念知道Vivado怎么建工程Verilog能看懂至于MIPI DPHY本身不需要你事先精通。2. 整体方案设计与选型思路2.1 为什么选Xilinx FPGA做MIPI DPHY接收Xilinx FPGA在MIPI DPHY接收这件事上有几个天然优势。首先是SelectIO资源丰富7系列和UltraScale的HP Bank支持LVDS差分输入输入延迟IDELAY和比特滑动Bitslice功能可以精确调整采样点。其次是时钟资源MMCM和PLL能生成各种频率的采样时钟配合ISERDESE2做串并转换1:8或者1:4的降速都很灵活。再就是Xilinx提供了现成的MIPI DPHY IP核Vivado里可以直接例化省去了自己写HS/LP状态机的麻烦。但选Xilinx不代表随便选个型号就行。如果你用的是Spartan-6或者更老的器件SelectIO的速率可能撑不住MIPI DPHY的高速率。7系列的Artix-7、Kintex-7HP Bank的LVDS接收速率可以到1.25Gbps以上配合IDELAY做源同步采样跑MIPI DPHY的HS模式基本够用。UltraScale系列就更宽裕了。我个人的经验是如果MIPI DPHY的每通道速率在800Mbps以下Artix-7的HP Bank完全能扛如果超过1Gbps建议上Kintex-7或者UltraScale。2.2 硬件方案的核心考量硬件设计这块MIPI DPHY的差分对走线有几个硬性要求。第一差分阻抗必须控制在100欧姆这跟MIPI DPHY的电气规范是一致的。第二差分对内的两条线要严格等长误差控制在5mil以内否则共模抑制会变差眼图会闭合。第三差分对之间的长度偏差也要控制尤其是时钟通道和数据通道之间偏差太大会导致采样窗口偏移。端接电阻这块MIPI DPHY的HS模式要求在接收端加100欧姆的差分端接。有些FPGA的HP Bank内部有可配置的端接电阻可以通过Vivado的IO约束来使能。但内部端接的精度和一致性不如外部电阻如果速率比较高建议还是用外部100欧姆电阻放在尽量靠近FPGA引脚的位置。电平标准的选择也很关键。MIPI DPHY的HS模式是差分小信号共模电压大概200mV差分摆幅100mV到300mV。FPGA的LVDS输入标准通常要求共模电压在1.2V左右所以不能直接接。常见的做法是用AC耦合电容隔直然后在FPGA端重新偏置共模电压。或者用专门的MIPI DPHY转LVDS的电平转换芯片但这样会增加成本和板面积。2.3 逻辑方案的架构选择逻辑层面MIPI DPHY接收的架构可以分成两种一种是用Xilinx的MIPI DPHY IP核另一种是自己用SelectIO原语搭。IP核的好处是省事Vivado里配置一下通道数、速率、字节对齐方式就能生成一个带AXI接口的模块直接跟VDMA或者Video In to AXI4-Stream对接。坏处是灵活性差IP核的某些参数不能改而且不同版本的Vivado里IP核的行为可能有差异。自己搭的话核心是用ISERDESE2做串并转换IDELAYE2做延迟调整然后自己写HS/LP检测状态机和字节对齐逻辑。这种方式灵活但调试工作量大尤其是IDELAY的校准和字节对齐需要反复试。我个人的建议是如果你的项目时间紧直接用IP核先把链路跑通再考虑优化。如果项目对灵活性要求高或者IP核的某些行为不符合你的需求那就自己搭。下面我会以自己搭为主来展开因为这样能把每个环节的原理讲清楚IP核的使用反而相对简单。3. 硬件设计细节与实操要点3.1 差分对走线与阻抗控制MIPI DPHY的差分对走线第一步是确定叠层。如果你用的是四层板建议把差分对走在顶层或者底层参考平面是完整的地平面。不要走在电源平面旁边电源噪声会耦合到差分对上。如果是六层板可以把差分对走在内层上下都有地平面参考这样阻抗更好控制。差分阻抗100欧姆的计算跟线宽、线间距、介质厚度、介电常数都有关系。以常见的FR-4板材为例介电常数大概4.2如果介质厚度是0.2mm线宽0.15mm线间距0.2mm差分阻抗大概在100欧姆左右。但实际值要用阻抗计算工具算比如Polar SI9000或者Saturn PCB Toolkit。算完之后让PCB厂按你的叠层做阻抗控制他们会微调线宽来达到目标阻抗。等长这块差分对内的两条线要严格等长误差控制在5mil以内。如果走线需要拐弯用45度角或者圆弧不要用90度直角。差分对之间的等长时钟通道和数据通道的偏差控制在50mil以内数据通道之间的偏差控制在100mil以内。这些数值不是绝对的速率越高要求越严。注意差分对走线不要跨分割参考平面必须完整。如果必须跨分割在跨分割的地方加缝合电容但效果不如不跨。3.2 端接电阻与共模偏置MIPI DPHY的HS模式端接前面说了建议用外部100欧姆差分电阻。位置放在FPGA引脚附近走线尽量短。如果FPGA的HP Bank支持内部端接可以在Vivado里设置DIFF_TERM为TRUE但内部端接的电阻精度大概在10%左右高速率下可能不够。共模偏置这块MIPI DPHY的HS模式共模电压大概200mV而FPGA的LVDS输入共模范围通常在0.3V到1.5V之间。所以不能直接接需要AC耦合。AC耦合电容通常用0.1uF放在端接电阻和FPGA引脚之间。耦合电容之后FPGA端的共模电压需要重新偏置可以用两个电阻分压比如从1.2V电源分压得到0.6V然后通过电感或者磁珠馈到差分线上。但这样会增加元件而且偏置网络的寄生参数可能影响信号完整性。另一种做法是用专门的MIPI DPHY转LVDS芯片比如TI的SN65LVDS或者美信的MAX系列。这些芯片内部集成了端接和偏置输出直接是LVDS电平FPGA端不需要额外处理。缺点是增加成本而且芯片的延迟可能影响时序。我试过两种方案如果速率在800Mbps以下AC耦合加电阻偏置完全能用眼图张开度也够。如果速率超过1Gbps建议用专门的转换芯片信号质量更稳。3.3 电源与时钟设计MIPI DPHY的电源噪声要求比较高尤其是HS模式差分摆幅只有100mV到300mV电源噪声很容易淹没信号。建议给MIPI DPHY的接收电路单独供电用LDO而不是DC-DCLDO的PSRR更好。如果必须用DC-DC后面加一级LC滤波。时钟方面MIPI DPHY的时钟通道是差分时钟速率是数据通道速率的一半。比如数据通道800Mbps时钟通道就是400MHz。FPGA端需要用这个时钟来采样数据通常用IBUFDS把差分时钟转成单端然后送到MMCM或者PLL做倍频生成ISERDESE2需要的采样时钟。这里有个细节MIPI DPHY的时钟通道在HS模式下是连续的但在LP模式下会停止。所以FPGA端的时钟恢复逻辑要能处理时钟停止的情况。通常的做法是用一个状态机检测时钟活动当时钟停止时切换到内部时钟并复位ISERDESE2。4. 逻辑实现与核心环节解析4.1 ISERDESE2与IDELAYE2的配合ISERDESE2是Xilinx FPGA里做高速串并转换的原语支持1:4、1:6、1:8、1:10的降速比。MIPI DPHY的HS模式数据是DDR的所以ISERDESE2要配置成DDR模式降速比通常选1:8这样输出是8位并行数据速率降到原来的八分之一。IDELAYE2是输入延迟原语可以调整输入信号的延迟步进精度跟参考时钟有关。7系列里IDELAYE2的参考时钟是200MHz时步进大概是78ps。UltraScale里精度更高。IDELAYE2的作用是调整采样点让ISERDESE2在数据眼图的中心采样。IDELAYE2的校准有两种方式一种是固定延迟根据经验值设置另一种是动态校准用IDELAYCTRL和眼图扫描来找最佳采样点。固定延迟简单但不同板子、不同温度下可能不准。动态校准复杂但可靠性高。我一般先用固定延迟跑通然后用Vivado的IBERT或者自己写眼图扫描逻辑来找最佳值。提示IDELAYE2的延迟值不是越大越好要配合ISERDESE2的建立保持时间。如果延迟太大数据可能采到下一个比特。4.2 HS/LP模式检测与状态机MIPI DPHY的HS模式和LP模式切换是靠差分线上的共模电压和差分摆幅来区分的。LP模式时差分线是单端信号共模电压大概1.2V摆幅0到1.2V。HS模式时差分线是差分小信号共模电压200mV摆幅100mV到300mV。FPGA端要检测这个切换通常用比较器或者LVDS输入加阈值判断。7系列的HP Bank里可以用LVDS输入加内部比较器但阈值不好调。更常见的做法是用一个LP接收器把差分线当单端信号接收然后判断电平。当检测到LP模式时关闭HS接收路径切换到LP接收当检测到HS模式时打开HS接收路径。状态机的设计核心是检测HS模式的起始序列。MIPI DPHY的HS模式起始是一个LP到HS的转换序列LP-11、LP-01、LP-00然后进入HS模式。这个序列的时序要求很严LP-01和LP-00的持续时间有明确规定。状态机要能识别这个序列并在正确的时间点打开HS接收。4.3 字节对齐与数据解析HS模式的数据是串行的经过ISERDESE2降速后变成8位并行数据。但8位数据的字节边界可能不对齐因为ISERDESE2的起始点不确定。字节对齐就是找到正确的字节边界让数据包的起始字节对齐到8位数据的低位。MIPI DPHY的字节对齐通常靠数据包里的同步字。CSI-2协议里每个数据包以SoTStart of Transmission开始SoT是一个特定的序列。FPGA端检测到这个序列后调整ISERDESE2的Bitslip信号让字节边界对齐。Bitslip是ISERDESE2的一个控制信号每拉高一次并行数据的字节边界滑动一位。通过反复拉高Bitslip并检测同步字可以找到正确的字节边界。这个过程可以自动做也可以手动调。自动做的话写一个状态机检测到同步字就停止Bitslip手动做的话用Vivado的调试工具看数据手动调整。数据解析这块CSI-2协议的数据包有包头、数据、包尾。包头里有数据类型、虚拟通道、数据长度等信息。FPGA端要解析这些字段把有效数据提取出来送到后续的图像处理模块。如果只是做图像采集可以只解析长包图像数据短包帧同步、行同步可以忽略或者简单处理。5. 实操过程与关键步骤记录5.1 Vivado工程搭建与IP配置第一步建Vivado工程选对器件型号。如果你用的是Artix-7选xc7a200t或者类似的HP Bank多的型号。工程建好后先加MIPI DPHY IP核。Vivado的IP Catalog里搜MIPI能找到MIPI DPHY Receiver或者MIPI CSI-2 Receiver。配置的时候通道数选你实际用的速率填MIPI DPHY的每通道速率字节对齐方式选自动。IP核配置完后生成示例设计看看IP核的接口和时序。示例设计里通常有一个测试模式可以先生成测试数据验证链路是否通。如果测试模式能出数据说明硬件和IP核的基本配置没问题。如果你要自己搭那就先例化IBUFDS、ISERDESE2、IDELAYE2这些原语。IBUFDS把差分时钟转单端ISERDESE2做串并转换IDELAYE2做延迟调整。这些原语的配置参数可以参考Xilinx的SelectIO手册里面有详细的时序图和参数说明。5.2 约束文件的编写约束文件是FPGA开发里最容易出错的地方。MIPI DPHY的约束核心是时钟约束和IO约束。时钟约束要定义输入时钟的频率和抖动IO约束要定义差分对的引脚位置和电平标准。差分对的引脚位置在Vivado里用set_property PACKAGE_PIN来指定。电平标准用set_property IOSTANDARD来指定MIPI DPHY的HS模式通常用LVDS或者LVDS_25。如果用了AC耦合和外部偏置IOSTANDARD可以设成LVDS如果直接接可能要设成LVDS_25并调整共模电压。时钟约束这块输入时钟用create_clock定义频率是MIPI DPHY时钟通道的速率。然后定义生成时钟用create_generated_clock定义MMCM或者PLL输出的时钟。时序约束要覆盖ISERDESE2和IDELAYE2的路径确保建立保持时间满足。注意约束文件里的时钟频率要和实际一致否则时序分析会出错。如果时钟频率填错了Vivado可能报时序违例也可能不报但实际跑起来会出问题。5.3 上板调试与眼图扫描上板调试的第一步是确认时钟有没有。用示波器或者逻辑分析仪看FPGA引脚的时钟信号确认频率和摆幅正常。如果时钟没有检查IBUFDS的配置和引脚约束。时钟有了之后看数据。如果用的是IP核IP核通常有AXI接口可以用Vivado的ILA抓AXI总线上的数据。如果数据全是0或者全是1说明采样点不对需要调IDELAY。如果数据有变化但不稳定说明字节对齐没做好需要调Bitslip。眼图扫描是自己搭方案里最有用的调试手段。写一个状态机逐步增加IDELAY的值每增加一次采集一批数据统计误码率。误码率最低的IDELAY值就是最佳采样点。这个过程可以自动做也可以手动做。自动做的话写一个扫描逻辑把结果存到BRAM里然后用ILA读出来。我实测下来眼图扫描能把误码率从10的负3次方降到10的负9次方以下。但扫描时间比较长如果IDELAY有32个步进每个步进采1000个数据大概需要几秒钟。对于调试来说这个时间可以接受。5.4 数据解析与图像重建数据对齐之后就是解析CSI-2协议的数据包。CSI-2的数据包格式包头是4个字节第一个字节是数据类型第二个字节是虚拟通道和数据类型的高位第三和第四是数据长度。数据长度是像素数据的字节数。包尾是2个字节的CRC。FPGA端解析的时候先检测SoT然后读包头根据数据类型判断是长包还是短包。长包的话读数据长度然后接收对应字节数的数据最后校验CRC。短包的话直接处理同步信息。图像重建这块如果只是采集原始数据可以把数据直接写到DDR里然后用VDMA送到HDMI或者DisplayPort显示。如果需要做图像处理比如去马赛克、白平衡、伽马校正可以在数据流里加相应的模块。Xilinx的HLS工具可以用来写图像处理算法生成AXI4-Stream接口的IP核直接跟MIPI DPHY接收模块对接。6. 常见问题与排查技巧实录6.1 时钟有但数据不出这是最常见的问题。时钟有说明IBUFDS和时钟路径没问题。数据不出可能的原因有几个一是IDELAY值不对采样点偏了二是字节对齐没做好数据边界错了三是HS/LP状态机没切换HS接收路径没打开。排查的时候先用ILA看ISERDESE2的输出。如果输出全是0或者全是1调IDELAY。如果输出有变化但不稳定调Bitslip。如果输出完全没变化检查HS/LP状态机看HS接收路径有没有打开。6.2 数据偶尔出错数据偶尔出错通常是时序余量不够。可能的原因一是IDELAY值不是最佳采样点靠近眼图边缘二是时钟抖动太大MMCM的配置需要优化三是电源噪声LDO的PSRR不够。排查的时候先做眼图扫描找最佳IDELAY值。然后看MMCM的配置把带宽设成OPTIMIZED抖动设成LOW。如果还不行检查电源用示波器看电源纹波如果纹波超过50mV加LC滤波。6.3 不同板子表现不一致不同板子表现不一致通常是硬件一致性问题。可能的原因一是差分对走线长度偏差不同板子的偏差不一样二是端接电阻精度不同批次的电阻精度不一样三是FPGA的工艺偏差不同批次的FPGA延迟不一样。排查的时候先量差分对的长度确保等长。然后量端接电阻确保100欧姆。如果还不行每块板子单独做眼图扫描把最佳IDELAY值存到Flash里上电时加载。6.4 常见问题速查表问题现象可能原因排查方法解决措施时钟有但数据全0IDELAY值不对调IDELAY做眼图扫描找最佳IDELAY值数据有变化但不稳定字节对齐没做好调Bitslip检测同步字自动字节对齐数据偶尔出错时序余量不够眼图扫描看MMCM配置优化IDELAY和MMCM不同板子表现不一致硬件一致性问题量走线长度和端接电阻每块板单独校准HS模式进不去HS/LP状态机问题看状态机状态检查HS检测序列提示调试的时候先用低速跑通再逐步提高速率。低速下时序余量大容易定位问题。高速下问题多但定位难度大。7. 几个容易被忽略的实操心得第一个心得IDELAY的参考时钟要稳定。IDELAYE2的延迟步进跟参考时钟的频率有关如果参考时钟抖动大延迟步进就不准。建议用专门的200MHz时钟给IDELAYCTRL不要跟其他逻辑共用时钟。第二个心得ISERDESE2的Bitslip要慎用。Bitslip每拉高一次字节边界滑动一位但滑动方向是固定的。如果滑过了要滑一圈才能回来。所以自动字节对齐的时候要设一个最大滑动次数超过就报错。第三个心得MIPI DPHY的LP模式信号要处理好。LP模式的信号是单端1.2VFPGA的HP Bank输入标准通常是LVCMOS12或者LVCMOS15。如果电平不匹配加一个电平转换芯片。LP模式的信号速率不高但时序要求严尤其是LP到HS的转换序列。第四个心得电源去耦要到位。MIPI DPHY的接收电路每个电源引脚都要加0.1uF和0.01uF的电容位置尽量靠近引脚。如果电源噪声大加一个铁氧体磁珠或者电感但要注意电感的自谐振频率。第五个心得调试的时候用ILA抓数据但ILA的采样深度有限。如果数据量大用Vivado的System ILA或者把数据存到BRAM里然后用UART或者以太网读出来。我试过用UART读速率慢但稳定适合长时间监测。8. 后续可以扩展的方向如果你已经把MIPI DPHY接收跑通了后续可以往几个方向扩展。一是多通道同步MIPI DPHY支持最多4个数据通道多通道之间的同步是个挑战需要做通道间偏斜校准。二是高速率优化如果速率超过1.5Gbps可能需要用UltraScale的GTH收发器而不是SelectIO。三是协议扩展CSI-2之上还有CCS摄像头串行接口支持更高的分辨率和帧率可以研究一下。我自己在实际操作中的体会是MIPI DPHY的调试硬件和逻辑各占一半。硬件设计好了逻辑调试就顺硬件有问题逻辑怎么调都出不来。所以前期在硬件上多花时间后期能省很多事。另外眼图扫描这个工具一定要做不要靠猜。猜出来的IDELAY值换个板子或者换个温度就不行了。