-# Copyright 2014-2015 Robert Jordens <jordens@gmail.com>
+# This file is Copyright (c) 2014-2015 Robert Jordens <jordens@gmail.com>
+# This file is Copyright (c) 2019 bunnie <bunnie@kosagi.com>
+# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
from migen import *
# XADC ---------------------------------------------------------------------------------------------
-analog_layout = [("vauxp", 16), ("vauxn", 16), ("vp", 1), ("vn", 1)]
-
class XADC(Module, AutoCSR):
- def __init__(self, analog=None):
- # add a CSR bank for controlling the XADC DRP. Adds bloat to the gateware
- # if you're not using this feature, but makes the code more elegant.
- self.drp_enable = CSRStorage() # must set this to 1 to use DRP, otherwise auto-sample
- self.drp_read = CSR()
- self.drp_write = CSR()
- self.drp_drdy = CSRStatus()
- self.drp_adr = CSRStorage(7)
- self.drp_dat_w = CSRStorage(16)
- self.drp_dat_r = CSRStatus(16)
-
- # monitor EOC/EOS so we can poll if the ADC has been updated
- self.eoc = CSRStatus()
- self.eos = CSRStatus()
- # TODO: hook up the alarm as interrupt
-
- drp_drdy = Signal()
-
- if analog == None:
- analog = Record(analog_layout)
- self.comb += [
- analog.vauxp.eq(0),
- analog.vauxn.eq(0),
- analog.vp.eq(0),
- analog.vn.eq(0),
- ]
-
- self.sync += [
- If(self.drp_read.re | self.drp_write.re,
- self.drp_drdy.status.eq(0)
- ).Elif(drp_drdy,
- self.drp_drdy.status.eq(1)
- )
- ]
-
+ def __init__(self):
# Temperature(°C) = adc_value*503.975/4096 - 273.15
self.temperature = CSRStatus(12)
- # Voltage(V) = as uadc_value*)/4096*3
+ # Voltage(V) = adc_value*)/4096*3
self.vccint = CSRStatus(12)
self.vccaux = CSRStatus(12)
self.vccbram = CSRStatus(12)
+ # End of Convertion/Sequence
+ self.eoc = CSRStatus()
+ self.eos = CSRStatus()
+
# Alarms
self.alarm = Signal(8)
self.ot = Signal()
+ # Analog
+ self.analog = Record([("vauxp", 16), ("vauxn", 16), ("vp", 1), ("vn", 1)])
+ self.analog.vauxp.reset = 1
+ self.analog.vp.reset = 1
+
# # #
busy = Signal()
channel = Signal(7)
eoc = Signal()
eos = Signal()
- data = Signal(16)
- auto = Signal()
- self.comb += auto.eq(~self.drp_enable.storage)
- adr = Signal(7)
- self.comb += [
- If(auto,
- adr.eq(channel),
- ).Else(
- adr.eq(self.drp_adr.storage)
- )
- ]
+ # XADC instance ----------------------------------------------------------------------------
+ self.dwe = Signal()
+ self.den = Signal()
+ self.drdy = Signal()
+ self.dadr = Signal(7)
+ self.di = Signal(16)
+ self.do = Signal(16)
self.specials += Instance("XADC",
- # from ug480
+ # From ug480
p_INIT_40=0x9000, p_INIT_41=0x2ef0, p_INIT_42=0x0400,
p_INIT_48=0x4701, p_INIT_49=0x000f,
p_INIT_4A=0x4700, p_INIT_4B=0x0000,
p_INIT_54=0xa93a, p_INIT_55=0x5111,
p_INIT_56=0x91eb, p_INIT_57=0xae4e,
p_INIT_58=0x5999, p_INIT_5C=0x5111,
- o_ALM=self.alarm, o_OT=self.ot,
- o_BUSY=busy, o_CHANNEL=channel, o_EOC=eoc, o_EOS=eos,
- i_VAUXN=analog.vauxn, i_VAUXP=analog.vauxp, i_VN=analog.vn, i_VP=analog.vp,
- i_CONVST=0, i_CONVSTCLK=0, i_RESET=ResetSignal(),
- o_DO=data, o_DRDY=drp_drdy, i_DADDR=adr, i_DCLK=ClockSignal(),
- i_DEN=(auto & eoc) | (~auto & (self.drp_read.re | self.drp_write.re)),
- i_DI=self.drp_dat_w.storage, i_DWE=self.drp_write.re,
- # o_JTAGBUSY=, o_JTAGLOCKED=, o_JTAGMODIFIED=, o_MUXADDR=,
+ o_ALM = self.alarm,
+ o_OT = self.ot,
+ o_BUSY = busy,
+ o_CHANNEL = channel,
+ o_EOC = eoc,
+ o_EOS = eos,
+ i_VAUXN = self.analog.vauxn,
+ i_VAUXP = self.analog.vauxp,
+ i_VN = self.analog.vn,
+ i_VP = self.analog.vp,
+ i_CONVST = 0,
+ i_CONVSTCLK = 0,
+ i_RESET = ResetSignal(),
+ i_DCLK = ClockSignal(),
+ i_DWE = self.dwe,
+ i_DEN = self.den,
+ o_DRDY = self.drdy,
+ i_DADDR = self.dadr,
+ i_DI = self.di,
+ o_DO = self.do
)
- self.sync += [
- If(drp_drdy,
- self.drp_dat_r.status.eq(data),
- ).Else(
- self.drp_dat_r.status.eq(self.drp_dat_r.status),
- )
- ]
-
- self.sync += [
- self.eoc.status.eq((~self.eoc.we & self.eoc.status) | eoc),
- self.eos.status.eq((~self.eos.we & self.eos.status) | eos),
+ self.comb += [
+ self.den.eq(eoc),
+ self.dadr.eq(channel),
]
+ # Channels update --------------------------------------------------------------------------
channels = {
0: self.temperature,
1: self.vccint,
2: self.vccaux,
6: self.vccbram
}
-
self.sync += [
- If(drp_drdy & auto,
+ If(self.drdy,
Case(channel, dict(
- (k, v.status.eq(data >> 4))
+ (k, v.status.eq(self.do >> 4))
for k, v in channels.items()))
)
]
+
+ # End of Convertion/Sequence update --------------------------------------------------------
+ self.sync += [
+ self.eoc.status.eq((self.eoc.status & ~self.eoc.we) | eoc),
+ self.eos.status.eq((self.eos.status & ~self.eos.we) | eos),
+ ]
+
+ def expose_drp(self):
+ self.drp_enable = CSRStorage() # Set to 1 to use DRP and disable auto-sampling
+ self.drp_read = CSR()
+ self.drp_write = CSR()
+ self.drp_drdy = CSRStatus()
+ self.drp_adr = CSRStorage(7)
+ self.drp_dat_w = CSRStorage(16)
+ self.drp_dat_r = CSRStatus(16)
+
+ # # #
+
+ self.comb += [
+ self.dwe.eq(self.drp_write.re),
+ self.di.eq(self.drp_dat_w.storage),
+ self.drp_dat_r.status.eq(self.do),
+ If(self.drp_enable.storage,
+ self.den.eq(self.drp_read.re | self.drp_write.re),
+ self.dadr.eq(self.drp_adr.storage),
+ ),
+ ]
+ self.sync += [
+ If(self.drp_read.re | self.drp_write.re,
+ self.drp_drdy.status.eq(0)
+ ).Elif(self.drdy,
+ self.drp_drdy.status.eq(1)
+ )
+ ]