The primary intent of data-types in the Verilog language is to represent data storage elements like bits in a flip-flop and transmission elements like wires that connect between logic gates and sequential structures.
What values do variables hold ?
Almost all data-types can only have one of the four different values as given below except for
event data types.
|0||represents a logic zero, or a false condition|
|1||represents a logic one, or a true condition|
|x||represents an unknown logic value (can be zero or one)|
|z||represents a high-impedance state|
The following image shows how these values are represented in timing diagrams and simulation waveforms. Most simulators use this convention where red stands for
X and orange in the middle stands for high-impedance or
What does the verilog value-set imply ?
Since Verilog is essentially used to describe hardware elements like flip-flops and combinational logic like NAND and NOR, it has to model the value system found in hardware. A logic one would represent the voltage supply Vdd which can range anywhere between 0.8V to more than 3V based on the fabrication technology node. A logic zero would represent ground and hence a value of 0V.
x means that the value is simply unknown at the time, and could be either 0 or 1. This is quite different from the way
X is treated in boolean logic, where it means "don't care".
As with any incomplete electric circuit, the wire that is not connected to anything will have a high-impedance at that node and is represented by
z. Even in verilog, any unconnected wire will result in a high impedance.
Nets and Variables
Nets and variables are the two main groups of data types which represent different hardware structures and differ in the way they are assigned and retain values.
Nets are used to connect between hardware entities like logic gates and hence do not store any value on its own. In the image shown below, a net called net_11 is used to connect between the output of the AND gate to the first input of the flip-flop called data_0. In a similar way, the two inputs of the AND gate are connected to nets net_45 and net_67.
There are different types of nets each with different characteristics, but the most popular and widely used net in digital designs is of type
wire is a Verilog data-type used to connect elements and to connect nets that are driven by a single gate or continuous assignment. The
wire is similar to the electrical wire that is used to connect two components on a breadboard.
When there is a requirement for mulitple nets, they can be bunched together to form a single
wire. In the image shown below, we have a 4-bit wire that can send 4 separate values on each one of the wires. Such entities with a width more than 1 are called vectors as we shall see in the next article.
wire [3:0] n0; // 4-bit wire -> this is a vector
It is illegal to redeclare a name already declared by a net, parameter or variable as shown in the code below.
module design; wire abc; wire a; wire b; wire c; wire abc; // Error: Identifier "abc" previously declared assign abc = a & b | c; endmodule
A variable on the other hand is an abstraction of a data storage element and can hold values. A flip-flop is a good example of a storage element.
reg can be used to model hardware registers since it can hold values between assignments. Note that a
reg need not always represent a flip-flop because it can also be used to represent combinational logic.
In the image shown on the left, we have a flip-flop that can store 1 bit and the flip-flop on the right can store 4-bits.
integer is a general purpose variable of 32-bits wide that can be used for other purposes while modeling hardware and stores integer values.
integer count; // Count is an integer value > 0
time variable is unsigned, 64-bits wide and can be used to store simulation time quantities for debugging purposes. A
realtime variable simply stores time as a floating point quantity.
time end_time; // end_time can be stored a time value like 50ns realtime rtime; // rtime = 40.25ps
real variable can store floating point values and can be assigned the same way as
real float; // float = 12.344 - can store floating numbers
module testbench; integer int_a; // Integer variable real real_b; // Real variable time time_c; // Time variable initial begin int_a = 32'hcafe_1234; // Assign an integer value real_b = 0.1234567; // Assign a floating point value #20; // Advance simulation time by 20 units time_c = $time; // Assign current simulation time // Now print all variables using $display system task $display ("int_a = 0x%0h", int_a); $display ("real_b = %0.5f", real_b); $display ("time_c = %0t", time_c); end endmodule
ncsim> run int_a = 0xcafe1234 real_b = 0.12346 time_c = 20 ncsim: *W,RNQUIE: Simulation is complete.
Strings are stored in
reg, and the width of the
reg variable has to be large enough to hold the string. Each character in a string represents an ASCII value and requires 1 byte. If the size of the variable is smaller than the string, then Verilog truncates the leftmost bits of the string. If the size of the variable is larger than the string, then Verilog adds zeros to the left of the string.
// "Hello World" requires 11 bytes reg [8*11:1] str = "Hello World"; // Variable can store 11 bytes, str = "Hello World" reg [8*5:1] str = "Hello World"; // Variable stores only 5 bytes (rest is truncated), str = "World" reg [8*20:1] str = "Hello World"; // Variable can store 20 bytes (rest is padded with zeros), str = " Hello World"
Here is a full example showing how the three variables given above can be simulated.
module testbench; reg [8*11:1] str1; reg [8*5:1] str2; reg [8*20:1] str3; initial begin str1 = "Hello World"; str2 = "Hello World"; str3 = "Hello World"; $display ("str1 = %s", str1); $display ("str2 = %s", str2); $display ("str3 = %s", str3); end endmodule
Note that str1 has the right size to store all 11 bytes of the string "Hello World" and hence the whole string gets printed. However str2 can store only 5 bytes and hence the upper 6 bytes get truncated and end up with storing only "World". The third variable str3 is larger than 11 bytes and pads empty spaces to the left and hence the value stored in it becomes " Hello World".
ncsim> run str1 = Hello World str2 = World str3 = Hello World ncsim: *W,RNQUIE: Simulation is complete.