A flip-flop is only guaranteed to resolve to a clean 0 or 1 if its data input is stable for before the clock edge and after it. Violate that window and the output can hover between logic levels for an unbounded time. That state is metastability, and it is not a fault you can design away — only one whose probability you can push below the lifetime of the product.
The window you cannot avoid
Any signal crossing from one clock domain to another is asynchronous with respect to the receiving clock. Sooner or later an edge lands inside the setup/hold window. The relevant question is never “will it happen” but “how often”.
- — resolution time you allow before sampling again
- — the flop’s resolution time constant, a process parameter
- — the metastability window width
- , — receiving clock rate and data toggle rate
The exponential is the whole point. Doubling the time you give the flop to settle does not double MTBF, it squares it. Going from one flop to two typically moves MTBF from hours to longer than the age of the universe.
The two-flop synchronizer
Two flip-flops in series, both on the receiving clock. The first one is allowed to go metastable; it gets a full clock period to resolve before the second one samples it.
module sync_2ff #(parameter WIDTH = 1) (
input wire clk,
input wire rst_n,
input wire [WIDTH-1:0] async_in,
output reg [WIDTH-1:0] sync_out
);
reg [WIDTH-1:0] meta;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
meta <= '0;
sync_out <= '0;
end else begin
meta <= async_in; // may go metastable
sync_out <= meta; // has had a full period to settle
end
end
endmoduleThree rules that come with it:
- Never fan out the first stage. If
metadrives anything other thansync_out, different loads can resolve to different values and you have just built a circuit that disagrees with itself. - Only synchronize single bits this way. Two bits crossing together can resolve on different clock edges, so a bus can transit through values it never actually held. Use a handshake or an async FIFO with Gray-coded pointers instead.
- Tell the tools. Constrain the path as a false path or
set_max_delay, otherwise static timing analysis will report a violation it cannot fix and you will be tempted to “solve” it by deleting the synchronizer.
The bug does not reproduce
Metastability failures are rare, temperature-dependent, and vanish under a logic analyzer. If a design fails once a week in the field and never on the bench, audit every clock-domain crossing before you audit anything else.
See also
- FPGA vs ASIC — the same rules, very different cost of getting it wrong
- Back to the vault