How to use class variables inside an assertion module?



Hi,
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.Please solve the issue.

Region: /top_sv_unit

** Error: (vsim-3043) …/ref/i2c_assertions.sv(224): Unresolved reference to ‘cfg’ in cfg.data_tran_RD.

Region: /top/i2c_assert

** Error: (vsim-3043) …/ref/i2c_assertions.sv(189): Unresolved reference to ‘cfg’ in cfg.data_tran_WR.

Region: /top/i2c_assert

** Error: (vsim-3043) …/ref/i2c_assertions.sv(145): Unresolved reference to ‘cfg’ in cfg.mem_addr_tran.

Region: /top/i2c_assert

** Error: (vsim-3043) …/ref/i2c_assertions.sv(103): Unresolved reference to ‘cfg’ in cfg.slave_addr_tran.

Here are the code list

//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:

Hi Rajan,

Dynamic entity(class is dynamic entity)couldn’t be used in property OR sequence of assertion in module.
So You need to change class to module if it is possible.

Thanks,
VS

In reply to rajan passionate:

Hi,

Assign / Copy the config variable which you want to use inside a property to a local variable. Like this.

module i2c_assertions();
...
int data_tran_RD;
int data_tran_WR;
int slave_addr_tran;
...
always@(clk)
begin
  . . .
  data_tran_RD    = cfg.data_tran_RD;
  data_tran_WR    = cfg.data_tran_WR;
  slave_addr_tran = cfg.slave_addr_tran;
  . . .
end
 . . .
property p5;
  @(posedge I2C_INTERFACE.scl)
  s1|=> ( slave_addr_tran == 1'b1 );
endproperty : p5
 . . .

endmodule : i2c_assertions

This should help…

In reply to BHEEMA THANGAVELU:

It is showing the same errors even after assigning to local variables.

In reply to rajan passionate:

Actually those config variables need to be updated in the BFM.It is not showing any errors in bfm while importing.

In reply to rajan passionate:

By importing CONFIG package, you will be able to see only the class not all the handles for that class, in your case cfg is the handle you want in your assertions module.

You may have point the cfg in i2c_assertion to cfg in your BFM.
In top module you can do like this.

module top;
. . .
  initial
  begin
    env_m          = new(APBINT);
    env_s          = new(I2C_INTERFACE);
    i2c_assert.cfg = env_s.cfg;

    // OR You can directly point BFM's cfg
    // i2c_assert.cfg = env_s.BFM.cfg;

    // Similarly from your environment after creating the BFM, point the cfg in BFM
    // to cfg in env
    // BFM.cfg = this.cfg; // This is env class
  end
. . .
endmodule : top

Then in you assertion module have the instance of cfg. Need not create it.

module i2c_assertions();
. . .
  i2c_config cfg;
. . .
  always@(clk)
  begin
    . . .
    data_tran_RD    = cfg.data_tran_RD;
    data_tran_WR    = cfg.data_tran_WR;
    slave_addr_tran = cfg.slave_addr_tran;
    . . .
  end

  . . .
  property p5;
    @(posedge I2C_INTERFACE.scl)
    s1|=> ( slave_addr_tran == 1'b1 );
  endproperty : p5
  . . .

endmodule : i2c_assertions

In reply to BHEEMA THANGAVELU:

It’s still showing the same error sir.

In reply to rajan passionate:

Can you post the error message. I believe the cfg in assertion is pointing to null at time 0.

Try replacing always block with initial block with forever and add a statement wait(cfg != null).

initial
begin
  wait(cfg != null);
  forever
  begin
    @(posedge clk);
    . . .
    data_tran_RD    = cfg.data_tran_RD;
    data_tran_WR    = cfg.data_tran_WR;
    slave_addr_tran = cfg.slave_addr_tran;
    . . .
  end
end

Try this and let me know if it worked…

In reply to BHEEMA THANGAVELU:
Is is showing again the same error sir.

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

In reply to rajan passionate:

Can you paste the full code of assertions and point the line where the error is encountered???

In reply to BHEEMA THANGAVELU:
Thank you bheema.Actually after assigning to local variables in that module as you said,I used cfg.variable in properties.That’s the reason it’s showing error.Now it’s solved.Thank you for your support.

You can always assign values to variables in any interface from class.
Use these interfaces in your assertions.

In reply to ashish_banga:

Hi Bheema,
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));


Please solve my issue