Uvm sequence need to know dut signal value after posedge

Hi,
I am writing a uvm test bench for a design. My driver & sequence sends data to DUT & Driver resp. using the code below; For sequence, to prepare next data item, it needs knowledge of dut signal value in current cycle (after dut completed its work on signal). I am able to achieve this by using #2 delay in driver, updating dut signal value in seq item after delay, then calling item_done(). Now, when sequence thread is unblocked by item_done call, knows dut value and uses it to prepare next item.
Driver code:
forever begin
@(vif.tb_drv_cb);
if (vif.rst) begin
vif.tb_drv_cb.data <= 32’b0;
vif.tb_drv_cb.vld <= 1’b0;
end else begin
seq_item_port.get_next_item(pkt);
vif.tb_drv_cb.data <= pkt.data;
vif.tb_drv_cb.vld <= pkt.vld;
#2;
pkt.rdy = vif.rdy;
seq_item_port.item_done();
end
end
Sequence Code:
virtual task body;
int i = 0;
bit l_vld = 0;
pkt = packet::type_id::create(“pkt”);
repeat(10) begin
if(pkt.rdy && l_vld) begin
i++;
end
pkt.randomize();
pkt.data = i;
l_vld = pkt.vld;
end
start_item(pkt);
if(pkt.rdy && l_vld) begin
i++;
end
pkt.vld = 0;
pkt.data = i;
finish_item(pkt);
endtask : body
I am searching for answer without using any # delay. Is this possible?

In reply to verif_eng_20:

3 things:
(1) You never need to know values of virtual interface signals in the sequence. Per definition the sequences does not have any relationship to the virtual interface.
(2) dealing in the driver with absolute delays like #2 is useless and adds risk. The driver is syynchronized only by the clock signal.
(3) If you need response data from your DUT in the seuqnce you can pass back from the driver data to the sequence.

In reply to chr_sue:

Yes, I agree.
To pass DUT data back from driver to sequence, how can I read current cycle DUT value of signal in driver?

In reply to verif_eng_20:

Your DUT interface follows a certain protocol. This is indicating when read data are available and valid. You are are storing the read data in the response tarnsaction and send it back to the sequence.

In reply to chr_sue:
Yes, when storing read data, I will have race condition between read vs DUT write.
If I use clocking block, I would get to see previous clock edge value. (I could get value after current clock edge modifying default sampling behavior to sample after clock edge, but this is again equivalent to using Delay). Probably, I can’t get to see value after current clock edge without using # delay in UVM.

In reply to verif_eng_20:

Are you sure this is a race condition? Your protocol should be save. You could sample the read data on the falling edge.

In reply to chr_sue:

I was under impression that driver should always send data on every clock edge to DUT. I modified the code without using # delay and achieved same behavior with this
Driver Code:
super.run_phase(phase);
do begin
@(vif.tb_drv_cb);
if(vif.rst) begin
vif.tb_drv_cb.vld <= 0;
vif.tb_drv_cb.data <= 0;
end
end while (vif.rst);
forever begin
seq_item_port.get_next_item(pkt);
vif.tb_drv_cb.data <= pkt.data;
vif.tb_drv_cb.vld <= pkt.vld;
@(vif.tb_drv_cb);
if(pkt.vld) begin
while(!vif.tb_drv_cb.rdy) begin
@(vif.tb_drv_cb);
end
end
seq_item_port.item_done();
end
Sequence Code:
repeat(20) begin
start_item(pkt);
if(l_vld) begin
i++;
end
pkt.randomize();
pkt.data = i;
l_vld = pkt.vld;
finish_item(pkt);
end
With this, sequence becomes easy, it would send data same as before it vld is low else increments and send.
Driver now blocks itself till it sees DUT rdy high.
//////////////////////////////////////////
I believe sampling at neg edge as you have said also works.

Thank you.