This shows you the differences between two versions of the page.
— |
geda:icarus_ieee1364 [2012/02/20 15:14] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Icarus Verilog vs. IEEE1364 ====== | ||
+ | <code> 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.</code> |