Don’t use $unit and module parameters when SystemVerilog package import can do the job

In a SystemVerilog design many basic types and sizes are shared. Passing them down as Verilog-style module parameters through endless levels of instantiation hierarchy isn’t the best way to keep SystemVerilog module definitions generic.

SystemVerilog added two lexical scoping mechanisms beyond module definitions for this purpose, the compilation-unit scope ($unit) and packages. I recommend packages.

An old objection that is no longer accurate was that types and sizes from packages could not be used in the declarations of module ports without either fully qualified package references (such as type_package::T) or wildcard imports into $unit. But that was fixed in IEEE Std 1800-2009 by allowing package imports directly after the module name in a definition.

A new objection is that package imports after the module name clutter up the code, because if they are sharing global types and values they are needed in almost every module and interface definition. But here I show an easy way to get rid of the clutter with an unobtrusive macro.

`define _ import global_parameters::*, type_package::*;

module test `_
( input var T in[N]
, output var T out[N]
  always_comb out = in;

Type-checking SystemVerilog interfaces using a class signature

As I wrote here,

Unlike class specializations, interface specializations cannot be used in a module port declaration. For example, the following is disallowed

module m #(parameter N) (IFC#(N) ifc, ...);

Steven Sharp followed up here that perhaps it was an oversight instead of a decision. Either way, it is still disallowed. He discusses some of the problems this causes for separate compilation. Happily, it is possible to get the effect of at least type checking SystemVerilog interfaces by combining class specializations (8.25) and interface-based typedefs (6.18) using a couple macros.

`define SIGNATURE_DEFINE(Params) \
   typedef SIGNATURE Params \%SIGNATURE ;

`define SIGNATURE_CHECK(Params, Port) \
  if (1) begin \
    typedef SIGNATURE Params Expected; \
    typedef Port.\%SIGNATURE Actual; \
    if (type(Expected) != type(Actual)) begin \
      $fatal("Mismatch"); \
    end \

Here’s a simple example

virtual class SIGNATURE#(int N, type T);

interface IFC#(int N, type T);
  T a[N], z[N];
  modport mp (input a, output z);

module top;
  IFC#(8,int) ifc_inst();
  test#(32,byte) test_inst(;

module test#(int N, type T)( ifc_mp);
  `SIGNATURE_CHECK(/*IFC*/#(N,T), ifc_mp);
  // ...
Copyright © 2016 Brad Pierce

Innovation and standards

According to Dave Rich

The whole point of a having a standard is recording common practice.

[We] have a long history that other end users and implementers of the standard do not have. It’s easy for us to understand the intent, and search the LRM for justifications, but those other people do not have that benefit. And all the people in that environment (training, support, maintenance, AEs), are faced with these problems every day (and many times each day).

According to Brad Pierce

There are more answers to “Why Standards?” than just “recording common practice”.

For example, “Standards can fuel innovation by providing a common starting point.”

Importing Java-style interface classes was an excellent addition to the SystemVerilog language, but they were not common practice in SystemVerilog tools.

According to Dave

I’m not trying to say there’s no place for innovation in standards, it’s just that you can’t forget the underlying principle that brought everybody together in the first place.

I know that if you get a lot of engineers in a room they all will want to work on new and exciting ideas but you can’t forget about the foundation. My favorite analogy:: you can build the most advanced aircraft in the world, but it will never take off unless someone designs the rubber tires.

According to Brad

I’m not objecting to investing some resource into perfecting our rubber tires, I just don’t think the ones we have now are so defective that we can only dare taxi around the airport.

There ought to be a balance between maintenance and innovation, if only to fire up the enthusiasm of the participants. I don’t know anyone that wants to be on projects that have fallen completely into maintenance mode. Maintenance is an honorable and necessary function, and we all do some of it, but it’s thin gruel that should only be eaten as part of a balanced diet.

SystemVerilog: Backward compatibility with Verilog was a key to its success

According to Dave Rich

Superlog was originally designed to be a complete remake of Verilog using more modern programming concepts. My role as the company’s first application engineer was simply to convince people to use it. However, after working at four different Verilog start-ups, I realized how important it was to support legacy code and that migration to a new language must come in the form of evolution, not revolution. So we changed the design of Superlog to be 100% backward compatible with Verilog, as SystemVerilog is today.

UVM beyond SystemVerilog

According to Chris Edwards in “Expanding role of UVM takes center stage at DVCon Europe

[DVCon Europe general chair Martin] Barnasconi says UVM provides a useful framework that can be extended beyond its home of SystemVerilog-based IP verification […]

“We need to think beyond SystemVerilog,” says Barnasconi. “That’s where the challenge is if you ask me. System-level people might use SystemC, C++ or Matlab Simulink. The methodology concept behind UVM is something we should build upon to make it more applicable to other disciplines.

“In the conference there is a tutorial on UVM in SystemC. Teams are trying to bring the methodology to different languages. It underlines the ‘U’ in universal in my view. We also have the trend towards software-driven verification. We need to enable this software layer can be used within sequences defined in UVM.”

Waveform debugging 2015

According to Dave Rich in “A Decade of SystemVerilog: Unifying Design and Verification?

Most design engineers still debug their simulations the same way they debug in the lab: they look at waveforms. During simulation, they rarely look at the design source code, and certainly never look at the testbench code (unless it’s just basic pin wiggling like a waveform). Verification engineers are not much different. They rely on waveform debugging because that is what they were brought up on, and many do not even realize source-level debugging is available to them.

Vital signs

In SystemVerilog design, ‘unique case () inside’ should be your default ‘case’

I recommend requiring the following macro instead of direct uses of  case or casex

`define CASE(EXPR) \
   unique case (EXPR) inside

except when there’s a strong justification for the more expensive alternative

   priority case (EXPR) inside

If, as usual, the expectation is that every value should find a match, or if there is a default branch, then close with

`define ENDCASE \

But if the intent really is for some values not to match any case items, and there is no default branch, then close with


INVITATION: Celebrate 10 Years of IEEE 1800™ SystemVerilog – 14 October 2015 – San Jose, CA USA

Forwarding an invitation for

WHAT: Celebrate 10 Years of SystemVerilog
DATE: 14 October 2015
TIME: Noon-2PM Celebration and Open Discussion
LOCATION: Cadence Design Systems, Building 10, 2655 Seely Avenue, San Jose, CA 95134

According to the invitation

We invite all who have worked to create SystemVerilog from the beginning days of Accellera to the first IEEE version to the most recent revision in 2012 to come together to celebrate and discuss the next steps in further standardization.

A Verilog parameter infers its type from its value — the myth that there is a default signed integer parameter type in Verilog

Because it’s so common to assign a signed integer constant to a Verilog parameter

parameter SIZE = 8;

a myth has arisen that there is a default signed integer parameter type in Verilog.

But there is no default parameter type in Verilog. The type of a parameter (or a local parameter) is the type of whatever value is eventually assigned to it during elaboration. Override SIZE above with "four score and seven years ago" and its type becomes an unsigned vector of width 240.

Verilog 2001 (IEEE Std 1364-2001) added the ability to write

parameter integer SIZE = 8;

so that the right-hand side would instead be evaluated in the context of an assignment to a parameter of type integer. But that never caught on, because apparently it’s considered too painful to write integer after every parameter.

(An extra complication is that Verilog also has some half-way specifications you can add to parameters. For the horrible details, see the bottom of p. 694 in IEEE Std 1800-2012.)

When SystemVerilog extended the Verilog type system, it allowed any of those new types to be used after parameter. Most importantly here, it added an int type that is a 2-state version of integer.

If you are confident it’s only going to be a simple signed integer parameter value, such as #(.N(8)), then I guess even in SystemVerilog you could go ahead and still omit the explicit type from the parameter declaration, because it’s too painful to write the three extra characters int after every parameter.

But if I personally were defining a SystemVerilog coding guideline, I would insist on parameter int N = … or some other explicit type, instead of letting it depend on the type of the value.

parameter int SIZE = 8;

Nonblocking assignments (NBA) — the myth of Verilog parallel assignment

Because of examples like the following, which swaps the value of a and b

a <= b;
b <= a;

a misconception has arisen that Verilog nonblocking assignments (NBA) achieve parallel assignment. Instead, an NBA defers an assignment until late in the time step, but calculates immediately the value that is eventually to be assigned. So in the above example, the values of b and a are calculated when the NBAs are encountered, and are saved away until they are used later in the time step.

Consider instead a more realistic example, where the “parallel assignment” intuition breaks down.

memory[write_idx0] <= data0;
memory[write_idx1] <= data1;

Because write_idx0 and write_idx1 could be equal, priority logic is required so that the last write will win. And what would a “parallel assignment” mean anyway when these indices are equal? — Nondeterminism, multiple-writers, …? Defining parallel assignment is not an obvious thing, and the Verilog language standard does not attempt it within a sequential block.

Such examples get created when, through outside knowledge, the designer knows that the indices will never be equal, hence parallel assignment would be unproblematic. In SystemVerilog, an immediate assertion could be used to inform the tool of this fact, or with an extra loop, the unique0 case construct

foreach (memory[idx]) begin:parallel
  unique0 case(idx)
    write_idx0: memory[idx] <= data0;
    write_idx1: memory[idx] <= data1;