I had put off responding to this email, but now the issue has come up again in the BC. >From: "danielm" <danielm@aldec.com.pl> >LRM: >" In Verilog, an initialization value specified as part of the declaration >is executed as if the assignment were made from an initial block, after >simulation has started. In SystemVerilog, setting the initial value of a >static variable as part of he variable declaration (including static class >members) shall occur before any initial or always blocks are started." > >Is initialization really a part of declaration - if so then newly declared >identifier is visble after ';', and in initialization phase this identifier >remains not declared. I mean what should happened for below code: > >module top; > parameter p=123; > initial begin : _label > int p=p; //this is circular illegal assignment p=p, or at the moment >of initialization p from outer scope is still visible? > $display(p); > end >endmodule My opinion has been that this should be treated as a reference to the p in the outer scope, which requires that the identifier not become visible until after its full declaration, including the initializer. The main reason is that this could be useful in some situation, while the circular assignment is useless. This argument is weaker now that Shalom has pointed out a possible use for the circular reference, to invoke a method: Colors c = c.first; This is meaningful because this method is unusual in not requiring the value of the variable that is the object of the method. Another argument on this is that it avoids the question of what the value of the variable is before it is initialized. Some people seem to be assuming that a circular reference is inherently illegal, but there is no such rule in the LRM. If the circular reference is possible, and no rule is added to make it illegal, then the behavior should be defined. It seems to me that the definition is pretty obvious: it has the default initialization value. This makes sense in a couple of ways. First, one expects "p=p" to have no effect. So "int p=p;" should have the same effect as "int p;" and that initializes p to its default initialization value of 0. Second, you can regard the process of initialization as first initializing to the default initialization value, and then if there is an explicit initializer, executing that. So I don't think there is a big need to avoid the circular reference. Also, if hierarchical references are allowed in initializers, you cannot prevent the circular reference, so you need to define it anyway. Then there are the historical precedents. For a net with a continuous assignment on the net declaration, the assignment has always been able to refer to the net being declared, since that is what Verilog-XL did. Unlike variable initializers, there are situations where it makes sense to refer to the left-hand-side net in the assignment, to create a combinational loop: wire q = en ? d : q; While this may not be a recommended modeling style, it is a valid way to describe a transparent latch. Also, back before Verilog-2001, there was no way that q could refer to anything but the q on the left-hand-side. Without $unit or generate scopes, the scopes where nets could be declared were never nested inside any other scope where a different q could be found. So if it didn't refer to the net on the LHS, it would have to be an error. So the usefulness argument favored letting the RHS refer to the LHS. If the decision were being made today, the scope argument would not be valid any more. But I assume that this is something that is already well enough established that it cannot be changed. Another precedent would be a parameter declared inside a generate scope, with a default value that refers to the same name: module top; parameter p = 41; if (1) begin localparam p = p + 1'b1; initial $display(p); end endmodule I don't know if there is anything in the LRM that addresses this. I don't know whether implementations have treated it consistently. The one I tested treats this as a reference to the outer p. I think that makes the most sense. As with variables, a reference to the outer p might be useful, while a reference to the inner one is not. The problem of circularity is worse for parameters, since they don't have a concept of a default value other than the one specified for them. They may not even have a type, but get it from the value, which makes the type circular also. And the value is not allowed to use hierarchical references, so this prevents that other way of getting a circular reference. That makes it more useful to avoid this way of getting it. Overall, I am still inclined to make a variable visible only after the initializer. However, it isn't a strong opinion. Steven Sharp sharp@cadence.com -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Fri Apr 25 15:11:18 2008
This archive was generated by hypermail 2.1.8 : Fri Apr 25 2008 - 15:12:17 PDT