Hi Everyone !!!
In this blog we are going to see the concepts of Structure in System Verilog.
- Structure is a collection of variables and/or constants under a single name. The entire collection can be referenced, using the name of the structure. Each member within the structure also has a name, which is used to select it from the structure.
- Structure can be accessed as whole or separately.
Syntax:
module TB;
<structure_name>.<variable_name>
struct {
int a, b; // 32-bit variables
data_t data; // user-defined type
logic [23:0] addr; // 24-bit variable
bit flag; // 1-bit 2-state var.
} struct_ex;
Structure allows all type of variables except net types(wire/tri) or var type variables in inside structure. It leads to compilation error. By using struct as wire/tri/var we can access. We will discuss about in structure accessing.
Structure Declaration Methods:
- Wire Structure
module TB;
struct {
logic a;
bit d;
wire e; // In structure net is used it leads to compilation error
logic b;} my_data;
endmodule
The above compilation can be overcome by using wire/tri
module TB;
wire struct { // Here all the variables will act as wire only irrespective of declaration
logic a;
bit d;
logic e;
logic b;} my_data;
assign my_data.a=1'b1;
initial begin
my_data.b=1'b1; / /Here "b" act as wire irrespective of declaration. It leads to compilation
//error because we are used in procedural block
my_data.d=1'b1; /Here "d" act as wire irrespective of declaration. It leads to compilation
//error because we are used in procedural block
$display(" A =%0d B=%0d", my_data.a,my_data.b);
end
endmodule
From this we conclude that net not allowed inside the structure. By using wire/tri struct we can access the variable as wire/tri irrespective of declaration. Inside the wire struct all the variables treated as net variables. So we must follow the net variables code rules to access wire struct variables. similarly we can use var struct also.
- Typed and anonymous Structure
A typedef declaration lets you define your own identifiers that can be used in place of type specifiers such as int, byte, real.
Declaring structure as typedef does not allocate any storage. When a structure is declared without typedef then the structure is called as anonymous structure.
If there is a need to create multiple structure variables with the same constituents,it will be better to create user defined structure.
module TB;
typedef struct {
int a;
bit d;
logic b;} my_data;
my_data examp; // structure instantiation which is allowed in typedef only
my_data examp1; // structure instantiation which is allowed in typedef only
initial begin
examp.a=10; // Here 10 is assigned for a
examp1.a=15; // Here 15 is assigned for a
// The same variable accessed with different handle name which is allowed in typedef only
$display(" A =%0d A1=%0d", examp.a,examp1.a);
end
endmodule
OUTPUT:
A=10 A1=15
- Packed Structure
By default structure is unpacked. A packed structure is a mechanism for subdividing a vector into subfields, which can be conveniently accessed as a member. packed structure is packed without any memory gap.
A packed structure stores all members of the structure as contiguous bits, in a specified order. A packed structure is stored as a vector, with the first member of the structure being the left-most field of the vector. The right-most bit of the last member in the structure is the least-significant bit of the vector, and is numbered as bit 0.
All members of a packed structure must be integral values. An integral value is a value that can be represented as a vector, such as byte, int and vectors created using bit or logic types. A structure cannot be packed if any of the members of the structure cannot be represented as a vector. This means a packed structure cannot contain real or shortreal variables, unpacked structures, unpacked unions, or unpacked arrays .
Packed structure can be accessed by using structure name or bitwidth.
module TB;
struct packed {
logic[8:0] a;
bit[5:0] b;
logic c} my_data;
initial begin
my_data.a=9'd9; //Here I am accessing strucure by name
my_data.[6:1]=6'd6; //Here I am accessing strucure by bitwidth
my_data.[0]=1; //Here I am accessing strucure by bitwidth
$display(" ENTIRE STRUCTURE =%p A=%0d B=%0d C=%0d", my_data, my_data.a,my_data.b,my_data.c); /Here I am printing value by structure name
end
endmodule
OUTPUT:
- Signed Packed Structure
Packed structures can be declared with the signed or unsigned keywords. These modifiers affect how the entire structure is perceived when used as a vector in mathematical or relational operations.They do not affect how members of the structure are perceived. Each member of the structure is considered signed or unsigned, based on the type declaration of that member. A part select of a packed structure is always unsigned, the same as part selects of vectors in Verilog.
EX:
module TB;
typedef struct packed unsigned { //here unsigned so it doesn't care about MSB bits values. It consider the whole value as positive only
logic [1:0] a;
logic[1:0] b;
bit c;} my_data;
my_data A,B; // structure handles
initial begin
// Assigning different values to structure handles
A=8; // binary form is 01000
B=17; // binary form is 10001
if(A>B) begin // Comparing two different handles of structures
$display("A is greater than B");
end else begin
$display("B is greater than A");
end
end
endmodule
OUTPUT:
B is greater than AThe same code can be tried for signed it will produce a different results.
module TB;
typedef struct packed signed { //here signed so MSB bit is considered for negative sign indication
logic [1:0] a;
logic[1:0] b;
bit c;} my_data;
my_data A,B; // structure handles
initial begin
// Assigning different values to structure handles
A=8; // binary form is 01000
B=17; // binary form is 10001 -> here MSB bit is set its is negative value
if(A>B) begin // Comparing two different handles of structures
$display("A is greater than B");
end else begin
$display("B is greater than A");
end
end
endmodule
OUTPUT:
A is greater than BNote :
Based on our use case we can select signed or unsigned structure. Inside structure signed/unsigned not into the part.
IMPORTANT KEY POINTS:
- The signing of unpacked structures is not allowed. The following declaration would be considered illegal:
typedef struct signed {
int f1 ;
logic f2 ;
} my_daya; // illegal declaration
- If all data types within a packed structure are 2-state, the structure as a whole is treated as a 2-state vector.
- If any data type within a packed structure is 4-state, the structure as a whole is treated as a 4-state vector. If there are also 2-state members in the structure, there is an implicit conversion from 4-state to 2-state when reading those members and from 2-state to 4-state when writing them.
- Only packed structures should be an integral type only.
- A packed structure can be used with a typedef.
- A structure can be assigned as a whole and passed to or from a subroutine as a whole.
- Members of a structure data type can be assigned individual default member values by using an initial assignment with the declaration of each member. The assigned expression shall be a constant expression.
- An example of initializing members of a structure type is as follows:
int addr = 1 + constant;
int crc;
byte data [4] = '{4{1}};
} my_data;
The structure can then be instantiated.
my_data pi; // initialization defined by the typedef.
if an explicit initial value expression is used with the declaration of a variable, the initial assignment
expression within the structure data type shall be ignored. For example:
my_data pi = '{1,2,'{2,3,4,5}};
my_data pi; // initialization defined by the typedef.
if an explicit initial value expression is used with the declaration of a variable, the initial assignment
expression within the structure data type shall be ignored. For example:
my_data pi = '{1,2,'{2,3,4,5}};
- my_data pi= '{default:0}; // set all members of my_data to 0 (allowed)
- my_data pi = '{addr:0,crc:16,data:1} // (allowed-list by name)
- my_data pi = '{5,10,1} // (allowed-list by order)
- my_data pi ='{addr:6,1,0} // not allowed (illegal to mix listing by name and orger-leads to compilation error)
ADDITIONAL POINTS:
- Structures can be passed as an argument to task and functions.
- Both unpacked and packed structures are synthesizable. Synthesis supports passing structures through module ports, and in/out of tasks and functions.
- Because a packed structure is stored as a vector, operations on the complete structure are treated as vector operations. Therefore, math operations, logical operations, and any other operation that can be performed on vectors can also be performed on packed structures EX:
- typedef struct{ logic a;
- logic[7:0] b;
- logic[31:0] c;} my_data;
- my_data pin,pout;
- initial begin
- pot=pin<<2;
- end
Difference between array and structure?
- Structure differs from an array, in that an array is a collection of elements that are all the same type and size, where as a structure is a collection of variables and or constants that can be different types and different sizes.
- Another difference is that array elements can be accessed by using array index where as in structure elements are accessed by using structure name.
Hope this logic's will be useful to everyone !!!
Giving feedback is more precious than writing an article!!! 😊😊😊😊😊
Always welcome both positive and negative feedback's !!!
Feel free to post any queries related SV and UVM
“Let the improvement of yourself keep you so busy that you have no time to criticize others.”
― Roy T. Bennett,
― Roy T. Bennett,
Hi, If in case my desgin signals are packed in some kind of structure and I need to access them with the help of interface only. Then how do I get that signals with usage of these two in my TB somewhere, such as connectivity between these two. Please post this if you have any clue on this.
ReplyDelete