11.2 Basics of the Verilog Language
Chapter start
Previous page
Next page
11.2 Basics of the Verilog Language
A Verilog identifier
[Verilog LRM2.7], including the
names of variables, may contain any sequence of letters, digits, a dollar
sign '$' , and the underscore '_' symbol. The
first character of an identifier must be a letter or underscore; it cannot
be a dollar sign '$' , for example. We cannot use characters
such as '-' (hyphen), brackets, or '#' (for active-low
signals) in Verilog names (escaped
identifiers are an exception). The following is a shorthand way of saying
the same thing:
identifier ::= simple_identifier | escaped_identifier
simple_identifier ::= [a-zA-Z][a-zA-Z_$]
escaped_identifier ::=
\ {Any_ASCII_character_except_white_space} white_space
white_space ::= space | tab | newline
If we think of '::='
as an equal sign, then the preceding "equation" defines the syntax
of an identifier. Usually we use the Backus-Naur form (BNF) to write these
equations. We also use the BNF to describe the syntax of VHDL. There is
an explanation of the BNF in Appendix A. Verilog syntax definitions
are given in Appendix B. In Verilog all names, including keywords and
identifiers, are case-sensitive. Special commands for the simulator (a system
task or a system function) begin with a dollar sign '$' [Verilog LRM 2.7]. Here are some
examples of Verilog identifiers:
module identifiers;
/* Multiline comments in Verilog
look like C comments and // is OK in here. */
// Single-line comment in Verilog.
reg legal_identifier,two__underscores;
reg _OK,OK_,OK_$,OK_123,CASE_SENSITIVE, case_sensitive;
reg \/clock ,\a*b ; // Add white_space after escaped identifier.
//reg ,123_BAD; // Bad names even if we declare them!
initial begin
legal_identifier = 0; // Embedded underscores are OK,
two__underscores = 0; // even two underscores in a row.
_OK = 0; // Identifiers can start with underscore
OK_ = 0; // and end with underscore.
OK$ = 0; // $ sign is OK, but beware foreign keyboards.
OK_123 =0; // Embedded digits are OK.
CASE_SENSITIVE = 0; // Verilog is case-sensitive (unlike VHDL).
case_sensitive = 1;
\/clock = 0; // An escaped identifier with \ breaks rules,
\a*b = 0; // but be careful to watch the spaces!
("Variable CASE_SENSITIVE= %d",CASE_SENSITIVE);
("Variable case_sensitive= %d",case_sensitive);
("Variable \/clock = %d",\/clock );
("Variable \a*b = %d",\a*b );
end endmodule
The following is the output
from this model (future examples in this chapter list the simulator output
directly after the Verilog code).
Variable CASE_SENSITIVE= 0
Variable case_sensitive= 1
Variable /clock = 0
Variable \a*b = 0
11.2.1 Verilog Logic Values
Verilog has a predefined
logic-value system or value set [Verilog
LRM 3.1] that uses four logic values: '0' , '1'
, 'x' , and 'z' (lowercase 'x' and
lowercase 'z' ). The value 'x' represents an uninitialized
or an unknown logic value--an unknown value is either '1' ,
'0' , 'z' , or a value that is in a state of change.
The logic value 'z' represents a high-impedance value, which
is usually treated as an 'x' value. Verilog uses a more complicated
internal logic-value system in order to resolve conflicts between different
drivers on the same node. This hidden logic-value system is useful for switch-level
simulation, but for most ASIC simulation and synthesis purposes we do not
need to worry about the internal logic-value system.
11.2.2 Verilog Data Types
There are several
data types in Verilog--all except one need to be declared before
we can use them. The two main data types are nets and registers
[Verilog LRM 3.2]. Nets are
further divided into several net types. The most common and important net
types are: wire and tri (which are identical); supply1
and supply0 (which are equivalent to the positive and negative power
supplies respectively). The wire data type (which we shall
refer to as just wire from now on) is analogous to a wire in
an ASIC. A wire cannot store or hold a value. A wire
must be continuously driven by an assignment statement (see Section 11.5).
The default initial value for a wire is 'z' [Verilog LRM3.6]. There are also integer,
time, event, and real data types.
module declarations_1;
wire pwr_good, pwr_on, pwr_stable; // Explicitly declare wires.
integer i; // 32-bit, signed (2's complement).
time t; // 64-bit, unsigned, behaves like a 64-bit reg.
event e; // Declare an event data type.
real r; // Real data type of implementation defined size.
// An assign statement continuously drives a wire:
assign pwr_stable = 1'b1; assign pwr_on = 1; // 1 or 1'b1
assign pwr_good = pwr_on & pwr_stable;
initial begin
i = 123.456; // There must be a digit on either side
r = 123456e-3; // of the decimal point if it is present.
t = 123456e-3; // Time is rounded to 1 second by default.
("i=%0g",i," t=%6.2f",t," r=%f",r);
#2 ("TIME=%0d",," ON=",pwr_on,
" STABLE=",pwr_stable," GOOD=",pwr_good);
; end
endmodule
i=123 t=123.00 r=123.456000
TIME=2 ON=1 STABLE=1 GOOD=1
A register data type is declared
using the keyword reg and is comparable to a variable in a
programming language. On the LHS of an assignment a register data type (which
we shall refer to as just reg from now on) is updated immediately
and holds its value until changed again. The default initial value for a
reg is 'x' . We can transfer information directly
from a wire to a reg as shown in the following
code:
module declarations_2;
reg Q, Clk; wire D;
// Drive the wire (D):
assign D = 1;
// At a +ve clock edge assign the value of wire D to the reg Q:
always @(posedge Clk) Q = D;
initial Clk = 0; always #10 Clk = ~ Clk;
initial begin #50; ; end
always begin
("T=%2g", ," D=",D," Clk=",Clk," Q=",Q); #10; end
endmodule
T= 0 D=z Clk=0 Q=x
T=10 D=1 Clk=1 Q=x
T=20 D=1 Clk=0 Q=1
T=30 D=1 Clk=1 Q=1
T=40 D=1 Clk=0 Q=1
We shall discuss assignment
statements in Section 11.5. For now, it is
important to recognize that a reg is not always equivalent
to a hardware register, flip-flop, or latch. For example, the following
code describes purely combinational logic:
module declarations_3;
reg a,b,c,d,e;
initial begin
#10; a = 0;b = 0;c = 0;d = 0; #10; a = 0;b = 1;c = 1;d = 0;
#10; a = 0;b = 0;c = 1;d = 1; #10; ;
end
always begin
@(a or b or c or d) e = (a|b)&(c|d);
("T=%0g",," e=",e);
end
endmodule
T=10 e=0
T=20 e=1
T=30 e=0
A single-bit wire
or reg is a scalar (the default). We may also declare
a wire or reg as a vector with a range
of bits [Verilog LRM 3.3].
In some situations we may use implicit declaration for a scalar wire
; it is the only data type we do not always need to declare. We must use
explicit declaration for a vector wire or any reg
. We may access (or expand) the range of bits in a vector one at
a time, using a bit-select, or as a contiguous subgroup of bits (a
continuous sequence of numbers--like a straight in poker) using a part-select
[Verilog LRM 4.2]. The following
code shows some examples:
module declarations_4;
wire Data; // A scalar net of type wire.
wire [31:0] ABus, DBus; // Two 32-bit-wide vector wires:
// DBus[31] = leftmost = most-significant bit = msb
// DBus[0] = rightmost = least-significant bit = lsb
// Notice the size declaration precedes the names.
// wire [31:0] TheBus, [15:0] BigBus; // This is illegal.
reg [3:0] vector; // A 4-bit vector register.
reg [4:7] nibble; // msb index < lsb index is OK.
integer i;
initial begin
i = 1;
vector = 'b1010; // Vector without an index.
nibble = vector; // This is OK too.
#1; ("T=%0g",," vector=", vector," nibble=", nibble);
#2; ("T=%0g",," Bus=%b",DBus[15:0]);
end
assign DBus [1] = 1; // This is a bit-select.
assign DBus [3:0] = 'b1111; // This is a part-select.
// assign DBus [0:3] = 'b1111; // Illegal : wrong direction.
endmodule
T=1 vector=10 nibble=10
T=3 Bus=zzzzzzzzzzzz1111
There are no multidimensional
arrays in Verilog, but we may declare a memory data type as an array
of registers [Verilog LRM 3.8]:
module declarations_5;
reg [31:0] VideoRam [7:0]; // An 8-word by 32-bit wide memory.
initial begin
VideoRam[1] = 'bxz; // We must specify an index for a memory.
VideoRam[2] = 1;
VideoRam[7] = VideoRam[VideoRam[2]]; // Need 2 clock cycles for this.
VideoRam[8] = 1; // Careful! the compiler won't complain about this!
// Verify what we entered:
("VideoRam[0] is %b",VideoRam[0]);
("VideoRam[1] is %b",VideoRam[1]);
("VideoRam[2] is %b",VideoRam[2]);
("VideoRam[7] is %b",VideoRam[7]);
end
endmodule
VideoRam[0] is xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
VideoRam[1] is xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz
VideoRam[2] is 00000000000000000000000000000001
VideoRam[7] is xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz
We may also declare an integer
array or time array in the same way as an array of reg
, but there are no real arrays [Verilog
LRM 3.9]:
module declarations_6;
integer Number [1:100]; // Notice that size follows name
time Time_Log [1:1000]; // - as in an array of reg.
// real Illegal [1:10]; // Illegal. There are no real arrays.
endmodule
11.2.3 Other Wire Types
There are the following
other Verilog wire types (rarely used in ASIC design) [Verilog
LRM 3.7]:
wand , wor , triand
, and trior model wired logic. Wiring, or dotting, the outputs
of two gates generates a logic function (in emitter-coupled logic, ECL,
or in an EPROM, for example). This is one area in which the logic values
'z' and 'x' are treated differently.
tri0 and tri1 model
resistive connections to VSS or VDD.
trireg is like a wire
but associates some capacitance with the net, so it can model charge storage.
There are also other
keywords that may appear in declarations:
scalared and vectored
are properties of vectors [Verilog
LRM 3.3].
small , medium
, and large model the charge strength of trireg
connections [Verilog LRM 7].
11.2.4 Numbers
Constant numbers
are integer or real constants [Verilog
LRM 2.5]. Integer constants are written as
width'radix value
where width
and radix are optional. The radix (or base) indicates
the type of number: decimal ( d or D ),
hex ( h or H ), octal ( o
or O ), or binary ( b or B
). A number may be sized or unsized. The length of an unsized
number is implementation dependent. We can use '1' and '0'
as numbers since they cannot be identifiers, but we must write 1'bx
and 1'bz for 'x' and 'z' . A number
may be declared as a parameter [Verilog
LRM 3.10]. A parameter assignment belongs inside a module declaration
and has local scope [Verilog
LRM3.11]. Real constants are written using decimal (100.0) or
scientific notation (1e2) and follow IEEE Std 754-1985 for double-precision
floating-point numbers. Reals are rounded to the nearest integer, ties (numbers
that end in .5) round away from zero [Verilog
LRM 3.9], but not all implementations follow this rule (the output from
the following code is from VeriWell, which rounds ties toward zero for negative
integers).
module constants;
parameter H12_UNSIZED = 'h 12; // Unsized hex 12 = decimal 18.
parameter H12_SIZED = 6'h 12; // Sized hex 12 = decimal 18.
// Note: a space between base and value is OK.
// Note: `' (single apostrophes) are not the same as the ' character.
parameter D42 = 8'B0010_1010; // bin 101010 = dec 42
// OK to use underscores to increase readability.
parameter D123 = 123; // Unsized decimal (the default).
parameter D63 = 8'o 77; // Sized octal, decimal 63.
// parameter ILLEGAL = 1'o9; // No 9's in octal numbers!
// A = 'hx and B = 'ox assume a 32 bit width.
parameter A = 'h x, B = 'o x, C = 8'b x, D = 'h z, E = 16'h ????;
// Note the use of ? instead of z, 16'h ???? is the same as 16'h zzzz.
// Also note the automatic extension to a width of 16 bits.
reg [3:0] B0011,Bxxx1,Bzzz1; real R1,R2,R3; integer I1,I3,I_3;
parameter BXZ = 8'b1x0x1z0z;
initial begin
B0011 = 4'b11; Bxxx1 = 4'bx1; Bzzz1 = 4'bz1; // Left padded.
R1 = 0.1e1; R2 = 2.0; R3 = 30E-01; // Real numbers.
I1 = 1.1; I3 = 2.5; I_3 = -2.5; // IEEE rounds away from 0.
end initial begin #1;
("H12_UNSIZED, H12_SIZED (hex) = %h, %h",H12_UNSIZED, H12_SIZED);
("D42 (bin) = %b",D42," (dec) = %d",D42);
("D123 (hex) = %h",D123," (dec) = %d",D123);
("D63 (oct) = %o",D63);
("A (hex) = %h",A," B (hex) = %h",B);
("C (hex) = %h",C," D (hex) = %h",D," E (hex) = %h",E);
("BXZ (bin) = %b",BXZ," (hex) = %h",BXZ);
("B0011, Bxxx1, Bzzz1 (bin) = %b, %b, %b",B0011,Bxxx1,Bzzz1);
("R1, R2, R3 (e, f, g) = %e, %f, %g", R1, R2, R3);
("I1, I3, I_3 (d) = %d, %d, %d", I1, I3, I_3);
end
endmodule
H12_UNSIZED, H12_SIZED (hex) = 00000012, 12
D42 (bin) = 00101010 (dec) = 42
D123 (hex) = 0000007b (dec) = 123
D63 (oct) = 077
A (hex) = xxxxxxxx B (hex) = xxxxxxxx
C (hex) = xx D (hex) = zzzzzzzz E (hex) = zzzz
BXZ (bin) = 1x0x1z0z (hex) = XZ
B0011, Bxxx1, Bzzz1 (bin) = 0011, xxx1, zzz1
R1, R2, R3 (e, f, g) = 1.000000e+00, 2.000000, 3
I1, I3, I_3 (d) = 1, 3, -2
11.2.5 Negative Numbers
Integer numbers are
signed (two's complement) or unsigned. The following example
illustrates the handling of negative constants [Verilog LRM 3.2
, 4.1]:
module negative_numbers;
parameter PA = -12, PB = -'d12, PC = -32'd12, PD = -4'd12;
integer IA , IB , IC , ID ; reg [31:0] RA , RB , RC , RD ;
initial begin #1;
IA = -12; IB = -'d12; IC = -32'd12; ID = -4'd12;
RA = -12; RB = -'d12; RC = -32'd12; RD = -4'd12; #1;
(" parameter integer reg[31:0]");
("-12 =",PA,IA,,,RA);
(" ",,,,PA,,,,IA,,,,,RA);
("-'d12 =",,PB,IB,,,RB);
(" ",,,,PB,,,,IB,,,,,RB);
("-32'd12 =",,PC,IC,,,RC);
(" ",,,,PC,,,,IC,,,,,RC);
("-4'd12 =",,,,,,,,,,PD,ID,,,RD);
(" ",,,,,,,,,,,PD,,,,ID,,,,,RD);
end
endmodule
parameter integer reg[31:0]
-12 = -12 -12 4294967284
fffffff4 fffffff4 fffffff4
-'d12 = 4294967284 -12 4294967284
fffffff4 fffffff4 fffffff4
-32'd12 = 4294967284 -12 4294967284
fffffff4 fffffff4 fffffff4
-4'd12 = 4 -12 4294967284
4 fffffff4 fffffff4
Verilog only "keeps track"
of the sign of a negative constant if it is (1) assigned to an integer
or (2) assigned to a parameter without using a base (essentially
the same thing). In other cases (even though the bit representations may
be identical to the signed number--hexadecimal fffffff4 in
the previous example), a negative constant is treated as an unsigned number.
Once Verilog "loses" the sign, keeping track of signed numbers
becomes your responsibility (see also Section 11.3.1).
11.2.6 Strings
The code listings
in this book use Courier font. The ISO/ANSI standard for the
ASCII code defines the characters, but not the appearance of the graphic
symbol in any particular font. The confusing characters are the quote and
accent characters:
module characters; /*
" is ASCII 34 (hex 22), double quote.
' is ASCII 39 (hex 27), tick or apostrophe.
/ is ASCII 47 (hex 2F), forward slash.
\ is ASCII 92 (hex 5C), back slash.
` is ASCII 96 (hex 60), accent grave.
| is ASCII 124 (hex 7C), vertical bar.
There are no standards for the graphic symbols for codes above 128.
´ is 171 (hex AB), accent acute in almost all fonts.
" is 210 (hex D2), open double quote, like 66 (in some fonts).
" is 211 (hex D3), close double quote, like 99 (in some fonts).
` is 212 (hex D4), open single quote, like 6 (in some fonts).
' is 213 (hex D5), close single quote, like 9 (in some fonts).
*/ endmodule
Here is an example showing
the use of string constants [Verilog
LRM 2.6]:
module text;
parameter A_String = "abc"; // string constant, must be on one line
parameter Say = "Say \"Hey!\"";
// use escape quote \" for an embedded quote
parameter Tab = " "; // tab character
parameter NewLine = "
"; // newline character
parameter BackSlash = "\"; // back slash
parameter Tick = "'"; // ASCII code for tick in octal
// parameter Illegal = "@"; // illegal - no such ASCII code
initial begin("A_String(str) = %s ",A_String," (hex) = %h ",A_String);
("Say = %s ",Say," Say \"Hey!\"");
("NewLine(str) = %s ",NewLine," (hex) = %h ",NewLine);
("\(str) = %s ",BackSlash," (hex) = %h ",BackSlash);
("Tab(str) = %s ",Tab," (hex) = %h ",Tab,"1 newline...");
("
");
("Tick(str) = %s ",Tick," (hex) = %h ",Tick);
#1.23; ("Time is %t", );
end
endmodule
A_String(str) = abc (hex) = 616263
Say = Say \"Hey!\" Say "Hey!"
NewLine(str) =
(hex) = 0a
\(str) = \ (hex) = 5c
Tab(str) = (hex) = 09 1 newline...
Tick(str) = ' (hex) = 27
Time is 1
Instead of parameters you may
use a define directive that is a compiler directive, and not
a statement [Verilog LRM 16]. The define directive has
global scope:
module define;
define G_BUSWIDTH 32 // Bus width parameter (G_ for global).
/* Note: there is no semicolon at end of a compiler directive. The character ` is ASCII 96 (hex 60), accent grave, it slopes down from left to right. It is not the tick or apostrophe character ' (ASCII 39 or hex 27)*/
wire [`G_BUSWIDTH:0]MyBus; // A 32-bit bus.
endmodule
Chapter start
Previous page
Next page
|