How To Drive Two Packets parallely Inside Driver

Hi,

I am trying to develop Memory VIP.In which i have requirement like to drive Command as well As data parallel.

requirements:

  1. Need to receive packets for both row and column command bus,as well as need to drive respective packets on respective bus at same time.

2)if row packets come and no packets for column, then need to drive row packet on row bus as well as same time i need to drive no packet(Specific bit Pattern like NOP)on column and vice versa.And if no packets arrived for both at that time i need to drive NOP on both the bus for both edge positive and negative.Overall if packet is available then need to drive it else always NOP on bus.

in short i Want to develop develop logic such that both row and column bus work interdependently but at same time.

I am unable to figure it how to develop logic according to my requirement.

Can Anyone give me idea how to develop it…!!
Any Sample Code or Examples.!!

Regards,
Harsh

In reply to harsh pandya:

It would be easier to understand your requirement clearly if you could mention some piece of code for the packet transaction class and bus interface signal details.

In reply to karan_18:


class mc_driver_c  extends uvm_driver#(mem_seq_item_c);
  
  //--------------------------------------------------------------------------------------------//
  // Internal variables dclaration //
  //--------------------------------------------------------------------------------------------//
  bit [2:0] wl;                // Write latecy
  bit [4:0] rl;                // read latecy
  bit       par;               // Parity Field
  bit       bl;                // burst length
  bit       ps_no;             // Pseudo no
  event     row_e,col_e;
  
  //--------------------------------------------------------------------------------------------//
  // Row And Column Command Queue //
  //--------------------------------------------------------------------------------------------//
  mem_seq_item_c     row_pkt_q[$]; // Queue To Store Row Packets
  mem_seq_item_c     col_pkt_q[$]; // Queue To Store Column Packets
  //--------------------------------------------------------------------------------------------//
  // Virtual interface //
  //--------------------------------------------------------------------------------------------//
  virtual mem_intf.driver mc_driver_vif; 

  //--------------------------------------------------------------------------------------------//
  // Agent Configuration class handle //
  //--------------------------------------------------------------------------------------------//
  mc_agent_config_c driver_cfg_h;

  //--------------------------------------------------------------------------------------------//
  // Analysis port declaration //
  //--------------------------------------------------------------------------------------------//
  uvm_analysis_port #(mem_seq_item_c) drv_port_mc_ps_0;
  uvm_analysis_port #(mem_seq_item_c) drv_port_mc_ps_1;
  
  //--------------------------------------------------------------------------------------------//
  // component registration //
  //--------------------------------------------------------------------------------------------//
  `uvm_component_utils(mc_driver_c)

  //--------------------------------------------------------------------------------------------//
  // Constructor //
  //--------------------------------------------------------------------------------------------//
  function new (string name,uvm_component parent);
    super.new(name,parent);
    drv_port_mc_ps_0 = new("drv_port_mc_ps_0",this);
    drv_port_mc_ps_1 = new("drv_port_mc_ps_1",this);
  endfunction :new

  //--------------------------------------------------------------------------------------------//
  // Build phase //
  //--------------------------------------------------------------------------------------------//
  function void build_phase(uvm_phase phase);
    void'(uvm_config_db#(mc_agent_config_c)::get(this,"","mc_driver_config"
    ,driver_cfg_h));
    if(!uvm_config_db#(virtual mem_intf )::get(this,"","mem_intf"
    ,mc_driver_vif))begin
      `uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_type_name()
      ,".mc_driver_vif"});
    end
  endfunction :build_phase

  //--------------------------------------------------------------------------------------------//
  // run phase //
  //--------------------------------------------------------------------------------------------//
  virtual task run_phase(uvm_phase phase);    
    mem_initilization();
    fork
      get_item();
      row_pkt_collector();
      col_pkt_collector();
    join
  endtask : run_phase
  

  //--------------------------------------------------------------------------------------------//
  // Initilization //
  //--------------------------------------------------------------------------------------------//
  virtual task mem_initilization();
    bit [5:0] ra;
    bit [7:0] ca;

    `uvm_info(get_type_name(),
    $sformatf("--[  :  mem Initilization Start :  ]--"),
    UVM_MEDIUM)
  ......
  ......
  ......
    `uvm_info(get_type_name(),
    $sformatf("--[  :  mem Initilization Done:  ]--"),
    UVM_MEDIUM)
  endtask : mem_initilization
  
  //--------------------------------------------------------------------------------------------//
  // Driver Packet receive from sequencer //
  //--------------------------------------------------------------------------------------------//
  virtual task get_item();
    forever begin
      seq_item_port.try_next_item(req);
      if(req == null)begin
        if((row_pkt_q.size() == 0) && (col_pkt_q.size() == 0))begin
          rnop_cnop_comb_driver();
         end else if(row_pkt_q.size() > 0)begin
          cnop();
        end else begin
          rnop(); 
        end
      end else begin
        //Storing Packet According to Command
        if(req.cmd_e inside {RD,WR})begin
          mem_seq_item_c col_pkt;
          $cast(col_pkt,req.clone());
          col_pkt_q.push_back(col_pkt);
          -> row_e;
        end else begin
          mem_seq_item_c row_pkt;
          $cast(row_pkt,req.clone());
          row_pkt_q.push_back(row_pkt);
          -> col_e;
        end

          //Sending to score board
          `uvm_info(get_type_name(),
          $sformatf("--[  : %s PKT Arrived In Driver :  ]--",req.cmd_e.name()),
          UVM_LOW)
          if(req.pseudo_no == 0)begin
            req.dir="TX";
            drv_port_mc_ps_0.write(req);
            `uvm_info(get_type_name(),
            $sformatf("--[  : Driver Sent %s PKT To SB In PS%d :  ]--",
            req.cmd_e.name,req.pseudo_no),
            UVM_LOW)
          end else begin
            req.dir="TX";
            drv_port_mc_ps_1.write(req);
            `uvm_info(get_type_name(),
            $sformatf("--[  : Driver Sent %s PKT To SB In PS%d :  ]--",
            req.cmd_e.name,req.pseudo_no),
            UVM_LOW)
          end
        @(negedge mc_driver_vif.ck_t)
        seq_item_port.item_done();
      end
    end
  endtask : get_item
  
//--------------------------------------------------------------------------------------------//
  // Row Packet COllector //
  //--------------------------------------------------------------------------------------------//
  virtual task row_pkt_collector();
    while(1)begin
      wait(row_e.triggered);
      if(row_pkt_q.size > 0)begin
        mem_seq_item_c pkt_r;
        pkt_r = row_pkt_q.pop_front();
        row_cmd_create(pkt_r);
      end
      #1ns;
    end
  endtask : row_pkt_collector

  //--------------------------------------------------------------------------------------------//
  // Column Packet COllector //
  //--------------------------------------------------------------------------------------------//
  virtual task col_pkt_collector();
    while(1)begin
      wait(col_e.triggered);
      if(col_pkt_q.size > 0)begin
        mem_seq_item_c pkt_c;
        pkt_c = col_pkt_q.pop_front();
        col_cmd_create(pkt_c);
      end
      #1ns;
    end
  endtask : col_pkt_collector

//Other Respective task
...
...
...

endclass

hear is code. but is not working like my requirement.

In reply to harsh pandya:

The packet which is sent to scoreboard(via analysis port) should be collected from what is actually being driven on the DUT interface(i.e from the monitor using the virtual interface handle) and not from what is received from sequencer.


virtual task get_item();
    forever begin
      seq_item_port.try_next_item(req);
      if(req == null)begin
       :
       :
      end else begin
        //Storing Packet According to Command
        if(req.cmd_e inside {RD,WR})begin
          drive_column_pkt(req);
        end else begin
          drive_row_pkt(req);
        end
      end
      @(negedge mc_driver_vif.ck_t)
      seq_item_port.item_done();

//This task should drive the DUT interface signals as per the protocol
task drive_column_pkt(...);
:
:
endtask
task drive_row_pkt(...);
:
:
endtask

If it is still not working, please show the code where the interface signals are driven.

In reply to karan_18:

In reply to harsh pandya:
The packet which is sent to scoreboard(via analysis port) should be collected from what is actually being driven on the DUT interface(i.e from the monitor using the virtual interface handle) and not from what is received from sequencer.


virtual task get_item();
forever begin
seq_item_port.try_next_item(req);
if(req == null)begin
:
:
end else begin
//Storing Packet According to Command
if(req.cmd_e inside {RD,WR})begin
drive_column_pkt(req);
end else begin
drive_row_pkt(req);
end
end
@(negedge mc_driver_vif.ck_t)
seq_item_port.item_done();
//This task should drive the DUT interface signals as per the protocol
task drive_column_pkt(...);
:
:
endtask
task drive_row_pkt(...);
:
:
endtask

If it is still not working, please show the code where the interface signals are driven.

Hi Karan,

thank you…!!

packets are coming from sequencer …!!

yes its driving on interface…!!

here issue is not with packet…packets are coming proper manner…!!

but the issue is if i got separate packets for row and column bus i want to drive simultaneously on interface.so basically i need to check is there any packet in other queue.if yes then i need to drive both simultaneously. or if not then need to drive that packet on reactive bus and need to drive nop on other bus.

right now its works but issue is if i have packet inside both row and column queue…my driver is driving those packets one by one not bot at same time.

so my question is what are the changes required to achieve my requirement…!!

and one more thing vip is not connected with dut i am just checking how driver is driving.