Welcome ! This website will help YOU (recent graduates/professionals) learn verification languages like SystemVerilog and UVM. Register for free and access more content !

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. Almost all data-types can only have one of the four different values as given below except for real and 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
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 technology node the digital circuit will be built. 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.

Watch a quick video !

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 (except for trireg) like shown in the image below. A net is used to connect between a NAND gate and a flip-flop. In a similar way, the NAND inputs and other flip flop pins are wired to other components via other nets. A variable is an abstraction of a data storage element and can hold values. A flip-flop is a good example of a storage element.

nets and variables

There are different types of nets each with different characteristics as shown in the table, but the most popular and widely used net in digital designs is the wire. It is used to connect elements and for nets that are driven by a single gate or continuous assignment. The tri net type can be used where multiple drivers drive a net. It is illegal to redeclare a name already declared by a net, parameter or variable.

module design;
  wire    abc;
  wire    abc;   // Error: Identifier "abc" previously declared
  reg     abc;   // Error: Identifier "abc" previously declared
reg type variable

Now we'll take a look at the different types of variables supported in Verilog. reg can be used to model hardware registers since it can hold values between assignments. Note that a reg need not represent a hardware storage element because it can also be used to represent combinational logic.

Other data-types : integer, real

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. A time variable is unsigned, 64-bits wide and can be used to store simulation time quantities for debugging purposes. A real variable can store floating point values and can be assigned the same way as integer and reg. A realtime variable simply stores time as a floating point quantity.

    integer     count;              // Count is an integer value > 0
    time        end_time;           // end_time can be stored a time value like 50ns
    real        float;              // float = 12.344  - can store floating numbers
    realtime    rtime;              // rtime = 40.25ps 
wire type net

Scalars and Vectors

A net or reg declaration without a range specification is considered 1-bit wide and is a scalar. If a range is specified, then the net or reg becomes a multibit entity known as a vector.

scalar and vector in verilog
  wire       o_nor;           // single bit scalar net
  wire [7:0]  o_flop;          // 8-bit vector net
  reg         parity;          // single bit scalar variable
  reg  [31:0] addr;            // 32 bit vector variable to store address

The range gives the ability to address individual bits in a vector. The most significant bit of the vector should be specified as the left hand value in the range while the least significant bit of the vector should be specified on the right.

  wire  [msb:lsb]   name;
  integer           my_msb;
  wire [15:0]        priority;      // msb = 15, lsb = 0
  wire [my_msb: 2]   prior;         // illegal

A 16 bit wide net called priority will be created in the example above. Note that the msb and lsb should be a constant expression and cannot be substituted by a variable. But they can be any integer value - positive, negative or zero; and the lsb value can be greater than, equal to or less than msb value.


Any bit in a vectored variable can be individually selected and assigned a new value as shown below. This is called as a bit-select. If the bit-select is out of bounds or the bit-select is x or z, then the value returned will be x.

bit-select in verilog
  reg [7:0]      addr;         // 8-bit reg variable [7, 6, 5, 4, 3, 2, 1, 0]
  addr [0] = 1;                // assign 1 to bit 0 of addr
  addr [3] = 0;                // assign 0 to bit 3 of addr
  addr [8] = 1;                // illegal : bit8  does not exist in addr


part-select in verilog

A range of contiguous bits can be selected and is known as a part-select. There are two types of part-selects, one with a constant part-select and another with an indexed part-select.

  reg [31:0]    addr;
  addr [23:16] = 8'h23;         // bits 23 to 16 will be replaced by the new value 'h23 -> constant part-select

Having a variable part-select allows it to be used effectively in loops to select parts of the vector. Although the starting bit can be varied, the width has to be constant.

[<start_bit> +: <width>]     // part-select increments from start-bit
[<start_bit> -: <width>]     // part-select decrements from start-bit
module des;
  reg [31:0]  data;
  int         i;
  initial begin
    data = 32'hFACE_CAFE;
    for (i = 0; i < 4; i++) begin
      $display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
    $display ("data[7:0]   = 0x%0h", data[7:0]);
    $display ("data[15:8]  = 0x%0h", data[15:8]);
    $display ("data[23:16] = 0x%0h", data[23:16]);
    $display ("data[31:24] = 0x%0h", data[31:24]);
Simulation Log
ncsim> run
data[8*0 +: 8] = 0xfe              // ~ data [8*0+8 : 8*0]
data[8*1 +: 8] = 0xca              // ~ data [8*1+8 : 8*1]
data[8*2 +: 8] = 0xce              // ~ data [8*2+8 : 8*2]
data[8*3 +: 8] = 0xfa              // ~ data [8*3+8 : 8*3]

data[7:0]   = 0xfe
data[15:8]  = 0xca
data[23:16] = 0xce
data[31:24] = 0xfa
ncsim: *W,RNQUIE: Simulation is complete.

Common Errors

module tb;
   reg [15:0]    data;
   initial begin
      $display ("data[0:9] = 0x%0h", data[0:9]);   // Error : Reversed part-select index expression ordering

Was this article helpful ?

We use cookies to personalize content and ads, to provide social media features and to analyze our traffic. You consent to our cookies if you continue to use our website. To find out more about the cookies we use and how to delete them, see our privacy policy.

  I accept cookies from this site.
EU Cookie Directive plugin by www.channeldigital.co.uk