Time checking sequence

Hi forum!

I want to have a sequence on the antecedent side of my properties in order not to duplicate the function call and local variables in every property. The sequence calls the function and looks for the time whether it has passed a specific delay. Unfortunately, it does seem like antecedent never matches and function is called only once. What’s wrong here?

Here is the code,

module tb;
logic clk;

time delay = 50ms;

function bit check_time();
  $display("running check time %t", $time);
  return ($time > delay) ? 1'b1 : 1'b0;
endfunction

localparam CLK_PERIOD = 1ms;
always #(CLK_PERIOD/2) clk=~clk;

initial begin
    #100ms $finish;
end

sequence check_time_s;
    bit res;
    (1, res = check_time) ##0 (res == 1'b1);
endsequence

property check_time_p;
    @(posedge clk) check_time_s |-> 1;
endproperty
check_delay: assert property(check_time_p)
    else $error("Assertion label failed!");

endmodule

Simulation output,

vsim -voptargs=+acc=npr

run 100ms

running check time 0

** Note: $finish : testbench.sv(15)

Time: 100 ms Iteration: 0 Instance: /tb

End time: 07:07:27 on Feb 24,2021, Elapsed time: 0:00:01

Errors: 0, Warnings: 0

In reply to emin:

A simple error, the TB never clocked because
logic clk; // is initialized to x
COde works OK; made simple mods


module tb;
    bit clk;
     
    realtime delay = 50ms;
     
    function automatic bit check_time();
      // $display("running check time %t", $realtime);
      return ($realtime > delay) ? 1'b1 : 1'b0;
    endfunction
     
    localparam CLK_PERIOD = 1ms;
    // always #(CLK_PERIOD/2) clk=!clk;
    initial forever #10 clk=!clk;  
     
    initial begin
        #100ms $finish;
    end
     
    sequence check_time_s;
        bit res;
        (1, res = check_time()) ##0 (res == 1'b1);
    endsequence
     
    property check_time_p;
        @(posedge clk) check_time_s |-> 1;
    endproperty
    check_delay: assert property(check_time_p) // $display("@t %t PASS", $realtime);
        else $error("Assertion label failed!");
     
endmodule

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact http://cvcblr.com/home.html
** SVA Handbook 4th Edition, 2016 ISBN 978-1518681448

  1. SVA Package: Dynamic and range delays and repeats SVA: Package for dynamic and range delays and repeats | Verification Academy
  2. Free books: Component Design by Example FREE BOOK: Component Design by Example … A Step-by-Step Process Using VHDL with UART as Vehicle | Verification Academy
    Real Chip Design and Verification Using Verilog and VHDL($3) Amazon.com
  3. Papers:

In reply to ben@SystemVerilog.us:

Thank you Ben!
Sorry I forgot to initialize the clock. But real problem is, trying to call the function without parenthesis,

()

After adding parenthesis it worked like a charm. I have few more questions regarding your modifications,

  1. Is it better to use $realtime rather than $time?
  2. Are there any differences between always forever and initial forever?
  3. What is the advantage of using data type bit over logic?

Thank you in advance.

In reply to emin:
function call and task calls with functions and tasks require the empty argument list, in other words the ().


module m; 
  bit f1, a; 
  function f; 
    return 1;
  endfunction
  
  initial begin 
    a=f; // <<< need f()
    $display ("a=%b", a); 
  end 
endmodule
 "Invalid function call: f." "testbench.sv" 8  8

In reply to ben@SystemVerilog.us:

  1. Is it better to use $realtime rather than $time?
    YES>
  2. Are there any differences between always forever and initial forever?
    I don’t believe so; they both work.>
  3. What is the advantage of using data type bit over logic?

With bit, there is no need to initialize the clk. Logic is of course 4 states, but I don’t believe that there is much impact in terms of speed for simulation, maybe less memory.

In reply to ben@SystemVerilog.us:

Thank you Ben, really appreciate it!