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