在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 16469|回复: 5

[资料] 怎么使用XADC检测Xilinx FPGA的温度和电压

[复制链接]
发表于 2018-3-22 19:53:28 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
1.1
XADC简介

  为了提高系统集成度,Xilinx的7Series FPGA器件内部都集成了一个模数转换器(Analog-to-DigitalConverter),以下简称XADC。该模块具有以下特性:

Ø
模拟信号转换为数字信号

Ø
FPGA的温度和电压检测功能

Ø
根据用户设置的参数生成警报

1.2
UG480使用例程

根据官方给出的例程,本文档针对温度和电压检测功能,整理出了简要使用方法。

使用官方的ug480.v完成温度电压寄存器的访问,该模块代码如下:






  1. `timescale 1ns / 1ps
  2. module ug480 (
  3.     input DCLK, // Clock input for DRP
  4.     input RESET,
  5.     input [3:0] VAUXP, VAUXN,  // Auxiliary analog channel inputs
  6.     input VP, VN,// Dedicated and Hardwired Analog Input Pair
  7.    
  8.     output reg [15:0] MEASURED_TEMP, MEASURED_VCCINT,
  9.     output reg [15:0] MEASURED_VCCAUX, MEASURED_VCCBRAM,
  10.     output reg [15:0] MEASURED_AUX0, MEASURED_AUX1,
  11.     output reg [15:0] MEASURED_AUX2, MEASURED_AUX3,

  12.     output wire [7:0] ALM,
  13.     output wire [4:0]  CHANNEL,      
  14.     output wire        OT,
  15.     output wire        EOC,
  16.     output wire        EOS
  17.     );     

  18.     wire busy;
  19.     wire [5:0] channel;
  20.     wire drdy;
  21.     wire eoc;
  22.     wire eos;
  23.     wire i2c_sclk_in;
  24.     wire i2c_sclk_ts;
  25.     wire i2c_sda_in;
  26.     wire i2c_sda_ts;
  27.    
  28.    
  29.     reg [6:0] daddr;
  30.     reg [15:0] di_drp;
  31.     wire [15:0] do_drp;
  32.     wire [15:0] vauxp_active;
  33.     wire [15:0] vauxn_active;
  34.     wire dclk_bufg;

  35.     reg [1:0]  den_reg;
  36.     reg [1:0]  dwe_reg;
  37.    
  38.     reg [7:0]   state = init_read;
  39.     parameter       init_read       = 8'h00,
  40.                     read_waitdrdy   = 8'h01,
  41.                     write_waitdrdy  = 8'h03,
  42.                     read_reg00      = 8'h04,
  43.                     reg00_waitdrdy  = 8'h05,
  44.                     read_reg01      = 8'h06,
  45.                     reg01_waitdrdy  = 8'h07,
  46.                     read_reg02      = 8'h08,
  47.                     reg02_waitdrdy  = 8'h09,
  48.                     read_reg06      = 8'h0a,
  49.                     reg06_waitdrdy  = 8'h0b,
  50.                     read_reg10      = 8'h0c,
  51.                     reg10_waitdrdy  = 8'h0d,
  52.                     read_reg11      = 8'h0e,
  53.                     reg11_waitdrdy  = 8'h0f,
  54.                     read_reg12      = 8'h10,
  55.                     reg12_waitdrdy  = 8'h11,
  56.                     read_reg13      = 8'h12,
  57.                     reg13_waitdrdy  = 8'h13;
  58.    
  59.         BUFG i_bufg (.I(DCLK), .O(dclk_bufg));
  60.    always @(posedge dclk_bufg)
  61.       if (RESET) begin
  62.          state   <= init_read;
  63.          den_reg <= 2'h0;
  64.          dwe_reg <= 2'h0;
  65.          di_drp  <= 16'h0000;
  66.       end
  67.       else
  68.          case (state)
  69.          init_read : begin
  70.             daddr <= 7'h40;
  71.             den_reg <= 2'h2; // performing read
  72.             if (busy == 0 ) state <= read_waitdrdy;
  73.             end
  74.          read_waitdrdy :
  75.             if (eos ==1)          begin
  76.                di_drp <= do_drp  & 16'h03_FF; //Clearing AVG bits for Configreg0
  77.                daddr <= 7'h40;
  78.                den_reg <= 2'h2;
  79.                dwe_reg <= 2'h2; // performing write
  80.                state <= write_waitdrdy;
  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.          write_waitdrdy :
  88.             if (drdy ==1) begin
  89.                state <= read_reg00;
  90.                end
  91.             else begin
  92.                den_reg <= { 1'b0, den_reg[1] } ;
  93.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  94.                state <= state;         
  95.             end
  96.          read_reg00 : begin
  97.             daddr   <= 7'h00;
  98.             den_reg <= 2'h2; // performing read
  99.             if (eos == 1) state   <=reg00_waitdrdy;
  100.             end
  101.          reg00_waitdrdy :
  102.             if (drdy ==1)          begin
  103.                MEASURED_TEMP <= do_drp;
  104.                state <=read_reg01;
  105.                end
  106.             else begin
  107.                den_reg <= { 1'b0, den_reg[1] } ;
  108.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  109.                state <= state;         
  110.             end
  111.          read_reg01 : begin
  112.             daddr   <= 7'h01;
  113.             den_reg <= 2'h2; // performing read
  114.             state   <=reg01_waitdrdy;
  115.             end
  116.             reg01_waitdrdy :
  117.            if (drdy ==1)          begin
  118.                MEASURED_VCCINT = do_drp;
  119.                state <=read_reg02;
  120.                end
  121.             else begin
  122.                den_reg <= { 1'b0, den_reg[1] } ;
  123.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  124.                state <= state;         
  125.             end
  126.          read_reg02 : begin
  127.             daddr   <= 7'h02;
  128.             den_reg <= 2'h2; // performing read
  129.             state   <=reg02_waitdrdy;
  130.             end
  131.          reg02_waitdrdy :
  132.             if (drdy ==1)          begin
  133.                MEASURED_VCCAUX <= do_drp;
  134.                state <=read_reg06;
  135.                end
  136.             else begin
  137.                den_reg <= { 1'b0, den_reg[1] } ;
  138.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  139.                state <= state;         
  140.             end
  141.          read_reg06 : begin
  142.             daddr   <= 7'h06;
  143.             den_reg <= 2'h2; // performing read
  144.             state   <=reg06_waitdrdy;
  145.             end
  146.          reg06_waitdrdy :
  147.             if (drdy ==1)          begin
  148.                MEASURED_VCCBRAM <= do_drp;
  149.                state <= read_reg10;
  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_reg10 : begin
  157.                daddr   <= 7'h10;
  158.                den_reg <= 2'h2; // performing read
  159.                state   <= reg10_waitdrdy;
  160.             end
  161.          reg10_waitdrdy :
  162.             if (drdy ==1)          begin
  163.                MEASURED_AUX0 <= do_drp;
  164.                state <= read_reg11;
  165.             end
  166.             else begin
  167.                den_reg <= { 1'b0, den_reg[1] } ;
  168.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  169.                state <= state;         
  170.             end
  171.          read_reg11 : begin
  172.             daddr   <= 7'h11;
  173.             den_reg <= 2'h2; // performing read
  174.             state   <= reg11_waitdrdy;
  175.             end
  176.          reg11_waitdrdy :
  177.             if (drdy ==1)          begin
  178.                MEASURED_AUX1 <= do_drp;
  179.                state <= read_reg12;
  180.                end
  181.             else begin
  182.                den_reg <= { 1'b0, den_reg[1] } ;
  183.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  184.                state <= state;         
  185.             end
  186.          read_reg12 : begin
  187.             daddr   <= 7'h12;
  188.             den_reg <= 2'h2; // performing read
  189.             state   <= reg12_waitdrdy;
  190.             end
  191.          reg12_waitdrdy :
  192.             if (drdy ==1)          begin
  193.                MEASURED_AUX2 <= do_drp;
  194.                state <= read_reg13;
  195.                end
  196.             else begin
  197.                den_reg <= { 1'b0, den_reg[1] } ;
  198.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  199.                state <= state;         
  200.             end
  201.          read_reg13 : begin
  202.             daddr   <= 7'h13;
  203.             den_reg <= 2'h2; // performing read
  204.             state   <= reg13_waitdrdy;
  205.             end
  206.          reg13_waitdrdy :
  207.             if (drdy ==1)          begin
  208.                MEASURED_AUX3 <= do_drp;
  209.                state <=read_reg00;
  210.                daddr   <= 7'h00;
  211.             end
  212.             else begin
  213.                den_reg <= { 1'b0, den_reg[1] } ;
  214.                dwe_reg <= { 1'b0, dwe_reg[1] } ;      
  215.                state <= state;         
  216.             end
  217.          default : begin
  218.             daddr <= 7'h40;
  219.             den_reg <= 2'h2; // performing read
  220.             state <= init_read;
  221.             end
  222.          endcase

  223. XADC #(// Initializing the XADC Control Registers
  224.     .INIT_40(16'h9000),// averaging of 16 selected for external channels
  225.     .INIT_41(16'h2ef0),// Continuous Seq Mode, Disable unused ALMs, Enable calibration
  226.     .INIT_42(16'h0400),// Set DCLK divides
  227.     .INIT_48(16'h4701),// CHSEL1 - enable Temp VCCINT, VCCAUX, VCCBRAM, and calibration
  228.     .INIT_49(16'h000f),// CHSEL2 - enable aux analog channels 0 - 3
  229.     .INIT_4A(16'h0000),// SEQAVG1 disabled
  230.     .INIT_4B(16'h0000),// SEQAVG2 disabled
  231.     .INIT_4C(16'h0000),// SEQINMODE0
  232.     .INIT_4D(16'h0000),// SEQINMODE1
  233.     .INIT_4E(16'h0000),// SEQACQ0
  234.     .INIT_4F(16'h0000),// SEQACQ1
  235.     .INIT_50(16'hb5ed),// Temp upper alarm trigger 85
  236.     .INIT_51(16'h5999),// Vccint upper alarm limit 1.05V
  237.     .INIT_52(16'hA147),// Vccaux upper alarm limit 1.89V
  238.     .INIT_53(16'hdddd),// OT upper alarm limit 125 - see Thermal Management
  239.     .INIT_54(16'ha93a),// Temp lower alarm reset 60
  240.     .INIT_55(16'h5111),// Vccint lower alarm limit 0.95V
  241.     .INIT_56(16'h91Eb),// Vccaux lower alarm limit 1.71V
  242.     .INIT_57(16'hae4e),// OT lower alarm reset 70 - see Thermal Management
  243.     .INIT_58(16'h5999),// VCCBRAM upper alarm limit 1.05V
  244.     .SIM_MONITOR_FILE("design.txt")// Analog Stimulus file for simulation
  245. )
  246. XADC_INST (// Connect up instance IO. See UG480 for port descriptions
  247.     .CONVST (1'b0),// not used
  248.     .CONVSTCLK  (1'b0), // not used
  249.     .DADDR  (daddr),
  250.     .DCLK   (dclk_bufg),
  251.     .DEN    (den_reg[0]),
  252.     .DI     (di_drp),
  253.     .DWE    (dwe_reg[0]),
  254.     .RESET  (RESET),
  255.     .VAUXN  (vauxn_active ),
  256.     .VAUXP  (vauxp_active ),
  257.     .ALM    (ALM),
  258.     .BUSY   (busy),
  259.     .CHANNEL(CHANNEL),
  260.     .DO     (do_drp),
  261.     .DRDY   (drdy),
  262.     .EOC    (eoc),
  263.     .EOS    (eos),
  264.     .JTAGBUSY   (),// not used
  265.     .JTAGLOCKED (),// not used
  266.     .JTAGMODIFIED   (),// not used
  267.     .OT     (OT),
  268.     .MUXADDR    (),// not used
  269.     .VP     (VP),
  270.     .VN     (VN)
  271. );

  272.     assign vauxp_active = {12'h000, VAUXP[3:0]};
  273.     assign vauxn_active = {12'h000, VAUXN[3:0]};

  274.     assign EOC = eoc;
  275.     assign EOS = eos;

  276. endmodule


复制代码


1.3
UG480功能描述

上述代码主要是通过DRP访问时序进行配置、读取XADC模块的寄存器,从而得到需要的温度电压等相关信息。其中的XADC模块是调用Xilinx的原语设计的。各输出信号的意义如下表所示:

Table 1 ug480 信号说明

  

MEASURED_TEMP

  
  

测试所得的温度值

  
  

MEASURED_VCCINT

  
  

测试所得的VCCINT值

  
  

MEASURED_VCCAUX

  
  

测试所得的VCCAUX值

  
  

MEASURED_VCCBRAM

  
  

测试所得的VCCBRAM值

  
  

MEASURED_AUX0

  
  

4个模拟输入通道的监测

  
  

MEASURED_AUX1

  
  

MEASURED_AUX2

  
  

MEASURED_AUX3

  
  

ALM

  
  

警报信号,超出用户设置的值就会拉高.

  

bit[0]:温度

  

bit[1]: VCCINT

  

bit[2]: VCCAUX

  

bit[3]: VCCBRAM

  

bit[4]: VCCPINT

  

bit[5]: VCCPAUX

  

bit[6]: VCCO_DDR

  

bit[7]: bit[6:0]的逻辑或运算

  
  

CHANNEL

  
  

当前输出(更新)的类型,针对上述XADC的配置模式,其对应关系如下:

  

0x00:Temperatuere(MEASURED_TEMP)

  

0x01:VCCINT(MEASURED_VCCINT)

  

0x02:VCCAUX(MEASURED_VCCAUX)

  

0x06:VCCBRAM(MEASURED_VCCBRAM)

  

0x10:MEASURED_AUX0

  

0x11:MEASURED_AUX1

  

0x12:MEASURED_AUX2

  

0x13:MEASURED_AUX3

  
  

OT

  
  

Over Temperature,温度超出用户设置的阈值之后,该信号会拉高。

  
  

EOC

  
  

ADC转换结束标志,Active High.

  
  

EOS

  
  

状态寄存器访问结束标志,Active  High.每次刷新完状态寄存器,则给出一个EOS脉冲,此时DRP访问状态机会依次读取所有的状态寄存器。

  

从XADC的寄存器配置可以看出,温度的上限警报为85°C,超出温度(OT)的值为125°C,VCCINT上限警报为1.05V,VCCAUX上限警报为1.89V,VCCBRAM上限警报为1.05V。

Table 2 XADC ControlRegisters

  

Name

  
  

Address

  
  

Software

  

Attribute

  
  

Description

  
  

Configuration register 0

  
  

40h

  
  

INIT_40

  
  

XADC基本配置寄存器

  
  

Configuration register 1

  
  

41h

  
  

INIT_41

  
  

Configuration register 2

  
  

42h

  
  

INIT_42

  
  

Sequence registers

  
  

48h to 4Fh

  
  

INIT_48 to

  

INIT_4F

  
  

通道序列配置寄存器

  
  

Alarm registers

  
  

50h to 5Fh

  
  

INIT_50 to

  

INIT_5F

  
  

警报阈值配置寄存器

  

具体的寄存器配置介绍请参考Xilinx 官方手册UG480

ADC总是产生一个16位转换结果。但是只使用12bit的数据,这12位数据对应于16位状态寄存器中的12个MSB(最高位)。可以通过未使用的LSB(低四位)来最小化量化效应或通过求平均值或滤波来提高分辨率。对这12bit数据,需要做一个格式转换才能得到实际的摄氏度和电压值,温度转换方程如下:



Temp(℃)=(MEASURED_TEMP[15:4]* 503.975)/4096-273.15

电压转换方程如下:



VCCINT=(MEASURED_VCCINT[15:4]* 3)/4096

VCCAUX、VCCBRAM的电压转换方式和VCCINT一致。


这样,通过温度、电压转换方程即可得到较为精确的温度和电压。通过这个转换方程,可以看出例程中温度配置的警报阈值85file:///D:/Temp/msohtmlclip1/01/clip_image006.png是怎么得来的了:


同理,配置参数INIT_50给的是0xb5ed,那么温度阈值等于0xb5e * 503.975 / 4096 –273.15 = 84.89file:///D:/Temp/msohtmlclip1/01/clip_image006.png

1.4
XADCMIG 控制器使用技巧

一个FPGA内部只有一个ADC模块,当我们使用了MIG控制器的时候,在生成MIG控制器的过程中有一个选项提示是否使能XADC,这个时候我们不能使能这个XADC模块,否则会产生冲突。Disable了MIG控制器的内部XADC模块调用之后,MIG控制器会有一个输入温度的端口提供给用户,此时就需要在外部调用这个XADC这个模块,然后将温度值MEASURED_TEMP[15:4]给到这个端口。如下:

MIG制器Disable XADC:


figure 1 MIG XADC Disable

端口连接:





  1. .device_temp_i (  MEASURED_TEMP[15:4]     ),// input [11:0]      device_temp_i


复制代码

ug480例化使用:






  1.     ug480 ug480_inst(
  2.         //Input
  3.         .DCLK               (  Clk50M                   ),// Clock input for DRP
  4.         .RESET              (  !nRst                    ),//Active Hign
  5.         .VAUXP              (  4'h0                     ),// Auxiliary analog channel inputs
  6.         .VAUXN              (  4'h0                     ),// Auxiliary analog channel inputs
  7.         .VP                 (  1'b0                     ),// Dedicated and Hardwired Analog Input Pair
  8.         .VN                 (  1'b0                     ),// Dedicated and Hardwired Analog Input Pair
  9.         
  10.         //Output
  11.         .MEASURED_TEMP      (  MEASURED_TEMP[15:0]      ),
  12.         .MEASURED_VCCINT    (  MEASURED_VCCINT[15:0]    ),
  13.         .MEASURED_VCCAUX    (  MEASURED_VCCAUX[15:0]    ),
  14.         .MEASURED_VCCBRAM   (  MEASURED_VCCBRAM[15:0]   ),
  15.         .MEASURED_AUX0      (  MEASURED_AUX0[15:0]      ),
  16.         .MEASURED_AUX1      (  MEASURED_AUX1[15:0]      ),
  17.         .MEASURED_AUX2      (  MEASURED_AUX2[15:0]      ),
  18.         .MEASURED_AUX3      (  MEASURED_AUX3[15:0]      ),
  19.         .temp_ref           (  temp_ref                 ),
  20.         .ALM                (  ALM[7:0]                 ),
  21.         .CHANNEL            (  CHANNEL[4:0]             ),
  22.         .OT                 (  OT                       ),
  23.         .EOC                (  EOC                      ),
  24.         .EOS                (  EOS                      )
  25.     );
  26.    


复制代码

可以看出,ug480在例化使用时,VAUXP、VAUXN、VP、VN这几个信号直接给了0,是因为他们是用于前面提到的模数转换功能使用的,我们只使用了温度电压检测,因此这几个信号可以不用。复位信号高电平有效。


需要注意的是MIG控制器需要的温度值刷新时间间隔最小是116us,所以XADC模块使用时INIT_41这个寄存器必须设置为Continuous Seq Mode(例程中的默认设置就好),也就是按照轮训方式刷新。为了测试该轮训刷新时间,通过在7Seriers 160T测试EOS的频率为40Mhz(DCK给50M参考时钟),也就是说,ug480的配置模式在50M参考时钟的工作状态下,输出值的刷新时间是25ns.完全满足MIG的刷新时间要求。

其余输出信号如MEASURED_TEMP等可以直接提供给MCU读取,MCU读取之后用转换方程转换之后即可得到FPGA当前的工作温度和电压了。另外还可将ALM信号、OT信号以中断的形式反馈至MCU处理。

以上描述均属个人通过了解UG480之后在K7 160T测试之后得到的结论,若和UG480有冲突的地方,请以UG480为准。UG480参考文档

 楼主| 发表于 2018-3-23 14:16:37 | 显示全部楼层
第一次发帖~请各位大佬多多关照
发表于 2018-11-30 21:59:49 | 显示全部楼层
学习中。。。。
发表于 2018-12-11 19:37:46 | 显示全部楼层
thanks
发表于 2019-3-7 13:52:04 | 显示全部楼层
复位信号写成1‘b0有没有问题呢
发表于 2023-3-8 15:24:24 | 显示全部楼层
正找怎么用这玩意儿的文档呢,就找到奉献的楼主了,必须赞一个
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-3-28 21:25 , Processed in 0.026301 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表