Having issues with wait statements

Hi,

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

In reply to sv_beginner:

You have an @(posedge clk) between the wait() statement and the if statement. It is likely that the signals change during that time period.

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.

In reply to sv_beginner:

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.

So, how can I wait until the statements evaluate? Why does the wait statement execute before the statement get evaluated?

In reply to sv_beginner:

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.

In reply to cgales:

You can also do

@(posedge clk iff (wr_complete == '1 && rd_complete == '1) )

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?

In reply to sv_beginner:

wait (EXPR) statement;

is equivalent to

while (!EXPR) @EXPR;
statement;