Icarus Verilog vs. IEEE1364 Copyright 2000 Stephen Williams The IEEE1364 standard is the bible that defines the correctness of the Icarus Verilog implementation and behavior of the compiled program. The IEEE1364.1 is also referenced for matters of synthesis. So the ultimate definition of right and wrong comes from those documents. That does not mean that a Verilog implementation is fully constrained. The standard document allows for implementation specific behavior that, when properly accounted for, does not effect the intended semantics of the specified language. It is therefore possible and common to write programs that produce different results when run by different Verilog implementations. STANDARDIZATION ISSUES These are some issues where the IEEE1364 left unclear, unspecified or simply wrong. I'll try to be precise as I can, and reference the standard as needed. I've made implementation decisions for Icarus Verilog, and I will make clear what those decisions are and how they affect the language. * OBJECTS CAN BE DECLARED ANYWHERE IN THE MODULE Consider this module: module sample1; initial foo = 1; reg foo; wire tmp = bar; initial #1 $display("foo = %b, bar = %b", foo, tmp); endmodule Notice that the ``reg foo;'' declaration is placed after the first initial statement. It turns out that this is a perfectly legal module according to the -1995 and -2000 versions of the standard. The statement ``reg foo;'' is a module_item_declaration which is in turn a module_item. The BNF in the appendix of IEEE1364-1995 treats all module_item statements equally, so no order is imposed. Furthermore, there is no text (that I can find) elsewhere in the standard that imposes any ordering restriction. The sorts of restrictions I would look for are "module_item_declarations must appear before all other module_items" or "variables must be declared textually before they are referenced." Such statements simply do not exist. (Personally, I think it is fine that they don't.) The closest is the rules for implicit declarations of variables that are otherwise undeclared. In the above example, ``bar'' is implicitly declared and is therefore a wire. However, although ``initial foo = 1;'' is written before foo is declared, foo *is* declared within the module, and declared legally by the BNF of the standard. Here is another example: module sample2; initial x.foo = 1; test x; initial #1 $display("foo = %b", x.foo); endmodule module test; reg foo; endmodule; From this example one can clearly see that foo is once again declared after its use in behavioral code. One also sees a forward reference of an entire module. Once again, the standard places no restriction on the order of module declarations in a source file, so this program is, according to the standard, perfectly well formed. Icarus Verilog interprets both of these examples according to "The Standard As I Understand It." However, commercial tools in general break down with these programs. In particular, the first example may generate different errors depending on the tool. The most common error is to claim that ``foo'' is declared twice, once (implicitly) as a wire and once as a reg. So the question now becomes, "Is the standard broken, or are the tools limited?" Coverage of the standard seems to vary widely from tool to tool so it is not clear that the standard really is at fault. It is clear, however, that somebody goofed somewhere. My personal opinion is that there is no logical need to require that all module_item_declarations preceed any other module items. I personally would oppose such a restriction. It may make sense to require that declarations of variables within a module be preceded by their use, although even that is not necessary for the implementation of efficient compilers. However, the existence hierarchical naming syntax as demonstrated in sample2 can have implications that affect any declaration order rules. When reaching into a module with a hierarchical name, the module being referenced is already completely declared (or not declared at all, as in sample2) so module_item order is completely irrelevent. But a "declare before use" rule would infect module ordering, by requiring that modules that are used be first defined. * TASK AND FUNCTION PARAMETERS CANNOT HAVE EXPLICIT TYPES Consider a function negate that wants to take a signed integer value and return its negative: function integer negate; input [15:0] val; negate = -val; endfunction This is not quite right, because the input is implicitly a reg type, which is unsigned. The result, then, will always be a negative value, even if a negative val is passed in. It is possible to fix up this specific example to work properly with the bit pattern of a 16bit number, but that is not the point. What's needed is clarification on whether an input can be declared in the port declaration as well as in the contained block declaration. As I understand the situation, this should be allowed: function integer negate; input [15:0] val; reg signed [15:0] val; negate = -val; endfunction In the -1995 standard, the variable is already implicitly a reg if declared within a function or task. However, in the -2000 standard there is now (as in this example) a reason why one might want to actually declare the type explicitly. I think that a port *cannot* be declared as an integer or time type (though the result can) because the range of the port declaration must match the range of the integer/time declaration, but the range of integers is unspecified. This, by the way, also applies to module ports. With the above in mind, I have decided to *allow* function and task ports to be declared with types, as long as the types are variable types, such ag reg or integer. Without this, there would be no portable way to pass integers into functions/tasks. The standard does not say it is allowed, but it doesn't *disallow* it, and other commercial tools seem to work similarly. * ROUNDING OF TIME When the `timescale directive is present, the compiler is supposed to round fractional times (after scaling) to the nearest integer. The confusing bit here is that it is apparently conventional that if the `timescale directive is *not* present, times are rounded towards zero always. * VALUE OF X IN PRIMITIVE OUTPUTS The IEEE1364-1995 standard clearly states in Table 8-1 that the x symbols is allowed in input columns, but is not allowed in outputs. Furthermore, none of the examples have an x in the output of a primitive. Table 8-1 in the IEEE1364-2000 also says the same thing. However, the BNF clearly states that 0, 1, x and X are valid output_symbol characters. The standard is self contradictory. So I take it that x is allowed, as that is what Verilog-XL does. * REPEAT LOOPS vs. REPEAT EVENT CONTROL There seems to be ambiguity in how code like this should be parsed: repeat (5) @(posedge clk) ; There are two valid interpretations of this code, from the IEEE1364-1995 standard. One looks like this: procedural_timing_control_statement ::= delay_or_event_control statement_or_null delay_or_event_control ::= event_control | repeat ( expression ) event_control If this interpretation is used, then the statement should be executed after the 5th posedge of clk. However, there is also this interpretation: loop_statement ::= repeat ( expression ) statement If *this* interpretation is used, then should be executed 5 times on the posedge of clk. The way the -1995 standard is written, these are both equally valid interpretations of the example, yet they produce very different results. The standard offers no guidance on how to resolve this conflict, and the IEEE1364-2000 DRAFT does not improve the situation. Practice suggests that a repeat followed by an event control should be interpreted as a loop head, and this is what Icarus Verilog does, as well as all the other major Verilog tools, but the standard does not say this. * UNSIZED EXPRESSIONS AS PARAMETERS TO CONCATENATION {} The Verilog standard clearly states in 4.1.14: "Unsized constant numbers shall not be allowed in concatenations. This is because the size of each operand in the concatenation is needed to calculate the complete size of the concatenation." So for example the expression {1'b0, 16} is clearly illegal. It also stands to reason that {1'b0, 15+1} is illegal, for exactly the same justification. What is the size of the expression (15+1)? Furthermore, it is reasonable to expect that (16) and (15+1) are exactly the same so far as the compiler is concerned. Unfortunately, Cadence seems to feel otherwise. In particular, it has been reported that although {1'b0, 16} causes an error, {1'b0, 15+1} is accepted. Further testing shows that any expression other then a simple unsized constant is accepted there, even if all the operands of all the operators that make up the expression are unsized integers. This is a semantic problem. Icarus Verilog doesn't limit the size of integer constants. This is valid as stated in 2.5.1 Note 3: "The number of bits that make up an unsized number (which is a simple decimal number or a number without the size specification) shall be *at*least* 32." [emphasis added] Icarus Verilog will hold any integer constant, so the size will be as large as it needs to be, whether that is 64bits, 128bits, or more. With this in mind, what is the value of these expressions? {'h1_00_00_00_00} {'h1 << 32} {'h0_00_00_00_01 << 32} {'h5_00_00_00_00 + 1} These examples show that the standard is justified in requiring that the operands of concatenation have size. The dispute is what it takes to cause an expression to have a size, and what that size is. Verilog-XL claims that (16) does not have a size, but (15+1) does. The size of the expression (15+1) is the size of the adder that is created, but how wide is the adder when adding unsized constants? One might note that the quote from section 4.1.14 says "Unsized *constant*numbers* shall not be allowed." It does not say "Unsized expressions...", so arguably accepting (15+1) or even (16+0) as an operand to a concatenation is not a violation of the letter of the law. However, the very next sentence of the quote expresses the intent, and accepting (15+1) as having a more defined size then (16) seems to be a violation of that intent. Whatever a compiler decides the size is, the user has no way to predict it, and the compiler should not have the right to treat (15+1) any differently then (16). Therefore, Icarus Verilog takes the position that such expressions are *unsized* and are not allowed as operands to concatenations. Icarus Verilog will in general assume that operations on unsized numbers produce unsized results. There are exceptions when the operator itself does define a size, such as the comparison operators or the reduction operators. Icarus Verilog will generate appropriate error messages. $Id: ieee1364-notes.txt,v 1.7 2001/02/17 05:27:31 steve Exp $ $Log: ieee1364-notes.txt,v $ Revision 1.7 2001/02/17 05:27:31 steve I allow function ports to have types. Revision 1.6 2001/02/12 16:48:04 steve Rant about bit widths. Revision 1.5 2001/01/02 17:28:08 steve Resolve repeat ambiguity in favor of loop. Revision 1.4 2001/01/01 19:12:35 steve repeat loops ambiguity. Revision 1.3 2000/12/15 00:21:46 steve rounding of time and x in primitives. Revision 1.2 2000/11/19 22:03:04 steve Integer parameter comments. Revision 1.1 2000/07/23 18:06:31 steve Document ieee1364 issues.