UVM sequence problem and uvm_do problem

I write a uvm sequence, but I found the uvm_do have problem. The logic is right. But the waveform is not responded to my logic. It has one cycle delay.

 while(1)begin
                if(m_trans.gnt)begin
                  i = i + 1;
                  $display($realtime, " i=%d  my gnt = %d",i, m_trans.gnt);
                  `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                          m_trans.req == 1'b1; 
                                          m_trans.wen == 1'b0; 
                                          m_trans.tcdm_addr == 32'h10000000+4*i;})
                  $display($realtime, " i=%d  my gnt = %d",i, m_trans.gnt);
                
                end
                $display($realtime,"i=%d gnt = %d data=%d", i, m_trans.gnt, data);
        
                   `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                          m_trans.req == 1'b1; 
                                          m_trans.wen == 1'b1; 
                                          m_trans.tcdm_addr == 32'h10000000+4*i;})
               if(i==5)begin
                  break;
               end  
                
         end

This is my code. And this is output.

520 i= 1 my gnt = 1
530 i= 1 my gnt = 0
530i= 1 gnt = 0 data=-1107428987
540i= 1 gnt = 0 data=-1107428987
550i= 1 gnt = 0 data=-1107428987
560i= 1 gnt = 0 data=-1107428987
570i= 1 gnt = 0 data=-1107428987
580i= 1 gnt = 0 data=-1107428987
590i= 1 gnt = 0 data=-1107428987
600 i= 2 my gnt = 1
610 i= 2 my gnt = 0

And I think this UVM_DO(when gnt signal is 1) will last one cycle between 520ns to 530ns.
But from the waveform, I found this UVM_DO(when gnt signal is 1) lasts one cycle between 530ns to 540ns.

I don’t know why does it happen, does anyone know how UVM_DO in detail about its timing.

In reply to jundijiujieke:

The sequence does not know anything about clock_cyles.
And I do not understand the mechanism with the gnt. Where does the gnt come from?
I believe it is not necessary in your sequence code. You can handle this in the driver.

In reply to chr_sue:

Thanks for your reply, it is shaking hand protocol. I send req signal(input), and DUT will output gnt signal(output), when the gnt signal is high, I will change my control signals(input).

In reply to jundijiujieke:

This is my driver code.

ifndef MY_DRIVER__SV define MY_DRIVER__SV
class my_driver extends uvm_driver#(my_transaction);

virtual my_if vif_tcdm;
virtual my_if vif_flash;
virtual my_if vif_ahb ;

`uvm_component_utils(my_driver)
function new(string name = “my_driver”, uvm_component parent = null);
super.new(name, parent);
endfunction

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual my_if)::get(this, “”, “vif_tcdm”, vif_tcdm))
uvm_fatal("my_driver", "virtual interface must be set for vif_tcdm!!!") if(!uvm_config_db#(virtual my_if)::get(this, "", "vif_flash", vif_flash)) uvm_fatal(“my_driver”, “virtual interface must be set for vif_flash!!!”)
if(!uvm_config_db#(virtual my_if)::get(this, “”, “vif_ahb”, vif_ahb))
`uvm_fatal(“my_driver”, “virtual interface must be set for vif_ahb!!!”)

endfunction

extern task main_phase(uvm_phase phase);
extern task drive_one_pkt(my_transaction tr);
endclass

task my_driver::main_phase(uvm_phase phase);
//when wen = 1’d0, write enable, when wen =1’d1, read enable
while(!vif_tcdm.s_soc_rstn)
@(posedge vif_tcdm.s_soc_clk);
$display($realtime,“initialize”);
while(1) begin
seq_item_port.get_next_item(req);
drive_one_pkt(req);
seq_item_port.item_done();
end
endtask

task my_driver::drive_one_pkt(my_transaction tr);

repeat(1) @(posedge vif_tcdm.s_soc_clk);
vif_tcdm.tcdm_addr = tr.tcdm_addr;
vif_tcdm.be = tr.be ;
vif_tcdm.req = tr.req ;
vif_tcdm.wdata = tr.wdata ;
vif_tcdm.wen = tr.wen ;

tr.gnt     = vif_tcdm.gnt      ;
tr.r_opc   = vif_tcdm.r_opc    ;
tr.r_rdata = vif_tcdm.r_rdata  ;
tr.r_valid = vif_tcdm.r_valid  ;
//ahb signals
tr. haddr  = vif_ahb.haddr  ;
tr. hburst = vif_ahb.hburst ;
tr. hprot  = vif_ahb.hprot  ;
tr. hwdata = vif_ahb.hwdata ;
tr. hsel   = vif_ahb.hsel   ; 
tr. hsize  = vif_ahb.hsize  ;  
tr. htrans = vif_ahb.htrans ;
tr. hwrite = vif_ahb.hwrite ; 

tr.hrdata  = vif_ahb.hrdata ;
tr.hready  = vif_ahb.hready ;		  
tr.hresp   = vif_ahb.hresp  ;      

//flash
tr.raddr = vif_flash.raddr;
tr.waddr = vif_flash.waddr;
tr.we = vif_flash.we ;
tr.re = vif_flash.re ;
tr.dout = vif_flash.dout ;
tr.din = vif_flash.din ;

endtask

`endif

In reply to jundijiujieke:

In reply to chr_sue:
Thanks for your reply, it is shaking hand protocol. I send req signal(input), and DUT will output gnt signal(output), when the gnt signal is high, I will change my control signals(input).

I understand the mechanism. But you are checking the gnt in the sseq_item. How does it come to the seq_item?
gnt should not be a variable in your seq_item. It is only necessary to implement your correct protocoöl in the driver.

In reply to chr_sue:

I define the output in my transaction, so i can get the output signal in my sequence.
The sequence is right, only it has one cycle delay when i use uvm_do_with from the waveform.

In reply to jundijiujieke:

I guess the gnt signal comes out of the DUT. Right?
And what are you doing in your driver?
What is that

vif_tcdm.tcdm_addr = tr.tcdm_addr;
vif_tcdm.be = tr.be ;
vif_tcdm.req = tr.req ;
vif_tcdm.wdata = tr.wdata ;
vif_tcdm.wen = tr.wen ;

I guess your seq_item is here ‘req’.
And be, wdata etc are in your seq_item? Right?

In reply to chr_sue:
Yes, gnt comes out of the DUT.
In my driver, I let transaction signal connect to interface each cycle.
My problem is uvm_do has one delay from the waveform.
Can I use create()/start_item()/randomize()/finish_item() so that you can control the entire sequence_item() in my sequence to solve this problem.

In reply to jundijiujieke:

The delay problem is caused in your driver. It does not come from the sequence.
And you are doing strange things in your driver as I asked in my last post.
You are assigning a whole transaction item to your virtual interface

vif_tcdm.req = tr.req ;

What is the virtual interface doing with your seq_item ‘req’? You should clean up your code.

In reply to chr_sue:
OK, you mean my drive_one_pkg task is wrong. Should I remove all the assignments.
The interface is used to connect to DUT as simulus.

And this is my_case code.

ifndef MY_CASE0__SV define MY_CASE0__SV
class case0_sequence extends uvm_sequence #(my_transaction);
my_transaction m_trans;

function new(string name= “case0_sequence”);
super.new(name);
endfunction

virtual task pre_body();
  	$display("%s",get_full_name());

endtask

virtual task body();
int j = 0;
int i = 0;
int k = 0;
int data = 32’d0;

  if(starting_phase != null) 
     starting_phase.raise_objection(this);
     $display($realtime);
     #120ns
     $display($realtime,"stat ");
     `uvm_do_with(m_trans,{m_trans.be == 4'h0;
                           m_trans.req == 1'b0; 
                           m_trans.wen == 1'b0; 
                          })
     $display($realtime,"initial");
     `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                           m_trans.req == 1'b1; 
                           m_trans.wen == 1'b0; 
                           m_trans.tcdm_addr == 32'h10000000;
                           m_trans.wdata == 32'h12345678;})
     $display($realtime,"first ");
     /*`uvm_do_with(m_trans,{m_trans.be == 4'hF;
                           m_trans.req == 1'b1; 
                           m_trans.wen == 1'b0; 
                           m_trans.tcdm_addr == 32'h10000104;})*/
     //$display("%d", m_trans.wdata);
     //end
    
    while(1)begin
            //@(posedge m_trans.gnt);
            //$display("gnt = %d", m_trans.gnt);
            if(m_trans.gnt)begin
              j = j + 1;
              $display($realtime, " j=%d  my gnt = %d",j, m_trans.gnt);
              `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                      m_trans.req == 1'b1; 
                                      m_trans.wen == 1'b1; 
                                      m_trans.tcdm_addr == 32'h10000000+4*j;})
             // #60ns//during this gnt becomes 1 
              //#50ns
              data = m_trans.wdata;
            end
            $display($realtime,"j=%d gnt = %d data=%d", j, m_trans.gnt, data);
            //repeat(1)@(posedge m_trans.gnt)begin
               `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                      m_trans.req == 1'b1; 
                                      m_trans.wen == 1'b0; 
                                      m_trans.tcdm_addr == 32'h10000000+4*j;
                                      m_trans.wdata == data;})
           //if(j==16386)begin
           if(j==12)begin
              $display($realtime, "this is j==5");
              break;
           end  
            
     end

     #40ns
     $display($realtime);
    // while(1)begin
        if(m_trans.gnt)begin
           `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                      m_trans.req == 1'b1; 
                                      m_trans.wen == 1'b0; 
                                      m_trans.tcdm_addr == 32'h10000100;
                                      })
           k = 1;
           $display($realtime);
        end
       /* if(k==1)begin
           break;
        end*/
     //end

      `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                           m_trans.req == 1'b1; 
                           m_trans.wen == 1'b1; 
                           m_trans.tcdm_addr == 32'h10000000;
                           m_trans.wdata == 32'h0;})
     $display($realtime);
     #20ns
     
     while(1)begin
            //@(posedge m_trans.gnt);
            //$display("gnt = %d", m_trans.gnt);
            if(m_trans.gnt)begin
              i = i + 1;
              $display($realtime, " i=%d  my gnt = %d",i, m_trans.gnt);
              `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                      m_trans.req == 1'b1; 
                                      m_trans.wen == 1'b0; 
                                      m_trans.tcdm_addr == 32'h10000000+4*i;})
              $display($realtime, " i=%d  my gnt = %d",i, m_trans.gnt);
             // #60ns//during this gnt becomes 1 
              //#50ns
            end
            $display($realtime,"i=%d gnt = %d data=%d", i, m_trans.gnt, data);
            //repeat(1)@(posedge m_trans.gnt)begin
               `uvm_do_with(m_trans,{m_trans.be == 4'hF;
                                      m_trans.req == 1'b1; 
                                      m_trans.wen == 1'b1; 
                                      m_trans.tcdm_addr == 32'h10000000+4*i;})
           //if(i==16386)begin
           if(i==12)begin
              break;
           end  
            
     end
    //#20ns
 // end
  #100;
  if(starting_phase != null) 
     starting_phase.drop_objection(this); 

endtask

`uvm_object_utils(case0_sequence)
endclass

class my_case0 extends base_test;

virtual my_if vif_tcdm;

function new(string name = “my_case0”, uvm_component parent = null);
super.new(name,parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
`uvm_component_utils(my_case0)
endclass

function void my_case0::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual my_if)::get(this, “”, “vif_tcdm”, vif_tcdm))
`uvm_fatal(“my_case”, “virtual interface must be set for vif_tcdm!!!”)
$display(“%s”,get_full_name());

uvm_config_db#(uvm_object_wrapper)::set(this,
“env.i_agt.sqr.main_phase”,
“default_sequence”,
case0_sequence::type_id::get());//connect the sequence to sequencer

endfunction

`endif

In reply to jundijiujieke:

Unfortunately the code you are providing is confusing.
After your last post I assume req is a variable of your seq_item.
In the previous post you are doing

seq_item_port.get_next_item(req);
drive_one_pkt(req);

This indicates req is a seq_item.
Is it possibel to share your code on EDAPlaygound.com
or privately with me, sending your code to christoph@christoph-suehnel.de.

In reply to chr_sue:

I just follow this example to write my code, and use uvm_do in sequence part.

In reply to jundijiujieke:

That`s not a good example for learning UVM.
It has a xcouple of weaknesses.
I’ll make a couple of adoptions and come back to you.

In reply to chr_sue:
Thanks for your reply, can you recommend me some good UVM projects for me to learn?