Verilog Language Reference: Verilog Modeling Style Guide (CFE), Product Version 3.1
Verilog Language Reference: Verilog Modeling Style Guide (CFE), Product Version 3.1
Table of contents:
1. Overview 2
2. Lexical Conventions 2
3. Data Types 4
4. Expressions 7
5. Assignments 13
6. Gate and Switch Level Modeling 14
7. User-Defined Primitives (UDPs) 15
8. Behavioral Modeling 21
9. Tasks and Functions 25
10. Hierarchical Structures 27
11. System Tasks 31
12. Compiler Directives 32
13. Pragmas 33
Gärtner Péter
1. Overview
This brochure describes the common Verilog language syntax supported by the Cadence tools
that accept models written at the Register Transfer Level (RTL) of abstraction.
Note: The tools may have other mechanisms to support other Verilog constructs. Please refer the
respective documentation for details.
2. Lexical Conventions
Verilog language source files are a stream of lexical tokens. A lexical token consists of one or
more characters. The layout of tokens in a source file is free format--that is, spaces and newlines
are not syntactically significant.
This brochure uses a syntax formalism based on the Backus-Naur Form (BNF) to define the
Verilog language syntax.
White space can contain the characters for blanks, tabs, newlines, and formfeeds. These characters
are ignored except when they serve to separate other tokens. However, blanks and tabs are
significant in strings.
There are two forms to introduce comments. A one-line comment starts with the two characters //
and ends with a newline. A block comment starts with /* and ends with */. Block comments
cannot be nested, but a one-line comment can be nested within a block comment.
Operators
Operators are single-, double-, or triple-character sequences and are used in expressions.
"Expressions" discusses the use of operators in expressions. Unary operators appear to the left of
their operand. Binary operators appear between their operands. A ternary operator has two
operator characters that separate three operands.
Numbers
You can specify constant numbers in decimal, hexadecimal, octal, or binary format. Negative
numbers are represented in 2's complement form. When used in a number, the question mark (?)
character is the Verilog alternative for the z character. The underscore character (_) is legal
anywhere in a number except as the first character, where it is ignored.
Note: Real numbers are rounded off to the nearest integer.
Syntax
decimal_number ::=
[ sign ] unsigned_number
| [ size ] decimal_base unsigned_number
real_number ::=
[sign] unsigned_number.unsigned_number
| [sign]unsigned_number[.unsigned_number]e[sign]unsigned_number
| [sign]unsigned_number[.unsigned_number]E[sign]unsigned_number
sign ::= + | -
size ::= unsigned_number
unsigned_number ::= decimal_digit { _ | decimal_digit }
decimal_base ::= 'd | 'D
binary_base ::= 'b | 'B
octal_base ::= 'o | 'O
hex_base ::= 'h | 'H
decimal_digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
binary_digit ::= x | X | z | Z | 0 | 1
octal_digit ::= x | X | z | Z | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
hex_digit ::= x | X | z | Z | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7| 8 | 9 | a | b | c | d | e | f | A | B | C | D | E | F
Strings
A string is a sequence of characters enclosed by double quotes and all contained on a single line.
Strings used as operands in expressions and assignments are treated as a sequence of eight-bit
ASCII values, with one eight-bit ASCII value representing one character. To declare a variable to
store a string, declare a register large enough to hold the maximum number of characters the
variable will hold. Note that no extra bits are required to hold a termination character; Verilog
does not store a string termination character. Strings can be manipulated using the standard
operators.
Note: When a variable is larger than required to hold a value being assigned, Verilog pads the
contents on the left with zeros after the assignment. This is consistent with the padding that occurs
during assignment of non-string values.
Certain characters can be used in strings only when preceded by an introductory character called
an escape character. The following table lists these characters in the right-hand column with the
escape sequence that represents the character in the left-hand column.
An identifier is used to give an object, such as a register or a module, a name so that it can be
referenced from other places in a description. An identifier is any sequence of letters, digits,
dollar signs ($), and the underscore (_) symbol. The first character must not be a digit or $; it can
be a letter or an underscore. Upper- and lower-case letters are considered to be different.
Identifiers can be up to 1024 characters long.
Escaped Identifiers
Escaped identifiers provide a means of including any of the printable ASCII characters in an
identifier (the decimal values 33 through 126, or 21 through 7E in hexadecimal). An escaped
identifier starts with the backslash character (\) and ends with white space (blank, tab, newline).
When using bit- or part- selects on the escaped identifier, the bit- or part- select operator must be
preceded by a space. Neither the leading backslash character nor the terminating white space is
considered to be part of the identifier.
Note: Remember to terminate escaped identifiers with white space, otherwise characters that
should follow the identifier are considered as part of it.
Keywords
Keywords are predefined non-escaped identifiers that are used to define the language constructs.
A Verilog HDL keyword preceded by an escape character is not interpreted as a keyword. All
keywords are defined in lowercase. Therefore, you must be type them in lowercase in source
files.
3. Data Types
Data types represent the data storage and transmission elements of digital hardware.
Value Set
The values 0 and 1 are logical complements of one another. When the z value is present at the
input of a gate, or when it is encountered in an expression, the effect is usually the same as an x
value. All of the data types except event store all four basic values. All bits of vectors can be
independently set to one of the four basic values.
Nets
The net data types represent physical connections between structural entities, such as gates. A net
does not store a value. Instead, it must be driven by a driver, such as a gate or a continuous
assignment.
Syntax
net_type ::= wire | tri | tri1 | supply0 | wand | triand | tri0 | supply1 | wor | trior
Net Types
The wire and tri nets connect elements. The net types wire and tri are identical in their syntax and
functions; two names are provided so that the name of a net can indicate the purpose of the net in
that model. A wire net is typically used for nets that are driven by a single gate or continuous
assignment. The tri net type is typically used where multiple drivers drive a net.
Wired Nets
Wired nets are of type wor, wand, trior, and triand, and are used to model wired logic
configurations. Wired nets resolve the conflicts that result when multiple drivers drive the same
net. The wor and trior nets create wired or configurations, such that when any of the drivers is 1,
the net is 1. The wand and triand nets create wired and configurations, such that if any driver is 0,
the net is 0.
The net types wor and trior are identical in their syntax and functionality--as are the wand and
triand.
Supply Nets
The supply0 and supply1 nets model the power supplies in a circuit. The supply0 nets are used to
model Vss (ground) and supply1 nets are used to model Vdd or Vcc (power). These nets should
never be connected to the output of a gate or continuous assignment, because the strength they
possess will override the driver.
When a net is being driven by more than one drivers, the net value is resolved as follows:
Registers
A register is an abstraction of a data storage element. The keyword for the register data type is
reg. A register stores a value from one assignment to the next. An assignment statement in a
procedure acts as a trigger that changes the value in the register.
Syntax
register_name ::=
register_identifier
| memory_identifier [ upper_limit_constant_expression : lower_limit_constant_expression ]
Vectors
A net or reg declaration without a range specification is one bit wide; that is, it is scalar. Multiple
bit net and reg data types are declared by specifying a range, and are known as vectors. The
range specification gives addresses to the individual bits in a multi-bit net or register. The most
significant bit (MSB) is the left-hand value in the range and the least significant bit (LSB) is the
right-hand value in the range. The range is specified as follows:
Note: The keywords scalared and vectored apply only to vector nets and do not apply to vector
registers.
Implicit Declarations
In the absence of an explicit declaration of a variable, statements for gate, user-defined primitive,
and module instantiations assume an implicit variable declaration. This happens if you specify a
variable that has not been explicitly declared previously in one of the declaration statements of
the instantiating module in the terminal list of an instance of a gate, a user-defined primitive, or a
module. These implicitly declared variables are scalar nets of type wire.
Memories
An array of registers can be used to model memories. Each register is known as a word and is
addressed by a single array index. Memories are declared in register declaration statements by
specifying the element address range after the declared identifier.
Syntax
register_name ::=
memory_identifier [ upper_limit_constant_expression : lower_limit_constant_expression ]
For example, the following declaration declares a memory mema of 256 8-bit registers:
Depending upon the assignment, a memory register is interpreted as a wire, a latch or a flip-flop.
Integers
In addition to modeling hardware, there are other uses for variables in an HDL model. Although
you can use the reg variables for general purposes such as counting the number of times a
particular net changes value, the integer register data type is provided for convenience and to
make the description more self-documenting.
Syntax
register_name ::=
register_identifier
| memory_identifier [ upper_limit_constant_expression : lower_limit_constant_expression ]
You may use an integer variable as a general-purpose variable for manipulating quantities that are
not regarded as hardware registers. The size of an integer variable is 32 bits.
You can use arrays of integer variables. The integer arrays are declared in the same manner as
arrays of reg variables, as in the following example:
integer a[1:64]; // an array of 64 integers
You can assign values to the integer variable the same manner as reg variables and use procedural
assignments to trigger their value changes.
The integer variables are signed quantities. Arithmetic operations performed on integer variables
produce 2's complement results.
Parameters
Parameters represent constants that need to be used many places in the design. Parameters do not
belong to either the register or the net group. Parameters are not variables.
Syntax
Even though they represent constants, you can modify parameters at compilation time to have
values that are different from those specified in the declaration assignment. This allows you to
customize module instances. You can modify the parameter with the defparam statement, or you
can modify the parameter in the module instance statement. Typical uses of parameters are to
specify the width of variables. You can access bits and parts of parameters declared in this way
and use them in assignments and logic operations.
See "Overriding Module Parameter Values" for more details on parameter value assignment.
4. Expressions
An expression is a construct that combines operands with operators to produce a result that is a
function of the values of the operands and the semantic meaning of the operator. Alternatively,
an expression is any legal operand -- for example, a net bit-select. Wherever a value is needed in
a statement, an expression can be given. However, several statement constructs limit an expression
to a constant expression. A constant expression consists of constant numbers and predefined
parameter names only, but can use any of the operators defined in "Operators".
For its use in expressions, data type integer shares the same traits as the data type reg. Descriptions
of register usage apply to integers as well.
Operators
Operator Type
{} concatenation
+ - * / arithmetic
% modulus
> >= < <= relational
! logical negation
&& logical and
|| logical or
== logical equality
!= logical inequality
=== case equality
!== case inequality
~ bit-wise negation
& bit-wise and
| bit-wise inclusive or
^ bit-wise exclusive or
^~ or ~^ bit-wise equivalence
& reduction and
~& reduction nand
| reduction or
~| reduction nor
^ reduction xor
~^ or ^~ reduction xnor
<< shift left
>> shift right
<<< arithmetic shift left
>>> arithmetic shift right
?: conditional
The following table lists the Verilog's binary and ternary operators from highest precedence to the
lowest; operators with the same precedence are shown in the same row.
! ~ highest precedence
* / %
+ -
== != === !==
& ^~ | && ||
All operators associate left to right. Associativity refers to the order in which a language evaluates
operators having the same precedence. Thus, in the following example, B is added to A and then
C is subtracted from the result of A+B: A+B-C
When operators differ in precedence, the operators with higher precedence apply first. In the
following example, B is divided by C (division has higher precedence than addition) and then the
result is added to A: A + B / C
Parentheses can change the operator precedence: (A + B) / C // not the same as A + B / C
Operands can be expressed as based and sized numbers--with the following restriction: The
Verilog language interprets a number of the form sss 'fnnn, when used directly in an expression,
as the unsigned number represented by the two's complement of nnn. The following example
shows two ways to write the expression "minus 12 divided by 3." Note that -12 and -d12 both
evaluate to the same bit pattern, but in an expressionn -d12 loses its identity as signed, negative
number.
integer IntA;
IntA = -12 / 3; // The result is -4.
IntA = -'d 12 / 3; // The result is 1431655761
Arithmetic Operators
The unary operators are the plus (+) and minus (-) signs.
The binary arithmetic operators are the following:
The unary arithmetic operators take precedence over the binary operators. For the arithmetic
operators, if any operand bit value is the unknown value x, then the entire result value is x.
Integer division truncates any fractional part.
An arithmetic operation on a register data type behaves differently than an arithmetic operation
on an integer data type. A register data type is seen as an unsigned value and an integer data type
is seen as a signed value. As a result, when you assign a value of the form
- size base_format number
to a register and then use that register as an expression operand, you are actually using a positive
number that is the two's complement of number. In contrast, when you assign a value of the form
- size base_format number
to an integer and then use that integer as an expression operand, the expression evaluates using
signed arithmetic. The following example shows various ways to divide minus twelve by three
using integer and register data types in expressions.
integer intA;
reg [15:0] regA;
intA = -4'd12;
regA = intA / 3; // Result is 65532, which is the bit pattern
// for 16 bit -4 assigned to an unsigned register
regA = -4'd12; // Result is 65524 because regA is unsigned
intA = regA / 3;
intA = -4'd12 / 3; // Result is 1431655761 because it is evaluated to 32 bits
regA = -12 / 3; // Result is 65532 because regA is unsigned.
Relational Operators
All the relational operators yield the scalar value 0 if the specified relation is false, or the value 1
if the specified relation is true. If, due to unknown bits in the operands, the relation is ambiguous,
then the result is the unknown value (x).
Equality Operators
These four operators compare operands bit for bit, with zero filling if the two operands are of
unequal bit-length. As with the relational operators, the result is 0 if false, 1 if true.
For the == and != operators, if either operand contains an x or a z, then the result is the unknown
value (x). The === and !== operators are treated just like == and != respectively.
All four equality operators have the same precedence.
Logical Operators
The operators logical AND (&&) and logical OR (||) are logical connectives. The result of the
evaluation of a logical comparison is one (defined as true),
zero (defined as false), or, the unknown value (x) if either operand is x or z.
The precedence of && is greater than that of ||, and both are lower than relational and equality
operators.
The third logical operator is the unary logical negation operator !. The negation operator converts
a non-zero or true operand into 0 and a zero or false operand into 1. An ambiguous truth value (
x or z) remains as x.
Bit-Wise Operators
The bit operators perform bit-wise manipulations on the operands--that is, the operator compares
a bit in one operand to its equivalent bit in the other operand to calculate one bit for the result.
When the operands are of unequal bit length, the shorter operand is zero-filled in the most
significant bit positions.
Reduction Operators
The unary reduction operators perform a bit-wise operation on a single operand to produce a
single bit result.
Shift Operators
The shift operators, << and >>, perform left and right shifts of their left operand by the number
of bit positions given by the right operand. Both shift operators fill the vacated bit positions with
zeroes.
The arithmetic shift operators (<<< and >>>) work the same as regular shift operators on unsigned
objects. However, when used on signed objects, the following rules apply:
Arithmetic shift left ignores the signed bit and shifts bit values to the left (like a regular
shift left operator), filling the open bits with zeroes.
Arithmetic shift right propagates all bits, including the signed bit, to the right while
maintaining the signed bit value.
Conditional Operator
The conditional operator has three operands separated by two operators in the following format:
If <cond_expr> evaluates to false, then <false_expr> is evaluated and used as the result. If
<cond_expr> evaluates to true, then <true_expr> is evaluated and used as the result.
Concatenations
A concatenation is the joining together of bits resulting from two or more expressions. The
concatenation is expressed using the brace characters { and }, with commas separating the
expressions within.
Unsized constant numbers are not allowed in concatenations because the size of each operand in
the concatenation is needed to calculate the complete size of the concatenation. Concatenations
can be expressed using a repetition multiplier as shown in the next example:
Operands
There are several types of operands that can be specified in expressions. The simplest type is a
reference to a net or register in its complete form -- that is, just the name of the net or register is
given. In this case, all of the bits making up the net or register value are used as the operand. If a
single bit of a vector net or register is required, then a bit-select operand is used. A part-select
operand is used to reference a group of adjacent bits in a vector net or register.
A memory element can be referenced as an operand.
A concatenation of other operands (including nested concatenations) can be specified as an
operand.
A function call is an operand.
Bit-selects extract a particular bit from a vector net or register. The bit can be addressed using an
expression. The next example specifies the single bit of acc that is addressed by the operand
index.
acc[index]
The actual bit that is accessed by an address is, in part, determined by the declaration of acc. For
instance, each of the declarations of acc shown in the next example causes a particular value of
index to access a different bit:
If the bit select is out of the address bounds or is x, then the value returned by the reference is x.
Several contiguous bits in a vector register or net can be addressed, and are known as part-selects.
A part-select of a vector register or net is given with the following syntax:
vect[ms_expr:ls_expr]
Both expressions must be constant expressions. The first expression must address a more
significant bit than the second expression.
The next example and the bullet items that follow it illustrate the principles of bit addressing. The
code declares an 8-bit register called vect and initializes it to a value of 4. The bullet items
describe how the separate bits of that vector can be addressed.
Memory Addressing
The syntax for a memory address consists of the name of the memory and an expression for the
address, specified with the following format:
mem_name[addr_expr]
The addr_expr can be any expression; therefore, memory indirections can be specified in a single
expression. The next example illustrates memory
indirection:
mem_name[mem_name[3]]
In the above example, mem_name[3]addresses word three of the memory called mem_name. The
value at word three is the index into mem_name that is used by the memory address mem_name
[mem_name[3]]. As with bit-selects, the address bounds given in the declaration of the memory
determine the effect of the address expression. If the index is out of the address bounds or is x,
then the value of the reference is x.
There is no mechanism to express bit-selects or part-selects of memory elements directly. If this is
required, then the memory element has to be first transferred to an appropriately sized temporary
register.
Strings
String operands are treated as constant numbers consisting of a sequence of 8-bit ASCII codes,
one per character, with no special termination character. The syntax of strings is as follows:
5. Assignments
The assignment is the basic mechanism for getting values into nets and registers. An assignment
consists of two parts, a left-hand side and a right-hand side, separated by the equal sign (=). The
right-hand side can be any expression that evaluates to a value. The left-hand side indicates the
variable that the right-hand side is to be assigned to. The left-hand side can take one of the
following forms, depending on whether the assignment is a continuous assignment or a
procedural assignment:
Legal left-hand Side Forms in Assignment Statements:
Continuous Assignments
Continuous assignments drive values onto nets, both vector and scalar. The word continuous is
used to describe this kind of assignment because the assignment is always active. Whenever
simulation causes the value of the right-hand side to change, the assignment is re-evaluated and
the output is propagated. Continuous assignments provide a way to model combinational logic
without specifying an interconnection of gates. Instead, the model specifies the logical expression
that drives the net. The expression on the right-hand side of the continuous assignment is not
restricted in any way, and can even contain a reference to a function. Thus, the result of a case
statement, if statement, or other procedural construct can drive a net.
Syntax
net_declaration ::=
net_type [ vectored | scalared ] [ range ] list_of_net _identifiers ;
| net_type [ vectored | scalared ] [ range ] list_of_net _assignments ;
Syntax
n_output_gate_instance ::=
[ name_of_gate_instance ] ( output_terminal {, output_terminal } , input_terminal )
enable_gate_instance ::=
[ name_of_gate_instance ] ( output_terminal, input_terminal, enable_terminal )
A combinational UDP uses the value of its inputs to determine the next value of its output. Each
UDP has exactly one output that can be in one of three states 0, 1, or x.
A sequential UDP uses the value of its inputs and the current value of its output to determine the
next value of its output.
UDP Definition
Syntax
upd_declaration ::=
primitive
udp_identifier (udp_port_list);
udp_port_declaration { udp_port_declaration }
udp_body
endprimitive
combinational_body ::=
table
combinational_entry { combinational_entry }
endtable
sequential_body ::=
table
sequential_entry { sequential_entry }
endtable
output_symbol ::= 0 | 1 | x | X
level_symbol ::= 0 | 1 | x | X | ? | b | B
edge_symbol ::= r | R | f | F | p | P | n | N | *
UDP definitions are independent of modules; they are at the same level as module definitions in
the syntax hierarchy. They can appear anywhere in the source text, either before or after they are
used inside a module. They cannot appear between the keywords module and endmodule.
UDP Terminals
UDPs can have multiple input terminals, but only one output terminal. They cannot have
bidirectional inout terminals. All UDP terminals are scalar. No vector terminals are allowed.
Only logic values of 0, 1, or x are allowed on input and output. The tri-state value z is not
supported.
The output terminal must be the first terminal in the terminal list.
The output terminal of a sequential UDP requires an additional declaration as type reg. It is illegal
to declare a reg for the output terminal of a combinational UDP.
UDP Declarations
UDPs must contain input and output terminal declarations. The output terminal declaration begins
with the keyword output, followed by one output terminal name. The input terminal declaration
begins with the keyword input, followed by one or more input terminal names.
Sequential UDPs must contain a reg declaration for the output terminal. Combinational UDPs
cannot contain a reg declaration. You can specify the initial value of the output terminal reg in an
initial statement in a sequential UDP.
The state table that defines the behavior of a UDP begins with the keyword table and ends with
the keyword endtable. Each row of the table is created using a variety of characters that indicate
input and output states. Three states--0, 1, and x--are supported. The z state is not supported.
There are a number of special characters you can use to represent certain combinations of state
possibilities. These are listed in "Summary of UDP Symbols".
Combinational UDPs have one field per input and one field for the output. Use a colon to
separate the input fields from the output field. Each row of the table is terminated by a semicolon.
For example, the following state table entry specifies that when the three inputs are all 0, the
output is 0.
table
0 0 0 : 0;
...
endtable
Sequential UDPs have an additional field inserted between the input fields and the output field.
This additional field represents the current state of the UDP and is considered equivalent to the
current output value. It is delimited by colons. For example:
table
0 0 0 : 0 : 0;
...
endtable
The order of the inputs in the state table description must correspond to the order of the inputs in
the port list in the UDP definition header. It is not related to the order of the input declarations.
Each row in the table defines the output for a particular combination of input states. If all inputs
are specified as x, then the output must be specified as x. All combinations that are not explicitly
specified result in a default output state of x.
Consider the following entry from a Sequential UDP state table:
01:?:1;
In this entry, the ? represents a don't-care condition. This symbol indicates iterative substitution of
1, 0, and x. The table entry specifies that when the inputs are 0 and 1, the output is 1 irrespective
of the value of the current state. You do not have to explicitly specify every possible input
combination. All combinations that are not explicitly specified result in a default output state of x.
It is illegal to have the same combination of inputs, including edges, specified for different
outputs.
Like the ? symbol described in the preceding section, there are several symbols that you can use
in UDP definitions to make the description more readable. The following table summarizes the
meaning of all the value symbols that are valid in the table part of a UDP definition.
0 Logic 0
1 Logic 1
x or X Unknown
? Iteration of 0, 1, and x Cannot be used in output field
b or B Iteration of 0 and 1 Like ?, except x is excluded
Cannot be used in output field
- No change Can only be used in output field of a sequential
UDP
(vw) Value change from v to w v and w can be any one of: 0, 1, x, ?, or b
* Same as ?? Any value change on input
r or R Same as 01 Rising edge on input
f or F Same as 10 Falling edge on input
p or P Iteration of (01), (0x), and (x1) Positive edge on input
n or N Iteration of (10), (1x), and (x0) Negative edge on input
Combinational UDPs
In combinational UDPs, the output state is determined solely as a function of the current input
states. Whenever an input changes state, the UDP is evaluated and one of the state table rows is
matched. The output state is set to the value indicated by that row. All combinations of the inputs
that are not explicitly specified drive the output to the unknown value x.
Edge-Sensitive UDPs
Edge-sensitive sequential UDPs model latches and flip-flops. In level-sensitive UDP behavior, the
values of the inputs and the current state are sufficient to determine the output value. Edge-
sensitive behavior differs in that changes in the output are triggered by specific transitions of the
inputs. This makes the state table a transition table.
The previous example has terms like (01) in the input fields. These terms represent transitions of
the input values. Specifically, (01) represents a transition from 0 to 1. The first line in the table
can be interpreted as follows: when clock changes value from 0 to 1 and data equals 0, the output
goes to 0 no matter what the current state is.
Note: Each table entry can have a transition specification on only one input. Entries such as the
one shown below are illegal:
(01)(01)0 : 0 : 1;
As in the combinational and the level-sensitive entries, a ? implies iteration of the entry over the
values 0, 1, and x. A dash (-) in the output column indicates no value change.
If the UDP is sensitive to edges of any input, the desired output state must be specified for all
edges of all inputs.
For synthesis semantics analysis, UDPs must be completely specified for all edges of all inputs.
For unspecified combinations, the output is assumed to hold previous output value.
UDP definitions allow a mixing of level-sensitive and edge-sensitive constructs in the same
description. The following example, which shows an edge-triggered JK flip-flop with
asynchronous preset and clear, illustrates this concept:
Example of Sequential UDP for Level-Sensitive and Edge-Sensitive Behavior
? ?? 01 : ? : 1 ; //preset logic
? ?? *1 : 1 : 1 ;
? ?? 10 : ? : 0 ; //clear logic
? ?? 1* : 0 : 0 ;
r 00 00 : 0 : 1 ; //normal clocking cases
r 00 11 : ? : - ;
r 01 11 : ? : 0 ;
r 10 11 : ? : 1 ;
r 11 11 : 0 : 1 ;
r 11 11 : 1 : 0 ;
f ?? ?? : ? : - ;
b *? ?? : ? : - ; //j and k transition cases
b ?* ?? : ? : - ;
endtable
endprimitive
In this example, the preset and clear logic is level-sensitive. Whenever the preset and clear
combination is 01, the output has value 1. Similarly, whenever the preset and clear combination
has value 10, the output has value 0.
The remaining logic is sensitive to edges of the clock. In the normal clocking cases, the flip-flop
is sensitive to the rising clock edge as indicated by an r in the clock field in those entries. The
insensitivity to the falling edge of clock is indicated by a hyphen (-) in the output field (see UDP
Table Symbols table) for the entry with an f as the value of clock. Remember, you must specify
the desired output for this input transition to avoid unwanted x values at the output. The last two
entries show that the transitions in j and k inputs do not change the output on a steady low or high
clock.
Level-Sensitive Dominance
In some cases, an edge-sensitive and a level-sensitive table entry may conflict with each other. In
these cases, the general rule is that when the input and current state conditions of a level-sensitive
table entry and an edge-sensitive table entry specify conflicting next states, the level-sensitive
entry dominates the edge-sensitive entry.
The following table shows a level-sensitive table entry and an edge-sensitive entry from the
Example of Sequential UDP for Level-Sensitive and Edge-Sensitive Behavior figure. The column
on the right shows a case that is included by the table entry.
The included cases specify opposite next state values for the same input and current state
combination. The level-sensitive case specifies that when the inputs clock, jk and pc are 0 00 01,
and the current state is 0, the output changes to 1. The edge-sensitive case specifies that when
clock falls from 1 to 0, and the other inputs jk and pc are 00 01, and the current state is 0, the
output changes to 0. In this example, the level-sensitive entry dominates, and the output changes
to 1.
Reducing Pessimism
Three-valued logic tends to make pessimistic estimates of the output when one or more inputs are
unknown. You can use UDPs to reduce this pessimism. Consider the following model of a latch:
The last two entries specify what happens when the clock input has value x. If these are omitted,
the output q will go to x whenever the clock is x. This is a pessimistic model, as the latch should
not change its output if it is already 0 and the data input is 0. This is also true when the data input
is 1 and the current output is 1.
Consider the JK flip-flop with preset and clear in the following example. This example has
additional entries for the positive clock (p) edges, the negative clock edges (?0 and 1x), and with
the clock value x. In all of these situations, the output remains unchanged rather than going to x.
Thus, this model is less pessimistic than the latch example given earlier.
UDP Instances
You specify instances of user-defined primitives inside modules in the same manner as gate and
switch primitives. The instance name is optional except when the instance is declared as an array.
Syntax
udp_instance ::=
[ name_of_udp_instance ]
( output_port_connection,
input_port_connection [, input_port_connection} )
The port order is as specified in this syntax definition. Only two delays (rising and falling) can be
specified, because z is not supported for UDPs. An optional
range may be specified for an array of UDP instances. The port connection rules are the same as
outlined in "Port Connection Rules".
8. Behavioral Modeling
All procedures in Verilog are specified within one of the following four statements:
always statement
initial statement
task
function
Tasks and functions are procedures that are enabled from one or more places in other procedures.
Tasks and functions are covered in "Tasks and Functions".
The initial and always statements are enabled at the beginning of simulation. The initial statement
executes only once and its activity dies when the statement has finished. The always statement
executes repeatedly. Its activity dies only when the simulation is terminated. There is no limit to
the number of initial and always blocks that can be defined in a module.
always Statement
Each always statement repeats continuously throughout the whole simulation run.
Syntax
The always statement, because of its looping nature, is useful only when used in conjunction with
some form of step control.
If the sensitivity list of an always statement is not complete, then a latch is inferred.
initial Statement
An initial statement is similar to an always statement, except that it is executed only once.
Syntax
Procedural Assignments
As described in "Assignments", procedural assignments are for updating reg, integer, and memory
variables. There is a significant difference between procedural assignments and continuous
assignments, as described below:
Continuous assignments drive net variables and are evaluated and updated whenever an
input operand changes value.
Procedural assignments update the value of register variables under the control of the
procedural flow constructs that surround them.
The right-hand side of a procedural assignment can be any expression that evaluates to a value.
However, part-selects on the right-hand side must have constant indexes. The left-hand side of the
procedural assignment indicates the variable that receives the assignment from the right-hand
side.
The left-hand side of a procedural assignment can take one of the following forms:
Register or integer variable; that is, an assignment to the name reference of one of these
data types.
Bit-select of a register or integer variable; that is, an assignment to a single bit that leaves
the other bits untouched.
Part-select of a register or integer variable; that is, a part-select of two or more
contiguous bits that leaves the rest of the bits untouched. For the part-select form,
only constant expressions are legal.
Memory element; that is, a single word of a memory. Note: Bit-selects and part-selects
are illegal on memory element references.
concatenation of any of the above
A concatenation of any of the previous four forms, which effectively partitions the
result of the right-hand side expression and assigns the partition parts to the various
parts of the concatenation.
Note: Assignment to a register or time variable does not sign-extend. Assignment to a register
differs from assignment to an integer variable when the right-hand side evaluates to fewer bits
than the left-hand side. Registers are unsigned; if you assign a register to an integer, the variable
does not sign-extend.
A blocking procedural assignment statement is executed before the execution of the statements
that follow it in a sequential block. The non-blocking procedural assignment allows assignment
scheduling without blocking the procedural flow.
Syntax
The assign and deassign procedural assignment statements allow continuous assignments to be
placed onto registers for controlled periods of time. The assign and deassign procedural
statements allow, for example, modeling of asynchronous clear/preset on a D-type edge-triggered
flip-flop, where the clock is inhibited when the clear or preset is active.
Syntax
Conditional Statements
Conditional statements are used to conditionally execute one of the many sets of statements based
on specified conditions.
Syntax
case_item ::=
expression {, expression } : statement_or_null
| default [:] statement_or_null
Each conditional statement must conform to one or both of the following rules:
The conditional statement must be in a sequential (begin-end) procedural block.
The conditional statement must include an else statement.
The expressions are evaluated in order. If any expression is true, the statement set associated with
it is executed, and the whole conditional chain is terminated.
The case statement is a special multi-way decision statement that tests whether an expression
matches one of several other expressions, and branches accordingly. The default statement is
optional. Using multiple default statements in one case statement is illegal syntax.
module L1(in1,in2,cond,out1);
input [1:0] in1,in2,cond;
output [1:0] out1;
reg [1:0] out1;
always @(in1 or in2 or cond)
begin
case(cond)
2'b00 : out1 = in1 & in2;
2'b11 : out1 = in1 | in2;
2'b00 : out1 = in1 ^ in2;
endcase
end
endmodule
Incomplete assignment of signals in a case statement. Consider the following example:
module L2(in1,in2,cond,out1,out2);
input [1:0] in1,in2,cond;
output [1:0] out1,out2;
reg [1:0] out1,out2;
always @(cond or in1 or in2)
begin
case(cond)
2'b00 : out1 = in1 & in2;
2'b01 : out2 = in1 & in2;
2'b11 : out1 = in1 | in2;
2'b10 : out2 = in1 ^ in2;
endcase
end
endmodule
While all possible branches of the case statement have been enumerated, signals out1 and out2 are
not assigned in all branches. Hence a latch is inferred for out1 and out2.
module L3(cond,in1,out1);
input cond;
input [1:0] in1;
output [1:0] out1;
reg [1:0] out1;
always @(in1 or cond)
if(cond)
out1 = in1;
endmodule
Looping Statements
There are three types of looping statements that provide a means of controlling the execution of a
statement, either zero, one, or more times.
Repeat executes a statement a fixed number of times.
While executes a statement until an expression becomes false. If the expression starts out
false, the statement is not executed at all.
for controls execution of its associated statement(s) by a three-step process, as follows:
a.Executes an assignment, normally used to initialize a variable, that controls the
number of loops executed.
b.Evaluates an expression--if the result is zero, the for loop exits. If it is not zero,
the for loop executes its associated statement(s) and then performs step c.
c.Executes an assignment, normally used to modify the value of the loop-control
variable, then repeats step b.
Syntax
loop_statement ::=
repeat ( expression ) statement
| while (expression ) statement
| for ( reg_assignment ; expression ; reg_assignment ) statement
Note: Data dependent loops are not supported. Hence, the repeat statement in the following
example is illegal:
The execution of a procedural statement can be synchronized with a value change on a net or
register or with the occurrence of a declared event.
Syntax
Sequential Blocks
The sequential block statements group two or more statements together so that they act
syntactically like a single statement. In sequential blocks, the statements are executed one after
another.
A sequential block has the following characteristics:
• Statements execute in sequence, one after another.
• Control passes out of the block after the last statement executes.
Blocks can be named by adding block_identifier after the keyword begin. Thus, you can declare
local variables for the block.
In the Verilog language, all variables are static--that is, a unique location exists for all variables
and leaving or entering blocks does not affect the values stored in them. Thus, block names give
a means of uniquely identifying all variables at any simulation time.
Syntax
seq_block ::=
begin
[ : block_identifier { block_item_declaraction } ] { statement }
end
Tasks
A task is enabled by the statement that defines the argument values to be passed to the task, and
by the variables that will receive the results. Control is passed back to the enabling process after
the task is complete. A task can enable other tasks, which in turn can enable still other tasks--with
no limit on the number of tasks enabled. Regardless of how many tasks have been enabled,
control does not return until all enabled tasks are complete.
Syntax
Task Declaration
task_declaration ::=
task task_identifier;
{ task_item_declaration }
statement_or_null
endtask
task_item_declaration ::=
block_item_declaration
| input_declaration
| output_declaration
| inout_declaration
Task Enabling
If an argument in the task is declared as input, then the corresponding expression can be any
expression. If the argument is declared as an output or inout, then the expression must be valid on
the left-hand side of a procedural assignment.
Functions
A function returns a value that is to be used in an expression. Functions have at least one input
argument and no output arguments. They return a single value. Functions are more limited than
tasks. The following rules govern their usage:
• A function cannot enable tasks.
• A function definition must contain at least one input argument.
• A function definition must include an assignment of the function result value to the
internal variable that has the same name as the function.
• A function definition cannot contain an inout declaration or an output declaration.
Syntax
Function Declaration
function_declaration ::=
function [ range_or_type ] function_identifier;
function_item_declaration { function_item_declaration }
statement
endfunction
Function Calling
The function definition implicitly declares a register, internal to the function, with the same name
as the function. This register either defaults to one bit or is the type that range_or_type specifies.
The range_or_type can specify that the function's return value is an integer, or a value with a
range of [n:m] bits. The function assigns its return value to the internal variable bearing the
function's name.
A function call is an operand within an expression.
Module Declaration
module_declaration ::=
module | macromodule module_identifier [ list_of_ports ] ;
{ module_item }
endmodule
module_item ::=
module_item_declaration
| parameter_override
| continuous_assign
| gate_instantiation
| udp_instantiation
| initial_construct
| always_construct
module_item_declaration ::=
parameter_declaration
| input_declaration
| output_declaration
| inout_declaration
| net_declaration
| reg_declaration
| integer_declaration
| task_declaration
| function_declaration
Module Instantiation
module_instantiation ::=
module_identifier [ parameter_value_assignment ]
module_instance {, module_instance };
list_of_module_connections ::=
ordered_port_connection {, ordered_port_connection }
| named_port_connection {, named_port_connection }
When one module instantiates another module, it can alter the values of any parameters declared
within the instantiated module in the following two ways:
1. Through the defparam statement that allows assignment to the parameters using their
hierarchical names
2. Through module instance parameter value assignment that allows values to be assigned
inline during module instantiation.
defparam statement
The defparam statement changes the value of any parameter in any module instance throughout
the design. Specify the value of the parameter by using the hierarchical name of the parameter.
The alternative method of assigning values to parameters is by supplying values to all or some
parameters of particular module instances. The order of values must be the same as the order of
module parameters. It is not necessary to supply values for all parameters. However, all
parameters must be specified.
Note: If a parameter has been defined with an expression containing another parameter,
overriding the value of the second parameter also overrides the value of the first parameter.
Macromodules
A macromodule serves the same purpose as a standard module but has certain limitations. Hence,
it uses significantly lower memory during compilation. Macromodules are normally used for
simple modules that are frequently used in a design. A macromodule can contain only the
following constructs:
• gate and switch instances
• user-defined primitive instances
• nets
The following restrictions apply to the constructs used in macromodules:
• The terminal lists in gate instances and the port lists in UDP instances cannot contain
expressions with variable operands (such as those used in dynamic bit selects).
• Procedural statements and register declarations are illegal in macro modules. If these are
present, then the macromodule is treated as a normal module.
• If there are part-selects or concatenations in the port connections, then the macromodule
instance is treated as a normal module.
You can specify macromodules by using the keyword macromodule in place of the keyword
module in the module definition. Instances of macromodules are specified in exactly the same
way as instances of normal modules.
Ports
Ports interconnect the hardware description consisting of modules, primitives, and macromodules.
For example, module A can instantiate module B, using port connections appropriate to module
A. These port names can differ from the names of internal nets and registers specified in the
definition of module B.
Syntax
port_reference ::=
port_identifier
| port_identifier [ constant_expression ]
| port_identifier [ msb_constant_expression : lsb_constant_expression ]
The port_expression syntax item in the port definition can be one of the following:
• a simple identifier
• a bit-select of a vector declared within the module
• a part-select of a vector declared within the module a concatenation of any of the above
Bit-selects and part-selects result in the automatic expansion of the vector nets they reference.
Note that the port_expression is optional because ports can be defined that do not connect to
anything internal to the module.
Port Declarations
Each port listed in the module definition's list_of_ports must be declared in the body of the
module as an input, output, or bidirectional inout. This is in addition to any other declaration for
a particular port-- for example, a net, a reg, or a wire.
To connect the ports listed in a module instantiation and the ports defined by the instantiated
module, use any of the following methods:
• Connecting module ports by the ordered list
• The ports listed for the module instance are in the same order as the ports listed in the
module definition.
• Connecting module ports by name
• Explicitly link the two names for each side of the connection--the name used in the
module definition, followed by the terminal used in the instantiating module.
Note: The two types of module port connections cannot be mixed; connections to the ports of a
particular module instance must be made either all by position or all by name.
Note: A port that is declared as input but is used as an output, and vice versa, is coerced to inout.
The following rules govern the ways module ports are declared and the ways they are
interconnected:
When the two nets connected by a port are of different net types, the resulting single net is
assigned one of the following:
• The dominating net type, if one of the two nets is "dominating"
• The net type external to the module
The following table shows the resultant net type as a result of collapsing a module port that
connects two nets.
external net: wire & tri wand & triand wor & trior tri0 tri1 supply0
supply1
Internal net:
wire & tri ext ext ext ext ext ext ext
wand & triand int ext warn warn warn ext ext
wor & trior int warn ext warn warn ext ext
ext indicates the external net is used for merging, int indicates that the internal net is used for
merging, and warn indicates that a warning is issued and the external net type is used for
merging.
Hierarchical Names
Every identifier in a Verilog description has a unique hierarchical path name. The hierarchy of
modules and the definition of items such as tasks and named blocks within modules define these
path names. The hierarchy of names can be viewed as a tree structure, in which each module
instance, task, function, or named begin-end block defines a new hierarchical level, or scope.
At the top of the scope are the names of modules for which no instances have been created. The
top of the scope is the root of the hierarchy. Inside any module, each module instance, task
definition, function definition, and named begin-end block defines a new branch of the
hierarchy. Named blocks within named blocks and within tasks and functions also create new
branches.
Each node in the hierarchical name tree is a separate scope with respect to identifiers. A particular
identifier can be declared, at most, once in any scope.
You can reference any named Verilog object uniquely in its full form by concatenating the names
of the modules, tasks, functions, or blocks that contain it. Use the period character to separate
each of the names in the hierarchy. For example, wave.a.bmod.keep.hold shows five levels. The
complete path name to any object starts at a top-level module. You can use this path name from
any level in the description. The first node name in this path name (wave, in the example) can
also be the top of a hierarchy that starts at the level in which the path is being used.
Upwards Name Referencing
The name of a module is sufficient to identify the module and its location in the hierarchy. A
lower-level module can reference items in a module above it in the hierarchy if the name of the
higher-level module is known.
Syntax
<name_of_module>.<name_of_item>
Syntax
system_task_enable ::=
system_task_name [ ( system_task_expression {, system_task_expression } ) ] ;
system_task_name ::=$identifier
The $readmemb and $readmemh system tasks read a specified text file and load its contents into a
specified memory.
Syntax
load_memory_tasks ::=
$readmemb | $readmemh
("file_name", memory_name [, start_addr [, finish_addr]]);
Syntax
Syntax
These compiler directives allow you to include lines of code that are optionally compiled. The
'ifdef compiler directive checks for the definition of a variable name. If the variable name is
defined, the lines following the 'ifdef directive are included. If the variable name is not defined
and an 'else directive exists, the line following the 'else directive are included. The 'endif directive
closes the conditional compilation definition.
Syntax
conditional_compilation_directive ::=
'ifdef text_macro_name
first_group_of_lines
[ 'else
second_group_of_lines
'ifdef ]
13. Pragmas
Pragmas are directives that control the cycle interpretation of the HDL source. They are inserted
as meta-comments in the HDL source.
The translation control pragmas include or exclude a part of the HDL source from processing.
These pragmas are always used in pairs and you can use them anywhere in the HDL description.
You can use these pragmas on complete statements only. You can not specify these pragmas as a
part of an expression.
Note: The code between the pragma pair is still checked for syntax correctness.
synthesis_off and synthesis_on Pragmas
The synthesis_off and synthesis_on pragmas instruct the tool to stop and start processing the code
respectively. These pragmas are normally used to hide simulation-only constructs from the
synthesis. In the following example, the status monitoring code has been hidden from synthesis
using the synthesis_off and synthesis_on pragmas:
Note: The translate_off and translate_on pragmas also work as the synthesis_off and
synthesis_on pragmas.
The verification_on and verification_off pragmas have similar functions as the synthesis_off and
synthesis_on pragmas but are always nested within a pair of the synthesis_off and synthesis_on
pragmas. They also instruct the tool to start and stop processing the code respectively. The
verification_on and verification_off pragmas are normally used to segment out methodology-
specific information in the HDL source. In the following example, the code between the
synthesis_off and synthesis_on pragmas is not synthesized. The code between the verification_on
and verification_off pragmas is used by the tools for methodology verification.
...
//<synthesis_off_directive>
//simulation-specific code
//<verification_on_directive>
cycle C1(cl, reset, num, max);
fc_edge_detector clock (.fc_signal(ck),.fc_risingedge(ck_rising),
.fc_fallingedge(ck_falling));
...
//<verification_off_directive>
//<synthesis_on_directive>
...
The case decoding pragmas control the synthesis of case statements. You can insert the pragma
directives in a case statement wherever a meta-comment can be legally inserted. You can insert
multiple pragma directives in one case statement.
full_case Pragma
The full_case pragma forces the tool to assume that the associated case statement is complete even
when all branches may not be covered. By using of this pragma, you need not write the default
logic and avoid latch inference as a latch may be inferred if you do not assign values of a variable
for all possible conditions. For example,
Here the out value for in == 2 is not defined. Also the default value is not defined. Normally this
construct is inferred as a latch. When you use the full_case pragma directive, this construct is
assumed to be complete that is, all possible values are assumed to have been enumerated.
However, the full_case pragma directive cannot avoid latch inference in some cases. For example:
reg a, b;
reg [1:0] c;
case (c) // <full_case_pragma_directive>
0: begin a = 1; b = 0; end
1: begin a = 0; b = 0; end
2: begin a = 1; b = 1; end
3: b = 1; // a is not assigned here
endcase
In this example, all possible branches of the case statement have been enumerated. But a is not
assigned when c==3. Hence, the full_case pragma directive prevents a latch for b but not for a.
parallel_case Pragma
The parallel_case pragma forces the tool to assume that the branches of the associated case
statement are mutually exclusive. For example, the generated logic is very complex for the
following case statement:
Instead, you may use the parallel_case pragma directive as follows to simplify the generated
logic: