Clocking Blocks:
Guidelines to follow
1.
When
using a clocking block, the testbench must access only its clockvars and should
never access the clocking signals directly.(CB_name.Clock_var_name)
clocking
wr_cb@(posedge clock);
default input #1 output #1;
============Clocking Var’s==============
output wr_address;
output data_in;
output write;
endclocking:
wr_cb
2.
Testbench
code should synchronize itself to a clocking block’s clock event by waiting for
the clocking block’s own named event, NOT by waiting for the raw clock event.
·
Testbench code that uses a
clocking block should never synchronize itself to the raw clock event
such as @(posedge
clock). This would give rise to unexpected behavior of
input sampling.
// GOOD
testbench procedural code – Wait on clocking block event
@ (IF_name.CB_name) //Do this
valid_result = IF_name.CB_name.Clock_var;
...
...
// BAD
testbench procedural code – Wait on raw event
@(posedge clock) // DON’T DO THIS
unreliable_result
= IF_name.CB_name.Clock_var;
·
REASON 1: The name of a clocking block
(and, therefore, of its named event) can be chosen to reflect the
testbench-facing effect of the clock.
Eg.
clocking video_pixel_clk @(negedge vClk);
·
The clocking block hides the
clock’s edge polarity from the testbench. If the testbench carefully uses @video_pixel_clock everywhere, instead of @(negedge vClk), then future changes to
the clock’s name or polarity can be accommodated simply by changing our
clocking block’s definition.
3.
Write to output clockvars
using the clocking drive operator <=. Never try to write an output clockvar using simple assignment =
·
Testbench obtains the values of
the input clocking signals as they were at a time before the clock event,
with the actual time specified by the clocking skew(input #1). The
testbench can then use those “pre-clock” values to compute appropriate stimulus
for the DUT.
·
After the clock event has
already happened, we do not wish to risk hold time violations by applying new
stimulus immediately. Instead, we apply our new stimulus some time after the
clock event, so that it is stable and ready for the next clock.
·
simple_CB.to_DUT <=
new_stimulus; // Clocking drive
·
Driving the output clocking
var’s with use of NBA as actually known as clocking drive.
·
According to the SystemVerilog
LRM, it is illegal to write to an output clockvar using the regular assignment
operator =
·
The clocking block’s timing
skews do not affect what happens if you access the original signals directly.
Timing skews are relevant only when the testbench makes access through the
clocking block’s clockvars.
4.
Use input#1step unless
you have a special reason to do otherwise. It guarantees that your testbench
sees sampled values that are consistent with the values observed by your
SystemVerilog assertions, properties and sequences.
·
The default skew for clocking
block input sampling, if no skew is explicitly specified, is input #1step.
·
Delay specification indicates
that the signal’s value is to be sampled just before the simulation time
at which the clock event occurs. “just before” means that the signal is sampled
before any activity at the time of the clock event, but after any
earlier simulation activity. For example, clock event occurs at time 15ns.
Suppose, too, that there was some simulation activity (code execution, signal
value changes, etc) at time 14.5ns, and nothing happened between those two
times. input#1step sampling requires the simulator to report the value of our clocking
block input signal as it was during that idle time between 14.5ns and 15.0ns.
·
input#1step yields exactly the
same value as you would obtain by using the $sampled system function at
the moment of the clock event. This is the same value that is sampled for
the signal if it appears in a SVA property or sequence.
5.
Use non-zero output skew
values in your clocking blocks to make waveform displays clearer, and to avoid
problems caused by clock network delays in gate level simulation.
· The default output skew for a
clocking block is output#0.
· This skew specification causes
the driven signal to be updated during execution of the Re-NBA scheduling
region of the same simulation timestep in which the clock event occurred.
· This behavior is closely
similar to the effect of an ordinary non-blocking assignment (NBA) executed on
the clock event, but it will happen after all such NBAs have completed.
6.
Never use input#0
in your clocking blocks.
· input#0 sampling delay
specification causes the clocking block to sample an input signal in the
Observed region of the SystemVerilog scheduler.
· The Observed region occurs very
late in the events queue, even later than the NBA region, and therefore input#0
sampling can see the new values of register outputs after they have been
updated by NBA assignments executed at the clock edge.
·
input#0 sampling allows our
testbench a “sneak preview” of the value of a signal after the effects of the
current clock. Normally your testbench would not be able to see that new value
until the next clock.
Notes:
·
If a clocking block output or inout drives
a net, the driven value will automatically initialize to 'z (all
high-impedance).
·
When a signal is driven by more than one
clocking block output, that signal should be a variable.
·
Testbench code can read an input clockvar,
but cannot write to it. Perhaps more surprisingly, testbench code can drive
(write to) an output clockvar, but cannot read that clockvar to inspect its
value.
·
When user code reads an inout clockvar it
is in fact reading a corresponding input clockvar; by contrast, when user code
drives an inout clockvar it is in fact driving a corresponding output clockvar.
·
Declare your clocking block in an
interface. Expose the clocking block, and any asynchronous signals that are
directly related to it, through a modport of the interface. In your
verification code, declare a virtual interface data type that can reference
that modport.
·
Use your clocking block to establish signal
directions with respect to the testbench. Do not add the raw signals to a
testbench-facing interface's modport.
modport master_mp(clocking master_cb, input
RESET_async_n,
input READY,
output VALID, DATA); // WRONG
– exposes raw signals
·
Clocking blocks should usually be accessed
through a virtual interface variable pointing to a modport of the clocking
block’s enclosing interface.
·
In that situation, each clockvar must be
accessed using the three-part dotted name virtual_interface.clocking_block.clockvar
------------------------------------------------------------------------------------------------
Reference: SNUG Austin 2012 "Taming Testbench Timing":
http://www.verilab.com/
No comments:
Post a Comment