A path that exists structurally but can never carry a meaningful transfer would otherwise generate violations that cost effort and sometimes area. A false path removes it. But removing a check is a statement about the design, and if the statement is wrong the chip can fail in silicon with a clean report.
# not-run: SDC is not executable here
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b] ;# clock to clock (needs a reason)
set_false_path -from [get_ports test_mode] -to [all_registers -data_pins] ;# static signal
set_false_path -through [get_pins mux/I1] -from [get_clocks clk_a] ;# a path never selected
set_false_path -hold -from [get_clocks clk_a] -to [get_clocks clk_b] ;# hold-only removal (setup still checked)Justification | Evidence required |
|---|---|
Static during operation (mode, test pins) | Proof the signal is constant when the capture path is active (and constant constraints via case analysis if possible) |
Mutually exclusive functions | Logic proof: the select combination cannot occur |
Asynchronous clocks | A verified CDC protocol on every crossing, not just the removed check |
Reset asserted asynchronously with synchronised deassertion, or a quasi-static reset | The synchroniser (or proof the reset is static in operation) identified, with recovery/removal checks kept where they apply |
# Scope check: how many endpoints does a broad false path silence?
all_paths = [("a", "x"), ("a", "y"), ("b", "x"), ("b", "y"), ("c", "z")]
# intended: only the real false path from b to y
intended = {("b", "y")}
# written: from {b} to all endpoints (too broad)
written = {p for p in all_paths if p[0] == "b"}
extra = written - intended
assert intended <= written and extra == {("b", "x")}
print("PASS: the exception also silences", sorted(extra), "which is a real path")The exception was meant for one path but, written from b to everything, it also removes (b, x). That is the typical overbreadth: a -from without a matching -to. Review exceptions by listing the paths they cover and comparing with the intent.
Each false path has a written reason and an owner; "it was failing" is not a reason.
Exceptions are as narrow as possible (through points and specific pins), never from a clock to all endpoints without cause.
A bare set_false_path applies to both setup and hold; use -setup or -hold when only one check should be removed.
Whether the path can ever carry a real transfer in operation, with evidence. If it can, a false path hides a real failure and the design needs a fix; if it cannot, the justification must be written and reviewed.