data_declaration18 ::=
[const]
[lifetime] variable_declaration
| constant_declaration
| type_declaration
| package_import_declaration
| virtual_interface_declaration
variable_declaration ::=
data_type list_of_variable_decl_assignments ;
lifetime
::= static | automatic
18) In a data_declaration that is not within the
procedural context it shall be illegal to use the automatic keyword.
Constants are named data variables
items which never change. There are three kinds of constants,
declared with the keywords localparam, specparam and const, respectively. All three can be initialized with a
literal.
A parameter or local parameter
can only be set to an expression of literals, parameters or local parameters, genvars, enumerated names, or a constant function of these.
Hierarchical names are not allowed.
A specparam can also be set
to an expression containing one or more specparams.
A constant declared with
the const keyword, can only be set to an expression of literals,
parameters, local parameters, genvars, enumerated names, a
constant function of these, or other constants. The parameters, local
parameters or constant functions can have hierarchical names. This is because
the static constants are calculated after elaboration.
This means that the object acts like a variable that cannot be written.
The arguments to the new method must be constant expressions. The members of the object can be written
(except for those members that are declared const).
Verilog-2001
allows tasks and functions to be declared as automatic, making all storage within the task or function
automatic. SystemVerilog allows specific data within a static task or function
to be explicitly declared as automatic. Data declared as automatic has the lifetime of the
call or block, and is initialized on each entry to the call or block. The lifetime
of a fork…join, fork…join_any, or fork…join_none block shall encompass the execution of all
processes spawned by the block. The lifetime of a scope enclosing any fork…join
block includes the lifetime of the fork…join block.
Note that automatic or
dynamic variables cannot be written with nonblocking or continuous assignments.
Automatic variables and dynamic constructs—objects handles, dynamic arrays,
associative arrays, strings, and event variables—are
shall be limited to the procedural
context.
5.8 Type Compatibility
Some SystemVerilog constructs and operations
require a certain level of type compatibility for their operands to be legal.
There are four levels of type compatibility, formally defined here: Equivalent,
Assignment Compatible, Cast Compatible, and Non-Equivalent.
Note that there is no category for identical
types defined here because there is no construct in the SystemVerilog language
that requires it. For example, as defined below, ‘int’ may be interchanged with ‘bit signed [0:31]’ wherever it is
syntactically legal to do so. Users may define their own level of type identity
by using the $typename system function (See section
22.2 Typename function), or through use of the PLI.
5.8.1 Equivalent Types
Two data types shall be defined as
equivalent data types using the following inductive definition. If the two data
types are not defined equivalent using the following definition then they shall
be defined to be non-equivalent.
1.
Any built-in type is equivalent to every other
occurrence of itself, in every scope.
2.
A simple typedef or type parameter
override that renames a built-in or user defined type is equivalent to that
built-in or user defined type within the scope of the type identifier.
typedef bit node; // ‘bit’ and
‘node’ are equivalent types
typedef type1 type2; // ‘type1’
and ‘type2’ are equivalent types
3.
An anonymous enum, struct, or union type is equivalent to itself among variables declared within the same
declaration statement and no other types.
struct {int A; int
B;} AB1, AB2; // AB1, AB2 have equivalent types
struct {int A; int
B;} AB3; // AB3 is not type equivalent to AB1
4.
A typedef for an enum, unpacked struct, or unpacked union, or a class is equivalent to itself and variables declared
using that type within the scope of the type identifier.
typedef struct {int A; int
B;} AB_t;
AB_t AB1;
AB_t AB2; // AB1 and AB2 have
equivalent types
typedef struct {int A; int
B;} otherAB_t;
otherAB_t AB3; //
AB3 is not type equivalent to AB1 or AB2
5.
Packed arrays, packed structures,
and built-in integral types are equivalent if they contain the same number of
total bits, are either all 2-state or all 4-state, and are either all signed or
all unsigned. Note that if any bit of a packed structure or union is 4-state,
the entire structure or union is considered 4-state.
typedef bit signed [7:0]BYTE; // equivalent to the byte type
typedef struct packed signed {bit[3:0] a,b;}
uint8;
// equivalent to the byte type
6.
Unpacked array types are equivalent by having
equivalent element types and identical shape. Shape is defined as the number of
dimensions and the number of elements in each dimension, not the actual range
of the dimension.
bit [9:0] A[0:5];
bit [
typedef bit [10:1] uint10;
uint10 C[6:1]; // A, B and C have equivalent
types
typedef int anint[0:0]; // anint is
not type equivalent to int
7.
Explicitly adding signed or unsigned modifiers to a
type that does not change its default signing, does not create a non-equivalent
type. Otherwise, the signing must match to have equivalence
typedef
bit unsigned ubit; // type equivalent to
bit
8.
A typedef for an enum, unpacked struct, or unpacked union, or a class type declared in
a package is always equivalent to itself, regardless of the scope where the
type is imported.
The scope of a type identifier includes the
hierarchical instance scope. This means that each instance with user defined
types declared inside the instance creates a unique type. To have type
equivalence among multiple instances of the same module, interface, or program,
a type must be declared at higher level in the compilation unit scope than the
declaration of the module, interface or program, or imported from a package.
The following example is assumed to be
within one compilation unit, although the package declaration need not be in
the same unit:
package p1;
typedef struct {int A;} t_1;
endpackage
typedef struct {int A;} t_2;
module
sub();
import p1:t_1;
parameter type t_3 = int;
parameter type t_4 = int;
typedef struct {int A;} t_5;
t_1 v1; t_2 v2; t_3 v3; t_4 v4; t_5 v5;
endmodule
module top();
typedef struct {int A;} t_6;
sub #(.t_3(t_6)) s1 ();
sub #(.t_3(t_6)) s2
();
initial begin
s1.v1 = s2.v1; // legal - both types from
package p1 (rule 8)
s1.v2 = s2.v2; // legal - both types from
$unit (rule 4)
s1.v3 = s2.v3; // legal - both types from
top (rule 2)
s1.v4 = s2.v4; // legal - both types are
int (rule 1)
s1.v5 = s2.v5; // illegal - types from s1
and s2 (rule 4)
end
endmodule
5.8.2 Assignment Compatible
All equivalent types,
and all non-equivalent types that have implicit casting rules defined between
them are assignment compatible types. For example, all integral types are
assignment compatible. Conversion between assignment compatible types may
involve loss of data by truncation or rounding.
Compatibility may be in one direction
only. For example, an enum can be converted
to an integral type without a cast, but not in the other way around. Implicit
casting rules are defined in Section 3 Data Types and Section 7 Operators and
Expressions.
5.8.3 Cast Compatible
All assignment compatible types, plus all
non-equivalent types that have defined explicit casting rules are cast
compatible types. For example, an integral type requires a cast to be assigned
to an enum.
Explicit casting rules are defined in
Section 3 Data Types.
5.8.4 Type Incompatible
These are all the remaining
non-equivalent types that have no defined implicit or explicit casting rules.
Class handles and chandles are type
incompatible with all other types.