|
| 1 | +# Exercise 5: Synchronicity |
| 2 | + |
| 3 | +<p align="right"> |
| 4 | +A connecting principle, linked to the invisible... |
| 5 | +</p> |
| 6 | + |
| 7 | +------ |
| 8 | +## What you'll do: |
| 9 | + |
| 10 | +Create a module that counts from 1 to 9 and back to 1 again. Formally verify that the output can never be greater than 9 and can never be 0. Cover the case where the output is 3. |
| 11 | + |
| 12 | +## Synchronous domains |
| 13 | + |
| 14 | +Unlike combinatorial domains, synchronous domains are associated with a clock signal and a reset signal. Assignments that are added to a synchronous domain take place on one of its clock's edge, the positive edge by default. |
| 15 | + |
| 16 | +The `sync` domain is the default domain that is always present: |
| 17 | + |
| 18 | +```python |
| 19 | +x = Signal() |
| 20 | +m.d.sync += x.eq(~x) |
| 21 | +``` |
| 22 | + |
| 23 | +The above will flip `x` on every positive edge of the sync clock. |
| 24 | + |
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | +You can only drive a signal from one domain. This would result in a driver-driver conflict: |
| 29 | + |
| 30 | +```python |
| 31 | +x = Signal() |
| 32 | +m.d.sync += x.eq(~x) |
| 33 | +m.d.comb += x.eq(0) |
| 34 | +``` |
| 35 | + |
| 36 | +## Synchronous resets |
| 37 | + |
| 38 | +A signal driven from a synchronous domain gets reset when that domain's reset signal goes high and the clock's edge happens, or on circuit initialization. The reset value of the signal is set by the `reset` key when creating the signal, and defaults to 0: |
| 39 | + |
| 40 | +```python |
| 41 | +x = Signal(reset=1) |
| 42 | +m.d.sync += x.eq(~x) |
| 43 | +``` |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | + |
| 48 | +You can prevent the signal from getting reset, except on circuit initialization, by using the key `reset_less`: |
| 49 | + |
| 50 | +```python |
| 51 | +x = Signal(reset=1, reset_less=True) |
| 52 | +m.d.sync += x.eq(~x) |
| 53 | +``` |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +## Synchronous signals are registers |
| 58 | + |
| 59 | +If a synchronous signal isn't assigned on an edge, it retains its value. |
| 60 | + |
| 61 | +```python |
| 62 | +x = Signal(8) |
| 63 | +load = Signal() |
| 64 | +loadval = Signal(8) |
| 65 | + |
| 66 | +with m.If(load): |
| 67 | + m.d.sync += x.eq(loadval) |
| 68 | +``` |
| 69 | + |
| 70 | +For the above, only if `load` is high will `x` be loaded with `loadval` on the sync clock edge. |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +You can think of the domain's reset signal as loading all registers in that domain with their reset values (unless they're `reset_less`). |
| 76 | + |
| 77 | +## Bounded model checking |
| 78 | + |
| 79 | +Up until now, we've been using bounded model checking to assert on combinatorial logic. However, with sequential logic, signals can change with time. So, bounded model checking specifies the number of time steps to take after the initial reset. This is specified in the `[options]` section of the sby file, as the value of `depth`. That's why it's called "bounded model checking", because it checks your model only up to the depth you specify. |
| 80 | + |
| 81 | +This means that you will have to know how long to run your verification before you can be sure all your asserts are checked. Later we will see a more powerful technique (induction) which doesn't have such a painful requirement. |
| 82 | + |
| 83 | +What exactly is "a time step"? It's a change in a clock signal. So, a full cycle of the sync clock would be two time steps. |
| 84 | + |
| 85 | +----- |
| 86 | + |
| 87 | +This is only true if the `multiclock` parameter in `[options]` is set to `on`. Unless you really really know what you're doing, leave it set to `on`. |
| 88 | + |
| 89 | +----- |
| 90 | + |
| 91 | +## The domain for Asserts and Covers |
| 92 | + |
| 93 | +Unless you really really know what you're doing, keep asserts and covers in the combinatorial domain. The asserts will be checked on every time step. |
| 94 | + |
| 95 | +## Your turn |
| 96 | + |
| 97 | +You can use the [answers/e05_counter.sby](answers/e05_counter.sby) file to run your formal verification. It is set up for 22 time steps, or 11 cycles of the clock. This should be enough to have the counter cycle around once. |
0 commit comments