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.
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.)
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.
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.