Structures in SystemVerilog
A structure in SystemVerilog is a user-defined composite data type that groups variables of different data types under a single name. It is similar to structs in C or C++. Each variable in a structure is called a member or field. The key feature of a structure is that each field has its own memory space, meaning they do not overlap.
Declaring a Structure
To declare a structure, use the struct keyword, followed by the list of data fields and their types. Each field has a name and a type, allowing different types of data to be grouped together.
// Example of structure definition
typedef struct {
int id; // Integer field
bit [7:0] data; // 8-bit data field
string name; // String field
} Packet;
In this example, Packet is a structure type with three fields:
id: an integer.data: an 8-bit wide bit vector.name: a string.
Using a Structure
Once a structure type is defined, you can create instances of it and access individual fields using the dot (.) operator.
module test();
typedef struct {
int id; // Integer field
bit [7:0] data; // 8-bit data field
string name; // String field
} Packet;
Packet pkt;
initial begin
// Assign values to the structure fields
pkt.id = 101;
pkt.data = 8'hFF;
pkt.name = "TestPacket";
// Access structure fields
$display("Packet ID: %0d, Data: %h, Name: %s", pkt.id, pkt.data, pkt.name);
end
endmodule
Output:
Packet ID: 101, Data: ff, Name: TestPacket
Nested Structures
Structures can also contain other structures, enabling the creation of complex data models.
module test();
typedef struct {
int x, y;
} Coordinates;
typedef struct {
int id;
Coordinates location;
} Object;
initial begin
Object obj;
obj.id = 1;
obj.location.x = 10;
obj.location.y = 20;
$display("Object ID: %0d, Location: (%0d, %0d)", obj.id, obj.location.x, obj.location.y);
end
endmodule
In this example, the Object structure includes a Coordinates structure, allowing Object to have a location with x and y coordinates.
Output:
Object ID: 1, Location: (10, 20)
Unions in SystemVerilog
A union is similar to a structure but with one critical difference: all fields in a union share the same memory space. This means only one field can hold a valid value at a time, as they overlap in memory. This makes unions useful for interpreting a memory region in different ways.
Declaring a Union
To declare a union, use the union keyword, followed by the fields it contains.
// Example of union definition
typedef union {
int int_val;
bit [31:0] bit_val;
real real_val;
} Data;
In this example, Data is a union type with three fields:
int_val: an integer.bit_val: a 32-bit bit vector.real_val: a real (floating-point) number.
Since these fields overlap in memory, changing one field affects the others.
Using a Union
Unions are useful when the same data needs to be accessed in different formats. Here’s an example of using a union.
module test();
// Example of union definition
typedef union {
int int_val;
bit [31:0] bit_val;
real real_val;
} Data;
// Create an instance of Data union
Data my_data;
initial begin
// Assign an integer value
my_data.int_val = 42;
$display("Integer Value: %0d, Bit Representation: %h", my_data.int_val, my_data.bit_val);
// Change the bit representation directly
my_data.bit_val = 32'hDEADBEEF;
$display("Integer Value: %0d, Bit Representation: %h", my_data.int_val, my_data.bit_val);
end
endmodule
In this example, modifying my_data.int_val changes the underlying memory, which is reflected in my_data.bit_val. Similarly, modifying my_data.bit_val changes my_data.int_val‘s interpretation of the memory contents.
Output:
Integer Value: 42, Bit Representation: 0000002a
Integer Value: -559038737, Bit Representation: deadbeef
Tagged Unions
System Verilog supports tagged unions, which include a tag to identify which field is currently in use. Tagged unions improve safety by preventing unintended memory access to fields that aren’t valid.
module test();
typedef union tagged {
int int_val;
bit [31:0] bit_val;
real real_val;
} SafeData;
SafeData my_safe_data;
initial begin
// Set the tagged union to use int_val
my_safe_data = tagged int_val 100;
$display("Tagged Union - Integer Value: %0d", my_safe_data.int_val);
// Set the tagged union to use real_val
my_safe_data = tagged real_val 3.14;
$display("Tagged Union - Real Value: %f", my_safe_data.real_val);
end
endmodule
Here, the tagged keyword ensures that only one field of SafeData is active at a time, enhancing safety and readability by clarifying which data type is being accessed.
Output:
Tagged Union - Integer Value: 100
Tagged Union - Real Value: 3.140000
Structures vs. Unions: Key Differences
| Feature | Structure | Union |
|---|---|---|
| Memory Allocation | Each field has its own memory space | All fields share the same memory space |
| Data Access | All fields can hold independent values | Only one field can hold a valid value |
| Use Case | Group related data | Access the same data in different formats |
| Safety | Safer, as fields do not overlap | Requires caution to avoid invalid access |
Summary
SystemVerilog structures and unions provide effective ways to manage complex data. Structures allow the grouping of related data with each field having its own memory space, making them ideal for grouping signals. Unions, on the other hand, allow the same memory space to be accessed in different formats, useful for reinterpreting data. By understanding and using these constructs, you can write more efficient and maintainable SystemVerilog code for hardware designs.