ARTICLE DETAIL

资讯详情

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

7系列FPGA XADC实战:DRP与AXI4-Lite接口配置及避坑指南

7系列FPGA XADC实战:DRP与AXI4-Lite接口配置及避坑指南 1. 从一次温度采集异常说起XADC到底解决什么问题前阵子帮朋友排查一块7系列FPGA板子的温度采集问题现象很典型逻辑里读出来的芯片温度一直卡在某个固定值不动偶尔跳变一次又回到原点。他一开始怀疑是传感器坏了换了板子还是一样又怀疑是I2C总线时序问题折腾了两天没结果。最后我让他把XADC的DRP接口时序抓出来看问题一目了然——他读的是同一个通道的缓存寄存器根本没触发新的转换读到的永远是上一次的旧数据。这个案例其实暴露了很多人在用XADC时的通病把它当成一个普通的读寄存器外设忽略了它内部是一套带转换时序、带状态机、带通道复用的模拟采集系统。XADCXilinx Analog-to-Digital Converter是集成在7系列FPGA和Zynq-7000系列里的一个硬核模块它不需要你外挂ADC芯片就能直接采集芯片内部的温度、各路供电电压也能通过外部模拟输入通道采集板级模拟信号。对于做电源监控、温度保护、模拟量采集这类需求它能省掉一颗外部ADC和一堆外围电路性价比很高。但集成不等于简单。XADC有两套完全不同的访问接口一套是DRPDynamic Reconfiguration Port直接挂在FPGA逻辑侧适合纯逻辑工程快速读取另一套是AXI4-Lite接口通过AXI总线挂到MicroBlaze或Zynq的PS端适合软硬协同的场景。这两套接口的配置方式、时序要求、寄存器映射都不一样选错了或者配错了就会出现上面那种读出来不动的怪现象。这篇内容我打算把XADC IP核从配置到接口实战的完整链路讲透重点放在三个地方IP核配置里那些容易忽略但影响巨大的选项、DRP和AXI4-Lite两套接口的实际用法与取舍、以及实测中踩过的坑和排查思路。不管你是刚接触7系列FPGA的新手还是用过XADC但总觉得不太对劲的老手应该都能从里面找到点有用的东西。关键词里提到的Vivado、XADC、IP核、AXI4-Lite、DRP我会在对应章节里逐一展开尽量做到看完就能上手配、上手调。2. XADC IP核配置界面里那些决定成败的选项打开Vivado的IP Catalog搜XADC出来的就是XADC Wizard。这个配置界面看着选项不多但每一项背后都对应着硬件行为配错了轻则读数不准重则整个IP不工作。我按配置页的顺序把几个关键项拆开讲。2.1 基础配置页接口类型与采样模式的选择逻辑第一页最上面是Interface Selection三个选项DRP、AXI4-Lite、None。这里的选择直接决定了你后面怎么访问XADC。选DRPIP核会暴露一组DRP端口di、do、daddr、den、dwe、drdy等你在逻辑里自己写状态机去读写。适合纯FPGA逻辑工程不需要处理器。选AXI4-LiteIP核会封装成一个AXI从设备挂到AXI互联矩阵上由MicroBlaze或Zynq PS通过寄存器访问。适合软硬协同代码里直接读写地址就行。选None一般不用除非你只想用XADC的告警输出alarm而不需要读数据。我个人的经验是如果你的工程里有MicroBlaze或者用的是Zynq优先选AXI4-Lite软件侧读写比写DRP状态机省事太多如果是纯逻辑的Artix-7或者Kintex-7工程没有处理器那就老老实实选DRP自己写个简单的读取状态机也不复杂。往下是Startup Channel Selection这里勾选的是上电后自动循环采样的通道。默认会勾选温度Temperature和几路内部供电VCCINT、VCCAUX、VCCBRAM等。这里有个细节如果你只关心外部模拟输入可以把内部通道全部取消勾选这样序列器只扫你需要的通道单轮采样周期更短读取延迟更低。但如果你要做芯片健康监控那内部通道一个都别关。Sequencer Mode这一项很多人直接默认其实值得说一下。它有两个模式Continuous连续循环采样和Single Channel单通道。Continuous模式下XADC会自动按你勾选的通道顺序循环转换你随时读到的都是最近一次转换的结果Single Channel模式下你需要通过控制寄存器手动指定当前采样的通道。绝大多数场景用Continuous就够了只有在你需要精确控制某个通道采样时刻的时候才用Single Channel。2.2 告警与平均被低估的读数稳定性开关配置页里有一块是Alarm设置可以设置温度上限、VCCINT上下限等告警阈值。这些告警会通过IP核的alarm输出端口或者状态寄存器反映出来。做温度保护逻辑的时候这个功能很实用——你不需要在逻辑里自己比较阈值直接用电平信号触发保护动作就行。但真正影响读数质量的是Averaging平均设置。XADC支持对每个通道的转换结果做平均可选不平均、平均16次、平均64次、平均256次。这个设置的本质是用采样时间换精度平均次数越多读数越稳但单次更新周期越长。我实测过一组数据用内部温度通道在室温环境下平均次数读数波动范围单通道更新周期约不平均±3~5 LSB最短16次±1~2 LSB约16倍64次±1 LSB以内约64倍256次基本不跳约256倍提示如果你做的是温度监控这种慢变量直接上64次或256次平均读数稳得让你怀疑是不是坏了。但如果你要采的是快速变化的模拟信号平均次数必须降下来否则信号直接被平滑没了。这里有个容易踩的坑平均设置是全局的不是单通道的。也就是说你没法给温度通道设256次平均、给外部通道设不平均。所以如果你的工程里既有慢变量又有快变量得在读数稳定性和响应速度之间做个折中或者干脆用两套采样策略分时切换。2.3 时钟与校准为什么你的读数总差那么一点XADC需要一个参考时钟配置页里叫DCLK典型值是50MHz范围是8MHz到250MHz。这个时钟不是随便给的它直接决定了XADC的转换时序。DCLK频率越高单次转换越快但功耗也越高。一般50MHz是个稳妥的选择除非你有特殊的低延迟需求。还有一个隐藏很深的选项是Calibration。XADC内部有校准机制上电后会做一次自校准。如果你在配置里禁用了校准或者校准还没完成就开始读数据读出来的值会明显偏差。我遇到过有人为了加快启动把校准关了结果温度读数差了十几度查了半天才发现是这个原因。注意XADC上电后需要一段校准时间典型值是几百微秒。如果你在FPGA配置完成后立刻读XADC建议先等一小段时间或者读状态寄存器的校准完成位确认后再开始采集。配置页最后是Summary会列出你当前的配置摘要。我习惯在这里截个图存档后面调试的时候对照着看省得忘了当初配了什么。3. DRP接口实战纯逻辑工程里怎么把数据读出来选DRP接口的工程IP核会暴露一组端口核心的几个是daddr[6:0]DRP地址7位指定要读写的寄存器di[15:0]写入数据do[15:0]读出数据denDRP使能高有效dwe写使能高写低读drdy数据就绪读操作完成后拉高一个周期dclkDRP时钟和XADC的DCLK是同一个DRP的读写时序不复杂但有几个点必须卡准否则就是读不到或者读到错的数据。3.1 DRP读时序的关键三步与状态机写法DRP读操作分三步把要读的寄存器地址放到daddr上同时拉高dendwe保持低电平。保持den高一个dclk周期然后拉低。等待drdy拉高此时do上的数据就是读出的结果。听起来简单但实际写状态机的时候很多人会在den拉高几个周期和drdy什么时候来这两个点上出错。我一般用三段式状态机IDLE → ASSERT → WAIT → DONE。// DRP读状态机简化示例 localparam IDLE 2b00; localparam ASSERT 2b01; localparam WAIT 2b10; localparam DONE 2b11; reg [1:0] state; reg [6:0] daddr_r; reg den_r, dwe_r; always (posedge dclk) begin case(state) IDLE: begin if (start_read) begin daddr_r target_addr; den_r 1b1; dwe_r 1b0; state ASSERT; end end ASSERT: begin den_r 1b0; // den只保持一个周期 state WAIT; end WAIT: begin if (drdy) begin data_out do; // 锁存读出数据 state DONE; end end DONE: begin state IDLE; end endcase end这里的关键是den只拉高一个dclk周期。我见过有人把den一直拉高结果DRP接口反复触发读操作drdy一直跳数据根本锁不住。另外drdy是脉冲信号不是电平信号它只拉高一个周期所以必须在WAIT状态里用边沿或者电平判断及时锁存do。3.2 通道寄存器地址映射别读错了地方DRP的地址空间里每个通道对应一个固定的地址。常用的几个通道DRP地址十六进制说明温度0x00芯片结温VCCINT0x01内核供电VCCAUX0x02辅助供电VCCBRAM0x06BRAM供电外部通道00x10VP/VN差分对外部通道10x11VAUXP[0]/VAUXN[0].........外部通道160x20VAUXP[15]/VAUXN[15]这里有个大坑温度通道的地址是0x00但读出来的数据格式和电压通道不一样。温度是12位有符号数单位是摄氏度换算公式是温度 (读出值 4) * 503.975 / 4096 - 273.15而电压通道是12位无符号数换算公式是电压 (读出值 4) * 3.0 / 4096注意那个 4因为XADC的16位寄存器里高12位才是有效数据低4位是状态位或者保留位。很多人直接拿16位数据去算结果差了一大截。提示如果你读出来的温度值是个很大的正数或者负数八成是忘了做有符号数处理和 4。先检查数据格式再怀疑硬件。3.3 连续读取的节奏控制什么时候读才不会拿到旧数据在Continuous模式下XADC的序列器在后台不停循环采样。你通过DRP读某个通道的寄存器时读到的是最近一次该通道转换完成的结果。这里就有个节奏问题如果你读得太快可能两次读到的是同一次转换的结果如果你读得太慢数据可能已经更新了好几轮。我的做法是根据平均次数和通道数估算单轮采样周期然后以略大于这个周期的间隔去读。比如你勾选了5个通道每个通道平均16次DCLK是50MHz那么单通道转换时间大约是单次转换约 26个DCLK周期含平均开销 16次平均 ≈ 416个DCLK周期 ≈ 8.32us 5个通道一轮 ≈ 41.6us所以你每隔50us左右读一次基本能保证每次读到的都是新数据。如果你不管节奏用10MHz的时钟去读那读到的全是重复值看起来就像数据不动。4. AXI4-Lite接口软硬协同场景下的寄存器访问方式如果你用的是Zynq或者带MicroBlaze的工程AXI4-Lite接口会省事很多。IP核被封装成一个AXI从设备你只需要在Vivado里把它挂到AXI互联矩阵上分配好地址然后在软件里读写对应偏移的寄存器就行。4.1 AXI4-Lite寄存器映射与地址偏移XADC的AXI4-Lite接口把DRP的地址空间映射到了一组32位寄存器上。每个DRP地址对应一个32位寄存器低16位是数据高16位保留。常用的偏移地址寄存器偏移地址对应DRP地址说明温度0x0000x00结温VCCINT0x0040x01内核电压VCCAUX0x0080x02辅助电压外部通道00x0400x10VP/VN外部通道10x0440x11VAUX[0]控制寄存器0x3000x40序列器控制状态寄存器0x3040x41状态标志在软件里假设你分配的基地址是0x44A00000那么读温度就是#define XADC_BASE 0x44A00000 #define XADC_TEMP (XADC_BASE 0x000) u32 raw *(volatile u32*)XADC_TEMP; float temp ((raw 4) 0xFFF) * 503.975 / 4096.0 - 273.15;注意这里我用了(raw 4) 0xFFF先右移4位再取低12位确保拿到的是有效数据。温度是有符号的但在实际芯片温度范围内一般-40到125度12位有符号数的高位符号位处理要小心。如果温度是负的raw 4之后需要做符号扩展。4.2 软件侧的读取节奏与中断配合AXI4-Lite接口的好处是软件读写很直观但坏处是软件不知道XADC什么时候更新了数据。如果你在软件里死循环读读到的可能是旧值如果你读得太慢又浪费了XADC的采样能力。两种做法轮询方式软件定时读间隔根据采样周期定。简单但占用CPU。中断方式XADC可以配置在转换完成时产生中断通过IP核的中断输出软件在中断服务程序里读。效率高但配置稍复杂。我一般用轮询就够了因为XADC采的都是慢变量没必要上中断。轮询间隔设个1ms对CPU来说毫无压力。注意AXI4-Lite的读写是有延迟的一次读操作可能需要几个时钟周期才能返回数据。如果你在软件里连续读多个通道建议每次读之间加一点间隔或者用非阻塞方式读避免总线拥塞。4.3 DRP与AXI4-Lite的取舍什么场景选哪个这两套接口没有绝对的好坏关键看你的工程架构对比项DRPAXI4-Lite适用场景纯逻辑工程带处理器工程访问方式逻辑状态机软件读写资源占用少多AXI互联灵活性高可精确控制时序中受总线延迟影响调试难度较高需抓时序较低软件打印即可读取速度快单周期访问较慢总线开销如果你的工程里已经有MicroBlaze或Zynq那AXI4-Lite是首选软件调试比抓逻辑时序舒服太多。如果你是纯逻辑工程或者对读取时序有精确要求那就用DRP。我做过一个电源监控项目用的是Artix-7纯逻辑DRP状态机写了不到100行跑得很稳。5. 实测中踩过的坑与排查链路XADC用起来不难但坑不少。我把这几年踩过的、见过的坑整理一下按排查链路的形式呈现方便你遇到问题时对照着查。5.1 读数恒定不变从通道地址查到采样使能这是最常见的现象读数卡在一个值不动。排查顺序确认读的是正确的通道地址。温度是0x00VCCINT是0x01别读串了。确认DRP读时序正确。用ILA抓den、drdy、do看drdy有没有正常脉冲。如果drdy一直不拉高说明DRP读操作根本没触发。确认XADC的序列器在跑。读状态寄存器DRP地址0x41看序列器忙标志位。如果序列器没启动那所有通道的数据都不会更新。确认平均次数和读取节奏匹配。如果你设了256次平均却每10us读一次那读到的全是同一轮的数据。我遇到的那次读数不动最后查出来是第2条den信号被逻辑里的其他条件一直拉低DRP读操作压根没发出去。用ILA一抓就看到了den全程低电平。5.2 温度读数偏差大校准、格式、参考电压三连查温度读数偏差超过5度基本是这三个原因之一校准未完成上电后立刻读校准还没做完。等几百微秒再读。数据格式处理错误忘了 4或者没做有符号数处理。参考电压不准XADC的内部参考电压有精度范围如果你用外部参考检查外部参考电压是否稳定。我建议在逻辑里加一个简单的校准完成检测读状态寄存器的校准完成位确认后再开始采集。软件侧也一样初始化时先等校准完成。5.3 外部通道读数跳变模拟前端的锅还是数字接口的锅外部模拟通道读数跳变先别急着怀疑XADC。排查顺序检查模拟输入端的滤波。XADC的采样保持电路对输入阻抗有要求如果前端阻抗太高采样电容充不满读数就会跳。加个RC滤波或者用运放做缓冲。检查VP/VN和VAUX的接法。差分输入和单端输入的接法不一样接错了读数完全不对。检查DCLK质量。DCLK抖动太大会影响转换精度用示波器看一下时钟质量。检查电源噪声。模拟供电和数字供电要分开地平面要完整。我做过一个外部电压采集的项目读数一直跳最后发现是前端分压电阻太大1MΩ级别XADC的采样电容充不满。换成10kΩ级别的分压电阻读数立刻就稳了。5.4 综合报错与实现失败XADC相关的DRC和时序问题XADC IP核在综合和实现阶段也可能报错常见的有DRC RTSTAT-2这个报错通常和时钟资源有关检查DCLK是不是走了全局时钟缓冲。时序不满足DRP接口的时序约束没加对或者DCLK频率太高。检查XDC里的时钟约束。IP核版本不匹配Vivado升级后旧工程的XADC IP核可能需要重新生成。提示XADC的DCLK一定要走BUFG不要用普通布线资源。我见过有人把DCLK从普通IO引进来直接接XADC结果时序一塌糊涂读数全是乱的。6. 几个让XADC用起来更顺手的实战技巧最后分享几个我在实际项目里总结的小技巧都是文档里不太会写、但用起来很实在的东西。技巧一用ILA抓DRP接口比看代码快十倍。调试DRP的时候别一行行看状态机代码直接在Vivado里例化一个ILA把daddr、den、dwe、drdy、do都抓上。触发条件设成den上升沿一抓就能看到完整的读时序哪里不对一目了然。技巧二温度换算用整数运算省资源。如果你在逻辑里做温度换算浮点运算会消耗大量DSP资源。可以用定点数近似温度 ≈ (raw 4) * 123 / 1000 - 273这个近似公式在0到100度范围内误差小于1度足够用了。技巧三外部通道不用的就关掉。配置XADC的时候只勾选你实际用到的通道。不用的通道关掉序列器扫描更快单轮采样周期更短读取延迟更低。我见过有人把16个外部通道全勾上结果一轮采样要几百微秒读数延迟大得没法做实时控制。技巧四AXI4-Lite的基地址别写死。在Vivado里分配地址后软件里用xparameters.h里的宏别手写地址。工程重新生成后地址可能会变写死的地址一改就崩。技巧五XADC的告警输出可以直接接逻辑。如果你做温度保护不用在软件里比较阈值直接把XADC的alarm输出接到逻辑里超温直接触发风扇或者降频。响应速度比软件轮询快得多。技巧六多通道读取用轮询表别用一堆if-else。如果你要读多个通道用一个数组存地址循环读代码简洁也好维护。我一般定义一个通道地址表读的时候遍历一遍数据存到对应的数组里。// 通道地址轮询表 localparam CH_NUM 4; reg [6:0] ch_addr [0:CH_NUM-1]; initial begin ch_addr[0] 7h00; // 温度 ch_addr[1] 7h01; // VCCINT ch_addr[2] 7h02; // VCCAUX ch_addr[3] 7h10; // 外部通道0 end这样加通道、减通道只改表就行状态机不用动。XADC这个IP核说复杂不复杂说简单也不简单。核心就那几件事配置选对接口、时序卡准、数据格式处理对、读取节奏匹配上。把这几点做到位它就是一个很稳的片上模拟采集模块。我现在的项目里只要用到7系列FPGA基本都会把XADC用起来省一颗外部ADC不说还能顺便监控芯片自己的健康和供电状态一举两得。
返回列表