十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

FMC接口wAIT信号详解:FPGA子卡数据采集稳定性的关键

FMC接口wAIT信号详解:FPGA子卡数据采集稳定性的关键 调试一块FPGA板卡时FMC接口上挂着一块ADC子卡数据读回总是偶发错位。我抓了半天波形才找到根因——FMC wait signal没有使能子卡忙碌时会拉低wAIT请求线FPGA这一侧却没响应照样按固定节奏访问总线数据自然就乱了。这篇文章想把这个细节讲透。无论你是刚接触FMC接口还是已经在做FPGA高速采集、通信方案只要跟子卡打交道都建议把wait signal这件事的优先级调高一点。它平时不显眼但一旦出问题就是那种最难查的偶发故障。我会把原理、硬件连接、逻辑实现、时序约束和实际调试中踩过的坑一次性说清楚。1. FMC Wait Signal是什么为什么大家都容易忽略它1.1 先搞清楚FMC接口的基本构成FMCFPGA Mezzanine Card是ANSI/VITA 57.1标准定义的一种FPGA夹层卡接口目的很直接让FPGA载板Carrier Card和子卡Mezzanine Card之间可以高速、标准化地互联。市面上大量ADC/DAC子卡、光纤通信模块、摄像头接口板都是基于FMC接口做的。FMC接口从规格上分两类LPCLow Pin Count数据引脚少适合低速或中等速率应用功耗也低。HPCHigh Pin Count提供更多差分对和单端信号适合高速数据传输比如万兆以太网、高速数据采集。除了高速数据线FMC连接器上还有低速控制信号、JTAG、I2C、参考时钟、电源管理引脚。这些看似不起眼的低速信号里就藏着我们今天的主角——wAIT信号在VITA 57.1标准里它的全称是Wait State Request。很多工程师拿到一个FMC子卡第一件事是把高速差分对连好、把时钟约束搞定、跑通数据通路这没问题。但低速控制信号往往被当成反正硬件已经连好软件里不用管的部分直接忽略。而wait signal恰恰就是这种忽略一时爽调试火葬场的信号。1.2 Wait Signal的本质总线层面的等我一下类比一下你开车经过一个收费站前车正在缴费你需要停下来等不能直接开过去。这里的正在缴费状态就相当于子卡拉低了wAIT信号FPGA作为主控方必须减速等待前方处理完成才能继续前进。在FMC接口中wait signal是一个由子卡驱动、FPGA接收的异步握手信号。子卡在以下场景会主动拉低该信号请求FPGA暂停当前总线操作子卡内部的FIFO接近满或接近空暂时无法接收或提供数据ADC模块正在转换数据还没有准备好子卡上某个低速外设如SPI/I2C芯片需要额外的访问时间子卡正在进行内校准或自检不希望FPGA此时发起读写如果FPGA没有使能wait signal的检测逻辑它就不会搭理子卡的请求总线照常推进。后果通常是寄存器回读值全FF、数据偶发错位、通信协议时序错乱甚至接口直接挂死。更麻烦的是这些问题不是每次上电都稳定复现经常需要抓很久才能锁定到wait信号上。1.3 什么场景下必须开启wait signal基于我个人的项目经历下面这几类场景基本属于必须使能的范畴场景为什么必须使用wait signal不使能的典型后果ADC/DAC子卡数据回读子卡FIFO深度有限转换数据未就绪时需要等待数据错位、丢帧、偶发采样值异常子卡内部寄存器慢速外设访问I2C/SPI器件响应慢需要拉长总线周期读回全FF或固定错误值子卡固件在线升级flash擦写期间无法响应正常读写升级失败或总线挂死多板卡同步采集多块FMC互连各子卡忙闲状态不同需要等待最慢的节点同步失败通道间数据不对齐FMC回环测试子卡自动切换收发模式时需要等待间隔测试结果不稳定判断的标准很简单**只要你的子卡在被访问时存在数据暂时没准备好的可能性就应该使能wait信号并为它设计好响应逻辑。**不要等出了问题再补偶发类故障补起来非常消耗精力。2. 深入硬件层wAIT信号、上拉电阻与双宽子卡2.1 VITA 57.1标准下wAIT信号的真实角色在VITA 57.1标准里wAIT信号被定义为一个低电平有效的异步请求信号。也就是说子卡正常工作时让该信号保持高电平当它需要FPGA暂停当前总线周期时会将wAIT拉低。这里有个容易混淆的点既然叫信号很多工程师会想当然地把它当成普通单端信号直接连到FPGA GPIO上完事。没错物理连接确实如此但在逻辑层面它的行为更像是一个中断请求IRQ或者握手信号而不是一个同步的地址/数据线。这意味着你不能把它当作同步信号直接采样必须做跨时钟域处理。在标准中wAIT信号出现在FMC连接器的低速引脚区和LA/HA/HB/LB这些并行数据总线并列。具体对应到连接器的哪一个针脚取决于你的载板设计。常见的设计会在原理图里标成FMC_WAIT或wAIT#参考Xilinx官方FMC载板的原理图也能找到明确的连接方式。另外要注意wAIT通常不是单点信号在HPC连接器上可能有多路wait信号分别对应不同的bank或通道。设计时不能只看一份简化的引脚图要对着VITA 57.1的连接器定义表逐一确认。2.2 开漏驱动与上拉wAIT线最简单的门道按照标准wAIT信号推荐使用开漏Open-Drain驱动方式。这和I2C的SDA/SCL原理类似多个设备可以通过线与Wired-AND的方式共享同一条wAIT线任何一个设备拉低时整条线都是低电平。正因为是开漏驱动板级必须有上拉电阻否则信号会悬空。这个电阻阻值一般取4.7kΩ到10kΩ具体取决于信号线上的寄生电容和驱动能力。阻值太大上升沿会变缓阻值太小静态功耗会偏高。实际调试中如果发现wAIT信号上升沿很软、毛刺多多半就是这个上拉电阻选大了。还要注意电平标准匹配。FMC接口的低速信号通常走LVCMOS常见电压有1.8V、2.5V、3.3V具体看载板对应bank的VCCO供电。如果子卡输出的是3.3V电平而FPGA bank设置了1.8V轻则信号采样错误重则烧毁IO。所以拿到子卡第一件事不是写代码而是对着两边的原理图确认电平域是否一致。这件事我在调试中真的遇到过板卡设计人员两端电平没对齐所有信号看起来都有波形但FPGA读出来的值就是不对。2.3 双宽子卡Double Width对wait信号的影响热词里提到了fmc双宽子卡尺寸这里顺带讲一下。FMC子卡除了最常见的单宽Single Width约69mm×76.5mm还有双宽Double Width约69mm×184.15mm规格。双宽子卡的物理尺寸更长板上可以容纳更多模拟前端、更大的电源模块或更复杂的信号调理电路所以高速数据采集类子卡经常采用双宽设计。双宽子卡通常会占用两个FMC连接器位置这意味着载板上需要规划两个连接器的信号布局。wAIT信号在这种情况下也会出现两组分属两个连接器对应不同逻辑区域。FPGA内部需要分别处理不能简单地把两组wAIT短接在一起否则其中一个连接器上挂的设备忙会无差别阻塞另一个连接器的访问。设计双宽子卡时建议在载板上为每个连接器的wAIT信号都配置独立的上拉电阻和可测试的调试引脚。这个看起来是硬件细节实际上对软件调试帮助巨大逻辑分析仪或示波器能直接测到wAIT的真实电平变化而不是只能通过FPGA内部抓信号间接推断。3. 实操三种使能wait signal的路线对比3.1 路线一通过子卡寄存器手动使能很多商业FMC子卡在设计时会提供一个控制寄存器其中某个bit专门负责wait signal的使能。例如某款ADC子卡通过SPI接口配置0x08寄存器bit[1]写1表示开启wAIT输出写0表示旁路wait功能。这种方式的优势是灵活性高你可以在系统初始化阶段先关闭wait快速访问一些基本信息在进入正式采集模式之前再打开wait避免干扰。调试时也可以用这种方式快速做A/B对照——同一段采集代码分别跑wait开关两种状态数据差异一目了然。具体操作方法很直接查阅子卡硬件手册找到wait signal enable寄存器的地址和位定义初始化序列中增加一次寄存器写操作使能wait输出使用逻辑分析仪抓取wAIT引脚波形确认使能后信号线在空闲状态为高不过这类寄存器通常只能控制子卡是否输出wait请求FPGA侧如果完全不管这个信号使能了也白使能。于是就需要下面两条路线配合。3.2 路线二自定义逻辑状态机中的wait响应这是最通用、也更推荐的做法在FPGA内部把wAIT信号纳入你的总线状态机让它真正参与读写节拍的调度。核心逻辑其实就是一个带wait轮询的状态机发起读请求后判断wAIT是否有效如果有效则保持当前状态哪也不去直到wAIT无效才继续推进。下面是我在一个采集项目里用过的简化版Verilog结构module fmc_wait_example ( input wire clk, // 系统时钟 input wire rst_n, // 复位 input wire fmc_rd_req, // 外部发起读请求 input wire fmc_wait_n, // 来自子卡的wAIT信号低有效 output reg [31:0] rd_data, // 读回数据 output reg rd_valid // 数据有效标志 ); // 两级同步消除亚稳态 reg [1:0] wait_sync; always (posedge clk or negedge rst_n) begin if (!rst_n) wait_sync 2b11; // 复位默认为高电平即不等待 else wait_sync {wait_sync[0], fmc_wait_n}; end wire wait_n_synced wait_sync[1]; localparam IDLE 2d0; localparam WAIT_DATA 2d1; localparam DONE 2d2; reg [1:0] state; always (posedge clk or negedge rst_n) begin if (!rst_n) begin state IDLE; rd_data 32h0; rd_valid 1b0; end else begin rd_valid 1b0; case (state) IDLE: begin if (fmc_rd_req) state WAIT_DATA; end WAIT_DATA: begin // 子卡忙等待子卡不忙采样数据 if (~wait_n_synced) state WAIT_DATA; else begin rd_data 32hA5A5_1234; // 这里换成实际子卡数据总线 rd_valid 1b1; state DONE; end end DONE: begin state IDLE; end default: state IDLE; endcase end end endmodule这里有两个细节值得展开。第一wAIT必须做两级同步。它来自子卡和FPGA系统时钟没有固定相位关系如果直接采很容易出现亚稳态导致状态机误判。两级同步并不复杂但真有不少工程因为偷懒省了这一步最后用ILA抓到状态机在奇怪的时序点跳变。第二状态的推进条件是wAIT无效且数据已稳定。实际项目中wAIT撤销之后数据线可能还需要一点点时间才能稳定尤其是高频数据总线。保守的做法是用状态机在wAIT无效后增加一个附加时钟周期的等待或者根据时序约束来保证建立时间。3.3 路线三使用现成IP和参考设计时的注意事项如果你的项目是基于Xilinx Vivado或Intel Quartus的Block Design流程常见的做法是在IP核外部添加wait逻辑或者使用厂商参考设计中已经集成了wait功能的IP。这里要注意参考设计里的wait处理往往和具体子卡强绑定直接拿来用不能保证适配你的硬件。我遇到过的情况是参考设计里的IP假设wAIT信号在高电平有效但我们的子卡是低电平有效结果使能wait后状态机直接卡死整个接口像死机一样。后来查IP的配置页面才发现有一个Active Level的选项被参考设计设成了高电平有效改成低电平后一切正常。所以不管用哪家IP都必须注意几点核实wAIT信号的极性和你的子卡是否一致确认IP内部已经包含了跨时钟域同步逻辑检查IP暴露出来的wait信号是否默认连接到了正确的物理引脚如果IP没有wait接口那就退回到路线二自己用状态机处理3.4 wait相关时序约束怎么给时序约束是wait信号最容易踩坑的地方。wAIT是异步信号原则上不参与同步时序分析所以不能被当作普通输入端口硬加input delay约束。常见的做法是使用set_false_path或set_max_delay约束告诉综合工具不需要对这条路径做严格的setup/hold分析因为逻辑里已经用两级同步器处理了。在XDC里可以这样写# 假设系统时钟为clk_100m set_false_path -from [get_ports fmc_wait_n] -to [get_pins wait_sync_reg[0]/D] set_false_path -from [get_ports fmc_wait_n] -to [get_pins wait_sync_reg[1]/D]上面这种约束把异步端口到同步器寄存器的路径设为false path是典型做法。如果你的工具支持也可以用set_max_delay来约束组合逻辑的延迟防止wAIT信号到达同步器前绕了太多逻辑导致毛刺set_max_delay -from [get_ports fmc_wait_n] -to [get_pins wait_sync_reg[0]/D] 10需要提醒的是不要一上来就复制约束要先确认自己的设计中是否真的有两级同步器。如果直接把false_path加到了没有同步器的路径上工具就不会去检查这条路径的时序门级仿真和实测出现亚稳态的概率会明显增大。4. 调试实录我踩过的wait signal的坑4.1 坑一wAIT信号悬空导致乱触发有一次在实验室调一块FMC接口的视频采集板现象是每间隔一段时间采集到的画面会出现整行花屏。用ILA抓内部信号发现状态机偶发地长时间停留在等待状态好像子卡一直在发wait请求。检查子卡手册确认wait输出是开漏。赶紧拿示波器去测FMC连接器上的wAIT引脚发现空闲电平只有0.4V完全不是高电平。再查载板原理图wAIT引脚上没有接上拉电阻子卡内部也没有设计内部上拉。开漏输出没有上拉信号线就悬空电平漂到了阈值附近FPGA采样的结果就一会儿高一会儿低状态机自然颠三倒四。解决办法很朴素在载板的wAIT引脚上加一个10kΩ上拉电阻PCB下一版改掉当前版本用飞线也先顶上。从那以后我养成了一个习惯所有FMC低速控制信号先在硬件上确认有没有上拉再去做逻辑。4.2 坑二使能wait后吞吐率掉一半另一个项目里FPGA通过FMC接口向DAC子卡传输波形数据。一开始没使能wait数据传输速度符合预期。后来为了稳定性打开了wait检测结果有效吞吐率直接掉了一半。抓波形发现wait信号每个周期都被拉低约一两个时钟但问题在于我在逻辑里把wait的同步、判断放在了数据发送的关键路径上导致每个数据周期都要额外插入等待。实际原因是DAC子卡内部FIFO几乎一直处于半满以下、快要空的状态它会不停发送wait请求来等待数据填充。表面看这是正常的流控行为但吞吐率掉半说明我的请求节奏和wait节拍没有配合好。优化方法是采用预判断在发起数据请求前先检查FIFO状态寄存器只有确认空间充足时才启动批量传输而不是每发一个数就去被动等wait撤销。这种方式可以有效减少不必要的等待吞吐率也恢复到预期的80%以上。4.3 坑三跨时钟域采样亚稳态这是最隐蔽的一类问题。FPGA系统时钟跑在150MHz子卡侧wAIT信号变化频率不高看起来属于慢信号进快系统很多工程师因此忽略了同步。但在某些温度、电压和布局情况下wAIT本来就贴着时钟沿变化一旦采样触发器进入亚稳态状态机可能出现无法预测的跳转。这类问题在实验室往往复现不出来频率极低但现场设备偶尔跑几天就会出现一次异常。排查手段就是加两级同步器并在同步器之前尽量不要插入任何组合逻辑。改造后跑了很长一段时间的压力测试没有再出现偶发异常。亚稳态问题最好的解决方式是预防而不是出了事故再排查。哪怕你推断这个异步信号不会出问题也建议所有进入FPGA的异步控制信号都过一遍两级同步器性价比极高。4.4 常见问题速查表问题现象可能原因快速排查方法状态机长时间卡在等待态wAIT悬空、被外部拉低、电平域不匹配示波器测FMC连接器wAIT引脚静态电平数据偶发错位没有做异步信号同步加两级同步器观察ILA中状态机跳变是否异常使能wait后性能明显下降每周期都插入等待预判断不足抓wAIT波形占空比优化请求节奏寄存器回读全FF子卡忙但FPGA没等待或电平不匹配先关wait确认基本读写是否正常不同FMC连接器相互干扰双宽子卡两组wAIT被错误短接分别测量两个连接器的wAIT信号5. 写在最后经验与建议5.1 项目规划阶段就想好wait信号归属wait signal最大的问题不是技术复杂而是它太容易被当成硬件连好就能用的信号。我的建议是把wait信号纳入系统设计的必备检查项硬件原理图阶段确认上拉电阻和电平匹配FPGA代码阶段预留同步器和状态机接口软件阶段确认子卡寄存器的使能位是否配置。任何一环缺失都可能在未来变成难查的偶发故障。5.2 一个省事的调试小技巧最后分享一个很实用的方法在FPGA内部把同步后的wAIT信号引到一个可读的状态寄存器里再通过片上逻辑分析仪或串口日志把它打印出来。这样即使在现场没有示波器也能远程判断wAIT信号的状态是否正常。我在多个项目里都用这个方法排查过子卡忙闲问题省掉了不少来回找仪器的麻烦。FMC wait signal的使能和调试本质上就是一块小小的握手协议。它不复杂但讲究细节。把每个环节理清楚你的FMC接口稳定性和开发效率都能上一个台阶。
返回列表