diff --git a/litex/soc/cores/xadc.py b/litex/soc/cores/xadc.py index 5244b8fe0..551738ac6 100644 --- a/litex/soc/cores/xadc.py +++ b/litex/soc/cores/xadc.py @@ -1,4 +1,6 @@ -# Copyright 2014-2015 Robert Jordens +# This file is Copyright (c) 2014-2015 Robert Jordens +# This file is Copyright (c) 2019 bunnie +# This file is Copyright (c) 2019 Florent Kermarrec # License: BSD from migen import * @@ -7,76 +9,45 @@ from litex.soc.interconnect.csr 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, @@ -87,39 +58,77 @@ class XADC(Module, AutoCSR): 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) + ) + ]