Author Archive: sharvil111

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.

 

 

UVM-OVM: Yet another compare issue…

Hi guys, recently we discovered one more bug in UVM and OVM build in compare methods. Previously, I discussed about UVM-OVM: Compare method bugs which was about associative array, this post is related to different object types.

Recently the committee has reported/resolved one more bug in UVM/OVM built-in compare method. Note that the following applies to all the UVM and OVM based simulations.

Continue reading →

UVM: Forcing signals in UVM style

Apologies for a late post… Today I would like to mention about some of the useful HDL signal manipulation methods in UVM.

Have you ever wondered about how the backdoor accesses work in RAL?  We provide a string context path to our RAL based register class and we call some peek/poke API to hierarchically access the signal/register in DUT.

How can we do it in SystemVerilog? Providing a string based path and depositing/reading value based on hierarchical access. This seems to be very difficult using plain SystemVerilog. But this is a game played by something called as DPI/VPI.

UVM provides the backdoor access sub-routines for force/release or read/deposit some vale on any hierarchical path provided in the argument. These functions acts as an interface between SystemVerilog and C code to perform various operations. These functions can not only be used for backdoor accesses, but also for forcing some value in any RTL modules.

Continue reading →

ASIC design flow: File extensions

I would like to describe some of the known file extensions that we usually come across while during the entire cycle of chip design. Mostly are the file formats used by Synopsis tools.

Here are the extensions, let me know if I missed out something 🙂

.LEF 

An ASCII data format, used to describe a standard cell library. Includes the design rules for routing and the Abstract of the cells, no information about the internal netlist of the cells. A LEF file contains the following sections:

Continue reading →

ASIC Design Flow outline (Part-1)

Today, ASIC design flow is a very sophisticated and developed process. The overall ASIC design flow and the various steps within the ASIC design flow have proven to be both practical and robust in multi-millions ASIC designs until now. Let’s discuss about an overview of these steps in the design flow.

1) SPECIFICATION:

Lot of activity from gathering market requirement to deciding the technical aspect is done first. This is the crucial step as it will affect the future of the product. Here, vendors may want to get feedback from potential customers on what they are looking for. Once this is done  final specification sheet with all possible technical details is made and handed over to the next team.

Continue reading →

ASIC Design Flow outline (Part-2)

Continuing from the previous post about ASIC Design Flow Part-1, here is some detail explanation about backend flows.

backend

Backend flow

Continue reading →

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 →

UVM-OVM: Compare method bugs

Hi all this post mainly focusing on exercising a caution while using UVM/OVM built-in compare methods using field utility macros. We have seen many folks discouraging about the usage of field utility macros due to their overhead and complexity. But there seems more to it…

Recently while doing some conversion from OVM to UVM, I came across a bug in OVM while using “compare” method for associative arrays. The array was registered with factory with “OVM_NOPRINT” attribute. So I used “UVM_NOPRINT” as a UVM counterpart. But the testcase failed in UVM while it passed in OVM.

Continue reading →

UVM: How TLM ports work? (The straightforward way)

Continuing from my previous post about “UVM: How the TLM ports work?“, here I am presenting an easy way to understand the mystery. Today we will develop a simple infrastructure in SystemVerilog for the same put port. One can implement a get port in a similar fashion just by changing the direction of argument to the tasks.

Ports are nothing but the lightweight intermediate classes that calls specific tasks from one class to another. We will implement following infrastructure in this example:

Continue reading →

%d bloggers like this: