Verilog equivalent of "wait until ... for ..."?

Mousstix picture Mousstix · Sep 11, 2012 · Viewed 34.3k times · Source

In a Verilog testbench, I'm trying to code the following behavior:

  • Wait until an event occurs (rising / falling edge) for a maximum time, i.e. an equivalent of the VHDL instruction:

    wait until <event> for <duration>;
    

which has the following behavior (reminder):

  • either the event occurs;
  • or the duration expires.

Unless I'm mistaken, I did not find any direct equivalent of this function in Verilog... So I tried the following code:

reg watchdog;
// ...

// Set a signal 'watchdog' in background which will be triggered in 10 us.
fork
  watchdog <= #10_000 1'b1;
join

// Wait until SIGNAL is set to '1' *OR* watchdog event occurs.
@(posedge SIGNAL or posedge watchdog);

// Reset the watchdog
watchdog <= 1'b0;

This code does the work but the last instruction does not cancel or supercede the fork instruction. So, in a second call to this code (with for example watchdog <= #50_000 1'b1;), the first watchdog may be triggered (too soon unfortunately).

Any better idea? (either an equivalent or a way to cancel the first planned fork?)

P-S : to do it in SystemVerilog is not an option... ;-)

Answer

dwikle picture dwikle · Sep 11, 2012

To do this in Verilog you need to use disable. I would suggest getting rid of the watchdog signal entirely and just using two branches of a fork.

Below is a working example. Note that each branch of the fork calls disable f if that branch succeeds. Disabling the fork will terminate the branch which did not succeed.

module top;

reg signal;

task test();
   fork : f
      begin
         // Timeout check
         #10
         $display("%t : timeout", $time);
         disable f;
      end
      begin
         // Wait on signal
         @(posedge signal);
         $display("%t : posedge signal", $time);
         disable f;
      end
   join
endtask

initial begin
   // test signal before timeout
   fork
      test;
      begin
         signal = 0;
         #5;
         signal = 1;
         #5;
         signal = 0;
         #10;
      end
   join
   // test signal after timeout
   fork
      test;
      begin
         signal = 0;
         #15;
         signal = 1;
         #5;
      end
   join
end