Sequence to that respond to done signal

I am writing the task body below

task body();
  req = packet::type_id::create("rqst");

  start_item(req);
    void`(randomize() with req.sel == 1;
                           req.en == 1;
                           req.addr == 20'h0100;);
  finish_item(req);
endtask : body

I am driving this signals to DUT. After the operation is completed, done bit will be set to 1.
On receiving done with I want to send address 20’h1100. So aim is to receive done as a response from DUT and send the packet to driver with another address. How can I code the sequence body for that.

In reply to bachan21:

To be honest, I do not see any ‘done’ bit in your seq_item.
What do you mean with ‘done’ bit?
Or do you want to send consecutive seq_items? this automatically donw when adding a next start_item/finish_item.

In reply to chr_sue:

done is a part of sequence item class, which is an output from DUT.
done bit is raised to indicate current operation is done and next inputs can be passed.
Should I use multiple start and finish items?

In reply to bachan21:

This is what the call of item_done() in the driver is doing. It is the indication to the sequencer to generate the next seq_item.
start_item/finish_item creates exactly 1 item. If you need more you have to implement multiple start_item/finish_item.
To make your code easy you could use a loop construct in the body method like this

task body();
 repeat (10) begin
  req = packet::type_id::create("req");
  start_item(req);
    void`(randomize() with sel == 1; en == 1; addr inside {20'h0000, 20'h0100};);
  finish_item(req);
endtask : body

This generates seq_item with addr in random order.

It looks like your seq_item has data members you do not need, like sel and en. You can set these variables directly in the driver.

In reply to chr_sue:

I think, I didn’t give much details on my DUT behavior. It takes up the address and performs write action on next 100 addresses near to it. So I had wait till this action is completed to drive next address. If I am using the body you provided it will overwrite the initial address and address calculation for further operation will be blocked. Is there any way to involve response port here?

Also I cant set sel and enable in driver as the driving is different for other tests.

In reply to bachan21:

You are determining the timing behavior in your driver. The next seq_item will be retrieved after the item_done has been sent. This behavior does not override anything.
How do you differentiate your tests? Do you have really differnet protocols in your driver?
I do not believe it.

In reply to chr_sue:

No. I use same protocol. I was looking forward something like response port to achieve this behavior.

In reply to bachan21:

repeat (10) begin
req = packet::type_id::create("req");
start_item(req);
void`(randomize() with sel == 1; en == 1; addr inside {20'h0000, 20'h0100};);
finish_item(req);

But I cant just put my body code like this. The addresses are deterministic in nature. So I have drive to those specific values in order. So should I use multiple start and finish item?

In reply to bachan21:

Deterministic means you have to use fixed addresses in a well-defined order?

In reply to chr_sue:

Yes exactly

In reply to bachan21:
int addr_q[$]; // declaration of a queu to store addresses

in the body method fill the queue with the proper addresses in the right order (using an assigment pattern or a loop.

task body();
   int tmp_addr;
   addr_q = '{addr1, addr2, ...};

    repeat (10) begin
      req = packet::type_id::create("req");
      tmp_addr = addr_q.pop_front();  // returns the first element of this queue
      start_item(req);
        void`(randomize() with sel == 1; en == 1; addr == tmp_addr;);
      finish_item(req);
   end
endtask

In reply to chr_sue:

Yes this can work. A little bit modification in driver will realize my logic.

In reply to bachan21:

Please let us know if it is working.
If the next address depends on some data you receive from the DUT you need a response sent from the driver to the sequence.

In reply to chr_sue:

In reply to chr_sue:

Hi,
This method is working. But I am facing an issue now.
I have created two sequences with 2 different queue values.

bit [19:0] q;

In first sequence (the name is a_seq), I have given following values

q = {20'h983, 20'h183};

In the second q(b_seq), I have given following values

q = {20'h903, 20'h103};

First sequence is working properly and done bit is produced for value 20’h983 and 20’h183
In case of second test only 20’h903 is being passed successfully. Test is hanging when 20’h103 is passsed.

But the crazy thing is when I have assigned 20’h983 and 20’h183 to q of a_seq. It’s driven successfully. Given that the other contents of a_seq and b_seq are same,it doesn’t make any sense. What can be the possible reason for hanging in this situation?

In reply to chr_sue:

In reply to bachan21:
int addr_q[$]; // declaration of a queu to store addresses
in the body method fill the queue with the proper addresses in the right order (using an assigment pattern or a loop.

task body();
int tmp_addr;
addr_q = '{addr1, addr2, ...};
repeat (10) begin
req = packet::type_id::create("req");
tmp_addr = addr_q.pop_front();  // returns the first element of this queue
start_item(req);
void`(randomize() with sel == 1; en == 1; addr == tmp_addr;);
finish_item(req);
end
endtask

@chr_sue ,If i have to drive addr2 based on response of addr1 from driver to sequence depends on “done” bit of sequence item class ,so following below code of driver and sequence is correct ?

driver code ::

task run_phase( uvm_phase phase );
  REQ req_item; //REQ is parameterized type for requests
  RSP rsp_item; //RSP is parameterized type for responses
 
  bit [15:0] rdata;
  bit resp;
 
  forever begin
    seq_item_port.get(req_item); // finish_item in sequence is unblocked
 
    //BFM handles all pin wiggling 
     drive(req_item);
 
    $cast(rsp_item, req_item.clone()); // Create a response transaction by cloning req_item
    rsp_item.set_id_info(req_item); // Set the rsp_item sequence id to match req_item
    
    rsp_item.done = resp;
    seq_item_port.put(rsp_item); // Handshake back to the sequence via its get_response() call
  end
endtask

sequence code ::

task body();
   int tmp_addr;
   addr_q = '{addr1, addr2, ...};
 
      req = packet::type_id::create("req");
      tmp_addr = addr_q.pop_front();  // returns the first element of this queue
      start_item(req);
        void`(randomize() with sel == 1; en == 1; addr == tmp_addr;);
      finish_item(req);
     //first addr1 sequence is completed

     get_response(rsp);   //wait for response for first addr1

    if(rsp.done == 1)
    begin
    req = packet::type_id::create("req");
      tmp_addr = addr_q.pop_front();  // returns the second element of this queue 
      start_item(req);
        void`(randomize() with sel == 1; en == 1; addr == tmp_addr;);  
      finish_item(req);
    end
    
     
endtask