Category: SystemVerilog
SystemVerilog Struct
SystemVerilog Struct
The SystemVerilog struct groups the data types of multiple types. The entire group can be referenced as a whole, or the individual data type can be referenced by name.
Struct Syntax
Struct is defined with the Struct keyword followed by variables of multiple data type with in the curly braces.
typedef struct packed { type_1 var_1; type_2 var_2; type_3 var_3; } struct_name;
SystemVerilog Packed Struct
Struct defined with the keyword Packed is referred as packed struct
Only packed data types and integer data types are allowed with in the packed struct
Packed Struct example
In the below example, variable of bit type are grouped in the struct.
module struct_tb; typedef struct packed { bit [7:0] addr; bit valid; bit [31:0] data; } mem_pkt; mem_pkt pkt; initial begin // Initializing Struct pkt = '{8'h6, 1'b1, 32'hC001_0FAB}; $display ("pkt = %p", pkt); // Change the struct field value pkt.addr = 8'h8; $display ("pkt = %p", pkt); // Change the struct field value pkt.data = 32'hFFF0_0FFF; $display ("pkt = %p", pkt); end endmodule
Simulator Output
pkt = '{addr:'h6, valid:'h1, data:'hc0010fab} pkt = '{addr:'h8, valid:'h1, data:'hc0010fab} pkt = '{addr:'h8, valid:'h1, data:'hfff00fff}
SystemVerilog UnPacked Struct
By default struct is of Unpacked type, i.e struct without Packed keyword.
Packed Struct example
In the below example, byte, enum and bit types are grouped in the struct.
module struct_tb; typedef enum logic {INVALID_PKT,VALID_PKT} pkt_type; typedef struct packed { byte addr; pkt_type valid; bit [31:0] data; } mem_pkt; mem_pkt pkt; initial begin // Initializing Struct pkt = '{8'h6, VALID_PKT, 32'hC001_0FAB}; $display ("pkt = %p", pkt); // Change the struct field value pkt.addr = 8'h8; $display ("pkt = %p", pkt); // Change the struct field value pkt.valid = INVALID_PKT; $display ("pkt = %p", pkt); end endmodule
Simulator Output
pkt = '{addr:'h6, valid:VALID_PKT, data:'hc0010fab} pkt = '{addr:'h8, valid:VALID_PKT, data:'hc0010fab} pkt = '{addr:'h8, valid:INVALID_PKT, data:'hc0010fab}
SystemVerilog int vs integer
difference between SystemVerilog int vs integer
Int
2-state SystemVerilog data type, 32 bit signed integer
Integer
4-state Verilog data type, 32 bit signed integer
For SystemVerilog data type refer to SystemVerilog Data Types
difference between struct and array systemverilog
SystemVerilog struct and array difference
- Array groups the elements of same data type
- Struct groups the elements of different data type
Array
Collection of variables of same data type.
int addr[10]; //Array of int type bit [31:0] data[63]; //Array of bit type
Struct
Collection of variables of different data types.
typedef enum logic {INVALID_PKT,VALID_PKT} pkt_type; typedef struct packed { byte addr; pkt_type valid; bit [31:0] data; } mem_pkt;
For detailed description refer to,
SystemVerilog dpi
SystemVerilog DPI C++
SystemVerilog DPI (Direct Programming Interface) is an interface which can be used to interface SystemVerilog with foreign languages. These Foreign languages can be C, C++, SystemC as well as others.
DPI allows the user to easily call functions of other language from SystemVerilog and to export SystemVerilog functions, so that they can be called in other languages.
Advantage of DPI is, it allows to make use of the code exists in other languages.
DPI Import and export methods
Import Method
The methods (functions/tasks) implemented in Foreign language can be called from SystemVerilog and such methods are called Import methods.
Export methods
The methods implemented in SystemVerilog can be called from Foreign language such methods are called Export methods.
It is allowed to transfer the data between two languages through arguments passing and return.
DPI Declaration
Import Declaration
import “DPI-C” function int calc_parity (input int a);
Export Declaration
export “DPI-C” my_cfunction = function myfunction;
SystemVerilog DPI Example
Calling C++ method from SystemVerilog file
//---------------------------------------------- // SystemVerilog File //---------------------------------------------- module dpi_tb; import "DPI-C" function void c_method(); initial begin $display("Before calling C Method"); c_method(); $display("After calling C Method"); end endmodule //---------------------------------------------- // C++ file //---------------------------------------------- #include stdio.h #include stdlib.h extern "C" void c_method() { printf(" Hello World...!\n"); }
Simulator Output
Before calling C Method [C-Prog] Hello World...! After calling C Method
Calling SystemVerilog method from C++ file
//---------------------------------------------- // SystemVerilog File //---------------------------------------------- module dpi_tb; export "DPI-C" function sv_method; import "DPI-C" context function void c_method(); initial begin $display("Before calling C Method"); c_method(); $display("After calling C Method"); end function void sv_method(); $display(" [SV-Prog] Hello World...!"); endfunction endmodule //---------------------------------------------- // C++ file //---------------------------------------------- #include stdio.h #include iostream #include svdpi.h using namespace std; extern "C" void sv_method(); extern "C" void c_method() { printf(" [C-Prog] Hello World...!\n"); sv_method(); }
Simulator Output
Before calling C Method [C-Prog] Hello World...! [SV-Prog] Hello World...! After calling C Method
SystemVerilog Print enum as String
SystemVerilog print enum name
As we know enum defines a set of named values.
refer to SystemVerilog enum for detailed description.
Printing or displaying the enum name is easy for debug, by using enum method “name”, enum name can be displayed.
module enum_datatype; //declaration typedef enum int { red=0, green=1, blue=4, yellow, white=6, black=9 } Colors; Colors color; initial begin color = 4; $display("Colors :: Value of %0s is \t= %0d",color.name(),color); end endmodule
Simulator Output
Colors :: Value of blue is = 4
SystemVerilog enum of logic bit int
SystemVerilog enum of logic bit int
This section provides the examples to declare SystemVerilog enum of logic type, enum of bit type and enum of int type
enum of logic type example
module enum_datatype; //declaration enum logic [3:0] { red=0, green=1, blue=4, yellow, white=6, black=9 } Colors; initial begin Colors = Colors.first; for(int i=0;i < 6;i++) begin $display("Colors :: Value of %0s is \t= %0d",Colors.name(),Colors); Colors = Colors.next; end end endmodule
Simulator Output
Colors :: Value of red is = 0 Colors :: Value of green is = 1 Colors :: Value of blue is = 4 Colors :: Value of yellow is = 5 Colors :: Value of white is = 6 Colors :: Value of black is = 9
enum of bit type example
module enum_datatype; //declaration enum bit [3:0] { red=0, green=1, blue=4, yellow, white=6, black=9 } Colors; initial begin Colors = Colors.first; for(int i=0;i < 6;i++) begin $display("Colors :: Value of %0s is \t= %0d",Colors.name(),Colors); Colors = Colors.next; end end endmodule
Simulator Output
Colors :: Value of red is = 0 Colors :: Value of green is = 1 Colors :: Value of blue is = 4 Colors :: Value of yellow is = 5 Colors :: Value of white is = 6 Colors :: Value of black is = 9
enum of int type example
module enum_datatype; //declaration enum int { red=0, green=1, blue=4, yellow, white=6, black=9 } Colors; initial begin Colors = Colors.first; for(int i=0;i < 6;i++) begin $display("Colors :: Value of %0s is \t= %0d",Colors.name(),Colors); Colors = Colors.next; end end endmodule
Simulator Output
Colors :: Value of red is = 0 Colors :: Value of green is = 1 Colors :: Value of blue is = 4 Colors :: Value of yellow is = 5 Colors :: Value of white is = 6 Colors :: Value of black is = 9
SystemVerilog enum cast
SystemVerilog enum casting
Assigning a variable to enum type is illegal, below example shows assigning variable to enum type.
Assigning variable to enum
module enum_datatype; //declaration typedef enum int { red=0, green=1, blue=4, yellow, white=6, black=9 } Colors; Colors color; initial begin color = 4; $display("Colors :: Value of %0s is \t= %0d",color.name(),color); end endmodule
Simulator Output
Warning-[ENUMASSIGN] Illegal assignment to enum variable testbench.sv, 11 enum_datatype, "color = 4;" Only expressions of the enum type can be assigned to an enum variable. The type int is incompatible with the enum 'Colors' Expression: 4 Use the static cast operator to convert the expression to enum type. Colors :: Value of blue is = 4
enum casting
In the above example we have seen that assigning variable to enum type is illegal, this can be overcome by using casting.
Below example shows using cast to assign variable to enum type.
module enum_datatype; //declaration typedef enum int { red=0, green=1, blue=4, yellow, white=6, black=9 } Colors; Colors color; initial begin $cast(color,4); $display("Colors :: Value of %0s is \t= %0d",color.name(),color); end endmodule
Simulator Output
Colors :: Value of blue is = 4
SystemVerilog logic vs wire
SystemVerilog logic vs wire
Wire is verilog datatype whereas logic is SystemVerilog data type.
Logic:
SystemVerilog logic data type is 4-state data type
Wire:
Verilog wire also 4-state data type, wire is used to connect input and output ports of a module instantiation together with some other element in your design
Assertions in SystemVerilog
SystemVerilog Assertions
Assertions are primarily used to validate the behavior of a design. An assertion is a check embedded in design or bound to a design unit during the simulation. Warnings or errors are generated on the failure of a specific condition or sequence of events.
Assertions are used to,
- Check the occurrence of a specific condition or sequence of events.
- Provide functional coverage.
There are two kinds of assertions:
- Immediate Assertions
- Concurrent Assertions
Immediate Assertions:
Immediate assertions check for a condition at the current simulation time.
An immediate assertion is the same as an if..else statement with assertion control. Immediate assertions have to be placed in a procedural block definition.
Syntax
label: assert(expression) action_block;
- The optional statement label (identifier and colon) creates a named block around the assertion statement
- The action block is executed immediately after the evaluation of the assert expression
- The action_block specifies what actions are taken upon success or failure of the assertion
action_block;
pass_statement; else fail_statement;
- The pass statement is executed if the expression evaluates to true
- The statement associated with else is called a fail statement and is executed if the expression evaluates to false
- Both pass and fail statements are optional
- Since the assertion is a statement that something must be true, the failure of an assertion shall have a severity associated with it. By default, the severity of an assertion failure is an error.
- Other severity levels can be specified by including one of the following severity system tasks in the fail statement:
- $fatal is a run-time fatal.
- $error is a run-time error.
- $warning is a run-time warning, which can be suppressed in a tool-specific manner.
- $info indicates that the assertion failure carries no specific severity.
- If an assertion fails and no else clause is specified, the tool shall, by default call $error.
Below are the different forms of immediate assertion syntax with and without optional items
//With Pass and Fail statement; Fail verbosity info; assert(expression) $display(“expression evaluates to true”); else $display(“expression evaluates to false”); //Only With Pass statement; assert(expression) $display(“expression evaluates to true”); //With Pass and Fail statement; Fail verbosity fatal; assert(expression) $display(“expression evaluates to true”); else $fatal(“expression evaluates to false”); //Only With Fail statement; Multiple statements in Faile condition and Fail verbosity fatal; assert(expression) else begin ……. ……. $fatal(“expression evaluates to false”); end //Only With Fail statement; Fail verbosity warning; assert(expression) else $warning(“expression evaluates to false”); //With Label and Fail statement; Fail verbosity warning; label: assert(expression) else $warning(“expression evaluates to false”);
Immediate assertion example
Below is the simple immediate assertion,
always @(posedge clk) assert (a && b);
Below is the wave diagram for the above assertion.
Condition (a && b) will be checked at every posedge of the clock, failure in the condition leads to an assertion failure.
module asertion_ex; bit clk,a,b; //clock generation always #5 clk = ~clk; //generating 'a' initial begin a=1; b=1; #15 b=0; #10 b=1; a=0; #20 a=1; #10; $finish; end //Immediate assertion always @(posedge clk) assert (a && b); endmodule
Simulator Output
ncsim: *E,ASRTST (./testbench.sv,23): (time 15 NS) Assertion asertion_ex.__assert_1 has failed ncsim: *E,ASRTST (./testbench.sv,23): (time 25 NS) Assertion asertion_ex.__assert_1 has failed ncsim: *E,ASRTST (./testbench.sv,23): (time 35 NS) Assertion asertion_ex.__assert_1 has failed Simulation complete via $finish(1) at time 55 NS + 0
Concurrent Assertions:
Concurrent assertions check the sequence of events spread over multiple clock cycles.
- The concurrent assertion is evaluated only at the occurrence of a clock tick
- The test expression is evaluated at clock edges based on the sampled values of the variables involved
- It can be placed in a procedural block, a module, an interface or a program definition
c_assert: assert property(@(posedge clk) not(a && b));
The Keyword differentiates the immediate assertion from the concurrent assertion is “property.”