尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
FPGA实现AD9653四通道125M ADC采集:LVDS接收与SPI配置
做过多通道高速采集的朋友应该都有体会FPGA端真正麻烦的往往不是算法本身而是ADC芯片的配置、高速串行数据的接收、跨时钟域的处理这些地基活。这篇聊聊我用Vivado做的一个AD9653四通道Verilog工程采样率125M涉及SPI配置和LVDS接收整个代码工程是从零写的不是拿厂商例程改的跑通后稳定采集了几个月。内容会包含架构拆解、每一块的原理和关键代码思路以及我在调板过程中踩过的坑希望对正在做类似ADC采集的人有帮助。1. 项目背景与整体架构为什么要用多片AD9653拼四通道先说需求来源。某次接到的任务是要做一套四通道同步采集系统输入信号带宽几十兆动态范围要求比较高所以ADC位数不能低于14位。板卡面积和功耗都有严格限制不能用太夸张的高端器件。综合对比了ADI家的几款ADC最终定了AD9653采样率125M14位分辨率。这里有个细节容易踩坑单颗AD9653是双通道的要凑四通道就得用两片所以FPGA工程里所有逻辑都是围绕“两片ADC、四个通道”设计的。选AD9653还有一个原因它输出的是LVDS接口而且自带数据时钟DCO属于源同步传输。源同步虽然对布线长度和时钟质量有要求但比JESD204B那种高速串行协议简单得多不需要复杂的链路训练也不依赖专用参考时钟在中低规模采集板卡上非常实用。整个信号链可以从头到尾控制在合理的功耗和成本范围内。系统的整体架构分成三块模拟前端与ADC两片AD9653每片两组差分输入输出LVDS数据线和DCO时钟。FPGA采集与缓存LVDS接收、串并转换、并行数据对齐、异步FIFO、AXI4-Stream输出。上位机传输链路通过USB3.0桥接芯片把数据包上传这部分我直接用现成IP工程里不做重点。这个结构最大的好处是每一层都能独立调试先把SPI配置跑通再抓LVDS波形再调数据对齐最后才接FIFO和上位机。千万别想着一次全通分层验证能让你少掉一半头发。关键参数表模块参数说明采样率125 MSPSADC输出DCO频率125M分辨率14 bit每位通过LVDS差分对传输通道数4 通道由两片双通道AD9653构成LVDS形态源同步并行每一通道一组数据线DCOFPGA7系列中端器件使用BUFIO、ISERDESE2、IDELAYE22. SPI配置模块寄存器时序与状态机设计2.1 AD9653的SPI协议基础AD9653的寄存器配置走三线/四线SPI具体由CFG_PIN决定我用的三线模式CSB、SCLK、SDIO三根线。数据帧固定32位包括8位指令和24位数据。指令部分最高位是读/写标志接着是两位无关位低五位是寄存器地址。数据部分则是16位地址的填充位实际寄存器数据在低8位。真正写寄存器时发完8位指令后跟一个无关字节然后是8位有效数据。刚开始写SPI驱动时最容易犯的错是纠结高8位还是低8位。实际上很简单有效寄存器数据在24位payload的最低8比特前面16位全部填0。例如写地址0x00、数据0x01指令就是写标志加地址00payload就是0x000001。SPI时序和普通EEPROM差不多CSB拉低SCLK时钟沿采样SDIO按高位先出写完一帧拉高CSB。2.2 上电初始化状态机设计配置状态机我写了单独模块核心状态包括上电等待、寄存器写入序列、锁相环稳定等待、配置完成。之所以要拉一个上电等待是因为ADC的AVDD和DVDD上电后有稳定时间我配置为等待5ms。寄存器写入序列用了一个case语句生成地址和数据例如写入0x00、0x01芯片软复位然后通过0x08配置内部基准、0x0A设置LVDS输出电流等。初始化完成后置位cfg_done信号LVDS接收模块才开始工作。这里有个很实用的经验配置完成后一定要把SPI模块的时钟停掉或让片选保持高电平。我遇到过ADC正常输出但SCLK上持续有毛刺导致偶发寄存器误写的情况。后来在cfg_done后把SCLK拉到固定电平、CSB拉高问题立刻消失。如果条件允许还可以回读寄存器验证AD9653支持读操作三线模式下读帧同样是32位把SDIO切到输出即可。2.3 配置不生效的排查手段SPI配置不生效时不要一上来就怀疑代码先用逻辑分析仪抓CSB、SCLK、SDIO三根线确认帧格式对不对。最常见的两个问题一个是SCLK空闲极性搞反AD9653要求SCLK空闲为低、数据在上升沿被采样第二个是片选低电平期间SCLK多翻转了一次造成CSB和SCLK的相对位置不对。这两个问题用示波器一目了然。3. LVDS接收链路BUFIO加ISERDESE2的双沿采样实现3.1 为什么LVDS接收要单独处理AD9653在125M采样率下14位数据加上DCO每通道相当于15对LVDS信号。如果直接把差分对接到普通IO靠内部逻辑时钟去采时序根本收不拢。因为差分数据和DCO在板级走线上存在skew而且DCO的频率是125MHz逻辑时钟要采到全部数据位时序余量极小。稳妥的方案是使用FPGA内部的专用IO资源DCO差分时钟经过IBUFDS转单端后由BUFIO直接驱动ISERDESE2的采样时钟数据线经过IBUFDS之后由IDELAYE2做精细延迟再进入ISERDESE2做串并转换。BUFIO的优势在于它是从IO Bank直接取时钟不经过全局时钟网络延迟最小而且可以保证与数据在同一个时钟区域内对齐。3.2 ISERDESE2参数配置与位宽展开ISERDESE2我配置成双数据率模式factor8。这样每个周期14位数据被拆成两个并行拍第一个DDR采样第二个DDR采样各自得到7位合起来就还原了14位。实际代码里每个通道例化8个ISERDESE2分别对应14个数据位和1个DCO的DDR位不对DCO不做串并转换只需要触发FIFO或作为BUFIO时钟源。数据位才是串并转换的对象。代码里最核心的部分是IDELAYE2的tap值调整。AD9653手册给出的数据与DCO之间的建立保持时间窗口约为几百皮秒而FPGA内部IDELAY一个tap的延迟大约在30到80皮秒具体由IDELAYCTRL的参考时钟决定。调试时我先把所有数据位的tap设为固定值0x20先看能不能解出基本帧再用vio核动态微调直到误码降为零。如果使用自动训练就把对齐使能放到约束中复位释放后自动扫描。3.3 双沿采样与bit对齐的根本问题ISERDESE2拿到的是差分线上的串行比特流必须正确知道哪一个bit是LSB哪个是MSB。AD9653默认输出格式中DCO的上升沿对应高字节位或低字节位不同通道之间还有可能因为LVDS极性接反造成整体bit翻转。这就需要在接收端做一个训练对齐过程ADC输出已知的测试patternFPGA端检测pattern的起始位置然后通过ISERDESE2的bitslip信号移动位边界。实际工程中我在上电初始化后先配置AD9653输出全0、全1、交替patternFPGA端检测每个通道1的计数是否等于零或满量程这一步能快速判断LVDS数据线有没有错位、短路、接反。确认无误后再配置成正常数据模式检查每通道数据高14位是不是有效。如果发现所有通道都错了固定几位基本就是bitslip没有对齐如果只是某一通道错那就查那个通道的硬件连接。4. 多片ADC同步与跨时钟域数据流4.1 为什么四通道数据会不同步两片AD9653虽然有同一个采样时钟输入但每片内部的采样时钟相位不一定完全一致上电复位的时刻也不一样所以四通道样本在时间上天然存在偏差。这个问题对要求多通道严格同步的应用非常致命。解决办法有两种一是配置AD9653的采样同步功能让两片ADC同时复位采样时钟二是在FPGA端把四通道数据统一纳入同一个FIFO读时钟域依靠FIFO写侧的使能对齐逻辑保证每个通道的样本序号一致。我采用的是第二种。四通道LVDS接收模块各自解出并行数据然后统一打拍进入各自的独立FIFOFIFO的读时钟是同一个读使能由统一的samples_valid控制。这样即使各通道写入FIFO的时刻有微小差异读出时也是按同一节奏读做到样本级对齐。需要特别注意FIFO初始化时一定要将所有通道的复位释放时刻对齐否则复位移相会造成一次永久性的偏置。4.2 异步FIFO与AXI-Stream打包每通道数据是14位加符号位或状态位之后凑成16位四个通道合起来一个采样时刻就是64位。用异步FIFO把数据从125M采样时钟域搬到传输接口时钟域例如100M的USB3接口时钟。FIFO深度我留了4K采样率长期高于传输速率时负责缓冲突发模式下不要让它写满。AXI-Stream打包的逻辑比较简单四个通道的数据并成一行附带帧头字节上位机端按帧头定位采样点即可。这里有个值得分享的细节FIFO的读写指针在跨时钟域时用的是格雷码Vivado的标准异步FIFO IP会自动处理但如果用源码务必保证写指针读侧同步和读指针写侧同步否则空满标志很容易误判导致丢数或错位。4.3 跨时钟域的最佳实践在处理LVDS接收数据时任何跨时钟域信号都不能直接打一拍了事。ISERDESE2输出的并行数据是DCO时钟域的FIFO写侧是采样时钟域FIFO本身完成了异步转换这是正确的做法。但不要因为偷懒把并行数据直接接到普通寄存器去采那时序必然出问题。我在工程里用了一个标志位来对齐通道当一线通道解出帧头后拉高sop信号其他通道的sop通过fifo内的特殊字来识别然后在读侧统一做一次流水同步。5. 约束文件与板级要点管脚分配、电平标准和时钟区域5.1 LVDS管脚分配的硬性规则在Vivado中约束LVDS管脚必须成对使用而且对IO Bank的电平标准要正确设置。7系列FPGA中LVDS电平支持HP Bank和HR Bank工作电压也不一样HP Bank是1.8VHR Bank是2.5V或3.3V。AD9653的LVDS输出供电是DVDD典型1.8V所以我把ADC的LVDS输出连接到了FPGA的HP Bank电平标准选LVDS_25或LVDS_18需确认外部端接。更关键的是DCO时钟必须分配到Bank内的MRCC或SRCC管脚否则没法用BUFIO驱动同一Bank内的ISERDESE2。如果DCO和任意一组数据线在同一个Bank用相邻的MRCC管脚最好。我在第一版PCB上因为布局关系把DCO分配到了SRCC导致BUFIO无法输出到所有需要的数据IOB后来被迫改板。FPGA选型时务必先查封装Pinout把所有LVDS对分配到有足够采样时钟资源的Bank。5.2 xdc约束示例我整理一段简化的xdc约束set_property PACKAGE_PIN AH5 [get_ports adc_dco_p] set_property PACKAGE_PIN AG5 [get_ports adc_dco_n] set_property IOSTANDARD LVDS_25 [get_ports adc_dco_p] set_property IOSTANDARD LVDS_25 [get_ports adc_dco_n] set_property PACKAGE_PIN AJ5 [get_ports adc_data_p[0]] set_property PACKAGE_PIN AK5 [get_ports adc_data_n[0]] set_property IOSTANDARD LVDS_25 [get_ports adc_data_p[*]] set_property IOSTANDARD LVDS_25 [get_ports adc_data_n[*]]当然最终约束要根据实际PCB的引脚连接来定。这里要提醒的是LVDS输入不需要额外加DIFF_TERM如果加了反而可能影响共模电压除非器件手册明确要求片内端接。5.3 时钟区域规划采集既然涉及125M的DCO建议所有LVDS I/O尽量分布在相邻的IO BankDCO的MRCC所在的Bank能覆盖的数据位数量是有限的Bank越大能接收的LVDS位越多。如果四通道数据分别在不同Bank每个Bank需要有独立的DCO资源。一个常见做法是每片AD9653的通道数据放在同一BankDCO走该Bank的MRCC这样两片ADC用两个独立Bank避免跨Bank时钟域问题。6. 仿真验证与实测调板踩坑记录6.1 写仿真模型逼真一点纯靠上板调试验证太慢。我用了一组与AD9653行为相近的仿真模型模拟LVDS时序产生125M DCO14位数据按帧输出随机模式。测试台里从SPI配置完成开始延时再打开LVDS输出检查ISERDESE2解出的并行数据是否和输入的pattern一致。仿真阶段的重点不是数据值完全一致而是确认时序窗口能否满足开发需求。比如DCO频率是125MHz周期8ns仿真模型里故意加入0.3ns的数据延迟抖动看FPGA端采样是否有误码。6.2 板级实测中的三个路径问题第一个是LVDS数据线某一根虚焊。现象是单通道数据偶发大跳变用Vivado的debug插入ILA抓数据发现某一bit长时间表现为固定电平用万用表量LVDS对地电压发现浮空补焊后正常。第二个是DCO时钟的极性反了。ISERDESE2在DDR模式下上升沿采到的是数据位的高半部分下降沿是低半部分如果DCO极性反了解出来的14位数据就会变成一组交错错位的值。这个可以靠bitslip恢复但更规矩的做法是查PCB上DCO和数据的走线长度和极性尽量从源头上避免。第三个是数据对齐失败时值看似正常。有些pattern不敏感比如满量程正弦输入时即使bit偏移一位低两位变化也不明显。所以调试时最好用满速率的伪随机码或方波作为输入只有这种信号才能暴露位对齐问题。6.3 几个可以复用的调试技巧一是使用Vivado的VIO核在运行时动态修改IDELAYE2的tap值这比每次改了约束重新综合快得多。把tap值做成可写寄存器扫描范围0到31逐档看ILA中的数据是否稳定就能快速找到最佳tap区间。二是使用集成逻辑分析仪ILA触发条件设置为帧头匹配抓取四个通道的并行数据。注意ILA本身也会消耗时钟资源数据率太高时不要长时间全速抓取用少量深度采样即可。三是把SPI配置结果回读校验做成自动流程。上电后先写配置再读关键寄存器比如0x08、0x0A等比对写入值与回读值不一致就自动设错误标志方便批量测试和老化验证时快速定位。7. 整套工程的实际工程量与后续改进空间整个工程代码量不算大核心模块包括SPI配置、LVDS接收、FIFO、AXI4-Stream输出总计约三千行Verilog综合后占用资源比较低7系列中端器件完全够用。最花时间的其实是前期的接口验证和板级调试代码本身在架构设计合理的情况下并不会反复修改太多。个人认为这套架构最大的扩展方向是可以平滑迁移到更高采样率和更多通道。比如换成双通道250M的ADC只需要把ISERDESE2的factor参数和FIFO位宽调整一下整体架构不用动如果要扩到八通道那就把四通道例化为一组再做一个上层同步模块数据流路径几乎可以复用。另一个改进方向是增加动态IDELAY训练逻辑目前我是在初始化阶段手动扫描tap值后续可以做成上电自校准完全不需要人为干预。如果大家手头正在做类似的ADC采集项目建议先把SPI配置、LVDS接收、数据对齐这三块单独验证通过再往下做传输协议。地基稳了后面所有调试都省心。我这套工程里裁剪掉了一些板级特定配置和上位机相关代码但核心逻辑是可以直接沿用的。如果评论区有做同步多通道采集的朋友欢迎交流你们在LVDS对齐上的做法我这边后来也整理了一些关于DCO采样窗口的测试数据有时间会再单独写一篇。
RELATED

相关推荐

Multi-DBSCAN多密度聚类算法解析与Python实践

Multi-DBSCAN多密度聚类算法解析与Python实践

做空间聚类的人大概都遇到过这种尴尬:数据里有几坨挤得很紧的点簇,又有几片散得跟芝麻似的稀疏簇。经典的 DBSCAN 只给一套eps和min_samples,半径定小了,稀疏簇被当成噪声;半径定大了,密集簇又粘成一团。我…

📅 2026/10/17 6:09:10
Android逆向入门:APK反编译、重打包与签名工具链实战

Android逆向入门:APK反编译、重打包与签名工具链实战

简介:这套工具面向Android开发、安全测试和逆向学习人员,将apktool、dex2jar、jd-gui、autosign等常用组件整合为一体化逆向助手,能够完成APK反编译、DEX转JAR、Java代码查看、重签名等核心操作,帮助使用者快速分析应用结构、定位…

📅 2026/10/17 6:09:10
AI对话小程序模板实战:云函数中转与流式渲染全解析

AI对话小程序模板实战:云函数中转与流式渲染全解析

简介:这是一份AI人工智能机器人对话微信小程序的完整前端模板,面向具有一定编程基础、需要快速搭建对话类小程序界面的开发者。模板采用HBuilder编写,涵盖对话消息展示、输入交互、会话列表、表情与快捷回复等基础模块,但不含后端…

📅 2026/10/17 6:09:10
MORE NEWS

更多资讯

📰

Linux:信号的认识、信号的产生、信号的保存、信号的处理

一、对信号的宏观认识从实际的场景来举例:红绿灯、上课铃声,电话铃声等都是一种信号的产生,而我们对这种信号处理的方式是后天训练而形成的,如:红灯停,绿灯行。 所以对于OS的信号而言,也就是工程师们内置提前写好的,对于对信号怎么…

📰

内测分发折腾史:从微信传包到海哈游分发

做独立开发这几年,写代码的时间其实只占一半,另一半全耗在了“把包送到测试同学手里”这件事上。今天想聊聊内测分发这个看似不起眼、实则极其磨人的环节,以及我最终怎么用 海哈游分发 把这事儿理顺的。一、那些年我发内测包踩过的坑最开始&a…

📰

一根线的显相:人体拓扑论

—— 关于人体拓扑生长原理及未来仿生体路径的假说 本文为作者(道影子)基于内观体悟所提出的一个思想假说,非实证科学结论。文中涉及 "维性力网"" 人体拓扑 " 等概念,均为本体系内的自洽设定,供同…

📰

小说推文配套漫剧生产,知漫剧高速生成成片方案

引言: 短剧漫剧赛道持续升温,小说推文的玩法也在升级——文字推文配漫剧成片,成了完播率最高的组合。推文拼的不再是文案,是配套产能。 小说推文配漫剧,拼的是生成速度。知漫剧(zz.jiaxunai.cn&#xff09…

📰

WuKongIM v2→v3 迁移元数据读取规则深度解析:设备冷启动凭据、重复会话与空身份记录的迁移策略

即时通讯后端 【免费下载链接】WuKongIM More than just IM 不只是即时通讯(IM) 项目地址: https://gitcode.com/gh_mirrors/wu/WuKongIM 点击查看 免费下载 本文基于 WuKongIM 仓库中的《v2 元数据读取规则与迁移进展》报告(docs/superpowers/reports/…

📰

中标麒麟上CUDA环境搭建与深度学习推理实战

1. 为什么要在中标麒麟上折腾CUDA中标麒麟这套系统,接触过的人心里都有数。它在不少单位的办公终端和服务器上跑了好些年,界面用的是MATE桌面,底层是Linux内核,包管理走的是RPM那一套。平时拿它写文档、跑脚本、做点轻量级开发都没…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬