Line 9... |
Line 9... |
-- # Access to the control register can be permanently locked by setting the lock bit. This bit #
|
-- # Access to the control register can be permanently locked by setting the lock bit. This bit #
|
-- # can only be cleared by a hardware reset (external or caused by the watchdog itself). #
|
-- # can only be cleared by a hardware reset (external or caused by the watchdog itself). #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # BSD 3-Clause License #
|
-- # BSD 3-Clause License #
|
-- # #
|
-- # #
|
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
|
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
|
-- # #
|
-- # #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # permitted provided that the following conditions are met: #
|
-- # permitted provided that the following conditions are met: #
|
-- # #
|
-- # #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
Line 94... |
Line 94... |
enable : std_ulogic; -- 1=WDT enabled
|
enable : std_ulogic; -- 1=WDT enabled
|
clk_sel : std_ulogic_vector(2 downto 0);
|
clk_sel : std_ulogic_vector(2 downto 0);
|
mode : std_ulogic; -- 0=trigger IRQ on overflow; 1=trigger hard reset on overflow
|
mode : std_ulogic; -- 0=trigger IRQ on overflow; 1=trigger hard reset on overflow
|
rcause : std_ulogic; -- cause of last system reset: '0' = external, '1' = watchdog
|
rcause : std_ulogic; -- cause of last system reset: '0' = external, '1' = watchdog
|
reset : std_ulogic; -- reset WDT
|
reset : std_ulogic; -- reset WDT
|
force : std_ulogic; -- force action
|
enforce : std_ulogic; -- force action
|
lock : std_ulogic; -- lock control register
|
lock : std_ulogic; -- lock control register
|
end record;
|
end record;
|
signal ctrl_reg : ctrl_reg_t;
|
signal ctrl_reg : ctrl_reg_t;
|
|
|
-- prescaler clock generator --
|
-- prescaler clock generator --
|
Line 125... |
Line 125... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
write_access: process(rstn_i, clk_i)
|
write_access: process(rstn_i, clk_i)
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
ctrl_reg.reset <= '0';
|
ctrl_reg.reset <= '0';
|
ctrl_reg.force <= '0';
|
ctrl_reg.enforce <= '0';
|
ctrl_reg.enable <= '0'; -- disable WDT
|
ctrl_reg.enable <= '0'; -- disable WDT
|
ctrl_reg.mode <= '0'; -- trigger interrupt on WDT overflow
|
ctrl_reg.mode <= '0'; -- trigger interrupt on WDT overflow
|
ctrl_reg.clk_sel <= (others => '1'); -- slowest clock source
|
ctrl_reg.clk_sel <= (others => '1'); -- slowest clock source
|
ctrl_reg.lock <= '0';
|
ctrl_reg.lock <= '0';
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
if (rstn_sync = '0') then -- internal reset
|
if (rstn_sync = '0') then -- internal reset
|
ctrl_reg.reset <= '0';
|
ctrl_reg.reset <= '0';
|
ctrl_reg.force <= '0';
|
ctrl_reg.enforce <= '0';
|
ctrl_reg.enable <= '0'; -- disable WDT
|
ctrl_reg.enable <= '0'; -- disable WDT
|
ctrl_reg.mode <= '0'; -- trigger interrupt on WDT overflow
|
ctrl_reg.mode <= '0'; -- trigger interrupt on WDT overflow
|
ctrl_reg.clk_sel <= (others => '1'); -- slowest clock source
|
ctrl_reg.clk_sel <= (others => '1'); -- slowest clock source
|
ctrl_reg.lock <= '0';
|
ctrl_reg.lock <= '0';
|
else
|
else
|
-- auto-clear WDT reset and WDT force flags --
|
-- auto-clear WDT reset and WDT force flags --
|
ctrl_reg.reset <= '0';
|
ctrl_reg.reset <= '0';
|
ctrl_reg.force <= '0';
|
ctrl_reg.enforce <= '0';
|
-- actual write access --
|
-- actual write access --
|
if (wren = '1') then
|
if (wren = '1') then
|
ctrl_reg.reset <= data_i(ctrl_reset_c);
|
ctrl_reg.reset <= data_i(ctrl_reset_c);
|
ctrl_reg.force <= data_i(ctrl_force_c);
|
ctrl_reg.enforce <= data_i(ctrl_force_c);
|
if (ctrl_reg.lock = '0') then -- update configuration only if unlocked
|
if (ctrl_reg.lock = '0') then -- update configuration only if unlocked
|
ctrl_reg.enable <= data_i(ctrl_enable_c);
|
ctrl_reg.enable <= data_i(ctrl_enable_c);
|
ctrl_reg.mode <= data_i(ctrl_mode_c);
|
ctrl_reg.mode <= data_i(ctrl_mode_c);
|
ctrl_reg.clk_sel <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c);
|
ctrl_reg.clk_sel <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c);
|
ctrl_reg.lock <= data_i(ctrl_lock_c);
|
ctrl_reg.lock <= data_i(ctrl_lock_c);
|
Line 176... |
Line 176... |
end if;
|
end if;
|
end if;
|
end if;
|
end process wdt_counter;
|
end process wdt_counter;
|
|
|
-- action trigger --
|
-- action trigger --
|
irq_o <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.force) and (not ctrl_reg.mode); -- mode 0: IRQ
|
irq_o <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.enforce) and (not ctrl_reg.mode); -- mode 0: IRQ
|
hw_rst <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.force) and ( ctrl_reg.mode); -- mode 1: RESET
|
hw_rst <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.enforce) and ( ctrl_reg.mode); -- mode 1: RESET
|
|
|
|
|
-- Reset Generator & Action Cause Indicator -----------------------------------------------
|
-- Reset Generator & Action Cause Indicator -----------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
reset_generator: process(rstn_i, clk_i)
|
reset_generator: process(rstn_i, clk_i)
|