Nets, Regs, and logic

Verilog-2001 states that a net can be written by one or more continuous assignments, primitive outputs, or through module ports. The resultant value of multiple drivers is determined by the resolution function of the net type. A net cannot be procedurally assigned. If a net on one side of a port is driven by a variable on the other side, a continuous assignment is implied. A force statement can override the value of a net. When released, it returns to the resolved value.

Verilog-2001 also states that one or more procedural statements can be written to variables, including procedural continuous assignments. The last write determines the value. A variable cannot be continuously assigned. The force statement overrides the procedural assign statement, which in turn overrides the normal assignments. A variable cannot be written through a port; it must go through an implicit continuous assignment to a net.

In SystemVerilog, all variables can now be written either by one continuous assignment or by one or more procedural statements, including procedural continuous assignments. It shall be an error to have multiple continuous assignments or a mixture of procedural and continuous assignments writing to any term in the expansion of a written longest static prefix of a logic variable. All data types can be written through a port.

SystemVerilog variables can be packed or unpacked aggregates of other types. Multiple assignments made to independent elements of a variable are examined individually. An assignment where the left-hand side contains a slice is treated as a single assignment to the entire slice. It shall be an error to have a packed structure or array-type written with a mixture of procedural and continuous assignments. Thus, an unpacked structure or array can have one element assigned procedurally, and another element assigned continuously. And, each element of a packed structure or array can have a single continuous assignment. For example, assume the following structure declaration:

struct {
bit [7:0] A;
bit [7:0] B;
byte C;
} abc;

The following statements are legal assignments to struct abc:

assign abc.C = sel ? 8’hBE : 8’hEF;
not (abc.A[0],abc.B[0]),
(abc.A[1],abc.B[1]),
(abc.A[2],abc.B[2]),
(abc.A[3],abc.B[3]);
always @(posedge clk) abc.B <= abc.B + 1;

The following additional statements are illegal assignments to struct abc:

// Multiple continuous assignments to abc.C
assign abc.C = sel ? 8’hDE : 8’hED;
// Mixing continuous and procedural assignments to abc.A
always @(posedge clk) abc.A[7:4] <= !abc.B[7:4];

For the preceding rule, a declared variable initialization or a procedural continuous assignment is considered a procedural assignment. A force statement is neither a continuous nor a procedural assignment. A release statement shall not change the variable until there is another procedural assignment or shall schedule a re-evaluation of the continuous assignment driving it. A single force or release statement shall not be applied to a whole or part of a variable that is being assigned by a mixture of continuous and procedural assignments.

A continuous assignment is implied when a variable is connected to an input port declaration. This makes assignments to a variable declared as an input port illegal. A continuous assignment is implied when a variable is connected to the output port of an instance. This makes procedural or continuous assignments to a variable connected to the output port of an instance illegal.

SystemVerilog variables cannot be connected to either side of an inout port. SystemVerilog introduces the concept of shared variables across ports with the ref port type.

The compiler can issue a warning if a continuous assignment could drive strengths other than St0, St1, StX, or HiZ to a variable. In any case, SystemVerilog applies automatic type conversion to the assignment, and the strength is lost.

An assignment as part of the logic declaration is a variable initialization, not a continuous assignment. For example:

wire w = vara & varb; // continuous assignment
logic v = consta & constb; // initial procedural assignment
logic vw; // no initial assignment
assign vw = vara & varb; // continuous assignment to a logic
real circ;
assign circ = 2.0 * PI * R; // continuous assignment to a real

<< Previous | Next >>