Modports & Assertions
Modports & Assertions
• The modport (module ports) groups and specifies the port directions to the
signals declared within the interface.
• modports are declared inside the interface with the keyword modport.
• By specifying the port directions, modport provides access restrictions.
• The keyword modport indicates that the directions are declared (as if inside the
module).
• modport item declared as input is not allowed to be driven or being assigned.
Any attempt to drive leads to a compilation error.
• The Interface can have any number of modports, the signals declared in the
interface can be grouped in many modports
• Modports can have, input, inout, output, and ref
2
• Note that when you make an instance from the DUT or the testbench, you select
the convenient modport, by the following syntax:
interface_name.modport_name
3
• T
4
• The timing between the testbench and the design must be carefully orchestrated.
You need to drive and receive the synchronous signals at the proper time in
relation to the clock.
• Drive too late or sample too early, and your testbench is off a cycle.
• Even within a single time slot (for example, everything that happens at time 100
ns), mixing design and testbench events can cause a race condition, such as when
a signal is both read and written at the same time. Do you read the old value, or
the one just written?
• SystemVerilog has several constructs to help you control the timing of the
communication.
5
• Module ports and interfaces by default do not specify any timing requirements or
synchronization schemes between signals.
• A clocking block defined between clocking and endcocking does exactly that.
• It is a collection of signals synchronous with a particular clock and helps to
specify the timing requirements between the clock and the signals.
• This would allow test writers to focus more on transactions rather than worry
about when a signal will interact with respect to a clock.
• A testbench can have many clocking blocks, but only one block per clock.
• The delay_value represents a skew of how many time units away from the clock
event a signal is to be sampled or driven.
• If a default skew is not specified, then all input signals will be sampled #1step
and output signlas driven 0 ns after the specified event.
6
• SystemVerilog adds the clocking block that identifies clock signals, and captures
the timing and synchronization requirements of the blocks being modeled.
• A clocking block assembles signals that are synchronous to a particular clock,
and makes their timing explicit.
• The clocking block is a key element in a cycle-based methodology, which
enables users to write testbenches at a higher level of abstraction. Simulation is
faster with cycle based methodology.
• Depending on the environment, a testbench can contain one or more clocking
blocks, each containing its own clock plus an arbitrary number of signals.
• If an input skew is specified then the signal is sampled at skew time units before
the clock event. If output skew is specified, then output (or inout) signals are
driven skew time units after the corresponding clock event. A skew must be a
constant expression, and can be specified as a parameter.
• If skew is not specified, default input skew is 1 step and output skew is 0.
• Specifying a clocking block using a SystemVerilog interface can significantly
reduce the amount of code needed to connect the TestBench without race
condition (races are explained later).
7
• An interface block can use a clocking block to specify the timing of synchronous
signals relative to the clocks.
• Any signal in a clocking block is now driven or sampled synchronously, ensuring
that your testbench interacts with the signals at the right time.
• If you have multiple clock domains, an interface can contain multiple clocking
blocks, one per clock domain, as there is single clock expression in each block.
• Typical clock expressions are @(posedge clk) for a single edge clock and @(clk)
for a DDR (double data rate) clock.
• Once you have defined a clocking block, your testbench can wait for the
clocking expression with @<interface name>.cb rather than having to spell out
the exact clock and edge.
• Now if you change the clock or edge in the clocking block, you do not have to
change your testbench.
8
• Here the test bench uses signals that are synchronized by the clocking block
named cb.
• Note that the values of the testbench outputs () are assigned values at the times
given the table below, however they are actually assigned 2 ns after the rising
edge of the clock as specified by the clocking block.
Output name Time of assignment Actual driving time
read 0 22
enable 0 22
addr 0 22
addr 30 62
addr 95 102
• Also note that the data coming from the DUT is sampled 10ns before the rising
clock edge. So the sampled value is not the value just before the clock edge, but
the existing value 10 ns before the edge.
• The samples value appears at the rising clock edge. For example, the value
appearing at time 60ns, is the DUT data value at time 50ns.
9
• Ver
10
• Assertions are pieces of code that check the relationships between design signals, either
once or over a period of time. You can create temporal assertions about signals in your
design using SystemVerilog Assertions (SVA).
• The most familiar assertions look for errors such as two signals that should be mutually
exclusive or a request that was never followed by a grant. These error checks should stop
the simulation as soon as they detect a problem.
• Assertions are instantiated similarly to other design blocks and are active for the entire
simulation.
• The simulator keeps track of what assertions have been triggered, and so you can gather
functional coverage data on them.
• There are two types of assertions: Immediate Assertions, and Concurrent Assertions.
These two types will be explained in the following slides.
11
• Here, the designer mistakenly made the Master Reset Synchronous.
• As shown in the waveform, resetting the output is synchronized with the edge of
the clock. The specifications states that the reset is an asynchronous reset.
• How can assertions help revealing this error?
12
• The immediate assertion statement is a test of an expression performed when the
statement is executed in the procedural code.
• Immediate assertions are simple non-temporal domain assertions that are
executed like statements in a procedural block.
• The assertion condition is non-temporal, which means its execution computes
and reports the assertion results at the same time.
• If the expression evaluates to X, Z or 0, then it is interpreted as being false and
the assertion is said to fail.
• Otherwise, the expression is interpreted as being true and the assertion is said to
pass.
• In the above code we are using the assertion to test whether the output Q is reset
immediately after MR is activated.
• The message says: on line 16 of the file testbench.sv, the assertion
top.u2.assertion1 started at 3 ns to check the signal x.Q, failed.
13
• An immediate assertion has optional then and else clauses.
• If you want to augment the default message, you can add your own.
• The above example shows how to create a custom error message in an immediate
assertion.
• If Q does not have the expected value. you'll see an error message as shown
above.
• SystemVerilog has four functions to print messages:
$info,
$warning,
$error
$fatal.
• You can use the then-clause to record when an assertion completed successfully.
14
• In System Verilog, severity of assertion messages is classified by using four
system tasks. These are $fatal, $error, $warning and $info.
• If an action block is specified, user-defined severity can be created by using
these system tasks.
• Every assertion failure has an associated severity which can be specified in the
fail-statement block.
• If assertion does not have a fail-statement block, then by default $error system
task will be called with default message.
• The syntax of severity system tasks except $fatal is identical to $display, but for
$fatal, an optional error code can be added as a first argument before the
message to be displayed.
$fatal: The $fatal ends the simulation, that means it has an implicit call of $finish.
$warning: This generates a run time warning message, without terminating the
simulation
$error: This generates a run time error that does not terminate the simulation.
$info: This generates information to the user and indicates that the assertion failure
carries no specific severity.
15
• The other type of assertions is the concurrent assertion that you can think of as a
small model that runs continuously, checking the values of signals for the entire
simulation.
• Concurrent assertions are written as follows: assert property, unlike immediate
assertions which are written as follows: assert
• The behaviour of a design may be specified using statements similar to these:
A Request should be followed by an Acknowledge occurring no more
than two clocks after the request is asserted. You can check that using an
assertion like this one:
assert property (@(posedge clk) Req |-> ##[1:2] Ack);
We use the implication operator |-> to express some event implies some
other thing. ##[1:2] means after one or two clock cycles
16
• Here is a simple assertion to check that whenever the load line is active, then at
the very next rising edge of the clock the counter is loaded by the values found
on the P inputs.
• It is clear that there is an error in the design, as the value loaded is P+1 not P, so
the assertion fails.
• It is also clear that, as the assertion is a concurrent assertion, it is active during
the whole simulation time, and whenever it fails an error message is issued.
• In the shown simulation the assertion fails twice. One time at 25 ns, and the
second time at 75 ns.
• In the previous slide we used “|->” as an implication operator, whereas in the
above example we used “|=>”. So is there any difference between them ?
17
• The implication is equivalent to an if-then structure.
• The left-hand side of the implication is called the “antecedent” and the right-
hand side is called the “consequent.”
• The antecedent is the gating condition. If the antecedent succeeds, then the
consequent is evaluated.
• The implication construct can be used only with property definitions.
• There are 2 types of implications:
Overlapped implication
Non-overlapped implication
18
• The overlapped implication is denoted by the symbol |->.
• If there is a match on the antecedent, then the consequent expression is evaluated
in the same clock cycle.
• The shown property checks that, if signal “a” is high on a given positive clock
edge, then signal “b” should also be high on the same clock edge.
19
• The non-overlapped implication is denoted by the symbol |->.
• If there is a match on the antecedent, then the consequent expression is evaluated
in the next clock cycle.
• The shown property checks that, if signal “a” is high on a given positive clock
edge, then signal “b” should also be high on the next clock edge.
20
• If there is a match on the antecedent, then the consequent expression is evaluated
after certain number of cycles expressed by ## followed by the number of cycles.
21
• If there is a match on the antecedent, then the consequent expression is evaluated
after certain range of cycles expressed by ## followed by a range of cycles.
• In the above example, if you want b to be high in the same clock cycle, or withn
4 cycles, we write the range as ##[0:4]
22
• The upper limit of the timing window specified in the right-hand side can be
defined with a “$” sign which implies that there is no upper bound for timing.
• This is called the eventuality operator. The checker will keep checking for a
match until the end of the simulation.
• The shown property checks that, if signal a is high on a given positive clock
edge, then signal b will be high eventually starting from the next clock cycle.
23
• Here we have a property to check if a signal b remains low for at least 3 clock
cycles.
24
• When the system task $fell(b) is evaluated at certain clock edge, it compares the
value of b at this clock edge with its value at the previous clock edge. If the new
value is 0, and the old value is nonzero, then $fell evaluates to true.
• When the system task $stable(b) is evaluated at certain clock edge, it compares
the value of b at this clock edge with its value at the previous clock edge. If the
two values are the same, then $stable evaluates to true.
• $stable(b)[*4] means $stable should be true for 4 consecutive times.
25
• When
26
• When the system task $changed(a) is evaluated at certain clock edge, it compares
the value of a at this clock edge with its value at the previous clock edge. If the
the two values are different, then $changed evaluates to true.
27
• Ver
28
• T
29
• T
30
• T
31