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 real and event data types.

0represents a logic zero, or a false condition
1represents a logic one, or a true condition
xrepresents an unknown logic value (can be zero or one)
zrepresents 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 Z.

verilog value system

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 or 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 or 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

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.

nets and variables

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. A 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.

breadboard-wires

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
wire type net

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

Variables

reg type variable

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.

Verilog data-type 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.

flip-flops with different widths

Other data-types

integer

An 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

A 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

A real variable can store floating point values and can be assigned the same way as integer and reg.


    real        float;              // float = 12.344  - can store floating numbers

Datatypes Example


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
 Simulation Log
ncsim> run
int_a 	= 0xcafe1234
real_b 	= 0.12346
time_c 	= 20
ncsim: *W,RNQUIE: Simulation is complete.

Verilog Strings

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".

 Simulation Log
ncsim> run
str1 = Hello World
str2 = World
str3 =          
Hello World
ncsim: *W,RNQUIE: Simulation is complete.