verilogsystem-verilog

System Verilog equivalent of VHDL's "wait until rising_edge() for ..." followed by "if rising_edge()"


I'm looking for SV code that is equivalent to these lines in VHDL:

process begin
    wait until rising_edge(mysig) for 1 us;
    if rising_edge(mysig) do_something() else do_something_else(); end if;

By adapting an answer from @dave_59 on another forum, I have the following SV task which I think implements the 'wait until rising_edge()' line above:

task automatic timed_re_wait (ref logic sig, input time timeout);
    bit expired;
    fork begin
        fork begin #timeout; expired = '1; end
        join_none
        wait(@posedge sig or expired);
        disable fork;
    end
    join
endtask

As the VHDL IF statement above implies, the timeout is not necessarily an error condition, so I don't want to create any sort of error message in the task. I want to leave that to the next line in the code after the task is called, e.g.

initial begin
    timed_re_wait(mysig, 1us);
    // now do something if posedge(mysig), do something else if not

Did I implement the timed_re_wait() task correctly? It seems to work in simulation, but I have not considered if there are corner cases I'm missing.

Regarding the code after the call to the task, how can I detect if there is currently a rising edge on mysig? If that can't be done, is my only other option to have the task output the 'expired' bit and use that in my IF?


Solution

  • I think this should work for you. I would use an event instead of a bit for the expired.

    module top;
      
      logic mysig;
      task automatic timed_re_wait (ref logic sig, 
                                    input time timeout, event expired);
        fork begin
          fork
            #timeout -> expired;
          join_none
          @(posedge sig or expired);
          disable fork;
        end join
      endtask
          
      initial begin
        event timo;
        timed_re_wait(mysig, 1us, timo);
        if (timo.triggered) $display("timed out"); // valid only in same timestep
      end
    endmodule