当前位置:   article > 正文

xilinx FPGA的XADC功能测试_xilinx xadc

xilinx xadc

​ 注:扫码关注小青菜哥哥的weixin公众号,免费获得更多优质的核探测器与电子学资讯~

https://img-blog.csdnimg.cn/2ee3fd694ac942f0b1aa035ff308dc03.jpeg

Xilinx 7系列FPGA内置了一个模数转换模块,称为XADC。XADC内部集成了两个最高1MHz采样率,1Vpp的ADC模块,可以采集FPGA外部输入的模拟信号并转为数字信号。

XADC不需要外接任何输入信号,就可以测量FPGA内部的温度、VCCINT、VCCBRAM、VCCAUX电压。另外,还可以测量多达17路的外部差分输入模拟信号的幅度,包括专用差分信号输入信号VP/N以及VAUXP/N[15:0]。

所有的待测量信号均通过XADC内部的两个12bit-1MSPS的ADC模块(ADC_A和ADC_B)测量,并将转换结果存入状态寄存器(Status Registers),用户通过DRP接口可以在FPGA内部读取这些数据,也可以在vivado软件的调试界面中用JTAG获得这些数据。

另外ADC工作的配置参数由用户提供,用户将参数可以实时在线写入控制寄存器(Control Registers),从而实时控制ADC的工作状态,用户也可以在初始化配置XADC后将参数固定,不用实时配置,用户只需等待XADC初始化完成后,不断读取状态寄存器中的值即可。如下图1所示为XADC的功能模块图:

图1:XADC的功能模块图

1,硬件工作环境

FPGA:kintex-7。供电:12V/4A 直流电源。该板卡最多外接32通道2Vpp模拟信号以及20路外部触发信号。数据传输接口方式有千兆以太网接口、高速光纤接口以及低速USB串口。

图2:硬件PCB

2,逻辑开发环境

Vivado2017.4。

3,测试工程的逻辑框图介绍

如下图3所示为逻辑实现框图,由于硬件电路在设计时并没有考虑外部输入模拟电压的应用需求,因此本次测试针对的是FPGA内部的工作温度、内核电压VCCINT、VCCBRAM以及辅助电压VCCAUX这4个工作参数。

图3:逻辑测试框图

4,实现方法介绍

实现上就是对Dynamic Reconfiguration Port (DRP) 的时序进行读写操作,XADC的源语参数确定后,只需要对DRP端口进行读操作,就ok了。时序上并不复杂,其ug480官方文档给出的时序图如下图4所示,我们按照该时序控制信号就行了。

图4:DRP读写时序

如果我们连时序图都懒得看,也有其它办法。其官方给出了片上温度测量、VCCINT、VCCBRAM、VCCAUX以及4路VAUXP/N[3:0]的代码例程,ug480的第83页开始给出了应用例程和仿真测试时序,直接copy到我们的工程就可以了,DRP控制时序上非常简单,小青菜哥哥在这里就不一一介绍DRP端口信号的时序了,可以直接仿真看更清晰。

5,板级测试

我们copy了官方提供的代码并修改配置参数为只测试片上温度测量、VCCINT、VCCBRAM、VCCAUX这4路信号,并利用图3的框图建立工程,在线测试了温度和电压的功能。如图5所示为ILA在线监测的片上温度测量、VCCINT、VCCBRAM、VCCAUX这4路信号的时序图:其中EOC为每次ADC完成1路信号转换指示信号,EOS为每4路信号完成转换的指示信号。每个EOC指示信号的时间间隔为100个DRP时钟周期,因此可以推断出ADC的采样率为1MSPS。每次EOS拉高后,就表示用户可以从状态寄存器中读取4路信号的值了。

图5:4路信号整体测试时序图

如图6所示为读取这4路信号的更细节时序图,可以看到连续写入4个Dadd地址后,随后会出现drdy信号4次拉高,每次拉高时我们取出数据即可,共取4次,从而完成片上温度测量、VCCINT、VCCBRAM、VCCAUX这4路信号的取数。

图6:4路信号测试细节时序图

从图7可以更明显的观察到,每次drdy拉高时,对应读取了1路信号。拉高4次,完成4路信号的一次读取过程,之后再监测EOS信号,只要它再次拉高,就又在状态寄存器中读取这4路信号的值,如此循环往复。

图7:drdy信号拉高时取数

将取出来的4路数据通过网络接口发送到计算机,通过编写上位机软件就可以实时显示FPGA的温度和和电压了,如图8所示:FPGA的工作温度在49°附近波动,VCCINT为~1V,VCCBRAM也为~1V,VCCAUX为~1.8V,和实际FPGA的供电电压一致。

图8:上位机温度、电压监视界面

小青菜哥哥的XADC测试完整源代码如下,请大家参考:

  1. `timescale 1ns / 1ps
  2. //
  3. // Engineer: 小青菜哥哥
  4. // Create Date: 2020/06/12 17:12:08
  5. // Design Name:
  6. // Module Name: Module_XADC
  7. // Project Name: xilinx XADC测试
  8. module Module_XADC(
  9. input DCLK, // Clock input for DRP 100MHz
  10. input RESET,
  11. output [31:0] dataout,
  12. output datavld
  13. );
  14. wire busy;
  15. wire [5:0] channel;
  16. wire drdy;
  17. reg [6:0] daddr;
  18. reg [15:0] di_drp;
  19. wire [15:0] do_drp;
  20. wire [15:0] vauxp_active;
  21. wire [15:0] vauxn_active;
  22. reg [1:0] den_reg;
  23. reg [1:0] dwe_reg;
  24. reg [11:0] MEASURED_TEMP, MEASURED_VCCINT;
  25. reg TEMP_VALID,VCCINT_VALID,VCCAUX_VALID,VCCBRAM_VALID;
  26. reg [11:0] MEASURED_VCCAUX, MEASURED_VCCBRAM;
  27. reg [7:0] state = init_read;
  28. parameter init_read = 8'h00,
  29. read_waitdrdy = 8'h01,
  30. write_waitdrdy = 8'h03,
  31. read_reg00 = 8'h04,
  32. reg00_waitdrdy = 8'h05,
  33. read_reg01 = 8'h06,
  34. reg01_waitdrdy = 8'h07,
  35. read_reg02 = 8'h08,
  36. reg02_waitdrdy = 8'h09,
  37. read_reg06 = 8'h0a,
  38. reg06_waitdrdy = 8'h0b,
  39. read_reg10 = 8'h0c,
  40. reg10_waitdrdy = 8'h0d,
  41. read_reg11 = 8'h0e,
  42. reg11_waitdrdy = 8'h0f,
  43. read_reg12 = 8'h10,
  44. reg12_waitdrdy = 8'h11,
  45. read_reg13 = 8'h12,
  46. reg13_waitdrdy = 8'h13;
  47. always @(posedge DCLK)
  48. if (RESET) begin
  49. state <= init_read;
  50. den_reg <= 2'h0;
  51. dwe_reg <= 2'h0;
  52. di_drp <= 16'h0000;
  53. TEMP_VALID<=1'b0;
  54. VCCINT_VALID<=1'b0;
  55. VCCAUX_VALID<=1'b0;
  56. VCCBRAM_VALID<=1'b0;
  57. end
  58. else
  59. case (state)
  60. init_read : begin
  61. daddr = 7'h40;
  62. den_reg = 2'h2; // performing read
  63. if (busy == 0 ) state <= read_waitdrdy;
  64. end
  65. read_waitdrdy :
  66. if (drdy ==1) begin
  67. di_drp = do_drp & 16'h03_FF; //Clearing AVG bits for Configreg0
  68. daddr = 7'h40;
  69. den_reg = 2'h2;
  70. dwe_reg = 2'h2; // performing write
  71. state = write_waitdrdy;
  72. end
  73. else begin
  74. den_reg = { 1'b0, den_reg[1] } ;
  75. dwe_reg = { 1'b0, dwe_reg[1] } ;
  76. state = state;
  77. end
  78. write_waitdrdy :
  79. if (drdy ==1) begin
  80. state = read_reg00;
  81. end
  82. else begin
  83. den_reg = { 1'b0, den_reg[1] } ;
  84. dwe_reg = { 1'b0, dwe_reg[1] } ;
  85. state = state;
  86. end
  87. read_reg00 : begin
  88. TEMP_VALID<=1'b0;
  89. VCCINT_VALID<=1'b0;
  90. VCCAUX_VALID<=1'b0;
  91. VCCBRAM_VALID<=1'b0;
  92. daddr = 7'h00;
  93. den_reg = 2'h2; // performing read
  94. if (EOS == 1) state <=reg00_waitdrdy;
  95. end
  96. reg00_waitdrdy :
  97. if (drdy ==1) begin
  98. MEASURED_TEMP = do_drp[15:4];
  99. TEMP_VALID<=1'b1;
  100. VCCINT_VALID<=1'b0;
  101. VCCAUX_VALID<=1'b0;
  102. VCCBRAM_VALID<=1'b0;
  103. state <=read_reg01;
  104. end
  105. else begin
  106. den_reg = { 1'b0, den_reg[1] } ;
  107. dwe_reg = { 1'b0, dwe_reg[1] } ;
  108. state = state;
  109. end
  110. read_reg01 : begin
  111. TEMP_VALID<=1'b0;
  112. VCCINT_VALID<=1'b0;
  113. VCCAUX_VALID<=1'b0;
  114. VCCBRAM_VALID<=1'b0;
  115. daddr = 7'h01;
  116. den_reg = 2'h2; // performing read
  117. state <=reg01_waitdrdy;
  118. end
  119. reg01_waitdrdy :
  120. if (drdy ==1) begin
  121. MEASURED_VCCINT = do_drp[15:4];
  122. TEMP_VALID<=1'b0;
  123. VCCINT_VALID<=1'b1;
  124. VCCAUX_VALID<=1'b0;
  125. VCCBRAM_VALID<=1'b0;
  126. state <=read_reg02;
  127. end
  128. else begin
  129. den_reg = { 1'b0, den_reg[1] } ;
  130. dwe_reg = { 1'b0, dwe_reg[1] } ;
  131. state = state;
  132. end
  133. read_reg02 : begin
  134. TEMP_VALID<=1'b0;
  135. VCCINT_VALID<=1'b0;
  136. VCCAUX_VALID<=1'b0;
  137. VCCBRAM_VALID<=1'b0;
  138. daddr = 7'h02;
  139. den_reg = 2'h2; // performing read
  140. state <=reg02_waitdrdy;
  141. end
  142. reg02_waitdrdy :
  143. if (drdy ==1) begin
  144. MEASURED_VCCAUX = do_drp[15:4];
  145. TEMP_VALID<=1'b0;
  146. VCCINT_VALID<=1'b0;
  147. VCCAUX_VALID<=1'b1;
  148. VCCBRAM_VALID<=1'b0;
  149. state <=read_reg06;
  150. end
  151. else begin
  152. den_reg = { 1'b0, den_reg[1] } ;
  153. dwe_reg = { 1'b0, dwe_reg[1] } ;
  154. state = state;
  155. end
  156. read_reg06 : begin
  157. TEMP_VALID<=1'b0;
  158. VCCINT_VALID<=1'b0;
  159. VCCAUX_VALID<=1'b0;
  160. VCCBRAM_VALID<=1'b0;
  161. daddr = 7'h06;
  162. den_reg = 2'h2; // performing read
  163. state <=reg06_waitdrdy;
  164. end
  165. reg06_waitdrdy :
  166. if (drdy ==1) begin
  167. MEASURED_VCCBRAM = do_drp[15:4]; //由于硬件设计没有使用外部输入模拟端口,因此只进行温度、vccint、vccaux、vccbram这前四个值的读取
  168. TEMP_VALID<=1'b0;
  169. VCCINT_VALID<=1'b0;
  170. VCCAUX_VALID<=1'b0;
  171. VCCBRAM_VALID<=1'b1;
  172. state <= read_reg00/*read_reg10*/;
  173. end
  174. else begin
  175. den_reg = { 1'b0, den_reg[1] } ;
  176. dwe_reg = { 1'b0, dwe_reg[1] } ;
  177. state = state;
  178. end
  179. /* read_reg10 : begin
  180. daddr = 7'h10;
  181. den_reg = 2'h2; // performing read
  182. state <= reg10_waitdrdy;
  183. end
  184. reg10_waitdrdy :
  185. if (drdy ==1) begin
  186. MEASURED_AUX0 = do_drp;
  187. state <= read_reg11;
  188. end
  189. else begin
  190. den_reg = { 1'b0, den_reg[1] } ;
  191. dwe_reg = { 1'b0, dwe_reg[1] } ;
  192. state = state;
  193. end
  194. read_reg11 : begin
  195. daddr = 7'h11;
  196. den_reg = 2'h2; // performing read
  197. state <= reg11_waitdrdy;
  198. end
  199. reg11_waitdrdy :
  200. if (drdy ==1) begin
  201. MEASURED_AUX1 = do_drp;
  202. state <= read_reg12;
  203. end
  204. else begin
  205. den_reg = { 1'b0, den_reg[1] } ;
  206. dwe_reg = { 1'b0, dwe_reg[1] } ;
  207. state = state;
  208. end
  209. read_reg12 : begin
  210. daddr = 7'h12;
  211. den_reg = 2'h2; // performing read
  212. state <= reg12_waitdrdy;
  213. end
  214. reg12_waitdrdy :
  215. if (drdy ==1) begin
  216. MEASURED_AUX2= do_drp;
  217. state <= read_reg13;
  218. end
  219. else begin
  220. den_reg = { 1'b0, den_reg[1] } ;
  221. dwe_reg = { 1'b0, dwe_reg[1] } ;
  222. state = state;
  223. end
  224. read_reg13 : begin
  225. daddr = 7'h13;
  226. den_reg = 2'h2; // performing read
  227. state <= reg13_waitdrdy;
  228. end
  229. reg13_waitdrdy :
  230. if (drdy ==1) begin
  231. MEASURED_AUX3= do_drp;
  232. state <=read_reg00;
  233. daddr = 7'h00;
  234. end
  235. else begin
  236. den_reg = { 1'b0, den_reg[1] } ;
  237. dwe_reg = { 1'b0, dwe_reg[1] } ;
  238. state = state;
  239. end*/
  240. endcase
  241. XADC #(// Initializing the XADC Control Registers
  242. .INIT_40(16'h9000),// Calibration coefficient averaging disabled, averaging of 16 selected for external channels
  243. .INIT_41(16'h2ef0),// Continuous Seq Mode, Disable unused ALMs, Enable calibration
  244. .INIT_42(16'h0400),// Set DCLK divider to 4, ADC = 1Msps, DCLK = 100MHz
  245. .INIT_48(16'h4701),// Sequencer channel - enable Temp sensor, VCCINT, VCCAUX, VCCBRAM, and calibration
  246. .INIT_49(16'h0000),// Sequencer channel - disabled all aux analog channels 0
  247. .INIT_4A(16'h4700),// Averaging enabled for Temp sensor, VCCINT, VCCAUX,VCCBRAM
  248. .INIT_4B(16'h0000),// No averaging on external channels
  249. .INIT_4C(16'h0000),// Sequencer Bipolar selection
  250. .INIT_4D(16'h0000),// Sequencer Bipolar selection
  251. .INIT_4E(16'h0000),// Sequencer Acq time selection
  252. .INIT_4F(16'h0000),// Sequencer Acq time selection
  253. .INIT_50(16'hb5ed),// Temp upper alarm trigger 85°C
  254. .INIT_51(16'h5999),// Vccint upper alarm limit 1.05V
  255. .INIT_52(16'hA147),// Vccaux upper alarm limit 1.89V
  256. .INIT_53(16'h0000),// OT upper alarm limit 125°C using automatic shutdown - see Thermal
  257. .INIT_54(16'ha93a),// Temp lower alarm reset 60°C
  258. .INIT_55(16'h5111),// Vccint lower alarm limit 0.95V
  259. .INIT_56(16'h91Eb),// Vccaux lower alarm limit 1.71V
  260. .INIT_57(16'hae4e),// OT lower alarm reset 70°C - see Thermal Management
  261. .INIT_58(16'h5999),// VCCBRAM upper alarm limit 1.05V
  262. .SIM_MONITOR_FILE("design.txt")// Analog Stimulus file for simulation
  263. )
  264. XADC_INST (// Connect up instance IO. See UG580 for port descriptions
  265. .CONVST (1'b0),// not used
  266. .CONVSTCLK (1'b0), // not used
  267. .DADDR (daddr),
  268. .DCLK (DCLK),
  269. .DEN (den_reg[0]),
  270. .DI (di_drp),
  271. .DWE (dwe_reg[0]),
  272. .RESET (RESET),
  273. .VAUXN (16'd0 ),// not used
  274. .VAUXP (16'd0 ),// not used
  275. .ALM (ALM),
  276. .BUSY (busy),
  277. .CHANNEL(CHANNEL),
  278. .DO (do_drp),
  279. .DRDY (drdy),
  280. .EOC (EOC),
  281. .EOS (EOS),
  282. .JTAGBUSY (),// not used
  283. .JTAGLOCKED (),// not used
  284. .JTAGMODIFIED (),// not used
  285. .OT (OT),
  286. .MUXADDR (),// not used
  287. .VP (1'b0),// not used
  288. .VN (1'b0)// not used
  289. );
  290. ila_xadc ila_xadc_inst (
  291. .clk (DCLK), // input wire clk
  292. .probe0(MEASURED_TEMP), // input wire [11:0] probe0
  293. .probe1(MEASURED_VCCINT), // input wire [11:0] probe1
  294. .probe2(MEASURED_VCCAUX), // input wire [11:0] probe2
  295. .probe3(MEASURED_VCCBRAM), // input wire [11:0] probe3
  296. .probe4(TEMP_VALID), // input wire [0:0] probe4
  297. .probe5(VCCINT_VALID), // input wire [0:0] probe5
  298. .probe6(VCCAUX_VALID), // input wire [0:0] probe6
  299. .probe7(VCCBRAM_VALID), // input wire [0:0] probe7
  300. .probe8(daddr),//wire [6:0]
  301. .probe9(den_reg[0]),//wire [0:0]
  302. .probe10(dwe_reg[0]),//wire [0:0]
  303. .probe11(busy),//wire [0:0]
  304. .probe12(do_drp),//wire [15:0]
  305. .probe13(drdy),//wire [0:0]
  306. .probe14(EOC),//wire [0:0]
  307. .probe15(EOS)//wire [0:0]
  308. );
  309. wire [31:0] fifo_in_temp = {16'd0,4'd1,MEASURED_TEMP};
  310. wire [31:0] fifo_in_vint = {16'd0,4'd2,MEASURED_VCCINT};
  311. wire [31:0] fifo_in_vaux = {16'd0,4'd3,MEASURED_VCCAUX};
  312. wire [31:0] fifo_in_vram = {16'd0,4'd4,MEASURED_VCCBRAM};
  313. reg [31:0] fifo_data_in;
  314. reg fifo_data_en;
  315. wire empty;
  316. fifo_xadc fifo_xadc_inst (
  317. .clk(DCLK), // input wire clk
  318. .srst(RESET), // input wire srst
  319. .din(fifo_data_in), // input wire [31 : 0] din
  320. .wr_en(fifo_data_en), // input wire wr_en
  321. .rd_en(~empty), // input wire rd_en
  322. .dout(dataout), // output wire [31 : 0] dout
  323. .full(), // output wire full
  324. .empty(empty), // output wire empty
  325. .valid(datavld) // output wire valid
  326. );
  327. always @(posedge DCLK)
  328. if (RESET) begin
  329. fifo_data_en<=1'b0;
  330. fifo_data_in<=32'b0;
  331. end
  332. else if(TEMP_VALID)
  333. begin
  334. fifo_data_en<=1'b1;
  335. fifo_data_in<=fifo_in_temp;
  336. end
  337. else if(VCCINT_VALID)
  338. begin
  339. fifo_data_en<=1'b1;
  340. fifo_data_in<=fifo_in_vint;
  341. end
  342. else if(VCCAUX_VALID)
  343. begin
  344. fifo_data_en<=1'b1;
  345. fifo_data_in<=fifo_in_vaux;
  346. end
  347. else if(VCCBRAM_VALID)
  348. begin
  349. fifo_data_en<=1'b1;
  350. fifo_data_in<=fifo_in_vram;
  351. end
  352. else
  353. begin
  354. fifo_data_en<=1'b0;
  355. fifo_data_in<=32'b0;
  356. end
  357. endmodule

今天的博文就到这里了,有问题请在小青菜哥哥的公众号留言,谢谢!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/491022
推荐阅读
相关标签
  

闽ICP备14008679号