For the worked tree, the controller keeps the core isolated until the 400 MHz PLL output has remained qualified, then lets the core reset synchronizer observe enough clean clock edges. A later lock loss returns the same domain to containment before any fallback clock is selected.
Synchronize or qualify asynchronous lock status.
Require lock stable for a documented interval.
Assert reset asynchronously on clock loss (from the clock-fault/reset controller) if the safety requirement needs immediate containment.
Release reset synchronously in each destination clock domain.
Mask traffic until both clock and reset contracts are complete.
// snippet: qualify lock before allowing reset release
// pll_lock_sync is already synchronised to ref_clk, so lost lock clears the
// count synchronously. Only power-on reset is an asynchronous clear; immediate
// containment on clock loss belongs to the separate clock-fault/reset controller.
always_ff @(posedge ref_clk or negedge por_n)
if (!por_n) lock_count_q <= '0;
else if (!pll_lock_sync) lock_count_q <= '0;
else if (!(&lock_count_q)) lock_count_q <= lock_count_q + 1'b1;
assign clock_qualified = &lock_count_q;Each slot is one ref_clk cycle, sampled just after its rising edge. The counter here is 2 bits wide, so lock must be high for three samples.
pll_lock_sync rises in slot 0; the count reaches 3 in slot 3 and clock_qualified rises with it.
Lock drops in slot 5. The next edge clears the count, so clock_qualified falls in slot 6.
Lock returns in slot 7, but the count restarts from 0: a short return of lock does not re-qualify the clock.
The architecture must define immediate reset/containment, isolation of outputs and transactions, diagnostics, reacquisition qualification, and a controlled resume sequence.