

// This is a testcase that shows false assertion firing,
// due to inter-timestep value fluxuations.
// Run this on your favorite verilog simulator.

// To prevent the problem, use +define+PREVENT to disable any
// previously started assertions. This will kill any erroneously
// started ones.

module inter;

  reg rs1, rs1a, s2, s3;

  reg do, d1, d2;

  reg tmp, s1a;

  reg clk;
  initial
    begin
    clk = 1'b1;
    forever clk = #5 ~clk;
    end

  wire  s1  = rs1 | ~s1a;

initial $monitor($stime,, "s1 = %b, s2=%b", s1, s2);

  initial begin
    rs1  <= 1'b0;
    s1a  <= 1'b1;
    s2   <= 1'b0;

    @(posedge clk);
    s1a <= 1'b0;  // Turn on s1.

    @(posedge clk);
    s2  <=    1'b1;    // Oops, we have both selects set...
    s1a <= #1 1'b1;  // Model input delay (from different coding style block.)

    @(posedge clk);

    s2  <= 1'b0;

    repeat (5) @(posedge clk);
    $finish;
    end



  event docheck;
  // Block with out assertion (modeled with a display statement.)
  always @(s1 or s2 or d1 or d2)
    begin
    // This is how one prevents false firings due to inter-timestep
    // value changes. By disabling a previously started assertion
    // it will not fail. NOTE: requiring this kills overlapping 
    // assertions, because disable stops all running blocks/assertions!
    `ifdef PREVENT
    disable checkit;  // disable any (ALL) previous assertions.
    `endif

    `ifdef INTER
    // This is our model of the antecedent in more complex
    // assertions. This may have been several nested if()'s or
    // a case item, etc.
    if (s1) 

      // Model our assertion - //assert never (s1 & s2);
      // This part uses assert (immediate) semantics by checking at the
      // end of the cycle.
	  -> docheck;
    `else
      if (s1) 
      // Model our assertion - //assert never (s1 & s2);
      if (s2) 
        begin
          // This part models assert_strobe semantics.
          -> docheck;
        end
    `endif


    // Our functionality that we are preventing.
    do = s1 & d1 | s2 & d2;
    end

  `ifdef INTER
  // Assert_Strobe model version.
  always @(docheck)
    begin :checkit
    @(posedge clk);
    if (s2)
      $display("Error(1) at time %0d - s1 and s2 are true.", $stime);
    end

  `else

  // Assert_Strobe model version.
  always @(docheck)
    begin :checkit
     #0 $display("Error(2) at time %0d - s1 and s2 are true.", $stime);
     //#0 $display("Error again - was this still running?.");
    end
  `endif

endmodule


