An event
is a static object handle to synchronize between two or more concurrently active processes. One process will trigger the event, and another process waits for the event.
- Can be assigned or compared to other event variables
- Can be assigned to
null
- When assigned to another event, both variables point to same synchronization object
- Can be passed to queues, functions and tasks
An enumerated type defines a set of named values. In the following example, light_* is an enumerated variable that can store one of the three possible values (0, 1, 2). By default, the first name in the enumerated list gets the value 0 and the following names get incremental values like 1 and 2.
enum {RED, YELLOW, GREEN} light_1; // int type; RED = 0, YELLOW = 1, GREEN = 2
enum bit[1:0] {RED, YELLOW, GREEN} light_2; // bit type; RED = 0, YELLOW = 1, GREEN = 2
The user can assign any integer value for any of the enumerated names. If any name does not have an assigned value, then it automatically takes the incremented value of the previous name.
enum {RED=3, YELLOW, GREEN} light_3; // RED = 3, YELLOW = 4, GREEN = 5
enum {RED = 4, YELLOW = 9, GREEN} light_4; // RED = 4, YELLOW = 9, GREEN = 10 (automatically assigned)
enum {RED = 2, YELLOW, GREEN = 3} light_5; // Error : YELLOW and GREEN are both assigned 3
enum bit[0:0] {RED, YELLOW, GREEN} light_6; // Error: minimum 2 bits are required
What is a SystemVerilog string ?
The string
data-type is an ordered collection of characters. The length of a string
variable is the number of characters in the collection which can have dynamic length and vary during the course of a simulation. A string variable does not represent a string in the same way as a string literal. No truncation occurs when using the string
variable.
Syntax
string variable_name [= initial_value];
variable_name is a valid identifier and the optional initial_value can be a string literal, the value "" for an empty string, or a string data type expression. If an initial value is not specified at the time of declaration, then the variable defaults to "", an empty string literal.
In the previous article, an overview of the major data types were given. In this session, we'll look at 4-state and 2-state variables and two new data types called logic
and bit
.
4-state data types
Types that can have unknown (X) and high-impedance (Z) value in addition to zero (0) and one (1) are called 4-state types. Note that reg
can only be driven in procedural blocks like always
and initial
while wire
data types can only be driven in assign
statements. SystemVerilog introduces a new 4-state data type called logic
that can be driven in both procedural blocks and continuous assign
statements. But, a signal with more than one driver needs to be declared a net-type such as wire
so that SystemVerilog can resolve the final value.
logic
module tb;
logic [3:0] my_data; // Declare a 4-bit logic type variable
logic en; // Declare a 1-bit logic type variable
initial begin
$display ("my_data=0x%0h en=%0b", my_data, en); // Default value of logic type is X
my_data = 4'hB; // logic datatype can be driven in initial/always blocks
$display ("my_data=0x%0h en=%0b", my_data, en);
#1;
$display ("my_data=0x%0h en=%0b", my_data, en);
end
assign en = my_data[0]; // logic datatype can also be driven via assign statements
endmodule
ncsim> run my_data=0xx en=x my_data=0xb en=x my_data=0xb en=1 ncsim: *W,RNQUIE: Simulation is complete.
2-state data types
In a typical verification testbench, there are many cases where we don't really need all the four values (0, 1, x, z) like for example when modeling a network packet with a header that specifies the length of the packet.Length is usually a number, but not X and Z. SystemVerilog adds many new 2-state data types that can only store and have a value of either 0 or 1. This will aid in faster simulation, take less memory and are preferred in some design styles.
When a 4-state value is converted to a 2-state value, any unknown or high-impedance bits shall be converted to zeros.
The most important 2-state data type is bit
which is used most often in testbenches. A variable of type bit
can be either 0 or 1 which represents a single bit. A range from MSB to LSB should be provided to make it represent and store multiple bits
bit
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);
// 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 = 4'b01zx;
$display ("var_b = %b", var_b);
end
endmodule
ncsim> run Initial value var_a=0 var_b=0x0 New values var_a=1 var_b=0xf Truncated value: var_b=0xa var_b = 0100 ncsim: *W,RNQUIE: Simulation is complete.
The bins
construct allows the creation of a separate bin for each value in the given range of possible values of a coverage point variable.
Usage
coverpoint mode {
// Manually create a separate bin for each value
bins zero = {0};
bins one = {1};
// Allow SystemVerilog to automatically create separate bins for each value
// Values from 0 to maximum possible value is split into separate bins
bins range[] = {[0:$]};
// Create automatic bins for both the given ranges
bins c[] = { [2:3], [5:7]};
// Use fixed number of automatic bins. Entire range is broken up into 4 bins
bins range[4] = {[0:$]};
// If the number of bins cannot be equally divided for the given range, then
// the last bin will include remaining items; Here there are 13 values to be
// distributed into 4 bins which yields:
// [1,2,3] [4,5,6] [7,8,9] [10, 1, 3, 6]
bins range[4] = {[1:10], 1, 3, 6};
// A single bin to store all other values that don't belong to any other bin
bins others = default;
}
Examples
module tb;
bit [2:0] mode;
// This covergroup does not get sample automatically because
// the sample event is missing in declaration
covergroup cg;
coverpoint mode {
bins one = {1};
bins five = {5};
}
endgroup
// Stimulus : Simply randomize mode to have different values and
// manually sample each time
initial begin
cg cg_inst = new();
for (int i = 0; i < 5; i++) begin
#10 mode = $random;
$display ("[%0t] mode = 0x%0h", $time, mode);
cg_inst.sample();
end
$display ("Coverage = %0.2f %%", cg_inst.get_inst_coverage());
end
endmodule
ncsim> run [10] mode = 0x4 [20] mode = 0x1 [30] mode = 0x1 [40] mode = 0x3 [50] mode = 0x5 Coverage = 100.00 % ncsim: *W,RNQUIE: Simulation is complete.
Automatic Bins
covergroup cg;
coverpoint mode {
// Declares a separate bin for each values -> Here there will 8 bins
bins range[] = {[0:$]};
}
endgroup
4 out of the total possible 8 values have been sampled and hence coverage is 50%.
ncsim> run
[10] mode = 0x4
[20] mode = 0x1
[30] mode = 0x1
[40] mode = 0x3
[50] mode = 0x5
Coverage = 50.00 %
ncsim: *W,RNQUIE: Simulation is complete.
Fixed Number of automatic bins
covergroup cg;
coverpoint mode {
// Declares 4 bins for the total range of 8 values
// So bin0->[0:1] bin1->[2:3] bin2->[4:5] bin3->[6:7]
bins range[4] = {[0:$]};
}
endgroup
mode never got a value of 6 or 7 and hence bin3 does not get hit. But all the other bins are hit and hence coverage is 75%.
ncsim> run [10] mode = 0x4 [20] mode = 0x1 [30] mode = 0x1 [40] mode = 0x3 [50] mode = 0x5 Coverage = 75.00 % ncsim: *W,RNQUIE: Simulation is complete.
Split fixed number of bins between a given range
covergroup cg;
coverpoint mode {
// Defines 3 bins
// Two bins for values from 1:4, and one bin for value 7
// bin1->[1,2] bin2->[3,4], bin3->7
bins range[3] = {[1:4], 7};
}
endgroup
Only 2/3 of the bins were hit and hence coverage is at 66.67%. To be specific, bin1 and bin2 were hit because mode was sampled to have 1 and [3,4] respectively.
ncsim> run [10] mode = 0x4 [20] mode = 0x1 [30] mode = 0x1 [40] mode = 0x3 [50] mode = 0x5 Coverage = 66.67 % ncsim: *W,RNQUIE: Simulation is complete.