Declaring class inside module

Hello,

I have a SystemVerilog Class defined in one file. Basically it is a configuration class. And there is SystemVerilog Module in another file which is PHY model. Now I need to access parameters of this configuration class in this Module but on declaring handle of this configuration class inside module gives compilation error. Please suggest a solution to use class inside the module.

Thanks in advance.

Regards,
Pinakin

In reply to upinakin:

What is the compilation error you are getting? Check the order in which the class file was included in your command-line.
Else use class forward declaration in your module code. (just like below.)

typedef class <your_class_name>;

You need to declare this class in a package , and import the package in every module you plan to declare a class variable of that class type. See SystemVerilog Coding Guidelines: Package import versus `include - Verification Horizons

In reply to dave_59:

Hi Dave,

Thanks for quick reply and providing solution.
After importing the package containing this class, the code is compiling and able to use the class variable inside the module.

Regards,
Pinakin

In reply to upinakin:

Hi Dave,I too facing the similar issue.Please help me.I am using class variables in my assertions module and bfm.I am importing class from a package into the module and istantiating this module in TOP.The errors which it was showing were peculiar.I am using Questasim 10.2c.
This is the error I am getting

** Error: …/ref/i2c_assertions.sv(167): (vlog-2110) Illegal reference to class “cfg”.

Here is the list of codes



//PACKAGE

package CONFIG;
class i2c_config;
 
bit start,stop;
bit WR;
bit RD;
bit slave_addr_tran;
bit mem_addr_tran;
bit data_tran_WR;
bit data_tran_RD;
bit slave_ack;
bit data_ack;
bit mem_ack;
int no_of_bytes_written;
int no_of_bytes_read;
endclass 
 
 
 
endpackage
//ASSERTIONS MODULE

import CONFIG::*;

module i2c_assertions();
 
 
 
logic scl;
 
i2c_if I2C_INTERFACE(.scl(scl));
 
 
 
//Config class 
 
 
 
//*******************************************************PROPERTIES and SEQUENCES*****************************************************//
 
initial
begin
i2c_config cfg;
cfg = new();
end
 
 
 
 
//START condition
 
 
sequence s1;
$fell(I2C_INTERFACE.sda);
endsequence
 
 
 
property p1;
 
@(posedge I2C_INTERFACE.scl) s1;
 
endproperty
 
 
 
//STOP condition
 
 
sequence s2;
@(I2C_INTERFACE.scl) $rose(I2C_INTERFACE.sda);
endsequence
 
 
property p2;
 
@(I2C_INTERFACE.scl) s2;
 
endproperty
 
 
 
 
 
 
//DATA VALIDITY
 
 
 
 
 
 
property p3;
 
@(I2C_INTERFACE.scl) s1|=>($stable(I2C_INTERFACE.sda))|=>(##[0:$](s2));
 
endproperty
 
 
 
 
//BUS IDLE
 
 
 
 
property p4;
 
@(I2C_INTERFACE.scl) s2|=>(I2C_INTERFACE.sda && I2C_INTERFACE.scl)|=>s1; 
 
endproperty
 
 
 
//SLAVE ADDRESS TRANSFER & ACK
 
 
 
 
//SLAVE ADDRESS trasnfer starts
 
 
property p5;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1);
 
 
endproperty
 
 
 
 
//SLAVE ADDRESS transfer ends
 
 
property p6;
 
@(posedge I2C_INTERFACE.scl) s1|=> ##8 (cfg.slave_addr_tran==1'b0);
 
endproperty
 
 
//SLAVE ADDRESS ACK
 
 
property p7;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe));
 
endproperty
 
 
 
 
//MEMORY ADDRESS TRANSFER & ACK
 
 
 
 
 
//MEMORY ADDRESS transfer starts
 
 
 
property p8;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9 !(I2C_INTERFACE.sda_oe)|=>(cfg.mem_addr_tran==1'b1);
 
endproperty
 
 
 
 
//MEMORY ADDRESS transfer ends
 
 
property p9;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=> ##8 (cfg.mem_addr_tran==1'b0);
 
endproperty
 
 
 
//MEMORY ADDRESS ACK
 
 
 
 
property p10;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe));
 
endproperty
 
 
 
 
 
//DATA TRANSFER & ACK (WRITE operation)
 
 
 
 
//DATA TRANSFER starts
 
 
 
property p11;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe))|=>(cfg.data_tran_WR==1'b1);
 
 
endproperty
 
 
//DATA TRANSFER ends
 
/*
property p12;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran_WR==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe))|=>##8 (cfg.data_tran_WR==1'b0);
 
endproperty
*/
 
//DATA TRANSFER ACK (by Slave)
 
 
property p13;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe))|->##9 (!(I2C_INTERFACE.sda_oe));
 
endproperty
 
 
//DATA TRANSFER & ACK (READ operation)
 
 
 
//DATA TRANSFER starts
 
 
property p14;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe))|=>(cfg.data_tran_RD==1'b1);
 
 
endproperty
 
 
 
//DATA TRANSFER ends
 
/*
property p15;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe))|=>##8 (cfg.data_tran_RD==1'b0);
 
endproperty
*/
 
//DATA TRANSFER ACK (by Master)
 
 
property p16;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|->##9(!(I2C_INTERFACE.sda_oe))|=>##9 (!(I2C_INTERFACE.sda_oe))|->##9 !(I2C_INTERFACE.sda);
 
 
endproperty
 
 
 
//RepStart condition
 
 
 
//When slave didn't respond during slave address transfer
 
 
 
property p17;
 
@(I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|=>##9 (I2C_INTERFACE.sda_oe);
 
endproperty
 
 
//When NACK sent during memory address transfer
 
 
property p18;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.mem_addr_tran==1'b1)|=>##9 (I2C_INTERFACE.sda_oe);
 
endproperty
 
 
//When NACK sent during data transfer
 
//WRITE to slave
 
 
 
property p19;
 
@(I2C_INTERFACE.scl) s1|=> (cfg.data_tran_WR==1'b1)|=>##9 (I2C_INTERFACE.sda_oe);
 
endproperty
 
 
 
//READ from slave
 
 
 
property p20;
 
@(I2C_INTERFACE.scl) s1|=> (cfg.data_tran_RD==1'b1)|=>##9 (I2C_INTERFACE.sda);
 
endproperty
 
 
//WRITE operation DETECT
 
 
property p21;
 
@(posedge I2C_INTERFACE.scl) s1|=> ##8(!(I2C_INTERFACE.sda));
 
 
endproperty
 
 
//READ operation detect
 
 
property p22;
 
@(posedge I2C_INTERFACE.scl) s1|=> ##8 I2C_INTERFACE.sda;
 
endproperty
 
 
 
//When slave didn't respond during slave address transfer
 
 
property p23;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.slave_addr_tran==1'b1)|=>##9 (I2C_INTERFACE.sda_oe);
 
 
endproperty
 
 
//NACK sent by slave when master sends memory address
 
 
property p24;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.mem_addr_tran==1'b1)|=>##9 (I2C_INTERFACE.sda_oe);
 
endproperty
 
 
//NACK sent by slave after sending data to slave
 
 
 
property p25;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.data_tran_WR==1'b1)|=>##9 (I2C_INTERFACE.sda_oe);
 
endproperty
 
 
 
//NACK sent by master after recieving data from slave
 
 
property p26;
 
@(posedge I2C_INTERFACE.scl) s1|=> (cfg.data_tran_RD==1'b1)|=>##9 (I2C_INTERFACE.sda);
 
endproperty
 
 
 
//Illegal Format (START followed by STOP in the next cycle)
 
 
 
 
 
property p27;
 
@(posedge I2C_INTERFACE.scl) s1 |=> s2;
 
endproperty
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/////////////*****************************************************************ASSERTIONS*******************************************************************/////////////
 
 
 
START      :  assert property (p1) $display (" START condition detected at %0t ",$time);
 
 
STOP       :  assert property (p2) $display (" STOP condition detected at %0t ",$time);
 
 
VALID_DATA :  assert property (p3) $display (" INVALID SDA TRANSITION ");          else    $display("Assertion Failed : INVALID DATA");
 
 
BUS_IDLE   :  assert property (p4) $display (" I2C bus went to IDLE state ");
 
 
SLAVE_ADDR_TRANSFER_START      :     assert property (p5)  $display (" SLAVE ADDRESS transfer started ");    
 
 
SLAVE_ADDR_TRANSFER_END        :     assert property (p6)  $display (" SLAVE ADDRESS transfer ended ");      
 
 
SLAVE_ADDR_ACK                 :     assert property (p7)  $display (" SLAVE generated ACK ");               
 
 
NO_RESPONSE_FROM_SLAVE         :     assert property (p23) $display (" SLAVE not responded for the slave address sent");    
 
 
 
 
MEM_ADDR_TRANSFER_START        :     assert property (p8)  $display (" MEMORY ADDRESS transfer started ");   
 
 
MEM_ADDR_TRANSFER_END          :     assert property (p9)  $display (" MEMORY ADDRESS transfer ended ");     
 
 
WRITE_TO_SLAVE_DETECT          :     assert property (p21) $display (" MASTER WRITES TO SLAVE ");           
 
 
READ_FROM_SLAVE_DETECT         :     assert property (p22) $display (" MASTER READS FROM SLAVE ");           
 
 
MEM_ADDR_ACK                   :     assert property (p10) $display (" SLAVE generated ACK after memory address has been sent by master ");
 
 
 
 
MEM_ADDR_NACK                  :     assert property (p24) $display (" SLAVE generated NACK after memory address has been sent by master ");
 
 
 
WRITE_DATA_TRANSFER_START      :     assert property (p11) $display (" DATA TRANSFER STARTED "); 
 
 
//WRITE_DATA_TRANSFER_END        :     assert property (p12) $display (" DATA TRANSFER ENDED ");               
 
 
DATA_ACK_BY_SLAVE              :     assert property (p13) $display (" SLAVE generated ACK ");              
 
 
DATA_NACK_BY_SLAVE             :     assert property (p25) $display (" SLAVE generated NACK after data has been sent by master ");   
 
 
 
 
READ_DATA_TRANSFER_START       :     assert property (p14) $display (" DATA TRANSFER STARTED ");            
 
 
//READ_DATA_TRANSFER_END         :     assert property (p15) $display (" DATA TRANSFER ENDED ");              
 
 
DATA_ACK_BY_MASTER             :     assert property (p16) $display (" MASTER generated ACK after data has been sent by SLAVE  ");                                     
 
 
 
 
DATA_NACK_BY_MASTER            :     assert property (p26) $display (" MASTER generated NACK after data has been sent by SLAVE ");
 
 
 
 
REP_START_1                    :     assert property (p17) $display (" RPEATED START DETECTED (No response to the SLAVE ADDRESS sent) ");   
 
 
 
 
REP_START_2                    :     assert property (p18) $display (" REPEATED START DETECTED (SLAVE generated NACK after the MEMORY ADDRESS  has been sent by the MASTER) ");
 
 
 
REP_START_3                    :     assert property (p19) $display (" REPEATED START DETECTED (SLAVE generated NACK after the DATA  has been sent by the  MASTER) ");
 
 
 
 
REP_START_4                    :     assert property (p20) $display (" REPEATED START DETECTED (MASTER generated NACK after the DATA has been sent by the slave) ");
 
 
 
ILLEGAL_FORMAT                 :     assert property (p27) $display (" ILLGEAL FORMAT:START followed by STOP in the next cycle ");
 
 
 
 
 
endmodule 
//TOP MODULE

`timescale 1ns/10ps

`include "apb_env.sv"
`include "i2c_env.sv"

import CONFIG::*;

 module top;
 
parameter CLOCK=5ns;
logic PCLK;
logic cyc;
wire sda;
logic scl;
logic scl0_o,scl0_oen,sda0_oen,sda0_o;
 
//INTERFACE INSTANCE
 
//`include "i2c_config.sv"
`include "i2c_assertions.sv"
 
APB_INT APBINT(.PCLK(PCLK));
 
i2c_if I2C_INTERFACE(.scl(scl));
 
 
//Program block Instance
 
i2c_assertions i2c_assert();
 
 
//DUT INSTANCES
 
 
 
 
ip_top ip(.pclk(APBINT.PCLK),
.presetn(APBINT.PRESETn),
.psel(APBINT.PSELx),
.penable(APBINT.PENABLE),
.pwrite(APBINT.PWRITE),
.paddr(APBINT.PADDR),
.pwdata(APBINT.PWDATA),
.prdata(APBINT.PRDATA),
.pready(APBINT.PREADY),
.pslverr(APBINT.PSLVERR),
.cyc(APBINT.cyc),
.scl(I2C_INTERFACE.scl),
.sda(I2C_INTERFACE.sda),
.sda0_o(sda0_o),
.sda0_oen(sda0_oen),
.scl0_o(scl0_o),
.scl0_oen(scl0_oen));
 
 
 
 
 
 
 
//ENVIRONMENT INSTANCE
 
 
 
apb_env env_m;
i2c_env env_s;
 
 
 
//TESTBENCH CLOCK
 
 
initial
begin:cgen
PCLK<=1'b0;
 
forever
#(CLOCK) PCLK<=~PCLK;
end:cgen
 
initial
 
begin:testcase
env_m = new(APBINT);
env_s = new(I2C_INTERFACE);
 
$display("Usage of Constraint Random Generator");
$display("Verif env with BFM,Generator,random test");
 
env_m.main();
env_s.main();
 
//#5000;
 
//$display("END of Lab5");
 
//$finish;
 
end:testcase
endmodule:top        

In reply to rajan passionate:
The SystemVerilog LRM prohibits accessing class properties directly in a concurrent assertion, but you can do it indirectly. The reason for this restriction is that concurrent assertions get synthesized by the compiler into something like a state machine, and the variables used in the Boolean expressions are implicitly sampled.

What you can do is create your own sampling logic that copies the class properties into intermediate static variables, and use those intermediate variables in your concurrent assertions.

In reply to dave_59:

Thanks dave.

In reply to rajan passionate:

Hi dave,

I am facing new issue now after running the simulation(after run -all)

** Fatal: (SIGSEGV) Bad handle or reference.

Time: 606 ns Iteration: 0 Process: /top/i2c_assert/#ALWAYS#25 File: …/ref/i2c_assertions.sv

Fatal error in Module i2c_assertions at …/ref/i2c_assertions.sv line 28

HDL call sequence:

Stopped at …/ref/i2c_assertions.sv 28 Module i2c_assertions

Here is my new partial assertion module code

import CONFIG::*;
module i2c_assertions(i2c_if I2C_INTERFACE);

tri1 sda;
bit slave_addr_tran;
bit mem_addr_tran;
bit data_tran_WR;
bit data_tran_RD;

//(.sda(sda));

i2c_config cfg;

always @(posedge I2C_INTERFACE.scl)
begin

slave_addr_tran   =   cfg.slave_addr_tran;

mem_addr_tran     =   cfg.mem_addr_tran;

data_tran_WR  =   cfg.data_tran_WR;

data_tran_RD  =   cfg.data_tran_RD;

end

//TOP module code

include "apb_env.sv" include “i2c_env.sv”

import CONFIG::*;

module top;

parameter CLOCK=5ns;
logic PCLK;
tri1 sda;
logic scl0_o,scl0_oen,sda0_oen,sda0_o;

//INTERFACE INSTANCE

APB_INT APBINT(.PCLK(PCLK));

i2c_if I2C_INT(.sda(sda));

//Assertion block Instance

i2c_assertions i2c_assert(.I2C_INTERFACE(I2C_INT));//.I2C_INTERFACE(I2C_INT));

–>Here I am using interface as the port in assertion module and calling using that port in top.When I do like this I am getting the above error.

–>Where as If I do like below I am not getting any errors but no effect of assertions will be seen.

//Here is my new partial assertion module code

import CONFIG::*;
module i2c_assertions();

tri1 sda;
bit slave_addr_tran;
bit mem_addr_tran;
bit data_tran_WR;
bit data_tran_RD;

//(.sda(sda));
i2c_if I2C_INTERFACE(.sda(sda));

i2c_config cfg;

always @(posedge I2C_INTERFACE.scl)
begin

slave_addr_tran   =   cfg.slave_addr_tran;

mem_addr_tran     =   cfg.mem_addr_tran;

data_tran_WR  =   cfg.data_tran_WR;

data_tran_RD  =   cfg.data_tran_RD;

end

//TOP module code

include "apb_env.sv" include “i2c_env.sv”

import CONFIG::*;

module top;

parameter CLOCK=5ns;
logic PCLK;
tri1 sda;
logic scl0_o,scl0_oen,sda0_oen,sda0_o;

//INTERFACE INSTANCE

APB_INT APBINT(.PCLK(PCLK));

i2c_if I2C_INT(.sda(sda));

//Assertion block Instance

i2c_assertions i2c_assert();//.I2C_INTERFACE(I2C_INT));