var keyword in SystemVerilog

S

siso

Guest
A simple question about the keyword ' var ' in SystemVerilog. I'm not
sure I understand its significance reading the standard. Esspecially
when it is used in the port lists.
How this relates to the synthesys? Is it a strictly test bench thing
or can be used in the RTL as well?

I'll appreciate your help.

s1s0
 
On Thu, 28 Jan 2010 08:17:33 -0800 (PST), siso wrote:

A simple question about the keyword ' var ' in SystemVerilog. I'm not
sure I understand its significance reading the standard. Esspecially
when it is used in the port lists.
This is, for sure, one of the darker and more cobwebby corners of
the language. I can't promise the following description is 100%
accurate, but it may help you to understand what's going on
enough to start to make sense of the LRM.

SystemVerilog added a huge bunch of new user-definable data
types, many of which (struct, enum, union) are very useful
for synthesisable design. Quite late in the development of
the language, folk began to worry that this created an
asymmetry: you can have variables of type enum, struct etc
but not wires, which were restricted (in older Accellera
versions of the SV standard) to being only arrays of 4-state
bits.

So the language was enhanced to support arbitrary 4-state
data types on wires. For example:

typedef enum logic [1:0]
{BAD=2'bx, RIGHT=2b01, LEFT=2'b10}
E;
typedef struct {
E e;
logic [7:0] b;
} S;

Given those typedefs I can create variables of type S, E etc:

E my_e;
S my_s;
initial begin
my_e = LEFT;
my_s.e = my_e;
...

But what about nets? Well, now you can have them:

wire S my_wire_s1, my_wire_s2;
assign my_wire_s1.e = RIGHT;
assign my_wire_s2 = my_s;

So we now have a variety of ways to declare things...

wire S my_wire_s;
S my_variable_s;
wire w; // eh????

We weasel our way out of that one by agreeing that
"wire w" is actually shorthand for "wire logic w";
it's a declaration of a net, and the data type on the
net is to be 4-state logic. That's pretty much the
same as "wire reg w", but that syntax would give any
Verilog user a serious heart problem so it was outlawed.

So hang on a moment... there's now a nasty asymmetry
between the two S declarations above. Why should a
data type ON ITS OWN mean you get a variable, when a data
type after the "wire" keyword just means the data type?
So we then add the "var" keyword for symmetry, and

var S my_variable_s;

is now the full, verbose way of declaring a variable.
Of course, that then leaves "wire w" looking a bit odd,
so we also add the same "logic" default to var:

var L; // same as "var logic L" or just "logic L;"

~~~~~~~~~~~~~~~~~~~~~~ Confused yet? ~~~~~~~~~~~~~~~~~~~~

Now, as you have correctly spotted, all this interacts in
a rather complicated way with the definition of module
ports. In regular Verilog, input ports are always nets:

module older (input A, ... // A is a wire inside the module

But in SystemVerilog, ports can have complex types...

module newer (input S s, ...

so now what happens? Well, it's OK in SystemVerilog because
you CAN drive a variable by continuous assignment, and most
SV users simply accept that this works and "s" is a variable.
However, that badly breaks the symmetry with plain "input A",
which is (presumably) "input logic A"; but to preserve back
compatibility with Verilog, it's essential that A should be
a net, not a variable. (It really matters, for various arcane
reasons that are of no concern whatever in RTL design.) So
it seems that
input S s
creates, in effect, "input wire S s". But there are many
occasions when you really want your module input to be a
variable rather than a net. So you are now permitted to
say "input var S s" to override the "wire" default.

At approximately this point in the discussion, my brain
usually explodes and I hand over to heavier-duty Verilog
gurus to explain all the rest of the voodoo about var and
wire on ports, their defaults, how the defaults propagate
along a port list if you omit some of them, and so on.
(The sound of popping neurons is unpleasant and I will
not attempt to reproduce it here.)

~~~~~~~~~~~~~~~ I hope you're confused by now, ~~~~~~~~~~~~
~~~~~~~~~~~~~~~ because I most certainly am. ~~~~~~~~~~~~

Now let's wipe away the confusion.

In practice, tool support for "var" and for user-defined
data types on wires is VERY limited and there is little point
in worrying about it. Considering the difference between
var and wire input ports: although the language rules are
very different, and you get different compile-time checking
from a simulator in the two cases, synthesis tools don't care
about the difference and a working design will both simulate
and synthesise correctly whichever you use. For some kinds
of simulation and modelling, the difference is significant;
but you can always program your way around it somehow, and
indeed you must do so when many tools don't support "var"
and wire datatypes properly.

How this relates to the synthesys? Is it a strictly test bench thing
or can be used in the RTL as well?
See above.

I'll appreciate your help.
I very much doubt I've helped, but it did me good to try :)
--
Jonathan Bromley
 
Hi Jonathan & all,

Thanks for the reply. It took me some time reading trough it and some
related parts of the standard, and in between I had to visit the
corner shop because I ran out of Aspirin.

I would like to summarise my understanding - please correct me if I'm
wrong, or comment appropriately.

wire [<data_type>] <data_name>; // net declaration (general form) -
// implies a default data_type "logic"
Example:
wire logic A; // same as
wire A; //

[var] [<data_type>] <data_name>; // variable declaration (general
form) -
// implies a default data_type only
if "var" is there
// and implies variable if (any)
data_type is there
Example:
var logic B; // same as
var B; // same as
logic B; //

It appears that my understanding of a "logic" as an alternative
(equivalent) of "reg" (see std. 6.1- Data declaration) is not precise
enough. It would be better to stick with the statement that the term
register was deprecated in favor of the term variable. Converting this
into a SV syntax it would be correct to say that in general terms the
declaration
var B;
is semantically more appropriate than the declaration
logic B;
Also - the term net (keyword "wire") has the same meaning in Verilog
and SystemVerilog.
I'm strugling with the syntax and semantics and with the connection
between them on this particular subject (and in general of course).
For example - if a "logic" keyword signifies a data type then what the
keywords "wire" and "var" are? Provided that they are described in the
chapter Data declarations?

Now about ports.
<direction> [<net/variable>] [<data_type>] <port_name>
Example:
output wire logic portA; // same as
( really !? )
output wire portA; // same as
output portA; // same as
// or
output var logic portA; // same as
output var portA; // same as
output logic portA; //

In the same line of thoughs then the line
output var portA;
// is more semantically appropriate than the line
output logic portA;

Will it be true to say then that in the RTL world , the port
declaration
input var A;
// is more strict than the
input A;
Because a net can have a number of continuous assignments while a
variable can't. In other words it's technically possible to assign to
a "traditionally" defined input port.

You're right Jonathan, looking at those lines above I'm considering
visiting my GP... as a start.

Looking forward for your comments.

s1s0
 
On Fri, 29 Jan 2010 06:58:36 -0800 (PST), siso wrote:

I would like to summarise my understanding - please correct me if I'm
wrong, or comment appropriately.

wire [<data_type>] <data_name>; // net declaration (general form) -
// implies a default data_type "logic"
Example:
wire logic A; // same as
wire A; //

[var] [<data_type>] <data_name>; // variable declaration -
// implies a default data_type only
// if "var" is there
// and implies variable if (any)
// data_type is there
Example:
var logic B; // same as
var B; // same as
logic B; //
That agrees with my understanding.

It appears that my understanding of a "logic" as an alternative
(equivalent) of "reg" (see std. 6.1- Data declaration) is not precise
I think it is. 'reg' and 'logic' are truly identical in IEEE SV,
although they were different for at least one stage in SV's
gestation and I've met numerous engineers who still wrongly
believe them to have different behaviours. The only
difference I'm aware of is that the specific combination
of keywords "wire reg" is forbidden, whereas "wire logic"
is OK.

register was deprecated in favor of the term variable.
That change (which, of course, applies only to documentation
and has no effect on language keywords or Verilog code) was
introduced in Verilog-2001. The word "register", in its
Verilog-95 usage to mean a variable in Verilog, has completely
disappeared from the LRM.
Converting this

it would be correct to say that in general terms the
declaration
var B;
is semantically more appropriate than the declaration
logic B;
I don't really see why. They are both shorthand forms
for "var logic B" and the latter one is far more
familiar; it also avoids the risk of anyone getting
the wrong end of the stick and thinking that "var"
is a data type.

Also - the term net (keyword "wire") has the same meaning in Verilog
and SystemVerilog.
I believe that's right. There are, of course, several other
sub-species of net but "wire" is by far the most commonly used.

I'm strugling with the syntax and semantics and with the connection
between them on this particular subject (and in general of course).
For example - if a "logic" keyword signifies a data type then what the
keywords "wire" and "var" are?
They are the "kind" of the data object. Variables are just
that: storage locations maintained by the simulator, into
which a new value can be written at any time, overwriting
any existing value. Nets are much more complicated; they
are connections that can have multiple drivers active
concurrently; the value seen on the net by anyone who
chooses to read it is a rather complicated function of
the values provided by each of the net's drivers, the
drive strengths of those drivers, and the net's delay.

Of course, for the overwhelming majority of RTL designs
the use-model for nets is rather simple: nets have a
single continuous driver with "strong" drive strength
and zero delay. Such a net has variable-like behaviour:
each update of the driver immediately causes the net's
value to follow identically. Consequently, RTL
designers often are mystified by the distinction
and regard it as a major irritation of Verilog that
they need to worry about which kind to use in any
given situation. For such users, one of the delights
of SV is that you can also have such a continuous
driver on a variable; consequently, SV RTL designs
don't usually need nets at all except for bidirectional
ports.

Now about ports.
direction> [<net/variable>] [<data_type>] <port_name
Example:
output wire logic portA; // same as
( really !? )
output wire portA; // same as
output portA; // same as
Yes, they're all the same. The signal INSIDE the module
is a wire.

output var logic portA; // same as
output var portA; // same as
output logic portA; //
Also true. Note, also, the subtlety that I failed to mention
in my earlier post because at the time I couldn't be bothered
checking the details in the LRM:

module foo(input logic A, output logic B);

In the above case, port A (being an input) is a net, whereas
port B (being an output) is a variable. This is deeply
disturbing to those who like their languages orthogonal
and regular, but is a necessary consequence of preserving
backwards compatiblity with Verilog. If you don't like
the default, you can change it:

module explicit(input var logic A, output wire logic B);

And note that B was a variable only because it had an
explicit data type:

module foo2(input A, output B); // A,B both nets

In the same line of thoughs then the line
output var portA;
// is more semantically appropriate than the line
output logic portA;
Again I don't really see why you think "var" is better;
but it is certainly true that they're the same.

Will it be true to say then that in the RTL world , the port
declaration
input var A;
// is more strict than the
input A;
Because a net can have a number of continuous assignments while a
variable can't. In other words it's technically possible to assign to
a "traditionally" defined input port.
Absolutely!!!! That's what I was alluding to when I said that
the distinction matters. In "Verilog classic", an input port
is usually thought of as a continuous assign of the outside
signal (hiconn) to the inside, port signal (loconn). If
you accept this model, then it's clearly possible for the
module itself to drive its own input port:

module Foolish (input A, ...);
assign A = 1'b1; // driver on A contends with the input

And, of course, if the external signal driving that port is
currently 1'b0 then you will see A==1'bx. The interesting
question, though, is what happens to the signal OUTSIDE
the module. Does it, too, see the internal driver; or
is it isolated by the notional buffer (continuous assign)
across the port boundary? In other words, are input
ports really just a fancy name for inout? Well.... it
depends. If you have access to IEEE 1800-2009, try
searching it for "port collapsing". Note very, very
carefully the relevant section's use of the words "can"
and "is possible" to convey the idea that port collapsing
may or may not happen depending on the alignment of planets,
amount of whitespace between compiler command-line switches,
wingbeats of butterflies on a minor planet of Betelgeuse, etc.
Come away with a firm conviction that You Don't Want To Do That.

By contrast, port collapsing of inout ports is self-evidently
A Good Thing, because the whole point of an inout port is
that you want to share a connection between the inside and
outside of a module. The scary part is that port collapsing
can easily turn your input ports into inouts without your
(explicit) permission.

In other words: if you want to enforce, reliably, the input-ness
of an input port, then it is a very smart move to ensure that
it is declared as a 'var' input (in the unlikely event that
your tools support that construct). It then has a continuous
assignment driving it across the port boundary, which in SV
automatically forbids any other attempt to assign or write to it.

Thanks for provoking me into revisiting this stuff and
refreshing my understanding!
--
Jonathan Bromley
 
Hi,

The duscussion was my pleasure indeed. The conclusions - not quite...

Whithout an intention to waste your time further - some short non-
technical comments below

  module foo(input logic A, output logic B);

In the above case, port A (being an input) is a net, whereas
port B (being an output) is a variable.  This is deeply
disturbing to those who like their languages orthogonal
and regular, but is a necessary consequence of preserving
backwards compatiblity with Verilog.
I'm not sure I can express in proper English what I think about this.

In the same line of thoughs then the line
output var portA;
// is more semantically appropriate than the line
output logic portA;

Again I don't really see why you think "var" is better;
but it is certainly true that they're the same.
I agree logic is far more familiar, and I do remember you previsous
post about var and how it was introduced in the language, and I do use
logic myself, but after this discussion it just seems to me that usage
of 'var' is less confusing potentially. It seems to be more consistent
having in mind also the port declarations. I'm not promoting it, a
couple of days ago I didn't have an idea what does it do. It's just a
thought.

In other words, are input
ports really just a fancy name for inout?  Well.... it
depends.  If you have access to IEEE 1800-2009, try
searching it for "port collapsing".  Note very, very
carefully the relevant section's use of the words "can"
and "is possible" to convey the idea that port collapsing
may or may not happen depending on the alignment of planets,
amount of whitespace between compiler command-line switches,
wingbeats of butterflies on a minor planet of Betelgeuse, etc.
Come away with a firm conviction that You Don't Want To Do That.
I agree. There is a similar (if not the same) story with "port
coercion". Don't know whether is still in the new standard. At least
one vendor is using this heavily and by default.

Thanks for provoking me into revisiting this stuff and
refreshing my understanding!
Thanks for your time!

s1s0
 
On Saturday, January 30, 2010 8:37:40 AM UTC-8, Jonathan Bromley wrote:
Thanks for provoking me into revisiting this stuff and
refreshing my understanding!
--
Jonathan Bromley

Ack. I was just reading some SV verification texts and ran across "var", which I had never seen before even though I've been using SV for a few years.. I read about it in the LRM (1800-2012) and still didn't understand why it existed. It seemed like an optional keyword. So, I searched here and found this thread and your great explanation. Now I pretty much understand what it does and why it was added and have a headache. Thanks :)

David
 

Welcome to EDABoard.com

Sponsor

Back
Top