From d0e8de077c7e3bff9dd4bbb4a8c683009550d264 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 17 May 2021 11:42:01 +0200 Subject: [PATCH] soc/SoCController: Add separate fields for SoC and CPU resets. As discussed in #909, in some specific cases, it can be interesting to be able to keep the CPU in reset while the rest of the SoC is still operating (ex the peripherals/bridges). With theses changes, the old behaviour is preserved to do a full SoC Reset (at the exception that writing a 1 is now mandatory) and a separate field specific to the CPU reset is added. The SoC Reset is a pulse (otherwise the system would be stuck in Reset) while the CPU Reset is based on the register value (so can be pulse or hold). --- CHANGES | 3 ++- litex/soc/integration/soc.py | 24 +++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 145609b90..49727447a 100644 --- a/CHANGES +++ b/CHANGES @@ -7,7 +7,8 @@ [> Added Features ----------------- - - cpu/vexriscv: Add CFU support. + - cpu/vexriscv: Add CFU support. + - soc/controller: Add separate SoC/CPU reset fields. [> API changes/Deprecation -------------------------- diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index cf6d53061..00bb806ec 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -658,7 +658,10 @@ class SoCIRQHandler(SoCLocHandler): class SoCController(Module, AutoCSR): def __init__(self, with_reset=True, with_scratch=True, with_errors=True): if with_reset: - self._reset = CSRStorage(1, description="""Any write to this register will reset the SoC.""") + self._reset = CSRStorage(fields=[ + CSRField("soc_rst", size=1, offset=0, pulse=True, description="""Write `1` to this register to reset the full SoC (Pulse Reset)"""), + CSRField("cpu_rst", size=1, offset=1, description="""Write `1` to this register to reset the CPU(s) of the SoC (Hold Reset)"""), + ]) if with_scratch: self._scratch = CSRStorage(32, reset=0x12345678, description=""" Use this register as a scratch space to verify that software read/write accesses @@ -671,8 +674,8 @@ class SoCController(Module, AutoCSR): # Reset if with_reset: - self.reset = Signal() - self.comb += self.reset.eq(self._reset.re) + self.soc_rst = self._reset.fields.soc_rst + self.cpu_rst = self._reset.fields.cpu_rst # Errors if with_errors: @@ -918,8 +921,11 @@ class SoC(Module): # Connect SoCController's reset to CPU reset. if hasattr(self, "ctrl"): - if hasattr(self.ctrl, "reset"): - self.comb += self.cpu.reset.eq(self.ctrl.reset) + self.comb += self.cpu.reset.eq( + # Reset the CPU on... + getattr(self.ctrl, "soc_rst", 0) | # Full SoC Reset command... + getattr(self.ctrl, "cpu_rst", 0) # or on CPU Reset command. + ) self.add_config("CPU_RESET_ADDR", reset_address) # Add CPU's SoC components (if any). @@ -952,11 +958,11 @@ class SoC(Module): }[self.bus.standard] # SoC Reset -------------------------------------------------------------------------------- - # Connect SoCController's reset to CRG's reset if presents. + # Connect soc_rst to CRG's rst if presents. if hasattr(self, "ctrl") and hasattr(self, "crg"): - if hasattr(self.ctrl, "_reset") and hasattr(self.crg, "rst"): - if isinstance(self.crg.rst, Signal): - self.comb += self.crg.rst.eq(self.ctrl._reset.re) + crg_rst = getattr(self.crg, "rst", None) + if isinstance(crg_rst, Signal): + self.comb += crg_rst.eq(getattr(self.ctrl, "soc_rst", 0)) # SoC CSR bridge --------------------------------------------------------------------------- # FIXME: for now, use registered CSR bridge when SDRAM is present; find the best compromise.