Usage of Var

I’m posting a question I found in another website.

What is the difference b/w the following declarations?
logic data_1;
var logic data_2;
wire logic data_3j;
bit data_4;
var bit data_5;

Can somebody please clarify ?


1 Like

SystemVerilog has some funky defaults in order to be backward compatible with Verilog.

SystemVerilog added the concept signal kinds: nets or variables, that are distinct from data types. This allows you to add data types like structs and enums to wires.

When you declare the variables data_1 and data_2

logic data_1;
reg [31:0] data_2;

This is implicitly equivalent to

var logic data_1;
var reg data_2;

Similarly, when you declare the net data_3;

wire data_3;

This is implicitly equivalent to

wire logic data_3;

You can also now do

struct { logic  parity,
         logic  [31:0] word
       } wordp_t;
wire wordp_t A;

The var keyword is usually not needed, but there are at least two places it becomes necessary.
When you use the type() operator, the var keyword is necessary to parse the declaration.

reg [2:0] A;
var type(A) B; // declare variable B the same type as variable A

In a port list, the default for ‘input logic A’ is to declare A as a wire, not a variable, so you would do

module mymod(input var logic A);

to make it a variable.

1 Like

In reply to dave_59:

Is there a way in SystemVerilog to create a variable that refers to a certain type.

For example: I need an associative array that can store a type

var type assoc_array[string];

else where I would like to use this array to create parameterized agents. I want to pass the value or the type stored in my assoc array when creating agents that deal with that type of packets.


In reply to prasadaddagarla:

There is no way to store a variable type directly. If the types you want to store are classes, then you can use what is called a proxy class. See session 3 of my SystemVerilog OOP for UVM course. The UVM implements this with the umm_object_wrapper class.

In reply to dave_59:

Hi Dave,

When would we want to make a input port a variable?

Thanks & Best Regards,

1 Like

In reply to Daphn:

When you want to enforce the direction of an input port. Because of port collapsing, Verilog cannot enforce the flow of data through an input or output port when both sides of the connection are nets. It behaves like a single piece of metal on silicon.

When one or both side of a port connection are variables, a unidirectional continuous assignment gets inserted in the connection. This also means that when applying a force to the lower level module’s port, the force does not propagate back through the port in the opposite direction.

1 Like

In reply to dave_59:
Hi Dave,

Thank you for replying.

Thanks & Best Regards,

The main difference between wire and logic is how they behave in the following case:

wire a = b;
logic a = b;

The first case is equivalent to a continuous assignment:

wire a;
assign a = b;

The second case is equivalent to initialization at time 0:

logic a;
initial a = b;

Note that in the second case logic behaves just like reg:

reg a;
initial a = b;

Interestingly enough, this difference is not covered in many tutorials and even senior engineers are frequently not aware of it.

In reply to yuri-panchul-samsung:

One small important distinction

logic a = 1; // is not exactly equivalent to

logic a;
initial a = 1;

Static variables get initialized once at time 0 before any initial or always processes have started.

logic a = 1;
logic b;
initial b = 1;
initial $display(a,,b);

The value of a displayed is guaranteed to be 1. The value of b displayed is indeterminate and could be 0 or 1.

In reply to dave_59:

Yes, thank for this additional distinction.

This bug “logic a = b” is difficult to debug, but it is flagged by some linters.

However at least one linter (I think it is from Synopsys) has another bug of its own.

If you write:

wire a = b; // OK
logic a = b; // ERROR, I agree
wire signed [7:0] a = b; // OK

So far so good. But:

typedef logic signed [7:0] abc;
abc a = b; // ERROR, I agree
wire abc a = b; // Also ERROR - it should not be an error

The last thing is I believe a bug in linter.

In reply to dave_59:

is there a summary or tutorial on all the kinds?
I couldn’t find much on SystemVerilog kinds? is it official terminology

In reply to xning:

There are only two “kinds” in this context; nets and variables. The particular issue regarding the difference between an initialization and a continuous assignment is discussed at the end of section 6.5 Nets and Variables.

The word “kind” is loosely used in throughout the LRM to refer to grouping of data or class types. However, there is one section that formally uses “kind” to be distinct from a “type”; section Rules for determining port kind, data type, and direction

1 Like