FPGA内置XADC从入门到实战:硬件结构、配置与温控案例

发布时间:2026/10/7 17:19:51
FPGA内置XADC从入门到实战:硬件结构、配置与温控案例 做FPGA项目的朋友几乎都会遇到这种情况板子莫名其妙发热却说不清是哪一路供电出了问题想采集一个慢速传感器信号又不想为这点需求外挂一颗ADC上电后想确认芯片工作是否正常只能拿万用表去量麻烦而且容易短路。Xilinx 7系列FPGA和Zynq-7000系列内部集成了一颗名为XADC的模数转换器双12位、最高1MSPS温度传感器和电源传感器都做在片内用对了能省掉一颗ADC芯片和一大堆外围电路。这篇文章我会从XADC的硬件结构、配置方法、数据换算讲起最后用一个温度监控加温控风扇的完整案例收尾让没接触过XADC的读者也能照着做出来。1. XADC到底是什么硬件一块藏在FPGA芯片里的模拟采集单元1.1 双12位ADC、1MSPS采样率与17对外部输入很多刚接触FPGA的人容易把XADC和“IP核”混为一谈以为它和RAM、FIFO一样是生成出来的软核。实际上XADC是7系列FPGA内部固化的模拟硬核只要芯片上电它就在工作不需要加载配置文件。这一点意义很大FPGA配置失败或者逻辑没跑起来的时候XADC依然能汇报芯片内部的温度和电压。从指标上看XADC内部集成了两个独立的12位ADC最高采样率1MSPS。两个ADC的好处是可以同时采集两路模拟信号比如一路采电压、一路采电流互不干扰。外部模拟输入总共有17对差分通道一对专用的VP/VN16对VAUXP[15:0]/VAUXN[15:0]。专用那对VP/VN不需要额外配置就能直接接模拟信号而16对辅助通道需要先在配置寄存器里使能对应通道否则引脚会处于高阻状态。我见过不少人第一次拿到原理图看到VAUXP/VAUXN那么多引脚不知道是干嘛的干脆全部悬空。实际上如果不用外部模拟输入这些引脚确实可以悬空但要在XADC配置里把对应通道关闭否则会有微小的漏电流对整体功耗和信号完整性都不是好事。1.2 内置传感器结温与三路电源电压的采样原理XADC最有价值的一点是它在芯片内部集成了温度传感器和电源传感器。温度传感器实测的是FPGA内部硅片的结温Junction Temperature不是封装表面的温度更不是散热片的温度。这对判断芯片是否过热非常关键——散热片测出来可能只有40℃但结温可能已经逼近85℃了。电源传感器则分别监控VCCINT内核电压、VCCAUX辅助电压和VCCBRAM块RAM电压。这三个电压是FPGA正常工作的生命线任何一个异常都可能引发时序问题或者偶发故障。以前排查这类问题只能拿示波器去量PCB上的引脚但引脚上的电压和芯片内部的电压其实是有误差的因为经过了封装引线、PCB走线存在压降。XADC直接测量的是芯片内部的电压反映的是芯片真正“吃到”的电压。这里有个很实用的小知识XADC在上电后、FPGA配置完成之前就已经开始自发转换了而且不需要用户逻辑干预。Vivado的Hardware Manager里打开任意一个7系列器件都能直接看到当前Die Temperature和VCCINT、VCCAUX等读数原理就是JTAG口在后台访问XADC。我带新板子习惯上电后先看一眼这个页面温度和电压正常才往下走很多时候能第一时间发现焊接短路、电源没起来这类低级问题。1.3 报警比较器硬件帮你盯着阈值除了把模拟量转成数字量XADC内部还有一组模拟比较器。你可以预先设定温度上限、电压上限、电压下限一旦某路测得的数值越过阈值ALM引脚或者状态寄存器的标志位会立即置位完全不需要CPU或FPGA逻辑去轮询。报警输出可以是8个独立的ALM引脚也可以汇总成一个中断信号。报警功能在设计上有个很巧妙的地方它天然带滞回。XADC的报警阈值寄存器区分“上限触发”和“下限解除”也就是说当温度超过85℃时触发高温报警必须降到80℃以下才解除报警。这个滞回窗口是硬件的不是软件实现的不会出现温度在临界点抖动导致报警反复打开关闭的问题。做板级保护的时候这个特性非常实用。2. 两种配置路径图形化IP核与裸机DRP直读2.1 XADC Wizard IP核适合快速搭原型Vivado里搜索“XADC Wizard”就能找到XADC的配置IP核。这个IP核最大的好处是图形化所有配置项一目了然适合快速搭原型或者不太熟悉XADC寄存器细节的人。IP核配置界面里有几个关键选项值得注意Interface可以选择无接口仅输出、DRP接口或者AXI4-Lite接口。无接口模式适合只要报警输出、不需要读数据的场景DRP接口适合逻辑自己控制读写时序AXI4-Lite接口适合Zynq或者带软核的系统。Channel Sequencer选择要采集的通道。这里可以选择自动扫描所有使能通道也可以配置成固定只采某几个通道。Averaging设置均值采样。这个选项对提高测量精度很有用后面会详细说。Alarm设置各通道的报警阈值。IP核里可以直接填物理值比如温度85℃VCCINT上限1.2V工具会自动帮你换算成寄存器值省去手算的麻烦。Sampling Rate如果需要精确控制采样率可以在这里设置外部采样时钟或者分频系数。用IP核生成的XADC模块输出端会有drdy、do、eoc、eos这些信号。drdy拉高表示读数据有效eoc表示单通道转换完成eos表示整个通道序列扫描完成。把这些信号接出来一个最简单的温度读取模块就搭好了。2.2 不依赖IP核XADC原语与DRP寄存器直接操作IP核虽然方便但它会占用一些逻辑资源而且对某些需要精细控制采样时序的场景反而不灵活。如果你不想用IP核可以直接例化XADC原语然后通过DRP接口读写寄存器。这里要澄清一个很容易混淆的问题寄存器地址。网上很多例程里写“读温度寄存器地址是0x2000”但XADC原语的DADDR端口只有7位地址范围是0x00到0x6B。0x2000是AXI4-Lite接口下温度寄存器的偏移地址而原语DRP接口下温度寄存器就是7h00。在XADC原语的DRP空间中常用寄存器地址如下地址功能0x00温度测量结果0x01VCCINT测量结果0x02VCCAUX测量结果0x03VCCBRAM测量结果0x04VP/VN外部输入测量结果0x05VAUX0测量结果0x06VAUX1测量结果往后依次递增0x40配置寄存器0采样率、校准等0x41配置寄存器1通道使能等0x42配置寄存器2模拟输入量程等0x50温度上限报警阈值0x51温度下限报警阈值DRP接口的读写时序和块RAM很接近拉高DEN读操作下DWE置0等一个周期后DO输出数据DRDY拉高表示数据有效写操作时DEN和DWE同时拉高给出地址和数据等待一次握手完成。2.3 一段可直接用的Verilog温度读取代码下面这段代码是我在实际项目里用的最小温度读取模块状态机非常简洁适合理解DRP读取流程。module xadc_temp_reader( input wire clk, input wire rst_n, output reg [15:0] temp_raw, output reg data_valid ); // 需要通过原语例化得到这些信号 wire den; wire dwe; wire [6:0] daddr; wire [15:0] do; wire drdy; reg [15:0] di; reg dwe_i; reg [6:0] daddr_i; reg [1:0] state; localparam S_IDLE 2d0; localparam S_READ 2d1; localparam S_DONE 2d2; always (posedge clk or negedge rst_n) begin if (!rst_n) begin state S_IDLE; dwe_i 1d0; daddr_i 7d0; temp_raw 16d0; data_valid 1b0; end else begin case (state) S_IDLE: begin dwe_i 1b0; daddr_i 7h00; // 温度寄存器 state S_READ; end S_READ: begin if (drdy) begin temp_raw do; data_valid 1b1; state S_DONE; end end S_DONE: begin data_valid 1b0; state S_IDLE; // 连续循环读取 end default: state S_IDLE; endcase end end assign den (state S_IDLE); assign dwe dwe_i; assign daddr daddr_i; assign di 16d0; endmodule实际使用时还需要例化XADC原语把上面模块的den、dwe、daddr、do、drdy接到原语对应端口上。原语例化时可以带上INIT参数预设寄存器值比如把序列寄存器配成只扫描温度通道可以省去工作时动态配置的麻烦。3. 从12位原始码到真实物理量换算、滤波与校准3.1 温度和电压换算公式背后的标度因子拿到DO端口输出的16位数据后低12位才是真正的ADC码值。XADC的转换结果以12位二进制补码形式存储温度寄存器0x00里读到的值换算成摄氏度的公式是温度(℃) ADC码值 × 503.975 / 4096 - 273.15这个公式里503.975是温度传感器的满量程范围单位K4096对应12位ADC的满量程码值273.15是绝对零度。举个例子室温25℃时ADC码值大约等于(25273.15)×4096/503.975≈2424读出来是0x0978左右。电压通道的换算更直观电压(V) ADC码值 × 3.0 / 4096对于VCCINT、VCCAUX、VCCBRAM满量程电压是3V12位分辨率下每个LSB对应约0.732mV。VCCINT的典型值是1.0V左右对应码值大约是1365。如果你对应的是外部输入通道还要注意量程配置。XADC支持单极性和双极性输入量程也有0~1V和0~3V两种选项配置寄存器0x42里的对应位决定了当前量程。改量程之后换算公式里的满量程电压要跟着换这是新手最容易忽略的地方。3.2 数据一直在跳是正常的单次采样与均值滤波XADC单次采样的结果其实没那么“稳”尤其是温度通道连续两次读之间跳个几度都正常。这是因为ADC转换本身有量化噪声内部传感器也有一定的纹波加上芯片功耗波动导致结温小范围跳动。如果你把单次采样结果直接拿去做门限判断很可能出现风扇转一阵停一阵、报警灯乱闪的尴尬现象。解决思路不外乎两种。第一种是利用XADC IP核里的Averaging功能工具会自动对多次采样做平均再输出结果等效于提高了分辨率、抑制了噪声。Averaging可以配置成16次、64次甚至256次平均数值越大越稳定但响应速度也越慢。第二种是自己做软件滤波。我习惯在逻辑里做一个16周期的滑动平均每次读到的原始值先放进移位寄存器取平均后再参与运算always (posedge clk) begin if (data_valid) begin sum sum temp_raw - temp_buf[0]; temp_buf {temp_buf[14:0], temp_raw}; end end这个办法不需要额外的乘法器只是用两个周期做加法和减法资源占用非常小。3.3 系统偏差需要校准为什么板子上读出来的电压总是偏一点实际做板子的人会发现XADC读出来的VCCINT和万用表量内核电源引脚的结果不完全一样通常差个一二十毫伏。这并不一定是XADC不准更多是测量点不同引入的误差。XADC测的是芯片内部电源网络的电压万用表量的是PCB引脚处电压两者之间有封装引线电阻和PCB走线电阻的压降芯片功耗越大这个差值越明显。如果这个偏差不可接受就需要做校准。XADC的配置寄存器里提供了增益校准系数和偏移校准系数可以在系统里用已知的精确电压源输入到某个外部通道或者用高精度万用表读出实际VCCINT然后反向推算出校准值写入寄存器。我在实际项目里更常用的是软件校准把XADC读出的电压和基准万用表读数做一次线性拟合得到offset和gain两个系数保存到EEPROM里每次上电读取后修正。这个方法不改硬件效果也很直观尤其适合批量生产的板子可以在产测环节自动标定。4. 实战案例用XADC监控VCCINT并实现PWM温控风扇4.1 一个“温度到占空比”的小系统设计假设手头有个机箱级FPGA产品需要根据芯片结温自动调节风扇转速。最简单可靠的实现方式就是XADC温度读取PWM风扇控制。整个系统分三部分第一部分是XADC负责读取结温第二部分是转换与滤波逻辑把原始码值换算成温度并做均值处理第三部分是PWM生成模块根据当前温度输出对应占空比的方波驱动风扇。温度到占空比的控制曲线我最开始用的是纯线性映射30℃以下风扇不转30℃到60℃占空比从30%线性升到100%。实测发现一个明显问题如果负载动态变化导致温度小范围波动占空比会跟着抖动风扇转速忽快忽慢体验很差。后来改成带滞回的分段曲线效果立刻好了。具体做法是温度低于45℃占空比30%保持低速静音温度在45℃到70℃占空比按线性关系从30%升到100%温度高于70℃占空比直接拉满100%从高到低时多设一个5℃的回差窗口防止在45℃附近来回跳变4.2 报警阈值配置给芯片设一道硬保护除了风控XADC的报警功能在实战里更适合做硬保护。温度达到85℃时可能不是靠风扇转速拉得回来的这时应该做的是触发断电或者降低主频。用XADC的ALM输出可以直接接到电源管理芯片的使能引脚或者接到FPGA的中断输入让系统进入降频模式。配置报警阈值时我提几个实际建议。第一上限不要设在芯片极限能力附近比如7系列FPGA允许结温到100℃但你设95℃报警可能已经晚了因为芯片局部热点温度可能比传感器位置高十几度。设置85℃或90℃比较合理。第二正确利用下限阈值。报警寄存器里有上限和下限各一组上限用于触发下限用于解除。不要只设置上限否则温度降到上限以下一点点就解除报警在一个温度点附近反复开关配合风扇控制会非常难受。第三报警输出引脚逻辑极性要在原理图设计阶段就确认好。XADC的ALM输出默认为高有效但可以通过寄存器配置取反。如果接的是低有效使能信号记得在IP核配置里改好否则变成反向控制温度越高系统越供电那就出大事了。4.3 PWM风扇控制的代码实现PWM调制用计数器就能实现关键是选择频率和死区处理。风扇PWM频率一般选20kHz到30kHz避开人耳可听范围和风扇机械谐振点。下面这段代码是我项目里的简化版占空比由外部输入的target_duty决定module pwm_fan ( input wire clk, input wire rst_n, input wire [7:0] target_duty, // 0~100 output reg [1:0] fan_pwm // 双风扇两路对称输出 ); localparam PERIOD 4000; // 25kHz 100MHz 时钟 reg [15:0] cnt; reg [15:0] threshold; always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 16d0; end else if (cnt PERIOD - 1) begin cnt 16d0; end else begin cnt cnt 1b1; end end always (posedge clk or negedge rst_n) begin if (!rst_n) begin threshold 16d0; end else begin threshold (PERIOD * target_duty) / 100; end end always (posedge clk or negedge rst_n) begin if (!rst_n) begin fan_pwm 2d0; end else if (cnt threshold) begin fan_pwm 2b11; // 双路风扇同时开启 end else begin fan_pwm 2b00; end end endmodule阈值计算这里没有做流水线优化PERIOD和target_duty的乘法在100MHz下建立时间完全来得及如果你的主频跑到300MHz以上建议改成两个周期的流水线。4.4 实测效果我在一块Kintex-7板子上跑过这个系统室温25℃时FPGA闲置XADC读到的结温是38℃左右风扇低速转噪声几乎听不见跑满资源利用率做压力测试后结温升到67℃此时风扇已经开到80%左右能明显感到出风变强关掉压力测试后结温回落到55℃以下风扇转速逐步降回去。整个过程占空比切换平缓没有出现转速来回抽风的现象。5. 容易踩的坑外部输入范围、采样率与大误区澄清5.1 外部模拟输入的真实摆幅限制XADC的外部输入引脚不是万能的。专用模拟输入VP/VN和辅助输入VAUXP/VAUXN的模拟电压范围受限于供电和配置常用单极性0~3V模式下输入电压绝对不能超过3V否则会损坏芯片。如果不确定信号幅度我建议先用分压电阻把电压降到2.5V以内再进XADC。差分输入的处理也容易出问题。VAUXP和VAUXN是配对使用的如果你只想测一个单端信号可以把负端接到AGND正端接信号。但注意AGND和FPGA的数字地通常是同一个地网络模拟信号容易受数字开关噪声干扰所以PCB布局时模拟输入走线要尽量短、远离高速数字线。另外外部通道不是想用就能用的。默认复位状态下所有外部辅助通道都是关闭的必须先写配置寄存器0x41使能对应通道启动序列扫描然后才能读到有效数据。很多网上问“为什么VAUX0读出来全是0”的人多半就是忘了这一步。5.2 不要指望XADC采高速信号XADC最高1MSPS的采样率听起来好像“也不算太低”但你要明白1MSPS意味着最高信号频率不超过500kHz实际工程应用还要留出余量能干净地采到100kHz以内的信号就算很不错了。我遇到过有人想用XADC采一个2MHz的模拟信号理由是“我的信号幅度不太大对精度要求也不高”。这从原理上就走不通采样必然混叠采出来的波形根本不能看。如果真要采高频信号老老实实外接高速ADC或者换带高速ADC的专用芯片。一个更常用的边界场景是XADC很适合做“传感器采集”比如热敏电阻、光敏电阻、电位器输出、电池电压、温度传感器这类缓慢变化的信号对采样率要求低对精度和稳定性要求高XADC反而比外接ADC更方便因为省掉了通信接口和供电。5.3 XADC、System Monitor和Zynq-7000的关系这里顺便澄清一个经常被问的问题System Monitor和XADC是什么关系Xilinx 6系列FPGA时代类似的功能模块叫System Monitor。到了7系列这个模块升级成了XADC增加了双ADC架构、更多外部通道等能力。所以你在旧文档里看到System Monitor就把它理解成XADC的前身就行。另外Zynq-7000系列包括热词里提到的XC7Z045的PL部分也内置了同样功能的XADC。Zynq的PS部分可以通过内部互联访问PL的XADC寄存器更方便的是通过AXI总线直接读取。在Zynq里用XADC还有一点额外注意PS侧的VCCPINT、VCCPAUX电压是另一组监控通道不要和PL侧的VCCINT、VCCAUX搞混。7系列里不同子系列XADC的通道排布略有差异但核心用法一致只要对照UG480确认自己的芯片型号对应的引脚和通道编号即可。5.4 不用XADC的人也需要知道的事最后说个反直觉的坑即便你的设计完全不想用XADC它默认也是开启的。这意味着如果外部连接到VAUX引脚的信号幅度超过允许范围或者引脚上有不稳定的浮空电压XADC内部可能产生异常电流影响整体可靠性。所以不用的外部输入通道也要在配置里明确关闭或者在原理图上把未使用的VAUXP/VAUXN接地。我见过一块板子Debug时经常无规律死机查了几个月没结果。最后发现原因竟然是一个悬空的VAUX引脚在特定电磁环境下积累了静电通过XADC的模拟输入通路耦合到芯片内部干扰了电源轨。把引脚强下拉后问题彻底消失。这个案例说明XADC的引脚设计必须认真对待不能因为是“辅助功能”就随意处理。我在实际工作中已经习惯把XADC当成板级调试的标配工具新板子上电先读温度和三路核心电压系统长时间运行用报警中断监控异常负载功耗波动剧烈用XADC数据辅助分析。它虽然不算精密仪器但作为FPGA集成度最高的“自检单元”很多问题都能在早期暴露出来。做调试的时候初期想把电压、温度先稳住XADC是成本最低、上手最快的选择。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询