1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Xilinx XADC support for 7 Series FPGAs
5 # The 7 Series FPGAs contain an on-chip 12 bit ADC that can probe die
6 # temperature, internal power supply rail voltages as well as external
7 # voltages. The XADC is available both from fabric as well as through the
10 # This code implements access through the JTAG TAP.
12 # https://www.xilinx.com/support/documentation/user_guides/ug480_7Series_XADC.pdf
14 # build a 32 bit DRP command for the XADC DR
15 proc xadc_cmd {cmd addr data} {
21 return [expr {($cmds($cmd) << 26) | ($addr << 16) | ($data << 0)}]
24 # XADC register addresses
25 # Some addresses (status registers 0-3) have special function when written to.
96 proc xadc_select {tap} {
103 proc xadc_xfer {tap cmd addr data} {
104 set ret [drscan $tap 32 [xadc_cmd $cmd $addr $data]]
106 return [expr "0x$ret"]
109 # XADC register write
110 proc xadc_write {tap addr data} {
111 xadc_xfer $tap WRITE $addr $data
114 # XADC register read, non-pipelined
115 proc xadc_read {tap addr} {
116 xadc_xfer $tap READ $addr 0
117 return [xadc_xfer $tap NOP 0 0]
120 # convert 16 bit register code from ADC measurement on
121 # external voltages (VAUX) to Volt
122 proc xadc_volt {code} {
123 return [expr {$code * 1./(1 << 16)}]
126 # convert 16 bit temperature measurement to Celsius
127 proc xadc_temp {code} {
128 return [expr {$code * 503.975/(1 << 16) - 273.15}]
131 # convert 16 bit suppply voltage measurement to Volt
132 proc xadc_sup {code} {
133 return [expr {$code * 3./(1 << 16)}]
136 # perform a single channel measurement using default settings
137 proc xadc_single {tap ch} {
138 set cfg0 [xadc_read $tap [XADC CFG0]]
139 set cfg1 [xadc_read $tap [XADC CFG1]]
141 xadc_write $tap [XADC CFG0] $cfg0
142 # single channel, disable the sequencer
143 xadc_write $tap [XADC CFG1] 0x3000
144 # leave some time for the conversion
146 set ret [xadc_read $tap [XADC $ch]]
148 xadc_write $tap [XADC CFG0] $cfg0
149 xadc_write $tap [XADC CFG1] $cfg1
153 # measure all internal voltages
154 proc xadc_report {tap} {
156 echo "TEMP [format %.2f [xadc_temp [xadc_single $tap TEMP]]] C"
157 foreach ch [list VCCINT VCCAUX VCCBRAM VPVN VREFP VREFN \
158 VCCPINT VCCPAUX VCCODDR] {
159 echo "$ch [format %.3f [xadc_sup [xadc_single $tap $ch]]] V"