ARTICLE DETAIL

资讯详情

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

FPGA内嵌XADC实战:IP核配置、DRP与AXI4-Lite接口详解

FPGA内嵌XADC实战:IP核配置、DRP与AXI4-Lite接口详解 1. 项目缘起与XADC核心价值解读第一次接触XADC是在一个工业数据采集项目上当时需要监控FPGA芯片内部的结温以及几路外部传感器的模拟电压。板子上的ADC芯片选型还没定硬件同事随口提了一句“7系列FPGA里面不是自带ADC吗”这才把XADC拉进了视野。说实话刚开始我对这个硬核是有点抵触的总觉得“附赠”的东西精度和灵活性都不够看但实际用下来发现在采样率要求不高的监控场景里XADC确实能省掉一颗外置ADC和配套的基准源电路对成本和板面积的压缩非常直接。XADC全称是Xilinx Analog-to-Digital Converter是集成在7系列FPGA以及后续UltraScale的部分器件内部的一个12位、1MSPS的模数转换器模块。它有两个独立的ADC通道可以同时采样两路模拟信号内部还集成了一个温度传感器和多个电源电压监测通道。对于做7k系列XADC读取的开发者来说最常打交道的场景无非三类芯片结温监控、内部电源轨电压监测、以及通过外部模拟输入通道采集传感器信号。这三类场景基本覆盖了XADC在工业控制、通信设备、测试仪器中的绝大多数用法。为什么要在Vivado里用IP核的方式来配置XADC而不是直接例化原语这个问题我踩过坑。早期我尝试过直接调用XADC原语代码量确实少但端口时序、动态重配置逻辑、状态机控制都得自己写调试起来非常痛苦。Vivado提供的XADC Wizard IP核把这些底层细节都封装好了通过图形化界面就能完成通道选择、采样模式、报警阈值、平均次数等关键参数的配置生成的示例代码和约束文件也基本能直接跑通。更重要的是IP核支持AXI4-Lite接口和DRP接口两种访问方式前者适合挂到MicroBlaze或Zynq的PS端通过寄存器读写后者适合纯逻辑侧直接访问灵活性很高。这篇文章面向的是已经装好Vivado、对FPGA基本开发流程有概念、但还没深入用过XADC的工程师。我会从IP核的配置界面讲起把每个关键参数背后的含义和选择逻辑说清楚然后分别给出DRP接口和AXI4-Lite接口的实操代码和仿真验证方法最后把我在实际项目中遇到的坑和排查思路整理出来。你不需要有模拟电路设计的深厚背景但至少得知道什么是采样率、什么是参考电压这样理解起来会更顺畅。2. XADC IP核配置界面逐项拆解2.1 从IP Catalog找到XADC Wizard在Vivado的Flow Navigator里点开IP Catalog搜索框输入“xadc”出来的第一个就是XADC Wizard。双击打开配置界面你会看到几个标签页Basic、ADC Setup、Alarms、Single Channel、Dynamic Reconfiguration、Simulation。很多人第一次配的时候直接一路Next点到底结果生成出来的IP核要么通道不对要么报警阈值乱设仿真波形完全看不懂。我建议你按顺序一个一个标签页过每个参数都搞清楚再往下走。Basic标签页里最重要的是Interface Selection。这里有两个选项AXI4-Lite和DRP。选哪个取决于你的系统架构。如果你的FPGA里跑了MicroBlaze软核或者用的是Zynq系列想把XADC数据送到PS端处理那就选AXI4-LiteIP核会自动生成一套AXI从机接口你通过读写寄存器就能拿到ADC数据和配置报警阈值。如果你只想在纯逻辑侧用状态机直接读ADC值不需要处理器介入那就选DRP接口更简单时序也更可控。我个人的经验是如果项目里已经有AXI总线基础设施选AXI4-Lite更省事如果是纯Verilog/VHDL的逻辑设计DRP更直接。还有一个Startup Channel Selection让你选择上电后默认采样的通道。通常选“Single Channel”然后指定一个通道就行后面可以在线切换。如果你选了“Sequencer Mode”XADC会自动按顺序轮询多个通道适合需要同时监控多路信号但不需要高速采样的场景。2.2 ADC Setup里的采样参数怎么定ADC Setup标签页是配置的核心。这里有几个关键参数Acquisition Time、Conversion Rate、Averaging、External Multiplexer。Acquisition Time是采样保持电路的充电时间单位是纳秒。这个值跟你的信号源阻抗直接相关。信号源阻抗越大需要的采样时间越长。XADC的采样电容大约是3pF如果你外部信号经过分压电阻或者RC滤波等效源阻抗可能到几kΩ甚至几十kΩ。这时候如果Acquisition Time设得太短采样电容充不满转换结果就会偏低。我一般会先用公式估算t_acq ≥ 10 × R_source × C_sample。假设源阻抗是10kΩ采样电容3pF那t_acq至少需要300ns。实际配置时我会留一倍余量设成600ns左右。当然Acquisition Time越长最大采样率就越低这是一个权衡。Conversion Rate是ADC的转换速率单位是KSPS千次采样每秒。XADC最高支持1MSPS但这是在最短采样时间下的理论值。实际配置时Vivado会根据你设的Acquisition Time自动计算可用的最高转换率。如果你手动设了一个超过上限的值工具会报错。我通常会把转换率设在100KSPS到500KSPS之间对于温度监控和电源电压监测10KSPS都绰绰有余没必要追求极限速度。Averaging是平均次数可以选None、16、64、256。这个功能非常实用。XADC的原始输出会有一定的噪声尤其是在电源电压监测通道上开关电源的纹波会耦合进来。开启平均后XADC会自动连续采样多次然后取平均输出结果会平滑很多。代价是有效采样率下降。比如你设了256次平均转换率是100KSPS那实际输出更新率就只有100K/256≈390Hz。对于温度监控这种慢变量完全够用。我一般会开16次或64次平均兼顾响应速度和噪声抑制。External Multiplexer选项是给外部模拟多路复用器用的。如果你板子上有外部的模拟开关想通过XADC来控制通道切换可以在这里使能XADC会输出多路复用器的控制信号。大多数场景用不到保持默认关闭即可。2.3 Alarms标签页的阈值设置逻辑Alarms标签页用来设置报警阈值。XADC内部有多个报警寄存器当温度、VCCINT、VCCAUX、VCCBRAM等参数超过上限或低于下限时会置位相应的报警信号。这些报警信号可以连接到FPGA的逻辑资源用来触发保护动作比如降低时钟频率、关闭某些模块、或者点亮故障指示灯。温度报警的上限值设置要参考芯片的结温规格。7系列FPGA的商用级结温范围是0到85摄氏度工业级是-40到100摄氏度。我一般会把上限报警设在85度下限设在5度。注意这是结温不是环境温度实际结温会比环境温度高20到30度取决于散热条件和功耗。如果你把上限设得太低正常工作时就会频繁误报。电压报警的阈值设置要参考你板子的实际电源精度。以VCCINT为例7系列FPGA的VCCINT标称值是1.0V允许波动范围通常是±5%也就是0.95V到1.05V。你可以把上限设在1.05V下限设在0.95V。但实际电源芯片的输出精度、纹波、负载调整率都会影响这个值建议先用XADC读一段时间实际电压观察波动范围再留一定余量来设阈值。注意报警阈值一旦设定在IP核生成后就固定了。如果后期需要调整要么重新生成IP核要么通过DRP接口在线修改报警寄存器。后者更灵活但需要额外的逻辑设计。2.4 通道配置与动态重配置Single Channel标签页用来配置单个通道的详细参数。XADC有多个模拟输入通道包括专用的VP/VN差分对和最多16个辅助模拟输入通道通过外部多路复用器扩展。在7系列FPGA上通常只有VP/VN和少数几个辅助通道可用具体取决于封装和引脚分配。每个通道可以单独设置Acquisition Time和Averaging。如果你某个通道的信号源阻抗特别大可以单独把这个通道的采样时间加长不影响其他通道。这个灵活性在混合信号采集场景里很有用。Dynamic Reconfiguration标签页是给需要在线修改XADC配置的场景准备的。比如你想在运行时切换采样通道、修改平均次数、调整报警阈值就可以通过DRP接口写对应的配置寄存器。Vivado会生成一个DRP接口的示例模块里面包含了写配置寄存器的状态机。这个功能在需要自适应调整采样策略的系统里很有价值但复杂度也相应提高。我建议新手先把静态配置跑通再考虑动态重配置。3. DRP接口实战纯逻辑侧读取XADC数据3.1 DRP接口时序解析DRPDynamic Reconfiguration Port是XADC提供的一个简单同步接口用来读写XADC内部的配置寄存器和状态寄存器。它包含以下信号DEN使能、DWE写使能、DADDR地址、DI写数据、DO读数据、DRDY数据有效、DCLK时钟。读操作的时序是在DCLK上升沿DEN拉高DWE拉低DADDR给出要读的寄存器地址一个周期后DRDY拉高DO上出现有效数据。写操作的时序类似只是DWE拉高DI上给出要写的数据。这个接口的时序并不复杂但有几个细节容易出错。第一DEN和DADDR必须在同一个时钟周期内有效不能先给地址再给使能。第二DRDY信号只持续一个时钟周期必须在它拉高的那个周期采样DO否则数据就丢了。第三DCLK的频率不能超过XADC的规格通常建议在50MHz以下太高了XADC内部逻辑跟不上。我一般会写一个简单的状态机来驱动DRP接口。状态机有四个状态IDLE、SETUP、READ、WAIT。IDLE状态下等待触发信号SETUP状态下给出DEN、DADDR和DWEREAD状态下等待DRDYWAIT状态下锁存DO并返回IDLE。这个状态机跑在50MHz时钟下读一次寄存器大约需要4到5个周期也就是80到100ns完全能满足大多数监控场景的需求。3.2 关键寄存器地址与数据格式XADC的寄存器地址是7位的常用的几个地址如下表所示寄存器名称地址十六进制说明Temperature0x00芯片结温12位数据VCCINT0x01内部核心电压VCCAUX0x02辅助电压VP/VN0x03专用模拟输入对VAUX[0]0x10辅助通道0VAUX[1]0x11辅助通道1Flag0x3F报警标志寄存器Config0x40配置寄存器数据格式方面温度寄存器的12位数据需要做转换。XADC输出的温度码值是以12位二进制补码形式表示的转换公式是温度摄氏度 码值 × 503.975 / 4096 - 273.15。举个例子如果读到的码值是0x0A00也就是2560那温度就是2560 × 503.975 / 4096 - 273.15 ≈ 315 - 273.15 ≈ 41.85摄氏度。这个公式我建议直接写成Verilog里的定点运算或者用MicroBlaze做浮点计算。电压寄存器的转换公式是电压伏特 码值 × 3.0 / 4096。因为XADC的内部参考电压是3.0V实际是2.5V或3.0V取决于具体配置12位满量程对应3.0V。比如码值是0x555也就是1365那电压就是1365 × 3.0 / 4096 ≈ 1.0V。这个公式适用于VCCINT、VCCAUX和VP/VN通道。3.3 完整DRP读取模块的Verilog实现下面是我在实际项目中用的一个DRP读取模块经过多次迭代稳定可靠。模块的输入是50MHz时钟和复位信号输出是温度值和电压值以及一个数据有效标志。module xadc_drp_reader ( input wire clk, input wire rst_n, output reg [11:0] temp_data, output reg [11:0] vccint_data, output reg [11:0] vaux0_data, output reg data_valid ); localparam IDLE 2b00; localparam SETUP 2b01; localparam READ 2b10; localparam WAIT 2b11; reg [1:0] state; reg [6:0] daddr; reg den; reg dwe; reg [15:0] di; wire [15:0] do; wire drdy; reg [2:0] ch_sel; reg [15:0] timeout_cnt; // 通道轮询计数器 always (posedge clk or negedge rst_n) begin if (!rst_n) ch_sel 3d0; else if (state IDLE timeout_cnt 16d0) ch_sel ch_sel 1b1; end // 超时计数器防止DRDY一直不来 always (posedge clk or negedge rst_n) begin if (!rst_n) timeout_cnt 16d0; else if (state IDLE) timeout_cnt 16d50000; else if (timeout_cnt 0) timeout_cnt timeout_cnt - 1b1; end // 根据通道选择设置地址 always (*) begin case (ch_sel) 3d0: daddr 7h00; // 温度 3d1: daddr 7h01; // VCCINT 3d2: daddr 7h10; // VAUX0 default: daddr 7h00; endcase end // 主状态机 always (posedge clk or negedge rst_n) begin if (!rst_n) begin state IDLE; den 1b0; dwe 1b0; di 16d0; data_valid 1b0; end else begin case (state) IDLE: begin data_valid 1b0; if (timeout_cnt 16d0) begin state SETUP; den 1b1; dwe 1b0; end end SETUP: begin den 1b0; state READ; end READ: begin if (drdy) begin state WAIT; end end WAIT: begin case (ch_sel) 3d0: temp_data do[11:0]; 3d1: vccint_data do[11:0]; 3d2: vaux0_data do[11:0]; endcase data_valid 1b1; state IDLE; end endcase end end // 例化XADC IP核DRP接口 xadc_wiz_0 u_xadc ( .dclk (clk), .den (den), .dwe (dwe), .daddr (daddr), .di (di), .do (do), .drdy (drdy), .vp_in (1b0), .vn_in (1b0), .vauxp0 (1b0), .vauxn0 (1b0), .convst (1b0), .alarm (), .busy (), .channel (), .eoc (), .ot () ); endmodule这个模块的核心思路是轮询三个通道温度、VCCINT、VAUX0。每读到一个通道的数据就更新对应的输出寄存器并置位data_valid。超时计数器用来防止DRDY因为意外原因一直不拉高导致状态机卡死。实际测试下来在50MHz时钟下每个通道的读取周期大约是2微秒三个通道轮询一遍不到10微秒对于监控应用来说绰绰有余。3.4 仿真验证与波形分析写完代码后一定要做仿真。我一般会写一个简单的testbench给50MHz时钟和复位信号然后观察状态机的跳转和DRDY的响应。在Vivado里跑行为仿真重点看几个地方DEN和DADDR是否对齐、DRDY是否在预期周期拉高、DO上的数据是否稳定。如果DRDY一直不拉高首先检查DCLK频率是否超了。XADC的DRP接口对时钟频率有要求虽然手册上说最高可以到50MHz但实际仿真模型可能在更高频率下行为异常。其次检查DEN的脉冲宽度太窄了XADC可能采样不到。我一般会让DEN保持一个完整时钟周期这样最稳妥。仿真通过后下一步是上板实测。把温度值和电压值通过UART打印出来或者用ILA抓波形。我第一次上板时发现温度读数一直在跳后来发现是平均次数设成了None原始数据噪声比较大。改成64次平均后温度读数稳定在±0.5度以内完全满足监控需求。4. AXI4-Lite接口实战处理器侧读取XADC4.1 AXI4-Lite接口的优势与适用场景如果你的系统里有MicroBlaze软核或者Zynq的PS端用AXI4-Lite接口访问XADC会更方便。IP核会自动生成一套AXI从机接口你只需要像读写普通寄存器一样操作XADC不需要自己写DRP状态机。Vivado还会自动生成对应的软件驱动在SDK或Vitis里直接调用API函数就能读取温度和电压值。AXI4-Lite接口的另一个好处是支持中断。你可以配置XADC在报警条件满足时产生中断处理器收到中断后再去读报警寄存器判断是哪个参数超限了。这种事件驱动的处理方式比轮询效率高得多尤其适合低功耗场景。不过AXI4-Lite接口也有代价。它需要占用AXI互联资源如果你的系统里AXI总线已经很拥挤了再加一个XADC可能会影响时序收敛。另外AXI4-Lite的读写延迟比DRP高因为要经过互联矩阵和协议转换。对于高速采样场景DRP更合适对于监控和配置场景AXI4-Lite更省心。4.2 IP核AXI4-Lite接口的寄存器映射XADC Wizard在AXI4-Lite模式下会生成一个寄存器映射把XADC的内部寄存器映射到AXI地址空间。常用的寄存器偏移地址如下偏移地址寄存器名称访问方式说明0x00Temperature只读温度数据低12位有效0x04VCCINT只读核心电压数据0x08VCCAUX只读辅助电压数据0x0CVP/VN只读专用模拟输入0x40VAUX[0]只读辅助通道00x44VAUX[1]只读辅助通道10x100Flag只读报警标志0x104Config读写配置寄存器注意这些偏移地址是相对于AXI基地址的。在Vivado的Address Editor里你可以看到XADC IP核被分配的基地址通常是0x44A00000或者类似的地址。在软件里访问时基地址加上偏移地址就是完整的物理地址。4.3 MicroBlaze软核读取XADC的软件实现在Vitis里Xilinx提供了XADC的驱动库函数前缀是XAdcPs_。下面是一段典型的读取温度和电压的代码#include xadcps.h #include xparameters.h #include xstatus.h XAdcPs XAdcInst; int main(void) { XAdcPs_Config *ConfigPtr; u32 TempRaw, VccintRaw, Vaux0Raw; float Temperature, Vccint, Vaux0; // 初始化XADC驱动 ConfigPtr XAdcPs_LookupConfig(XPAR_XADCPS_0_DEVICE_ID); if (ConfigPtr NULL) { return XST_FAILURE; } XAdcPs_CfgInitialize(XAdcInst, ConfigPtr, ConfigPtr-BaseAddress); // 设置采样模式 XAdcPs_SetSequencerMode(XAdcInst, XADCPS_SEQ_MODE_SINGLECHANNEL); while (1) { // 读取温度 XAdcPs_SetSingleChParams(XAdcInst, XADCPS_CH_TEMP, FALSE, FALSE, FALSE); while (XAdcPs_GetAdcBusy(XAdcInst)); TempRaw XAdcPs_GetAdcData(XAdcInst, XADCPS_CH_TEMP); Temperature XAdcPs_RawToTemperature(TempRaw); // 读取VCCINT XAdcPs_SetSingleChParams(XAdcInst, XADCPS_CH_VCCINT, FALSE, FALSE, FALSE); while (XAdcPs_GetAdcBusy(XAdcInst)); VccintRaw XAdcPs_GetAdcData(XAdcInst, XADCPS_CH_VCCINT); Vccint XAdcPs_RawToVoltage(VccintRaw); // 读取VAUX0 XAdcPs_SetSingleChParams(XAdcInst, XADCPS_CH_AUX_MIN, FALSE, FALSE, FALSE); while (XAdcPs_GetAdcBusy(XAdcInst)); Vaux0Raw XAdcPs_GetAdcData(XAdcInst, XADCPS_CH_AUX_MIN); Vaux0 XAdcPs_RawToVoltage(Vaux0Raw); // 打印结果 printf(Temperature: %.2f C\n, Temperature); printf(VCCINT: %.3f V\n, Vccint); printf(VAUX0: %.3f V\n, Vaux0); // 延时 for (volatile int i 0; i 1000000; i); } return 0; }这段代码的关键是XAdcPs_SetSingleChParams函数它用来切换采样通道。每次切换通道后要等待XAdcPs_GetAdcBusy返回false才能读取数据。XAdcPs_RawToTemperature和XAdcPs_RawToVoltage是驱动库提供的转换函数内部已经实现了前面说的转换公式直接调用就行不用自己算。提示在Vitis里使用XAdcPs驱动时需要在Board Support Package里使能xadcps库。如果编译时报“undefined reference to XAdcPs_LookupConfig”检查一下BSP设置里是否勾选了对应的驱动。4.4 AXI4-Lite接口的时序约束与调试AXI4-Lite接口的时序约束相对简单因为IP核已经帮你处理了大部分协议细节。你只需要确保AXI时钟通常是s_axi_aclk和XADC的DCLK是同一个时钟域或者做好跨时钟域处理。Vivado在生成IP核时会自动添加必要的时序约束你可以在XDC文件里看到。调试AXI4-Lite接口时最常用的工具是Vivado的AXI Protocol Checker。它会在仿真时监测AXI总线上的协议违规比如握手信号不匹配、突发长度错误等。如果上板后发现读不到数据先用ILA抓AXI总线的读写事务看看地址是否正确、握手是否完成。我遇到过一次问题是AXI基地址配错了软件读的地址和IP核实际映射的地址不一致导致一直返回0xFFFFFFFF。后来在Address Editor里核对了一下把基地址改对就好了。5. 常见问题与排查技巧实录5.1 温度读数异常跳动或明显偏离这是最常见的问题。温度读数跳动通常是因为平均次数设得太低或者采样时间不够。XADC的温度传感器输出本身有一定的噪声不开平均的话读数可能在±3度范围内跳动。解决办法很简单把Averaging设成64或256读数就会稳定下来。如果温度读数明显偏离实际值比如室温下读到60度那可能是转换公式用错了。注意XADC输出的温度码值是无符号数还是补码不同版本的IP核可能不一样。我建议先用Xilinx提供的转换函数验证一下如果函数算出来是对的那就是你自己写的公式有问题。还有一种情况是温度读数一直不变比如始终是0或者始终是最大值。这通常是DRP接口没有正确读取或者通道地址配错了。用ILA抓一下DRDY和DO信号看看有没有数据返回。如果DRDY一直不拉高检查DCLK频率和DEN脉冲宽度。5.2 电压读数偏差大或报警误触发电压读数偏差大首先要检查参考电压。XADC的内部参考电压是1.25V但经过内部缓冲后实际满量程可能是3.0V或2.5V取决于具体配置。如果你用的转换公式假设满量程是3.0V但实际配置是2.5V那读数就会偏大20%。在IP核配置界面里确认一下Reference Voltage的设置然后调整转换公式。报警误触发通常是阈值设得太紧。比如VCCINT的标称值是1.0V你把上限设成1.01V那正常波动就可能触发报警。建议先用XADC读一段时间实际电压记录最大值和最小值然后留至少±3%的余量来设阈值。另外报警信号最好做一下消抖连续多次超限才认为真的报警避免瞬态波动导致误动作。5.3 DRP接口读不到数据的排查思路DRP接口读不到数据排查顺序如下第一检查DCLK是否有时钟频率是否在规格范围内第二检查DEN和DADDR是否在同一个周期有效第三检查DRDY是否在预期周期拉高第四检查DO上的数据是否稳定。如果DRDY不拉高可以尝试降低DCLK频率或者增加DEN的脉冲宽度。如果DO上数据一直是0检查DADDR是否指向了正确的寄存器。还有一个容易忽略的点是XADC的复位。XADC IP核有一个复位信号如果复位没有正确释放XADC会一直处于复位状态DRP接口不响应。确保复位信号在上电后保持足够长时间的低电平然后释放。5.4 AXI4-Lite接口软件读不到数据的排查软件读不到数据先确认AXI基地址是否正确。在Vivado的Address Editor里查看XADC IP核的基地址然后在软件里用这个基地址加上偏移地址来访问。如果基地址对了但还是读不到检查BSP里是否使能了XAdcPs驱动。如果驱动没使能编译会报错但有时候只是警告容易被忽略。另外AXI4-Lite接口的读写需要正确的字节使能信号。如果你用Xil_Out32和Xil_In32函数字节使能会自动处理。但如果自己写AXI事务要注意WSTRB信号的设置。我遇到过因为WSTRB设错导致写入配置寄存器不生效的情况后来改用Xil_Out32就正常了。5.5 常见问题速查表现象可能原因排查方法解决措施温度读数跳动平均次数太低检查Averaging设置设为64或256温度读数偏离转换公式错误用官方函数验证修正公式或改用官方函数电压读数偏大参考电压配置不匹配检查IP核Reference Voltage调整转换公式报警误触发阈值太紧记录实际波动范围留±3%余量加消抖DRDY不拉高DCLK频率过高用示波器或ILA测频率降低到50MHz以下DO数据为0DADDR错误核对寄存器地址表修正地址AXI读不到数据基地址错误检查Address Editor修正软件基地址AXI写不生效WSTRB错误抓AXI波形改用Xil_Out326. 实操心得与进阶建议XADC这个模块说简单也简单说坑多也坑多。我用了几年下来最大的体会是不要把它当成一个高精度ADC来用。它的12位分辨率、1MSPS采样率在监控场景里够用但如果你要做音频采集或者精密测量还是老老实实选外置ADC。XADC的真正价值在于集成度和便利性省掉外置芯片和基准源对于成本敏感、板面积紧张的项目来说非常划算。另一个心得是关于平均次数的选择。很多人为了追求响应速度把平均关掉结果读数噪声大得没法用。其实对于温度监控响应速度根本不重要温度变化本身就很慢开256次平均输出更新率还有几百Hz完全够用。对于电源电压监测开16次或64次平均既能抑制开关噪声又能保持足够的响应速度。我一般会针对不同通道设置不同的平均次数温度通道开最大电压通道开中等。关于DRP和AXI4-Lite的选择我的建议是如果系统里已经有处理器优先用AXI4-Lite软件开发和调试都更方便如果是纯逻辑设计或者对采样时序有严格要求用DRP。两者也可以混用比如用DRP做高速数据采集用AXI4-Lite做配置和报警管理但这样会增加设计复杂度新手不建议。最后分享一个调试小技巧在Vivado里例化XADC IP核时勾选“Generate Example Design”工具会生成一个完整的示例工程包含DRP接口的Verilog代码和仿真testbench。这个示例代码是官方验证过的可以直接拿来参考。我最初就是靠这个示例代码理解了DRP接口的时序然后在它的基础上改成了自己的轮询逻辑。如果你在配置或接口上卡住了不妨先跑一遍示例工程看看波形和代码很多问题会迎刃而解。
返回列表