1. 为什么XC7Z010的ADC引脚值得单独拿出来讲
XC7Z010-1CLG400C这颗芯片在Zynq-7000家族里属于入门级的存在,双核Cortex-A9加上Artix-7架构的可编程逻辑,400引脚的CLG封装,体积小、功耗低,做工业控制和数据采集的板子用得特别多。但很多人第一次用它的XADC模块时都会卡在同一个地方:引脚到底怎么配?为什么Vivado里明明选了XADC核,引脚约束却总是报错?
这个问题的根源在于XADC的引脚分两类。一类是专用的模拟输入引脚,VP/VN和VAUXP/VAUXN,这些引脚在芯片上是固定的,不受普通IO约束管辖;另一类是XADC与PL逻辑交互时用到的控制信号,比如转换启动、通道选择、数据就绪这些,它们走的是普通IO或者内部逻辑,需要你在约束文件里明确指定。很多人把这两类混在一起处理,结果就是约束冲突或者功能不生效。
我手上这块XC7Z010-1CLG400C的开发板,XADC部分前后调了大概两周,踩过的坑包括引脚分配冲突、参考电压不稳导致采样值跳变、Vivado里XADC核的时钟配置不对导致转换结果全是零。这篇文章就把这些经验完整地整理出来,从XADC的基本架构讲到引脚约束的具体写法,再到实际调试时怎么排查问题。不管你是刚接触Zynq-7000的新手,还是已经用过其他FPGA但第一次碰XADC的工程师,应该都能从中找到可以直接用的东西。
提示:XC7Z010-1CLG400C的XADC模块和7系列FPGA里的XADC是同一套IP,但Zynq上多了一层PS端的访问路径,配置时要注意区分。
2. XADC模块的核心架构与引脚分类逻辑
2.1 XADC在Zynq-7000里的位置和基本能力
XADC全称是Xilinx Analog-to-Digital Converter,在7系列FPGA和Zynq-7000里都是硬核模块,不占用PL的逻辑资源。它包含一个12位、1MSPS的模数转换器,支持最多17个外部模拟输入通道(1个专用VP/VN加16个辅助通道VAUXP/VAUXN),另外还能测量芯片内部的温度和供电电压。
在XC7Z010-1CLG400C这个具体型号上,XADC的专用模拟输入引脚是固定的。VP/VN对应芯片的某个特定BANK引脚,VAUXP/VAUXN则分布在BANK35和BANK34上。这里有个关键点:不是所有VAUX通道在这个封装里都可用。CLG400是400引脚的CSP封装,引脚数量有限,Xilinx在分配时只引出了部分辅助通道。具体哪些可用,必须查UG480文档里的引脚映射表,不能想当然。
XADC的转换结果可以通过两种方式读出。一种是通过PL端的DRP(Dynamic Reconfiguration Port)接口,用逻辑去读写XADC的寄存器;另一种是在Zynq上通过PS端的devcfg或者直接访问XADC的寄存器地址。两种方式各有适用场景,PL端DRP适合高速连续采样,PS端访问适合低速监控和配置。
2.2 专用模拟引脚和辅助通道的区别
专用模拟引脚就是VP/VN这一对。VP是正输入端,VN是负输入端,它们直接连到XADC的模拟前端,不需要经过任何IO缓冲。这对引脚的输入范围是0到1V(差分),或者单端模式下0到1V。注意这个电压范围是硬限制,超过1V会损坏芯片,所以外部信号必须经过分压或者运放调理。
辅助通道VAUXP/VAUXN有16对,但实际可用的数量取决于封装。在CLG400上,根据UG480的表,可用的辅助通道大概是8对左右,分布在BANK35和BANK34。这些通道的输入范围同样是0到1V差分。和VP/VN不同的是,辅助通道可以通过XADC内部的序列器自动轮询,不需要CPU干预,适合多路低速采样的场景。
这里要特别强调一个容易搞错的地方:VAUXP/VAUXN引脚在芯片上是有双重功能的。它们默认是普通数字IO,只有当你例化了XADC核并且在约束里正确配置后,才会切换成模拟输入。如果你在Vivado里没有正确设置,这些引脚就还是普通IO,你往里灌模拟信号不仅采不到数,还可能因为数字IO的输入结构导致信号失真。
2.3 控制信号引脚的角色划分
XADC和PL逻辑交互时用到的控制信号包括:adc_convst(转换启动)、adc_chsel(通道选择)、adc_eoc(转换结束)、adc_eos(序列结束)、adc_drdy(数据就绪)、adc_do(数据输出)、adc_dclk(DRP时钟)、adc_den(DRP使能)、adc_dwe(DRP写使能)、adc_daddr(DRP地址)、adc_di(DRP数据输入)。
这些信号在Vivado的XADC核里都有对应的端口。如果你用的是AXI XADC核,这些信号会被封装成AXI接口,你不需要直接管;如果你用的是DRP接口的XADC核,就需要自己在逻辑里生成这些控制信号。对于XC7Z010这种小芯片,PL资源有限,用DRP接口更省资源,但控制逻辑要自己写。
这些控制信号走的是普通IO或者内部逻辑,不占用专用模拟引脚。在约束文件里,你只需要约束那些真正引出到芯片引脚的信号,比如如果你要把adc_convst引到外部按键上,就需要约束对应的IO引脚。如果全部在PL内部逻辑里闭环,就不需要额外的引脚约束。
3. XC7Z010-1CLG400C的ADC引脚完整列表与约束写法
3.1 专用模拟输入引脚的物理位置
XC7Z010-1CLG400C的VP/VN引脚在芯片的BANK35上,具体引脚号需要查Xilinx的封装文件。根据UG480和XC7Z010的pinout文档,VP对应的是某个特定引脚,VN对应另一个。这里我不直接给引脚号,因为不同批次的芯片或者不同的开发板设计可能有差异,最可靠的方法是打开Vivado,在I/O Planning里查看XADC的专用引脚位置。
在Vivado里查看的方法是:打开你的工程,在Flow Navigator里点Open Implemented Design,然后Window -> I/O Planning。在I/O Planning的Package视图里,XADC的专用引脚会以不同的颜色标出。你可以直接看到VP/VN和可用的VAUXP/VAUXN在芯片上的物理位置。
对于VAUX通道,在CLG400封装上可用的通道包括VAUXP0/VAUXN0、VAUXP1/VAUXN1、VAUXP8/VAUXN8、VAUXP9/VAUXN9等。具体哪些可用,同样以Vivado的I/O Planning为准。我实测下来,CLG400上大概有6到8对辅助通道可用,足够做多路电压监控了。
3.2 辅助通道的引脚约束模板
在XDC约束文件里,XADC的模拟引脚不需要像普通IO那样写set_property PACKAGE_PIN和set_property IOSTANDARD。实际上,如果你在Vivado里例化了XADC核,这些引脚会自动被占用,你不需要手动约束。但如果你要指定某个VAUX通道对应哪个物理引脚,就需要在XADC核的配置里设置。
具体操作是:在Vivado的Block Design里双击XADC核,在配置界面里找到Channel Setup,勾选你要用的辅助通道。然后在Constraints里,Vivado会自动生成对应的引脚约束。如果你用的是DRP接口的XADC核,需要在XDC里手动添加:
# XADC专用模拟引脚约束示例 # 注意:这些引脚不需要IOSTANDARD,Vivado会自动处理 set_property PACKAGE_PIN [get_package_pins VP] [get_ports vp_in] set_property PACKAGE_PIN [get_package_pins VN] [get_ports vn_in]但实际上,对于XADC的模拟引脚,更常见的做法是不在XDC里手动约束,而是让Vivado根据XADC核的配置自动分配。你只需要在XADC核的配置界面里选好通道,Vivado会在实现时自动把信号连到对应的物理引脚。
注意:如果你在XDC里手动约束了XADC的模拟引脚,然后又让Vivado自动分配,可能会产生冲突。建议只用一种方式,要么全手动,要么全自动。
3.3 控制信号的引脚约束方法
控制信号如果引出到外部引脚,就需要正常的IO约束。比如你要把adc_convst引到一个外部按键上,约束写法是:
set_property PACKAGE_PIN T14 [get_ports adc_convst] set_property IOSTANDARD LVCMOS33 [get_ports adc_convst]这里的引脚号T14只是示例,实际用哪个引脚取决于你的开发板原理图。对于XC7Z010-1CLG400C,BANK34和BANK35的IO电压通常是3.3V或者1.8V,具体看你的板子设计。约束时IOSTANDARD要和实际电压匹配,否则Vivado会报错。
如果控制信号只在PL内部使用,不引出到芯片引脚,那就不需要任何引脚约束。你只需要在逻辑里正确连接这些信号即可。这种情况下,XADC的配置完全通过DRP接口或者AXI接口在内部完成。
3.4 完整引脚列表速查表
下面这个表整理了XC7Z010-1CLG400C上XADC相关引脚的类型和约束方式。引脚号一列我留空,因为不同开发板的引脚分配可能不同,你需要根据自己板子的原理图填写。
| 引脚类型 | 信号名 | 方向 | 约束方式 | 备注 |
|---|---|---|---|---|
| 专用模拟输入 | VP | 输入 | Vivado自动分配 | 正端,0-1V |
| 专用模拟输入 | VN | 输入 | Vivado自动分配 | 负端,通常接地 |
| 辅助模拟输入 | VAUXP[0] | 输入 | XADC核配置选择 | 通道0正端 |
| 辅助模拟输入 | VAUXN[0] | 输入 | XADC核配置选择 | 通道0负端 |
| 辅助模拟输入 | VAUXP[1] | 输入 | XADC核配置选择 | 通道1正端 |
| 辅助模拟输入 | VAUXN[1] | 输入 | XADC核配置选择 | 通道1负端 |
| 辅助模拟输入 | VAUXP[8] | 输入 | XADC核配置选择 | 通道8正端 |
| 辅助模拟输入 | VAUXN[8] | 输入 | XADC核配置选择 | 通道8负端 |
| 辅助模拟输入 | VAUXP[9] | 输入 | XADC核配置选择 | 通道9正端 |
| 辅助模拟输入 | VAUXN[9] | 输入 | XADC核配置选择 | 通道9负端 |
| 控制信号 | adc_convst | 输入 | 普通IO约束 | 转换启动 |
| 控制信号 | adc_chsel[4:0] | 输入 | 普通IO约束 | 通道选择 |
| 控制信号 | adc_eoc | 输出 | 普通IO约束 | 转换结束 |
| 控制信号 | adc_eos | 输出 | 普通IO约束 | 序列结束 |
| 控制信号 | adc_drdy | 输出 | 普通IO约束 | 数据就绪 |
| 控制信号 | adc_do[15:0] | 输出 | 普通IO约束 | 数据输出 |
| 控制信号 | adc_dclk | 输入 | 普通IO约束 | DRP时钟 |
| 控制信号 | adc_den | 输入 | 普通IO约束 | DRP使能 |
| 控制信号 | adc_dwe | 输入 | 普通IO约束 | DRP写使能 |
| 控制信号 | adc_daddr[6:0] | 输入 | 普通IO约束 | DRP地址 |
| 控制信号 | adc_di[15:0] | 输入 | 普通IO约束 | DRP数据输入 |
这个表里的控制信号方向是以XADC核为参照的。adc_convst、adc_chsel、adc_dclk、adc_den、adc_dwe、adc_daddr、adc_di是输入到XADC核的,adc_eoc、adc_eos、adc_drdy、adc_do是从XADC核输出的。约束时要注意方向,别搞反了。
4. Vivado里配置XADC的完整实操流程
4.1 新建工程和IP核例化
打开Vivado,新建一个工程,器件选xc7z010clg400-1。这个型号在Vivado的器件列表里直接搜“7z010”就能找到。工程建好后,创建一个Block Design,然后在里面添加Zynq Processing System和XADC Wizard两个IP。
Zynq Processing System的配置里,要注意把XADC的时钟源选上。在PS的Clock Configuration里,有个FCLK_CLK0,把它使能并设成50MHz或者100MHz,这个时钟后面要给XADC用。另外在PS-PL Configuration里,把M_AXI_GP0接口使能,这样PS才能通过AXI访问XADC。
XADC Wizard的配置分几个页面。在Basic页面里,Interface Selection选DRP或者AXI。如果选AXI,XADC会自动挂到PS的M_AXI_GP0上,你不需要自己写控制逻辑;如果选DRP,你需要自己在PL里生成DRP时序。对于XC7Z010这种小芯片,如果只是做低速监控,选AXI更省事;如果要高速连续采样,选DRP更灵活。
在Channel Setup页面里,勾选你要用的通道。Startup Channel Selection里可以选VP/VN和几个VAUX通道。Sequencer Mode选Continuous或者Single Channel,取决于你的应用。如果要多通道轮询,选Continuous,然后在Sequence里排好通道顺序。
在Timing Setup页面里,设置转换时钟的频率。XADC的转换时钟(adcclk)范围是26MHz到50MHz,典型值是50MHz。这个时钟可以由PS的FCLK提供,也可以由PL的MMCM生成。注意adcclk和DRP时钟(dclk)是两回事,dclk可以比adcclk慢,但不要超过adcclk的频率。
4.2 时钟配置和DRP时序参数计算
XADC的转换时间计算公式是:转换周期 = (通道数 + 1) × 26个adcclk周期。比如你选了4个通道,adcclk是50MHz,那转换周期就是(4+1)×26/50MHz = 2.6微秒。也就是说每2.6微秒完成一轮4通道的采样,每个通道的采样率是1/2.6微秒 ≈ 384kSPS。
DRP时钟dclk的频率决定了你读取转换结果的速度。dclk的最大频率是adcclk的一半,也就是25MHz。如果你用PS的AXI接口读,AXI的时钟是100MHz,但XADC内部会做跨时钟域处理,你不需要关心dclk的具体频率。
如果你用DRP接口,需要自己生成dclk。dclk的周期要大于等于adcclk周期的2倍。比如adcclk是50MHz(周期20ns),dclk最大25MHz(周期40ns)。实际用的时候建议留点余量,dclk用20MHz左右比较稳。
DRP读写的时序是:先拉高den,同时给出daddr和dwe(读操作为0),然后在dclk的上升沿,XADC采样这些信号。如果是读操作,drdy会在几个周期后拉高,表示do上的数据有效。如果是写操作,dwe拉高,di上给出要写的数据,drdy拉高表示写完成。
4.3 引脚约束文件的编写
在Block Design里配置好XADC后,右键Block Design,选Generate Output Products,然后Create HDL Wrapper。接下来在Constraints里新建一个XDC文件,添加引脚约束。
对于XADC的模拟引脚,如果你在XADC核里已经选了通道,Vivado会在实现时自动分配物理引脚,你不需要在XDC里写。但如果你要指定某个通道对应哪个物理引脚,可以在XDC里用set_property指定。不过更推荐的做法是让Vivado自动分配,因为手动指定容易和XADC核的内部约束冲突。
对于控制信号,如果你把它们引到了外部引脚,就需要在XDC里约束。比如:
# 控制信号引脚约束 set_property PACKAGE_PIN U15 [get_ports adc_convst] set_property IOSTANDARD LVCMOS33 [get_ports adc_convst] set_property PACKAGE_PIN U16 [get_ports adc_eoc] set_property IOSTANDARD LVCMOS33 [get_ports adc_eoc]引脚号U15、U16只是示例,实际用哪个引脚要看你的板子原理图。IOSTANDARD要和BANK电压匹配,XC7Z010的BANK34和BANK35通常支持3.3V、2.5V、1.8V等,具体看你的板子设计。
提示:如果你在实现时遇到“IOSTANDARD not specified”的错误,说明你约束了引脚但没指定电平标准。加上
set_property IOSTANDARD即可。
4.4 生成比特流和硬件验证
约束写好后,依次跑Synthesis、Implementation、Generate Bitstream。如果Implementation变红,通常是时序不满足或者引脚冲突。先看Timing Report,如果WNS是负的,说明时序有问题,需要调整时钟频率或者优化逻辑。如果报引脚冲突,检查XDC里有没有重复约束同一个引脚。
生成比特流后,连接开发板,打开Hardware Manager,Program Device。然后在Vivado的Serial I/O或者SDK里读取XADC的数据。如果你用的是AXI接口,可以在SDK里直接读XADC的寄存器地址;如果你用的是DRP接口,需要在PL逻辑里把转换结果存到BRAM或者FIFO里,然后通过PS读出来。
我实测下来,用AXI接口最省事,PS端直接读寄存器就能拿到转换结果。但AXI接口的延迟比DRP大,如果你要做高速闭环控制,DRP更合适。对于XC7Z010这种小芯片,PL资源有限,用AXI接口可以省下不少逻辑资源。
5. 常见问题排查与避坑经验实录
5.1 采样值跳变或者全是零
这是最常见的问题。采样值全是零,通常是因为XADC的时钟没接上,或者adcclk的频率超出了范围。检查PS的FCLK_CLK0有没有使能,频率是不是在26MHz到50MHz之间。如果时钟没问题,检查XADC核的复位信号,XADC需要一个复位脉冲来初始化,复位没给或者复位时间太短都会导致转换不工作。
采样值跳变,通常是参考电压不稳或者模拟输入没有滤波。XADC的内部参考电压精度是±1%,如果你对精度要求高,需要外接精密参考电压。模拟输入端要加RC低通滤波,截止频率根据你的信号频率来定。我一般用1kΩ电阻加100nF电容,截止频率大概1.6kHz,对大多数低速采样够用了。
还有一个容易被忽略的点:XADC的模拟输入引脚在芯片内部有保护二极管,如果输入电压超过1V,二极管会导通,导致采样值异常。所以外部信号一定要先分压到0-1V范围内。分压电阻的精度直接影响采样精度,建议用1%精度的电阻。
5.2 Vivado实现报错和时序不满足
Vivado Implementation变红,常见原因有几个。一是引脚约束冲突,比如同一个引脚被约束了两次,或者XADC的模拟引脚被手动约束了但和XADC核的内部约束冲突。解决方法是检查XDC文件,把重复的约束删掉,模拟引脚让Vivado自动分配。
二是时序不满足。XADC的DRP接口对时序有要求,dclk的周期不能太短。如果你用50MHz的adcclk,dclk最大25MHz,但实际用的时候建议降到20MHz以下,留足余量。如果时序报告里显示dclk相关的路径WNS是负的,降低dclk频率或者加流水线寄存器。
三是XADC核的时钟域处理有问题。XADC的adcclk和dclk是异步的,如果你在PL逻辑里直接跨时钟域读do,会有亚稳态问题。正确做法是用drdy信号做握手,drdy拉高后再读do,或者用双触发器同步。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方法 |
|---|---|---|---|
| 采样值全是零 | adcclk未连接或频率不对 | 检查FCLK_CLK0是否使能 | 使能FCLK_CLK0,设成50MHz |
| 采样值全是零 | XADC复位未释放 | 检查复位信号 | 给XADC一个至少100ns的复位脉冲 |
| 采样值跳变 | 参考电压不稳 | 测量VREFP/VREFN | 外接精密参考或加滤波电容 |
| 采样值跳变 | 模拟输入未滤波 | 检查输入端 | 加RC低通滤波 |
| 采样值超范围 | 输入电压超过1V | 测量输入电压 | 加分压电路 |
| Implementation变红 | 引脚约束冲突 | 检查XDC文件 | 删除重复约束 |
| Implementation变红 | 时序不满足 | 看Timing Report | 降低dclk频率 |
| DRP读不到数据 | drdy未拉高 | 用ILA抓drdy | 检查DRP时序 |
| DRP读不到数据 | daddr错误 | 检查DRP地址 | 查UG480的寄存器地址表 |
| AXI读不到数据 | AXI接口未使能 | 检查PS配置 | 使能M_AXI_GP0 |
5.4 独家避坑技巧
第一个技巧:XADC的模拟输入引脚在不用的时候,不要悬空。悬空的引脚会引入噪声,影响其他通道的采样。不用的时候接地或者接一个固定的参考电压。
第二个技巧:如果你用多个VAUX通道,通道之间的串扰是不可避免的。降低串扰的方法是增加采样间隔,或者在每个通道的输入端加缓冲运放。我实测下来,相邻通道的串扰大概在-60dB左右,对大多数应用够用了。
第三个技巧:XADC的温度测量通道可以用来做芯片温度监控。温度传感器的精度是±4°C,虽然不高,但用来做过热保护足够了。读温度的方法是访问XADC的寄存器0x00,转换公式在UG480里有。
第四个技巧:Vivado的XADC核在配置时,有个“Enable Calibration”选项。勾上后,XADC会在上电时自动校准,提高采样精度。但校准需要额外的时钟周期,如果你对启动时间有要求,可以关掉校准,手动在初始化后触发一次校准。
第五个技巧:如果你在SDK里读XADC数据,注意字节序。XADC的输出是16位的,高12位是有效数据,低4位是0。读出来后要右移4位才能得到实际的12位采样值。
6. 从XADC到系统级数据采集的扩展思路
6.1 多通道轮询和DMA传输
XC7Z010的XADC支持最多8对辅助通道,如果你要做多路数据采集,可以用序列器自动轮询。在XADC核的配置里,把Sequencer Mode设成Continuous,然后在Sequence里排好通道顺序。XADC会按照你设定的顺序依次转换每个通道,转换结果通过DRP或者AXI读出。
如果采样率要求高,可以用DMA把XADC的数据直接搬到DDR里。在Zynq上,可以用PS的DMA控制器,把AXI XADC的数据流通过DMA搬到内存。这样CPU不需要干预,可以专心做数据处理。配置DMA的方法是:在Block Design里添加AXI DMA IP,把XADC的AXI Stream接口连到DMA的S2MM端口,然后DMA的M_AXI_MM2S连到PS的DDR控制器。
6.2 采样精度提升的硬件调理方法
XADC的12位分辨率理论精度是1/4096,但实际精度受参考电压、输入噪声、量化误差等因素影响。要提升精度,硬件上可以做几件事。一是用外部精密参考电压芯片,比如REF3012或者ADR4525,精度可以做到0.1%以内。二是输入端加仪表放大器,把微弱信号放大到0-1V范围,同时提高输入阻抗。三是加多阶RC滤波或者有源滤波,把带外噪声滤掉。
软件上可以做过采样和平均。XADC的采样率是1MSPS,如果你只需要低速采样,可以连续采多次然后取平均,等效分辨率可以提高。比如采16次取平均,等效分辨率可以提高2位,到14位。但要注意,过采样要求输入信号在采样期间保持稳定,否则平均会引入误差。
6.3 在PS端读取XADC数据的代码示例
如果你用的是AXI XADC核,在SDK里可以直接读寄存器。XADC的寄存器基地址在xparameters.h里定义,通常是XPAR_XADC_WIZ_0_BASEADDR。读VP/VN通道的代码大概是这样:
#include "xparameters.h" #include "xil_io.h" #define XADC_BASEADDR XPAR_XADC_WIZ_0_BASEADDR #define XADC_VP_OFFSET 0x200 #define XADC_VN_OFFSET 0x204 u32 read_xadc_channel(u32 offset) { u32 raw = Xil_In32(XADC_BASEADDR + offset); return (raw >> 4) & 0xFFF; // 取高12位 } int main() { u32 vp_value = read_xadc_channel(XADC_VP_OFFSET); u32 vn_value = read_xadc_channel(XADC_VN_OFFSET); // 电压计算:value / 4096 * 1.0V float vp_voltage = (float)vp_value / 4096.0f; float vn_voltage = (float)vn_value / 4096.0f; return 0; }这段代码里,XADC_VP_OFFSET和XADC_VN_OFFSET是XADC寄存器的偏移地址,具体值查UG480。读出来的原始数据右移4位得到12位有效值,然后除以4096乘以1V得到实际电压。
注意:XADC的输入范围是0到1V,如果你外部信号是0到3.3V,需要先分压。分压比是3.3:1,用两个电阻,比如10kΩ和4.7kΩ,分压后的电压范围是0到1.06V,接近1V但略超。更安全的做法是用10kΩ和3.3kΩ,分压后是0到0.825V,留足余量。
6.4 后续扩展方向
XADC只是数据采集的第一步。采到的数据可以进一步处理,比如做FFT分析、滤波、阈值报警等。XC7Z010的PL资源虽然不多,但跑一个简单的FIR滤波器或者FFT核还是够的。你可以把XADC的数据流送到FIR核做低通滤波,然后再送到PS做后续处理。
另一个扩展方向是用XADC做闭环控制。比如你采集一个电压信号,根据采样值调整PWM输出,做成一个简单的稳压电源或者电机控制器。XC7Z010的PL里有PWM核,PS里跑控制算法,XADC做反馈,整个闭环可以在单芯片上完成。
我在实际项目里用XC7Z010做过一个多路电压监控模块,8个VAUX通道轮流采样,采样率每通道10kSPS,数据通过DMA搬到DDR,PS端做平均值和阈值判断。整个系统跑下来,PL资源占用不到30%,PS的CPU占用率也很低。这套方案对于工业设备的状态监控来说完全够用了。
踩过几次坑之后,我的体会是:XADC的配置本身不复杂,难的是细节。时钟、复位、参考电压、输入调理,任何一个环节出问题都会导致采样异常。建议第一次用的时候,先用VP/VN通道做单通道测试,确认基本功能正常后再扩展到多通道。另外,Vivado的ILA是个好东西,抓一下drdy和do的波形,很多问题一眼就能看出来。