ARTICLE DETAIL

资讯详情

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

FPGA实战:DDR3布线避坑指南——从MIG训练失败到稳定运行

FPGA实战:DDR3布线避坑指南——从MIG训练失败到稳定运行 拿到新焊好的板子连上JTAG下载MIG生成的bitstream然后盯着ILA里的init_calib_complete信号等它拉高。等了十秒没动静又等了半分钟还是低电平。这是很多FPGA新手第一次碰DDR3时的经典场面明明原理图照着手册画的电源电压量着也全对可DDR3就是不给你好脸色。我自己的第一块Artix-7板子就这么翻过车。后来陆陆续续画过几版DDR3把能踩的坑都踩了一遍才慢慢摸清楚这东西到底在跟你较什么劲。DDR3布线这事说难也难说简单也简单——它需要你在动手画PCB之前先搞明白高速接口的工作逻辑而不是像画普通GPIO一样随便拉线。这篇文章我会以Xilinx 7系列为例把我实测过的案例、绕过的弯路、验证过的方法全都写出来给准备上手DDR3的新手一份能直接照着做的避坑清单。1. 让新手崩溃的经典画面calib_done就是拉不高1.1 第一块DDR3板子的失败现场我那次用的是一颗XC7A35T-2FTG256配一颗DDR3颗粒型号是MT41K256M1616bit位宽单颗容量4Gbit。原理图参考了开发板的设计MIG IP也按照官方文档配置好了按理说这种单颗粒的设计在硬件上应该很简单。但现实是bitstream加载完之后MIG内部的校准流程始终无法完成calib_done信号一直趴在地上。我当时的排查顺序是这样的先量电压VCCIO 1.5V、VTT 0.75V、VREF 0.75V全对。再量时钟DDR3的CK差分对频率正确示波器上能看到波形。用万用表测地址线、控制线的连接逐根跟原理图比对没发现断路。最后排查到DQS差分对才发现两颗芯片之间的DQS_P和DQS_N在PCB布线的最后阶段被我通过交换差分对的功能对调了。对就是我画PCB的时候为了让DQS走线更顺眼在布线编辑器里交换了差分对的极性。原理图上网络名看着没问题但物理上已经接反了。DQS是DDR3数据采样的时钟参考正负极性接反MIG做写训练的时候根本锁不住数据校准当然失败。1.2 把DDR3当成普通RAM来布是最大的认知错位我在各种FPGA群里见过太多类似的问题。新手往往把DDR3理解成存储空间大一点的RAM觉得只要地址线、数据线连通了就行反正FPGA逻辑里读写的时候会自动处理时序。这个想法害人不浅。DDR3不是普通RAM。它工作在几百兆赫兹的时钟频率下数据总线是源同步接口靠DQS信号来对齐DQ数据地址和控制信号又是系统同步接口靠CK时钟来采样。这意味着PCB上的每一根走线长短、每一处阻抗变化、每一段参考平面是否连续都会直接影响信号的时序关系和信号完整性。说个更直白的比喻DDR3的数据传输就像一场接力赛DQS是接力棒DQ是运动员。接力棒必须在合适的位置递到运动员手里早一点或晚一点都不行。MIG上电后的校准过程本质上就是在反复测量接力棒和运动员之间的相对位置然后通过FPGA内部的延时链去补偿。如果PCB布线把DQS和DQ之间的距离拉得乱七八糟MIG再怎么调也补不回来。所以新手必须建立起一个概念DDR3布线不是在连线而是在控制时间。每一组信号走多长、换几次层、离参考平面多远都是在控制信号的传播延迟和回流路径。这才是DDR3布线的本质。2. 布线之前必须想明白的四件事2.1 拓扑单颗芯片也要讲究多颗更要讲DDR3的拓扑结构是新手第一个容易忽略却又非常重要的点。很多人以为拓扑是多颗DDR3才需要考虑的事情单颗芯片随便拉就行。这个想法在低速下没毛病但到了DDR3的速率下即使是单颗芯片拓扑结构也会影响信号质量。数据信号DQ、DQS、DM因为是源同步每个byte lane内部点对点连接一颗DDR3对应一组DQS这个关系是固定的。真正容易出问题的是地址线、控制线、命令线这些共享信号。单颗DDR3时这些信号从FPGA出来直接到DDR3走线短的话问题不大。但如果板上挂了2颗或4颗DDR3共享信号就必须考虑走线方式。现在主流做法是fly-by拓扑也就是地址/控制信号像串糖葫芦一样依次经过每一颗DDR3最后在末端接端接电阻上拉到VTT。这种方式能减小stub反射特别适合DDR3-1066以上的速率。我看到有些新手用老的T型拓扑把地址线从FPGA出来分两路对称走到两颗DDR3然后等长做得异常痛苦。T型拓扑不是不行但要求分支完全对称在多层板上实现难度高而且DDR3的地址信号本身频率不低分支处的阻抗不连续很容易造成振铃。一颗芯片的设计就简单多了直接点对点连接末端要不要端接取决于走线长度。Xilinx的UG586建议走线长度非常短通常在0.5英寸以内时可以不接端接电阻但保守一点的话还是预留端接电阻的位置调试的时候根据波形决定贴不贴。2.2 阻抗和参考平面信号回不了家一切都白搭阻抗这个事很多新手知道要做50Ω单端、100Ω差分但不知道为什么要做。我换个方式解释当信号沿着走线传播时如果走线的瞬时阻抗发生变化一部分信号能量会被反射回来导致波形出现台阶、过冲、振铃。阻抗越不连续反射越严重接收端看到的波形就越差。DDR3的阻抗目标值JEDEC标准里没做强制统一Xilinx在UG586里给出了明确建议单端走线控制在50Ω±10%DQS差分对控制在100Ω±10%。这个目标要靠叠层设计和线宽控制来实现。我说一个很多人容易忽略的点阻抗参考的是哪个平面DDR3走线最好是参考完整的GND平面因为地平面是信号回流最自然的路径。如果你的走线跨过了一个被分割的电源平面比如从1.5V电源区域跨到了3.3V电源区域信号的回流电流就得绕道等效于走线阻抗突变同时形成一个很大的回流环路。这个环路就是一个天线既往外辐射噪声也接收外部干扰。我见过一块板子DDR3数据线几乎全走在表层表层下面是完整的GND平面信号质量很好但有一根地址线为了绕过过孔换到了另一层而那一层的下方正好有一条电源分割带结果这根线的波形明显比别的线差一大截。这就是参考平面不连续的直接后果。具体到层叠设计4层板能不能做DDR3能但最好只用于DDR3-800或者走线非常短的场合。DDR3-1066以上我建议至少6层板保证有两层完整的地平面给信号回流。Xilinx的7系列MIG在配置时问你目标速率你会发现速率越高可用的时序余量越小对PCB的依赖就越大。别为了省两层板钱把整个项目的稳定性搭进去。2.3 等长到底该做到多少别再看网上玄学网上讲DDR3等长的帖子很多但很多是互相抄来的各种说法都有有的说数据组要等长到±5mil有的说±50mil就行还有的说地址线相对时钟要短。新手看了更晕。我直接按Xilinx的官方建议结合自己的实测给你一套能落地的参考值。先算一笔账。FR4板材里内层走线的信号传播延迟大约是170ps/inch也就是每英寸大约170皮秒。10mil的等长误差换算成时间约1.7ps。DDR3-1066的UI一个数据位的时间宽度是937psDDR3-1600的UI是625ps。所以数据组的等长控制在±20~30mil换算成时间只有3~5ps对时序余量的影响很小控制到±50mil以内也问题不大。真正要紧的是DQS和DQ之间的相对关系因为DQS是用来采样DQ的两者一旦偏太多训练就失败。我自己的做法是数据组内部包括DQ、DQS差分对、DM全部等长到±25mil以内DQS差分对内部正负两根线之间等长到±5mil以内并且尽量少换层。这个要求不高绕线的时候注意一下就能做到。地址线、控制线、命令线这些东西情况不一样。它们由CK时钟采样属于系统同步。MIG的校准只管DQS和DQ的相位不会去管地址线的时序所以地址线的等长完全靠布局布线来保证。我的建议是地址/控制/命令组相对CK信号的等长控制在±150mil以内。你说能不能更松能但松了之后遇到温度变化或者批次差异就可能出现偶发错误这个我后面案例里细说。还有一种非常坑的做法把所有的线为了好看全部绕得一样长。数据线和地址线的时序要求根本不是一个量级你把DQ按地址线的标准绕那么长反而增加了走线寄生电容和串扰风险。正确的做法是分组处理组内等长组间不要乱绕。2.4 VTT、VREF和电源去耦供电不稳布线再好也白搭很多新手画DDR3时把全部精力放在信号线上却忽略了供电。DDR3的电源系统比想象中复杂因为它有三路电压VDD/VDDQ 1.5V、VTT 0.75V、VREF 0.75V。VTT和VREF都是VDDQ的一半但用途完全不同。VTT是端接电压给地址线、控制线末端的上拉端接供电。DDR3的地址线在接收端会有电流从VTT流出来所以VTT的瞬态电流变化很大。这就要求VTT电源必须有足够多的去耦电容靠近DDR3芯片放置而且0.1uF和1uF要搭配着来。VREF是输入参考电压DDR3芯片内部用它来判断信号是高还是低。VREF对噪声非常敏感如果VREF纹波太大直接导致数据误判。所以VREF的滤波电容要靠近DDR3的VREF引脚放置走线尽量短粗。我见过一块板子DDR3跑training能过但就是读写不稳定后来用示波器量到VREF上有大约200mV的纹波罪魁祸首是VREF走线和一条高速DQS走线在相邻层平行走了将近2英寸。把VREF改用宽走线并远离DQS之后问题瞬间消失。这种问题靠改布线解决而不是靠改逻辑。去耦电容的摆放同样重要。每个DDR3电源引脚附近都应该有对应的去耦电容原则是电容尽量靠近电源引脚过孔直接从电容焊盘打到电源平面和地平面不要在中间串联长的走线。电容离得越远寄生电感越大高频去耦效果越差。新手容易犯的错误是电容放了但为了布线好看把电容放得远远的中间还穿了好几个过孔结果等于没放。上电时序也要注意。DDR3手册里通常要求VDD和VDDQ先上电VTT和VREF跟随其后而且VTT电压不能超过VDDQ。如果你用了简单的电源电路加RC延迟要确认时序满足数据手册要求否则可能损伤DDR3芯片甚至导致上电后无法初始化。3. 基于Xilinx 7系列MIG的设计要点3.1 MIG生成的pinout比你想的更死板Xilinx 7系列里面DDR3控制器是通过MIG 7 Series IP实现的。MIG这玩意很强大但也很霸道它在生成IP的时候会根据你选择的FPGA型号、封装、DDR3颗粒、位宽锁定一组推荐引脚并且输出一份pinout文件.ucf或.xdc格式。这份文件就是你的原理图设计依据没有商量的余地。很多新手的操作习惯是先画原理图随便分配几个BANK给DDR3然后到MIG里选引脚的时候发现对不上再回头改原理图。这么一来一回浪费时间不说还容易改出bug。正确做法是第一步就打开Vivado把MIG IP配一遍拿到pinout文件再按这份pinout去画原理图和PCB。MIG的引脚要求为什么这么固定因为7系列FPGA的I/O结构里DQS信号必须落在特定的引脚上对应的DQ byte lane也是固定的。比如一个byte lane是DQS_P/DQS_N加8根DQ这组引脚在封装里的物理位置是确定的你不能把一个byte lane的DQS分配到另一个byte lane所在的区域去。MIG让你选的引脚必须满足这种字节通道关系还要求时钟、地址、控制信号分布在同一个BANK的合适位置。这里有一个实际经验在MIG配置界面的Pin Compatible那一步建议选择Fixed Pin Out。虽然MIG也允许你手动调整引脚但新手尽量少动。我那次调试DQS极性接反的板子就是因为自己手动调整过BANK后来查问题时要反复对比MIG建议值和实际原理图非常痛苦。3.2 Bank电压、时钟和复位MIG起不来先查这三样7系列FPGA的BANK分两类HP BankHigh Performance高本征速度和HR BankHigh Range宽电压范围。Kintex-7、Virtex-7有HP Bank而Artix-7全是HR Bank。HP Bank适合DDR3这类高速接口HR Bank的电压范围宽但性能上限低一些。DDR3的标准电压是1.5V所以不管HP还是HRVCCO都要接1.5V。但有个细节7系列的MIG在配置界面里会让你选FPGA的温度等级、速度等级然后算出支持的最高DDR3速率。Artix-7比如XC7A35T-2MIG通常只支持到DDR3-1066左右不是网上有些人说的能跑1600甚至1866。如果你选了一个超出芯片能力的目标频率MIG配置界面会直接报错或者给警告。新手容易犯的错是拿着Kintex-7的设计习惯硬套Artix-7把频率设得很高然后板子调不通。MIG的输入时钟也就是系统时钟是由外部晶振提供的一般推荐100MHz或200MHz差分时钟也可以是单端。需要在MIG配置里保持一致。这个时钟必须是自由运行的不能靠FPGA内部逻辑生成再反馈进来因为MIG上电后要靠它做PLL锁定和训练。我见过一个项目因为系统时钟是从别的BANK临时引出来的信号结果MIG一直锁不上查了半天才发现问题。复位信号也很关键。MIG有系统复位sys_rst有的版本里叫reset和用户侧复位aresetn。sys_rst低有效上电后必须保持一段时间低电平等电源稳定了再释放。如果你的复位信号被外部电路拉高得太早MIG可能在电源还没稳定的时候就开始初始化训练当然失败。调试时如果init_calib_complete拉不高第一步先看这几个信号系统时钟有没有正常翻转、sys_rst有没有在电源稳定后才释放、MIG的debug端口输出的是什么状态。MIG自带debug接口会把训练到哪一步卡住暴露出来。这是最直接的排查入口比拿示波器瞎量信号有用得多。4. 实测案例复盘从训练失败到20小时压力测试通过4.1 第一版差分对极性接反training直接失败前面说的第一版板子现象就是校准不完成。我在当时的调试记录里把整条链路重新走了一遍第一步检查MIG状态。我在ILA里挂了err、calib_done、以及MIG debug接口输出的dbg_*信号。发现步骤卡在Write Training阶段dbg_sts显示写训练没通过。第二步检查DDR3芯片侧的条件。用示波器量VTT和VREF的纹波都很干净量CK差分对频率正确幅度正常。第三步检查DQS。这时候才发现问题。两个DQS差分对虽然示波器上都有波形但仔细看相位DQS0这一组和另一组的波形形态不一致。再一回查原理图发现是我在布线软件里交换了差分对极性。这类问题在PCB布线工具里其实很常见。布线软件一般允许你交换差分对的正负极而不改变网络名本意是方便布线但对DDR3这种严格区分极性的接口来说这种便利很容易埋雷。修好这个问题的方式只有改版因为DQS的极性在物理上已经反了靠MIG配置是没法翻转的。第一块板子给我的教训是凡是MIG配置里明确给出的差分引脚尤其是DQS、CK、地址组差分信号画完板子一定要逐根对一遍网络表。不要盲目相信布线工具帮你做的差分交换操作。4.2 第二版偶发错误最坑人最后栽在地址线等长上第二版改回来之后training顺利通过init_calib_complete正常拉高我以为这次稳了。结果在做压力测试的时候发现一个更让人抓狂的问题偶发读写错误。具体现象是这样的跑MIG自带的example design读写某些固定pattern0x55、0xAA、自增地址全部通过跑个几百次也稳定。但一旦跑伪随机数据加随机地址的长时间测试大约每隔几分钟到几十分钟就会出现一次错误。这种偶发性问题最坑人因为你不确定是逻辑问题、时序问题还是硬件问题。我用ILA把出错的数据抓了出来发现错误很有规律出错的位置全部集中在某个特定地址区间而且出错的位是固定的某一位。这一下就把范围缩小了。特定地址区间说明问题不在数据线上固定某一位说明问题指向一根特定的地址线。回到布线图里查这根地址线发现问题了。这根地址线在等长处理的时候为了满足和时钟的等长约束绕了一个特别长的蛇形线。绕线本身没什么但它的换层位置正好跨过一条电源分割带而且绕线的蛇形部分又和另一组控制信号平行走了一段很长的距离。这样一来这根地址线上的信号质量天然比其他线差一旦温度和电压出现波动时序余量就不够了导致偶发建立时间违规。这个问题最后是通过两处修改解决的一是把地址线的换层位置调整到参考平面完整的地方避开电源分割带二是重新做等长时让蛇形线的间距拉大到3倍线宽以上减少平行耦合。改版后同样跑了20个小时压力测试零错误。这个案例说明一个道理偶发错误比一直跑不通更难查。一直跑不通你还能用示波器、逻辑分析仪死磕偶发错误你得读懂错误特征通过数据分析把范围缩小到具体某一根信号线上再回到布线图里找原因。新手遇到这个问题第一反应往往是怀疑DDR3芯片坏了或者焊接有问题但换芯片、补焊都解决不了——因为问题从一开始就在PCB上。4.3 完整验证流程怎样才算真的调通了DDR3调通的标准到底是什么init_calib_complete拉高只是万里长征第一步只能说MIG的校准通过了不表示你的DDR3在恶劣条件下还能稳定工作。我个人的验证流程是这样的跑MIG自带example design。这个设计会给用户侧接口发读写请求并且有错误计数。先确认基本读写功能没问题。做地址铺满测试。把所有地址空间都写上特定值再读出来比较可以用自增地址取反pattern组合覆盖到地址线的每一位翻转。做伪随机数据长跑。用LFSR产生伪随机数据随机地址写入延迟随机时间后读回。这一步主要验证数据线和DQS的稳定性。温度/电压边际测试。有条件的话用热风枪给DDR3局部加热或者用可调电源把VCCIO电压从1.4V调到1.6V观察错误率。如果余量充足这些操作不应该导致错误。ILA实时监控。如果出现错误ILA要能抓到出错的地址和数据配合出错的次数统计推断问题范围。我的标准是连续跑20小时以上零错误或者至少跑100万次随机读写零错误才算这块板子的DDR3调通了。不要觉得这个标准太高DDR3在正常工作时是持续高频读写的如果余量不足迟早会在现场暴露问题。到那时候再改板成本就不是几块样板的问题了。5. 新手自检清单打样前把这10项过一遍写到最后我把自己画DDR3板子时用的自检清单整理出来。每次打样前逐项核对一遍能帮你挡掉绝大部分低级错误。序号检查项说明1MIG引脚分配是否直接来自生成的pinout文件不要手动随意分配DQ/DQS位置2DQS差分对极性是否与网络表一致重点检查布线软件有没有自动交换差分对3DQS差分对内部等长是否在±5mil以内差分对内时序要求最高4数据组DQ/DQS/DM等长是否在±25mil以内注意按byte lane分组各自等长5地址/控制/命令相对CK等长是否在±150mil以内这类信号不做训练全靠布线保证6阻抗控制是否明确写在叠层约束里单端50Ω、差分100Ω误差±10%7所有DDR3走线是否有连续参考平面避免跨分割、跨电源区域8VTT端接电阻是否放在走线末端端接位置不对等于没端接9去耦电容是否靠近DDR3电源引脚0.1uF和1uF搭配过孔直连电源/地平面10系统时钟、复位、上电时序是否满足要求晶振频率和MIG配置一致复位延迟释放再补充几条工具使用上的建议。用Cadence Allegro或者嘉立创EDA专业版这类支持约束管理的工具不要靠肉眼拉等长。Allegro里可以设置Net Group比如把一组DQ加DQS加DM丢进一个Match Group然后设好等长目标值用蛇形绕线功能自动绕。嘉立创EDA专业版里也有类似功能虽然没有Allegro那么专业但最基本的等长约束、差分约束都能设置。我见过一些新手完全靠手工一根根比长度最后差了一两百mil还不自知这是没必要的。蛇形绕线的时候间距至少保持3倍线宽。蛇形线弯折处的平行段如果靠得太近相邻的弯折之间会产生耦合本来是为了等长而绕的线结果反而引入额外的串扰得不偿失。我自己的习惯是蛇形线的间距做到4倍线宽以上。打好样回来不要急着上电。先用万用表量一遍电源对地阻抗确认没有短路然后下电再量DDR3芯片供电引脚处的电压是否正确最后才烧bitstream跑train。这个流程虽然简单但能避免很多烧完板子发现冒烟的惨剧。至于后续扩展如果你的板子准备从DDR3升级到DDR4或者想跑更高的速率核心思路是一样的把时序预算算清楚把信号完整性做好把电源完整性做好。DDR3这块入门关过了后面很多东西都是触类旁通。我自己第二次画DDR3的时候明显感觉压力小了很多。不是因为我技术突飞猛进而是第一次踩坑踩出来的认知已经刻在脑子里了信号是要回流的时序是要预算的电源是要看的。你把这几个意识建立起来了DDR3布线这事其实也就那么回事。
返回列表