☰
基于FPGA的AD7606八通道同步采样与波形显示实践
2026/10/26 17:46:13 网站建设 项目流程

做 FPGA 开发这些年,我越来越觉得“采集”这件事儿比多数人想象的更有门道。最近把黑金 AN706 板卡重新翻出来,配合板载的 8 通道同步采样 ADC 跑了一轮完整的波形显示实验,从硬件链路梳理到 FPGA 驱动代码编写,再到 HDMI 实时显示,整个过程踩了不少坑,也把很多以前模糊的概念彻底理顺了。这篇就专门聊聊这次实验里的核心设计思路、代码落地细节和几个我亲测有效的问题排查方法,希望能给正在做多通道数据采集或者还在纠结“同步采样到底比顺序采样强在哪”的朋友一些参考。

1. 为什么 8 通道同步采样是刚需:相位误差与工程代价

1.1 顺序采样与同步采样的本质差别

先从一个最典型的场景说起。我在测一个三相电机驱动器的电压电流波形时,最开始用的是普通多路 ADC,芯片内部是一个转换器加一个多路选择开关,通道轮流切换采样。当时没细想,觉得 8 路信号嘛,挨个采就行,反正频率也不高。结果把三相电流做出来一对比,通道之间的波形总有那么一点点“错位”,尤其是在算有功功率的时候,误差一下子就被放大了。

问题就出在“轮流”这两个字上。任何一路 ADC 在同一时刻只能采一个通道,多路选择器切换需要时间,每采完一路,下一路拿到的其实是延迟了一段时间之后的信号。对直流或者低频缓变信号来说,这个延迟可以忽略;但对工频交流、电机反电动势、振动信号这类随时间变化的信号,通道间的时间差就等于相位差。相位差在高精度测量和闭环控制里是最要命的东西。

而同步采样 ADC 的原理就简单直接:内部有多个采样保持器,每个通道都有自己独立的采样保持电容。FPGA 给一个转换启动信号,所有通道在同一时刻把模拟量“冻结”到各自的保持电容里,然后 ADC 再依次把每个保持电容里的值转换成数字量。这样采集到的 8 个数据,从时间轴上看就是在同一个瞬间的 8 个点的值,通道之间不存在时间偏移。换句话说,同步采样解决的是“同一时刻”的问题,而不是“转换速度”的问题。

1.2 8 通道意味着哪些典型应用

8 路同步采样的需求并不是拍脑袋想出来的。我梳理了一下实际工程里最常见的几类场景,基本都能套到这个框架里:

  • 三相电力测量:三路电压加三路电流正好六通道,剩下的还能留两路做中线电流或者零序信号。功率计算需要同时刻的 U 和 I,否则角度误差会直接带进有功、无功、功率因数的计算结果。
  • 电机控制与驱动:三相电流采样、母线电压、散热器温度,凑起来正好 8 路,而且电机控制里 PWM 开关噪声大,电流波形畸变严重,同步采样的相位一致性是评估控制算法性能的基础。
  • 结构振动与声学测量:三轴加速度计、多麦克风阵列,每个传感器都需要同一时刻的采样值才能做波束成形、阵列分析或者模态分析。
  • 生物电信号:多导联脑电、心电的同步记录,本质上也是多通道时间一致性要求极高的场合。

8 通道是一个很实用的规模:它覆盖了三相系统的完整采集需求,又不会像 16 通道、32 通道那样让 PCB 布局和数据传输复杂度过高。对学习 FPGA 的人来说,8 通道的数据量和接口复杂度也刚好处在“有挑战但能驾驭”的位置。

1.3 为什么选 AD7606 这类芯片做教学载体

黑金 AN706 板卡上用的 8 通道同步采样 ADC 是 ADI 的 AD7606 系列。这颗芯片在工业数据采集和 FPGA 教学里几乎成了“标准答案”,不是因为它是性能天花板,恰恰因为它的设计很“会做人”。

AD7606 单颗芯片集成了 8 个完整的采样保持前端和 16 位逐次逼近型 ADC,不需要外部运放做信号调理,输入范围可以配置成 ±5V 或者 ±10V 双极性,也可以只读单极性。供电也省心,模拟部分 5V,数字接口由 VDRIVE 引脚决定,可以直接挂 3.3V 的 FPGA IO。这些特性让它非常适合直接跟 FPGA 对接——不需要一堆分立器件,不需要双电源域,一个芯片就能把模拟前端和数字转换全包圆了。

数据接口方面,AD7606 提供了并行 16 位和串行 SPI 两种接口。并行模式速度快、时序直观,适合 FPGA 入门时理解读写流程;串行模式引脚少,适合后续做系统集成时给 FPGA 省 IO。AN706 上默认把两种接口都引出来了,实验默认走并行方式,但代码里也留了串行模式的注释。

整个视频课程里把 AD7606 归为“同步采样 ADC”而不是普通“多通道 ADC”,这个定位是准确的。共享采样保持器和独立采样保持器是两代方案的分水岭,理解这个区别比背引脚编号重要得多。

2. AN706 上的 ADC 硬件链路:从接插件到接口时序

2.1 板卡硬件资源与信号通路

把 AN706 板卡拿在手里先看了一圈,和 ADC 相关的资源集中在 PCB 的一个区域内:板载一片 AD7606,外加输入接插件、基准电压、电源转换和一组排针引出所有数字控制信号。输入接插件是焊盘式的,把螺丝端子焊上就能接传感器信号;不想焊也能直接用杜邦线从旁边的排针往里灌信号。

板卡上 ADC 的通道输入做了简单的 RC 滤波,这层防护主要是抑制高频噪声和反射,实验环境里够用。需要提醒的是,AD7606 的输入阻抗不是无穷大,虽然它内部有高阻输入的信号调理电路,但接高内阻传感器时最好还是加一级电压跟随器,否则会引入比例误差。我这次实验直接用了信号发生器输出,内阻 50 欧姆,所以没这个烦恼。

与 FPGA 的连接方式也值得说。AD7606 的数字引脚全部接到了 FPGA 的普通 IO 上,没有经过电平转换芯片,因为 VDRIVE 直接接到了 3.3V,数字接口逻辑电平就是 3.3V LVCMOS,和 Artix-7 的 Bank 电压完全匹配。这里有一个经验:如果某块板子的 ADC 数字接口供电是 5V,那么 FPGA 的 IO 必须确认是否耐压 5V,很多 FPGA 的 IO 并不支持,设计时第一件事就是查 Bank 电压和引脚耐压。

2.2 接口信号与时序约束

AD7606 的控制信号并不复杂,核心就是 CONVST、BUSY、CS、RD,外加并行数据线 DB[15:0]。整体工作流程可以描述成三个环节:

  1. 转换触发:CONVST 引脚产生一个上升沿(或者把 CS 直接拉低后拉高 CONVST,取决于配置),所有通道同时进入采样保持并启动转换。
  2. 转换等待:BUSY 拉高,表示内部 ADC 正在转换;BUSY 拉低,说明转换结果已经锁存到输出寄存器。
  3. 并行读取:CS 拉低后,第一个 RD 脉冲把通道 1 的数据放到数据总线上,第二个 RD 脉冲读通道 2,依此类推,8 个 RD 脉冲取完 8 个通道。

时序上最需要关注的是 RD 有效后数据总线的建立时间,以及 BUSY 下降沿到第一个 RD 脉冲的最小间隔。我最初写状态机时没注意后者,导致最后几个通道的数据偶尔抓飞掉,后来在代码里加了几个周期的延时才稳定。

接口速率这块也测算过:AD7606 在 200kSPS 的采样率下,每 5 微秒完成一次全通道转换,每个通道 16 位,8 个通道共 128 位数据。5 微秒内读完 128 位,就算在并行模式下,对 FPGA 的时序也是毫无压力的;如果换成串行 SPI 模式,200kSPS 下时钟频率大概在 25MHz 以上,也还行,但余量就没有并行模式那么富裕了。

2.3 量化范围与多通道数据的物理含义

AD7606 是 16 位 ADC,输出编码是有符号数。双极性输入下,±10V 范围对应 -32768~+32767,±5V 范围对应同样编码但满量程减半。实验里我把输入范围配成 ±10V,这意味着数据手册上的编码值除以 32767,再乘以 10V,就是真实电压值。

这个换算关系必须写对,否则波形显示出来比例尺全错。我在代码里把 16 位有符号数直接往外抛,上位机或者显示模块在算坐标时先按符号扩展成 32 位有符号数再做除法,避免 Verilog 里无符号数除以负数时出现莫名其妙的错误。

3. 波形显示实验的整体架构:采集、缓存、刷新三块怎么配合

3.1 顶层模块划分

整个实验的功能不复杂,但跨时钟域和显示时序是容易出问题的地方。我的顶层设计分了三块:ADC 采集控制、数据缓存、波形显示,另外加一个按键模块用于切换显示模式和触发模式。

ADC 采集控制模块负责生成 CONVST 脉冲、等待 BUSY、读取 8 通道数据,并把数据按通道号写入缓存。波形显示模块负责从缓存读数据,换算成屏幕坐标,产生 VGA/HDMI 时序。两者频率不同:采集逻辑跟着一个独立的采样时钟或者分频计数器走,显示逻辑在像素时钟下跑。如果不加缓存直接让两边通过组合逻辑互相访问,要么显示端被采集端打断导致画面撕裂,要么采集端被显示端拖累丢数据。所以缓存这层必须有。

我用的是双端口 RAM:写入端口连接采集模块,读出端口连接显示模块,时钟各走各的。这样两边完全解耦,采集模块只需关心“我写进去了”,显示模块只需关心“我读出来了”。唯一要做的是保证写地址和读地址在不同时刻访问不同区域,否则会出现读到的数据是一个半旧半新的混合体。

3.2 缓存深度与像素点对应关系

屏幕上的波形显示,本质上是一个把离散采样值映射到屏幕坐标再画线的过程。实验用的显示分辨率是 640×480 @60Hz,每行 640 个像素,实际可用的波形绘制区域在水平方向留了边距之后约 600 像素。

每个通道在一屏上显示多少个采样点,决定了缓存的大小。我选择了每通道显示 512 个点,这样水平方向 600 像素对应于 512 个采样点,每个点之间大约 1.17 个像素,画线时用 Bresenham 或者简单的线性插值拉过去,视觉上是一条连续曲线。8 通道 × 512 点 × 16 位 = 64Kbit 的存储量,用 Xilinx 的 Block RAM 一个 18Kb 块还不够,但两个 Block RAM 或者一个块配置成双端口就绰绰有余。

这里有个设计选择:滚动显示还是整帧抓拍。滚动显示的优点是实时感强,波形像心电图一样从右向左刷新;缺点是 8 条波形同时滚动时 CPU/显示逻辑的处理量稍大。整帧抓拍则是一次触发抓满 512 个点,然后花一帧时间慢慢画出来,适合观察周期性信号的细节。我的实现里做了一个模式选择,默认滚动模式,按键切换抓拍模式。实际教学演示中,抓拍模式的视觉效果更清晰,因为不会有一堆残影互相干扰。

3.3 触发逻辑怎么设计

波形显示实验里最影响体验的是触发。如果没有触发,刷新频率和信号频率不同步,画面上的波形会来回跑动,看起来像喝了酒一样在抖动。为了让波形“站稳”,需要一个简单的触发检测。

我的做法是:在每个通道数据写入的同时,比较当前值和上一个值,检测到上升沿(负值变正值且越过某个阈值)时,把写地址清零,重新开始缓存。这样每次采集的 512 个点都是从同一个相位点开始,周期性信号的波形自然就稳定了。阈值和触发通道都可以通过按键切换,默认触发通道是通道 1,阈值设为 0。

触发逻辑有副作用:如果输入信号幅值很小、一直低于阈值,或者信号不是周期性的,触发永远不会发生,缓存永远写不满,屏幕会一直停留在上一帧。解决方法是加一个超时计数器和自由运行模式,超过一段时间没有触发就自动切换为自由运行,用采集满 512 点而不是触发点来决定帧边界。

4. 驱动代码的落地细节:状态机、FIFO 与坐标换算

4.1 AD7606 并行读取状态机

下面这是我在实验里用的简化版 AD7606 驱动状态机,去掉了调试端口和实际配置参数,保留了核心流程。对第一次接触这颗芯片的人来说,照着这个框架跳进去调试,比一上来读几十页数据手册要友好得多。

module ad7606_ctrl( input clk_50m, input rst_n, input start, // 外部触发一次转换 output reg convst, input busy, output reg cs_n, output reg rd_n, input [15:0] adc_data, output reg [15:0] ch_data[0:7], output reg [3:0] state_debug ); localparam IDLE = 4'd0; localparam CONVST_LOW = 4'd1; localparam CONVST_HIGH = 4'd2; localparam WAIT_BUSY = 4'd3; localparam RD_CH0 = 4'd4; localparam RD_CH1 = 4'd5; // 通道 2~6 略 localparam RD_CH7 = 4'd11; reg [2:0] ch_cnt; reg [7:0] wait_cnt; always @(posedge clk_50m or negedge rst_n) begin if (!rst_n) begin state_debug <= IDLE; convst <= 1'b1; cs_n <= 1'b1; rd_n <= 1'b1; ch_cnt <= 3'd0; end else begin case (state_debug) IDLE: begin convst <= 1'b1; if (start) state_debug <= CONVST_LOW; end CONVST_LOW: begin convst <= 1'b0; // 拉低一段时间 state_debug <= CONVST_HIGH; end CONVST_HIGH: begin convst <= 1'b1; // 上升沿触发转换 state_debug <= WAIT_BUSY; end WAIT_BUSY: begin if (!busy) begin cs_n <= 1'b0; state_debug <= RD_CH0; end end RD_CH0: begin rd_n <= 1'b0; // RD 低电平期间读数据 ch_data[0] <= adc_data; state_debug <= RD_CH1; // 按 AD7606 手册,数据在 RD 拉低后建立,可根据实际时序加一拍延迟 end // RD_CH1..RD_CH6 同理 RD_CH7: begin rd_n <= 1'b0; ch_data[7] <= adc_data; cs_n <= 1'b1; // 读完全部通道,CS 拉高 rd_n <= 1'b1; state_debug <= IDLE; end default: state_debug <= IDLE; endcase end end endmodule

注意上面代码有个细节:严格按 AD7606 手册,RD 拉低后到数据总线上数据稳定的时间大约在几十纳秒量级。我用的 FPGA 内部锁存发生在同一个时钟沿,50MHz 下周期是 20ns,如果 RD 拉低的组合逻辑和锁存逻辑之间走线延迟不够,可能真的会拿到还没稳定的数据。稳妥的做法是在 RD 拉低后用一个计数器延时 1~2 个时钟周期,再锁存总线数据。这段代码在实际工程里一定要按芯片封装后的时序重新做约束,不能拿仿真波形直接照搬。

4.2 跨时钟域缓存:FIFO 与双端口 RAM

采集模块工作在 50MHz 采集时钟下,显示模块工作在像素时钟下,两个时钟之间是无相位的异步关系。最简单的跨时钟域方法是直接用分布式的双端口 RAM:写端口挂在采集时钟域,读端口挂在像素时钟域。

地址分配上,滚动模式用线性写地址,每写完一帧就回到零;显示模块用一个独立的读地址,它只需要在屏幕上逐行扫描时把需要显示的那段数据顺次读出来。FIFO 在这种场景不是最好的选择,因为显示端不是“顺序消费所有数据”,而是按屏幕上每个像素的位置随机访问某个历史采样点,所以更像一个内存映射,而不是一个队列。

如果把滚动模式升级成“伪实时”效果,就需要两块 RAM 做乒乓操作:采集模块写 RAM_A 的同时,显示模块读 RAM_B;采集写满 512 个点后切换,显示模块转而读 RAM_A,采集模块开始写 RAM_B。乒乓切换的关键是两个时钟域之间的“写满”标志需要先做同步,否则显示模块可能在新数据还没写稳时就开始读,画面上出现一行花点。我用的同步方案是两级寄存器打拍 + 握手信号,实际用下来没有出现过错误切换。

4.3 波形显示的坐标换算

把采样值变成屏幕上的点,数学部分不复杂,但细节容易做歪。核心公式只有两个:

  • X 坐标 = 起始X + n × 水平缩放系数
  • Y 坐标 = 起始Y - (采样值 - 下限) × 垂直缩放系数 / 满量程范围

其中垂直缩放系数由显示区域高度和 ADC 满量程决定。例如显示区域高度 400 像素,ADC 满量程 65536,那么每 1 LSB 对应约 0.006 像素,直接用除法会得到小数,所以实际代码里用乘法和移位来代替:垂直缩放系数近似成 (400×1024)/65536 = 6.25,然后在 FPGA 里做 10 位移位除法即可。

画线部分,我没有用复杂的 Bresenham 直线算法。屏幕水平方向 512 个点对应约 600 像素,用简单的“每两个采样点之间线性插值”就够视觉平滑了。插值宽度不大时误差在 1 个像素以内,完全不影响观察。

每个通道用不同颜色区分,显示模块里维护一个通道序号,用于从缓存中取出对应通道的数据。颜色我固定分配了红、黄、绿、青、蓝、紫、白、橙,这样 8 条波形混在一起也能区分。实验里有人问能不能把通道标签也打到屏幕上,这个其实做起来也不难,文本显示模块和波形显示模块共用一个显存地址计算结构,就是字库 ROM 占用一点 Block RAM。

5. 实测踩坑:四条通道波形粘连问题的完整排查过程

5.1 现象描述与初步猜测

第一次完整跑通显示后,我盯着屏幕看了几分钟,发现一个很恼人的问题:通道 1 和通道 2 的波形在幅值过大时会发生“粘连”——两条本来应该完全分离的曲线,在波峰附近互相吸引,甚至出现短暂的完全相同。通道 3 和通道 4 则表现正常。

这种问题在示波器上经常被归结为“通道隔离度不够”,第一反应往往是怀疑模拟前端串扰。但我的输入源是信号发生器,用了两路输出,一路接通道 1,一路接通道 2,波形分别是 1kHz 正弦和 2kHz 方波,源内阻 50 欧姆,理论上不会互相拽。于是我把通道 1 的输入线拔掉,单看通道 2 的波形,发现通道 2 依然带有一个和通道 1 频率相同的微弱成分。问题没那么简单。

5.2 排查链路:从模拟串扰到数字时序

我按顺序做了三次排查,每次记录现象并排除一组可能性。

第一轮,怀疑电源串扰。AD7606 的参考电压由板载基准芯片提供,如果参考电压纹波大,所有通道都会受影响。我用示波器测了 AVCC 和基准电压,纹波都正常;给通道 1 和通道 2 同时输入直流电位时,ADC 读到两个不同但稳定的值,说明模拟通路本身没有被短路。

第二轮,怀疑数字接口时序。通道 1 和通道 2 在并行读取时是前两个 RD 脉冲读出的,如果 RD 时序有问题,理论上最先受影响的也是前两个通道。我把状态机里 RD 脉冲宽度加长,同时在读取后额外加了 4 个时钟周期的稳定时间,重新上电后粘连现象明显减弱但仍然存在,只是阈值往上抬了。这说明时序是一个因素,但不是根因。

第三轮,我直接用 ChipScope 抓了寄存器里的 8 通道数据,发现一个关键现象:当通道 1 输入大幅值信号、通道 2 输入小幅值信号时,通道 2 的读数里会周期性地混入一段和通道 1 完全相同的数据样点。也就是说,问题出在“数据写入缓存”这一层,而不是模拟采样本身。顺着这个线索查代码,发现我的采集模块里,通道 2 的寄存器赋值语句写错了触发条件——它继承了通道 1 的赋值使能,导致在通道 1 的 RD 周期里,通道 2 的寄存器也被更新成了总线上的同一个值。

5.3 根因修复与验证

修复代码错误的成本极低:把通道 2 赋值语句的使能条件换成通道 2 自己的 RD 计数即可。但这段排查对我的启发很大——很多“模拟串扰”其实都是数字逻辑 bug 的伪装。

修复后我用同样的输入条件跑了一个小时,波形完全分离,粘连阈值也消失了。想验证通道间隔离度的话,可以给相邻通道加一个阶跃信号,观察另一通道的响应幅度,照 AD7606 手册的参数,相邻通道串扰大约在 -100dB 量级,这个数量级在波形显示上根本看不见。

这次排查留下的第二个经验是:调试多通道 ADC 项目时,千万不要只靠屏幕上的波形判断好坏,一定要把 ADC 的原始数字量拉到逻辑分析仪或者在线逻辑分析仪里看。屏幕上很多显示层的“假象”(缩放、插值、坐标换算错误)和采集层的“真问题”(寄存器赋值错误、时序建立不足)会互相掩盖,用原始数据定位才是最可靠的。

5.4 实测指标与观察

稳定运行后我做了一组粗略的实测:输入一个 100Hz、5V 峰峰值正弦波,显示频率和幅值都与信号源读数一致;切换到 10kHz 方波时,波形边沿开始出现明显的过冲,这是输入 RC 滤波和 ADC 带宽限制共同造成的,属于正常现象。

采样率方面,示波器上观察 CONVST 信号的周期,实测为 5 微秒(200kSPS),抖动小于 2ns,这个抖动来自 FPGA 内部计数器的固定延迟,完全可接受。换上串行 SPI 模式后采样率降到大约 50kSPS,这是因为串行读出时间比并行更长,总帧周期变大了。

关于 AD7606 的信噪比,我没有专业音频分析仪做完整测试,但把输入端短路后采集了 65536 个点求方差,估算出来的噪声底大约有 3 个 LSB。这个结果对波形显示实验完全够用,足够显示 12 位的有效精度。想深挖信噪比的话,可以在采集端累加 8192 个点做 FFT,观察 1kHz 信号的信噪比指标,这也是黑金云课堂后续章节的常见操作。

6. 如果能重来:方案替换与扩展方向

6.1 从并行读取换成 SPI 串行读取的代价

这次实验默认用的是并行读取,IO 占用 16 根数据线加 4 根控制线,功耗和布局压力都不大。但如果想把这个设计移植到更多通道的板卡上,或者想节省 IO 给 HDMI 显示和按键控制用,SPI 模式会更划算。

AD7606 的 SPI 模式只需要 SCLK、DIN、DOUT 三根线(CS 仍需要一根控制线),8 个通道的数据在 SCLK 的驱动下依次从 DOUT 移出。代价是读延迟变长:每通道 16 位,8 通道 128 位,SCLK 频率假如 20MHz,单帧读取需要 6.4 微秒,比并行模式的 2 微秒左右长了不少。这意味着 200kSPS 的采样率会被串行读取拖到大概 80kSPS,如果传感器信号本身是几十 kHz 级别的,还能接受;要是想做更高频的采集,就得用并行或者找更高转换速率的 ADC。

6.2 多片 AD7606 级联:采样率翻倍的思路

8 通道同步采样其实是“时间同步”的一个特殊情况。如果你需要 16 通道、24 通道,甚至需要通过轮询两组 ADC 来“伪造”更高采样率,级联是绕不开的。

多片 AD7606 级联有两条路线。一是完全独立模式:每一片的 CONVST 连同一个信号,所有片同时触发,数据分别读到 FPGA 里。这种方案需要的 GPIO 数量线性增长,但时序最简单。二是菊花链模式:片 1 的 DOUT 接到片 2 的 DIN,片 1 的 SCLK 和片 2 的 SCLK 并联,读的时候一个 SCLK 脉冲流把所有芯片的数据串行移出来。菊花链节省了 IO 引脚,但 128 位的数据加上级联芯片的数量会让单帧读取时间成倍拉长。

如果只是想提高等效采样率而不是增加通道数,可以考虑两片 AD7606 的 CONVST 信号之间错开半拍,比如片 1 在 t=0 触发,片 2 在 t=2.5us 触发,这样两片交替输出,等效采样率从 200k 提升到 400kSPS。代价是相位一致性的概念被打破了——你得到的 400k 个点并不是同一时刻的 8 通道值,而是 8 通道在交错时刻的独立采样,这点用在分析单通道频谱时没问题,但不要再拿去做三相功率计算。

6.3 上位机波形显示与 FPGA 显示的分工

这次实验选择把波形直接通过 HDMI 显示器展示,原因是课堂演示更直观,现场没有电脑也能看。但很多工程场景里,更实用的方案是让 FPGA 只做采集和预处理,把数据通过串口或者以太网送到上位机,由 Python 或 LabVIEW 画波形。

这时候就体现出“波形显示实验”和“数据采集实验”的侧重点差异了。FPGA 显示波形解决的是实时性,但牺牲了交互性:改量程、调触发阈值、切换通道都要重新综合,体验比较笨拙。上位机方案则相反,数据到了 PC 之后就灵活了,Zoom、FFT、滤波、保存历史记录都是软件层面的事。但代价是 FPGA 侧必须有一套可靠的通信协议,比如最简单的就是按帧格式发送。我在另一个版本里用 UART 把 AD7606 的 8 通道数据打包成 ASCII 字符串发送给串口助手,上位机再按行解析,虽然效率低(每秒只能传几千帧),但胜在零依赖,连串口终端都能看到波形。想提高吞吐的话可以换 USB 转串口加二进制协议,或者直接上以太网 UDP。

6.4 往更高速的 ADC 走:FPGA 的 LVDS 接口

AD7606 的并行接口对 FPGA 来说太友好了,友好到让人忽略了真正的高速 ADC 往往是另一副面孔。如果换成 ADS52J90、AD9680 这类千兆采样率的转换器,数据接口通常是 JESD204B 或者 LVDS,一根线上串行承载多位数据,时钟频率动辄几百 MHz。这时候 FPGA 内部需要做 LVDS 接收、位对齐、通道对齐、多通道去偏斜,复杂度会跳一个数量级。

从学习路径来讲,先把 AD7606 的同步采样机制吃透,再用 FPGA 的 LVDS 接收原语去对接更高速率的数据,是比较顺的进阶路线。因为同步采样 ADC 的“时间一致性”思路和高速 ADC 的“高速串行对齐”思路是共通的,只是实现载体从并行总线变成了高速串行链路。黑金云课堂后面的章节也确实有专门的 LVDS 接收实验,我在用 ALINX 的板卡做类似实验时理解速度明显比直接啃 JESD204B 协议要快得多。

6.5 这次实验里我最想保留的三个设计习惯

复盘整个实验,有三个设计习惯是我强烈建议保留到后续所有采集项目里的。

第一,数据缓存永远采用读、写、控制分离的分层结构,不要为了省一个 RAM 块让写地址和读地址互相干扰。花几行代码多建一个双端口 RAM,换来的是排查问题时清晰的边界。

第二,所有 ADC 原始数据在进入显示或者通信模块之前,必须先在逻辑分析仪里做一次“信号完整性体检”。很多看起来像模拟问题、电源问题或者电磁兼容问题的现象,最后都在数字逻辑里找到了答案,这次通道粘连就是活生生的例子。

第三,凡是涉及多通道数据共享总线的设计,赋值语句的使能条件要用一个显式的通道计数值统一生成,不要依赖复制粘贴然后手动改条件。我用的是 Verilog 的 generate 块生成 8 个通道的赋值逻辑,这样每个通道的使能条件完全同构,不可能出现通道 2 用了通道 1 的使能信号这种低级错误。

如果你也在做类似的多通道同步采样项目,建议先不要急着堆功能,先把“同一时刻、多个通道、无差错传输到缓存”这三件事做扎实,再考虑画波形、做 FFT 或者上位机交互。基础打得越稳,后面遇到高速 ADC 和复杂协议时才越有底气。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询