I have couple of tasks in a testbench that does continuous writes and reads. Example is shown below. Each task after they are called should be waiting on the expression inside the wait statement. But sometimes, the wait statement executes prematurely although the expression is not true. I know that the expression is not true because the signals inside the “if” statement following the wait statement inside the tasks do not exceute.
Please let me know as to what I am doing wrong here.
task write ();
wait(wr_complete == 1 && rd_complete == 1'b1);
@(posedge clk);
if (wr_complete == 1 && rd_complete == 1'b1)
begin
wr <= 1'b1;
addr <= {4{$urandom}};
end
repeat(2) @(posedge clk);
....
....
endtask
task read ();
wait(wr_complete == 1 && rd_complete == 1'b1);
@(posedge clk);
if (wr_complete == 1 && rd_complete == 1'b1)
begin
rd <= 1'b1;
addr <= {4{$urandom}};
end
repeat(2) @(posedge clk);
....
....
endtask
repeat (10)
begin
write();
read();
end
I checked for the signals in the wait expression even using the monitor statement, but they don’t change when the wait expression evaluates. “wait” expression evaluates, for example, when the wr_complete is still a LOW and rd_complete was HIGH from before.
The signals don’t necessarily have to change for the wait statement to evaluate as true.
Is there a specific reason you are using both a wait() statement and then an if statement? Why not ‘while (wr_complete && rd_complete) @(posedge clk);’
Without seeing more code, it’s difficult to provide more analysis. Can you post a self-contained example that demonstrates your issue?
The “if” statement doesn’t really have to be there. I removed it and the problem with the wait statement still persists. Using the “while” hangs up the simulation.
"The signals don’t necessarily have to change for the wait statement to evaluate as true. " - this is the issue I’m facing. Isn’t “wait” supposed to block the process until that particular expression becomes true? Maybe my understanding of the “wait” is wrong.
I can post the code, but it is huge. The testbench that I posted above tests a RAM and the RAM has the “wr_complete” and “rd_complete” to signal if the operations are complete.
The while() statement I provided earlier is incorrect. If you need to wait until wr_complete and rd_complete are both high, then you want:
while (!(wr_complete && rd_complete)) @(posedge clk);
The wait() statement is immediately evaluated when called. If it passes, then execution continues. If it doesn’t pass, then it will block. If you do a simultaneous read and write, then both while() statements will pass, but then one if statement will fail due to a race condition.
You don’t have to post your entire testbench. Just a small code example that shows the problem you are having.
Thank you so much dave_59 and cgales. Both the solutions work.
But I am still a little bit curious about the wait statement.
“The signals don’t necessarily have to change for the wait statement to evaluate as true.” - Why is this the case? Shouldn’t both the signals need to be HIGH for this wait statement to evaluate as true and unblock the rest of the code that follows?
How is the wait statement in general different from a while statement?