Skip to content

Watchdog Timer (WDT) β€” Technical Documentation

Contents

  1. Overview
  2. Module Interface
  3. Register Map
  4. Window Mode
  5. Lock Mechanism
  6. Reset and Interrupt

Overview

Purpose

The watchdog module implements a system watchdog timer. If it is not refreshed within the configured time, it generates a system reset or an interrupt.

File Location

rtl/periph/wdt/watchdog.sv

Features

  • 32-bit down counter
  • Window mode (early refresh rejection)
  • Lock register protection
  • Debug pause support
  • Early warning interrupt
  • System reset generation

Module Interface

Port Definitions

module watchdog
  import level_param::*;
(
    input  logic clk_i,
    input  logic rst_ni,

    // Register interface
    input  logic            stb_i,
    input  logic [     2:0] adr_i,
    input  logic [     3:0] byte_sel_i,
    input  logic            we_i,
    input  logic [XLEN-1:0] dat_i,
    output logic [XLEN-1:0] dat_o,

    // Debug interface
    input  logic debug_halt_i,

    // Outputs
    output logic wdt_reset_o,
    output logic wdt_irq_o
);

Signal Descriptions

Signal Direction Description
debug_halt_i in Freeze counter while in debug
wdt_reset_o out Watchdog reset signal
wdt_irq_o out Early warning interrupt

Register Map

Offset Register Description
0x00 CTRL Control register
0x04 LOAD Counter reload value
0x08 VALUE Current counter (read-only)
0x0C KEY Key register (refresh/lock)
0x10 WINDOW Window threshold
0x14 STATUS Status/clear register

CTRL Register

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ [4]   β”‚ dbg_pause β”‚ Pause counter during debug halt                     β”‚
β”‚ [3]   β”‚ win_en    β”‚ Window mode enable                                  β”‚
β”‚ [2]   β”‚ irq_en    β”‚ Early warning interrupt enable                      β”‚
β”‚ [1]   β”‚ rst_en    β”‚ Reset generation enable                             β”‚
β”‚ [0]   β”‚ wdt_en    β”‚ Watchdog enable                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

KEY Register Values

parameter KEY_REFRESH = 32'h5A5A_5A5A;  // Counter refresh
parameter KEY_UNLOCK  = 32'h1234_5678;  // Unlock registers
parameter KEY_LOCK    = 32'hDEAD_BEEF;  // Lock registers

STATUS Register

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ [2] β”‚ window_err β”‚ Early refresh error (window mode)                    β”‚
β”‚ [1] β”‚ early_warn β”‚ Early warning flag (counter < threshold)             β”‚
β”‚ [0] β”‚ timeout    β”‚ Timeout occurred                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Window Mode

Concept

Window mode prevents refreshing too early. This helps catch stuck-in-loop bugs.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        WINDOW MODE                                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                          β”‚
β”‚   LOAD ─────────────────────────────────────────────────────────────     β”‚
β”‚        β”‚                                                                 β”‚
β”‚        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚        β”‚  β”‚         CLOSED WINDOW (early refresh = error)         β”‚     β”‚
β”‚        β”‚  β”‚                                                       β”‚     β”‚
β”‚   WIN  ───│───────────────────────────────────────────────────────│─    β”‚
β”‚        β”‚  β”‚                                                       β”‚     β”‚
β”‚        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚        β”‚                                                                 β”‚
β”‚        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚        β”‚  β”‚           OPEN WINDOW (refresh allowed)                β”‚     β”‚
β”‚   WARN ───│───────────────────────────────────────────────────────│─    β”‚
β”‚        β”‚  β”‚                                                       β”‚     β”‚
β”‚        β”‚  β”‚                                        β–² IRQ          β”‚     β”‚
β”‚        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚        β”‚                                                                 β”‚
β”‚   0  ──│───────────────────────────────────────────────────────────│─   β”‚
β”‚        β”‚                                           β–² RESET         β”‚     β”‚
β”‚        β–Ό                                                            β”‚     β”‚
β”‚      Counter                                                        β”‚     β”‚
β”‚                                                                          β”‚
β”‚   Rules:                                                                β”‚
β”‚   1. Refresh while CNT > WINDOW β†’ window_err β†’ reset                    β”‚
β”‚   2. Refresh while WARN < CNT <= WINDOW β†’ OK, reload                    β”‚
β”‚   3. CNT < WARN β†’ early_warn IRQ                                        β”‚
β”‚   4. CNT == 0 β†’ timeout β†’ reset                                         β”‚
β”‚                                                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Window Mode Timing

              LOAD value
                 β”‚
                 β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚                                                          β”‚
      β”‚  CLOSED WINDOW (counter > WINDOW)                        β”‚
      β”‚  Refresh here β†’ ERROR                                    β”‚
      β”‚                                                          β”‚
WINDOWβ”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
      β”‚                                                          β”‚
      β”‚  OPEN WINDOW (WARN < counter <= WINDOW)                  β”‚
      β”‚  Refresh here β†’ OK, counter reloads                      β”‚
      β”‚                                                          β”‚
 WARN β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
      β”‚                                                          β”‚
      β”‚  WARNING ZONE (counter < WARN)                           β”‚
      β”‚  IRQ generated, refresh still allowed                    β”‚
      β”‚                                                          β”‚
   0  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β–²
              β”‚ TIMEOUT β†’ RESET

Lock Mechanism

Register Protection

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        LOCK MECHANISM                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                          β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                         β”‚
β”‚   β”‚           β”‚                                                         β”‚
β”‚   β”‚  LOCKED   │◄────────────────────────────────────────────┐           β”‚
β”‚   β”‚           β”‚                                             β”‚           β”‚
β”‚   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                                             β”‚           β”‚
β”‚         β”‚                                                   β”‚           β”‚
β”‚         β”‚ Write KEY_UNLOCK (0x12345678)                     β”‚           β”‚
β”‚         β”‚                                                   β”‚           β”‚
β”‚         β–Ό                                                   β”‚           β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                             β”‚           β”‚
β”‚   β”‚           β”‚                                             β”‚           β”‚
β”‚   β”‚ UNLOCKED  β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β”‚   β”‚           β”‚     Write KEY_LOCK (0xDEADBEEF)                         β”‚
β”‚   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜     or timeout (after N cycles)                         β”‚
β”‚         β”‚                                                               β”‚
β”‚         β”‚ Registers writable                                            β”‚
β”‚         β–Ό                                                               β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚   β”‚ CTRL, LOAD, WINDOW registers can be modified                  β”‚     β”‚
β”‚   β”‚ KEY register always writable (for refresh)                    β”‚     β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                                                          β”‚
β”‚   Locked state: Only KEY register writable                              β”‚
β”‚   Unlocked state: All registers writable (time-limited)                 β”‚
β”‚                                                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Operations

// Refresh watchdog
write KEY, 0x5A5A5A5A

// Unlock registers for modification
write KEY, 0x12345678
write LOAD, new_value      // Allowed
write CTRL, new_value      // Allowed
write KEY, 0xDEADBEEF      // Re-lock

// If no re-lock, auto-lock after timeout

Reset and Interrupt

Output Generation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        RESET/IRQ GENERATION                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                          β”‚
β”‚   Counter                                                                β”‚
β”‚      β”‚                                                                   β”‚
β”‚      β–Ό                                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                   β”‚
β”‚   β”‚ CNT < WARN_TH?  │────────┐                                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚ YES                                      β”‚
β”‚           β”‚ NO               β–Ό                                          β”‚
β”‚           β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚           β”‚           β”‚ irq_en set? │────►│  wdt_irq_o  β”‚               β”‚
β”‚           β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ YES β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β”‚           β”‚                                                              β”‚
β”‚           β–Ό                                                              β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                   β”‚
β”‚   β”‚  CNT == 0?      │────────┐                                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚ YES                                      β”‚
β”‚           β”‚ NO               β–Ό                                          β”‚
β”‚           β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚           β”‚           β”‚ rst_en set? │────►│ wdt_reset_o  β”‚              β”‚
β”‚           β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ YES β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚           β”‚                                                              β”‚
β”‚           β–Ό                                                              β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                   β”‚
β”‚   β”‚ Window error?   │────────┐                                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚ YES                                      β”‚
β”‚           β”‚ NO               β–Ό                                          β”‚
β”‚           β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                  β”‚
β”‚           β”‚           β”‚ wdt_reset_o  β”‚ (immediate)                      β”‚
β”‚           β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β”‚
β”‚           β”‚                                                              β”‚
β”‚           β–Ό                                                              β”‚
β”‚     Normal operation                                                     β”‚
β”‚                                                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Debug Pause

// Counter freezes during debug halt
always_ff @(posedge clk_i) begin
    if (!rst_ni) begin
        counter <= LOAD;
    end else if (wdt_en) begin
        if (dbg_pause && debug_halt_i) begin
            // Counter frozen
        end else begin
            counter <= counter - 1;
        end
    end
end

Usage Example

C Header

#define WDT_BASE       0x20008000

#define WDT_CTRL       (*(volatile uint32_t*)(WDT_BASE + 0x00))
#define WDT_LOAD       (*(volatile uint32_t*)(WDT_BASE + 0x04))
#define WDT_VALUE      (*(volatile uint32_t*)(WDT_BASE + 0x08))
#define WDT_KEY        (*(volatile uint32_t*)(WDT_BASE + 0x0C))
#define WDT_WINDOW     (*(volatile uint32_t*)(WDT_BASE + 0x10))
#define WDT_STATUS     (*(volatile uint32_t*)(WDT_BASE + 0x14))

// Key values
#define WDT_KEY_REFRESH  0x5A5A5A5A
#define WDT_KEY_UNLOCK   0x12345678
#define WDT_KEY_LOCK     0xDEADBEEF

// CTRL bits
#define WDT_EN         (1 << 0)
#define WDT_RST_EN     (1 << 1)
#define WDT_IRQ_EN     (1 << 2)
#define WDT_WIN_EN     (1 << 3)
#define WDT_DBG_PAUSE  (1 << 4)

// STATUS bits
#define WDT_TIMEOUT    (1 << 0)
#define WDT_EARLY_WARN (1 << 1)
#define WDT_WIN_ERR    (1 << 2)

Basic Initialization

void wdt_init(uint32_t timeout_cycles) {
    // Unlock registers
    WDT_KEY = WDT_KEY_UNLOCK;

    // Set timeout
    WDT_LOAD = timeout_cycles;

    // Enable with reset generation
    WDT_CTRL = WDT_EN | WDT_RST_EN | WDT_DBG_PAUSE;

    // Lock registers
    WDT_KEY = WDT_KEY_LOCK;
}

Refresh (Kick)

void wdt_refresh(void) {
    // Write refresh key
    WDT_KEY = WDT_KEY_REFRESH;
}

Window Mode Setup

void wdt_init_window(uint32_t load, uint32_t window) {
    WDT_KEY = WDT_KEY_UNLOCK;

    WDT_LOAD = load;           // Total timeout
    WDT_WINDOW = window;       // Window threshold

    // Enable window mode with reset and IRQ
    WDT_CTRL = WDT_EN | WDT_RST_EN | WDT_IRQ_EN | WDT_WIN_EN;

    WDT_KEY = WDT_KEY_LOCK;
}

// Main loop with windowed refresh
void main_loop(void) {
    while (1) {
        // Do work...
        process_data();

        // Check if in valid window before refresh
        uint32_t cnt = WDT_VALUE;
        uint32_t win = WDT_WINDOW;

        if (cnt <= win) {
            wdt_refresh();  // Safe to refresh
        }
        // else: Still in closed window, wait
    }
}

Early Warning Handler

void wdt_irq_handler(void) {
    // Check early warning flag
    if (WDT_STATUS & WDT_EARLY_WARN) {
        // Log warning - timeout approaching
        log_warning("WDT timeout approaching!");

        // Try to refresh if possible
        wdt_refresh();

        // Clear flag (write 1 to clear)
        WDT_STATUS = WDT_EARLY_WARN;
    }

    // Check window error (shouldn't happen in ISR)
    if (WDT_STATUS & WDT_WIN_ERR) {
        log_error("WDT window violation!");
        // System will reset soon...
    }
}

Timeout Calculation

// Calculate timeout in seconds
// Assuming 50 MHz clock
#define SYS_CLK 50000000

uint32_t timeout_to_cycles(float seconds) {
    return (uint32_t)(seconds * SYS_CLK);
}

// 1 second timeout
wdt_init(timeout_to_cycles(1.0));

// 100 ms timeout
wdt_init(timeout_to_cycles(0.1));

Timing Example

Normal Operation

         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
LOAD ─────                                                              β”‚
         β”‚                                                              β”‚
         β”‚  β•²                                                           β”‚
         β”‚   β•²                                                          β”‚
         β”‚    β•²                                                         β”‚
         β”‚     β•² refresh                                                β”‚
         β”‚      ╲────────────────────────────────────────────────────── β”‚
         β”‚       β”‚β•²                                                     β”‚
         β”‚       β”‚ β•²                                                    β”‚
         β”‚       β”‚  β•² refresh                                           β”‚
         β”‚       β”‚   ╲─────────────────────────────────────────────────│
         β”‚       β”‚    β”‚β•²                                               β”‚
         β”‚       β”‚    β”‚ β•²                                              β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β•²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          No timeout if refreshed periodically

Timeout Event

         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
LOAD ─────                                                              β”‚
         β”‚                                                              β”‚
         β”‚  β•²                                                           β”‚
WINDOW ──│───╲──────────────────────────────────────────────────────────│
         β”‚    β•²                                                         β”‚
WARN ────│─────╲────────────────────────────────────────────────────────│
         β”‚      β•²                                             IRQ β–Ό     β”‚
         β”‚       β•²                                                      β”‚
   0 ────│────────╲─────────────────────────────────────────────────────│
         β”‚         β–²                                                    β”‚
         β”‚         β”‚ TIMEOUT β†’ RESET                                    β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  No refresh β†’ system reset

Summary

The watchdog module provides:

  1. 32-bit Counter: Down-counting timer
  2. Window Mode: Prevents stuck-in-loop bugs
  3. Lock Protection: Key-based register access
  4. Debug Support: Counter pause during halt
  5. Dual Output: Reset and early warning IRQ
  6. Configurable: Flexible timeout settings
  7. Safety Critical: System reliability feature