Some details about implicit wires.
Adding implicit wires turns out to be surprisingly subtle. Here are some notes about implicit wires in Verilog-2005.
When a wire is implicitly declared, its type is controlled by the
We think wires need to be declared, explicitly or implicitly, before being used. The Verilog-2005 standard seems not to explicitly say whether or not this is the case, and the language at the start of Section 4.5 is somewhat vague: we are supposed to assume implicit nets in the absence of an explicit declaration in certain situations. But later in 4.5 we find some language that pretty strongly suggests we are only to consider whether or not there is an explicit declaration before the use of the net: "and that identifier has not been declared previously in the scope...."
Section 4.5 outlines the conditions under which an implicit wire declaration
is supposed to be made. In each case, the implicit declaration is to be added
to the nearest scope. It seems like this mostly only matters in the case of
Note: I think that throughout Section 4.5, the words port expression declaration are a typo that should be port declaration; nowhere else in the Verilog-2005 standard do the words port expression declaration occur, at least according to Acrobat's find function.
If there is a port declaration like
Note that per 12.3.3, a port declaration like
If there is an undeclared identifier in the terminal list of a primitive or module instance, or in the left-hand side of a continuous assignment statement, then we are supposed to infer an implicit, scalar net.
I think a "primitive instance" is supposed to mean either a gate instance or a user-defined primitive instance. See for instance Section 7.1.6, which talks about "primitive instance connection lists" in reference to gates, and 11.6.6 where primitive terminals are distinguished from module ports. So, this means we should infer implicit wires in the ports/terminals of any instance, regardless of whether it's a gate/udp/module.
We developed some tests (see
#1. As expected, both allow implicit wires to be inferred from the arguments of gate and module instances. This seems to be the intent of Case 2.
#2. As expected, both complain about undeclared wires on the
right-hand side of an
#3. As expected, NCVerilog allows us to infer implicit nets from the
left-hand sides of
A subtle case is, what if #2 and #3 overlap, i.e., an undeclared wire occurs
on both the left-hand and right-hand sides? This isn't entirely contrived;
someone might occasionally write things like
#4. Mostly as expected, neither tool allows undeclared wires on
either side of an assignment in an always block. The tools even reject
implicit wires in procedural continuous assignments, e.g.,
This seems arguably incorrect: is not a procedural continuous assignment also a continuous assignment, whose LHS should therefore be able to contain implicit wires? But we mimick these tools and disallow the implicit net, even thought the spec might perhaps be interpreted as allowing it.
A nice consequence of disallowing implicit wires here is that it allows us
to avoid certain scoping questions. In particular, suppose we see a procedural
continuous assignment statement,
#5. As expected, neither implementation tolerates undeclared wires on either side of assignments in function bodies. This seems perfectly reasonable since functions aren't allowed to have procedural continuous assignments (10.4.4 E).
#6 As expected, both Verilog-XL and NCVerilog require that all wires
be declared (either explicitly or implicitly) before they are used. For
instance, they if
assign a = w; // error here, saying w is undeclared wire w;
And also for code like this:
not(a, w); wire w; // error here, saying w is implicitly declared above
#7 The whole declare-before-use thing is pretty strange for ports.
Suppose
wire c2 = c; // error here, saying c is not declared. input c;
Verilog-XL seems to require the port declaration to come before the wire declaration, if any. That is, it considers the following an error, whereas NCVerilog allows it:
wire c; input c;
This seems to hold for implicit declarations, too. For instance, Verilog-XL rejects the following, but NCVerilog allows it:
buf(c, c2); // implicit declaration of wire c here input c;
But both Verilog-XL and NCVerilog allow the following, even though you might
think the buf gate would introduce an implicit declaration of
input c; buf(c, c2); wire c;
We try to be permissive and mimick NCVerilog, but add a (non-fatal) warning if a wire's net declaration comes before its port declaration to explain that some other tools do not permit this.
In previous versions of VL, we allowed declarations to come in any order, and inferred an implicit wire whenever a wire was used in a context that permitted it. We now try to be more faithful to other Verilog systems and require that wires be declared before their first uses, since this seems like the right way to interpret the Verilog-2005 standard.
With regard to Case 1, we add a net declaration for each port declaration that is missing a corresponding wire declaration. In the process, we make sure that at least some declaration (be it a wire or port declaration) of each port occurs before every use of the port. If only a wire declaration occurs before some use of the port wire, we issue a non-fatal warning saying that Verilog-XL does not tolerate this ordering.
When we add implicit wires for ports, we use the range of the port
declaration, which seems to be correct with respect to the "vector width of
the port declaration expression," described above. We also keep the
signedness of the port, which isn't discussed above, but appears to be the
correct thing to do; see portdecl-sign for details. We place the
implicit wire declaration at the same location as the corresponding port
declaration, which seems like the easiest place to put it. We also mark each
implicit wire declaration with the
With regard to Case 2, we add one-bit wire declarations for any undeclared
wires that occur within the port arguments of gate and module instances, and
which occur in the left-hand sides of continuous assignments. For assignments,
we always issue a non-fatal warning that says Verilog-XL doesn't add implicit
nets here, and we always process the left-hand side first (like NCVerilog). We
add the wire declarations at the locations in which they are implicitly
declared, and mark them with the