add support for DRP on XADC
The design is backward-compatible in functionality for users who don't want to use DRP. That is, on power on, the XADC will scan the supply and temperature and store them in CSRs. If drp_enable is set, the scanning stops, and the XADC is now controlled by the DRP bus. Wher drp_enable is reset, the XADC may return to an auto-sample mode, but only if the internal registers are configured to do this. If you return to drp_enable without, for example, turning on the continuous sequence and setting which channels to check, the results will be unpredictable (mostly either it'll scan just once and stop, or it'll not scan all the channels, depending on the register settings). At this point, the backward compatibility was confirmed in testing, the DRP API is still a work in progress as the application this is being developed for needs to support fun stuff like real time sampling of signals to a buffer. Down the road, this block may have to be modified again to support an output FIFO, so we're not railing the CPU trying to do real time sampling of ADC data. This will probably be added as a True/False flag of some sort in the parameter list, because the FIFO will be expensive as far as BRAM goes to implement and applications that don't need the FIFO buffer can probably use that BRAM for better things.
This commit is contained in:
parent
219bb7f294
commit
56ccaeebf0
|
@ -7,12 +7,42 @@ 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):
|
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 = CSRStatus() # 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)
|
||||||
|
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) = adc_value*)/4096*3
|
# Voltage(V) = as uadc_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)
|
||||||
|
@ -28,8 +58,17 @@ class XADC(Module, AutoCSR):
|
||||||
eoc = Signal()
|
eoc = Signal()
|
||||||
eos = Signal()
|
eos = Signal()
|
||||||
data = Signal(16)
|
data = Signal(16)
|
||||||
drdy = Signal()
|
|
||||||
|
|
||||||
|
auto = Signal()
|
||||||
|
self.comb += auto.eq(~self.drp_enable.status)
|
||||||
|
adr = Signal(7)
|
||||||
|
self.comb += [
|
||||||
|
If(auto,
|
||||||
|
adr.eq(channel),
|
||||||
|
).Else(
|
||||||
|
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,
|
||||||
|
@ -44,12 +83,14 @@ class XADC(Module, AutoCSR):
|
||||||
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_OT=self.ot,
|
||||||
o_BUSY=busy, o_CHANNEL=channel, o_EOC=eoc, o_EOS=eos,
|
o_BUSY=busy, o_CHANNEL=channel, o_EOC=eoc, o_EOS=eos,
|
||||||
i_VAUXN=0, i_VAUXP=1, i_VN=0, i_VP=1,
|
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(),
|
i_CONVST=0, i_CONVSTCLK=0, i_RESET=ResetSignal(),
|
||||||
o_DO=data, o_DRDY=drdy, i_DADDR=channel, i_DCLK=ClockSignal(),
|
o_DO=data, o_DRDY=drp_drdy, i_DADDR=adr, i_DCLK=ClockSignal(),
|
||||||
i_DEN=eoc, i_DI=0, i_DWE=0,
|
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_JTAGBUSY=, o_JTAGLOCKED=, o_JTAGMODIFIED=, o_MUXADDR=,
|
||||||
)
|
)
|
||||||
|
self.comb += self.drp_dat_r.status.eq(data)
|
||||||
|
|
||||||
channels = {
|
channels = {
|
||||||
0: self.temperature,
|
0: self.temperature,
|
||||||
|
@ -59,7 +100,7 @@ class XADC(Module, AutoCSR):
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(drdy,
|
If(drp_drdy & auto,
|
||||||
Case(channel, dict(
|
Case(channel, dict(
|
||||||
(k, v.status.eq(data >> 4))
|
(k, v.status.eq(data >> 4))
|
||||||
for k, v in channels.items()))
|
for k, v in channels.items()))
|
||||||
|
|
Loading…
Reference in New Issue