Updated Verilog documentation
authorZipCPU <dgisselq@ieee.org>
Wed, 22 May 2019 00:55:46 +0000 (20:55 -0400)
committerZipCPU <dgisselq@ieee.org>
Wed, 22 May 2019 00:55:46 +0000 (20:55 -0400)
docs/source/verilog.rst

index d83b29911d4ba97d28f2c26f7632bd4700edaebf..f43f71fa2c398e4f01a9cccd800067f79bc59c7e 100644 (file)
 Formal extensions to Verilog
 ============================
 
-TBD
+Any Verilog file may be read using ``read -formal <file>`` within the
+SymbiYosys ``script`` section.  Multiple files may be given on the sames
+line, or various files may be read in subsequent lines.
+
+``read -formal`` will also define the ``FORMAL`` macro, which can be used
+to separate a section having formal properties from the rest of the logic
+within the core.
+
+.. code-block:: systemverilog
 
-``read -sv``
+   module somemodule(port1, port2, ...);
+       // User logic here
+       //
+   `ifdef FORMAL
+       // Formal properties here
+   `endif
+   endmodule
 
-``read_verilog -sv``
+The ``bind()`` operator can also be used when using the Verific front end.
+This will provide an option to attach formal properties to a given piece
+of logic, without actually modifying the module in question to do so as
+we did in the example above.
 
 SystemVerilog Immediate Assertions
 ----------------------------------
 
-TBD
+SymbiYosys supports three basic immediate assertion types.
+
+1. ``assume(<expr>);``
+
+   An assumption restricts the possibilities the formal tool examines, making
+   the search space smaller.  In any solver generated trace, all of the
+   assumptions will always be true.
+
+2. ``assert(<expr>);``
+
+   An assertion is something the solver will try to make false.  Any time
+   SymbiYosys is run with ``mode bmc``, the proof will fail if some set
+   of inputs can cause the ``<expr>`` within the assertion to be zero (false).
+   When SymbiYosys is run with ``mode prove``, the proof may also yield an
+   ``UNKNOWN`` result if an assertion can be made to fail during the induction
+   step.
+
+3. ``cover(<expr>);``
+
+   A cover statement only applies when SymbiYosys is ran with option
+   ``mode cover``.  In this case, the formal solver will start at the
+   beginning of time (i.e. when all initial statements are true), and it will
+   try to find some clock when ``<expr>`` can be made to be true.  Such a
+   cover run will "PASS" once all internal ``cover()`` statements have been
+   fulfilled.  It will "FAIL" if any ``cover()`` statement exists that cannot
+   be reached in the first ``N`` states, where ``N`` is set by the
+   ``depth`` option.  A cover pass will also fail if an assertion needs to
+   be broken in order to reach the covered state.
+
+To be used, each of these statements needs to be placed into an *immediate*
+context.  That is, it needs to be placed within an ``always`` block of some
+type.  Two types of ``always`` block contexts are permitted:
+
+- ``always @(*)``
+
+  Formal properties within an ``always @(*)`` block will be checked on every
+  time step.  For synchronous proofs, the property will be checked every
+  clock period.  For asynchronous proofs, i.e. those with ``multiclock on``,
+  the property will still be checked on every time step but, depending upon
+  how you set up your time steps, it may also be checked multiple times
+  per clock interval.
+
+  As an example, consider the following assertion that the ``error_flag``
+  signal must remain low.
+
+.. code-block:: systemverilog
+
+   always @(*)
+       assert(!error_flag);
+
+While it is not recommended that formal properties be mixed with logic in
+the same ``always @(*)`` block, the language supports it.  In such cases,
+the formal property will be evaluated as though it took place in the middle
+of the logic block.
+
+- ``always @(posedge <clock>)``
+
+  The second form of immediate assertion is one within a clocked always block.
+  This form of assertion is required when attempting to use the ``$past``,
+  ``$stable``, ``$changed``, ``$rose``, or ``$fell`` SystemVerilog functions
+  discussed in the next section.
 
-``assert(<expr>);``
+  Unlike the ``@(*)`` assertion, this one will only be checked on the clock
+  edge.  Depending upon how the clock is set up, that may mean that there are
+  several formal time steps between when this assertion is checked.
 
-``assume(<expr>);``
+  The two types of immediate assertions, both with and without a clock
+  reference, are very similar.  There is one critical difference between
+  them, however.  The clocked assertion will not be checked until the
+  positive edge of the clock following the time period in question.  Within
+  a synchronous design, this means that the fault will not lie on the last
+  time step, but rather the time step prior.  New users often find this
+  non-intuitive.
 
-``cover(<expr>);``
+One subtlety to be aware of is that any ``always @(*)`` assertion that
+depends upon an ``always @(posedge <clock>)`` assumption might fail before
+the assumption is applied.  One solution is to use all clocked or all
+combinatorial blocks.  Another solution is to move the assertion into an
+``always @(posedge <clock>)`` block.
 
 SystemVerilog Functions
 -----------------------
 
-TBD
+Yosys supports five formal related functions: ``$past``, ``$stable``,
+``$changed``, ``$rose``, and ``$fell``.  Internally, these are all implemented
+in terms of the implementation of the ``$past`` operator.
+
+The ``$past(<expr>)`` function returns the value of ``<expr>`` from one clock
+ago.  It can only be used within a clocked always block, since the clock is
+used to define "one clock ago."  It is roughly equivalent to,
+
+.. code-block:: systemverilog
+
+   reg past_value;
+   always @(posedge clock)
+       past_value <= expression;
+
+There are two keys to the use of ``$past``.  The first is that
+``$past(<expr>)`` can only be used within a clocked always block.  The second
+is that there is no initial value given to any ``$past(<expr>)``.  That means
+that on the first clock period of any design, ``$past(<expr>)`` will be
+undefined.
 
-``$past``
+Yosys supports both one and two arguments to ``$past``.  In the two argument
+form, ``$past(<expr>,N)``, the expression returns the value of ``<expr>``
+from ``N`` clocks ago.  ``N`` must be a synthesis time constant.
 
-``$stable``
+``$stable(<expr>)`` is short hand for ``<expr> == $past(<expr>)``.
 
-``$rose``, ``$fell``
+``$changed(<expr>)`` is short hand for ``<expr> != $past(<expr>)``.
+
+While the next two functions, ``$rose`` and ``$fell``, can be applied to
+multi-bit expressions, only the least significant bits will be examined.
+If we allow that ``<expr>`` has only a single bit within it, perhaps selected
+from the least significant bit of a larger expression, then we can
+express the following equivalencies.
+
+``$rose(<expr>)`` is short hand for ``<expr> && !$past(<expr)``.
+
+``$fell(<expr>)`` is short hand for ``!<expr> && $past(<expr)``.
 
 Liveness and Fairness
 ---------------------
@@ -42,22 +161,65 @@ TBD
 Unconstrained Variables
 -----------------------
 
-TBD
+Yosys supports four attributes which can be used to create unconstrained
+variables.  These attributes can be applied to the variable at declaration
+time, as in
+
+.. code-block:: systemverilog
 
-``(* anyconst *)``
+   (* anyconst ) reg some_value;
 
-``(* anyseq *)``
+The ``(* anyconst *)`` attribute will create a solver chosen constant.
+It is often used when verifying memories: the proof allows the solver to
+pick a constant address, and then proves that the value at that address
+matches however the designer desires.
 
-``(* allconst *)``
+``(* anyseq *)`` differs from ``(* anyconst *)`` in that the solver chosen
+value can change from one time step to the next.  In many ways, it is
+similar to how the solver will treat an input to the design, with the
+difference that an ``(* anyseq *)`` variable can originate internal
+to the design.
 
-``(* allseq *)``
+Both ``(* anyseq *)`` and ``(* anyconst *)`` marked values can be constrained
+with assumptions.
+
+Yosys supports two other attributes useful to formal processing,
+``(* allconst *)`` and ``(* allseq *)``.  These are very similar in their
+functionality to the ``(* anyseq *)`` and ``(* anyconst *)`` attributes we
+just discussed for creating unconstrained values.  Indeed, for both assertions
+and cover statements, the two sets are identical.  Where they differ is
+with respect to assumptions.  Assumed properties of an ``(* allseq *)``
+or ``(* allconst *)`` value will be applied to all possible values of that
+variable may take on.  This gets around the annoying reality associated with
+defining a property using ``(* anyconst *)`` or ``(* anyseq *)`` only to
+have the solver pick a value which wasn't the one that was constrained.
 
 Global Clock
 ------------
 
-TBD
+Accessing the formal timestep becomes important when verifying code in any
+asynchronous context.  In such asynchronous contexts, there may be multiple
+independent clocks within the design.  Each of the clocks may be defined by
+an assumption allowing the designer to carefully select the relationships
+between them.
+
+All of this requires the ``multiclock on`` line in the SBY options section.
+
+It also requires the ``(* gclk *)`` attribute.
+
+To use ``(* gclk *)``, define a register with that attribute, as in:
+
+.. code-block:: systemverilog
+
+    (* gclk ) reg formal_timestep;
+
+You can then reference this ``formal_timestep`` in the clocking section
+of an always block, as in,
+
+.. code-block:: systemverilog
 
-``(* gclk *)``
+    always @(posedge formal_timestep)
+        assume(incoming_clock == !$past(incoming_clock));
 
 SystemVerilog Concurrent Assertions
 -----------------------------------