Category Archives: System Verilog

Vacuous success for unbounded window in SystemVerilog Assertions

Today I’d like to unleash few of the unsung features SystemVerilog assertions. As we all know the power of assertions for quickly targeting using vivid types of properties and sequences. Apart from formal verification, even in a SV/UVM based randomized verification, it is always preferable to guard all the generic blocks like arbiters, FIFOs and other custom logic by assertions. This helps in safe guarding design for any corner cases which may involve significant debug cycle.

But one feature of assertions that all of us stumble upon is vacuous passing feature. The implication (|-> or |=>) provides a capability of vacuous passing of assertions. 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. If the antecedent does not succeed, then the property is assumed to succeed by default. This is called a “vacuous success.” While implication avoids unnecessary error messages, it can produce vacuous successes.

This implies that is an assertion is triggered by satisfying antecedent condition and if the consequent condition never gets satisfied (probably due to use of ‘eventuality’ operator), then the assertion never fails. Consider the following scenario:

We have an arbiter where grant can be asserted after N number of cycles of assertion of request. To verify that we get a grant for each of request, we would have something like following property:

property check();

    @(posedge clk)

    req |-> ##[0:$] gnt;

  endproperty

But here, if the request is asserted and we never get a grant from our arbiter, then this assertion will pass vacuously at the end of sim. Even there could be a testbench timeout which can tell us that something went wrong. Debugging a reason of testbench timeout can be tedious and counter intuitive many times. But if we somehow make this assertion fail during vacuous pass, then it would help greatly in saving debug cycle.

SystemVerilog LRM provides a “strong” operator to notify the assertion failure. As per IEEE 1800-2017, Section 16.12.1:

strong(sequence_expr) evaluates to true if, and only if, there is a nonempty match of the sequence_expr.

It implies that we could exploit the following assertion to match it exactly and eliminate vacuous passes at the end of test. Here, if request is asserted, then we are waiting for at least one nonempty match for grant. The assertion will fail if we see a request and never see a grant.

property check();

    @(posedge clk)

    req |-> strong(##[0:$] gnt);

  endproperty

Since only one match of a sequence_expr is needed for strong(sequence_expr) to hold, a property of the form strong(sequence_expr) evaluates to true if, and only if, the property strong(first_match(sequence_expr)) evaluates to true.

Another way to disable vacuous pass is using system command $assertvacuousoff as described in “Assertion control system tasks” in LRM section 20.12. This works similar to $assertcontrol but at a specifically to disable the vacuous passing.

Note that by default Synopsys VCS does not enable liveliness operators for compilation. We need to add “-assert svaext” to enable these operators.

There exists other operators like s_eventually, eventually etc, which can also be good to use. Refer to the below pages for more information on liveliness checking using assertions.

  1. The power of SVA in SystemVerilog.
  2. Doulos liveliness check properties.
  3. SVA FV tutorial.

Hope that this post helps you in easing out the debug cycles… Happy Diwali..!!

SystemVerilog: Rules for Width Casting and Padding Type

Many a times while making some code in RTL design and testbenches, there arises a need to width-cast a variable/signal into some other type. In SystemVerilog, the width-casting is done by a tick () operator. No, I am not going to explain different types of casting in this post but this write-up is dedicated to some trivial errors that can arise while using width-cast that can result in long hours of debugging…

The SystemVerilog 1800-2012 LRM, Section 6.24.1 describes cast operator as follows:

“If the casting type is a constant expression with a positive integral value, the expression in parentheses shall be padded or truncated to the size specified…

The signedness shall pass through unchanged, i.e., the signedness of the result shall be the self-determined signedness of the expression inside the cast”.

The simple looking statement has a deep meaning. The above snippet makes a good point about the signedness of the result. Let’s take a couple of examples:

Example #1, using “int” type

As “int” type is signed by LRM definition at section 6.11, the MSB of the expression in parentheses dictates the padding. If MSB is zero, there will be zero  padding, and if MSB is one, there will padding with ones.

module top ();

bit clk;


initial begin #15 clk =1 ; #15 $display ("vl_q1 = %h, vl_q2 = %h", u_test.vl_q1, u_test.vl_q2);


$finish; end


test u_test (.clk (clk));


endmodule

module test (input clk);
int  vl_d = 7;
int vl_q1, vl_q2;

always @ (posedge clk) begin
vl_q1 <= 3'(vl_d) ; //MSB is 3rd bit and is 1 - padding with ones
end

always @ (posedge clk) begin
vl_q2 <= 4'(vl_d);  // MSB is 4th bit and is 0 - padding with zeroes
end
endmodule

%vcs -sverilog t.v -R

Output: Compiler version N-2017.12-SP2-8; Runtime version N-2017.12-SP2-8;  Mar 27 05:00 2019

vl_q1 = ffffffff, vl_q2 = 00000007

As we can see in the above output,

  1. The signal v1_q1 is signed-extended with all 1’s since the MSB (3rd bit) of v1_d was 1’b1.
  2. The signal v1_q2 is signed-extended with all 1’s since the MSB (4th bit) of v1_d was 1’b0.

The result entirely depends on which bit of RHS is used in cast. Let’s see a couple of more instances.

Example #2, using “logic” type

If you use “logic” type which is not signed, there will be zero padding, regardless of MSB.

module top ();
bit clk;
initial begin #15 clk =1 ; #15 $display ("vl_q1 = %h, vl_q2 = %h", u_test.vl_q1, u_test.vl_q2);
$finish; end
test u_test (.clk (clk));
endmodule

module test (input clk);
logic  [1:0]  vl_d = 3;
logic  [31:0] vl_q1, vl_q2;

always @ (posedge clk) begin
vl_q1 <= 2'(vl_d) ;
end

always @ (posedge clk) begin
vl_q2 <= 3'(vl_d);
end

endmodule
%vcs -sverilog t.v -R
Compiler version N-2017.12-SP2-8; Runtime version N-2017.12-SP2-8;  Mar 27 05:07 2019
vl_q1 = 00000003, vl_q2 = 00000003

Example #3, using “logic signed” type

If you use “logic signed “ type, the MSB /sign bit dictates the padding, similar to type “int.

module top ();
bit clk;
initial begin #15 clk =1 ; #15 $display ("vl_q1 = %h, vl_q2 = %h", u_test.vl_q1, u_test.vl_q2);
$finish; end
test u_test (.clk (clk));
endmodule

module test (input clk);
logic signed [1:0]  vl_d = 3;
logic  [31:0] vl_q1, vl_q2;

  always @ (posedge clk) begin
vl_q1 <= 2'(vl_d) ;
end

  always @ (posedge clk) begin

    vl_q2 <= 3'(vl_d);  

  end

endmodule

%vcs -sverilog t.v -R

Compiler version N-2017.12-SP2-8; Runtime version N-2017.12-SP2-8;  Mar 27 05:13 2019
vl_q1 = ffffffff, vl_q2 = ffffffff

Hope that you have got an idea about how the width-casting works distinctively with different signedness and different width of signals. Let me know in comments if you have and doubt regarding this…

Article credits goes to Solvnet article.

 

 

SystemVerilog: Use of non-blocking while driving stimulus

This post is about a generally seen practice in any testbench driver. Ever thought that why it is better to use Non-Blocking Assignments (NBA’s) in driver? Let’s see what difference does it create.

As we know that every simulation in Verilog/SV executes according to a pre-defined set of steps known as stratified event queues. These steps are repeated for each an every entity and every time stamp. Let’s first understand the term known as simulation time and time stamp/time slot.

The term simulation time is used to refer to the time value maintained by the simulator to model the actual time it would take for the system description being simulated. The term time is used interchangeably with simulation time.

A time slot encompasses all simulation activity that is processed in the event regions for each simulation time.

Following are the event regions that are executed in each timestamp:

Continue reading →

SystemVerilog: Evaluating expressions

Apologies for the late post. Today I will like to describe about the technique used for evaluation of various simple-looking expressions in SV. Reading from System Verilog LRM 1800-2012, Chapter 11, following is the definition of expression:

An expression is a construct that combines operands with operators to produce a result that is a function of the values of the operands and the semantic meaning of the operator. Any legal operand, such as a net bitselect, without any operator is considered an expression.

Continue reading →

SystemVerilog: Fine grain process control

Continuing from my previous post about Process vs Threads, now let’s discuss about SystemVerilog processes. Systemverilog has a built in class named Process that allows one process to access and control other processes/threads.

When we fork off any thread, a new object of process class is created at that time. This object contains status information about that thread. An attempt to create a user defined object of process class will result in error.

Reading from IEEE 1800-2012, the process class includes following:
Continue reading →

Process vs Threads

Today I’d like to discuss about threads and process. Let’s take a look at a thread and a process actually means.

Referring to Microsoft’s documentation about threads and processes:

Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.

While a thread can be described as follows:
Continue reading →

Array of Covergroups

In a testbench sometimes there is a need to take multiple instances of a covergroup as per protocol requirement.

In that case Array of Covergroup is needed.

 

By default the coverage information of all covergroup instances shall be grouped together and simulator shall create overall coverage of all the instances combined . So, user will not be able to see separate coverage information of each instance of covergroup.
There are some cases when user want to view separate coverage for all the instances. 

Example :

 In a testbench there can be more than one agents.  All of them belong to different transaction, different generator, different driver etc. In that case, if user may not want to view overall coverage of all the agents, instead individual agent coverage is required.

So, You can use SystemVerilog’s  single-word  Per instance Coverage option.

Here is the simple example how one can declare Array of Covergroup and how can use it.

Continue reading →

One hot coverage of 32-bit vector

Hello friends,

Recently I came across a situation where I had to write a functional coverage for a 32-bit register of DUT which has a one hot kind of value configured i.e. only one bit can be set at a time. Then first idea that came in my mind was to write a single bin for each bit i.e. 32 bins/coverpoints in total. But that was not a good solution at all if you have 64 bits to be covered.

While reading the System Verilog LRM, I came to below solution.

Link for pseudo code

As this snippet is only for coverage purpose, it won’t check whether only a single bit is getting written. You need to write extra checks which make sure that only single bit is being written at a time.

Hope this will help you.

 

SystemVerilog: Passing Array as parameters

This is a simple post related to passing an array of parameters to module, class or interface, in SystemVerilog.

A parameter is a constant value declared within the module, class or interface. The value of parameter can be used to define a set of attributes for the entity which can alter its behavior as well as its physical representation.

Parameters contains a default value, which can be overridden at the time of instantiation, to alter the behavior of a particular instance. So, we can say parameters are used for generalization of any entity.
Continue reading →

SystemVerilog: The let construct

Hi all,

Today I am gonna discuss about the let construct in SystemVerilog.

Many times, when we encounter some repetition of code, in 90% of cases, an obvious alternative would be to create tasks/functions.

Lets start with an example to compare two variables of int type:

function void compare(int a,int b);
$display(“The result is : %0s”,(a==b) ? “Pass” : “Fail”);
endfunction

// Usage
compare(5,4); // The result is : Fail
compare(9,9); // The result is : Pass

The function works fine as long as a and b are int type variables. But sometimes things get really more fuzzy.  When using string or some other datatype argument, this function might not work. At that time, either explicit static cast or declaring a second function must be done.
Continue reading →

%d bloggers like this: