You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

160 lines
3.2 KiB

  1. # Xilinx XADC support for 7 Series FPGAs
  2. #
  3. # The 7 Series FPGAs contain an on-chip 12 bit ADC that can probe die
  4. # temperature, internal power supply rail voltages as well as external
  5. # voltages. The XADC is available both from fabric as well as through the
  6. # JTAG TAP.
  7. #
  8. # This code implements access through the JTAG TAP.
  9. #
  10. # https://www.xilinx.com/support/documentation/user_guides/ug480_7Series_XADC.pdf
  11. # build a 32 bit DRP command for the XADC DR
  12. proc xadc_cmd {cmd addr data} {
  13. array set cmds {
  14. NOP 0x00
  15. READ 0x01
  16. WRITE 0x02
  17. }
  18. return [expr {($cmds($cmd) << 26) | ($addr << 16) | ($data << 0)}]
  19. }
  20. # XADC register addresses
  21. # Some addresses (status registers 0-3) have special function when written to.
  22. proc XADC {key} {
  23. array set addrs {
  24. TEMP 0x00
  25. LOCK 0x00
  26. VCCINT 0x01
  27. VCCAUX 0x02
  28. VAUXEN 0x02
  29. VPVN 0x03
  30. RESET 0x03
  31. VREFP 0x04
  32. VREFN 0x05
  33. VCCBRAM 0x06
  34. SUPAOFFS 0x08
  35. ADCAOFFS 0x09
  36. ADCAGAIN 0x0a
  37. VCCPINT 0x0d
  38. VCCPAUX 0x0e
  39. VCCODDR 0x0f
  40. VAUX0 0x10
  41. VAUX1 0x11
  42. VAUX2 0x12
  43. VAUX3 0x13
  44. VAUX4 0x14
  45. VAUX5 0x15
  46. VAUX6 0x16
  47. VAUX7 0x17
  48. VAUX8 0x18
  49. VAUX9 0x19
  50. VAUX10 0x1a
  51. VAUX11 0x1b
  52. VAUX12 0x1c
  53. VAUX13 0x1d
  54. VAUX14 0x1e
  55. VAUX15 0x1f
  56. SUPBOFFS 0x30
  57. ADCBOFFS 0x31
  58. ADCBGAIN 0x32
  59. FLAG 0x3f
  60. CFG0 0x40
  61. CFG1 0x41
  62. CFG2 0x42
  63. SEQ0 0x48
  64. SEQ1 0x49
  65. SEQ2 0x4a
  66. SEQ3 0x4b
  67. SEQ4 0x4c
  68. SEQ5 0x4d
  69. SEQ6 0x4e
  70. SEQ7 0x4f
  71. ALARM0 0x50
  72. ALARM1 0x51
  73. ALARM2 0x52
  74. ALARM3 0x53
  75. ALARM4 0x54
  76. ALARM5 0x55
  77. ALARM6 0x56
  78. ALARM7 0x57
  79. ALARM8 0x58
  80. ALARM9 0x59
  81. ALARM10 0x5a
  82. ALARM11 0x5b
  83. ALARM12 0x5c
  84. ALARM13 0x5d
  85. ALARM14 0x5e
  86. ALARM15 0x5f
  87. }
  88. return $addrs($key)
  89. }
  90. # Select the XADC DR
  91. proc xadc_select {tap} {
  92. set XADC_IR 0x37
  93. irscan $tap $XADC_IR
  94. runtest 10
  95. }
  96. # XADC transfer
  97. proc xadc_xfer {tap cmd addr data} {
  98. set ret [drscan $tap 32 [xadc_cmd $cmd $addr $data]]
  99. runtest 10
  100. return [expr "0x$ret"]
  101. }
  102. # XADC register write
  103. proc xadc_write {tap addr data} {
  104. xadc_xfer $tap WRITE $addr $data
  105. }
  106. # XADC register read, non-pipelined
  107. proc xadc_read {tap addr} {
  108. xadc_xfer $tap READ $addr 0
  109. return [xadc_xfer $tap NOP 0 0]
  110. }
  111. # convert 16 bit register code from ADC measurement on
  112. # external voltages (VAUX) to Volt
  113. proc xadc_volt {code} {
  114. return [expr {$code * 1./(1 << 16)}]
  115. }
  116. # convert 16 bit temperature measurement to Celsius
  117. proc xadc_temp {code} {
  118. return [expr {$code * 503.975/(1 << 16) - 273.15}]
  119. }
  120. # convert 16 bit suppply voltage measurement to Volt
  121. proc xadc_sup {code} {
  122. return [expr {$code * 3./(1 << 16)}]
  123. }
  124. # perform a single channel measurement using default settings
  125. proc xadc_single {tap ch} {
  126. set cfg0 [xadc_read $tap [XADC CFG0]]
  127. set cfg1 [xadc_read $tap [XADC CFG1]]
  128. # set channel
  129. xadc_write $tap [XADC CFG0] $cfg0
  130. # single channel, disable the sequencer
  131. xadc_write $tap [XADC CFG1] 0x3000
  132. # leave some time for the conversion
  133. runtest 100
  134. set ret [xadc_read $tap [XADC $ch]]
  135. # restore CFG0/1
  136. xadc_write $tap [XADC CFG0] $cfg0
  137. xadc_write $tap [XADC CFG1] $cfg1
  138. return $ret
  139. }
  140. # measure all internal voltages
  141. proc xadc_report {tap} {
  142. xadc_select $tap
  143. echo "TEMP [format %.2f [xadc_temp [xadc_single $tap TEMP]]] C"
  144. foreach ch [list VCCINT VCCAUX VCCBRAM VPVN VREFP VREFN \
  145. VCCPINT VCCPAUX VCCODDR] {
  146. echo "$ch [format %.3f [xadc_sup [xadc_single $tap $ch]]] V"
  147. }
  148. }