core: add watchdog feature
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
parent
29bdf6805f
commit
0559f3f033
|
@ -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))
|
|
@ -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:
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue