Clock edge is not getting detected inside forever loop

I am trying a simple example in UVM. I am expecting the clock edge to be detected and print the transactions collected from interface. But, the posedge of clock written inside task ‘run_phase’ is not detected, in the sense, nothing after that clock edge statement is executed. FYI, I don’t have any clocking block declared in the interface. If I don’t use clock edge then it will become an infinite loop and print forever. How to fix this ? Thanks.

class ahb_monitor extends uvm_monitor;

	`uvm_component_utils(ahb_monitor);

	uvm_analysis_port#(ahb_tx) ap;	 // analysis port used for broadcasting

	virtual ahb_if vif;

	ahb_tx tx;

	function new (string name ="", uvm_component parent = null); // constructing monitor component

		super.new(name,parent);  

		ap = new ("ap", this); // object for analysis port
		
	endfunction
	
	function void build_phase(uvm_phase phase);

		uvm_config_db#(virtual ahb_if)::get(this,"","phy_intf_var",vif);

	endfunction

	task run_phase(uvm_phase phase);
		
		  //$display("mon run phase when reset high at %g", $time);
		forever begin
                        tx = ahb_tx::type_id::create("tx"); // for every new collection, new tx item is created 
			@(posedge vif.hclk);	// here is the problem 
				
				tx.addr = vif.addr;
				tx.dataQ = vif.dataQ;
				tx.wr_rd = vif.wr_rd;
				tx.burst_type = vif.burst_type;
				$display("displaying monitor contents");
				tx.print();
				$display("------------------------------");
                                ap.write(tx); // broadcast Tx
			
		end 
		
	endtask
endclass

In reply to rakesh2learn:

It is possible that the clock ‘hclk’ is not getting generated and is not connected to top level clock.

  • Add a check to see if you are getting interface pointer from configuration database,
if(!uvm_config_db#(virtual ahb_if)::get(this,"","phy_intf_var",vif))
  `uvm_fatal("AHB/MON", "Cannot get virtual interface.");

In reply to rakesh2learn:

An additional remark: Move the creation of your transaction outside of the forever loop:
task run_phase(uvm_phase phase);
tx = ahb_tx::type_id::create(“tx”); // for every new collection, new tx item is created
forever begin
@(posedge vif.hclk); // here is the problem
tx.addr = vif.addr;

end
endtask

In reply to mayurkubavat:

I am not getting UVM fatal print, so which means I am getting virtual interface to monitor, right ?
Below you can see the top and interface. As you can see I have included hclk in interface. Any other reason for the cause of this issue ?

interface ahb_if (input bit hclk, hresetn);

	bit [31:0] addr;
	bit [31:0] dataQ;
	bit wr_rd;
	bit [2:0] burst_type;	

endinterface
module top;
	
	`include "test_lib.sv" 

	reg hclk, hresetn;		
	
	initial begin 

		hclk = 1'b0;
		forever begin

			 #5 hclk = ~hclk;
	 	end
			
	end 

	initial begin   // active low reset generation 

		hresetn = 1'b0; 
		repeat(10) @(posedge hclk); 
		hresetn = 1'b1;
	end 	

	ahb_if inf(hclk, hresetn); // instantiating interface


	initial begin
	
		uvm_config_db #(virtual ahb_if)::set(null,"*","phy_intf_var",inf);  // registering physical interface to config_db with field name phy_intf_var
	end 

	initial begin
			
		run_test();
	end


endmodule

In reply to chr_sue:

Thanks. Also updated the code in my question.

In reply to rakesh2learn:

Another thought is,

  • You are not using monitor component at all? Add and check for any other display messages. Like, “MON: getting interface”, “MON: Entered run phase” etc. See if you are creating monitor component, and not just compiling!

  • Or run phase is ending immediately, in that case check if you are using objections correctly.

phase.raise_objection(this);
  // Add multiple clock delay
phase.drop_objection(this);
  • It is better to use setting of virtual interface and run_test() in same initial block as it might cause fail to get method because of execution order of initial block.
initial
  begin
    uvm_config_db #(virtual ahb_if)::set(null,"*","phy_intf_var",inf);
    run_test();
end

In reply to rakesh2learn:

I guess you have the classical setter-no-getters issue here. The set should be done to the agent level typically. I see you are doing at null & * - sort of global name-space. You should be able to debug this quite easily through check_config_settings, see my DVCon US slides @ http://www.go2uvm.org/2016/07/advanced-uvm-tutorial-from-dvcon-us-2016-slides-now-available/

Good Luck
Srini
www.go2uvm.org

In reply to mayurkubavat:

I am getting display messages like for example, ‘getting interface’ inside build phase and ‘entered run phase’. I have made run_test and set interface in the same initial block as suggested. No monitor output yet. Could you check if I am raising and dropping objections correctly as shown below:

class ahb_base_seq extends uvm_sequence #(ahb_tx); // created base sequence
	
	`uvm_object_utils(ahb_base_seq);
	
	function new (string name ="");  

		super.new(name); 
		
	endfunction
	
	task pre_body();

		if (starting_phase !=null)

			starting_phase.raise_objection(this);

	endtask

	task post_body();

		if (starting_phase !=null)

			starting_phase.drop_objection(this);

	endtask

endclass

// functional sequence
class ahb_10_tx_seq extends ahb_base_seq;
	
	`uvm_object_utils(ahb_10_tx_seq);

	function new (string name ="");  

		super.new(name); 
		
	endfunction
	
	task body();
		
		super.pre_body(); 
		repeat(10) `uvm_do_with(req,{ req.wr_rd==1'b1; }); 
		super.post_body();

	endtask

endclass

In reply to rakesh2learn:

Never raise objections in a sequence. Objections should be raised and dropped only at the test level. This is due to the performance overhead related to the raising and dropping of the objection, as well as the complexity required to determine if it should be raised or dropped.

I found the problem. Sorry, this was due to my carelessness. The driver was finishing at zero simulation time, because while driving I didn’t include clock edge in driver. Thanks to all of your valuable comments, I learned new things from your answers. As I didn’t post my driver code here so all the answers/suggestions are valid and helped me to narrow down to the root cause of the problem. Thank you all.

In reply to Srini @ CVCblr.com:

I used NULL while setting interface in top file because here the context represents its parent name and there is no parent for top file and that is why I kept it NULL and for instance argument I used *, so that the interface is set to all instances below top. This is my understanding. Correct me if I am wrong.