2-state Data Types

The 2-state data types, such as bit and int, can only represent two values: 0 and 1. This simplification reduces memory usage during simulation, as each bit requires only one bit of storage instead of two bits needed for the 4-state types (which include 0, 1, X for unknown, and Z for high impedance). This leads to faster simulation performance due to lower memory overhead and reduced complexity in handling states.

Data TypeSizeSigned RangeUnsigned RangeDescription
bit1-bit0 and 12-state variable
byte8-bit-27 to 27-10 to 28-12-state variable, similar to C char
shortint16-bit-215 to 215-10 to 216-12-state variable, similar to C short int
int32-bit-231 to 231-10 to 232-12-state variable, similar to C int
longint64-bit-263 to 263-10 to 264-12-state variable, similar to C long int

Such 2-state types are suitable for modeling at more abstract levels than RTL, such as system level and transaction level. For instance, when modeling a network packet with a header that indicates the packet length, the length should be a numeric value rather than X or Z.

When a 4-state value is converted to a 2-state value, unknown (X) or high-impedance (Z) bits shall be converted to zeros.


module tb;
  bit   [3:0] var_b;      // Declare a 4-bit variable of type "bit"  
  logic [3:0] x_val;     // Declare a 4-bit variable of type "logic"
  
  initial begin    
    x_val = 4'b01zx;
    
    // If a logic type or any 4-state variable assigns its value to a "bit" type 
    // variable, then X and Z get converted to zero
    var_b = x_val;
    $display ("x_val=%b var_b = %b", x_val, var_b);
  end
endmodule
 Simulation Log
xcelium> run
x_val=01zx var_b = 0100
xmsim: *W,RNQUIE: Simulation is complete.

bit

The bit type is a 2-state data type that can represent binary values, default being 0. The bit type is commonly used in testbenches and other verification code where the additional states (X and Z) are not needed. A range specification ([MSB:LSB]) should be provided to make it represent and store multiple bits.


module tb;
  bit       var_a;       // Declare a 1 bit variable of type "bit"
  bit [3:0] var_b;       // Declare a 4 bit variable of type "bit"
  
  logic [3:0] x_val;     // Declare a 4 bit variable of type "logic"
  
  initial begin
  
    // Initial value of "bit" data type is 0
    $display ("Initial value var_a=%0b var_b=0x%0h", var_a, var_b);
    
    // Assign new values and display the variable to see that it gets the new values
    var_a = 1;
    var_b = 4'hF;
    $display ("New values    var_a=%0b var_b=0x%0h", var_a, var_b);
    
    // If a "bit" type variable is assigned with a value greater than it can hold
    // the left most bits are truncated. In this case, var_b can hold only 4 bits
    // and hence 'h481 gets truncated leaving var_b with only 'ha;
    var_b = 16'h481a;
    $display ("Truncated value: var_b=0x%0h", var_b);  
  end
endmodule
 Simulation Log
ncsim> run
Initial value var_a=0 var_b=0x0
New values    var_a=1 var_b=0xf
Truncated value: var_b=0xa
ncsim: *W,RNQUIE: Simulation is complete.

byte

The byte data type is defined as an 8-bit signed integer. It uses two's complement representation, enabling it to store both positive and negative values. The range for a byte is from -128 to 127. The byte data type is useful for applications where memory efficiency is important, such as in large arrays or when representing small integer values.


module tb;
   byte           m_var_s;      // By default signed, and can represent positive and negative numbers
  
  initial begin
    
    #10 m_var_s  = 0;           // assign 0
    #20 m_var_s  = 2**7 - 1; 	// assign 127
    #30 m_var_s  = 2**7;        // assign 128
    #40 m_var_s  = 2**8 - 1;    // assign 255
  end 
  
  initial 
    $monitor("[%0t] m_var_s = 'd%0d  (0x%0h)", $time, m_var_s, m_var_s);
endmodule
 Simulation Log
xcelium> run
[0] m_var_s = 'd0  (0x0)
[30] m_var_s = 'd127  (0x7f)
[60] m_var_s = 'd-128  (0x80)
[100] m_var_s = 'd-1  (0xff)
xmsim: *W,RNQUIE: Simulation is complete.

shortint

A shortint in SystemVerilog is a 2-state, 16-bit signed integer data type.


module tb;
   shortint            m_var_s;      // By default signed, and can represent positive and negative numbers
  
  initial begin
    
    #10 m_var_s  = 0;             // assign 0
    #20 m_var_s  = 2**15 - 1;     // assign 127
    #30 m_var_s  = 2**15;         // assign 128
    #40 m_var_s  = 2**16 - 1;     // assign 256
  end 
  
  initial 
    $monitor("[%0t] m_var_s = 'd%0d  (0x%0h)", $time, m_var_s, m_var_s);
endmodule
 Simulation Log
xcelium> run
[0] m_var_s = 'd0  (0x0)
[30] m_var_s = 'd32767  (0x7fff)
[60] m_var_s = 'd-32768  (0x8000)
[100] m_var_s = 'd-1  (0xffff)
xmsim: *W,RNQUIE: Simulation is complete.

int

A int in SystemVerilog is a 2-state, 32-bit signed integer data type.


module tb;
   int            m_var_s;      // By default signed, and can represent positive and negative numbers
  
  initial begin
    
    #10 m_var_s  = 0;             
    #20 m_var_s  = 2**31 - 1;     
    #30 m_var_s  = 2**31;         
    #40 m_var_s  = 2**32 - 1;     
  end 
  
  initial 
    $monitor("[%0t] m_var_s = 'd%0d  (0x%0h)", $time, m_var_s, m_var_s);
endmodule
 Simulation Log
xcelium> run
[0] m_var_s = 'd0  (0x0)
[30] m_var_s = 'd2147483647  (0x7fffffff)
[60] m_var_s = 'd-2147483648  (0x80000000)
[100] m_var_s = 'd-1  (0xffffffff)
xmsim: *W,RNQUIE: Simulation is complete.

longint

A longint in SystemVerilog is a 2-state, 64-bit signed integer data type.


module tb;
   longint            m_var_s;      // By default signed, and can represent positive and negative numbers
  
  initial begin
    
    #10 m_var_s  = 0;             
    #20 m_var_s  = 2**63 - 1;     
    #30 m_var_s  = 2**63;         
    #40 m_var_s  = 2**64 - 1;     
  end 
  
  initial 
    $monitor("[%0t] m_var_s = 'd%0d  (0x%0h)", $time, m_var_s, m_var_s);
endmodule
 Simulation Log
xcelium> run
[0] m_var_s = 'd0  (0x0)
[30] m_var_s = 'd9223372036854775807  (0x7fffffffffffffff)
[60] m_var_s = 'd-9223372036854775808  (0x8000000000000000)
[100] m_var_s = 'd-1  (0xffffffffffffffff)
xmsim: *W,RNQUIE: Simulation is complete.

Signed and Unsigned

Signed data types can represent both positive and negative values, whereas unsigned data types can only represent non-negative values (zero and positive numbers). Signed data types use one bit (MSB) for the sign, which reduces the maximum positive value that can be represented compared to unsigned types of the same bit width. This means that while both signed and unsigned types may have the same number of bits, the unsigned type has a larger range of positive values.

Example

The sign can be explicitly defined using the keywords signed and unsigned.


module tb;
  byte    			s_byte;   // By default byte is signed
  byte unsigned  	u_byte;   // Byte is set to unsigned
  
  initial begin
    $display ("Size s_byte=%0d, u_byte=%0d", $bits(s_byte), $bits(u_byte));
    
    // Assign the "assumed" maximum value to both variables
    #1 s_byte = 'h7F;
       u_byte = 'h7F;
    
    // Increment by 1, and see that s_byte rolled over to negative because
    // byte is signed by default. u_byte keeps increasing because it is 
    // unsigned and can go upto 255
    #1 s_byte += 1;
       u_byte += 1;
    
    // Assign 255 (8'hFF) to u_byte -> this is the max value it can hold
    #1 u_byte = 'hFF;
    
    // Add 1 and see that it rolls over to 0
    #1 u_byte += 1;    
  end
  
  initial begin
    $monitor ("[%0t ns] s_byte=%0d u_byte=%0d", $time, s_byte, u_byte);
  end
endmodule
 Simulation Log
ncsim> run
Size s_byte=8, u_byte=8
[0 ns] s_byte=0 u_byte=0
[1 ns] s_byte=127 u_byte=127
[2 ns] s_byte=-128 u_byte=128
[3 ns] s_byte=-128 u_byte=255
[4 ns] s_byte=-128 u_byte=0
ncsim: *W,RNQUIE: Simulation is complete.

Understanding the difference between signed and unsigned data types is crucial for effective programming and hardware design. It allows developers to choose the right representation for their data needs while optimizing memory usage and ensuring data integrity.

Sign Cast

They can be converted into one another by casting.


module tb;
   shortint            m_var_s;      // By default signed, and can represent positive and negative numbers
   shortint unsigned   m_var_us;     // Explicitly set to 'unsigned' and represents only positive numbers   
  
  initial begin
    m_var_us = 2**16 - 1;
    m_var_s  = -1;
    
    // Convert an unsigned variable value to a signed variable value by casting    
    $display("m_var_us=%0d m_var_us=%0d", signed' (m_var_us), m_var_us);
    $display("m_var_s=%0d  m_var_s=%0d", unsigned' (m_var_s), m_var_s);
  end 
endmodule

Operations on unsigned integers can be faster in some cases since there’s no need to handle sign bits during arithmetic operations and can lead to more efficient code execution.

 Simulation Log
xcelium> run
m_var_us=-1 m_var_us=65535
m_var_s=65535  m_var_s=-1
xmsim: *W,RNQUIE: Simulation is complete.