In reply to Elaine_71:
Realize that a UVM testbench is more like software passing values through task/function arguments. If you try to use a non-blocking assignment to a variable and then immediately pass that variable to a routine argument, the argument gets the old value of the variable. In the design, we do not use function calls to pass values; we set signals before a clock edge, and the design captures the value synchronized to a clock edge. We use non-blocking assignments to the DUT to prevent races conditions with the clock edge.