2 title: Introduction to Formal Verification of Digital Circuits
7 # Why Formal Verification?
9 * A tool for finding bugs
10 * Complementary to simulation
11 * Helps finding corner cases
12 * ... triggered by specific sequences of events
14 # Comparison with traditional debugging concepts
16 | formal | traditional |
17 |--------------------------|-------------------|
18 | Cover | Simulation |
19 | Bounded Model Check | Unit test |
20 | k-Induction | Test fixture? |
21 | Exhaustive search | random test cases |
22 | synthesizable test-bench | can be procedural |
23 | "assume" inputs | test vectors |
24 | "assert" outputs | "assert" outputs |
28 * HDL: includes assertions
29 * SBY: work plan, drives the process
30 * Yosys: synthesizes to logic functions:
31 * state $s$: contents of all registers and inputs
32 * initial predicate: $I(s)$
33 * transition relation $T(s_1, s_2)$
36 * yosys-smtbmc: proves correctness or outputs a trace
38 * exhaustive search for a path from the initial state to a bad state
39 * if not found, the design is correct
40 * if found, output an error trace
43 # Unbounded inductive proof
47 $I(s_0) P(s_0) \wedge T(s_0,s_1)\overline{I(s_1)}P(s_1)
48 \wedge\dots\wedge T(s_{k-1},s_k)\overline{I(s_k)}
52 * base case: no path from initial state leads to a bad state in k steps
53 * inductive case: no path ending in a bad state can be reached in k+1 steps
54 * if inductive case fails, $k \leftarrow k + 1$ and repeat
56 # Single register with feedback
60 # Registered output with internal state
62 ![](states_output.png)
64 # Registered output with enable
66 ![](states_enable.png)
68 # Flip-flop with input
72 # Verifying a flip-flop
74 ![](states_verification.png)
76 # Complete flip-flop with input and enable
78 ![](states_complete.png)
80 # Code for simple register with feedback
83 module simple(input clk);
107 read_verilog -formal simple.v
114 # Output (simplified)
119 induction: Trying induction in step 1..
120 induction: Trying induction in step 0..
121 induction: Temporal induction successful.
122 basecase: Checking assumptions in step 0..
123 basecase: Checking assertions in step 0..
124 basecase: Status: passed
125 summary: engine_0 (smtbmc yices) returned pass
127 summary: engine_0 (smtbmc yices) returned pass
129 summary: successful proof by k-induction.
134 # Flip flop with enable (1/2)
137 from nmigen.asserts import Assert, Assume, Past
138 from nmutil.formaltest import FHDLTestCase
139 from nmigen import Signal, Module
142 class Formal(FHDLTestCase):
143 def test_enable(self):
149 m.d.sync += [r2.eq(r1), r1.eq(r2)]
151 m.d.sync += s.eq(r1 & r2)
153 # Flip flop with enable (2/2)
156 m.d.comb += Assert(~s)
157 m.d.sync += Assume(Past(en) | en)
158 m.d.comb += Assert(~r1 & ~r2)
159 self.assertFormal(m, mode="prove", depth=5)
162 if __name__ == '__main__':
166 # Induction failure example
169 summary: engine_0 returned pass for basecase
170 summary: engine_0 returned FAIL for induction
188 * Discussion: http://lists.libre-soc.org
189 * Libera IRC \#libre-soc
190 * http://libre-soc.org/
191 * http://nlnet.nl/entrust
192 * https://libre-soc.org/nlnet_2022_ongoing/
193 * https://libre-soc.org/nlnet/\#faq
194 * https://git.libre-soc.org/?p=soc.git;a=tree;f=src/soc/experiment/formal;hb=HEAD