In reply to Elaine_71:
It’s difficult to provide an exact answer without being able to reproduce the issue, but there are different timing semantics when using @(intf.mon_cb) and wait(intf.mon_cb.val). The wait statement is blocking, so there may be several clock cycles pass until this unblocks. After the loop finishes, the @(intf.mon_cb) may occur in the same time slice, so it enters the same loop again and you see the same transaction get sampled.
The general rule for clocking blocks is that you use @(intf.mon_cb) to ensure that all signals are updated at that point, and then determine action based on the signal values. You don’t want to use any other blocking constructs when using clocking blocks.