Assert, Assume, Cover: The Three Verbs
Run one line as assert, as assume and as cover, and read what each verdict does and does not say.
- Lesson
- F1.3
- Time
- 15 min
- Runs on
- SymbiYosys
- Check
- 4 questions
An engineer inherited a formal bench with a hundred green properties. Six of them were assume statements on outputs: someone had changed a failing assert to assume to get past it and never changed it back. The tool had been told to consider only the worlds where the bug did not happen. A cover on the symptom would have come back unreached in under a second and exposed the trick.
Read the diagram as text
- No assumptions: every input value, every cycle
- The legal environment: assume what the spec promises
- Assume on outputs: or assumptions that contradict
- False failures: traces the real master never sends
- Real bugs only: every FAIL is reachable
- Nothing to check: the proof is empty
- No assumptions → False failures
- The legal environment → Real bugs only
- Assume on outputs → Nothing to check
F3.2 and F3.3 turn the two wrong ends into a flow: catch over-constraint with covers, fix under-constraint with assumptions on inputs.
One Statement, Three Jobs
| Statement | What the tool does | What the result means |
|---|---|---|
assert(p) | Tries to break it and reports a counterexample if it can. | FAIL: a bug, or a missing assumption (F1.4). PASS: no failure within the depth. |
assume(p) | Takes it as true and looks only at input sequences where it holds. | The world shrinks. An assumption on an output hides design behaviour. |
cover(p) | Tries to reach it and reports the trace that does. | Unreached: dead logic, or an assumption that rules it out. |
restrict(p) | An assumption that only formal honours. | For formal-only case splits (F4.3). Simulators ignore it. |
In simulation (A1.1 Why assertions) assume behaves as assert and cover counts hits. To a prover the three are different jobs.
The verb says who is responsible. Assume what the environment does. Assert what the design does. Cover what you expect to be possible. An assume on an output is the tool-side name for cheating: F3.1 makes this the master rule.
The Same Line, Four Runs
Measured with smtbmc yices. The cover is reached at sampled step 4 and reported at 5: the same steps as the assert's counterexample in F1.1.
| Statements in the design | Mode | Measured result | Time |
|---|---|---|---|
assert($onehot0(gnt)) | bmc | FAIL at reported step 5 | 520 ms |
assume($onehot0(gnt)) in place of the assert (the cover line is dropped in this mode) | bmc | Refused: no assertion left to check | 169 ms |
assume($onehot0(gnt)) alone, no cover line | bmc | Refused: no assertion, cover or live check | 148 ms |
assume($onehot0(gnt)) and assert($onehot0(gnt)) | bmc | BMC PASS to depth 20 | 536 ms |
cover(!$onehot0(gnt)) | cover | Cover reached, reported step 5 | 515 ms |
cover(!$onehot0(gnt)) under assume($onehot0(gnt)) | cover | Cover unreached within the depth | 535 ms |
assert($onehot0(gnt)) under assume(weight != 8'hA5) | bmc | BMC PASS to depth 20 | 536 ms |
The buggy arb3 of F1.1 in every row; depth 20; smtbmc yices. The one thing that changes is the verb. Time is the wall time on this machine.
Row 2 is the trick from the hook. The assert became an assume and bmc drops the cover, so nothing is left to check. Plain SBY would print PASS anyway. This site refuses the job: a pass with no obligation means nothing. Row 3 is refused for the same reason.
Row 4 is what the inherited bench did, and no tool refuses it: the assert is "proven" because every world with two grants has been discarded. Row 6 is the sanity check that exposes it: the double grant became unreachable, and the design did not change.
Row 7 is the right shape of assumption, on an input. It also passes, and now the question is one for the spec, not the tool: does firmware ever write A5? In the F1.1 story it did. An assumption is a claim about the environment, and it goes into the sign-off list where someone must sign it (F7.3).
How the Engine Sees the Verbs
Concurrent SVA, as the industry writes it
assert property (@(posedge clk) disable iff (rst) $onehot0(gnt));
assume property (@(posedge clk) disable iff (rst) $onehot0(gnt));
cover property (@(posedge clk) !rst && !$onehot0(gnt));
Three verbs, one clock, the same expression.
Clocked immediate statements, as this engine runs them
always @(posedge clk) if (!rst) begin
assert($onehot0(gnt));
assume($onehot0(gnt));
cover(!$onehot0(gnt));
end
Yosys turns them into $assert, $assume and $cover cells.
On this site a bmc or prove task keeps asserts and assumes and drops covers. A cover task drops asserts, keeps assumes and searches for the shortest trace to each cover. So one design file can carry all three verbs, and the mode selects the job. The reset is itself an assumption: rst high in the $initstate step and low afterwards (F1.6).
Asked in Interviews
| Question | Answer |
|---|---|
| What are assert, assume and cover to a formal tool? | Checked, believed, reached. |
| What happens if you assume a property on an output? | The tool stops considering the behaviours where the design violates it. The proof is vacuous. |
| How do you detect an over-constraint? | A cover on a behaviour you expect to be possible comes back unreached (F3.2). |
| What is restrict? | An assumption that only formal honours; simulators ignore it. It is for formal-only case splits. |
Try It
mode bmc to mode cover (the Mode selector below does the same).[options]
mode bmc
depth 20
[engines]
smtbmc yices
[script]
read_verilog -formal -sv design.sv
prep -top arb3
[files]
design.svAssert
Run as it is: mode bmc. Read FAIL at reported step 5. The cover line is ignored in this mode.
Assume
Change
assert(toassume(and run again: refused, because bmc drops the cover and no assertion is left. Add theassertline under theassume, run: PASS. Is the bug fixed?Cover
Set the mode to cover and run. With the assume in place the double grant is unreached. Remove the assume: the cover is reached at reported step 5, and the trace is the F1.1 counterexample.
The right assumption
Back in mode bmc, delete the assume on
gntand addassume(weight != 8'hA5);beside the assert. PASS. Then decide: does the real firmware never write A5?
design.sv
props.sv
Use assert property (@(posedge clk) ...);. Leave blank for immediate assertions in the design.
Inputs are free unless constrained. Run to find a counterexample or check a proof.
Model: one positive-edge clock, binary data. Sampled history requires declaration-initialized variables; primary-input history is unsupported.
SBY summary and log
Check Yourself
Remember
- Assert: the tool tries to break it. Assume: the tool believes it and shrinks the world. Cover: the tool tries to reach it.
- Assume what the environment does, assert what the design does, cover what should be possible.
- An assume on an output makes the proof vacuous; a cover on the hidden behaviour comes back unreached.
- restrict is an assume only formal honours. In simulation, assume checks like assert and cover counts.