core: add watchdog feature

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
Fin Maaß 2024-06-20 16:38:38 +02:00
parent 29bdf6805f
commit 0559f3f033
4 changed files with 106 additions and 0 deletions

View File

@ -0,0 +1,70 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2024 Fin Maaß <f.maass@vogl-electronic.com>
# SPDX-License-Identifier: BSD-2-Clause
from migen import *
from litex.gen import *
from litex.gen.genlib.misc import WaitTimer
from litex.soc.interconnect.csr import *
from litex.soc.interconnect.csr_eventmanager import *
# Watchdog --------------------------------------------------------------------------------------------
class Watchdog(LiteXModule):
"""Watchdog
Provides a generic Watchdog core.
"""
def __init__(self, width=32, crg_rst=None, reset_delay=0, halted=None):
self.enable = Signal()
self.reset_mode = Signal()
self.feed = Signal()
self.halted = Signal()
self.execute = Signal()
self._control = CSRStorage(description="Watchdog Control.", fields=[
CSRField("feed", size=1, offset=0, pulse=True, description="Watchdog feed (Write ``1`` to feed)."),
CSRField("enable", size=1, offset=8, description="Watchdog enable."),
CSRField("reset", size=1, offset=16, description="Reset SoC when watchdog times out."),
CSRField("pause_halted", size=1, offset=24, description="Pause watchdog when CPU is halted.")
])
self.comb += [
self.enable.eq(self._control.fields.enable & ~self.halted),
self.feed.eq(self._control.fields.feed),
self.reset_mode.eq(self._control.fields.reset),
]
if isinstance(halted, Signal):
self.comb += self.halted.eq(halted & self._control.fields.pause_halted)
self._cycles = cycles = CSRStorage(description="Watchdog cycles until timeout.", size=width)
self._remaining = remaining = CSRStatus(description="Watchdog cycles remaining until timeout.", size=width)
self.ev = EventManager()
self.ev.wdt = EventSourceProcess(edge="rising")
self.ev.finalize()
self.sync += [
If(self.feed,
remaining.status.eq(cycles.storage)
).Elif(self.enable,
If(remaining.status != 0,
remaining.status.eq(remaining.status - 1)
),
self.execute.eq(remaining.status == 0),
)
]
self.comb += If(self.enable, self.ev.wdt.trigger.eq(self.execute))
if isinstance(crg_rst, Signal):
self.reset_timer = WaitTimer(reset_delay)
self.comb += self.reset_timer.wait.eq(self.enable & self.execute & self.reset_mode)
self.comb += If(self.reset_timer.done, crg_rst.eq(1))

View File

@ -1301,6 +1301,24 @@ class SoC(LiteXModule, SoCCoreCompat):
if self.irq.enabled:
self.irq.add(name, use_loc_if_exists=True)
# Add Watchdog ---------------------------------------------------------------------------------
def add_watchdog(self, name="watchdog0", width=32, crg_rst=None, reset_delay=None):
from litex.soc.cores.watchdog import Watchdog
if crg_rst is None:
crg_rst = getattr(self.crg, "rst", None) if hasattr(self, "crg") else None
if reset_delay is None:
reset_delay = self.sys_clk_freq
halted = getattr(self.cpu, "o_halted", None) if hasattr(self, "cpu") else None
self.check_if_exists(name)
watchdog = Watchdog(width=width, crg_rst=crg_rst, reset_delay=int(reset_delay), halted=halted)
self.add_module(name=name, module=watchdog)
if self.irq.enabled:
self.irq.add(name, use_loc_if_exists=True)
# SoC finalization -----------------------------------------------------------------------------
def finalize(self):
if self.finalized:

View File

@ -115,6 +115,11 @@ class SoCCore(LiteXSoC):
# UARTBone.
with_uartbone = False,
# Watchdog.
with_watchdog = False,
watchdog_width = 32,
watchdog_reset_delay = None,
# Others.
**kwargs):
@ -266,6 +271,10 @@ class SoCCore(LiteXSoC):
if timer_uptime:
self.timer0.add_uptime()
# Add Watchdog.
if with_watchdog:
self.add_watchdog(name="watchdog0" ,width=watchdog_width, reset_delay=watchdog_reset_delay)
# Methods --------------------------------------------------------------------------------------
def add_csr(self, csr_name, csr_id=None, use_loc_if_exists=False):
@ -338,6 +347,11 @@ def soc_core_args(parser):
soc_group.add_argument("--no-timer", action="store_true", help="Disable Timer.")
soc_group.add_argument("--timer-uptime", action="store_true", help="Add an uptime capability to Timer.")
# Watchdog parameters.
soc_group.add_argument("--with-watchdog", action="store_true", help="Enable Watchdog.")
soc_group.add_argument("--watchdog-width", default=32, type=auto_int, help="Watchdog width.")
soc_group.add_argument("--watchdog-reset-delay", default=None, type=auto_int, help="Watchdog width.")
# L2 Cache.
soc_group.add_argument("--l2-size", default=8192, type=auto_int, help="L2 cache size.")

View File

@ -314,6 +314,10 @@ overlay_handlers = {
'handler': i2s_handler,
'config_entry': 'I2S_LITEX'
},
'watchdog0': {
'handler': peripheral_handler,
'alias': 'wdt0',
},
'mmcm' : {
'alias': 'clock0',
'handler': peripheral_handler,