Referring to a property local variable from outside of property

Hi All,

How can I refer to a property’s local variable from outside of the property?

For example, I have the following property with a local variable ‘push_data’:


property data_chk;
// vars
bit [7:0] push_data;
// property 
@(posedge dram_clk) (push, push_data=in_data[7:0]) |-> ##[5:10] pop ##0 ((out_data == push_data);                                                                                            
endproperty

Now I want to refer to this property’s local variable named from here:

assert property (data_chk) 
else $error("-> Error in FIFO -> pushed data did not poped, pushed_data=%0h(hex)", pushed_data);

So, how can I do so (two lines above issue a syntax error)?

Thank you!

It is not possible to refer to a local variable from outside the property. Most people separate the data functionality checking from the protocol checking by using a scoreboard.

Scoreboard checks that the data that was pushed matches the data that was popped.
Assertion checks that pop comes between 5-10 clock cycles after push.

In reply to dave_59:

Dave is correct, but the assertion has issues anyways.
The issues

property data_chk;
   bit [7:0] push_data;
    @(posedge dram_clk) (push, push_data=in_data[7:0]) 
               |-> ##[5:10] pop ##0 ((out_data == push_data);                                                                                            
endproperty

Suppose you have the sequence
PUSH @t0, PUSH @t2, POP @t4
@t0, the assertion will fire and save data0, waiting for a pop
@t2, The assertion will fire and save data2, waiting for a pop
@t4, assertion started @t0 will succeed
@t4, assertion started @t2 will fail if data0 != data2
This is because each of those 2 successfully attempted assertions will terminate.
// <<< The assertion as written is poorly written (even if I gave you that answer :)
// (am Human too :) )

One way to solve this is to use supporting code. For example: 
1) Declare at the module level an associative array and an index (int type) 
2) In the property, declare a local variable for the write index used in that attempt 
3) In the assertion use the sequence_match_item to call a function that does 2 things:
   a) save the data into the associative array at that index
   b) increment the index
   Also, save the index used in that attempt into the local variable of the property 
4) in consequent, @ a pop, check that out_data==data_stored_in_associative_array @ saved index

Ben Cohen http://www.systemverilog.us/

  • SystemVerilog Assertions Handbook, 3rd Edition, 2013
  • A Pragmatic Approach to VMM Adoption
  • Using PSL/SUGAR … 2nd Edition
  • Real Chip Design and Verification
  • Cmpt Design by Example
  • VHDL books

In reply to ben@SystemVerilog.us:

Hello Ben,

Could you please help me understand how will the assertion started @t2 will fail at the completion of @t0 at time t=4? Are they not two independent active threads?

For assertion @t2, is the consequent check suppose to happen in the duration #[5:10]? i.e, at t=6 onwards?

===
@t4, assertion started @t2 will fail if data0 != data2
This is because each of those 2 successfully attempted assertions will terminate.

In reply to S.P.Rajkumar.V:

On second thoughts, the problem with this assertion for the fifo is uniqueness.
Below is a way to fix this using tags to force uniqueness. What I mean here is that yoou
don’t want a pop to complete 2 separate threads, as shown in the simulation results for
ap_data_checker_bad where one pop terminates both threads.
http://SystemVerilog.us/fifo_aa.png // simulation results
http://SystemVerilog.us/fifo_aa.sv
Concept is similar to tags used at hardware stores (pint dpt) with “now serving ticket x”)

module fifo_aa;
	bit clk, push, pop; 
	int tag_in, tag_out; 
	bit [7:0] in_data, out_data; 
	initial forever #5 clk=!clk;
	
   property p_data_chk_bad; // problem is uniqueness  <-------******
     bit [7:0] push_data;
     @(posedge clk) (push, push_data=in_data[7:0]) 
               |-> ##[1:10] pop ##0 (out_data == push_data); 
     endproperty 
     ap_data_checker_bad: assert property(p_data_chk_bad);
     
     function void inc_tag_in(); 
     	tag_in = tag_in + 1'b1; 
     endfunction 
     
     property p_data_unique;   // ***** THE FIX 
     	bit [7:0] push_data;
        int v_tag;
       @(posedge clk) (push, push_data=in_data[7:0], v_tag=tag_in, inc_tag_in()) 
               |-> ##[1:10] pop && tag_out==v_tag ##0 (out_data == push_data); 
     endproperty 
     ap_data_unique: assert property(p_data_unique) tag_out =tag_out+1; else tag_out =tag_out+1;
        
     initial begin 
     	#15;if (!randomize(in_data)) $display("error"); 
     	@(posedge clk) push <=1'b1; 
     	out_data <= in_data; 
     	@(posedge clk) push <= 1'b0; 
     	//if (!randomize(in_data)) $display("error"); 
     	@(posedge clk) push <=1'b1; 
     	@(posedge clk) push <= 1'b0; pop <= 1'b1;
     	@(posedge clk) pop <= 1'b0; out_data <= in_data;
     	@(posedge clk) push <= 1'b0; 
     	pop <= 1'b1;
     	@(posedge clk) pop <= 1'b0; 
     end 
endmodule

In reply to ben@SystemVerilog.us:

Ben,

Thank you for the explanation and the details. It is infact getting terminating only when both the push data are same as the 2nd consequent is matched immediately at first pop only.

Just to check my understanding, I think the same issue (in case WRITE → WRITE → READ, assuming the first two writes are writing same data) would be seen in the clock domain assertion specified in one of the recent posts. We need to take a similar care for this assertion too. Correct?

property p_async_fifo; 
   bit[WIDTH-1:0] v_wdata; 
   @(posedge wclk) (!wfull && wen, v_wdata=wdata) |-> 
	@(posedge rclk) ##[1:$] !rempty && ren ##0 rdata==v_wdata; 
endproperty

In reply to :

Understood clearly. Thank you very much for explaining this with a wonderful example too :)