soc/core/xadc: cleanup, simplify and add expose_drp method - keep CSR ordering with older version, requested for software compatibility. - always enable analog capability (user will just not use it if not needed). - add expose_drp method (similar to clock.py) for cases where DRP is needed.
This commit is contained in:
parent
5eec7432b8
commit
4dc0a61428
|
@ -1,4 +1,6 @@
|
||||||
# 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
|
# License: BSD
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
@ -7,76 +9,45 @@ from litex.soc.interconnect.csr import *
|
||||||
|
|
||||||
# XADC ---------------------------------------------------------------------------------------------
|
# XADC ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
analog_layout = [("vauxp", 16), ("vauxn", 16), ("vp", 1), ("vn", 1)]
|
|
||||||
|
|
||||||
class XADC(Module, AutoCSR):
|
class XADC(Module, AutoCSR):
|
||||||
def __init__(self, analog=None):
|
def __init__(self):
|
||||||
# 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)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Temperature(°C) = adc_value*503.975/4096 - 273.15
|
# Temperature(°C) = adc_value*503.975/4096 - 273.15
|
||||||
self.temperature = CSRStatus(12)
|
self.temperature = CSRStatus(12)
|
||||||
|
|
||||||
# Voltage(V) = as uadc_value*)/4096*3
|
# Voltage(V) = adc_value*)/4096*3
|
||||||
self.vccint = CSRStatus(12)
|
self.vccint = CSRStatus(12)
|
||||||
self.vccaux = CSRStatus(12)
|
self.vccaux = CSRStatus(12)
|
||||||
self.vccbram = CSRStatus(12)
|
self.vccbram = CSRStatus(12)
|
||||||
|
|
||||||
|
# End of Convertion/Sequence
|
||||||
|
self.eoc = CSRStatus()
|
||||||
|
self.eos = CSRStatus()
|
||||||
|
|
||||||
# Alarms
|
# Alarms
|
||||||
self.alarm = Signal(8)
|
self.alarm = Signal(8)
|
||||||
self.ot = Signal()
|
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()
|
busy = Signal()
|
||||||
channel = Signal(7)
|
channel = Signal(7)
|
||||||
eoc = Signal()
|
eoc = Signal()
|
||||||
eos = Signal()
|
eos = Signal()
|
||||||
data = Signal(16)
|
|
||||||
|
|
||||||
auto = Signal()
|
# XADC instance ----------------------------------------------------------------------------
|
||||||
self.comb += auto.eq(~self.drp_enable.storage)
|
self.dwe = Signal()
|
||||||
adr = Signal(7)
|
self.den = Signal()
|
||||||
self.comb += [
|
self.drdy = Signal()
|
||||||
If(auto,
|
self.dadr = Signal(7)
|
||||||
adr.eq(channel),
|
self.di = Signal(16)
|
||||||
).Else(
|
self.do = Signal(16)
|
||||||
adr.eq(self.drp_adr.storage)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
self.specials += Instance("XADC",
|
self.specials += Instance("XADC",
|
||||||
# from ug480
|
# From ug480
|
||||||
p_INIT_40=0x9000, p_INIT_41=0x2ef0, p_INIT_42=0x0400,
|
p_INIT_40=0x9000, p_INIT_41=0x2ef0, p_INIT_42=0x0400,
|
||||||
p_INIT_48=0x4701, p_INIT_49=0x000f,
|
p_INIT_48=0x4701, p_INIT_49=0x000f,
|
||||||
p_INIT_4A=0x4700, p_INIT_4B=0x0000,
|
p_INIT_4A=0x4700, p_INIT_4B=0x0000,
|
||||||
|
@ -87,39 +58,77 @@ class XADC(Module, AutoCSR):
|
||||||
p_INIT_54=0xa93a, p_INIT_55=0x5111,
|
p_INIT_54=0xa93a, p_INIT_55=0x5111,
|
||||||
p_INIT_56=0x91eb, p_INIT_57=0xae4e,
|
p_INIT_56=0x91eb, p_INIT_57=0xae4e,
|
||||||
p_INIT_58=0x5999, p_INIT_5C=0x5111,
|
p_INIT_58=0x5999, p_INIT_5C=0x5111,
|
||||||
o_ALM=self.alarm, o_OT=self.ot,
|
o_ALM = self.alarm,
|
||||||
o_BUSY=busy, o_CHANNEL=channel, o_EOC=eoc, o_EOS=eos,
|
o_OT = self.ot,
|
||||||
i_VAUXN=analog.vauxn, i_VAUXP=analog.vauxp, i_VN=analog.vn, i_VP=analog.vp,
|
o_BUSY = busy,
|
||||||
i_CONVST=0, i_CONVSTCLK=0, i_RESET=ResetSignal(),
|
o_CHANNEL = channel,
|
||||||
o_DO=data, o_DRDY=drp_drdy, i_DADDR=adr, i_DCLK=ClockSignal(),
|
o_EOC = eoc,
|
||||||
i_DEN=(auto & eoc) | (~auto & (self.drp_read.re | self.drp_write.re)),
|
o_EOS = eos,
|
||||||
i_DI=self.drp_dat_w.storage, i_DWE=self.drp_write.re,
|
i_VAUXN = self.analog.vauxn,
|
||||||
# o_JTAGBUSY=, o_JTAGLOCKED=, o_JTAGMODIFIED=, o_MUXADDR=,
|
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 += [
|
self.comb += [
|
||||||
If(drp_drdy,
|
self.den.eq(eoc),
|
||||||
self.drp_dat_r.status.eq(data),
|
self.dadr.eq(channel),
|
||||||
).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),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Channels update --------------------------------------------------------------------------
|
||||||
channels = {
|
channels = {
|
||||||
0: self.temperature,
|
0: self.temperature,
|
||||||
1: self.vccint,
|
1: self.vccint,
|
||||||
2: self.vccaux,
|
2: self.vccaux,
|
||||||
6: self.vccbram
|
6: self.vccbram
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(drp_drdy & auto,
|
If(self.drdy,
|
||||||
Case(channel, dict(
|
Case(channel, dict(
|
||||||
(k, v.status.eq(data >> 4))
|
(k, v.status.eq(self.do >> 4))
|
||||||
for k, v in channels.items()))
|
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)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in New Issue