Search code examples
vhdlverilog

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


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... ;-)


Solution

  • 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