Achieving a 4x1 Mux using port

Hi ,

I have 4 Sub-Components with put ports . These 4 Child ports are connected to a single Parent port and the parent port is connected to an Imp.

From the parent component I want depending on some logic Only 1 Sub-port should communicate with the Imp at a time till select line changes ( Logic for selecting port )

Here is my code ::



class componentA extends uvm_component;
   `uvm_component_utils(componentA)
 
  uvm_blocking_put_port #(string) m_put_port;
 
   function new (string name = "componentA", uvm_component parent= null);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      
      m_put_port    = new("m_put_port", this ); 
   
   endfunction

   

   virtual task run_phase (uvm_phase phase);
      int unsigned Index ;
	   phase.raise_objection(this);
	   
	   for ( int i = 1 ; i < 3 ; i++ )  // Call put() Twice !!
		begin 

         m_put_port.put( get_name() ); // Only m_put_port.get_name() would return same instance name !! 
		 # 3 ; 
         
	    end
     
       `uvm_info (get_name, $sformatf(" All put Done "), UVM_LOW)
	   phase.drop_objection(this);

   endtask

   
endclass 

class componentB extends uvm_component;
   `uvm_component_utils (componentB)

  uvm_blocking_put_imp #( string ,componentB) m_put_imp;

   function new (string name = "componentB", uvm_component parent= null);
      super.new (name, parent);
   endfunctionclass componentA extends uvm_component;
   `uvm_component_utils(componentA)
 
  uvm_blocking_put_port #(string) m_put_port;
 
   function new (string name = "componentA", uvm_component parent= null);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      
      m_put_port    = new("m_put_port", this ); 
   
   endfunction

   

   virtual task run_phase (uvm_phase phase);
      int unsigned Index ;
	   phase.raise_objection(this);
	   
	   for ( int i = 1 ; i < 3 ; i++ )  // Call put() Twice !!
		begin 

         m_put_port.put( get_name() ); // Only m_put_port.get_name() would return same instance name !! 
		 # 3 ; 
         
	    end
     
       `uvm_info (get_name, $sformatf(" All put Done "), UVM_LOW)
	   phase.drop_objection(this);

   endtask


   virtual function void build_phase (uvm_phase phase);
      
      m_put_imp = new("m_put_imp", this);
   
   endfunction


   task put ( string INT ) ;
    `uvm_info ("CompB", $sformatf(" Called from %0s ",INT), UVM_LOW)

   endtask


endclass


class agent extends uvm_agent ;

 `uvm_component_utils(agent) 

  componentA compA[] ;
  componentB compB ;
  
  uvm_blocking_put_port #(string) p_put_port;

   function new (string name = "agent", uvm_component parent= null);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      compA = new[4] ;
     
	 for ( int i = 0 ; i < 4 ; i ++ ) 
       compA[i] = componentA::type_id::create ($sformatf("compA_%0d",i), this);
     
	   compB = componentB::type_id::create ($sformatf("compB"), this);
       
	   p_put_port = new( "p_put_port" , this );

   endfunction

   virtual function void connect_phase (uvm_phase phase);
   
       for ( int i = 0 ; i < 4 ; i++ )
	    begin

          compA[i].m_put_port.connect(p_put_port); 
           
		end
   
          p_put_port.connect(compB.m_put_imp); 
   
   endfunction
   
  task run_phase ( uvm_phase phase ) ; 

    // Need Logic here ??


  endtask 

endclass


// Inside a module 

agent ag ;

initial begin

ag = new("ag",null);

run_test();

end


Currently if I run this all 4 ports communicate with the Imp .
I want that even if I call put() from all 4 ports at same time , control shouldn’t transfer to the Imp for 3 of them .

Ex: At time 0 if select line is 0 ( Logic needed ) , only put() from CompA[0] should call the put() method in Imp whereas put() called from other ports shouldn’t call Imp ( Since Select line is 0 , Input 0 should be transferred to Output )

In reply to MICRO_91:

Could you please elaborate what is the background of this very specific requirement. Is this on the driver or the analysis side?

In reply to MICRO_91:

I am not sure that there is any way to block the transaction on any port but you can filter it inside the put.


class componentB extends uvm_component;
  
  //indicate the currently selected line
  bit [1:0] selected_line;
  
   `uvm_component_utils (componentB)
 
  uvm_blocking_put_imp #( string ,componentB) m_put_imp;
 
   function new (string name = "componentB", uvm_component parent= null);
      super.new (name, parent);
      selected_line = 0;
   endfunction
  
   virtual function void build_phase (uvm_phase phase);
 
      m_put_imp = new("m_put_imp", this);
 
   endfunction
 
 
   task put ( string INT ) ;
     string tmp;
     tmp.itoa(selected_line);
     tmp = {"compA_", tmp};
     
     //Use the transaction only if it's sent by selected port
     if(tmp == INT)begin 
    	`uvm_info ("CompB", $sformatf(" Called from %0s ",INT), UVM_LOW)
     end
   endtask
 
 
endclass

In reply to chr_sue:

Hi ,

There isn’t a specific requirement . Just trying out different code .

In reply to Rahulkumar Patel:

Other solution I thought of is using config_db::get() from inside the put() method and setting it from logic . So while get() is same as input to put() we proceed with method else we skip the method .