From 8b36649c89b9b98d40988c520efe1efe23460a30 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 10 Feb 2023 10:08:16 +0100 Subject: [PATCH] cores/xadc: Re-arrange and simplify code a bit. --- litex/soc/cores/xadc.py | 365 ++++++++++++++++++++++------------------ 1 file changed, 197 insertions(+), 168 deletions(-) diff --git a/litex/soc/cores/xadc.py b/litex/soc/cores/xadc.py index 6d5239ece..d3d9862a4 100644 --- a/litex/soc/cores/xadc.py +++ b/litex/soc/cores/xadc.py @@ -2,7 +2,7 @@ # This file is part of LiteX. # # Copyright (c) 2014-2015 Robert Jordens -# Copyright (c) 2019-2021 Florent Kermarrec +# Copyright (c) 2019-2023 Florent Kermarrec # Copyright (c) 2019 bunnie # Copyright (c) 2021 Vamsi K Vytla # Copyright (c) 2022 Sylvain Munaut @@ -10,15 +10,28 @@ from migen import * +from litex.gen import LiteXModule + from litex.soc.interconnect.csr import * # Layouts ----------------------------------------------------------------------------------------- analog_layout = [("vauxp", 16), ("vauxn", 16), ("vp", 1), ("vn", 1)] -# Xilinx System Monitor DRP ------------------------------------------------------------------------ +# Xilinx System Monitor ---------------------------------------------------------------------------- + +class XilinxSystemMonitorChannel: + def __init__(self, name, addr, bits, desc): + self.name = name + self.addr = addr + self.bits = bits + self.desc = "\n".join(desc) if isinstance(desc, list) else desc + +class XilinxSystemMonitor(LiteXModule): + def add_channel(self, channel): + setattr(self, channel.name, CSRStatus(channel.bits, name=channel.name, description=channel.desc)) + channel.status = getattr(self, channel.name).status -class SystemMonitorDRP(Module, AutoCSR): def expose_drp(self): self.drp_enable = CSRStorage() # Set to 1 to use DRP and disable auto-sampling. self.drp_read = CSR() @@ -53,25 +66,34 @@ class SystemMonitorDRP(Module, AutoCSR): # Xilinx 7-Series System Monitor ------------------------------------------------------------------- -class S7SystemMonitor(SystemMonitorDRP, AutoCSR): - dadr_size = 7 +S7SystemMonitorChannels = [ + XilinxSystemMonitorChannel(name="temperature", addr=0x0, bits=12, desc=[ + "Raw Temperature value from XADC.", + "Temperature (°C) = ``Value`` x 503.975 / 4096 - 273.15.", + ]), + XilinxSystemMonitorChannel(name="vccint", addr=0x1, bits=12, desc=[ + "Raw VCCINT value from XADC.", + "VCCINT (V) = ``Value`` x 3 / 4096.", + ]), + XilinxSystemMonitorChannel(name="vccaux", addr=0x2, bits=12, desc=[ + "Raw VCCAUX value from XADC.", + "VCCAUX (V) = ``Value`` x 3 / 4096.", + ]), + XilinxSystemMonitorChannel(name="vccbram", addr=0x6, bits=12, desc=[ + "Raw VCCBRAM value from XADC.", + "VCCBRAM (V) = ``Value`` x 3 / 4096.", + ]), +] - def __init__(self, analog_pads=None): - # Temperature - self.temperature = CSRStatus(12, description="""Raw Temperature value from XADC.\n - Temperature (°C) = ``Value`` x 503.975 / 4096 - 273.15.""") - - # Voltages - self.vccint = CSRStatus(12, description="""Raw VCCINT value from XADC.\n - VCCINT (V) = ``Value`` x 3 / 4096.""") - self.vccaux = CSRStatus(12, description="""Raw VCCAUX value from XADC.\n - VCCAUX (V) = ``Value`` x 3 / 4096.""") - self.vccbram = CSRStatus(12, description="""Raw VCCBRAM value from XADC.\n - VCCBRAM (V) = ``Value`` x 3 / 4096.""") +class S7SystemMonitor(XilinxSystemMonitor): + def __init__(self, channels=S7SystemMonitorChannels, analog_pads=None): + # Channels. + for channel in channels: + self.add_channel(channel) # End of Convertion/Sequence self.eoc = CSRStatus(description="End of Convertion Status, ``1``: Convertion Done.") - self.eos = CSRStatus(description="End of Sequence Status, ``1``: Sequence Done.") + self.eos = CSRStatus(description="End of Sequence Status, ``1``: Sequence Done.") # Alarms self.alarm = Signal(8) @@ -85,25 +107,25 @@ class S7SystemMonitor(SystemMonitorDRP, AutoCSR): eos = Signal() # XADC instance. - self.dwe = Signal() - self.den = Signal() - self.drdy = Signal() - self.dadr = Signal(7) - self.di = Signal(16) - self.do = Signal(16) + self.dwe = Signal() + self.den = Signal() + self.drdy = Signal() + self.dadr = Signal(7) + self.di = Signal(16) + self.do = Signal(16) self.drp_en = Signal() self.specials += Instance("XADC", # 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_4C=0x0000, p_INIT_4D=0x0000, - p_INIT_4E=0x0000, p_INIT_4F=0x0000, - p_INIT_50=0xb5ed, p_INIT_51=0x5999, - p_INIT_52=0xa147, p_INIT_53=0xdddd, - p_INIT_54=0xa93a, p_INIT_55=0x5111, - p_INIT_56=0x91eb, p_INIT_57=0xae4e, - p_INIT_58=0x5999, p_INIT_5C=0x5111, + 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_4C = 0x0000, p_INIT_4D = 0x0000, + p_INIT_4E = 0x0000, p_INIT_4F = 0x0000, + p_INIT_50 = 0xb5ed, p_INIT_51 = 0x5999, + p_INIT_52 = 0xa147, p_INIT_53 = 0xdddd, + 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, @@ -116,8 +138,8 @@ class S7SystemMonitor(SystemMonitorDRP, AutoCSR): i_VN = 0 if analog_pads is None else analog_pads.vn, i_CONVST = 0, i_CONVSTCLK = 0, - i_RESET = ResetSignal(), - i_DCLK = ClockSignal(), + i_RESET = ResetSignal("sys"), + i_DCLK = ClockSignal("sys"), i_DWE = self.dwe, i_DEN = self.den, o_DRDY = self.drdy, @@ -125,49 +147,58 @@ class S7SystemMonitor(SystemMonitorDRP, AutoCSR): i_DI = self.di, o_DO = self.do ) - self.comb += [ - If(~self.drp_en, - self.den.eq(eoc), - self.dadr.eq(channel), - ) - ] + + # DRP. + self.comb += If(~self.drp_en, + self.den.eq(eoc), + self.dadr.eq(channel), + ) # Channels update. - channels = { - 0x0 : self.temperature, - 0x1 : self.vccint, - 0x2 : self.vccaux, - 0x6 : self.vccbram - } - self.sync += [ - If(self.drdy, - Case(channel, dict( - (k, v.status.eq(self.do >> 4)) - for k, v in channels.items())) - ) - ] + channel_cases = dict(zip( + [c.addr for c in channels], + [c.status.eq(self.do >> 4) for c in channels], + )) + self.sync += If(self.drdy, Case(channel, channel_cases)) - # End of Convertion/Sequence update. + # End of Conversion/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), ] -class XADC(S7SystemMonitor): pass +class XADC(S7SystemMonitor): pass # For compat. # Xilinx Ultrascale System Monitor ----------------------------------------------------------------- -class USFamilySystemMonitor(SystemMonitorDRP, AutoCSR): - dadr_size = 8 +USSystemMonitorChannels = [ + XilinxSystemMonitorChannel(name="temperature", addr=0x0, bits=10, desc=[ + "Raw Temperature value from SYSMONE1.", + "Temperature (°C) = ``Value`` x 503.975 / 1024 - 273.15.", + ]), + XilinxSystemMonitorChannel(name="vccint", addr=0x1, bits=10, desc=[ + "Raw VCCINT value from SYSMONE1.", + "VCCINT (V) = ``Value`` x 3 / 1024.", + ]), + XilinxSystemMonitorChannel(name="vccaux", addr=0x2, bits=10, desc=[ + "Raw VCCAUX value from SYSMONE1.", + "VCCAUX (V) = ``Value`` x 3 / 1024.", + ]), + XilinxSystemMonitorChannel(name="vccbram", addr=0x6, bits=10, desc=[ + "Raw VCCBRAM value from SYSMONE1.", + "VCCBRAM (V) = ``Value`` x 3 / 1024.", + ]), +] - def __init__(self, analog_pads=None): - # Channels CSRs - for reg_addr, name, desc in self._channels: - setattr(self, name, CSRStatus(10, name=name, description=desc)) +class USSystemMonitor(XilinxSystemMonitor): + def __init__(self, channels=USSystemMonitorChannels, primitive="SYSMONE1", sim_device="ULTRASCALE", analog_pads=None): + # Channels. + for channel in channels: + self.add_channel(channel) # End of Convertion/Sequence self.eoc = CSRStatus(description="End of Conversion Status, ``1``: Conversion Done.") - self.eos = CSRStatus(description="End of Sequence Status, ``1``: Sequence Done.") + self.eos = CSRStatus(description="End of Sequence Status, ``1``: Sequence Done.") # Alarms self.alarm = Signal(16) @@ -176,71 +207,68 @@ class USFamilySystemMonitor(SystemMonitorDRP, AutoCSR): # # # busy = Signal() - channel = Signal(self.dadr_size) + channel = Signal(8) eoc = Signal() eos = Signal() - # SYSMONE1 instance ------------------------------------------------------------------------ - self.dwe = Signal() - self.den = Signal() - self.drdy = Signal() - self.dadr = Signal(self.dadr_size) - self.di = Signal(16) - self.do = Signal(16) + # SYSMOM instance. + self.dwe = Signal() + self.den = Signal() + self.drdy = Signal() + self.dadr = Signal(8) + self.di = Signal(16) + self.do = Signal(16) self.drp_en = Signal() - - params = dict( + self.params = dict() + if sim_device is not None: + self.params.update(p_SIM_DEVICE=sim_device) + self.params.update( # From UG580 - p_INIT_40=0x9000, p_INIT_41=0x2fd0, p_INIT_42=0x1000, - p_INIT_46=0x000f, p_INIT_48=0x4701, p_INIT_49=0x000f, - p_INIT_47=0x000f, p_INIT_4A=0x47e0, p_INIT_4B=0x0000, - p_INIT_4C=0x0000, p_INIT_4D=0x0000, - p_INIT_4E=0x0000, p_INIT_4F=0x0000, - p_INIT_50=0xb5ed, p_INIT_51=0x5999, - p_INIT_52=0xa147, p_INIT_53=0xdddd, - 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_VAUXP = 0 if analog_pads is None else analog_pads.vauxp, - i_VAUXN = 0 if analog_pads is None else analog_pads.vauxn, - i_VP = 0 if analog_pads is None else analog_pads.vp, - i_VN = 0 if analog_pads is None else analog_pads.vn, - 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 + p_INIT_40 = 0x9000, p_INIT_41 = 0x2fd0, p_INIT_42 = 0x1000, + p_INIT_46 = 0x000f, p_INIT_48 = 0x4701, p_INIT_49 = 0x000f, + p_INIT_47 = 0x000f, p_INIT_4A = 0x47e0, p_INIT_4B = 0x0000, + p_INIT_4C = 0x0000, p_INIT_4D = 0x0000, + p_INIT_4E = 0x0000, p_INIT_4F = 0x0000, + p_INIT_50 = 0xb5ed, p_INIT_51 = 0x5999, + p_INIT_52 = 0xa147, p_INIT_53 = 0xdddd, + 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_VAUXP = 0 if analog_pads is None else analog_pads.vauxp, + i_VAUXN = 0 if analog_pads is None else analog_pads.vauxn, + i_VP = 0 if analog_pads is None else analog_pads.vp, + i_VN = 0 if analog_pads is None else analog_pads.vn, + i_CONVST = 0, + i_CONVSTCLK = 0, + i_RESET = ResetSignal("sys"), + i_DCLK = ClockSignal("sys"), + i_DWE = self.dwe, + i_DEN = self.den, + o_DRDY = self.drdy, + i_DADDR = self.dadr, + i_DI = self.di, + o_DO = self.do ) - if self._sim_device is not None: - params['p_SIM_DEVICE'] = self._sim_device - self.specials += Instance(self._block_name, **params) + self.specials += Instance(primitive, self.params) - self.comb += [ - If(~self.drp_en, - self.den.eq(eoc), - self.dadr.eq(channel), - ) - ] + # DRP. + self.comb += If(~self.drp_en, + self.den.eq(eoc), + self.dadr.eq(channel), + ) # Channels update. - self.sync += [ - If(self.drdy, - Case(channel, dict( - (reg_addr, getattr(self, name).status.eq((self.do >> 6) & 0x3ff)) - for reg_addr, name, desc in self._channels)) - ) - ] + channel_cases = dict(zip( + [c.addr for c in channels], + [c.status.eq((self.do >> 6) & 0x3ff) for c in channels], + )) + self.sync += If(self.drdy, Case(channel, channel_cases)) # End of Convertion/Sequence update. self.sync += [ @@ -248,55 +276,56 @@ class USFamilySystemMonitor(SystemMonitorDRP, AutoCSR): self.eos.status.eq((self.eos.status & ~self.eos.we) | eos), ] -# Xilinx Ultrascale+ System Monitor ----------------------------------------------------------------- +# Xilinx Ultrascale Plus System Monitor ------------------------------------------------------------ -class USSystemMonitor(USFamilySystemMonitor): +USPSystemMonitorChannels = [ + XilinxSystemMonitorChannel(name="temperature", addr=0x0, bits=10, desc=[ + "Raw Temperature value from SYSMONE4.", + "Temperature (°C) = ``Value`` x 507.5921310 / 1024 - 279.42657680." + ]), + XilinxSystemMonitorChannel(name="vccint", addr=0x1, bits=10, desc=[ + "Raw VCCINT value from SYSMONE4.", + "VCCINT (V) = ``Value`` x 3 / 1024." + ]), + XilinxSystemMonitorChannel(name="vccaux", addr=0x2, bits=10, desc=[ + "Raw VCCAUX value from SYSMONE4.", + "VCCAUX (V) = ``Value`` x 3 / 1024." + ]), + XilinxSystemMonitorChannel(name="vccbram", addr=0x6, bits=10, desc=[ + "Raw VCCBRAM value from SYSMONE4.", + "VCCBRAM (V) = ``Value`` x 3 / 1024." + ]), +] - _block_name = 'SYSMONE1' - _sim_device = None - _channels = [ - ( 0x0, 'temperature', - "Raw Temperature value from SYSMONE1.\n Temperature (°C) = ``Value`` x 503.975 / 1024 - 273.15."), - ( 0x1, 'vccint', - "Raw VCCINT value from SYSMONE1.\n VCCINT (V) = ``Value`` x 3 / 1024."), - ( 0x2, 'vccaux', - "Raw VCCAUX value from SYSMONE1.\n VCCAUX (V) = ``Value`` x 3 / 1024."), - ( 0x6, 'vccbram', - "Raw VCCBRAM value from SYSMONE1.\n VCCBRAM (V) = ``Value`` x 3 / 1024."), - ] +ZynqUSPSystemMonitorChannels = USPSystemMonitorChannels + [ + XilinxSystemMonitorChannel(name="vccpsintlp", addr=0xd, bits=10, desc=[ + "Raw VCCPSINTLP value from SYSMONE4.", + "VCCPSINTLP (V) = ``Value`` x 3 / 1024.", + ]), + XilinxSystemMonitorChannel(name="vccpsintfp", addr=0xe, bits=10, desc=[ + "Raw VCCPSINTFP value from SYSMONE4.", + "VCCPSINTFP (V) = ``Value`` x 3 / 1024.", + ]), + XilinxSystemMonitorChannel(name="vccpsaux", addr=0xf, bits=10, desc=[ + "Raw VCCPSAUX value from SYSMONE4.", + "VCCPSAUX (V) = ``Value`` x 3 / 1024.", + ]), +] -class USPSystemMonitor(USFamilySystemMonitor): +class USPSystemMonitor(USSystemMonitor): + def __init__(self, analog_pads=None): + USSystemMonitor.__init__(self, + channels = USPSystemMonitorChannels, + primitive = "SYSMONE4", + sim_device = "ULTRASCALE_PLUS", + analog_pads = analog_pads, + ) - _block_name = 'SYSMONE4' - _sim_device = 'ULTRASCALE_PLUS' - _channels = [ - ( 0x0, 'temperature', - "Raw Temperature value from SYSMONE4.\n Temperature (°C) = ``Value`` x 507.5921310 / 1024 - 279.42657680."), - ( 0x1, 'vccint', - "Raw VCCINT value from SYSMONE4.\n VCCINT (V) = ``Value`` x 3 / 1024."), - ( 0x2, 'vccaux', - "Raw VCCAUX value from SYSMONE4.\n VCCAUX (V) = ``Value`` x 3 / 1024."), - ( 0x6, 'vccbram', - "Raw VCCBRAM value from SYSMONE4.\n VCCBRAM (V) = ``Value`` x 3 / 1024."), - ] - -class ZynqUSPSystemMonitor(USFamilySystemMonitor): - - _block_name = 'SYSMONE4' - _sim_device = 'ZYNQ_ULTRASCALE' - _channels = [ - ( 0x0, 'temperature', - "Raw Temperature value from SYSMONE4.\n Temperature (°C) = ``Value`` x 507.5921310 / 1024 - 279.42657680."), - ( 0x1, 'vccint', - "Raw VCCINT value from SYSMONE4.\n VCCINT (V) = ``Value`` x 3 / 1024."), - ( 0x2, 'vccaux', - "Raw VCCAUX value from SYSMONE4.\n VCCAUX (V) = ``Value`` x 3 / 1024."), - ( 0x6, 'vccbram', - "Raw VCCBRAM value from SYSMONE4.\n VCCBRAM (V) = ``Value`` x 3 / 1024."), - ( 0xd, 'vccpsintlp', - "Raw VCCPSINTLP value from SYSMONE4.\n VCCPSINTLP (V) = ``Value`` x 3 / 1024."), - ( 0xe, 'vccpsintfp', - "Raw VCCPSINTFP value from SYSMONE4.\n VCCPSINTFP (V) = ``Value`` x 3 / 1024."), - ( 0xf, 'vccpsaux', - "Raw VCCPSAUX value from SYSMONE4.\n VCCPSAUX (V) = ``Value`` x 3 / 1024."), - ] +class ZyncUSPSystemMonitor(USSystemMonitor): + def __init__(self, analog_pads=None): + USSystemMonitor.__init__(self, + channels = ZyncUSPSystemMonitorChannels, + primitive = "SYSMONE4", + sim_device = "ZYNQ_ULTRASCALE", + analog_pads = analog_pads, + )