Value Set
Verilog supports four values and eight strengths to model the functionality of real
hardware. The four value levels are listed below
0 Logic zero, false condition
1 Logic one, true condition
x Unknown logic value
z High impedance, floating state
In addition to logic values, strength levels are often used to resolve conflicts between
drivers of different strengths in digital circuits. Value levels 0 and 1 can have the
strength levels listed
Strength Level Type Degree
supply Driving strongest
strong Driving
pull Driving
large Storage
weak Driving
medium Storage
small Storage
highz High Impedance weakest
If two signals of unequal strengths are driven on a wire, the stronger signal prevails.
For example, if two signals of strength strong1 and weak0 contend, the result is
resolved as a strong1. If two signals of equal strengths are driven on a wire, the result
is unknown. If two signals of strength strong1 and strong0 conflict, the result is an x.
Strength levels are particularly useful for accurate modeling of signal contention,
MOS devices, dynamic MOS, and other low-level devices. Only trireg nets can have
storage strengths large,medium, and small.
Registers
Registers represent data storage elements. Registers retain value until another value is
placed onto them. Do not confuse the term registers in Verilog with hardware
registers built from edge-triggered flipflops in real circuits. In Verilog, the term
register merely means a variable that can hold a value. Unlike a net, a register does
not need a driver. Verilog registers do not need a clock as hardware registers do.
Values of registers can be changed anytime in a simulation by assigning a new value
to the register. Register data types are commonly declared by the keyword reg. The
default value for a reg data type is x. An example of how registers are used is shown
below
reg reset; // declare a variable reset that can hold its value
initial
begin
reset = 1'b1; //initialize reset to 1 to reset the digital circuit.
#100 reset = 1'b0; // after 100 time units reset is deasserted.
end
Registers can also be declared as signed variables. Such registers can be used for
signed arithmetic as shown below
reg signed [63:0] m; // 64 bit signed value
integer i; // 32 bit signed value
Nets
Nets represent connections between hardware elements. Just as in real circuits, nets
have values continuously driven on them by the outputs of devices that they are
connected to.
Nets are declared primarily with the keyword wire. Nets are one-bit values by default
unless they are declared explicitly as vectors. The terms wire and net are often used
interchangeably. The default value of a net is z (except the trireg net, which defaults
to x ). Nets get the output value of their drivers. If a net has no driver, it gets the value
z.
wire a; // Declare net a for the above circuit
wire b,c; // Declare two wires b,c for the above circuit
wire d = 1'b0; // Net d is fixed to logic value 0 at declaration.
Note that net is not a keyword but represents a class of data types such as wire, wand,
wor, tri, triand, trior, trireg, etc. The wire declaration is used most frequently.
Vectors
Nets or reg data types can be declared as vectors (multiple bit widths). If bit width is
not specified, the default is scalar (1-bit).
wire a; // scalar net variable, default
wire [7:0] bus; // 8-bit bus
wire [31:0] busA,busB,busC; // 3 buses of 32-bit width.
reg clock; // scalar register, default
reg [0:40] virtual_addr; // Vector register, virtual address 41 bits wide
Vectors can be declared at [high# : low#] or [low# : high#], but the left number in the
squared brackets is always the most significant bit of the vector. In the example
shown above, bit 0 is the most significant bit of vector virtual_addr.
Vector Part Select
For the vector declarations shown above, it is possible to address bits or parts of
vectors.
busA[7] // bit # 7 of vector busA
bus[2:0] // Three least significant bits of vector bus,
// using bus[0:2] is illegal because the significant bit should always be on the left
of a range specification
virtual_addr[0:1] // Two most significant bits of vector virtual_addr
Variable Vector Part Select
Another ability provided in Verilog is to have variable part selects of a vector. This
allows part selects to be put in for loops to select various parts of the vector. There are
two special part-select operators:
[<starting_bit>+:width] - part-select increments from starting bit
[<starting_bit>-:width] - part-select decrements from starting bit
The starting bit of the part select can be varied, but the width has to be constant. The
following example shows the use of variable vector part select:
reg [255:0] data1; //Little endian notation
reg [0:255] data2; //Big endian notation
reg [7:0] byte;
//Using a variable part select, one can choose parts
byte = data1[31-:8]; //starting bit = 31, width =8 => data[31:24]
byte = data1[24+:8]; //starting bit = 24, width =8 => data[31:24]
byte = data2[31-:8]; //starting bit = 31, width =8 => data[24:31]
byte = data2[24+:8]; //starting bit = 24, width =8 => data[24:31]
//The starting bit can also be a variable. The width has to be constant. Therefore,
one can use the variable part select in a loop to select all bytes of //the vector.
for (j=0; j<=31; j=j+1)
byte = data1[(j*8)+:8]; //Sequence is [7:0], [15:8]... [255:248]
//Can initialize a part of the vector
data1[(byteNum*8)+:8] = 8'b0; //If byteNum = 1, clear 8 bits [15:8]
Integer , Real, and Time Register Data Types
Integer, real, and time register data types are supported in Verilog.
Integer
An integer is a general purpose register data type used for manipulating quantities.
Integers are declared by the keyword integer. Although it is possible to use reg as a
general-purpose variable, it is more convenient to declare an integer variable for
purposes such as counting. The default width for an integer is the host-machine word
size, which is implementation-specific but is at least 32 bits. Registers declared as
data type reg store values as unsigned quantities, whereas integers store values as
signed quantities.
integer counter; // general purpose variable used as a counter.
initial
counter = -1; // A negative one is stored in the counter
Real
Real number constants and real register data types are declared with the keyword
real.They can be specified in decimal notation (e.g., 3.14) or in scientific notation
(e.g., 3e6, which is 3 x 106 ). Real numbers cannot have a range declaration, and their
default value is 0. When a real value is assigned to an integer, the real number is
rounded off to the nearest integer.
real delta; // Define a real variable called delta
initial
begin
delta = 4e10; // delta is assigned in scientific notation
delta = 2.13; // delta is assigned a value 2.13
end
integer i; // Define an integer i
initial
i = delta; // i gets the value 2 (rounded value of 2.13)
Time
Verilog simulation is done with respect to simulation time. A special time register
data type is used in Verilog to store simulation time. A time variable is declared with
the keyword time. The width for time register data types is implementation-specific
but is at least 64 bits.The system function $time is invoked to get the current
simulation time.
time save_sim_time; // Define a time variable save_sim_time
initial
save_sim_time = $time; // Save the current simulation time
Simulation time is measured in terms of simulation seconds. The unit is denoted by s,
the same as real time. However, the relationship between real time in the digital
circuit and simulation time is left to the user.
Arrays are allowed in Verilog for reg, integer, time, real, realtime and vector
register data types. Multi-dimensional arrays can also be declared with any number of
dimensions. Arrays of nets can also be used to connect ports of generated instances.
Each element of the array can be used in the same fashion as a scalar or vector net.
Arrays are accessed by <array_name>[<subscript>]. For multi-dimensional arrays,
indexes need to be provided for each dimension.
integer count[0:7]; // An array of 8 count variables
reg bool[31:0]; // Array of 32 one-bit boolean register
variables
time chk_point[1:100]; // Array of 100 time checkpoint variables
reg [4:0] port_id[0:7]; // Array of 8 port_ids; each port_id is 5 bits
wide
integer matrix[4:0][0:255]; // Two dimensional array of integers
reg [63:0] array_4d [15:0][7:0][7:0][255:0]; //Four dimensional array
wire [7:0] w_array2 [5:0]; // Declare an array of 8 bit
vector wire
wire w_array1[7:0][5:0]; // Declare an array of single bit
wires
It is important not to confuse arrays with net or register vectors. A vector is a single
element that is n-bits wide. On the other hand, arrays are multiple elements that are 1-
bit or n-bits wide.
Examples of assignments to elements of arrays discussed above are shown below:
count[5] = 0; // Reset 5th element of array of count variables
chk_point[100] = 0; // Reset 100th time check point value
port_id[3] = 0; // Reset 3rd element (a 5-bit value) of port_id array.
matrix[1][0] = 33559; // Set value of element indexed by [1][0] to 33559
array_4d[0][0][0][0][15:0] = 0; //Clear bits 15:0 of the register accessed by
indices [0][0][0][0]
port_id = 0; // Illegal syntax - Attempt to write the entire array
matrix [1] = 0; // Illegal syntax - Attempt to write [1][0]..[1][255]
Memories
In digital simulation, one often needs to model register files, RAMs, and ROMs.
Memories are modeled in Verilog simply as a one-dimensional array of registers.
Each element of the array is known as an element or word and is addressed by a
single array index. Each word can be one or more bits. It is important to differentiate
between n 1-bit registers and one n-bit register. A particular word in memory is
obtained by using the address as a memory array subscript.
reg mem1bit[0:1023]; // Memory mem1bit with 1K 1-bit words
reg [7:0] membyte[0:1023]; // Memory membyte with 1K 8-bit words(bytes)
membyte[511]; // Fetches 1 byte word whose address is 511.
Parameters
Verilog allows constants to be defined in a module by the keyword parameter.
Parameters cannot be used as variables. Parameter values for each module instance
can be overridden individually at compile time. This allows the module instances to
be customized. Parameter types and sizes can also be defined.
parameter port_id = 5; // Defines a constant port_id
parameter cache_line_width = 256; // Constant defines width of cache line
parameter signed [15:0] WIDTH; // Fixed sign and range for parameter WIDTH
Module definitions may be written in terms of parameters. Hardcoded numbers should
be avoided. Parameters values can be changed at module instantiation or by using the
defparam statement. Thus, the use of parameters makes the module definition
flexible. Module behavior can be altered simply by changing the value of a parameter.
Verilog HDL local parameters (defined using keyword localparam -) are identical to
parameters except that they cannot be directly modified with the defparam statement
or by the ordered or named parameter value assignment. The localparam keyword is
used to define parameters when their values should not be changed. For example, the
state encoding for a state machine can be defined using localparam. The state
encoding cannot be changed. This provides protection against inadvertent parameter
redefinition.
localparam state1 = 4'b0001,
state2 = 4'b0010,
state3 = 4'b0100,
state4 = 4'b1000;
Strings
Strings can be stored in reg. The width of the register variables must be large enough
to hold the string. Each character in the string takes up 8 bits (1 byte). If the width of
the register is greater than the size of the string, Verilog fills bits to the left of the
string with zeros. If the register width is smaller than the string width, Verilog
truncates the leftmost bits of the string. It is always safe to declare a string that is
slightly wider than necessary.
reg [8*18:1] string_value; // Declare a variable that is 18 bytes
wide
initial
string_value = "Hello Verilog World"; // String can be stored in variable
Special characters serve a special purpose in displaying strings, such as newline, tabs,
and displaying argument values. Special characters can be displayed in strings only
when they are preceded by escape characters, as shown below:
Escaped Characters Character Displayed
n newline
t tab
%% %
" "
ooo Character written in 1?3 octal digits