HDL1051: Asynchronous reset release should be synchronized into the destination clock domain
Summary
| Reliability | Security | Maintainability | Code attribute | Effort to fix | Tags |
|---|---|---|---|---|---|
| HIGH | - | - | Intentionality | Logical | 30min | synthesis, bug-finder, do254-ss15, reset, cnes-std-03700, linty-ultra |
Description
Feed the external asynchronous reset into a two-stage synchronizer clocked by the destination clock, and use the synchronizer output as the reset of the logic in that clock domain. Repeat the synchronizer for each clock domain.
Noncompliant code example
library ieee;
use ieee.std_logic_1164.all;
entity bad_reset_example is
port (
clk : in std_logic;
reset_n : in std_logic;
d : in std_logic;
q : out std_logic
);
end entity;
architecture rtl of bad_reset_example is
begin
-- The external reset is used directly. Its release is not aligned with clk.
process (clk, reset_n)
begin
if reset_n = '0' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
end architecture;
Compliant solution
library ieee;
use ieee.std_logic_1164.all;
entity good_reset_example is
port (
clk : in std_logic;
reset_n : in std_logic;
d : in std_logic;
q : out std_logic
);
end entity;
architecture rtl of good_reset_example is
signal reset_n_sync_ff1 : std_logic;
signal reset_n_sync : std_logic;
begin
-- Assertion stays asynchronous. Release waits for two rising edges of clk.
process (clk, reset_n)
begin
if reset_n = '0' then
reset_n_sync_ff1 <= '0';
reset_n_sync <= '0';
elsif rising_edge(clk) then
reset_n_sync_ff1 <= '1';
reset_n_sync <= reset_n_sync_ff1;
end if;
end process;
process (clk, reset_n_sync)
begin
if reset_n_sync = '0' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
end architecture;
An asynchronous reset may assert at any time. That assertion is safe: every flip-flop is forced to a known value without waiting for a clock edge.
The release is the dangerous event. If the reset goes inactive at a time that is not aligned with the destination clock, some flip-flops leave reset on one clock edge and others on the next edge, or they become metastable. State machines, counters, and pipelines can then start from an inconsistent state. The failure depends on timing, temperature, and voltage, so it is intermittent.
Synchronize the release into every clock domain that uses the reset. A reset-release synchronizer is a chain of flip-flops clocked by the destination clock. The external reset still asserts asynchronously. Its release propagates through the chain, so every flip-flop in that clock domain sees the release on the same clock edge. The stages after the first may be ordinary clocked flip-flops, with no asynchronous reset of their own. A wire or an inverter between stages still belongs to the chain. Any other logic between stages does not.
A fully synchronous sampler is also a synchronizer. Its first flip-flop samples the asynchronous reset on the data pin, and each following flip-flop samples the previous stage. The logic then uses the last stage as its asynchronous reset. Assertion is delayed until the chain fills, instead of being immediate.
The parameter min is the minimum number of flip-flops in that chain. The default is 2.
Set it to 3 when the destination clock is slow or the project requires an extra stage.
Parameters
| Parameter | Value | Description |
|---|---|---|
| min | 2 | Minimum number of flip-flops in the reset-release synchronizer |