Universal Serial Bus System Architecture
Universal Serial Bus System Architecture
Cadence Design Systems, Inc. (Cadence), 2655 Seely Ave., San Jose, CA 95134, USA.
Trademarks: Trademarks and service marks of Cadence Design Systems, Inc. contained in this
document are attributed to Cadence with the appropriate symbol. For queries regarding Cadence's
trademarks, contact the corporate legal department at the address shown above or call
800.862.4522. All other trademarks are the property of their respective holders.
Open SystemC, Open SystemC Initiative, OSCI, SystemC, and SystemC Initiative are trademarks or
registered trademarks of Open SystemC Initiative, Inc. in the United States and other countries and
are used with permission.
Restricted Permission: This publication is protected by copyright law and international treaties
and contains trade secrets and proprietary information owned by Cadence. Unauthorized
reproduction or distribution of this publication, or any portion of it, may result in civil and criminal
penalties. Except as specified in this permission statement, this publication may not be copied,
reproduced, modified, published, uploaded, posted, transmitted, or distributed in any way, without
prior written permission from Cadence. Unless otherwise agreed to by Cadence in writing, this
statement grants Cadence customers permission to print one (1) hard copy of this publication
subject to the following conditions:
1. The publication may be used only in accordance with a written agreement between Cadence
and its customer.
2. The publication may not be modified in any way.
3. Any authorized copy of the publication or portion thereof must include all original copyright,
trademark, and other proprietary notices and this permission statement.
4. The information contained in this document cannot be used in the development of like
products or software, whether for internal or external use, and shall not be used for the benefit
of any other party, whether or not for consideration.
Disclaimer: Information in this publication is subject to change without notice and does not
represent a commitment on the part of Cadence. Except as may be explicitly set forth in such
agreement, Cadence does not make, and expressly disclaims, any representations or warranties as
to the completeness, accuracy or usefulness of the information contained in this document.
Cadence does not warrant that use of such information will not infringe any third party rights, nor
does Cadence assume any liability for damages or costs of any kind that may result from use of
such information.
Contents
1 13
Introduction to Assertions 13
Assertions in Verification 13
Using Assertions 13
ABV Documentation 14
2 16
Basic Assertion Concepts 16
About Assertions 16
Assertion Languages 16
Assertions and Coverage 17
Assertion Language Concepts 17
Describing Behavior 17
Specifying Requirements using Assertions 18
Comparing Specified and Actual Behavior with Assertions 19
Concurrent Assertions 21
Procedural Assertions 21
Immediate Assertions 21
Deferred Assertions 22
Enabling, Fulfilling, and Discharging Clauses 22
Common Assertion Forms 24
Invariant Assertions 24
Conditional Assertions 24
Temporal Assertions 24
3 25
Writing PSL Assertions 25
PSL Domain 25
PSL Structure 25
PSL Categories 26
PSL Lexical Structure 27
PSL Data Types 28
PSL Conditions 30
HDL Expressions in PSL 30
PSL Expressions 32
PSL Built-In Functions 32
PSL Clock Expressions 40
PSL Sequences 44
PSL Declarations 45
PSL Sequence Arguments 47
PSL Sequence Instantiation 48
PSL Sequence Operators 49
PSL Sequence Clocking 51
PSL Repetition 51
The true Value 54
PSL Properties 55
PSL Property Declarations 55
PSL Property Arguments 57
PSL Property Instantiation 58
PSL Property Operators 58
PSL Property Clocking 71
PSL Property Replication 71
PSL Directives 72
The PSL assert Directive 73
The PSL assume Directive 74
The PSL cover Directive 75
PSL Directive Labels 76
4 77
Using PSL 77
General Rules for Embedding PSL Assertions in the Design 77
Using PSL as Native Code in VHDL 78
Putting PSL Assertions in Verification Units 80
Putting SVA Assertions in a PSL Verilog Verification Unit 91
Using PSL Sequences 91
Using HDL Functions in PSL 92
Using SystemC PSL 92
Referring to Signals in SystemC PSL 92
Accessing Assertions from a SystemC Testbench 93
Using the PSL always and never Operators 93
Using always and never in the Same PSL Property 93
Writing One-Time Checks in PSL 94
Using PSL abort with never 94
Example of PSL until and abort Operators 95
Analogy for PSL abort and until Operators 97
Using the assume and restrict Directives 99
Using PSL Repetition in Suffix-Implication Operations 100
Sampling Signals in Assertions 100
Preventing Assertion Failures at Time 0 100
Avoiding BOOLOP Messages for PSL Assertions 101
Using PSL Reactive Test Techniques 101
Using the PSL ended() Construct 102
PSL Event-Based Reactive Test Example 102
Using PSL in VHDL 105
Using PSL Assertions in VHDL generate Statements 105
Using VHDL Outputs in PSL Assertions 106
Using PSL ended() in HDL 106
How Synthesis Pragmas Convert to PSL 107
Enabling/Disabling Assertions in HDL 108
1
Introduction to Assertions
Assertions in Verification
ssertion checking is a simple addition to your simulation-based verification methodology. All you
A
need to do is add monitors to your design. These monitors are called assertions. During simulation,
these monitors watch to see
If a specific condition occurs, or
If a specific sequence of events occurs
The monitors generate warnings or errors if required conditions or sequences fail, or if forbidden
conditions or sequences occur.
Using Assertions
Assertions written to detect errors have two main uses:
You can use assertions to monitor the interface of a module.
Placing monitors on a module interface can help when integrating a block into a design,
because the monitors will quickly identify when the protocols or sequences of signals are
incorrect. This feature can also be very useful when reusing a design, or when providing IP to
other organizations.
In Figure 1-1, the white boxes marked "A" are the assertions in a design that monitor the
inputs to a module.
You can use assertions to monitor signals within a block. These monitors help verify that the
signal is behaving properly during circuit operation.
Placing monitors on a signal within a block can help track down intermittent problems within a
design, because the monitor is always watching the signal for correct operation.
In Figure 1-1, the black boxes marked "A" are the assertions in a design that monitor signals
within a block.
ABV Documentation
For information that will help you quickly get started with assertion checking, see the following
Cadence manuals:
Assertion Writing Quick Start
Provides hands-on exercises to get you started with dynamic simulation of Property
Specification Language (PSL) assertions in the Verilog, SystemVerilog, VHDL, and SystemC
flavors; and with SystemVerilog Assertions (SVA). Also includes printable quick reference
pages for PSL, SVA and ABV Tool Commands.
For detailed information about writing and using assertions, see the following Cadence manuals:
Assertion Writing Guide
(This manual) Describes how to write PSL assertions for Verilog, SystemVerilog, VHDL, and
SystemC designs, and how to write SVA assertions for SystemVerilog designs.
2
Basic Assertion Concepts
About Assertions
An assertion is a behavioral description that can function as any or all of the following:
A specification of required behavior
A statement of assumptions about system inputs
An active element that checks for design errors during simulation or emulation
A formal statement that can be verified exhaustively using a formal analysis tool
A means of precisely documenting interface requirements for IP users
Assertion Languages
Assertions can be written in many ways, even in general-purpose languages such as C. However, it
is more efficient to use languages designed specifically to describe behavior over time in a manner
that fits well within the typical design verification flows used today. This guide provides an
introduction to two such languages, PSL and SVA.
PSL is the 1850 IEEE standard for PSL. Chapter 3, "Writing PSL Assertions," provides an
overview of PSL.
SVA is the SystemVerilog Assertions subset of the 1800 IEEE standard for SystemVerilog.
Chapter 5, "Writing SystemVerilog Assertions," provides an overview of SVA.
Describing Behavior
PSL and SVA model the behavior of a system in terms of a hierarchy of concepts:
There are various ways to interpret the requirements imposed by directives. The most literal view is
that directives impose requirements on the behavior of the design and its environment--they specify
what the design must do, and the ways in which the design can be used. An alternative view is that
directives impose requirements on the verification process--they specify how tools must use
behavioral specifications to verify the design.
Which view you adopt will depend upon the methodology you select for verification. A more
manual, user-directed methodology might suggest the second view; a more automatic methodology
might suggest the first view. This manual adopts the first view, interpreting directives as
requirements on the behavior of the design and its environment.
Sequences
A sequence is satisfied when every Boolean in the sequence is satisfied. Most sequences are
expressed relative to some clock, rather than the simulation cycle. For example, a sequence
states that if a is true, then b must be true in the next negative edge of the clock, and c must be
true in the cycle after that. The sequence is tightly satisfied in the clock cycle in which c
evaluates to true (Figure 2-1).
Figure 2-1 Satisfying a Sequence
Properties
A property is satisfied, or holds, in the first cycle in which every sequence and Boolean in the
property is satisfied.
For example, a property states that If a is true at the negative edge of the clock, then b must be
true on the next negative edge of the clock. When this behavior occurs, check that c is true on
the negative edge of the clock in which b is true, and that d is true on the negative edge of the
clock after that. The sequence takes place over a span of three clock cycles. If all of the
behaviors hold, it is said to be satisfied in the first clock cycle, as shown in Figure 2-2.
Properties can be classified into Single Cycle and Multi Cycle properties as explained below:
Single Cycle properties are simple boolean/same cycle implication/one cycle sequence
properties which require just one clock cycle to evaluate.
Following are some examples of the single cycle properties:
property single_cycle_bool;
@(posedge clk) disable iff(reset) a && b;
endproperty
property single_cycle_impl;
@(posedge clk) disable iff(reset) a |-> b;
endproperty
property single_cycle_seq;
@(posedge clk) disable iff(reset) a ##0 b;
endproperty
All the above properties require 'a' and 'b' to be true in the same clock cycle.
Multi Cycle properties span over more than one clock cycle and require two or more clock
cycles to activate and evaluate. Following are some simple examples of multi cycle
properties:
property multi_cycle_impl;
@(posedge clk) disable iff(reset) a |=> b;
endproperty
property multi_cycle_seq;
@(posedge clk) disable iff(reset) a ##1 b ##1 c |=> d ##5 e;
endproperty
Multi cycle properties include ranges and repetitions across number of clock cycles.
Assertion Categories
The following describes the different ways in which assertions can be activated and evaluated
during processing.
Concurrent Assertions
Concurrent as applied to assertions means that sequence detection runs concurrently with the
simulation; that is, the simulation continuously monitors design behaviors. The simulation evaluates
concurrent assertions when signals in the design that are referenced in the assertions change
values.
Procedural Assertions
A procedural assertion is evaluated when the flow of control in a procedural block of code reaches
the assertion.
You can use procedural assertions in a Verilog always block with procedural code, such as a case
statement or an if-then-else block. They will be evaluated depending on which branch is taken;
assertions will be activated only in the context in which they are important.
Immediate Assertions
Immediate assertions are procedural assertions that can check only a single combinational
condition; they cannot involve temporal (sequential) operators. These assertions are also referred to
as simple immediate assertions.
Deferred Assertions
Deferred Assertions
Deferred assertions are immediate assertions that are used to suppress errors that occur due to
glitching activity on combinational inputs to immediate assertions. These assertions are also
referred to as deferred immediate assertions.
The enabling condition can be any Boolean or sequential expression. You can string
multiple enabling conditions and implication operators together to form a complex enable. The
assertion is considered to begin when the first sequence of the enabling condition evaluates
to true.
The fulfilling condition defines the behavior to be checked. It is checked on every verification
cycle by default. If it has an associated enabling or clocking condition, that condition defines
when to check it.
In the following PSL example, the simulation continually monitors the in1 signal at every
positive edge of the default clock to see if it is true; this is the enabling condition.
default clock = (posedge clk);
The next in2 clause specifies a fulfilling condition. If in2 becomes true in the next simulation
cycle after in1 becomes true, the fulfilling condition has evaluated to true. If it does not, the
assertion fails.
The discharging condition indicates when to stop checking the behavior. When a
discharging condition becomes true, the simulation stops checking the fulfilling condition. In
PSL, for example, discharging conditions can be until, until_, async_abort, sync_abort, and
abort followed by a Boolean expression. In SVA, the discharging condition is specified using
the disable iff construct.
In the PSL example that follows, the until keyword specifies a discharging condition. When
in1 is true, in2 must be true in the next cycle, and remain true until the cycle in which in1 goes
false, even if in2 is true forever and in1 is never false.
// psl IN2_UNTIL_NOT_IN1: assert always (in1 -> next (in2 until !in1));
The clocking condition specifies when the conditions are to be checked, such as a particular
edge of the clock.
A property that is asserted will be checked during simulation. When the property's enabling
sequence occurs--when the endpoint of the enabling sequence is reached--the assertion expects
the fulfilling sequence to occur next. To see if this is true, the assertion is checked:
If the fulfilling sequence does occur, the assertion finishes.
If the fulfilling sequence does not occur, the assertion fails.
At any given time during simulation, the number of times each assertion has been checked, has
finished, or has failed is reported.
In simulation, properties are checked along a particular trace, or sequence of states through which
the design progresses as a result of its inputs.
If an assertion is not checked at all in a given simulation run, its enabling condition never
occurred during that run.
If it has been checked in a given run and has finished, the design's behavior during the run
conformed to the behavior described by the asserted property.
However, the assertion was checked only for that specific input stimulus, and only up until the
simulation ended. It is always possible that an assertion that did not fail in a given simulation
might fail if that simulation ran longer, or it might fail in another simulation.
In formal analysis, assertions are checked for all possible traces, starting at an initial state. If an
assertion does not fail in formal analysis, it will not fail in any simulation run, provided that the
constraints used to verify the property are satisfied by the context in which the design appears.
Invariant Assertions
An invariant condition is a condition that must hold throughout the operation of the design. The
condition must always or never be true.
For example:
A Grant never occurs without a Request.
The enable_n line must always be high on the falling edge of write_n.
The read_n and write_n lines must never be low at the same time.
Conditional Assertions
Conditional assertions specify that one condition must occur if another condition occurs. These
assertions specify activity that is required or disallowed as a consequence of some other activity.
For example:
If m_task = read, it must always be followed by read_n low for two samples, followed by read_n
high for one sample.
If A receives a Grant, then B does not.
Temporal Assertions
You can use assertions to set bounds on the behavior of a design. Temporal assertions can be
bounded or unbounded.
Bounded
Bounded assertions describe a condition that must occur within certain limits. For example, if
in2 is true, out1 must become true in the next cycle.
U nbounded
Unbounded assertions describe a condition that must eventually occur. For example, the
IOReq signal must be followed by an IOGrant at some indeterminate time in the future.
3
Writing PSL Assertions
PSL Structure
PSL is used to define properties--the temporal relationship among a set of design elements.
Properties are built from Booleans, sequences, and subordinate properties. There are two common
styles of properties in PSL:
Sequence-based ("suffix implication") properties
Sequence-based properties are built using the suffix implication operators, |-> and |=>. For
example:
{a[+];b} |=> {c[*];d}
For more information, see "The PSL |-> Suffix Implication Operator" and "The PSL |=> Suffix Next
Implication Operator" .
Keyword-based properties
Keyword-based properties are built using keyword operators and the Boolean implication
operator, ->. For example:
always a -> next b until c
These properties describe behavior patterns using English words that represent temporal relationships. The
keyword operators include always , never , until , until_ , before , before _, eventually! , next ,
PSL Categories
PSL properties always act as concurrent elements in the design. They monitor the behavior of the
inputs and outputs of other concurrent elements in the design. They act like a Verilog always block
or a VHDL process, reacting to changes on input signals.
Although you can embed a PSL assertion within a Verilog always block or VHDL
process, it is not affected by the sensitivity list of the always block or process, and is not
executed as a sequential statement. Any PSL assertion is executed as a separate process,
regardless of where you write it.
Identifiers
Identifiers are names of your choice to uniquely identify properties, sequences, and endpoints.
An identifier must start with an alphabetic character, followed by zero or more alphanumeric
characters, each of which can optionally be preceded by a single underscore. Identifiers are case-
sensitive in the Verilog, SystemVerilog, and SystemC flavors, and case-insensitive in the VHDL
flavor.
Keywords
I f you have an HDL name that is also a PSL keyword, you cannot reference it directly by its simple
name in a PSL property. You can reference the name indirectly, by using its HDL hierarchical or
qualified name. PSL keywords that are supported by the Incisive simulator are listed in the following
table.
Operators
Operators
For any flavor of PSL, the HDL operators, including logical, relational, and arithmetic operators,
have the highest precedence. The PSL operators and their precedence are listed in the following
table.
@ left
within left
SERE | left
: left
; left
-> right
Assertions are intended to monitor the HDL, not change the values of signals. The
increment and decrement operators are not allowed in PSL properties.
The following table shows, for each language, the data types (and, for Verilog, objects that contain
the implicit data type) that are compatible with each of the PSL type classes. These type classes
are used to define
What kind of arguments are used with built-in functions
What kind of expressions are allowed to appear as Boolean or Numeric expressions in a
sequence or property, or as arguments of a sequence or property
To use a data type that is not mentioned in Table 3-1, you need to either convert it to a supported
data type, or use it in an expression that results in a supported data type. For example, to use a
variable of type T in a Boolean expression, if T is not one of the types that are listed as compatible
with the Boolean type class, you can compare the variable to a value, provided that the comparison
operation returns a value of a type that is listed as compatible with the Boolean type class.
The data types listed in this table can be used as formal arguments to PSL properties and
sequences. Additionally, any HDL or user-defined data type can also be used.
1 Includes the Verilog objects that contain values of the built-in logic types, such as reg and wire
PSL Conditions
The PSL Boolean layer consists of expressions that represent these conditions. Expressions can
be
HDL Expressions in PSL
PSL Expressions
PSL Built-In Functions
PSL Clock Expressions
Boolean Expressions
The following guidelines apply to using Boolean expressions in PSL:
You can use any HDL operator, including comparison operators, in a Boolean expression.
Signals that can take on the bit values `0' or `1' are usually allowed to appear where a
Boolean expression is required in PSL. This includes any signal in Verilog, and signals of
certain types in VHDL, SystemVerilog, and SystemC (see Table 3-1).
_( SystemC/C++_expressions )
When the SystemC PSL parser encounters this literal-inclusion construct, it performs limited data
type checking, then passes everything between the parentheses. If an expression in the
SystemC/C++_expressions is not Boolean, you must use it in an expression that is Boolean--for
example, as an argument to a Boolean built-in function, or as an operand of a relational expression.
As the SystemC PSL parser does not parse for signal names in a literal inclusion construct,
value changes in an unclocked assertion will not be detected.
For detailed information, see "Boolean Expressions in SystemC PSL," in " Using SystemC PSL ," of the SystemC
Simulation Reference .
PSL Expressions
PSL defines the -> operator as an additional combinational operator, so that for Booleans A and B,
the expression A->B is also a Boolean expression, one that is true if either A is false or B is true.
If the operands are both Boolean, the -> operator is interpreted as the combinational implication
operator. Otherwise, it is interpreted as the temporal "logical if" operator.
For more information, see "The PSL -> Implication Operator".
stable().
Those that determine the values of bits in a vector at a given time: isunknown(), countones(),
onehot(), and onehot0().
The built-in functions are governed by the same clocking as the context in which they appear.
For example, prev(x) is true if x was true the last time this property was evaluated.
entity e is
port(Q: in bit_vector(0 to 3));
end e;
architecture e_a of e is
signal S: bit_vector(0 to 3);
signal Y: integer := 10;
signal X: integer := 50;
begin
S <= "1010";
process(Q)
begin
--psl property P1(const m) is always (S(0)->Q(m))
@(rising_edge(<<signal.top.clk:std_logic>>));
-- psl assert P1(2);
-- psl assert always {countones(<<signal.top.S:bit_vector(0 to 3)>>) =2};
end process;
process(Y)
begin
-- psl assert always {<<signal.top.topY:integer>> + Y < X};
end process;
end e_a;
entity top is
end top;
VHDL external name references work only in a pure VHDL context. You cannot reference
external names in other languages, such as Verilog. External name references cannot pass
through non-VHDL hierarchies, even if they terminate in a VHDL item.
Memories and multidimensional arrays are not supported as arguments to the built-in
functions.
For the VHDL flavor of PSL, the following data types are supported for the built-in functions:
std.standard.boolean
std.standard.bit
std.standard.integer
std.standard.real
std.standard.bit_vector
IEEE.std_logic_1164.std_logic
IEEE.std_logic_1164.std_logic_vector
IEEE.std_logic_1164.std_ulogic_vector
IEEE.numeric_std.signed
IEEE.numeric_std.unsigned
IEEE.numeric_bit.signed
IEEE.numeric_bit.unsigned
IEEE.std_logic_arith.signed
IEEE.std_logic_arith.unsigned
Limitations
Package referenced signal given as input argument to built-in function
A signal of any type, is member of package PACK, and cannot be passed as an input
argument to a built-in function prev/stable using dot operator (.) whereas built-in function prev
is used inside the architecture body.
Example:
-------PACKAGE------------
package pack is
TYPE STATE_TYPE is (
idle,
gnt0,
gnt1
);
SIGNAL state : STATE_TYPE := idle;
end;
----------ARCH------------------
use work.pack.all;
architecture arch of dut is
--psl property P2 is always {prev(work.pack.state) = idle}; //state is an enumerated signal
defined inside package scope
--psl assert P2;
begin
end arch;
Use of built-in function inside PSL Sequence along with fusion as well as delay operator
The fusion operator `:' and delay operator `;' are used inside a PSL Sequence. Built-in
functions along with any type of VHDL signal as input arguments are present with fusion and
delay operator inside PSL Sequence.
Example:
Signal std1 : std_logic := `0';
stable(std2)};
Use of nested built-in functions inside PSL Sequence where stable/prev appears as outer
built-in and rose/fell appear as inner built-in functions.
Multi-Dimention array or MD array with index given as input to PSL built-in function.
A scenario where signal arr2_rec of a MD array has been passed to a built-in function stable,
is a limitation for this feature.
This function indicates the rising edge of a signal. For example, the expression rose(in1) is true
(has the value 1) if in1 had the value 0 in the previous time tick and has the value 1 in the current
time tick. Otherwise, the expression is false.
In the following example, a specified condition must occur some time after the intc signal rises:
assert always
(rose(intc) -> eventually! (mw && add==3'b001));
This function indicates the falling edge of a signal. For example, the expression fell(in1) is true
(has the value 1) if in1 had the value one in the previous time tick and has the value 0 in the current
time tick. Otherwise, the expression is false.
The value of fell() is affected only by the sequence of time as seen by the verification tool. In the
following example, a specified condition must hold in the same time tick in which intc transitions
from 1 to 0:
assert always (fell(intc) -> (data==8'b0000_0000));
This function returns the value of an expression at the previous time tick as seen by the verification
tool. If you include a cycle index, i , this function returns the value of the expression in the i th
previous time tick.
For VHDL, the simulation tool must be able to determine the type of the expression at parse time, so
it must be a local identifier, not a complex expression of ambiguous width, such as a math
operation.
You can use Verilog OOMRs and VHDL external names for the expression. For VHDL external
names, use the << external . name : type >> syntax and the -v200X compiler option; see "Data
Types for PSL Built-In Functions" for an example and limitations. For Verilog and SystemVerilog,
you can also use packed structures and enumerated types.
he i value is the number of cycles in the past at which to sample the expression. This value can
T
be a statically computable positive integer, or a generate statement index variable. For
Verilog/SystemVerilog, the i value can be a generic, mathematical, or parameter expression.
Parameters and mathematical expressions are not supported for VHDL and SystemC.
The following example checks whether the address signal has the same value that it had in the
previous time tick:
assume always
({req && !ack} |=> address == prev(address))
@(posedge clk);
To improve performance, avoid large numbers in the argument of the prev() built-in
function. For example, prev(x,100) must find the value that x had 100 clocks
previous to the current clock cycle. Instead, it is more efficient to implement
this function with some auxiliary HDL.
This function returns True if the value of Any_Type is the same as it was in the previous time tick.
In the following example, the address signal must be stable in the time tick after the req && !ack
sequence finishes:
assume always ({req && !ack} |=> stable(address)) @(posedge clk);
For VHDL, the signed and unsigned types are not currently supported for this function.
ended(
Sequence )
This function is used to detect a sequence match. It returns True for the cycle in which the last
component of the sequence is detected, and False otherwise. If the second argument is specified, it
is equivalent to
ended({Sequence }@Clock_Expression )
The PSL ended() function can be used anywhere a Boolean can be used:
The ended() function is often used for reactive tests. For general information about reactive tests,
see Chapter 9, "Writing Reactive Tests using Assertions." For information about using the PSL
ended() function for reactive tests, see "Using PSL Reactive Test Techniques".
This function returns True if BitVector contains any bits that have a value of "unknown"--that is,
values other than 0 or 1.
In the following example, the A_unknown assertion calls $isunknown at each positive edge of clk:
A_unknown: assert always !isunknown(d) @(posedge clk);
This function returns the number of bits in BitVector that have a value of 1. For example:
assert always (countones(memword) % 2 == 1);
This function returns True if BitVector contains exactly one bit that has a value of 1. For example:
assert always onehot(gnt);
his function returns True if BitVector contains at most one bit that has a value of 1. The argument
T
can be an out-of-module reference (OOMR). For example:
assert always onehot0(enable[115:0]);
In the presence of race conditions, posedge and negedge can produce different results from
rose and fell.
You can use rose and fell within a sequence to detect data edges; for example:
{rose(a); fell(b)}
The rose and fell functions are portable between PSL dialects, whereas posedge and
negedge are not.
@( event_expression )
In many cases, you might want an assertion to be evaluated only at a specific event, like a clock
edge. To specify an event for evaluating assertions, use the clock expression at the end of your
property declaration.
The event_expression is the same as the event expression that you can use in the sensitivity list
of a Verilog always block or a VHDL process block.
Always use parentheses to associate the clock, because the clock has the highest
precedence, and applies only to the property to its immediate left. For example:
assert always GNT -> next BSY @(posedge clk);
is equivalent to
assert always GNT -> next (BSY @(posedge clk));
In the following example, the mem_control1 assertion will be evaluated each time the write or read
lines change value:
memcontrol1: assert never ( write && read ) ;
This declaration will evaluate the assertion on every rising edge of clk:
memcontrol1: assert never (write='1' AND read='1') @(rising_edge(clk)) ;
For Verilog/SystemVerilog and VHDL, you can specify multiple clocks for a property. This feature
allows you to specify assertions that cross clock domains.
A default clock declaration defines a clock expression to be applied to any directives within its
scope that do not have an explicit clock expression.
When several assertions in a module share the same edge expression or clock, you can define a
default clock to use for all of these assertions. The default clock is applied to any directive whose
property is not clocked at the highest level--the outermost property in the directive--as though the
property were parenthesized. You must define the default clock before the assertions that use it.
The Incisive implementation of PSL lets you define multiple default clocks. Only one
default clock is effective at any point in the code. This feature is not part of the PSL standard.
The default clock is used by all assertions that follow that default clock definition, until
another default clock definition is encountered.
When the clock expression in the most recent default clock declaration is true, if there is one;
otherwise
If you do not want a property definition to be clocked, you must put it before the first
default clock definition.
In property files, the default clock's effect is limited to the verification unit in
which it is defined. It is not inherited. It affects only the assert and other directives
in the verification unit in which it appears.
In this example
The check_on_signal_change assertion is an unclocked assertion. It has no clock defined in
the assertion, and it is declared before any default clock. This assertion is evaluated
whenever a or b changes value.
The pos_edge_clk assertion is clocked on the positive edge of clk. It has no clock defined in
the assertion, and it appears after the first default clock declaration, so it uses that default
clock. This is equivalent to
pos_edge_clk: assert always ( a='1' AND b='1' ) @(rising_edge(clk)) ;
The my_clock assertion is clocked on the positive edge of my_clk, as specified in the
assertion.
The neg_edge_clk assertion is clocked on the negative edge of clk. It has no clock expression
specified in the assertion, and it appears after the second default clock declaration, so it
uses the clock expression of that default clock declaration. This is equivalent to
neg_edge_clk: assert always ( a='1' AND b='1' ) @(falling_edge(clk)) ;
PSL Sequences
In general, a sequence is a series of conditions that occur at successive times. For example:
{req; ack; read; !req; !ack}
{state==s1; state==s3}
A sequence can be clocked or unclocked. The examples that follow assume that the sequences occur in a
context in which the default clock applies.
A sequence can also contain a series of elements, separated by the concatenation operator (;)
(see "Concatenation".). For example, the following is a sequence
{ req ; ack ; !req }
Each Boolean expression in the sequence represents a condition, and each condition occurs in the cycle after the
previous condition occurs.
A sequence can also contain other sequences. For example, the following sequence
{ { req ; ack } ; busy ; { !req ; !ack } }
This expression is equivalent to the following flattened sequence, which says that req occurs in
cycle 1, then ack occurs in cycle 2, then busy occurs in cycle 3, then !req occurs in cycle 4, and
!ack occurs in cycle 5.
{ req ; ack ; busy ; !req ; !ack }
PSL Declarations
PSL includes two forms of declaration related to sequences: the sequence declaration, and the
endpoint declaration. Both define a name associated with a sequence.
You can improve simulation performance by using sequences with more specific, and less
frequent, conditions. The following example shows an inefficient use of a sequence:
sequence command_silence is
{((m_command_en_n='0') or (m_command_in='1')) [*8 to inf]};
On the second and later cycles of this sequence, not only does the simulation begin to
count, but it creates new instances of the sequence. A more efficient solution is to use
auxiliary HDL code, as follows:
process (m_clk) begin
if (falling_edge(m_clk)) then
if ((m_command_en_n='0') or (m_command_in='1')) then
m_counter <= m_counter + 1;
else
m_counter <= 0;
end if;
end if;
end process;
The endpoint construct has been replaced by the built-in ended() function in the IEEE 1850
PSL standard. The endpoint declaration is still supported in the Incisive simulator for
backward compatibility.
For example, the following endpoint declaration defines the name RunPath to mean the end of the
specified sequence. Any reference to RunPath is the same as a reference to a Boolean signal that is
True in the last cycle of any trace that tightly satisfies the sequence in the RunPath definition (see
"Satisfaction and Endpoints in PSL").
endpoint RunPath is { (state=idle; state=start; (state=run)[*3]; state=done;
state=idle) };
The rules for formal and actual arguments and instantiation are the same for endpoint as they are
for the sequence declaration ("PSL Sequence Declaration").
Endpoints in Boolean expressions and the modeling layer are not supported. You can use
the built-in ended() function instead.
You can define a name for a single condition by declaring an endpoint for the sequence that
contains a single Boolean expression representing that condition. The endpoint name can
then be used wherever a Boolean expression is allowed within a sequence or property.
It takes time to construct an endpoint model, which can affect simulation performance. To
avoid unnecessary performance degradation, do not create endpoints that will not be used.
sequence--A sequence
property--A property
The argument type is followed by one or more argument names. The hdltype is followed by the
HDL or user-defined data type, then the argument name. Arguments in a list are separated by
semicolons. For example, the following sequence declaration defines the name GenericOp to mean a sequence in
which the start and done Boolean arguments bracket a series of n repetitions of the op sequence:
sequence GenericOp (boolean start, done; sequence op; const n) =
{start; op[*n]; done};
Similarly, the following endpoint declaration defines the name end_seq to mean the endpoint of
whatever sequence is passed in as argument S.
endpoint end_seq (sequence S) is { S };
ou can define sequences and use instances of them as components in complex assertions, as
Y
shown in the following examples:
sequence RW_DATA_EN = {!RcvDataEn; RcvDataEn[*4]};
rcv_write_RcvDataEn: assert always {triggerRW} |-> {RW_DATA_EN};
Concatenation
{ SERE ; SERE }
looks for
1. d equal to 1 on the first positive edge of clk. If this is not true, the assertion fails. If it is true,
then it looks for
2. a equal to 1 on the second positive edge of clk. If this is not true, the assertion fails. If it is true,
it looks for
3. b equal to 1 on the third positive edge of clk. If this is not true, the assertion fails. If it is true, it
looks for
4. c equal to 1 on the fourth positive edge of clk. If this is not true, the assertion fails. If it is true,
the assertion passes.
Fusion
Sequence : Sequence
A sequence can involve the fusion operator (: ), which is similar to the concatenation operator but
without a cycle delay. For example:
{ { req ; ack } : busy }
is a sequence that says that busy occurs in the last cycle of the { req ; ack } sequence. Generally,
the fusion operator means that the second operand overlaps the first operand by one cycle. If the
two operands are both sequences, the last condition of the left operand and the first condition of the
right operand both occur in the same cycle.
For example:
{ { req ; ack } : { busy ; done } }
is equivalent to
{ req ; (ack && busy) ; done }
OR
Sequence | Sequence
You can use the sequence OR operator, | , between two sequences, when either the first sequence
or the second sequence, or both, must start and not fail. For example:
header_i_o: assert always {header_in_seq} |=>
{{[*]; {header_out_seq}} | {cancel}}
@(posedge clk);
Non-Length-Matching AND
You can use the sequence AND operator, & , between two sequences, when both sequences must
start in the same cycle and not fail. The two sequences might finish in different cycles. For example:
sequence data_out = {{header_out_seq} &
{data_out==data_aux1; data_out==data_aux2;
data_out==data_aux3; data_out==data_aux4}}
@(posedge clk);
Length-Matching AND
You can use the sequence AND operator, && , between two sequences, when both sequences
must start in the same cycle and finish in the same, usually later, cycle. For example:
rd_and_wr: cover
{ {rd_seq} && {wr_seq} } @(posedge clk);
within
Sequence within Sequence
You can use the within operator between two sequences, when the first sequence must start at or
after the cycle in which the second sequence starts, and finish at or before the cycle in which the
second sequence finishes. This operator is equivalent to {[*];Sequence1;[*]} && {Sequence2}.
For example:
Ack_After_Req: assert always
{ {ack[*2]} within {req; [*]; grant} } @(posedge clk);
A sequence can be clocked by adding a clock expression. The clock expression specifies when the
Boolean expressions in the sequence are evaluated. For example:
{ req ; ack ; busy[*3] : done ; !req ; !ack } @(rose(clk))
i s a sequence clocked by rose(clk), a PSL built-in function that returns True when its argument
(clk) has just risen. Each Boolean expression in the sequence will be evaluated in turn at
successive rising edges of clk. If a sequence has no clock expression--is an unclocked sequence--
it inherits the clock expression from the context in which it is contained, if any.
For more information about clocking, see "PSL Clock Expressions".
PSL Repetition
R epetition operators define a sequence in which the operand occurs repeatedly. For example:
req[*3]
Similarly:
{ clk ; !clk }[*3]
is equivalent to
{ { clk ; !clk } ; { clk ; !clk } ; { clk ; !clk } }
which is equivalent to
{ clk ; !clk ; clk ; !clk ; clk ; !clk }
R [* n ] B [= n ] B [-> n ]
R [* n : m ] B [= n : m ] B [-> n : m ]
For example:
a[*3] matches the trace ( a , a , a )
If the repeat count is a range, the resulting sequence matches any trace in which the operand
is repeated some number of times in that range. If the upper bound in such a range is inf, the
upper end of the range is unbounded--that is, the resulting sequence will match any number of
repetitions equal to or greater than the lower bound of the range.
The upper limit for a repeat count is about 64K. Using very large repeat values,
such as ack[*20000000], uses a large amount of memory, but unbounded repeat
values, such as ack[*], do not.
R Equivalent to R [*0:inf].
[*]
R Equivalent to R [*1:inf].
[+]
R Matches an empty trace--a trace of length zero. For example, {a; b[*0]; c}
[*0] matches the trace (a, c), because b[*0] matches the empty, or zero-length,
trace between a and c.
B Matches any trace in which B does not occur. That is, B[=0] is equivalent to
[=0] !B[*].
[*] For any consecutive repetition operator, if the operator appears with no
[* n operand, the default operand is True, which matches any cycle. So [*]
] matches a trace of any length, including the empty trace; [*5] matches any
[* n trace of length 5; [*2:3] matches any trace of length 2 or 3; and [+] matches
:m] any trace of length 1 or more.
[+]
A repeated sequence might or might not match a trace, depending on how it is clocked. A
sequence can be clocked, either by an explicit clock expression or by inheriting a clock context.
A clocked sequence is evaluated only when its clock expression is True. For example, given
the following traces:
sequence a[*3] @(posedge clk or negedge clk) matches twice, but sequence
a[*3]@(rose(clk)) does not match.
A given sequence can match overlapping portions of the same trace. For example, given the
following traces, and assuming a clock of @(posedge clk or negedge clk):
ou can use repetition with true. For example, true[*3] represents three cycles in which anything
Y
can happen, and true[*] represents any number of cycles in which anything can happen. For
example:
A1_slc: assert never {true; (in1->in2); clk; true[*2]; out1};
The in1 and in2 signals are high in the next cycle.
Specifying [*3] between semicolons is the same as specifying true[*3]. Similarly, ;[*]; is the
same as ;true[*];, and ;[+]; is the same as ;true[+];.
PSL Properties
A property is a temporal relationship among conditions and sequences. For example:
always (a)
never {b; c; d}
{req; ack} |=> {read; !req; !ack}
property declaration describes the behavior of the design or its environment in terms of temporal
A
operators.
A PSL property declaration ends with a semicolon. For example:
property req_evnt_gnt = always
(req -> eventually! gnt) @(posedge clk);
You can define PSL sequences, properties, and endpoints in VHDL and SystemVerilog
packages. Notes about PSL in packages:
If a package containing PSL is used by an architecture, any verification unit bound to
that architecture can reference the package PSL.
PSL sequences and endpoints declared in package A can be used in other PSL
sequences, endpoints, and properties declared in package B, as long as package B
imports package A to make the PSL visible.
You can use both the pragma and native forms of VHDL PSL in packages.
You cannot define a default clock in a package, because it applies only to directives,
not to properties and sequences.
If you want properties and sequences in a Verilog package to reference properties and
sequences in another package that is compiled into a different library, you must import
the definitions of all of the referenced properties and sequences from both packages.
Similarly, for VHDL packages, you must specify a use clause to access referenced
properties and sequences in another package.
You must use the -assert compiler option to enable PSL pragmas in packages.
You must use the -v200x option for native PSL in VHDL packages.
You can define a PSL property in a VHDL entity definition, so that it applies to all
architectures associated with that entity. For example:
library ieee;
use ieee.std_logic_1164.all;
entity decoder_3to8 is
port (
clk : in std_logic;
input : in std_logic_vector(2 downto 0);
output : out std_logic_vector(0 to 7) );
begin
--psl default clock is (falling_edge(clk));
-- psl p1: cover {output(0); output(1); output(2) };
end decoder_3to8;
This feature will not work in a mixed-language model where the VHDL architecture is
actually a Verilog model.
The argument type is followed by one or more argument names, separated by commas. The
hdltype is followed by the HDL or user-defined data type, then the argument name. Arguments in a
list are separated by semicolons.
For example:
property ResultAfterN (boolean start, stop; property result; const n) = always
((start -> next[n] (result)) @ (posedge clk) abort stop);
3 See Table 3- 1.
The Incisive simulator does not support recursive instantiation of properties. You cannot
instantiate a declared property within itself.
Note: With the exception of eventually!, before!, and before!_, the strong (!) operators
are currently not supported.
For most assertions, properties must start with the always or never operator. These operators
declare when the property must be true. They specify invariant conditions that must hold throughout
the operation of the design. The invariant condition is defined by the appropriate HDL expression.
For a description of assertions that do not use the always or never keywords, see "Writing
One-Time Checks in PSL".
The simplest way to describe conditions in a property construct is to use Boolean expressions. For
example, the following property states that the write and read signals must never be true at the
same time:
mem_control1: assert never ( write='1' and read='1' ) ;
Both always and never specify a fulfilling condition. The expression is repetitively checked at the
edge condition. When the edge is not explicitly specified, the signals in the property form the edge
condition, similar to a sensitivity list (this is an Incisive simulator interpretation, and might not be
portable). The following are examples of invariant properties.
The enable_n line must always be high on the falling edge of write_n.
WRITE_N_AND_ENABLE_N: assert
The read_n and write_n lines must never be low at the same time.
READ_N_AND_WRITE_N: assert
For more information about using the always and never operators, see "Using the PSL always and
never Operators".
The -> ("logical if") operator allows if/then checking of an assertion. For example, the following
assertion
label : assert always left_operand -> right_operand ;
If the right_operand is also true, the assertion passes. If the right_operand is false, the
assertion fails.
he left operand must be a Boolean expression. The right operand can be a Boolean, sequence, or
T
property.
he following assertion uses the -> operator to specify that if gntA is true, gntB must be false in the
T
same cycle. There is no delay involved.
If_GntA_No_GntB: assert always
(gntA -> !gntB) @(posedge clk);
You can combine -> operators into a complex expression. In the following example, the
right_operand will be checked only when in_1 , in_2 , and in_3 are true:
complex_if: assert always in_1 -> in_2 -> in_3 -> right_operand ;
The |-> ("suffix implication") operator also allows if/then checking of an assertion. Unlike the ->
operator, which requires a Boolean expression as the left operand, the |-> operator requires a
sequence as the left operand. The |-> operator specifies that evaluation of the right operand starts
in the same cycle in which the left operand sequence finishes.
As the two operands must overlap by exactly one cycle, they cannot have different clocks--
the overlap cycle cannot be spread out over two different clocks.
If the right_operand is true, the assertion passes. If the right_operand is false, the assertion
fails.
The left operand must be a sequence. The right operand can be a Boolean, sequence, or property.
The following assertion uses the |-> operator to specify that in2 is true in the same cycle in which
in1 goes high. There is no delay between the completion of the left operand sequence and
checking of the right operand.
For information about the performance issues involved in using an open-ended repetition
operator in a suffix implication operation, see in "Using PSL Repetition in Suffix-Implication
Operations".
ou can use the |-> operator in place of the -> operator by putting braces around the Boolean
Y
expression that is the left operand of the -> operator. For example:
fill_up_fifo: assert always (seq_fill_up -> full) @(posedge clk);
The |=> ("suffix next implication") operator is yet another operator that allows if/then checking of
an assertion. Like the |-> operator, it requires a sequence as the left operand. Unlike the |->
operator, the |=> operator specifies that evaluation of the right operand must start in the next cycle
after the one in which the left operand sequence finishes.
For example, the following assertion
label : assert always { left_operand } |=> right_operand ;
If the right_operand is true, the assertion passes. If the right_operand is false, the assertion
fails.
The left operand must be a sequence. The right operand can be a Boolean, sequence, or property.
The following assertion uses the |=> operator to specify that a rising edge on in1 is followed by
another rising edge on in1. There is a one-cycle delay from the end of the left operand sequence to
the beginning of the right operand sequence.
Rising_IN1_Repeats: assert always ({!in1; in1} |=> {!in1; in1}) @(posedge clk);
In this example, the right operand sequence is the same as the left operand sequence, so each
occurrence of a rising edge on in1 that satisfies the right operand sequence also satisfies the left
operand sequence. Therefore, the assertion requires an infinite series of rising edges to occur.
For information about the performance issues involved in using an open-ended repetition
operator in a suffix implication operation, see in "Using PSL Repetition in Suffix-Implication
Operations".
You can use the |=> operator in place of the operator pair |-> next without changing the meaning.
For example:
assert always {Req} |-> next Ack;
The following example uses the |=> operator to specify that READ_PULSE must start in the first cycle
after m_task goes to 2'b10. In the following example, if m_task = 2'b10, it must always be followed by
read_n low for two samples, followed by read_n high for one sample. This assertion is sampled on
the positive edge of clk.
The until operators specify that the left operand holds until the right operand holds.
For many bus protocols, you expect a specific condition to hold until you receive a response.
Once the response is received, the protocol is complete. PSL has two operators to address these
kinds of protocols: until and until_. These operators specify a discharging condition--when this
condition occurs, the simulation stops checking the fulfilling condition.
The following example uses the until operator to model a bus protocol where req must hold until a
gnt is received. Once the response is received, the protocol is complete, and the assertion that
models the protocol ends successfully. For example:
hold_req_until_gnt: assert always
(req) -> (req until gnt) @(posedge clk);
Use until to model situations in which in-flight, multi-cycle behavior continues, but no new
behaviors start. For example, the until property is useful for checking that a Boolean condition
stays true until an event occurs in your system.
se until rather than abort if the behavior is a single-cycle Boolean condition, even though, in this
U
case, the two operators have the same meaning. Reserve abort for multi-cycle behavior.
Because until and until_ are weak operators (not followed by an exclamation mark, !), they do
not specify that the terminating property must eventually hold.
Using the until Operator
The until operator specifies that the left operand holds up to, but not necessarily including, the
cycle in which the right operand holds.
I n the following example, when in1 is true, in2 must be true in the next sample, and remain true
until in1 becomes false. This implies that in2 must stay high if in1 never becomes false.
IN2_UNTIL_NOT_IN1: assert always in1 -> next (in2 until !in1);
For more information about the until operator, see "Example of until Usage," following, and "Using
the PSL until and abort Operators".
U sing the until_ Operator
The until_ operator specifies that the left operand holds up to and including the cycle in which the
right operand holds.
he following example is similar to the previous one, except that in2 must be true up to and
T
including the cycle in which in1 goes false.
IN2_UNTIL_NOT_IN1: assert always in1 -> next (in2 until_ !in1);
Using the signal values shown in the following table, on the negative edge of the clock, the first
trace for this assertion is
active (A) when the enabling condition begins--REQ and GNT are 0 in clock tick 1.
This assertion creates overlapping traces. The behavior being checked begins in clock tick 1 and
finishes successfully in clock tick 2--the behavior occurred as specified. However, the discharging
condition has not been encountered, so the simulation continues checking for the behavior. A
second trace begins in clock tick 2 and finishes successfully in clock tick 3. The third trace begins in
clock tick 3, but the simulation stops checking the behavior when it encounters the discharging
condition in clock tick 4. If any other traces were being checked when the discharging condition
occurred, the simulation stops checking them as well.
Similarly, the simulation begins checking new traces in clock tick 5, which complete in clock ticks 6
and 7. However, when the enabling condition becomes false, assertion checking becomes inactive.
When REQ becomes 0 in clock tick 10, assertion checking begins again, and the assertion becomes
active.
For more information about until, see "Using the PSL until and abort Operators".
The before operators specify that one Boolean must hold before a second Boolean holds.
For the before/before! forms, a Boolean is True in some cycle before the cycle in which a
second Boolean is True. In the following example, GntA must be high before GntB goes high:
Rnd_Rbn_Gnt: assert always
@(posedge clk);
For the before_/before!_ forms, a Boolean is True in some cycle before or in the same cycle
in which a second Boolean is True. In the next example, which uses the before_ form of the
operator, IOReq must be high either before or in the same cycle in which IOGrant goes high:
Req_To_Gnt_B_: assert always
Because before and before_ are weak operators (not followed by an exclamation mark, !), they do
not specify that the left operand must eventually hold. The before! and before!_ forms specify that
the left operand must eventually hold.
In the following example, REQ must be high before GNT goes high:
// psl default clock = (negedge clk);
// psl assert_before: assert always (!REQ && !GNT) -> next (REQ before GNT);
Note: These and other states are described in "Understanding Assertion States," in Assertion
Checking in Simulation.
One of the operators you can use to check a sequence of events is the next operator.
If the left_operand holds in the current cycle, the right_operand must hold in the next cycle, or the
assertion fails.
In this example, if gnt[0] && !req[0] holds in a cycle, then !gnt[0] must hold in the next cycle, or
the assertion fails:
no_consec_gnt: assert always ((gnt[0] && !req[0]) -> next !gnt[0])
@(posedge clk);
If you use the next[ n ] form and the left_operand holds in the current cycle, the right_operand
must hold in the n th next cycle, or the assertion fails. The n value can be 0, which means that the
right_operand must hold in the current cycle. Using next right_operand is the same as using next
[1] right_operand .
n ext_ a -- Property is True in every cycle indicated by the Range , which must be a finite
value (inf is not supported). For example, if RWreq holds in a cycle, then RcvDataWrtAck must
hold in all of the next three cycles:
ack_1_to_3_after_req: assert always (RWreq ->
ne xt_e -- Property is True in some cycle indicated by the Range , which must be a finite
value (inf is not supported). For example, if RWreq holds in a cycle, then RcvDataWrtAck must
hold at least once in the next three cycles:
ack_sometime_after_req: assert always (RWreq ->
The eventually! operator is similar to the next operator, but does not specify exactly when the
right_operand must occur. With the eventually! operator, the right_operand can occur in the
current cycle, or in any later cycle.
The following is an example of specifying temporal nondeterminism, where the IOReq signal must
be followed by an IOGrant at some indeterminate time in the future. The IOGrant can happen in the
same cycle as the IOReq, or in a future cycle.
Req_Eventually_Gnt: assert always
(IOReq -> eventually! IOGrant) @(posedge clk);
To debug stalled transactions, you can place eventually! assertions on all events for
which your design waits, and write timeout code to terminate an abnormally long simulation.
When the simulator reports unsatisfied eventually! constructs, you can use the simulator
report to determine the reason for the timeout.
For some assertions, you might want to terminate assertion checking when a specific event
occurs. To do this, use one of the abo rt operators. It is not necessary for the enabling condition to
be satisfied for the abort condition to cancel checking of the assertion.
For the sync_abort operator, the cancellation signal is sampled at the specified clock event; if
it is active, checking is terminated.
For the abort and async_abort operators, checking is terminated when the cancellation signal
becomes active. The abort and async_abort operators are identical.
Note: IUS 5.7 and previous releases implemented the abort operator as a synchronous abort.
This assertion requires d to be true (high) for four consecutive cycles after sequence {a; b} occurs.
Signals a, b, and d are all sampled at the positive edge of the clock signal, clk.
Now consider this variation of the assertion:
D4_AFTER_A_B_ABORT_E:
assert always ({a; b} |=> d[*4] abort e) @(posedge clk);
In this case, if e becomes true at any time, whether at a positive edge of clk or not, the subproperty
(d[*4] abort e) is satisfied, so the implication is satisfied.
The operator precedence rules of PSL imply that this assertion is evaluated as if it was written with
parentheses, as follows:
assert always ({a; b} |=> (d[*4] abort e)) @(posedge clk);
In this case, the abort operator applies to the sequence d[*4]. So an occurrence of e does not
terminate the parent property--the implication--or any on-going recognition of {a;b}. It does not abort
the entire property; it only aborts the right-hand side of the implication. If, in the same or next cycle,
the parent property detects the end of sequence {a;b}, the right-hand side of the implication will be
checked again.
This assertion can also be written with explicit parentheses, as follows:
assert always (({a; b} |=> d[*4]) abort e) @(posedge clk);
In this case, an occurrence of e aborts the entire implication, so any recognition of {a;b} that is in
progress when e occurs is also terminated. However, because the parent always property is not
affected by the abort condition, the assertion will start checking for {a;b} again in the next cycle.
In this case, an occurrence of e will abort the entire always property. Because it is the topmost
property in the assertion, there is no outer property that will continue to evaluate after the abort, so
the abort condition will cause the assertion to stop evaluating for the rest of the verification run.
The abort operator is shorthand for the more explicitly-named operator, async_abort. Use either
abort or async_abort when the abort condition must have an effect independent of any clock edge.
Use the sync_abort operator when the abort condition can only have an effect at a clock edge.
For more information about the abort operator, see "Using the PSL until and abort Operators".
A property evaluates to true if both Property expressions evaluate to true. The AND_OP is one of
the following:
Verilog/SystemVerilog--&&
VHDL--and
Property @ Clock_Expression
For example:
Req_To_Gnt_B_: assert always (IOReq before_ IOGrant) @clk2;
You can use scalar replicator variables only; array variables are not currently
supported. For example, the following is not supported:
// NOT SUPPORTED
// psl property P1 = forall i[1:0] in boolean : ...
use ieee.std_logic_1164.all;
architecture behave of TT is
signal a, b, c, d : std_logic;
signal e, f : boolean;
begin
-- ILLEGAL
--
--
-- LEGAL
--
For more information about using forall, see "Using forall, %for, and for/generate".
PSL Directives
Verification directives tell a simulation what to do with the PSL declarations. For simulation, the
verification directives are the following:
assert--Expresses required design behavior. The simulator will check that the design
conforms to the specified behavior.
The simulator will check that the environment conforms to the specified behavior.
For the assert directive, you can use the optional severity and report keywords to specify a
severity level and error message text to use when the property fails.
For example:
assert Clr_Mem_Write_N report "Memory failure"
severity warning ;
If you specify both the message and the severity level, the report keyword must appear first.
Assertions with a severity of note or warning do not count as errors with regard to the simulator exit status.
To prevent any PSL property from being counted as an error relative to the simulator exit
status, regardless of severity, use the Tcl assertion -logging -error off command.
report
The report keyword changes the simulation reporting. Ordinarily, as the simulation runs, assertion
results are printed in the SimVision I/O area, as shown in this example:
ncsim: *E,ASRTST (./ctr.v,55): (time 120 NS) Assertion top.ctr.memctrl2 has failed
I f you use report to specify an error message, this message replaces the has failed portion of the
output. For example, if you include report" RW was high 2 cycles in a row" with the RWcycleFail
property, the output prints as follows:
ncsim: *E,ASRTST (./ctr.v,55): (time 120 NS) Assertion top.ctr.memctrl2
The message can be a string literal, Verilog parameter, or VHDL generic or constant. For example:
parameter err_msg = "Memory failure" ;
// psl assert Clr_Mem_Write_N report err_msg ;
generic (AWIDTH : integer := 12; DWIDTH : integer := 32) ;
-- psl assert Addr_Width report "AWIDTH" ;
For more information about the content of simulation error messages, see "Understanding
Simulator Error Messages " in Assertion Checking in Simulation.
The report option can only report when a failure occurs. It cannot report when a sequence
occurs, or when a condition has been fulfilled. Use the ended() construct to report sequence
matches.
severity
he default severity is error. If you change it to failure, the simulator treats an assertion violation
T
of that property as a fatal error, and terminates the simulation.
In simulation, assume directives are treated as if they were assert directives. This means that
assumptions about the design's primary inputs, if expressed using assume directives, will be
checked during simulation, and any failure of those assumptions will be reported. This check can
help ensure that the testbench is driving the design correctly during simulation.
I n formal analysis, assume directives are used as constraints during verification of the assertions,
because they describe the required behavior of the design environment. For example:
The cover directive checks whether the design behavior ever satisfies a sequence. For example:
packet_1cyc_overlap: cover
{sopl && !eop[*]; sop && eop}
report "One cycle packet overlap occurred." ;
For the cover directive, the report message is printed only if:
The restrict directive provides a way to constrain design inputs to a specified sequence. You can
use this directive to initialize the design to a specific state before starting the assertion checks.
The restrict directive constrains the environment so that the sequence holds throughout the entire simulation trace,
as compared to assume , which constrains the environment so that the property holds in a prefix of the simulation trace.
The following example specifies that test_mode must be low for the duration of the simulation:
no_test_mode: restrict {!test_mode[*]};
and checks that the sequence holds tightly throughout the entire simulation. If the restrict
sequence stops holding, the simulator issues an assertion failure message.
Using Labels
You can use labels in embedded PSL, property files, and simulator Tcl commands.
abels share the design name space. All naming rules of the respective design languages apply to
L
label names.
It is best to give your properties meaningful names or labels, which makes it easier to
Locate and understand failed properties when you are interactively debugging your
simulation
Identify the purpose of the properties when the design is used later in another context
4
Using PSL
Note: If you use the /* */ characters, the entire assertion must be enclosed within only one set of
the characters.
VHDL--The -- characters
Note: You can also embed PSL in VHDL without having to use the pragma form; see "Using
PSL as Native Code in VHDL".
The first line of the assertion must start with psl.
Because assertions are specified as comments, they will be ignored by tools that do not support
PSL.
Both psl and the word that follows it must be on the same line.
As your assertions become more complex, you might have difficulty reading the entire construct if it
is on a single line. To write a PSL construct that spans multiple lines, write your assertions as
follows:
For temporal assertions--assertions that span multiple clock cycles--an error message will
display the line of source code that contains the term that failed. If you keep the entire assertion on
one line, instead of using multiple lines, the entire assertion will be printed when a failure occurs.
N ative PSL is placed in the declarative regions of entities, architectures, packages, block statements
and generate statements, before the begin statement. The assertion statement containing the directive is
then placed in the executable statement region. For example:
use std.textio.all;
architecture a of top is
signal wordin : bit_vector(32 downto 1);
signal wordout :bit_vector(32 downto 1);
-- PSL declarations in architecture declaration region
property prop_param(const m; const n) is always
(wordout(m)->next wordout(n));
-- Default PSL clock
default clock is falling_edge(clk);
begin
-- PSL assertion statements in architecture statement region
assert prop_param(AA, BB);;
assert eventually! {in1; in2};;
assert never {in2; in1; in2} @(clk);
end architecture;
PSL as native VHDL code uses the same general syntax as embedded pragma PSL, except without the --
psl pragma construct, and with the normal VHDL restrictions on placement. If a concurrent statement is
ambiguous, and can be interpreted either as a concurrent assertion statement or as a PSL assertion
directive, it is interpreted as a concurrent assertion statement.
N otes about using PSL as native VHDL:
An assert condition statement with no temporal operators is treated as a VHDL concurrent
assertion.
An assert condition statement followed by report string is treated as a VHDL concurrent
assertion specifying a condition that must hold at all times.
Calls to PSL built-in functions from VHDL expressions that are outside a PSL declaration, directive,
or verification unit construct are not supported.
The pragma and native forms use the same namespace. For example:
-- ILLEGAL: NATIVE AND PRAGMA USE SAME NAME
--psl sequence s1 is {x; y};
sequence s1 is {a; b; c};
The pragma and native forms can co-exist, both embedded in the VHDL code and in verification
units. For example:
-- LEGAL
--psl property p1 is always enable -> x;
property p2 is always enable -> y;
You must use the -v200X compiler option to enable native PSL.
Adding assertions when you are working in teams where the HDL author does not create the
assertions
SVA that is included in a vprop or vmode verification unit is treated as HDL code. Therefore, the
restrictions on directives in these unit types applies only to PSL, and does not apply to SVA.
The optional design_unit value is the name of the module (Verilog, SystemVerilog, SystemC),
instance (Verilog, SystemVerilog), or entity (VHDL) in which to interpret the construct.
If bound to a module or entity, the assertion applies to every instance of the module or entity.
If bound to a Verilog or SystemVerilog instance, the HDL names and operators defined in that
context can be used within the verification unit. In the following example, the
READ_N_AND_WRITE_N assertion applies to the read_n and write_n signals in the
memtest2.mctl.mem8x256.i2 instance:
vunit bus_assert(memtest2.mctl.mem8x256.i2) {
READ_N_AND_WRITE_N: assert
never (!read_n && !write_n);
}
For details about instance binding, see "Using Verification Unit Instance Binding (Verilog only)".
Note: Instance binding is not supported for VHDL and SystemC.
If a design_unit is omitted, the verification unit will be unbound. This feature lets you group
commonly-used PSL declarations so they can be inherited by other PSL verification units.
The default clock construct used in a verification unit is the same as the standard PSL default
clock construct. For more information, see "Declaring Default Clocks in PSL".
Verification units can contain PSL declarations and statements, as well as auxiliary HDL code,
including SVA.
Note: For SystemC PSL, you cannot include arbitrary HDL code in a verification unit.
For example:
vunit Interface_Assertions (counter) {
inherit bus_if;
default clock = (posedge clk);
assert_no_gnta_wo_reqa: assert never (GntA && !ReqA);
cover_fair_for_A : cover {GntB;Busy[*];Done && ReqA && ReqB};
}
Verilog users can include the `define, `ifdef, `ifndef, `else, `endif, `undef, and `include
preprocessor directives in their property files.
Note: The scope of the macros is applicable to that particular property file only.
VHDL users can include library and use clauses in a property file, if placed just before the
verification unit declaration to which they apply. Each library/use clause affects only one
verification unit--the one before which it is placed. The use clause is also allowed inside a
verification unit. For example:
-- Use std_logic_1164 from the IEEE library
library ieee;
vunit vu1 (test) {
use ieee.std_logic_1164.all;
... }
Putting a default clock construct in the verification unit can help make the code self-documenting.
The pragma form of PSL (// psl) can be used in a verification unit the same as other pragmas.
However, for clarity, it is recommended that the non-pragma form of PSL be used in a verification
unit.
The contents of any verification unit are visible to other verification units associated with the same
module, unless the verification unit is bound to a specific module instance.
The verification unit instance name in the Design Browser will be verif_unit_name . The
hierarchical name to use in Tcl commands is full_path_to_instance . verif_unit_name .
You cannot reference a PSL object defined in a module from a verification unit that is bound to an
instance of that module. Instead, define the PSL objects in a package that is then referenced by both
the module and the verification unit.
Classes that are defined in a module are not visible to instances within that module. So class
objects cannot be referenced in a verification unit that is bound to an instance of that module. To
reference a class object from a verification unit, define that class in a package that is globally visible.
Class members of the associated module can be accessed, but they cannot be modified.
Multidimensional nets, or parts of a multidimensional net, that are declared in a module cannot be
referenced in a verification unit that is bound to an instance. Use a reg instead of a net.
If your PSL property file contains a verification unit that binds to an instance, you must specify the
property file when you compile the topmost module referenced by that instance. This permits the
compiler to locate the instance specified in the binding. For example, if a verification unit in prop.psl
binds to instance top.ex1:
ncvlog -propfile prop.psl top.v
Support files for instance binding are created in the worklib /.cdssvbind directory for three-step
mode and ./INCA_libs/.cdssvbind for irun.
vunit dut_psl(dut) {
owever, a generate scope within the dut module references property A2 before it is declared. This
H
reference causes an error, because properties referenced in a generate scope must be declared before
the generate:
input counter;
...
generate
if (1) begin: assert_gen
wire c;
wire d;
endmodule
To prevent this error, you can include the generate block in the verification unit:
vunit dut_psl(dut) {
generate
if (1) begin: assert_gen2
...
// psl assert (A2);
end
endgenerate
PSL Macros
You can use PSL macro processing to define properties in a Verilog verification unit. For the Cadence
implementation, the Verilog flavor supports the PSL %for and %if macros, which you can use to
conditionally or iteratively generate PSL statements.
You do not need to use the comment form (// psl) for these macros. When you include the -assert or -
propfile compiler option, the macros are recognized as PSL.
You can use any valid Verilog or SystemVerilog code within the macros.
Although Cadence has implemented extensions to support PSL declarations and directives
embedded in the design, it has not implemented extensions to support the %for and %if macros.
These macros can be used only in verification units.
The Incisive simulator first processes Verilog compiler directives--`define, `ifdef, `else, `include, and
`undef--then %if and %for.
For more information about these macros, see "The %for Construct (Verilog)" and "The %if Construct
(Verilog)".
The %for Construct (Verilog)
The %for construct replicates code a specified number of times. Each replication is made unique by
parameter substitution.
var --The replicator variable name; any legal PSL identifier name. It must be a unique name, with the
exception that it can be the same as another non-enclosing PSL replicator variable. The value of the
replicator variable must be statically computable.
expr1 , expr2 --Replication expressions; statically computed expressions that result in a legal PSL
range.
item --Replication item; any legal PSL alphanumeric string or previously defined preprocessor-style
macro. Items are separated by commas, and must be enclosed in curly braces.
For the first form of the construct, the code between %for and %end will be replicated expr2 - expr1 +1
times, assuming that expr2 is greater than or equal to expr1 .
For the second form of the construct, the code will be replicated according to the number of items in the
list. During each replication of the code, the loop variable value is substituted into the code. For example,
for a loop variable called i, you can access the current value of the loop variable from the loop body using
one of these methods:
If i is a separate token in the code, access its value by using i:
%for i in 0 .. 3 do
define aa(i) := i > 2;
%end
%for i in 1 .. 4 do
define aa%{i-1} := %{i-1} > 2;
%end
= * -
< != /
<= > %
+ >=
For more information about using the %for construct, see "Using forall, %for, and for/generate".
The %if construct generates the enclosed code if the condition specified in the expr is true.
This macro is similar to the #if preprocessor directive, except that it can be made conditional on variables
defined in an enclosing %for construct.
Another method of including IAL in a verification unit is to place the IAL components within a module in a
monitor file. For example:
endmodule
You can then instantiate the monitor module in the verification unit:
vunit Qtest (Queue)
{
// Instantiate IAL monitor
Qcheck QChk(qClk, reset, qInsert, qRemove, qFull, qEmpty);
}
For more information about using IAL components, see "The IAL Use Model" in "Assertion-Based
Verification Using the IAL ," in the Incisive Assertion Library Reference.
An SVA bind directive--You can bind PSL to the design by referencing it in an SVA bind directive.
For details about putting SVA in a PSL verification unit, and for a comparison of the advantages and
disadvantages of bind and verification unit techniques, see "Using SVA in a PSL Verilog Verification
Unit".
where sequence1 extends over more than one clock cycle. However, this syntax probably does not
describe a useful property of a design.
Many people, when they write a property of this form, assume that PSL will interpret it as an infinite
number of copies of the sequence concatenated together. They assume that the tool will look for {
sequence1 ; sequence1 ; sequence1 ; }.
The PSL language says that always { sequence1 } implies that the sequence has to hold at every clock
in the simulation. However, instead of concatenating copies of the sequence to be checked one after
another, the simulator creates a new copy of the sequence at every clock and begins a new check, which
produces overlapping assertion traces.
For example, you might want a property to ensure that the clock has a regular waveform. You might try
using the following assertion:
assert always { clk; !clk };
PSL does not concatenate this sequence into an infinite series of { clk; !clk; clk; !clk; }. Instead, it
starts a new copy of the sequence with each cycle in the design:
Cycle # 1 2 3 4
In cycle 1 of simulation or formal analysis, if the clock is high, the property passes. But in cycle 2, the first
copy of the sequence says that the clock must be low, while the second copy of the sequence says that
the clock must be high. No matter what the actual state of the clock, one of those properties is guaranteed
to fail.
function undriven(vec:std_logic_vector)
return boolean is
begin
for i in vec`range loop
if vec(i) = 'Z' then
return true;
end if;
end loop;
return false;
end;
Note: This simple assertion is portable to Verilog/SystemVerilog and VHDL. Assertions with
expressions within the SystemC literal inclusion function, _( SystemC/ C++_expressions ), are not
portable. See "SystemC Expressions in PSL".
Although syntactically correct, this approach is not recommended. With this construct, the simulator will
create nested loops for checking the assertion: one loop for the always construct and, for each cycle in
which a is true, a nested loop for the never construct to check that b is not true. Because this property
creates multiple parallel traces, it can significantly affect simulation performance.
To correct the problem in the previous example, use the following property instead:
good: assert always a -> next (( never b ) until_ a);
This property creates loops like the previous version, but the nested loop for this version checks that b is
not true only until a is true again. This reduces the large number of simultaneous traces.
This property will check that signals a and b are not both high. However, this property will be evaluated
only during the initial simulation cycle. The property will not be checked during the rest of simulation.
However, it might be useful for checking initial conditions in a simulation.
Assertion libraries often use these one-time checks to validate the parameters that must be defined
when the module is instantiated.
Similarly, the grammar description shows that properties can be started with the next or eventually!
keywords. For example:
not_a_and_b: assert next !( a && b ) ;
This property will check that signals a and b are not both high. This property will be evaluated only on the
first simulation cycle after initialization. The property will not be checked during the rest of simulation.
However, it might be useful for checking conditions right after initialization.
This property will check that signals a and b are not both high:
If the condition does not occur, an assertion error will be recorded at the end of simulation.
You might use this property to watch for an event that must happen at least once during simulation.
However, it will not check for any events after the first event.
Because of PSL operator precedence, the parser interprets the assertion as if it was written with the
following parentheses:
assert never ( bar abort(rst) );
he term bar abort(rst) is a PSL property. PSL allows only a Boolean or a sequence as the operand of
T
the never operator, not a property. Adding parentheses still does not result in the desired behavior:
When rst is true, the never bar term is aborted, which cancels all future checking of the bar signal. When
rst is deasserted, checking of the never bar term is not resumed.
One way to encode an abort term into a never property is to make the term part of the never property:
assert never (bar && !rst);
However, there is a difference if the left operand is a multi-cycle property. For example:
property f = ( {a} |=> {b;c;d} )
property f_until_e = (f until e)
property f_abort_e = (f abort e)
The table that follows shows the behavior on signals a, b, c, d, and e.
N indicates that the assertion trace will fail at some future time with an error message
Note: The f property, as written, will start a new trace of the assertion at every cycle where a is true.
Cycle: 1 2 3 4 5 6 7
a 1 1 1 1 0 0 0
b - 1 1 1 1 0 0
c - - 1 1 1 1 0
d - - - 1 1 1 1
e 0 0 0 0 0 0 0
f Y Y Y Y . . .
f_until_e Y Y Y Y . . .
f_abort_e Y Y Y Y . . .
For these values, f holds in cycles 1, 2, 3, and 4 because, in each of these cycles, the {a} condition
occurs, followed in the next three cycles by {b;c;d}. Because f holds in those cycles, f_until_e and
f_abort_e also hold in those cycles.
In the following case, f holds in cycles 1 and 2 as before, but it does not hold in cycles 3 and 4, because
the {a;b;c;d} sequence does not complete in cycles 6 and 7. Again, f_until_e and f_abort_e hold in the
same cycles in which f holds.
Cycle: 1 2 3 4 5 6 7
a 1 1 1 1 0 0 0
b - 1 1 1 1 0 0
c - - 1 1 1 0 0
d - - - 1 1 0 0
e 0 0 0 0 0 0 0
f Y Y N N . . .
f_until_e Y Y N N . . .
f_abort_e Y Y N N . . .
The following case shows the difference between abort and until when e goes high:
Cycle: 1 2 3 4 5 6 7
a 1 1 1 1 0 0 0
b - 1 1 1 1 0 0
c - - 1 1 1 0 0
d - - - 1 1 0 0
e 0 0 0 0 1 0 0
f Y Y N N . . .
f_until_e Y Y N N Y Y Y
f_abort_e Y Y Y Y Y Y Y
Here, signal e goes high in cycle 5. This removes the obligation for f to hold after cycle 5. However, the
requirements for f_until_e and f_abort_e are different:
For f_until_e, the occurrence of e removes the obligation for any new occurrences of {a} to be
followed by {b;c;d}. The {a}s that have already occurred must still be followed by {b;c;d}. That is,
it obligates any "in-flight" behavior to complete.
For f_abort_e, the occurrence of e removes the obligation for all "in-flight" behavior to complete, so
the traces that started in cycles 3 and 4 are not required to complete in cycles 6 and 7. Therefore,
f_abort_e holds in cycles 3 and 4 as well.
That is, as long as they have arrived before the kitchen closes, the diners will complete their meals.
In contrast, to describe the behavior of diners in the event that the restaurant catches fire, the assertion is
({arrive,seated,order} |=> {salad,dinner,dessert}) abort fire;
That is, regardless of what stage they are in, diners will abandon their meals if a fire breaks out.
These conditions can be combined, as follows:
property normal_dinner = {arrive,seated,order} |=> {salad,dinner,dessert};
The forall, %for, and for/generate constructs are similar. The following are the advantages and
disadvantages of each:
forall generates one assertion for all values. For example:
// psl check_init: assert
// forall i in {0,1,2} : always (!fifo[i]) @(rose(rstn));
The advantage of using forall is that there is only one assertion to track and monitor. The disadvantage is
that it is more difficult to debug, because more analysis is needed to understand which case failed.
Note: In IFV, forall acts like for/generate, except that a new scope is not created.
The for/generate construct creates a new scope for each of these assertions. For this example, the
assertion name, check_init, becomes part of the hierarchical path that you specify in Tcl commands. The
default clock from the parent scope applies to this scope.
The advantage of using for/generate is that all of the assertions can have the same name. The
disadvantage is that coverage reports, which list results by scope, can be lengthy.
The advantage of using %for is that it can be used to distinguish the assertion names while keeping them
all in one scope, because the index variable is a preprocessor step. The disadvantage is that the %for
construct can be used only in a verification unit.
The following table compares forall, for/generate, and %for.
The restrict directive is treated differently when the rightmost sequence is open-ended. A single
restrict can--if it is open-ended--cover the whole simulation. For example:
is satisfied and finishes after four cycles, because the trailing !rst[*] has no effect, as for the right-hand
imposes a constraint on the entire simulation that rst must stay low.
As shown in this example, many overlapping assertions have resulted. A large number of overlaps can
result in performance degradation.
failures.
Synthesis pragmas use the PSL default clock. If you define the default clock to be rose(clk),
assertions created from synthesis pragmas will not fire at time 0.
// psl P1: assert always (in1 -> next in2 -> next !in1);
had the following meaning, because next had a lower precedence relative to ->.
// psl P1: assert always ((in1 -> next (in2 -> next !in1)));
However, with the introduction of PSL1.1, next has a higher precedence relative to ->:
// psl P1: assert always (in1 -> (next in2) -> (next !in1));
Because the left-hand-side of the -> operator must be Boolean, the new precedence rules cause a fatal
BOOLOP error message when the parentheses are missing.
For more information about PSL operator precedence, see Operators precedence table.
For more information, see the description of the ended() construct in this manual, and section 5.2.3.6 in
the PSL IEEE 1850 standard.
vunit test_triggers(top.TX_Monitor) {
reg gframe = 0;
enum (DA, SA, Length, Payload, CRC, Err) state;
sequence good_frame_transmitted = {
state==DA[*12]; state==SA[*12]; state==Length[*2];
state==Payload[*min:max]; state==CRC[*8]; state!=Err};
For more information about using the ended() function, see "Using PSL ended() in HDL".
The test is defined to react to changes on that signal using the full hierarchical path. When a change
occurs, the code in the send_another() method is executed, which adds another randomized packet to the
processing and response checker queues.
The Cadence Incisive Enterprise Simulator-XL also provides SystemC classes that permit access
to PSL and SVA assertions for reactive tests. For details, see "Access to Assertions from SystemC
Testbench" in " Using SystemC PSL ," of the SystemC Simulation Reference.
A default clock in a generate scope affects directives only within that generate scope. If there is no default
clock in the generate scope, a default clock in the design unit scope applies, if it exists.
Some restrictions on VHDL output types have been relaxed in the latest version of the VHDL standard. To
prevent the WSSNEX error, you can compile with the -v200x option to the ncvhdl compiler, which uses this
newer set of rules.
Another way that ended() can be used in HDL, which is not recommended, is as an event control. For
example:
always @(ended({a;b}, posedge clk ) )
$display ("Sequence a;b detected at %t", $time);
This code will execute twice each time the sequence a;b is detected--once when the Boolean return value
is asserted, and once when the Boolean return value is deasserted. The Boolean return value is active for
one clock interval so, for Verilog level-sensitive event controls, the statements are executed on any
change. Although you might have intended the statement to execute once, when the sequence ends, it
will always execute twice.
nother type of unexpected behavior can result if the sequence ends multiple times on consecutive clock
A
cycles. You might have intended for the statement to be executed each time a sequence match is true, but
it will only be executed twice.
When considering the use of ended():
To avoid race conditions, always specify a clock for ended() that is different from that of the property
or HDL code.
R emember that when ended() is used as a Verilog event control, execution occurs when the result
of the ended() evaluation changes value--both when it becomes true and when it becomes false.
During simulation, if ctrl gets any value other than 0, 1, or 2, the assertion fires. Although this case
statement does not have 2'b11 as one of its options, it can still comply with the full-case check if 2'b11 was
never exercised during simulation.
one_hot
The PSL assertion generated for the one_hot pragma checks whether the associated bus to the
pragma is one-hot encoded. One-hot encoding specifies that only one of the bits of the bus can have
a 1 value at any given time. For example, a four-bit bus with one-hot encoding can only have a value
of 0001, 0010, 0100, or 1000.
one_cold
The PSL assertion generated for the one_cold pragma checks whether the associated bus to the
pragma is one-cold encoded. One-cold encoding specifies that only one of the bits of the bus can
have a 0 value at any given time. For example, a four-bit bus with one-cold encoding can only have
a value of 0111,1011, 1101, or 1110.
parallel_case
The PSL assertion generated for a parallel_case pragma ensures that two or more choices of a
caseX or caseZ statement are not selected at the same time. The assertion fires if more than one
choice is activated during simulation.
All of these examples will report a BNDWRN warning, "bit-select or part-select index out of declared
bounds," because
A1 and A3--The formal argument type is reg [3:0], and the actual argument type is reg [3:0], but
always (a[4]) specifies a bit-select out of the [3:0] range.
A2 and A4--The formal argument type is reg [3:0], but the actual argument type, reg [4:1], is
different.
5
Writing SystemVerilog Assertions
The SystemVerilog assertion language, SVA, lets you specify assertions for SystemVerilog
designs.
For more information about SystemVerilog assertions, see
IEEE 1800 Standard for SystemVerilog Unified Hardware Design, Specification and
Verification Language.
For more information about the Cadence implementation of SystemVerilog, see
Cadence SystemVerilog Reference
he following examples define several styles of immediate assertions inside always blocks.
T
Comments in the code describe each style.
if(!enable_n)
Simulation stops and the message goes to the log file when the randomization is not successful.
The assertion -redirect command does not work for immediate assertions.
In accordance with the IEEE 1800 SystemVerilog standard, vpi_control does not apply to
immediate assertions. Only system-level VPI commands apply.
A deferred assertion is used to suppress the errors that occur due to glitching activity on
combinational inputs to immediate assertions. A deferred immediate assertion is similar to simple
immediate assertion with the following key differences:
A #0 delay is specified after the assertion directive
always@(clk)
begin
x=foo();
a1: assert #0 (x>0) $display("a1 passed");
else $error("a1 failed as x=%d",x);
end
If the action block contains a pass or a fail statement, then each of the statements can contain only
one subroutine call, which can be a task, a task method, a void function, a void function method, or
a system task. In this case, begin-end statements cannot surround the pass or fail statements as
begin is not a subroutine call.
In an action block, a subroutine argument can be passed either by value or by reference as a ref
and a const ref. If an argument is passed by value, the expressions use the values of the underlying
variables when the deferred assertion expression was evaluated. However, if the argument is
passed by reference, expressions use the current values of the underlying variables in the Reactive
region. Further, it is not allowed to pass automatic or dynamic variables as actual to a ref or a const
ref formal.
Note: As a limitation in a subroutine call in an action block, saved values are not used when
actuals are out of scope or wires.
Reporting in a Deferred Assertion
In a deferred assertion, though the deferred assertion's expression is evaluated when the deferred
assertion statement is processed but the reporting or action blocks are scheduled in the Reactive
region in the current time step.
The action block subroutine call and the current values of its input arguments are placed in a
deferred assertion reporting queue with the currently executing process. When a deferred assertion
flush point is reached, the deferred assertion reporting queue is cleared and any pending assertion
reports are not executed. After a queue reaches the deferred assertion flush point, each pending
report that is in the Observed region of each simulation time step and has not been flushed either
matures or is confirmed for reporting. The associated subroutine call in the pending report is
executed in the Reactive region and finally, the report is cleared from the specific deferred assertion
report queue. Remember that any report that matures cannot be flushed.
In case a deferred assertion expression is evaluated in the Observed region, the deferred assertion
matures immediately. For example:
wait (S.triggered);//Here, S is a sequence.
A1: assert #0 (expr);
In the given example, S.triggered stands true only in the Observed region. Therefore, the deferred
assertion A1 will hit only the Observed region and will definitely report.
Note: At times, code in the Reactive region may modify a signal and lead to another pass to the
Active region. In this case, the Active region may re-execute some of the deferred assertions with
different reported results and may lead to glitching behavior. Though deferred assertions prevent
glitches due to order of procedural execution but do not prevent glitches caused by execution loops
between regions due to the assignments from the Reactive region.
Deferred Assertion Flush Point
A deferred assertion flush point is reached when:
A process that was earlier suspended resumes execution on reaching an event control or wait
statement.
A process that was declared by an always_comb or always_latch resumes execution due to a
transition on one of its dependent signals.
The outermost scope of the process is disabled by a disable statement. However, when you
disable a task or a non-outermost scope of a procedure any pending reports are not flushed.
Note: In IES, the flushing of deferred assertions in case the outermost scope of the process is
disabled by a disable statement is not supported and the results are reported.
When you specify the deferred assertion outside the procedural code as a module_common_item, it
is treated as if it is in an always_comb procedure. For example:
module m (input a, b);
a1: assert #0 (a == b);
endmodule
is equivalent to:
always_comb
begin:b1
foo(a);
end
always_comb
begin:b2
foo(b);
end
In the given example, if the function foo is called from processes b1 and b2 at the same time step,
then the execution of assertion a1 through process b1 will never flush the reporting of assertion
through process b2, and vice versa.
Concurrent assertions can describe Boolean behaviors or patterns of behavior that span clock
cycles. They can also specify assumptions about the environment, or monitor behavior for
functional coverage. Concurrent assertions are distinguished by the property and sequence
keywords; for example, assert property.
block, or program. You can also place a concurrent assertion in simple initial and always blocks.
Assertions in initial blocks are evaluated only once ("Embedding Concurrent Assertions in
Procedural Code").
The following example defines a property, P1, which checks that if a is true, and b is true two clock
cycles later, then c must be true one clock cycle after that. The concurrent assertion, A1, causes this
property to be checked during simulation or formal analysis.
property P1;
@(negedge clk) (a ##2 b) |=> (c);
endproperty
You can only use static class members in concurrent assertions. You cannot use a member
variable unless the variable is initialized at time 0. For example, you cannot define a clock as
a member of a class, then use it to clock a property. Doing so results in a run-time error.
Labels in SVA
identifier:
label gives a name to an assertion, assumption, or coverage statement. You can use a label in
A
other properties and in simulator Tcl commands to refer to the assertion, assumption, or coverage
statement.
Labels are optional, but strongly recommended. The label you provide is the name that will be
associated with this assertion in assertion and coverage analysis reports, and in the Assertion
Browser and coverage GUI. They can make it easier to locate and understand failed properties
when debugging your simulation.
If you do not provide a label, the tool generates one.
he identifier must be a legal Verilog or SystemVerilog name, and it must be unique within the
T
design name space.
This example defines an assertion labeled a_or_b_then_not_c:
A Boolean expression describes a behavior that might be true during a single clock cycle. It can be
any SystemVerilog expression that evaluates to 0, 1, X, or Z. The value 1 is interpreted as true; the
values 0, X, and Z are interpreted as false.
// Sequence
sequence S1 (term2, term3);
(a ##1 term2 ##1 term3);
endsequence
When an argument follows a set of arguments with a specific data type, it takes up the data type of
the preceeding set of arguments. For example, Property P5 shows a set of arguments in which the
argument AA is untyped, the argument BB that is of the type bit, the argument CC takes up the bit
data type, and DD is specified as untyped.
property P5 (AA, bit BB, CC, untyped DD);
@(negedge clk)
(BB ##1 CC) |=> (AA ##[1:2] (DD||AA));
endproperty
When using typed formal arguments, all arguments can be initialized and all integral types are
automatically truncated or sign/zero-extended for width mismatches before type checking.
IES supports sequence, property and event data types in typed formal argument. Declaraing a data
type as a sequence or property restricts the actual argument to a sequence or property instance or
expression. For example:
Property P5( sequence S, property P)
@(posegde clk)
S or P;
Endproperty
In the given example, the actual arguments S and P are restricted to a sequence or property.
Actual Arguments
When you instantiate a sequence or property, the argument list can be either name-associated or
positional. For example, P5 can be instantiated in either of the following ways:
positional_association: assert property (P5 (my_AA, my_BB));
named_association: assert property (P5 (.AA(my_AA), .BB(my_BB)));
efaults for SVA formal arguments are also supported. In the following example, when P6 is
D
instantiated, en takes the default value of 1. Arguments with a default value do not have to be
specified in the instance. The positional_association1 assertion relies on the default value of EN,
while positional_association2 relies on the default value of BB:
parameter true = 1;
property P6 (bit AA, BB=`true, EN=1);
@(negedge clk)
EN |-> (BB ##1 c) |=> (AA ##[1:2] (d||AA));
endproperty
named_association: assert property (P6(.AA(my_AA),.BB(my_BB)));
positional_association1: assert property (P6(my_AA, my_BB));
positional_association2: assert property (P6(my_AA, ,1));
You can also declare defaults for SVA formal arguments. In the following example, when BusReq is
instantiated, both min and max take the default value of 0:
Clocking in SVA
@(identifier | event_expression)
A clock expression specifies the clock or event that controls the evaluation of a sequence or
property. The values are sampled as follows:
identifier --On both edges of the expression for level expressions
If a clock expression specifies @(negedge clk), for example, the values in the assertions are
sampled when the clk signal transitions to low.
For example:
property P0;
@(posedge clk)
(a ##1 b ##1 c) |=> (!a ##[0:2] !b);
endproperty
Note: You cannot use the $rose and $fell sampled-value functions as clock expressions.
default clocking block specifies the clock or event that controls the evaluation of sequences or
A
properties within the block. For example:
default clocking master_clk @(posedge clk);
property p4; (a |=> ##2 b); endproperty
assert property (p4);
endclocking : master_clk
The clocking_event can be a clock event expression or a clk_identifier that was defined by
using a previous clocking/end clocking block. For example:
The clocking_items can be properties, sequences, and assertions. You cannot use hierarchical
names to refer to properties in clocking blocks.
Note: In the Cadence implementation, assertion statements are permitted in clocking blocks.
However, assertions in clocking blocks are not permitted by the IEEE 1800 standard.
Notes about default clocking blocks:
A contextually-inferred clocking event ("Embedding Concurrent Assertions in Procedural
Code") in a procedural block takes precedence over a default clock.
The default clock applies only when there is no explicit or inferred clock. An explicitly
specified leading clocking event takes precedence over a default clock.
block must be singly-clocked, and its clocking event must be identical to that of the clocking
block.
General clocking blocks are not supported for SVA; only the default clock is supported.
Clocking blocks and default clocking cannot be specified in a generate block.
If no clocking event is specified in a procedural concurrent assertion, the leading clocking event of
the assertion shall be inferred from the procedural context, if possible. If no clock can be inferred
from the procedural context, then the clocks are inferred from the default clocking, as if the assertion
were instantiated immediately before the procedure.
A clock is inferred for the context of an always or initial procedure that satisfies the following
requirements:
1. There is no blocking timing control in the procedure.
2. There is exactly one event control in the procedure.
3. Within the event control of the procedure, there is exactly one event expression that satisfies
both of the following conditions:
The event expression is of the form edge identifier expression1 [ iff expression2 ] and is not a
proper subexpression of an event expression of this form.
No term in expression1 appears anywhere else in the body of the procedure.
2. Here the leading clock for assertion will be "negedge clk", as procedural clock 'clk' does not have
any edge identifier.
default clocking def_clk @ (negedge clk);
endclocking
always @(clk)
A1: assert property ( a ##1 b);
always @(clk)
A1: assert property ( a ##1 b);
Flushing in fork/join
assert property (@(posedge clk1) (a ##1 b) |=> @(posedge clk2) (c ##1 d));
For if/else operations, the if and else clause properties must begin on the same clock as the
test of the if Boolean condition. (This support is as per 2005 LRM - and not as per 2009 LRM).
Empty match is not handled correctly in multiclock properties. For example, the given code is
not handled correctly:
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1[*0:1];
The clocking events of sequence and property definitions do not flow out of the definitions.
assertion_variable_declaration::= var_data_type
list_of_variable_decl_assignments
The var_data_type is the data type of the local variable. This data type can be one of the
supported data types allowed within assertions.
Note: The data supported as local variables include bit, byte, int, integer, logic, longint,
reg, shortint, time, Packed struct, class, signed and unsigned variants of these types, reg,
logic, and bit vectors, and arrays of supported types.
You can initialize local variables in sequence and property declarations (Section 16.10 of system
verilog LRM, IEEE 1800-2009). You can use local variable with input mode in argument list of
parameterized sequence and properties. The following example illustrates the initialization of a
local variable with input mode:
property P2 (local input int arg1 = 4 + P, local input int arg2 = 0);
(a ##2 b) |=> (arg1 != 0) && (arg1 != arg2);
endproperty
You can specify local variables in a sequence or property expression that will be executed when its
associated sequence is matched. Local variables can be assigned multiple times within a
sequence. Local variables can be used within a check that spans an arbitrary interval of time, and
that overlaps with other checks. These variables are used primarily to check data, especially when
the latency is variable and out of order.
As shown in the following example, when valid_in is true, the x variable is assigned the value of
data_in. If data_out is equal to x + 1 five cycles later, the property is true. Otherwise, the property is
false. When valid_in is false, this property evaluates vacuously to true.
property pipeline;
int x;
@(posedge clk) disable iff (reset)
(valid_in, x = data_in) |=> ##5 (data_out == (x+1));
endproperty
The following example shows the use of a packed struct as a local variable:
// Pipeline data check
typedef struct packed signed {reg[7:0] x, y;} data_struct;
property ex1;
data_struct ldata;
@(posedge clk)
(valid_in, ldata.x=data_in) |-> ##5 (data_out == ldata.x);
endproperty
Are dynamically created for every attempt to match the specified behavior, so copies of the
variable are continually being created and destroyed.
Because local variable values are so volatile, you cannot access these values with Tcl
commands. Attempts to do so will produce an "object not found" message.
Do not show up in the Design Browser, because they are dynamically created.
Local variables cannot be used in sampled value functions and system tasks such as $past.
You cannot export the values of local variables through typed formal arguments.
The following data types are not currently supported as local variables:
enum
Non-integer types: shortreal, real, realtime
string
Tagged union
Unpacked struct
being executed only when the property or sequence passes or fails. You can use this feature to get
more visibility into the inner workings of a sequential expression. For example:
sequence s1;
logic v, w;
(a, v=e) ##1 (b[->1], w=f,
$display("b after a with v= %h, w = %h\n", v, w));
endsequence
For details about this feature, see section 16.8, "Manipulating data in a sequence," and section
16.9, "Calling subroutines on match of a sequence," in the 1800 - 2009 IEEE Standard for
SystemVerilog.
SVA Sequences
A sequence describes a behavior that can span time. It is made up of sequence expressions
separated by time delays. The simplest type of sequence expression is a single Boolean
expression. However, sequence expressions can be more complex, including the use of repetition
operators and sequence instantiation.
A sequence can be declared in a module, interface, program block, clocking block, compilation unit
scope, or package.
Sequences can be evaluated over several clock cycles. If each sequence expression evaluates to
true in successive clock cycles, the entire sequence is said to be tightly satisfied.
Because they can span clock cycles, sequences have an endpoint--the clock cycle in which the
last sequence expression is satisfied. For example, suppose you defined a sequence, which states
At the negative edge of clk , if a is true, then b must be true in the next clock cycle, and c must be
true in the cycle after that.
he sequence ends in the last cycle of a series of cycles that tightly satisfy the sequence, as
T
follows:
The Incisive simulator uses "weak" semantics when evaluating SVA sequences. If the
enabling condition of a sequential assertion has been satisfied, but it is incomplete at the
end of simulation, the Incisive simulator does not report it as a failure.
Starting with 13.2 release, the default assertion evaluation semantics is weak for SVA assertions.
The default value of assert_report_incompletes is set to "0". Use assert_report_incompletes 1
to get strong semantics.
For details, see the description of the Failed state in "Understanding Assertion States" in Assertion
Checking in Simulation user guide.
sequenceidentifier [ argument_list ] ;
[] [ clock_expression] sequence_expression
[ sequence_opsequence_expression ] ... ;
endsequence [ :identifier ]
Clocking in SVA
identifier [ ( actual_arguments ) ]
You instantiate a sequence by using its name in an expression. If the sequence declaration has
formal arguments, you specify the actual argument values when you instantiate the sequence. The
actual argument list can be either name-associated or positional.
In the following example, the ReadTransaction sequence contains an instance of the BusReq
sequence, and passes the actual arguments, rq and ak, to the sequence:
sequence BusReq (req, ack);
req ##[1:3] ack;
endsequence
sequence ReadTransaction ;
BusReq(rq, ak) ##1 Transfer ##1 BusRls ;
endsequence
A sequence expression is made up of Boolean expressions and instances of other sequences. All
expressions in a sequence expression are evaluated on the clock edge of the property in which the
sequence is instantiated. You place time delays between sequence expressions to describe
behaviors that span clock cycles.
The delay value in a sequence expression can be any of the following:
##identifier Specifies any named object that has a fixed integer value
greater than or equal to 0 at simulation time.
Note: The delay value can be an untyped formal argument. When passed as a delay, the value
must be a compile-time constant. It cannot be an HDL variable value, or any expression using an
HDL variable.
In the following example, assume the sequence is instantiated in a property that is clocked on the
negative edge of clk. The sequence is satisfied when a holds, then b holds in the next clock cycle,
and c holds in the clock cycle after that.
a ##1 b ##1 c;
The next example also assumes that the sequence is instantiated in a property that is clocked on
the negative edge of clk. In this sequence, c must hold in any clock cycle from the first through the
fourth cycle after b holds, matching any of the possible waveforms shown for c.
b ##[1:4] c;
This example uses the identifier max to specify the number of clock cycles after c holds that d must
hold:
c ##(max) d;
This example defines a sequence, S1, that takes two arguments. S1 specifies that after the first
argument occurs, the second argument must occur from zero to two clock cycles later. The
sequence S2 instantiates S1 and passes the arguments b and a to S1.
sequence S1(AA, BB);
(AA ##[0:2] BB);
endsequence
sequence S2;
S1(b,a);
endsequence
SVA Repetition
R epetition operators define a sequence in which the operand occurs repeatedly. For example:
req[*3]
Similarly:
( clk ##1 !clk )[*3]
is equivalent to
( ( clk ##1 !clk ) ##1 ( clk ##1 !clk ) ##1 ( clk ##1 !clk ) )
which is equivalent to
( clk ##1 !clk ##1 clk ##1 !clk ##1 clk ##1 !clk )
When used as a formal argument, the repetition value must be untyped. Repetition values must be
compile-time constants.
There are three classes of repetition operators:
Consecutive repetition operator: [*n] and [+]
These operators apply to either a Boolean or a sequence. The resulting sequence matches
any trace in which the operand occurs for a specified number or range of consecutive cycles.
You can also use [*] for [0:$], and [+] for [1:$].
the cycles in which the Boolean does occur, but not following the cycle of the last occurrence
of the Boolean.
R [* n ] B [= n ] B [-> n ]
R [* n : m ] B [= n : m ] B [-> n : m ]
For example:
a[*3] matches the trace (a, a, a)
If the repeat count is a range, the resulting sequence matches any trace in which the operand is
repeated some number of times in that range. If the upper bound in such a range is $, the upper end
of the range is unbounded--that is, the resulting sequence will match any number of repetitions
equal to or greater than the lower bound of the range.
The upper limit for a repeat count is about 64K. Using very large repeat values, such as
ack[*20000000], uses a large amount of memory, but unbounded repeat values, such as
ack[*], do not.
A repeated sequence might or might not match a trace, depending on how it is clocked. A sequence
can be clocked by an explicit clock expression, or by inheriting a clock context. A clocked sequence
is evaluated only when its clock expression is True. For example, given the following traces,
sequence @(clk) a[*3] matches twice, but sequence @(posedge clk) a[*3] does not match:
A given sequence can match overlapping portions of the same trace. For example, given the
following traces:
Assertions are intended to monitor the HDL, not change the values of signals. The
increment and decrement operators are not allowed in SystemVerilog properties.
Specifies that two sequence expressions must begin in the same clock cycle, but they do not need
to end during the same cycle.
In the following example, the first sequence spans more time than the second sequence. The
match starts when a and c are true, assuming that the sequence is evaluated on the positive edge of
the clock. It ends when the second sequence completes; that is, when e holds.
Specifies that both sequences must end in the same clock cycle.
In this example, the match begins when a and c are true and ends when both b and e are true:
SVA or Operator
sequence_expression1 or sequence_expression2
Specifies that either the first or the second sequence expression must match, or both.
For example, this sequence matches if b holds, followed by c in the next clock cycle; or if d holds for
one or two cycles, followed by e in the next cycle; or if f holds for two cycles. Any of these
occurrences match the compound sequence:
(b ##1 c) or (d[*1:2] ##1 e) or f[*2]
Specifies that a condition must hold for the duration of a sequence expression.
For example, this expression ensures that an interrupt, irq, does not become true during the
specified sequence.:
Note: In IES, in addition to boolean expression, Sequence Match Item (SMI) on boolean expression
is also supported as the first operand of the "throughout" operator.
Specifies that the evaluation of a sequence stops when the first match of the sequence expression
is found. If more than one sequence expression matches at that time, they are both first matches.
When the sequence expression is matched, the sequence match item is executed. This optional
match item can be used to assign values to local variables or execute a $display statement. For
example:
property P6;
reg AA;
@(negedge clk)
first_match(seq1, AA = 0);
endproperty
If you use first_match in the enable condition of a property, it limits the instantiation of overlapping
properties. If you use first_match in the fulfilling condition of a property, it has no effect, because
the first match of a sequence is implicit in this context.
I n this example, for the sequence evaluation beginning at time 1, only the match that ends at time 2
is used; matches ending at time 3 and beyond are ignored:
first_match(a ##[1:3] !b);
sequence_instance.method
Because sequence method values are not available in the Preponed region, you cannot use
sequence methods in sampled-value functions.
The following table compares the three available sequence methods.
sequence_instance.ended
The ended method evaluates to true in a given clock tick if the sequence has reached its endpoint,
and false otherwise. The ended status of a sequence is set in the Observed region, and persists
throughout the Observed region.
The ended method can be used only to detect the endpoint of a sequence that is used in another
sequence. It cannot be used in disable iff Boolean expressions for properties. Also, an error is
reported when the use of ended causes circular dependencies between sequences. You cannot use
this method in a sampled value function, because the sequence values are not available in the
Preponed region.
An example of using the ended method is the following:
Evaluation
When the ended method is evaluated in an expression, it tests whether its operand sequence has
reached its endpoint at that particular clock tick. The ended method tests only for the endpoint of a
sequence, not its starting point. In the following example, the endpoint of the BusReq sequence,
when used in the ReadTransaction sequence, must occur one clock tick after Enable.
sequence BusReq;
@(posedge clk) req ##[1:3] ack;
endsequence
sequence ReadTransaction;
@(posedge clk) Enable ##1 BusReq.ended ##1 Transfer ##1 BusRls;
endsequence
If the ended call is removed from the BusReq instance, a match of BusReq must start one clock tick
after Enable.
sequence_instance.triggered
The triggered method evaluates to true in a given clock tick if the sequence has reached its
endpoint, and false otherwise. The triggered status of the sequence is set in the Observed region,
and persists throughout the remainder of the time step--that is, until simulation time advances. You
cannot use this method
In a sampled value function, because the sequence values are not available in the Preponed
region.
On sequences that treat their formal arguments as local variables--that is, the formal argument
is used as an lvalue in an operator assignment, or as an increment/decrement expression in a
sequence match item.
In action blocks.
The triggered method can be used only
In assertion context
An example of using the triggered method is the following:
The triggered sequence method can be used to construct reactive tests. For details, see "SVA
Reactive Tests using Sequence Methods".
Using triggered with Multiple Clocks
The triggered method can be used with multiple clocks. However, the ending clock of the
sequence instance to which triggered is applied shall be the same as the clock in the context
where the application of method ended appears.
sequence_instance.matched
The matched method detects the endpoint of a sequence used in another sequence. The matched
method can be used only in sequence expressions. This method is used when the clock of the
source sequence, sequence_instance, is different from the clock of the destination sequence, which
The matched method detects the endpoint of the source sequence, which is reached whenever
there is a match of its expression. This method synchronizes the two clocks by storing the result of
the source sequence until the first clock tick of the destination sequence after the match.
The matched status of the sequence is set in the Observed region, and persists until the Observed
region following the first clock tick of the destination sequence after the match.
An example of using the matched method is the following:
In the following example, the source sequence, s1, is evaluated at the positive edge of clk, while
the destination sequence, s2, is evaluated at the positive edge of sysclk. In s2, the endpoint of the
s1 instance is tested to occur sometime after the occurrence of inst. The matched method tests only
for the endpoint of a sequence, not its starting point.
sequence s1;
@ (posedge clk) $rose(a) ##1 b ##1 c;
endsequence
sequence s2;
@(posedge sysclk) reset ##1 inst ##1 s1.matched [->1] ##1 branch_back;
endsequence
A sequence instance on which matched is called can have multiple matches in a single cycle of the
destination sequence clock. The multiple matches are treated semantically the same way as
matching both disjuncts of an or. In other words, the thread evaluating the destination sequence will
fork to account for such distinct local variable valuations.
Sequence Events
Sequence Events
@sequence_name statement
@(sequence_name) statement
You can use a sequence instance in an event expression to control the execution of procedural
statements, based on the successful match of the sequence. The process is resumed following the
Observed region in which the endpoint of the match is detected.
Arguments to the sequence must be static. Using variables as sequence arguments results in an
error.
he sequence_name cannot be an out-of-module reference (OOMR). You cannot use sequence
T
events in classes and tasks.
A sequence event is a good alternative to an action block when only the pass condition is
significant, and when the coverage statistics that come automatically with assertions are not
needed.
In the following example, a sequence is defined once in the design under test, or in a design unit
bound to the DUT, and it sends an event to the test when the sequence is detected:
event notify_test_of_bad_crc;
sequence bad_crc;
@(posedge clk)
data_state[*min:max] ##1 bad_crc_state[*2];
endsequence
One or more tests can detect the event by using an OOMR, as follows:
@(top.dut.notify_test_of_bad_crc) $display("Processing bad CRC frame");
Similarly, if an event is specific to a given test, you can use an OOMR to define the sequence in the
test, as follows:
sequence bad_crc;
@(posedge clk)
top.dut.data_state[*min:max] ##1 top.dut.bad_crc_state[*2];
endsequence
SVA Properties
A property describes a behavior that you want to check during simulation. It can be a simple
behavior described by a single expression, or a complex behavior described by several
expressions and sequences with specific relationships between them. A property is distinguished
from a sequence in that it often contains implications.
Properties can be declared in a module, interface, program, package, or compilation unit scope.
property is similar to a Boolean expression, in that it holds at the beginning of the behavior that
A
matches. However, unlike a Boolean expression, a property can span any number of clock cycles; it
can even span an infinite length of time.
For example, suppose you have a property that states
If a is true, and b is true on the next positive edge of clk, then c must also be true, and d must be true
in the next clock.
The property takes place over a span of three clock cycles. If all of the behaviors hold, it is said to
be satisfied in the first clock cycle, as shown:
I t is also possible that a property will never be evaluated. During simulation, this can occur if the
test vectors do not trigger the behaviors being checked. The property does not fail because it is
never checked.
Note: Per the IEEE 1800 SystemVerilog standard, you cannot call the following types of functions
from within a property:
Functions that have output or inout arguments
You can declare a property in a module, interface, program, package, or compilation unit scope.
Note: Properties referenced in a package must be defined in that package.
The following are supported for properties:
Typed Formal Arguments
Clocking in SVA
identifier [ ( actual_arguments ) ]
You instantiate a property by using its name in an expression. If the property declaration has formal
arguments, you specify the actual argument values when you instantiate the property. The actual
argument list can be either name-associated or positional.
In this example, the P6 property passes the actual arguments, my_AA and my_BB, to the property:
parameter true = 1;
property P6 (bit AA, BB=`true, EN=1);
@(negedge clk)
EN |-> (BB ##1 c) |=> (AA ##[1:2] (d||AA));
endproperty
assert_P6: assert property P6(.AA(my_AA),.BB(my_BB));
The disable iff clause cancels any current obligations of the property to hold. You can use the
disable iff clause to terminate checking of an assertion at any time.
I n this example, if rst goes high, the current evaluation of the property is canceled, and the
property cannot fail. No new evaluations start until rst goes low, at which point the implication is
once again evaluated normally.
property P4;
@(negedge clk)
disable iff (rst)
(c) |-> (##[max-1:$] d);
endproperty
The default disable iff clause specifies the default reset condition that will apply to all assertion
statements that follow. For example:
default disable iff rst;
Semantic of disable iff has been changed to align with 2012 LRM. In IES 13.1 and earlier
releases, assertion is disabled if the disable iff signal becomes active anytime between sampling
and observed region. In IES 13.2, this behavior has been changed to use the value in the observed
region for disabling the assertion.
Notes about disable iff:
The value of the boolean_expression is its value in the current simulation cycle, not the
sampled value.
Per the IEEE 1800 SystemVerilog standard, nesting of disable iff clauses, either explicitly
or through property instantiation, is not legal.
The disable counter is incremented when an assertion transitions to the disabled state.
{ sequence_property
| implication_property
| property_conjunction
| property_disjunction
| negation_property
| until property
| nexttime property
| eventually property
| always property
| iff property
| implies property
| conditional_property
| instance_property }
sequence_expression ...
sequence Seq;
(a ##1 b && c);
endsequence
property Prop;
Seq[*3]##1(d && e);
endproperty
Strong
Evaluates to true if, and only if, there is a nonempty match of the sequence_expr . An
evaluation attempt of a strong (sequence_expr ) in progress will be reported as FAILED at the
end of simulation (EOS). All the evaluation attempts of a particular assertion in flight at EOS
will be reported.
Weak
Evaluates to true if, and only if, there is no finite prefix that witnesses inability to match the
sequence_expr . An evaluation attempt of a weak (sequence_expr ) in progress will be reported
as FINISHED at the end of simulation.
The following example is a valid expression:
assert property ( @(posedge clk) strong (a ##1 b) );
whereas, the following example is an invalid expression since strong/weak cannot operate upon
property_expr :
If the strong or weak operator is omitted, then the evaluation of the sequence_expr depends on
the assertion statement in which it is used. If the assertion statement is assert property or
assume property, then the sequence_expr is evaluated as weak (sequence_expr). Otherwise,
the sequence_expr is evaluated as strong (sequence_expr).
s_nexttime ( a |=> b )
Note: As per IEEE 1800-2012 LRM, starting 13.2 release, the default assertion evaluation
semantics is weak. Use assert_report_incompletes 1 to get strong semantics.
An implication property specifies a sequence that is checked only when a certain precondition is
satisfied.
The implication operators, |-> and |=>, differ as follows:
|-> If the left-hand operand matches the specified sequence, the endpoint of the match is
the starting point for evaluating the right-hand operand.
|=> If the left-hand operand matches the specified sequence, the starting point for
evaluating the right-hand operand is one clock cycle after the endpoint of the match.
The following example defines a property named P1, which is triggered on the negative edge of
clk. If a holds true for two cycles, and two cycles later b holds true for two cycles, then d must hold in
the next clock cycle after b ends.
property P1;
@(negedge clk)
(a[*2] ##2 b[*2]) |=> (d);
endproperty
The P2 example is similar, except that d is evaluated during the clock cycle in which the right-hand
expression completes.
property P2;
@(negedge clk)
(a[*2] ##2 b[*2]) |-> (d);
endproperty
he P4 example uses nested implication operators. It states that if a is followed by b, then in the
T
next clock cycle, c or d must hold, followed by d or e. In the next clock cycle, if f or e holds, g must
hold in the same clock cycle.
property P4;
@(negedge clk)
a ##1 b |=> (c || d) ##1 (d || e) |=> (f || e) |-> g ;
endproperty
For the followed-by property to succeed, the following conditions must be met:
From a given start point sequence_expression should have at least one successful match.
Starting from the end point of some successful match of sequence_expression,
property_expression shall be successfully evaluated.
From a given start point, evaluation of the followed-by property succeeds and returns true if, and
only if, there is a match of the antecedent sequence_expression beginning at the start point, and the
evaluation of the consequent property_expresion beginning at the end point of the match succeeds
and returns true.
These variants are classified based on:
Overlapping and non overlapping operators
Overlapping form
sequence_expression #-# property_expression
In overlapping form, the evaluation of consequent property_expression starts in the same cycle
where the antecedent sequence_expression matches.
Non-overlapping form
sequence_expression #=# property_expression
In non-overlapping form, the evaluation of consequent property_expression starts a cycle after the
antecedent sequence_expression matches.
The followed-by operators are the duals of the implication operators, “|->” and “|=>”. Therefore,
sequence_expression #-# property_expresion is equivalent to the following:
The following example defines a property named P1, where done shall be asserted at some clock
tick during the first 6 clock ticks, and rst shall always be low starting from one of the clock ticks
when done is asserted.
property p1;
##[0:5] done #-# always !rst;
endproperty
The P2 example is similar, except that done shall be asserted at some clock tick during the first 6
clock ticks, and rst shall always be low starting from the clock tick after one of the clock ticks when
done is asserted.
property p2;
##[0:5] done #=# always !rst;
endproperty
property_expression1 or property_expression2
notproperty_expression
A negation property defines a condition that must not occur. If the expression being checked holds,
the negation property returns false. If it does not hold, the property returns true.
D o not negate an implication property, because it will fail when the property passes
vacuously.
This example defines a property, N1, which returns false if a and rst are 1 at the same time:
property N1(a);
@(posedge clk)
not (a && rst);
endproperty
|s_until
|until_with
|s_until_with } property_expression2
The weak non overlapping form of until evaluates to true if and only if, `property_expr1' evaluates to
true at every clock tick beginning with starting clock tick of evaluation attempt and continue until
atleast a tick before a clock tick where `property_expr2' is true. If `property_expr2' is true at starting
clock tick of evaluation attempt, `property_expr1' need not be true at that clock tick.
The weak overlapping form of until evaluates to true if and only if, `property_expr1' evaluates to true
at every clock tick beginning with starting clock tick of evaluation attempt and continue until and
including a clock tick where `property_expr2' is true.
The strong non overlapping form of until requires that a current or future clock tick must exist at
which property_expr2 evaluates to true.
Weak nexttime
nexttime property_expr
The weak nexttime property evaluates to true if, and only if, either the property_expr evaluates to
true beginning at the next clock tick, or there is no further clock tick.
Indexed form of weak nexttime
nexttime [ constant_expression ] property_expr
The indexed weak nexttime property evaluates to true if, and only if, either there are not
constant_expression clock ticks or property_expr evaluates to true beginning at the last of the next
constant_expression clock ticks.
Strong nexttime
s_nexttime property_expr
The strong nexttime property evaluates to true if, and only if, there exists a next clock tick and
property_expr evaluates to true beginning at that clock tick.
Indexed form of strong nexttime
s_nexttime [ constant_expression ] property_expr
The indexed strong nexttime property evaluates to true if, and only if, there exists
constant_expression clock ticks and property_expr evaluates to true beginning at the last of the
next constant_expression clock ticks.
Note: The number of clock ticks given by constant_expression shall be a non-negative integer
constant expression.
Note: The default assertion semantics in 13.1 is still strong:
As per IEEE 1800-2009 LRM, default semantics should be weak.
For the operators which will have support for strong variant, the other variant will be treated as
weak.
The abort property operators are used to specify abort or exit condition for the evaluation of any
property_expression. Using different abort operators, the result of terminated evaluation is
specified as success or failure.
These variants are classified based on:
Asynchronous and synchronous abort properties
Asynchronous Abort Properties
accept_on (expression) property_expression
false. Otherwise, the overall evaluation of the property is equal to the evaluation of the
underlying property_expression.
Note:
Similar to disable iff clause, the operators accept_on and reject_on are evaluated at every
simulation time step.
Their abort condition is evaluated using sampled value as a regular Boolean expression in
assertions, unlike disable iff which uses current value. The abort operators accept_on and
reject_on represent asynchronous reset.
Evaluation attempt of abort operators accept_on and reject_on is nonvacuous if the
evaluation attempt of property_expression is nonvacuous and the expression_or_dist abort
condition evaluates to zero.
In both the asynchronous abort properties, the abort condition takes precedence when the
abort condition occurs at the same time step where the evaluation of property_expression
ends.
Synchronous Abort Properties
sync_accept_on (expression) property_expression
Note:
Unlike disable iff clause, accept_on, and reject_on, the operators sync_accept_on and
sync_reject_on are evaluated at the simulation time step when the clocking event happens.
Their abort condition is evaluated using sampled value as is done for accept_on and
reject_on, unlike disable iff which uses current value. The operators sync_accept_on and
sync_reject_on represent synchronous reset.
In both the synchronous abort properties, the abort condition takes precedence when the abort
condition occurs at the same time step where the evaluation of property_expression ends.
Any nesting of abort operators is allowed and these nested operators are evaluated in the
lexical order.
s_eventually } [ cycle_delay_const_range_expression ]
property_expression2
Strong eventually
s_eventually cycle_delay_const_range_expression
A propertyeventually [constant_range] property_expr evaluates to true if, and only if, either
there exists a current or future clock tick within the range specified by constant_range at which
property_expr evaluates to true or not all the current or future clock ticks within the range specified
by constant_range exist. The range for a weak eventually shall be bounded.
A ranged form of eventually , s_eventually[n:m] specifies the range of n+1 to m+1 clock ticks,
where counting starts at the current time step.
Note: The strong variant s_eventually cannot be applied to any property expression that
instantiates a recursive property [IEEE 1800-2012 LRM Section 16.13.17].
Ranged form of strong eventually
s_eventually [ cycle_delay_const_range_expression ] property_expr
always property_expr
Weak always
always property_expr
A property always property_expr evaluates to true if, and only if, property_expr holds at
every current or future clock tick.
Ranged form of weak always
always [ cycle_delay_const_range_expression ] property_expr
A property s_always [constant_range] property_expr evaluates to true if, and only if, all the
current or future clock ticks specified by constant_range exist and property_expr holds at each of
these clock ticks.
A property evaluates to true if and only if, either both property_expr1 and property_expr2 evaluate
to false or both property_expr1 and property_expr2 evaluate to true.
_________________________________________} property_expression2
A property of this form evaluates to true if, and only if, either property_expr1 evaluates to false or
property_expr2 evaluates to true.
A property expression used in implies operator can also contain an implies operator within
property_expr1 implies property_expr2 implies property_expr3
Example:
if(expression)
property_expression
[ else property_expression ]
The if, else if, and else constructs return true if a value holds when a given condition is met.
In this example, property P1 uses a nested if statement. This property checks b if a is true. If b is
true, c is checked one clock cycle later. If c is true, the assertion passes if d is true and, one clock
cycle later, e is true.
property P1;
@(negedge clk)
if(a) (b |=> if (c) (d |=> e));
endproperty
Property P2 uses an if/else statement. Like P1, this property checks (b |=> c) if a is true. If a is not
true, the property checks (d |=> e).
property P2;
@(negedge clk)
if(a) (b |=> c)
else (d |=> e);
endproperty
Property P3 uses the if/else if statement to check different values, depending upon the value of the
rst_count variable.
property P3;
@(negedge clk)
if(rst_count <= 0)
(a&&(b||c) |=> d ##[1:2] e)
else if (rst_count == 1)
(e |-> f ##[1:2] g)
else if(rst_count == 2)
((a&&b&&c) |-> ##[0:$] (d&&e&&f));
endproperty
identifier [ ( argument_list ) ]
An instance property instantiates a property within another property or assertion. If the property
declaration has an argument list, the formal arguments are instantiated with the actual arguments in
the instance property.
For example, property P specifies that if a or b is true, then c must be true in the same clock cycle.
The I1 assertion instantiates P and specifies that if a is 0, then P must hold in the next clock cycle:
property P;
In the given recursive property, if the formal argument p holds, then recursively, in the next cycle p
must also hold. In summary, p must hold at every cycle.
Example 2:
The given code illustrates a mutually recursive property.
property x;
1'b1 |=> y;
endproperty
property y;
1'b1 |=> x;
endproperty
Recursive properties are supported inside a module, interface, and package. However,
recursive properties are not supported in program, clocking blocks, and compilation-unit
scope.
test itest();
endmodule
module test;
sequence s1(x,y);
x ##1 y;
endsequence
endmodule
Example 2: The following example demonstrates how property p1 defined in interface inf is used in
module top. The hierarchical path inf_i.p1 in property tp1 within module top points to property p1
defined in interface inf.
module top;
inf inf_i();
property tp1;
endproperty
endmodule
interface inf;
property p1(a,b);
a ##1 b;
endproperty
endinterface
Example 3: The following example demonstrates the use of sequence method in procedural block
and in if generate block.
module top;
test itest();
always
begin
#2 wait(itest.s2(a).triggered);
end
generate
if(i>5)
begin: gen_blk1
assert #0(itest.s1.triggered);
end
endgenerate
endmodule
Example 4: The following example below demonstrates how SV property defined in for-generate
block within a module test is referenced using hierarchical path itest.loop[1].p1 from module top.
module top;
test itest();
endmodule
module test();
genvar i;
generate
begin : loop
property p1;
endproperty
end
endgenerate
endmodule
Limitations:
An assertion within a procedural block, that references a property or a sequence defined in an
out-of-module scope is not supported.
Any reference to compilation unit scope (cu-scope) variable, let construct, and user‐defined
data types in hierarchical referenced properties or sequences is not supported.
The failure message for assertions containing hierarchical reference to SVA properties or
sequences, does not point to the exact source code in assertion logging message.
SVA Directives
Directives specify how an assertion is used during the verification process--as a behavior to be
checked, or for collecting coverage information. Only properties with a verification directive are
evaluated. The evaluation result will be one of the following:
Finished
Failed
Vacuous
Disabled
Specifies a property to be checked during simulation, and any actions to take if the property passes
or fails. You can use the assert directive to declare an immediate assertion; use the assert property
directive to declare a concurrent assertion.
In this example, property p3 is declared as a concurrent assertion:
property p3 ; @(posedge d) (a ##2 b); endproperty
assert property (p3) else -> error_detected;
Specifies a property that must hold true throughout verification, and any actions to take if the
property passes or fails. When used in formal analysis, the assume function constrains the
conditions that are proven. When used in simulation, the function is used to check that only valid
stimuli are tested.
In this example, property P3 defines an assumption that, at every positive edge of D, A will be true,
and two clock ticks later, B will be true:
property p3 ; @(posedge D) (A ##2 B); endproperty
p3_label: assume property (p3);
Specifies a property or sequence to be monitored during simulation; the results are used as
coverage information. The cover statement can optionally specify a pass statement--an action to
take when the property or sequence passes. The pass statement cannot include any concurrent
assert, assume, or cover statements.
The cover property directive counts at most one match of the property for each evaluation attempt.
The cover sequence directive counts all matches of the sequence, rather than one per attempt. The
counts for cover property and cover sequence will differ for a variable-length sequence. For
example:
cover sequence (a ##1 b[*1:3] ##1 c);
For any one attempt, cover property will count only the first match, but cover sequence can result
in up to three matches for the sequence.
Note: The cover sequence directive is not currently part of the IEEE 1800-2005 standard for
SystemVerilog, but is proposed for a future release.
Specifies a procedural blocking statement that lets you wait on a property evaluation. The next
statement is not evaluated until the expected property passes or fails. The structure of the expect
statement is like an assert statement, because you can include an action block.
The expect statement can be located in any procedural blocking statement, including tasks and
class methods.
Note: The expect statement can refer only to static variables--automatic variables are not
supported.
The statement following the expect statement is executed after the Observed region in which the
property completes its evaluation is processed. When the property succeeds or fails, the process
unblocks, and the property stops being evaluated--that is, no property evaluation is started until that
expect statement is executed again.
If the property fails at its clocking event, the optional else clause of the action block is executed. If it
succeeds, the optional pass statement is executed.
You cannot use the expect statement within an action block.
The following example shows how the expect action block can be used:
initial begin
expect ((@ ... ) ##[1:10] data == value)
$info ("Value occurred. Continuing with test.");
else
begin
$error("Value did not occur within 10 clock cycles.");
$finish;
end
end
The expect statement can be used to construct reactive tests. For details, see "SVA Reactive Tests
using the expect Statement".
Note: Because the expect statement can fail, it is treated like an assertion in the Incisive simulator--
it appears in the Assertion Browser and assertion reports, and it increments finished and failed
counters in the coverage database.
An action block defines the actions to take when an assertion passes or fails.
The action blocks of concurrent assertions can contain sampled value functions ("SVA Sampled
Value Functions"), but the action blocks of immediate assertions cannot.
Note: The Incisive simulator does not support delays in action blocks, including the action block of
he following is an example of an action block. This assertion displays the message A1 passes
T
when the property passes, and A1 fails when the property fails.
A1: assert property (@(posedge clk) a || b -> c || d)
$display("%m passes");
else $error("%m fails");
Note: The 1800 IEEE Standard for SystemVerilog specifies that the pass statement runs when a
vacuous pass occurs, as well as when an assertion finishes. By default, the Incisive simulator runs
the pass statement only when the status is finished, not when a vacuous pass occurs. Use the -
strict option in Running an Assertion Simulation of Assertion Checking in Simulation to execute the
pass statement when a vacuous pass occurs.
Known Limitation
If an assertion contains an action block that has a message display function, a message is reported
as a result of the execution of the action block. This message is displayed in addition to the internal
message of completion that is reported from the tool. However, in some scenarios, these messages
from the action blocks are not reported alongside the internal messages from the tool.
Returns a message with an F severity level (fatal), and stops the simulation. With the support in
pass block, executed even when the assertion passes. Also, twice mentioned that it stops the
simulation.
call to $fatal implicitly calls the Verilog $finish system task. As for the $finish task, you can
A
specify a level of 0, 1, or 2, where
0 prints nothing
2 prints the simulation time plus memory and CPU usage statistics
Note: If you include a message argument, the level argument is required. Otherwise, the level
argument is optional and a simple $fatal() may be used.
The message argument is an optional string to be displayed when the task is called. The message
can contain format strings, similar to the $display function. The %m does not return the name of the
assertion, but returns the scope from which the task is called .
For example, this assertion checks that c and d are high at the same time:
assert_block: assert (c & d) $display ("PASS STMT");
else begin $fatal (0,"%m failed %b",c); end
If the assertion fails, simulation ends, and the following messages are displayed:
ncsim: *F,ASRTST (./test.v,87): (time 0 NS) Assertion test.assert_block_2 has failed
test.assert_block failed 1
The first message is returned by the simulator. The second message is specified in the call to
$fatal.
R eturns a simulator message with an E severity level (error). Whether simulation continues
depends on other configuration settings. By default, it stops when you are running the simulation in
interactive mode and continues in non-interactive mode.
For example, this assertion fails and calls the $error severity task if c or d is low:
assert_block: assert (c & d) $display ("PASS STMT");
else begin $error ("%m failed, c = %b",c); end
The following message is displayed when c=1, which indicates that d caused the assertion to fail:
ncsim: *E,ASRTST (./test.v,87): (time 0 NS) Assertion test.assert_block has failed
test.assert_block failed, c = 1
The simulation error count is optionally incremented. For details, see "assertion -logging" in
Assertion Checking in Simulation.
R eturns a simulator message with a W severity level (warning).This severity task does not
increment the simulation error count.
For example, this assertion calls the $warning severity task if c or d is low:
assert_block: assert (c & d) $display ("PASS STMT");
else begin $warning ("%m failed %b",c); end
$info (message[,args])
Returns a simulator message with an N severity level (note). This severity task does not increment
the simulation error count.
For example, this assertion calls the $info severity task if either c or d is low:
assert_block: assert (c & d) $display ("PASS STMT");
else begin $info (0,"%m failed %b",c); end
$sampled ( expression )
$rose ( expression [, [clocking_event] ] )
$fell ( expression [, [clocking_event] ] )
$stable ( expression [, [clocking_event] ] )
$changed ( expression [ , [ clocking_event ] ] )
$past ( expression [, [number_of_ticks ] [, [expression2 ] [, [clocking_event]]] ] )
The use of these functions is not limited to assertion features; they may be used as expressions in
procedural code as well. All variables referenced in the actual argument expressions passed to
these functions shall be static. The clocking event, although optional as an explicit argument to the
functions, $past, $rose, $stable, $changed, and $fell, is required for their semantics. The clocking
event is used to sample the value of the argument expression.
The following rules are used to infer the clocking event:
If called in an assertion, the appropriate clocking event from the assertion is used.
If called in an action block of a singly clocked assertion, the clock of the assertion is used.
If called in an action block of a multiclocked assertion, the leading clock of the assertion is
used.
If called in a procedural block, the inferred clock, if any, for the procedural code is used.
$sampled
$sampled(expression)
For a sampled value function other than $sampled, the clocking event is explicitly specified as an
argument or inferred from the code where the function is called.
$rose
$rose( expression[, clocking_event])]
Returns true if the least significant bit of an expression is changed to 1. Otherwise, it returns false.
$fell
$fell( expression[, clocking_event])]
Returns true if the least significant bit of an expression is changed to 0. Otherwise, it returns false.
$stable
$stable( expression[, clocking_event])]
Returns true if the value of an expression did not change during the current clock cycle.
$changed
$changed( expression[, clocking_event])]
$past
$past( expression [, [number_of_ticks ] [, [expression2 ] [,
[clocking_event]]] ])
Inside classes
The IEEE 1800-2012 LRM extends the parameter types of the bit-vector system functions to be bit-
stream types instead of just bit or bit-vectors. This is supported in IES.
$onehot
$onehot( expression )
Evaluates a bit vector and returns true if only one bit is high. Otherwise, the function returns false.
The following example defines a sequence, S3_4, which states that whenever a and b are 0 and c is
1, then a and c must be 0 and b must be 1 in the next clock cycle. The P34_onehot_ABCD property
calls the $onehot system function when S3_4 is detected, checking that, in the next clock cycle, only
one bit in d has the value 1.
sequence s3_4; (!a && !b && c) ##1 (!a && b && !c); endsequence
property P34_onehot_ABCD;
@(posedge clk) (s3_4 |=> ##1 $onehot(d));
endproperty
$onehot0
$onehot0( expression )
Evaluates a bit vector and returns true if zero or one bit is high. Otherwise, the function returns false.
This example defines a sequence, S3_4, which states that whenever a and b are 0 and C is 1, then a
and c must be 0 and b must be 1 in the next clock cycle. The P34_onehot0_ABCD property calls the
$onehot0 system function when S3_4 is detected, checking that in the next clock cycle, either all of
the bits in d have the value 0, or only one bit has the value 1.
sequence s3_4; (!a && !b && c) ##1 (!a && b && !c); endsequence
property P34_onehot0_ABCD;
@(posedge clk) (s3_4 |-> ##1 $onehot(d));
endproperty
$isunknown
$isunknown( expression )
Evaluates a bit vector and returns true if any bit is X or Z. Otherwise, the function returns false.
In this example, the A_unknown assertion calls $isunknown at each positive edge of clk:
$countones
$countones( expression )
Evaluates a bit vector and returns the number of bits whose value is 1; X and Z values are not
counted.
For example, this assertion counts the number of ones in vector d:
A_countones: assert property (@(posedge clk) $countones(d) > 0)
$display("Found ones");
else $error("Did not find ones");
Limitation:
Support of streaming concatenation operators( {>>{sig}} ) in Assertion context and SVFs.
Support of System verilog logical equality operators(==, !=) in assertion context, where
operands are 'unpacked arrays' or 'unpacked structures'.
The assertion control system tasks allow the HDL to control assertion checking from simulation.
Arguments are interpreted in the same way as for $dumpvars. If an assertion control task is used
without arguments, it affects all assertions in the hierarchy.
asrt_ctrl_task
$asserton, $assertoff, or $assertkill; these tasks are described individually in the sections
that follow.
level
Specifies the number of hierarchy levels below each specified module instance that are
affected. The level is interpreted relative to all tops in the design, regardless of where the task
is located in the design, similar to the way $dumpvars works.
Note: The 0 value can be used only if subsequent arguments specify module instances.
Setting this value to 0 affects all assertions in the specified module, and all module instances
below the specified module. It cannot be used to specify individual assertions.
list_of_modules_or_assertions
Specifies the scopes of the model to which the command applies. The
list_of_modules_or_assertions argument can specify entire modules or individual
assertions within a module. Instance names, including hierarchical instance names, are
supported. Only hierarchical references to properties are allowed; references to sequences
are not permitted.
Note: These tasks affect both SystemVerilog assertions and PSL assertions.
Assertion Control System Tasks Usage
You can use the assertion control system tasks to control
Assertions local to the assertion control system task by using the assertion name
All assertions under a hierarchy, by using the level argument and an instance name
$assertoff
Suspends checking of all specified assertions until $asserton is encountered. An assertion that is
already executing, including assertion action blocks, will continue executing.
$asserton
Resumes checking of all specified assertions that were disabled by a previous $assertoff.
Note: You cannot turn on permanently switched off assertions. An assertion is permanently turned
off in the following scenarios:
When command line option "-noassert" is used at elaboration time.
When cover’s finish count reaches the value specified on using simulation command line
switch, "-abvfinishlimit" or its tcl variant, "-finish_limit”.
When the total failure count from all the assertions reaches the value specified on using
simulation command line switch, "-abvglobalfailurelimit" or its tcl variant, "-
global_failure_limit".
When the assertion’s failure count reaches the value specified on using simulation command
line switch, "-abvfailurelimit" or its tcl variant, "-failure_limit".
When "assertion –off -always" tcl command or "-abvoff" command line option is used.
By default for cover properties.
To turn on cover properties, enable it using simulation command line switch "-abvcoveron” or
the elaboration command line switch, “-coverage u” or “-coverage all”.
$assertkill
Halts checking of all specified assertions that are currently executing, then suspends checking of all
specified assertions until $asserton is encountered.
Per the IEEE 1800 SystemVerilog standard, the $assertkill task has no effect on
immediate assertions and non-temporal concurrent assertions, due to scheduling issues.
When you use multiple assertion-control approaches, the last command received is
executed. For example, if you use $assertoff in your SystemVerilog code, then turn
assertions on with a Tcl command during simulation, the assertions will be on, because the
Tcl command was executed last.
Register callbacks and associated routines to run when an assertion state changes
Access UNIX utilities, do file I/O, and communicate with third-party tools and models.
Note: The following are not supported for immediate assertions, because they are combinatorial:
Controls--vpiAssertionReset and vpiAssertioKill
Several files in the installation are needed for the VPI SVA extensions. Include these files as
headers in the file that contains custom VPI calls. All of these files are located in
`ncroot`/tools/include.
vpi_user.h
Contains the constant definitions, structure definitions, and routine declarations and
prototypes used by the access routines. You must include this header at the beginning of
every file of C routines that use VPI calls.
sv_vpi_user.h
IEEE 1800 SystemVerilog VPI extensions. Contains the constant definitions, structure
definitions, and routine declarations and prototypes used by the access routines, as defined in
the standard.
vpi_user_cds.h
Contains Cadence extensions to the Verilog HDL specification.
stdio.h
Contains the definition of NULL.
Note: A file named vpi_abv_cds.h in `ncroot`/tools/include contains non-standard, assertion-
specific VPI routines for SVA and PSL. This file contains the constant definitions, and routine
declarations and prototypes, used by the access routines. These definitions are not needed if you
use sv_vpi_user.h.
There are three approaches to coding user routines. For more information, see "Creating a Debug
Image" in the Cadence VPI User Guide and Reference. The three approaches include:
Use the bootstrap function to dynamically load the library, by using the -LOADVPI
libraryname:bootstrapname option to irun or ncsim, or +LOADVPI=libraryname:bootstrapname
for ncverilog. The libraryname value is the name of the shared library containing the VPI
application. The bootstrapname is the name of the function in that library that will register the
VPI system tasks and functions. For example, in the following, abv_vpi_test.c contains the
VPI code, and test.v contains the Verilog code; 32-bit ELF binaries are created:
> gcc -c -g -fPIC -m32 -I. -I`ncroot`/tools/include
-o abv_vpi_test.o abv_vpi_test.c
> ncsim
To create 64-bit ELF binaries, use -m64 instead of -m32 in the gcc command, and -m
elf_x86_64 in the ld command.
You can modify and re-compile the vlog_startup_routines array in the dynamic shared library
that you are going to load. This array is in the vpi_user.c file.
name of the system task, which can then be called from Verilog HDL. The name must begin
with a $ sign.
The sections that follow discuss the custom VPI routines that you can create. Both dynamic and
static VPI is supported. This chapter describes how to
Get a list of all of the assertions in the design or scope of interest,
Get static information about the assertion
vpi_free_object(assertion_iterator);
Frees the iterator assertion_iterator .
vpi_handle_by_name(assertName, scope);
Returns the handle for the named assertion.
For example, these simple commands provide the basis for doing an operation on all assertions in
the design:
if ((assertion_iterator= vpi_iterate(vpiAssertion, 0)) != NULL )
while ( (assertion_handle = vpi_scan(assertion_iterator) ) != NULL )
Assertion type
Assert
Assume
Cover
Immediate Assertion
Assertion source information--the file, line, and column where the assertion is defined
vpi_get(vpiType, assertion_handle)
Returns the integer or Boolean of the specified property for the specified object.
vpiAssert
vpiAssume
vpiCover
vpiImmediateAssert
vpiPropertyDecl
vpiSequenceDecl
Example
Once you have a list of all assertions, you can filter them on a specified type:
if ((assertion_iterator= vpi_iterate(vpiAssertion, 0)) != NULL ) {
while ( (assertion_handle = vpi_scan(assertion_iterator) ) != NULL ) {
if (vpi_get(vpiType, assertion_handle) == vpiCover) {
/* process cover type assertions */
}
}
}
Syntax
vpi_control(control_reason, handle)
Where:
control_reason can be:
vpiAssertionSysReset--Discards all attempts in progress for all assertions, and restores the
vpiAssertionSysOff--Disables any new assertions from starting. Assertions that are already
executing are not affected. Existing callbacks are not affected.
vpiAssertionSysKill--Disables any new assertions from starting. Assertions that are already
executing are terminated. Existing callbacks are not affected.
vpiAssertionSysOn--Restarts the assertions system after it was stopped by
vpiAssertionSysOff or vpiAssertionSysEnd.
Syntax
where:
control_reason can be:
vpiAssertionReset--Discards all attempts in progress for this assertion, and resets this
assertion to its initial state. The attemptStartTime argument is invalid.
vpiAssertionDisable--Disables the starting of new attempts for this assertion. The
attemptStartTime argument is invalid.
vpiAssertionEnable--Enables the starting of new attempts for this assertion. The
When you register the callback, you define what condition is significant, and what routine to execute
when the callback occurs. A handle to the callback is returned when registration is successful. If an
error occurs during registration, NULL is returned.
Callbacks on assertions, like controls, can be set on the assertion system, or on individual
assertions.
Syntax
callback_handle = vpi_register_cb(
callback_reason,
pointer_to_callback_function,
user_data)
where:
callback_reason can be:
cbAssertionSysInitialized)--This callback occurs after the system has initialized. No
assertion-specific actions can be performed until this callback completes.
cbAssertionSysOn --The assertion system has become active, and starts processing
assertion attempts. By default, this callback occurs on simulation startup, but can be
delayed with system control tasks, or by using $asserton with no arguments, or by using
the Tcl assertion -on -all command.
cbAssertionSysOff--The assertion system is temporarily suspended. No new attempts
are processed, and no new callbacks occur. Assertions already executing are not
affected. This callback occurs as a result of a VPI control, $assertoff with no arguments,
or a Tcl disable command with the -all option.
cbAssertionSysKill--The assertion system is temporarily suspended. No new attempts
are processed, and no new callbacks occur. Assertions already executing are terminated.
This callback occurs as a result of a VPI control, or an $assertkill command with no
arguments.
cbAssertionSysEnd --All assertion processing has completed, and will have no further
affect. This callback normally occurs at the end of simulation.
cbAssertSysReset --This callback occurs when the assertion system is reset.
user_data --User-supplied data to be passed to the callback function when the callback
occurs.
Syntax
callback_handle = vpi_register_assertion_cb(
assertion_handle
callback_reason,
pointer_to_callback_function,
user_data)
where:
The assertion_handle can be:
Any concurrent, cover, assert, or assume statement
An immediate assertion.
Invalid assertion names are sequence or property names.
user_data --User-supplied data to be passed to the callback function when the callback
occurs.
Callback Functions
The callback function is executed when a registered callback occurs. Each callback can define a
unique callback function. This function is defined when the callback is registered.
The VPI prototype is passed an s_cb_data structure containing the callback reason and any user
data.
Syntax
my_cbname(
callback_reason
callback_time,
assertion_handle,
pointer_to_attempt_info,
reference_to_user_data)
where:
callback_reason is the reason specified with vpi_register_cb or
vpi_register_assertion_cb.
directive fails.
Removing Callbacks
ou can use the vpi_remove_cb command to remove an assertion system callback or an individual
Y
assertion callback.
Syntax
vpi_remove_cb(callback_handle)
where the callback_handle is the value that was returned when the callback was registered.
vpi_get(statistic, assertion_handle)
vpiCovered--True if the assertion has been attempted, has succeeded at least once, and has
never failed.
vpiAssertAttemptCovered--Returns the number of attempts to match the assertion.
Known Limitations
Support for assertion controls on specific scopes is deferred for a future release.
vpiHandles for property and sequence instances are deferred for a future release.
6
PSL Language Support Limitations
The Cadence-supported constructs of the PSL property specification language are limited to the
Verilog, SystemVerilog, VHDL, and SystemC flavors of the Boolean layer, the LTL segment of the
temporal layer, and some elements from the modeling and verification layers.
This subset is further restricted to the subset of PSL that can be checked on-the-fly, according to the
definition in section 4.4.4 of the 1850™ IEEE Standard for Property Specification Language (PSL),
17 October 2005.
An X in the following table indicates that the PSL construct is not supported for a given
language.
nondet(), 5.2.3.9 X X X X X
nondet_vector() 5.2.3.10
Multiple/nested 6.1.2.5 X
clocks
Parameterized 6.2.1.7.1 X X X X X
properties
Property OR 6.2.1.7.5 X X X X X
The 7.1.3 X X X X X
assume_guarantee, 7.1.5
restrict_guarantee, 7.1.7
fairness, and
strong_fairness
verification
directives
U nbound 7.2.1 X
verification units
Only the pragma form of PSL is supported in SystemVerilog packages. Other Known Limitations in
Only the pragma form of PSL is supported in SystemVerilog packages. Other Known Limitations in
PSL Support
For the SystemVerilog flavor of PSL, you cannot call the following types of functions from
within a property:
Functions that have output or inout arguments
Functions that have non-constant reference arguments
Functions that have static data declarations
Functions that modify data outside of the function scope
For the VHDL flavor of PSL:
You cannot use an endpoint declared in an upper scope.
For example, a property declared in a generate scope cannot use an endpoint in the
architecture body.
You cannot use parameters, such as generate variables, in the repetition expression of a
SERE.
There are some restrictions on the use of the forall replicator; for details, see "PSL Property
Replication".
In a verification unit, if you make an assignment to a signal declared in the design, that
assignment is added to the design. When there are multiple assignments to the same signal,
standard HDL rules apply. The Cadence implementation does not support the override
semantics described in the PSL LRM, so assignment in the verification unit does not override
assignments in the design. A VHDL signal defined in a verification unit does not override a
signal of the same name in the design.
Although you can bind a verification unit to a blackboxed module, both the module and the
verification unit properties are ignored during simulation. To apply PSL properties to the
inputs and outputs of a blackboxed module, bind the verification unit to the parent module or
hierarchy.
Memories and multidimensional arrays are not supported as arguments to the built-in
functions.
Verification unit instance binding is not supported for VHDL and SystemC.
7
Using SVA
The bind directive binds properties to design units. It can be specified in
When using this bind solution, it is not necessary to specify whether the target is Verilog or
VHDL. To ensure that binding occurs correctly, the bind specification must adhere to the
Incisive simulator mixed-language binding rules. For details, see "Mixed Verilog/VHDL
Simulation" in the Verilog Simulation User Guide.
The argument values you use depend on whether the target is SystemVerilog or VHDL.
target The name or hierarchical name of the The module name of the VHDL
module or interface instance to which object to which the bind_obj will be
the bind_obj will be attached. attached, which can be a VHDL
When bind is specified in a text file, Entity--Applies to all instances of
any hierarchical names for target all architectures of this entity
must begin with $root, because the
text file does not have the context to Architecture--Applies to all
resolve the hierarchical identifier instances of this architecture
correctly.
Instance
For a target specified as
module:instance , the bind_obj will Configuration instance
be bound to all instances of module The target can also be specified as
that have the name instance a Cell(View) name; for details, see
throughout the design. Multiple "Limitations on Binding to a VHDL
instances are separated by commas. Target".
For a target specified as
module:instance , the bind_obj will
be bound to all instances of module
that have the name instance
throughout the design. Multiple
instances are separated by commas.
A variable or a user-defined
function call cannot be used as a
bind_obj .
A list of actual argument values. Full Used for generics only. A list of
Verilog expression syntax is parameter values mapped to VHDL
supported for arguments. generics or literals. Only simple
names are allowed for parameters.
bind_inst The instance name that the The instance name that the
SystemVerilog object will have when SystemVerilog object will have
it is attached to the module. This when it is attached to the VHDL
name becomes part of the object. This name becomes part of
hierarchical reference for assertions the hierarchical reference for
and signals in the bound module. assertions and signals in the bound
module.
The instance created for this binding
adds another level of hierarchy to
the elaborated design under the
VHDL target.
The ports to bind to. Full Verilog The port map aspect that connects
expression syntax is supported for the SystemVerilog formal ports used
port connections. Ports can be in the assertions to the VHDL actual
connected by order or name. ports. Ports can be connected by
order or name. Multiple port
The .* notation and out-of-module
connections are separated by
references (OOMRs) are allowed in commas.
the port connection list when binding
to SystemVerilog. The .* notation is VHDL ports of mode out can be
not supported when binding to a read and used in the bound
Verilog or VHDL design file. SystemVerilog module.
The VHDL actual port can be an
external port or internal signal
declared in
The architecture declarative part
The entity declarative part
A package
A package body--deferred
constants
Note: Only simple names are
supported for port connections. No
expressions are allowed.
Connecting to VHDL records or two-
dimensional arrays, or any part of
them, is not supported.
Note: Support files for SystemVerilog binding are created in the worklib/.cdssvbind directory for
three-step mode, and ./INCA_libs/.cdssvbind for irun.
// Binds to an instance.
bind fifo:fifo1 fifo_full v2();
// Binds to an instance.
bind cell(v2_arch) fifo_full v3();
Note: D o not specify the entity/architecture using a hierarchical name starting with a Verilog top.
Verilog hierarchical names ending in VHDL scopes are not permitted.
You must specify the name of the external file using the -extbind filename option; for example:
ncelab -extbind bind_file
If you are using irun with the -top option, you must also specify -top binds_in_textfile as a
second top module name. For example:
irun -extbind bind_file -top dut -top binds_in_textfile
Using -top binds_in_textfile is only necessary if you use -top already, which is a
requirement for VHDL.
Another approach is to have all bind statements in a file, and provide that file in the same
If the target of a bind directive is protected, the bound instance will exist, but it will not be visible in
SimVision.
For details, see Chapter 10, "Writing Assertions for Protected IP."
The following table lists the Verilog and VHDL data types that are supported for port
connections.
Verilog VHDL
bit std_logic
bit std_ulogic
If a vector is used, the VHDL actual must be a constrained one-dimensional array subtype of a
std_logic vector, and the entire array must be passed. VHDL record members are not supported as
actuals.
Multiple variants of a target
Verilog and VHDL configurations have no effect in resolving the target of binds specified in a
text file.
Configurations can be used to resolve multiple variants of a target of binds specified in a
module scope.
Only the following VHDL object classes can be accessed by SystemVerilog assertions:
Signals
Ports
Constants
Package constants
Package signals
Shared variables
Generics
When you bind VHDL generic parameters to Verilog parameters, you can use the following
VHDL generics:
STD.STANDARD.INTEGER
STD.STANDARD.REAL
STD.STANDARD.TIME
STD.STANDARD.STRING
STD.STANDARD.BOOLEAN
Any user-defined enumerated type
VHDL process variables are not supported.
When you map a VHDL actual directly to a Verilog module parameter through a generic map
aspect, the actual must be one of the following types:
INTEGER_LITERAL
REAL_LITERAL
STRING_LITERAL
ENUMERATION_LITERAL
The syntax for binding to a compiled VHDL cell view is slightly different from binding to other
VHDL objects. The target, Cell(View) , must be the cell view instance name of the
architecture, and the bind_obj must be the SystemVerilog module name and parameter map:
();
The following applies to simulations using attempt-based counting only; it does not apply to
trace-based counting. For details, see "Setting Up the Assertion State Counters."
If you need comprehensive information about property failures, use the assert directive. When the
assert directive is used, by default property failures are
Disadvantages The scope is not unique when module A complete port list is
binding is used, so there can be name required for the module
conflicts between verification units. or instance to be bound.
Mixed-language binding is not supported.
Instance binding is currently available only
for Verilog/SystemVerilog.
Mechanics External file name provided at compile time Must supply a bind
with the - propfile option. directive.
The following is an example of using SVA in a PSL verification unit. The READ_BURST_READ_N
assertion is written in the Verilog flavor of PSL, and the END_OF_BURST sequence and
COUNT_BURST_READ_N assertion are SVA:
// PSL
READ_BURST_READ_N: assert
always ( {state == ready && m_req == '1' && m_task == read_burst} |=>
{READ_PULSE[*]; (addr_counter == (m_data[4:0]) - 1) && state == ready})
@(posedge clk);
// SVA
sequence END_OF_BURST;
addr_counter == (m_data[4:0] - 1 && read_n ##1
(addr_counter == (m_data[4:0] - 1) && !read_n)[*2] ##1
(state == ready)
);
endsequence
If it is unclear whether an assertion is PSL or SVA, the Incisive simulator assumes that it is PSL.
Although you can put SVA and Verilog PSL in a verification unit, you cannot define a sequence or
property in one language and use it in the other.
This capability is not part of either the PSL or the SystemVerilog standard.
Use Model
The use model is as follows:
1. D efine the properties in the package.
Note: You can define properties in a package, but you cannot use assertion statements in a
package.
2. In the program, module, or interface into which the package is imported, instantiate the
property in an assertion statement.
You can declare PSL properties and sequences in SystemVerilog packages, and
reference them from outside the package. PSL sequences and properties can also be
imported from one package into another package.
Examples
The following examples show how to create properties in a package.
The first property, area_not_preferred, shows one approach. In this example, all of the signals that
are used in the property must be declared in the package for the package to compile, although
these declarations might not be used when the property is imported. Also, the signal names used in
the package must match the signal names used in the design into which they are imported.
The second property, area_preferred, shows a better approach. This property takes advantage of
the ability to specify property arguments in the package, and pass the signals in as arguments when
the property is instantiated in a module. This preferred approach is shown by the area_preferred
property.
`ifndef my_properties
package example_properties;
property area_not_preferred;
@(posedge clk) disable iff (!reset)
(area == length * width);
endproperty
endpackage
`define my_properties
`endif
Code here
import example_properties::area_preferred;
area_check: assert property (area_preferred(clk, reset, length, width, area));
endmodule
If you include PSL in your package, you must use the pragma syntax:
`ifndef sv_props_pkg
package sv_props_pkg;
reg X, Y, Z, clk, rst;
// psl sequence SY = {S;Y};
// psl property XY_Z = (always
ended({XY}) -> next Z) @(posedge clk);
endpackage
`define sv_props_pkg;
`endif
module test;
...
import sv_props_pkg::*;
// psl assert_XY_Z: assert XY_Z;
endmodule
As shown in this example, many overlapping assertions have resulted. A large number of overlaps
can result in performance degradation.
You can also use the SystemC API to access assertions. For details, see "Access to
Assertions from SystemC Testbench," in "Using SystemC PSL ," of the SystemC Simulation
Reference.
Because the pass statement of an action block is any legal SystemVerilog procedural statement, it
can also be used to signal a failure to another part of the testbench. For example:
Action blocks are associated with both concurrent and immediate assertions. All assertions, with
the exception of immediate assertions in tasks and functions, create entries in the Assertion
Browser and assertion reports. Concurrent assertions are also recorded in the coverage reports.
Because the expect statement can fail, it is treated like an assertion, in the sense that there is an
entry in the Assertion Browser and assertion reports, and in the coverage reports.
One technique that can be used in SystemVerilog is to consolidate sequence generation and
detection into the test itself. Not only is this architecture useful for simulation, it is necessary for
acceleration, to minimize the synchronization needs of signals that pass between the simulator and
the hardware emulator.
The following code shows the use of the expect construct in a SystemVerilog test that waits for ten
cycles for a signal to have a certain value, then reports success or failure:
initial begin
expect (@(clk) ##[1:10] data == value)
$info ("value occurred. Continuing with test");
else
begin
$error("value did not occur within 10 clock cycles");
$finish;
end
end
wait ( sequence_instance.triggered );
You can delay the execution of procedural code by using wait, then use this function to
communicate sequence completion to a test.
In the following example, the initial block in the check program waits for the endpoint of either
sequence abc or sequence de. When either condition evaluates to true, the wait statement unblocks
the process, displays the sequence that unblocked the process, and executes the statement labeled
L2.
sequence abc;
@(posedge clk) a ##1 b ##1 c;
endsequence
sequence de;
@(negedge clk) d ##[2:5] e;
endsequence
program check;
initial begin
wait (abc.triggered || de.triggered);
if (abc.triggered)
$display ("abc succeeded");
if (de.triggered)
$display ("de succeeded");
L2: ...
end
endprogram
The state and clk variables are passed in, then the test references the name of the event
using its full hierarchical path.
This example assumes that the testbench module is named top, and the monitor is instantiated with
the name TX_Monitor.
#include <vpi_user.h>
#include <sv_vpi_user.h> // Contains assertion VPI declarations
/*
* 'asrtcb' is registered as a callback for all the assertion
* callbacks attached to assertions. It prints various details
* about the callback.
*/
PLI_INT32 asrtcb(PLI_INT32 reason,
p_vpi_time cb_time,
vpiHandle assertion,
p_vpi_attempt_info info,
PLI_BYTE8 * user_data)
{
p_start_time = 0;
/* get the handle of the assertion_status signal defined in the design */
vpiHandle assertion_status=vpi_handle_by_name("test.assertion_status",NULL);
s_vpi_value value_1;
vpi_printf("\n Assertion: %s", vpi_get_str(vpiName, assertion));
vpi_printf("\tTime: %e", cb_time->real);
vpi_printf("\tReason: %s\t Data: %d", reason_to_str(reason), user_data);
if(info) {
vpi_printf("\tStartTime:%e", info->attemptStartTime.real);
if(info->detail.failExpr)
vpi_printf("\n\tFAIL EXPR: %s", vpi_get_str(vpiDecompile, info->detail.failExpr));
}
if (strcmp( vpi_get_str(vpiFullName, assertion), "test.A1_sva" ) == 0)
vpi_printf("\nEXPECTED FAILURE OCCURRED!!\n");
else {
vpi_printf("\nUNEXPECTED ASSERTION FAILURE - TEST WILL FAIL!!\n");
value_1.format = vpiIntVal;
value_1.format = vpiIntVal;
value_1.value.integer = 1;
vpi_put_value(assertion_status, &value_1, cb_time, vpiForceFlag);
}
vpi_printf("\n");
switch(reason) {
case cbAssertionStart:
s_start_time.type = cb_time->type;
s_start_time.real = cb_time->real;
p_start_time = &s_start_time;
case cbAssertionSuccess:
break;
case cbAssertionFailure:
break;
default:
break;
}
return(0);
}
/*
* Register callbacks
* This routine is called only once when 'ncsim' loads this library
*/
void abv_vpi_test() {
vpiHandle hdl, asrts;
/* Iterate over all the assertions in the design and print the name */
asrts = vpi_iterate(vpiAssertion, NULL);
if(asrts) {
while(hdl = vpi_scan(asrts)) {
switch (vpi_get(vpiType,hdl)) {
case vpiAssume:
break;
case vpiAssert:
vpi_printf("\nPlacing callback on failure of assertion: %s",
vpi_get_str(vpiName, hdl));
vpi_register_assertion_cb(hdl, cbAssertionFailure, asrtcb, (PLI_BYTE8*)3);
break;
default:
break;
}
}
}
vpi_printf("\n\n");
}
When using VPI, it is important to have read and/or write access to the design variables that
are being referenced and driven by the VPI code.
module test;
bit assertion_status=0;
....
final
begin
if (assertion_status == 1'b1)
$display ("***Simulation Failed due to unexpected assertion failures");
else
$display ("***Simulation Passed %d",assertion_status);
end
endmodule
8
Maximizing Assertion Performance
When assertions are enabled in simulation, there is an overhead (both memory and runtime) during
compilation, elaboration and simulation. The most significant is the runtime overhead during
simulation.
There is no standard measure of the overhead which assertions introduce. Overhead depends on a
number of factors which include assertion density and coding styles.
However, there are several basic guidelines that, if followed, will help minimize the performance
cost of assertions. The sections that follow, describe the command-line options to help maximize
performance, switches to turn off some optimizations which are enabled by default, and assertion
writing guidelines that will help you minimize the overhead of assertions in your design and
maximize simulation performance.
`Assertions' as referred to in this chapter include `assert', `assume' and `cover' properties.
Command-line options
1. Limiting the failure/finish counts - You can disable the evaluation of assertions after a certain
failure/finish count is reached. You can specify this limit on the command-line. During
simulation once this limit is reached, assertion evaluation will be completely disabled, thus
reducing the simulation run time overhead of running with assertions. Following are the
options which you can use:
-abvfailurelimit <Number>
-abvfinishlimit <Number>
-abvglobalfailurelimit <Number>
For more details on these options, see "Setting Assertions finished/failed limits" in
Assertion Checking in Simulation.
2. Disable evaluation when assertion state is not changing - You can disable the evaluation of
assertions if the assertion state on consecutive clock cycle is the same or if the variables
sampled in the assertion are not changing. This will give you a runtime performance benefit
because of the reduced number of assertion evaluations. The following are the options which
you can use to enable this optimization:
-abvnostatechange <state>|all
This is a run time option which can be specified with ncsim/irun to evaluate assertions
and report results only when the assertion state changes.
If the result of an assertion is same at any consecutive execution, the evaluation at the
current cycle can be disabled and thus reduce the simulation runtime overhead of
running with assertions. This will mainly impact assertions without any sequence or
property operators. A particular state can also be suppressed. You can also choose to
just stop evaluation for particular assertion state.
You can also use the following Tcl command to suppress the assertion evaluation for
same consecutive state:
Assertion simulation performance with attempt-based counting is inefficient when there are many attempts
in progress simultaneously--that is, if the overlapping range of the enabling condition is very long. For any
assertion that does not start a lot of parallel attempts, the performance will not degrade noticeably.
In addition, the finish and fail counts might be different, depending on which count mechanism you choose:
Attempt-based counting reports when different attempts of an assertion finish and fail
simultaneously, which makes the number of attempts greater.
Trace-based counting reports multiple traces of an attempt, which can make the
number of traces greater.
4. Optimizing two cycle assertions - You can optimize the evaluation of two cycle assertion in a
design. This can be done using the following option:
-abv2copt
When this option is used, failure/finish reporting gets modified as successive failure and finishes and cycle
information are not reported.
5.Turning off assertion counters - You can optimize the assertion overhead during simulation
runtime by removing assertion counters. As a result of this optimization, finished, failed, and
disabled counts are collated and reported only when the user enables the counts using
commands that supersede optimization. This feature is restricted to SystemVerilog assertions
and is available under the following simulation time switch:
-abvoptreporting
You can also use the following Tcl command to optimize counts at anytime during the
simulation:
If you use this switch, then it will report passing of the assertion but will not maintain any
count. Thus assertion -summary will show "0" under disabled, finished, and failed
column. This optimization switch affects the functionality of some tcl commands. For
instance, if optimization is enabled, then assertion –logging command will not update
global failure error count while assertion –on command will turn on assertion, but will
not do any book keeping of counters.
If you run any one of the following commands, then the optimization will be
disabled for those assertions on which these commands have been applied:
abvglobalfailurelimit, errormax, abvfailurelimit, tcl, coverage u/all,
assert_count_traces, abvnostatechange, and gui.
cycle), IES will ignore that assertion evaluation. The assertion state count will not be changed,
no message will be reported, and action block will not be executed. Ignoring of assertion
evaluation (when the evaluated state is same as in the previous clock cycle) is also
applicable in the scenario where variable/expression has changed, but the resultant state is
still the same. This can result in less number of finished/failed counts as compared to the full
verbose functionality where assertion is evaluated at each clock cycle.
2. Optimizations for assertions having unbounded ranges - For assertions having unbounded
ranges, if there are number of parallel attempts, concluding at the same simulation time, only
the longest (primary) attempt is reported (in some cases, newest attempt might also get
reported ). All the secondary attempts are optimized out. This can result in less number of
finished/failed counts as compared to the full verbose functionality where all the parallel
attempts are evaluated and reported.
3. Single finished counts for cover property - As a result of this, only one finished count is
reported for cover property and after one finish, the evaluation of that cover property is turned
off.
4. Optimization for multiple identically clocked assertions - By default, IES will combine the
evaluation of multiple identically clocked assertions in a given scope. This leads to simulation
run-time optimization but, at the same time, can lead to skewed entries in the profile reports.
The evaluation load of all assertions combined for evaluation, will show up against one single
assertion.
5. Optimizations for vacuous counts and number of attempts for assertions - By default, IES does
not count vacuous pass, number of assertion attempts and cumulative pass (vacuous pass +
finished counts). This also implies that assertion -strict run-time tcl option will not work by
default.
6. Optimizations for Single Cycle assertions reporting - As a result of this, the debug information
related to number of cycles, is not reported with assertion failure message in the simulation
log.
The following section describes the options/switches to reverse each of these optimizations.
-abvevalnochange
This is a compile time option that turns off the optimization for single cycle assertions. By
default, such assertion evaluations are ignored if the assertion state remains same as in the
previous clock cycle.
-abvnorangeopt
This is a run time option that evaluates all attempts for properties having unbounded ranges
([n:$]).
-abvrecordcoverall
This is a run time option that enables counting of all finishes for cover properties.
In case of single cycle cover properties, just using this option is not enough. We also need to
add the -abvevalnochange option to disable the single cycle optimization before the cover
option can take effect.
-abvnoassertamalg
This is an elaboration time option that disables the merging of multiple identically clocked
assertions.
-abvrecordvacuous
This is a compile time option that enables the counting of vacuous pass, assertion attempts
and cumulative pass. This also enables the reporting of these counts when assertion -strict tcl
option is used at run-time.
-abvrecorddebuginfo
This is a compile time option that enables additional debugging info for single cycle
assertions (this switch will also imply -abvevalnochange), and is applicable to ncvlog and
irun.
// PSL
property holdReq(i) = always
(( rst && rose(busreq[i] && !gnt[i]) ) |->
((busreq[i]) throughout {!gnt[i]; [*]; gnt[i]} ))
@(posedge clk);
A condition that, if true, usually indicates that the sequence of interest has begun
The simulator can optimize more aggressively for the case where the initial condition is false and
there is no attempt in flight. If the initial condition is practically always true, this optimization cannot
occur, both because the condition is true, and because there will almost always be an attempt in
flight from the previous cycle.
For example, the following assertion starts a new attempt on every clock in which a is true:
// Inefficient SVA assertion
The difference is that now a new attempt will start only when a is followed by b. Here is another example:
// Inefficient for SVA--starting condition is usually true
sequence dowrite;
(state == idle) ##1 (state == write) ##1 (state == idle);
endsequence
The interesting condition for this assertion is not the idle state, which is true most of the time, but
the change from idle to write. This assertion will run faster if the starting condition is true much
less frequently, which avoids false matches at an earlier cycle:
// More efficient equivalent SVA assertion
sequence dowrite;
(state == write && $past(state) == idle) ##1 (state == idle);
endsequence
This assertion specifies that, when b follows a, c must be true on the next cycle. So for every attempt
in which a is true, the simulator must check, every clock cycle, that if b is true, c follows on the next
cycle. This definition prevents any attempt from ever finishing, because
It is not possible to rule out a future failure of that attempt
There can be a new attempt starting on every clock
In this case, put the large repetition on the right-hand side of the implication, so that the attempt can
complete when b is followed by c. For example:
// More efficient way to write SVA for attempt-based counting
assert property ( @(posedge clk) a |-> ##[0:$]b ##1 c );
Depending on the application, it is even better to reduce the number of valid attempts that are
started, as follows:
// Even better SVA--also minimizes the number of attempts that start
assert property ( @(posedge clk) $rose(a) |-> ##[0:$]b ##1 c );
In addition to following these guidelines, you can selectively disable assertions if they are
not required for a given simulation run. Disabling assertions improves performance.
Assertions can be disabled at
Run time--Provides some benefit; see "Enabling and Disabling Assertions "
in Assertion Checking in Simulation.
Elaboration time--Provides more benefit; see "Disabling Assertion Checking at
Elaboration Time " in Assertion Checking in Simulation.
Compile time--Provides the maximum benefit; see "Enabling/Disabling Assertion
Checking at Compile Time " in Assertion Checking in Simulation.
9
Writing Reactive Tests using Assertions
R eactive tests--tests that use feedback from design behavior during simulation to drive the
behavior of the test--can eliminate redundancy and dead time from a test, making it more efficient
and meaningful.
Assertion languages are used in reactive tests because they let you easily and concisely express
complex temporal conditions of interest--conditions that are often cumbersome to describe in HDL.
The PSL and SVA assertion languages can efficiently monitor the signals in the device under test
(DUT), and notify the test when a condition of interest is Observed.
For examples of reactive test implementations, see
"Using PSL Reactive Test Techniques"
"Using SVA Reactive Test Techniques"
SVA
The pass statement of an assertion action block
The expect statement
The end of a sequence as a level-sensitive wait control
Sequences used directly as event controls:
@(sequence ) begin ... end
Synchronization between the test and the simulator when the test language is not native to
the simulator or accelerator
For performance reasons, it is important to minimize the number of signals and events that
pass from the simulator to the test.
Should the reactivity code be associated with the test, the verification components, or the
DUT?
Maintenance
H ow does the user define and maintain a large collection of event names, and connect
them correctly in each test?
H ow are the various external files managed?
H andling of sequence overlap
Sequence overlap might be more of a coding style issue, but it needs to be considered.
euse and stability are key considerations in the placement of the reactive test constructs. You
R
must consider whether you want the reactive test to react to interface activity or to internal
functionality within the DUT:
Internal functionality--Referencing the internal signals and states of a DUT is not
recommended, because they are not as generic as the interface, and therefore not as re-
usable. More importantly, because the design is in development, names might not be stable.
React as desired.
It is important to remember that
The definition of a sequence and a reference to that sequence must be contained within the
same module.
You cannot use OOMRs or global signals to reference a named sequence or property.
You must define and detect the condition in the same module, then notify the test as follows:
For Verilog or SystemVerilog, trigger an event and reference the event from the test by using
OOMRs.
For VHDL, set a global signal that the test can reference.
When the test language is native to the simulator or accelerator, the sequence and property
definitions and detection can all be wholly contained in the test, where the property or sequence
definitions can use OOMRs to reference signals.
For PSL, the SystemC assertion API or assertion breakpoints are useful.
Inactivity
When responding to inactivity, It is important to distinguish between inactivity that is a result
of an error and inactivity that is permissible behavior. An example of legal event-oriented
inactivity might be that a grant did not occur within a specified amount of time. The grant might
not occur due to a bug in the chip, or it might not occur because the priority of the request was
not sufficient. The response often depends on the protocol at the interface. Using an HDL-
based watchdog timer is the underlying technique for this type of test:
For cases where the activity might be legal, use the action block to determine why the timer
fired, and respond accordingly.
For cases where the inactivity is likely to signal some unknown bug, the test should assert that
the timer does not time out. This allows the behavior to be captured by error reports.
SVA
"SVA Reactive Tests using the Pass Statement"
"SVA Reactive Tests using the expect Statement"
"SVA Reactive Tests using Sequence Methods"
"SVA Reactive Tests using Sequence Events"
"SVA Reactive Tests using VPI"
10
Writing Assertions for Protected IP
You might be writing assertions about a design that will be used as protected intellectual property
(IP). If so, you need to make sure that end users can debug simulation results for their designs that
contain your IP.
Selected Visibility
Use models for assertion protection are defined by the protected part of the assertion definition. For
the greatest control, the property and verification directive are split. For example:
// Block to be encrypted by ncprotect
// pragma protect
// pragma protect begin
`define property my_property
(@(posedge clk)
(a |-> b))
// pragma protect end
A_DEF:`my_property;
This technique, called selected visibility, protects the property definition, while keeping the
assertion visible. The most common use model is selected visibility. In this case
Messages about the assertion are printed to the log file.
The summary report lists statistics for the assertion.
The assert/cover statement named by the directive is visible in the Design Browser and
Assertion Browser.
The unprotected part of the assertion is visible in the Source Browser.
The assert/cover statement is affected by Tcl commands.
Table 10-1 summarizes the level of interaction for end users of protected assertions.
No visibility
Only assertion failures are reported; no filename, line number, or hierarchical path is printed.
ncsim: *E,ASRTST (): (time 1525 NS) Assertion has failed (2 cycles, starting 1475
NS)
Selected visibility
Prints all of the information about the assertion, but suppresses the source text of the
assertion.
ncsim: *E,ASRTST (./memctl.v,59): (time 1525 NS) Assertion
memtest2.mctl.START_WRITE_MEMORY has failed (2 cycles, starting 1475 NS)
The assertion and probe Tcl commands work for assertions with selected visibility.
For more information about the assertion summary, Assertion Browser, Design Browser, and Source Browser, see
Assertion Checking in Simulation .
Logging commands, such as assertion -logging and assertion -summary, are ignored for
protected assertions.
Exceptions
There are several scenarios in which assertions, or any other variables, are unprotected, but you
cannot access them:
If a VHDL entity declaration is partially--starting from the beginning--or completely protected,
the complete entity cannot be accessed.
Only the text between the pragmas is encrypted. The corresponding bound architecture
cannot be accessed, even if it is not protected. The following protects the complete ROM
entity:
-- pragma protect
entity ROM is
Similar scenarios apply for Verilog. To protect a Verilog module so that the complete module cannot
be accessed, you can protect
Limitations
The following limitations apply to IP protection when assertions are provided in a separate file:
If the bind statement is used within a protected portion of code, an error is generated, because
the module name must be visible.
Only unprotected bind directives are executed.
If the target of a bind directive is protected, the bound instance will not be visible in SimVision.
A verification unit that is compiled into a protected design unit is also protected; Tcl
commands will not affect assertions in such a verification unit.
11
PSL and SVA: Similarities and Differences
PSL was designed to work with many languages and support hierarchical properties. SVA was
designed to work with SystemVerilog and express linear properties.
Where their capabilities overlap, the formal semantics of PSL and SVA are identical. Their syntax is
the same in many cases, but is different at the top-level.
The primary characteristics of these assertion languages are the following:
SVA
Defined for SystemVerilog HDL
Assertions are synchronous, with one asynchronous reset
Assertions are linear and implementation-oriented
PSL
Defined for Verilog, SystemVerilog, VHDL, and SystemC
Assertions can be both synchronous and asynchronous, with multiple reset conditions
Assertions can be both abstract and hierarchical
Expressions
Both PSL and SVA use the underlying HDL expression syntax. PSL accepts Verilog,
SystemVerilog, VHDL, and SystemC expressions. SVA accepts SystemVerilog expressions.
Built-In Functions
The SVA and PSL xbuilt-in functions are similar: rose, fell, prev, stable, onehot, onehot0,
countones, and is_unknown. However, the notation varies, where PSL uses rose(), for example,
and SVA uses $rose().
Sequences
This section describes the similarities and differences between PSL and SVA sequence operators
and semantics.
Sequence Operators
Sequence Operators
SL and SVA have an equivalent set of sequence operators, with equivalent precedence, as
P
shown in the following table:
The differences between PSL and SVA operators are shown in the following table:
Sequence delimiters { } ( )
Sequence disjunction | or
The following table gives examples of equivalent PSL and SVA sequence operator usage:
Sequence Semantics
Both PSL and SVA imply nothing about unmentioned signals. If the assertion does not refer to a
Boolean, for example, it is not constrained. For example, a ##1 b does not imply that b is either true
or false in the first cycle, only that it must be true in the second cycle.
oth languages permit overlapping matches. For example, {a; b; c} starts a trace in a cycle if a is
B
true. If a is true in the second cycle, another trace starts before the first has finished or failed.
oth PSL and SVA sequences can be used to express behavior using regular-expression style
B
notation. A regular expression generally consists of a sequence of terms with optional repeat
counts, so that each term is required to occur 0 or more times in order to match the regular
expression. The PSL and SVA repetition operators provide this capability. For example:
PSL: { req; wait[*0:2]; ack }
Both PSL and SVA have repetition and delay shortcuts, where [*] means zero or more, and
[+] means one or more.
This form assumes that each condition is equally important. In some cases, you might want to
ignore certain conditions, and think of the behavior instead as a series of important conditions
separated by delays. Both PSL and SVA sequences can be used to express behavior in a delay-
In this case, the two languages use slightly different operations to achieve the same goal. In the
above example, PSL uses the repetition operation [*0:2]--which, when it stands by itself, is a
shorthand for true[*0:2], which will match anything for 0 to 2 cycles--together with the fusion
operator, :, to represent the delay until ack occurs. SVA uses an extended form of the concatenation
operator, ##, to accomplish the same thing. Both have the same meaning.
PSL SVA
always { req[*]; ack } |=> ( req[*] ##1 ack |=>
{ read; drdy; !req; !ack } read ##1 drdy ##1 !req ##1 !ack )
he PSL cover directive and the SVA cover sequence directive both take a sequence argument. All
T
matches of the sequence result in a match. SVA also has a cover property directive, which takes a
property argument. It will have a maximum of one match per attempt. The cover property directive
is similar to the assert property directive, except that failures are not reported.
Assertion Clocking
Assertion Clocking
The way in which clock expressions are specified in PSL and SVA are similar, but there are some
minor differences:
VA infers clocking from the context of the procedural code; PSL does not. For example, the
S
following PSL assertion will be evaluated at every simulator cycle, not on the positive edge of clk:
always @(posedge clk)
begin
// psl example always a=1;
end
Embedding
PSL constructs can be embedded within HDL source text by using special comments in which the
keyword psl is the first token after the comment symbol. For example:
oth line and block comments can be used, if the HDL supports both. A PSL declaration or
B
directive in a line comment can be continued in a subsequent comment line without the psl token.
Because PSL can be embedded using comments, tools that do not support PSL assertions can be
used together with those that do.
SVA constructs are inherently part of the SystemVerilog language, so SVA assertions can be
embedded within any SystemVerilog design. For example:
SystemVerilog Assertions
module M (a,b,reset_n)
...
property P;
@(posedge clk)
disable iff (reset_n) !(a&&b);
endproperty: P
External Modules
PSL constructs can be embedded within a verification unit that is associated with an HDL module.
The associated verification unit is pulled into the compilation process whenever the HDL module
with which it is associated is compiled. For example:
I n a similar fashion, SVA constructs can be placed in a separate module that is then bound to the
design module. For example:
module M (a,b,reset_n)
...
endmodule
For SVA, the module to be bound becomes an instance of the target module--that is, it becomes a
new level of hierarchy. For PSL, if the vunit is bound to an instance, it appears as an instance in
the module to which it is bound.
12
Dynamic ABV Implementation Guidelines
The following examples demonstrate how to get from a requirements specification to assertions. You
can check many requirements by taking advantage of a small subset of assertion constructs.
This appendix provides examples of how to create assertions based on commonly-used phrases that
appear in specifications for a device under verification. It shows efficient implementations for both PSL
and SVA, making it a good reference for comparing and contrasting the PSL and SVA assertion
languages.
This appendix starts by summarizing the steps for constructing an assertion. It then lists many common
phrases that appear in requirement specifications and, for each one, shows how to construct an assertion
that checks the specification. It also notes the implicit property coverage that is provided by the Incisive
tools, and points out where additional coverage metrics are useful.
After showing how to construct properties, this appendix provides a checklist of the types of requirements
to consider checking. It also provides coverage considerations, reuse considerations, performance
implications, and other general tips.
To make adoption easier, you can take advantage of a small subset of assertion constructs right away,
using these templates, then add more assertions later. It is also recommended that you use component
checks from the Incisive Assertion Library (IAL), such as the ones for FIFO behavior and arbitration. For
more information about IAL, see the Incisive Assertion Library Reference .
Creating an Assertion
Creating assertions is easy if you use the following steps:
1. Restate the requirement in the form of "if <>, then <>".
This statement specifies a condition to be checked.
2. D ecide when to check the condition.
The condition you defined becomes the enabling condition for the check, and will be the
expression on the left of the implication operator--that is, it is the if clause of the requirement. The
simulator increments the Checked count when this condition is true. Consider overlapping
conditions that might slow performance. For details, see "Assertion Coding Guidelines".
3. Decide how to express the condition to be checked.
4. N ame your assertion.
Create a name that describes the correct behavior that the assertion is designed to check. Naming
conventions can be useful for readability, and for configuring their operation in different tools. For
details, refer to ABV Methodology in your Incisive verification kit.
5. D ecide which verification directive to use.
For checks, you can use either assert or assume:
Use the assert directive when the property expresses the behavior of the device under
test.
Use the assume directive when the property expresses the behavior of the environment
that generates stimulus to the device under test.
U se the cover directive when the goal is to determine whether the behavior has been
tested by the simulation stimulus or, in the case of formal verification, to determine if the
behavior can possibly occur.
For more information, see "When to Use SVA assert versus cover".
Note: For formal verification, only assertions at the top level of the block being formally
verified can use assume, because these assumptions specify environment constraints for
the formal analysis. Because the top level often varies, the assert directive is
recommended for all assertions, and a naming convention can be used to distinguish
whether it is an assertion or an assumption, relative to the module in which it is
embedded. You can then override the verification directive independently from the code
for that top level when you run formal verification.
6. Decide what type of check to use:
For PSL, decide whether to use always, never, or a one-time check (see "Writing One-
Time Checks in PSL").
For SVA, decide whether to use a one-time check, a concurrent assertion that is checked
on every clock, or an immediate assertion in an alwaysblock.
Note: SVA immediate assertions and PSL never assertions do not provide implicit
coverage.
7. Consider how to clock the assertion.
Often, defining a default clock for the module is easiest. An assertion that is strictly combinatorial-
-for example, has no clock and is never disabled or aborted--will be checked whenever one of the
signals it references changes value. The Checked count will always be 0. Incisive coverage tools
filter out these assertions.
8. C onsider when the assertion must not be checked:
U se the abort or until clause in PSL.
Use the disable iff clause in SVA.
clk Clock
n , n1 , n2 Predefined constants
When a Boolean expression is required, the BoolX and BoolY terms are used. When a sequence
expression is required, the SeqX and SeqY terms are used. The X, Y, and Z terms can be Booleans or
sequence expressions, and are used in the drawings to represent both. It is important to understand
which alternative is applicable, especially for PSL, where type checking determines which implication
operator is used.
The following is a list of the templates that are provided:
Invariants
X must always be 1.
Control signals are always legal values.
X must never occur.
X must always be equal to Y .
Configuration mode must always be valid.
Simple implications
Y occurs when X occurs.
Data signals are valid when the read or write signal transitions low.
Legal status is read from the status register.
Next-cycle response
Y occurs one cycle after X occurs.
Time-bounded responses
Y occurs n cycles after X occurs.
Y must not occur for n cycles after X occurs.
sigX is high for a maximum of n cycles.
sigX is high for a minimum of n cycles.
Y occurs within n cycles of X .
Y must occur within n1 to n2 cycles after X occurs.
Z occurs within n1 to n2 cycles after X or Y occurs.
Y occurs after n cycles with no occurrence of X .
Event-bounded responses
Y occurs before Z after X occurs.
Y occurs until Z after X occurs.
Unbounded responses
Y occurs sometime after X occurs.
One-time checks
The value of parameter X is less than 3.
Invariants
X must always be 1.
BoolX == 1 BoolX == 1
PSL Assertion
X is a Boolean:
// psl BoolX_is_1: assert always (BoolX == 1) abort reset;
SVA Assertion
BoolX_is_1: assert property (
@(posedge clk) disable iff (reset)
(BoolX == 1));
Implicit Coverage
For PSL, the Checked count is incremented every time BoolX or reset change value. The Finished count
is incremented each time the property is checked while BoolX is 1 and reset is low.
For SVA, because all assertions are clocked, the Checked count is incremented at every posedge clk
while reset is low. The Finished count is incremented at every posedge clk where reset is low and
BoolX is one.
PSL Assertion
// psl valid_X_and_Y: assert never
((isunknown(sigX) || isunknown(sigY)) && !reset) @(rose clk);
SVA Assertion
valid_X_and_Y: assert property (
@(posedge clk) disable iff(reset)
(!$isunknown(sigX) && !$isunknown(sigY)) );
Implicit Coverage
When PSL never is used, coverage information is not provided. The Checked count is the number of
posedge clks when reset is low. The Finished count is 0. For SVA, and for PSL when always is used, the
Checked count is incremented at every posedge clk when reset is low. The Finished count is
incremented at every posedge clk when reset is low and X and Y are not unknown.
PSL Assertion
// psl X_must_never_occur: assert
never (X && !reset) @(posedge clk);
Note: If X is a sequence, the term of the sequence must be ANDed with reset .
SVA Assertion
X_must_never_occur: assert property (
@(posedge clk) disable iff (reset)
not(X) );
Implicit Coverage
The Checked count and the Finished count are the number of posedge clks when reset is low.
PSL Assertion
X is a Boolean:
// psl BoolX_eq_BoolY:
assert always ((BoolX == BoolY) abort reset) @(posedge clk);
SVA Assertion
BoolX_eq_BoolY: assert property (
@(posedge clk) disable iff(reset) (BoolX == BoolY) );
Implicit Coverage
The Checked count is the number of posedge clks when reset is low. The Finished count is incremented
at every posedge clk when reset is low and BoolX equals BoolY.
PSL Assertion
// psl valid_mode_X: assert always (
(modeX == 2'b01 || modeX == 2'b10) abort reset @(posedge clk);
SVA Assertion
valid_mode_X: assert property
(@(posedge clk) disable iff(reset)
(modeX == 2'b01 || modeX == 2'b10));
Implicit Coverage
The Checked count is the number of posedge clks when reset is low. The Finished count is incremented
at every posedge clk when reset is low and modeX is 2'b01 or 2'b10.
Simple Implications
{X} |-> Y
PSL Assertion
PSL Assertion
// psl if_X_then_Y:
assert always (({X} |-> Y) abort reset) @(posedge clk);
SVA Assertion
if_X_then_Y: assert property (
@(posedge clk) disable iff(reset) (X |-> Y) );
Implicit Coverage
The Checked count is incremented at every posedge clk when X is true and reset is low. The Finished
count is incremented at every posedge clk when X and Y are both true and reset is low.
D ata signals are valid when the read or write signal transitions low.
Restated: If cs_read or cs_write goes low, data is valid.
PSL Assertion
// psl valid_data: assert always
((fell(cs_write) || fell(cs_read)) -> !isunkown(data)
abort reset) @(posedge clk);
SVA Assertion
valid_data: assert property( @(posedge clk) disable iff (reset)
($fell(cs_write) || $fell(cs_read)) |-> (!$isunknown(data)) );
Implicit Coverage
Implicit coverage tells you how many read and write operations occurred. The Checked count is
incremented at every posedge clk when the read or write signal transitions to low and reset is low. The
Finished count is incremented at every posedge clk when the cs_read or cs_write signal transitions to
low, reset is low, and data is a known value.
PSL Assertion
// psl valid_status: assert always (
(address == `status) && (cs_read == 0) -> (data < 2)
abort(reset)) @(posedge clk);
SVA Assertion
SVA Assertion
status_valid: assert property
(@(posedge clk) disable iff (reset)
((address == `Qstatus) && (cs_read == 0)) |-> (data < 2 ) );
Implicit Coverage
Implicit coverage indicates the number of times the status register is read. The Checked count is
incremented at every posedge clk when reset is low and a read of the status register occurs. The
Finished count is incremented at every posedge clk when reset is low, a read of the status register
occurs, and the data value is less than 2.
Next-Cycle Response
{X} |=> Y
PSL Assertions
X is a Boolean:
// psl if_BoolX_then_Next_Y:
assert always ((BoolX -> next Y) abort reset) @(posedge clk);
X is a sequence:
// psl if_SeqX_then_Next_Y:
assert always ((SeqX |=> Y) abort reset) @(posedge clk);
SVA Assertion
if_X_then_next_Y: assert property (
@(posedge clk) disable iff(reset) (X |=> Y));
Implicit Coverage
The Checked count is incremented when (X and !reset) is true. The Finished count is incremented when
Y and !reset occurs on the cycle after X and !reset.
Time-Bounded Responses
Time-Bounded Responses
PSL Assertions
X is a Boolean:
// psl if_BoolX_then_Next_n__Y:
assert always ((BoolX -> next [n] Y) abort reset) @(rose(clk));
X is a sequence:
// psl if_SeqX_then_Next_n_Y:
assert always ((SeqX |-> { [*n] ; Y } abort reset) @(rose(clk);
SVA Assertion
SVA Assertion
if_X_then_next_Y: assert property (
@(posedge clk) disable iff(reset) (X |-> ##n Y));
Implicit Coverage
The Checked count is incremented when (X and !reset) is true. The Finished count is incremented when
Y occurs on the n th cycle after X, while !reset is true throughout.
PSL Assertions
X is a Boolean
// psl if_X_then_noY_for_n: assert always (
(boolX -> next !boolY[*n]) abort reset) @(posedge clk);
X is a sequence
// psl if_X_then_noY_for_n: assert always (
(seqX |=> !boolY[*n]) abort reset) @(posedge clk);
SVA Assertion
if_X_then_noY_for_n: assert property (
@(posedge clk) disable iff(reset) (X |=> !Y[*n ]) );
Implicit Coverage
The Checked count is incremented on the posedge clk when X is true while reset is low. The Finished
count is incremented on the posedge clk when Y does not occur for n cycles.
PSL Assertion
// psl sigX_high_max_n: assert always (
(rose(sigX) -> {sigX[*1:n]; !sigX}) abort reset) @(posedge clk);
SVA Assertion
sigX_high_max_n: assert property ( @(posedge clk) disable iff(reset)
($rose(sigX) |-> ( sigX[*1:n] ##1 !sigX )));
Implicit Coverage
Implicit Coverage
The Checked count is incremented when sigX rises and reset is low. The Finished count is incremented
at the first posedge clk when X goes low, assuming X was high for n cycles or less.
PSL Assertion
// psl sigX_high_min_n: assert always (rose(sigX) -> sigX[*n] abort reset) @(posedge
clk);
SVA Assertion
SVA Assertion
sigX_high_min_n: assert property ( @(posedge clk) disable iff(reset)
$rose(sigX) |-> sigX[*n] );
Implicit Coverage
The Checked count is incremented on the posedge clk when sigX rises and reset is low. The Finished
count is incremented when sigX is active n times, assuming that reset remained low throughout.
Implicit Coverage
The Checked count is incremented on the posedge clk when (X or Y) is true and reset is low. The
Finished count is incremented when Z occurs exactly n cycles after either X or Y occurs while reset
remains low.
PSL Assertion
// psl if_X_then_Y_within_n:
assert always (({X} |-> {Y within [*n]}) abort reset) @(rose(clk));
SVA Assertion
if_X_then_Y_within_n: assert property
(@(posedge clk) disable iff(reset)
X |-> (Y within 1'b1[*n]));
Implicit Coverage
The Checked count is incremented on the posedge clk when (X and !reset) is true. The Finished count
is incremented on the posedge clk when (Y and !reset) occurs on the n th cycle after X.
PSL SVA
PSL Assertions
X is a Boolean
// psl if_BoolX_then_Y_within_n1_to_n2: assert always (
(boolX -> {[*n1 :n2 ]; Y}) abort reset) @ rose(clk);
X is a sequence:
// psl if_SeqX_then_Y_within_n1_to_n2: assert always (
(seqX |-> {[*n1 :n2 ]; Y}) abort reset) @ rose(clk);
SVA Assertion
if_X_then_Y_within_n1_to_n2: assert property(
@(posedge clk) disable iff(reset) (X |-> ##[n1 :n2 ] Y));
Implicit Coverage
The Checked count is incremented on the posedge clk when X is true while reset is low. The Finished
count is incremented on the posedge clk if Y occurs when the assertion is active, assuming that reset
remains low.
PSL Assertions
X and Y are Booleans
// psl assert_if_XorY_then_Z_n1_to_n2_cycles_after: assert
always ((BoolX || BoolY) -> {[*n1:n2]; Z}) abort reset) @(rose(clk));
X or Y is a sequence
// psl assert_if_XorY_then_Z_n1_to_n2_cycles_after: assert
always ({{SeqX} | {SeqY}} |-> {[*n1:n2]; Z}) abort reset) @(rose(clk));
SVA Assertions
X and Y are Booleans
assert_if_BoolXorY_then_Z_n1_to_n2_cycles_after: assert property (
@(posedge clk) disable iff(reset) ((BoolX || BoolY) |-> ##[n1:n2] Z));
X or Y is a sequence
Implicit Coverage
The Checked count is incremented on the posedge clk when (X and !reset) or (Y and !reset) is true.
The Finished count is incremented on the posedge clk when Z occurs the first time between the n 1 st and
n 2 nd time, assuming !reset throughout.
PSL Assertion
X is a Boolean
// psl assert_if_notX_for_n_then_Y: assert
always (({rose(!boolX);!boolX[*n-1]} |=> Y) abort reset) @(posedge clk);
SVA Assertion
SVA Assertion
X is a Boolean
assert_if_notX_for_n_then_Y: assert property (
@(posedge clk) disable iff(reset)
$rose(!boolX) ##1 !boolX[*n-1] |=> Y );
Implicit Coverage
The Checked count is incremented on the posedge clk when X transitions low and stays low for n cycles.
The Finished count is incremented on the posedge clk when X remains low for n clocks followed by Y,
while !reset is true.
Event-Bounded Responses
Event-Bounded Responses
PSL Assertion
X is a Boolean
// psl assert_if_X_then_Y_before_Z: assert
always (({rose(boolX)} |-> Y before Z) abort reset) @(posedge clk);
SVA Assertion
X is a Boolean
assert_if_X_then_Y_before_Z: assert property (
Implicit Coverage
The Checked count is incremented on the posedge clk when X transitions high while reset=0. The
Finished count is incremented on the posedge clk after X transitions high and Y && !Z occurs, assuming
reset=0 and Z=0, because X transitioned high. The Failed count is incremented on the posedge clk when
X transitions high and Z=1 occurs before or at the same time that Y=1, assuming that reset=0 and Z=0,
because X transitioned high.
PSL Assertion
X is a Boolean
// psl assert_if_X_then_Y_until_Z: assert
always (({rose(boolX)} |-> Y until Z) abort reset) @(posedge clk);
SVA Assertion
X is a Boolean
assert_if_X_then_Y_until_Z: assert property (
@(posedge clk) disable iff(reset)
$rose(boolX) |-> boolY[*0:$] ##1 boolZ );
Implicit Coverage
The Checked count is incremented on the posedge clk when X transitions high while reset=0. The
Finished count is incremented on the posedge clk after X transitions high and Z occurs, assuming
reset=0 and Y=1, because X transitioned high. The Failed count is incremented on the posedge clk when
X transitions high and Y=0 occurs before or at the same time that Z=1 occurs, assuming reset=0 and Z=0,
because X transitioned high.
Unbounded Responses
PSL Assertions
X is a Boolean
// psl assert_if_BoolX_eventually_Y:
assert always ((BoolX -> next eventually! Y) abort reset) @(posedge clk);
X is a sequence
// psl assert_if_SeqX_eventually_Y:
assert always ((SeqX |=> eventually! Y) abort reset) @(posedge clk);
SVA Assertion
assert_if_X_then_next_Y: assert property (
@(posedge clk) disable iff(reset) (X |-> ##[1:$] Y));
Implicit Coverage
The Checked count is incremented on the posedge clk when (X and !reset) is true. The Finished count
is incremented on the posedge clk when Y occurs, assuming !reset throughout.
PSL SVA
BoolX -> next{(!boolX && !boolZ) X |=> (!BoolZ && !BoolX)[*0:$] ##1 Y
[*];Y}
PSL Assertion
// psl if_X_then_no_XorZ_until_Y: assert always(
(BoolX -> next{(!boolX && !boolZ)[*];Y}) abort reset) @(rose(clk));
SVA Assertion
if_X_then_no_XorZ_until_Y: assert property (
@(posedge clk) disable iff(reset)
(BoolX |=> (!BoolZ && !BoolX)[*0:$] ##1 Y) );
Implicit Coverage
The Checked count is incremented on the posedge clk when (X and !reset) is true. The Finished count
is incremented on the posedge clk when the assertion is active and Y occurs.
One-Time Checks
PSL Assertion
// psl ParamXlessthan3: assert (X < 3) @rose(clk);
SVA Assertion
Initial
ParamXlessthan3: assert(X < 3);
Implicit Coverage
Checked and Finished counts will be 1.
Check that all registers can be read from and/or written to, and, where possible, check that they
operate correctly.
Check that inputs and outputs behave as described in the specification, especially handshakes.
You can derive relationships to test from the waveforms provided in the specification.
C heck bus protocols--for example, required patterns, disallowed patterns, and transaction modes.
C heck that FSMs implement the desired response by writing assertions that describe the behavior
of their outputs. These assertions are especially useful for formal analysis.
For example, if an FSM is designed to ensure that the minimium packet size is 64 bytes, check that
the resulting packet is minimally 64 bytes.
Note: D o not write control-oriented assertions about the states of a state machine. States can
generally be verified by a visual inspection of the code, so such assertions add little value. Derive
assertions from the functional specification, not the implementation.
C heck that all corner cases, such as minimum and maximum sizes, waits, and minimum IFG, are
handled properly.
D escribe all corner cases and tricky areas that need to be tested, such as minimum and maximum
sizes, maximum wait states, minimum gaps, and full and empty FIFO levels.
It is best that designers write these assertions while they are creating the code, when possible
corner cases are fresh in their minds.
Make sure that all legal modes of the chip have been exercised
When the device is not in reset condition
After the device has been configured
Make sure that all legal register bit combinations have been exercised in normal operation, for all
registers, including control and status registers.
C ontrol register coverage might already be provided by the implicit coverage of related assertion
checks.
Ensure that all types of data transactions, handshakes, and arbitration have occurred.
In a property file that is bound to the design (PSL vunit or SVA bind)
Pro Always travels with the design. No need to modify the Component is portable.
design.
Assertions that document behavior Parser complains if the
can be placed near the logic with Easy to categorize file is missing, because it
which it is associated. assertions for is instantiated.
performance
One file contains all of the information.
optimizations.
Easy to separate
auxiliary code from
design code.
Con Must guard that supporting HDL code Multiple files are More work to instantiate
does not get synthesized or affect required. the assertions in the
code coverage results. design.
Parser will not
Assertions can clutter the RTL. complain if the file is An extra level of hierarchy
missing. adds a little complexity to
any analysis.
Multiple files are required.
In general, embed in the design those assertions that are specific to a design and are added by the designer, so they travel
with the design. Place interface assertions in a separate verification component, so they can be used across designs.
Sequences that involve [=] repetitions or ranges of repetition such as [*1:$] might
continue matching indefinitely, starting new checks.
Avoid extraneous enables--use the rose, fell, or stable functions to enable an assertion
check.
Sequential assertions typically have an enabling condition that must be true in order to check
the sequence. When the enabling condition is true in successive cycles, the assertion tracks
the overlapping behavior, which takes unnecessary time, and might produce unexpected
results.
For example, the following assertion starts tracking the behavior for every clock in which request is high,
although all checks will be satisfied by the same grant:
or in SVA:
Beware of signals that might start high and never fall when using rose to start the
checking of a property. One safeguard is to use $rose(request && !reset) instead
of $rose(request).
Avoid compound non-determinism--sequences that involve successive terms that have
variable repeats, such as b[*3] followed by c[*3].
In this example, if b and c are high simultaneously for three cycles, the directive needs to track
the following, separately and in parallel:
b[*3] followed by c[*0]
b[*2] followed by c[*1]
b[*1] followed by c[*2]
b[*0] followed by c[*3]
If the intent is to look for c only after b goes low, the following is much more efficient:
b[*3] followed by (not b and c[*3])
In PSL, do not use always x -> never y. For details, see "Using the PSL always and never
Operators".
Avoid large numbers in the argument of the prev() built-in function. For example,
prev(x,100) means the value of x at 100 clocks previous to the current clock cycle. This can
alternately be implemented with a little auxiliary HDL.
C onsider ahead of time whether you want all assertions to be enabled all of the time.
Assertions can be enabled and disabled by module (scope), by name, by verification
directive, and by omitting an external file. These techniques are generally sufficient, but
Verilog ifdefs and VHDL generates can allow you to further group categories of assertions.
To reuse properties at different levels of abstraction, specify them in terms of interface signals, so
they do not depend on implementation-dependent signals.
Create parameterized properties and sequences, and place them in SystemVerilog packages that
can be used throughout a design team and across projects. See "Using Packages for SVA".
Use descriptive names for properties and sequences. It is often beneficial to define commonly used
sequence elements, and create properties by combining them.
U se assertion libraries for commonly-used components in the design, like FIFOs and arbiters.
IAL is one such library. Libraries provide prepackaged assertions and coverage points. These
libraries are also a good reference for learning how to use assertion languages. For more
information about IAL, see the Incisive Assertion Library Reference.
Simplify your assertions by using auxiliary code. It provides a simpler learning curve and the result
is sometimes more readable to others. For example:
-- Do not overflow FIFO.
--
Where to start adding assertions, and how many to add, often depend on the maturity of the
design. Here are some guidelines:
For mature designs that are well tested, consider adding interface assertions that check to see
whether the device is connected properly.
For mostly verified designs, start adding assertions where you have seen problems in the past,
and in tricky areas, where there will be the most value.
For new designs, all assertions provide value.
To avoid false assertion firing in simulation and formal analysis, make storage elements (flip-flops)
resettable.
In PSL, use a default clock of rose(clk) in simulation to avoid issues at time 0 when signals
transition from X. Change the default clock to posedge(clk) for formal analysis.
In SVA, use $assertoff() at the start of simulation to prevent firings at t=0.
Some people find it convenient to use naming conventions to identify assertion categories. For
more recommendations, refer to the Incisive Plan-to-Closure Methodology: Assertion-Based
Verification document.
13
Glossary of ABV Terms
Assertion statement
A statement that a design must exhibit the behavior specified by a given property. Also, a directive
to verification tools to verify that the design does not fail to satisfy the specified property, for some or
all possible behaviors of the design.
A ttempt
The function of a design over time. Design behavior is often partitioned into combinational and
sequential behavior. In this context, timing is typically abstracted, so that in various situations
instantaneous, cycle-level, or higher-level abstractions of time are considered.
C oncurrent assertion
An assertion that runs concurrently with design components, so that it continuously monitors design
behavior.
C ondition
A situation in which a set of variables or signals satisfy some predicate that specifies a relationship
among their respective values at some instant in time. A condition is often represented by a
Boolean expression, which evaluates to True when the specified relationship is satisfied. For
example, the expression (A==B) is satisfied when the values of A and B are the same.
D UV
Design under verification. Also called DUT for design under test.
Fails
After the enabling condition of an assertion occurs, the fulfilling condition does not occur, or is
incomplete.
False
The values 1'b0, 1'bx, 1'bz, or any value interpreted as False when it is the value of an if statement
condition.
Finishes
After the enabling condition of an assertion occurs, the fulfilling condition occurs.
Immediate assertion
A procedural assertion that can check only a single combinational condition; it cannot involve
temporal operators.
Match
A sequence matches a trace if and only if the trace satisfies the sequence.
Occurs
A sequence occurs starting in some cycle and finishing in a (usually later) cycle if the trace starting
and ending in the respective cycles satisfies the sequence.
Property
A specification of the temporal relationship among a set of elements, each of which can be a
condition, sequence, or (sub)property. A property specifies the behavior of a portion of a design or
its environment.
Examples:
(ctr==0 before ctr==1)
never {ctr==1; ctr==3}
Procedural assertion
An assertion that is evaluated when the flow of control in a procedural block of code reaches the
assertion.
Satisfy
A state satisfies a condition if and only if the condition is True in that state.
A trace satisfies a sequence if and only if some behavior described by the sequence occurs in the
trace.
A trace satisfies a property if and only if the behavior described by the property occurs in the trace.
Example:
state (a==1, b==2, c==3) satisfies condition (a+b <= c)
This trace
SERE
A series of conditions that occur at successive times, particularly when the times are indicated by
active clock edges. Also, a form of extended regular expression that defines such a series of
conditions, involving operators that indicate concatenation, repetition, and co-occurrence of
elements, each of which can be a condition or a (sub)sequence. A sequence typically specifies the
behavior of a set of signals or variables, as viewed at successive clock edges.
Example:
{ctr==0; ctr==1; ctr==2; ctr==3}[*]
State
True
The value 1'b1, or any value interpreted as True when it is the value of an If statement condition.
A Property is True in the first cycle of a trace that satisfies the Property.
For implication and conditional properties, the value is vacuously true when the left-hand side of the
implication is true.
Vacuous
A vacuous pass occurs when a property is not checked, either because it is not enabled or because
it is discharged.