# Icarus Verilog vs. IEEE1364

                    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 precede 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
    irrelevant. 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 as 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) <statement>;

    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 <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 <statement> 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 NUMERIC CONSTANTS ARE NOT LIMITED TO 32 BITS

    The Verilog standard allows Verilog implementations to limit the size
    of unsized constants to a bit width of at least 32. That means that a
    constant 17179869183 (36'h3_ffff_ffff) may overflow some compilers. In
    fact, it is common to limit these values to 32bits. However, a
    compiler may just as easily choose another width limit, for example
    64bits. That value is equally good.

    However, it is not *required* that an implementation truncate at 32
    bits, and in fact Icarus Verilog does not truncate at all. It will
    make the unsized constant as big as it needs to be to hold the value
    accurately. This is especially useful in situations like this;

    	    reg [width-1:0] foo = 17179869183;

    The programmer wants the constant to take on the width of the reg,
    which in this example is parameterized. Since constant sizes cannot be
    parameterized, the programmer ideally gives an unsized constant, which
    the compiler then expands/contracts to match the l-value.

    Also, by choosing to not ever truncate, Icarus Verilog can handle code
    written for a 64bit compiler as easily as for a 32bit compiler. In
    particular, any constants that the user does not expect to be
    arbitrarily truncated by his compiler will also not be truncated by
    Icarus Verilog, no matter what that other compiler chooses as a
    truncation point.

    * 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.

    * MODULE INSTANCE WITH WRONG SIZE PORT LIST

    A module declaration like this declares a module that takes three ports:

    	module three (a, b, c);
    	  input a, b, c;
    	  reg x;
    	endmodule

    This is fine and obvious. It is also clear from the standard that
    these are legal instantiations of this module:

    	three u1 (x,y,z);
    	three u2 ( ,y, );
    	three u3 ( , , );
    	three u4 (.b(y));

    In some of the above examples, there are unconnected ports. In the
    case of u4, the pass by name connects only port b, and leaves a and c
    unconnected. u2 and u4 are the same thing, in fact, but using
    positional or by-name syntax. The next example is a little less
    obvious:

    	three u4 ();

    The trick here is that strictly speaking, the parser cannot tell
    whether this is a list of no pass by name ports (that is, all
    unconnected) or an empty positional list. If this were an empty
    positional list, then the wrong number of ports is given, but if it is
    an empty by-name list, it is an obviously valid instantiation. So it
    is fine to accept this case as valid.

    These are more doubtful:

    	three u5(x,y);
    	three u6(,);

    These are definitely positional port lists, and they are definitely
    the wrong length. In this case, the standard is not explicit about
    what to do about positional port lists in module instantiations,
    except that the first is connected to the first, second to second,
    etc. It does not say that the list must be the right length, but every
    example of unconnected ports used by-name syntax, and every example of
    ordered list has the right size list.

    Icarus Verilog takes the (very weak) hint that ordered lists should be
    the right length, and will therefore flag instances u5 and u6 as
    errors. The IEEE1364 standard should be more specific one way or the
    other.

    * UNKNOWN VALUES IN L-VALUE BIT SELECTS

    Consider this example:

    	reg [7:0] vec;
    	wire [4:0] idx = <expr>;
    	[...]
    	vec[idx] = 1;

    So long as the value of idx is a valid bit select address, the
    behavior of this assignment is obvious. However, there is no explicit
    word in the standard as to what happens if the value is out of
    range. The standard clearly states the value of an expression when the
    bit-select or part select is out of range (the value is x) but does
    not address the behavior when the expression is an l-value.

    Icarus Verilog will take the position that bit select expressions in
    the l-value will select oblivion if it is out of range. That is, if
    idx has a value that is not a valid bit select of vec, then the
    assignment will have no effect.

    * SCHEDULING VALUES IN LOGIC

    The interaction between blocking assignments in procedural code and
    logic gates in gate-level code and expressions is poorly defined in
    Verilog. Consider this example:

       reg a;
       reg b;
       wire q = a & b;

       initial begin
          a = 1;
          b = 0;
          #1 b = 1;
          if (q !== 0) begin
    	 $display("FAILED -- q changed too soon? %b", q);
    	 $finish;
          end
       end

    This is a confusing situation. It is clear from the Verilog standard
    that an assignment to a variable using a blocking assign causes the
    l-value to receive the value before the assignment completes. This
    means that a subsequent read of the assigned variable *must* read back
    what was blocking-assigned.

    However, in the example above, the "wire q = a & b" expresses some
    gate logic between a/b and q. The standard does not say whether a read
    out of logic should read the value computed from previous assigns to
    the input from the same thread. Specifically, when "a" and "b" are
    assigned by blocking assignments, will a read of "q" get the computed
    value or the existing value?

    In fact, existing commercial tools do it both ways. Some tools print
    the FAILED message in the above example, and some do not. Icarus
    Verilog does not print the FAILED message in the above example,
    because the gate value change is *scheduled* when inputs are assigned,
    but not propagated until the thread gives up the processor.

    Icarus Verilog chooses this behavior in order to filter out zero-width
    pulses as early as possible. The implication of this is that a read of
    the output of combinational logic will most likely *not* reflect the
    changes in inputs until the thread that changed the inputs yields
    execution.

    * BIT AND PART SELECTS OF PARAMETERS

    Bit and part selects are supposed to only be supported on vector nets
    and variables (wires, regs, etc.) However, it is common for Verilog
    compilers to also support bit and part select on parameters. Icarus
    Verilog also chooses to support bit and part selects on parameter
    names, but we need to define what that means.

    A bit or a part select on a parameter expression returns an unsigned
    value with a defined size. The parameter value is considered be a
    constant vector of bits foo[X:0]. That is, zero based. The bit and
    part selects operate from that assumption.

    Verilog 2001 adds syntax to allow the user to explicitly declare the
    parameter range (i.e. parameter [5:0] foo = 9;) so Icarus Verilog will
    (or should) use the explicitly declared vector dimensions to interpret
    bit and part selects.

    * EDGES OF VECTORS

    Consider this example:

       reg [ 5:0] clock;
       always @(posedge clock) [do stuff]

    The IEEE1364 standard clearly states that the @(posedge clock) looks
    only at the bit clock[0] (the least significant bit) to search for
    edges. It has been pointed out by some that Verilog XL instead
    implements it as "@(posedge |clock)": it looks for a rise in the
    reduction or of the vector. Cadence Design Systems technical support
    has been rumored to claim that the IEEE1364 specification is wrong,
    but NC-Verilog behaves according to the specification, and thus
    different from XL.

    Icarus Verilog, therefore, takes the position that the specification
    is clear and correct, and it behaves as does NC-Verilog in this
    matter.

    * REAL VARIABLES IN $dumpoff DEAD-ZONES

    The IEEE1364 standard clearly states that in VCD files, the $dumpoff
    section checkpoints all the dumped variables as X values. For reg and
    wire bits/vectors, this obviously means 'bx values. Icarus Verilog
    does this, for example:

        $dumpoff
        x!
        x"
        $end

    Real variables can also be included in VCD dumps, but it is not at
    all obvious what is supposed to be dumped into the $dumpoff-$end
    section of the VCD file. Verilog-XL dumps "r0 !" to set the real
    variables to the dead-zone value of 0.0, whereas other tools, such as
    ModelTech, ignore real variables in this section.

    For example (from XL):

        $dumpoff
        r0 !
        r0 "
        $end

    Icarus Verilog dumps NaN values for real variables in the
    $dumpoff-$end section of the VCD file. The NaN value is the IEEE754
    equivalent of an unknown value, and so better reflects the unknown
    (during the dead zone) status of the variable, like this:

        $dumpoff
        rNaN !
        rNaN "
        $end

    It turns out that NaN is conventionally accepted by scanf functions,
    and viewers that support real variables support NaN values. So while
    the IEEE1364 doesn't require this behavior, and given the variety that
    already seems to exist amongst VCD viewers in the wild, this behavior
    seems to be acceptable according to the standard, is a better mirror
    of 4-value behavior in the dead zone, and appears more user friendly
    when viewed by reasonable viewers.

    $Id: ieee1364-notes.txt,v 1.17 2003/07/15 03:49:22 steve Exp $
    $Log: ieee1364-notes.txt,v $
    Revision 1.17  2003/07/15 03:49:22  steve
     Spelling fixes.

    Revision 1.16  2003/04/14 03:40:21  steve
     Make some effort to preserve bits while
     operating on constant values.

    Revision 1.15  2003/02/16 23:39:08  steve
     NaN in dead zones of VCD dumps.

    Revision 1.14  2003/02/06 17:51:36  steve
     Edge of vectors notes.

    Revision 1.13  2002/08/20 04:11:53  steve
     Support parameters with defined ranges.

    Revision 1.12  2002/06/11 03:34:33  steve
     Spelling patch (Larry Doolittle)

    Revision 1.11  2002/04/27 02:38:04  steve
     Support selecting bits from parameters.

    Revision 1.10  2002/03/31 01:54:13  steve
     Notes about scheduling

    Revision 1.9  2002/01/26 02:08:07  steve
     Handle x in l-value of set/x

    Revision 1.8  2001/08/01 05:17:31  steve
     Accept empty port lists to module instantiation.

    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.