No time pass after @xxx_cb;

I have encountered a strange question:

`uvm_info("info1");
@inst_cb;
`uvm_info("info2");

normally, there should be 1 period time pass between these two infos,
but these 2 “uvm_info” was printed in the same time, just like there is no “@inst_cb”;

how could this happen? and how to avoid this, or solve this?

In reply to whwjez:

You are going to need to provide more context. What event controls come before the first info statement? If there was a @(posedge clk) before, and inst_cb is defined with that clock, you have a race condition.

My recommendation is that you only use the clocking block event control and no other event controls within the same process.

In reply to dave_59:

It Looks really like a Problem with mixing CB and clk Control.
See my example below (without a CB). It works fine.

module top;

 import uvm_pkg::*;
 `include "uvm_macros.svh"

 logic clk = 1'b0;

 always #10 clk = ~clk;

 initial begin
   `uvm_info("ID0", "info1", UVM_LOW);
    @clk;
   `uvm_info("ID0", "info2", UVM_LOW);
   $stop;
 end

endmodule

In reply to dave_59:

thank you for your advice. It is a big program and I can’t put it here, but it really looks like what you said, I use both “@(posedge clk_a)” and “@clocking_block” in the same program, and the clocking block is @clk_a. I am gonna use clocking_block only in this program.

In reply to chr_sue:

Can you tell me why mixing CB and clk Control can lead to a race condition? or is there any other document you can recommend me to read?

In reply to whwjez:

The description of clocking blocks in the LRM is in need of much improvement. See 0003012: Cleanups needed on clocking block text (Mantis 890 revisited!) - Accellera Mantis

The LRM says that the clocking block event is equivalent to the specified event control. But that can’t be true because a clocking block is a concurrent process that has to receive the the event and then generate the clocking block event. They have to be two separate events. Think of a clocking block as an implicit always block

clocking cb @(posedge clk);
input ...;
output ...;
endclocking
always @(posedge clk) begin : translated_cb
  // input sampling here
  // output scheduling here
  ->cb;
end
initial block
   @(posedge clk)
   ///
   @cb; // this is race


Without the clarification mentioned in the Mantis link, there is no way to predict if the cb event has already fired - either @(posedge clk) could resume first. With the clarification, the translated always @(posedge clk) happens later, and the behavior you are seeing will be expected.

In reply to dave_59:

Thank you for your answer, but when I only use clocking block as the event control, the there still race conditions, below is my simple test:


interface my_intf(input bit sys_clk);
	clocking cb @(posedge sys_clk);
	endclocking
endinterface

import uvm_pkg::*;
module top();

bit	clk=0;
my_intf	my_intf0(clk);

initial begin
	$timeformat(-9, 1, "ns", 10);
end

initial begin
	clk = 1;
	forever begin
		#5ns	clk = ~clk;
	end
end


initial begin
	`uvm_info("", $sformatf("before"), UVM_LOW);
	@my_intf0.cb;
	`uvm_info("", $sformatf("middle"), UVM_LOW);
	@my_intf0.cb;
	`uvm_info("", $sformatf("after"), UVM_LOW);
end
endmodule

the output is printed as below:


UVM_INFO ./test.sv(1298) @ 0.0ns: reporter [] before
UVM_INFO ./test.sv(1300) @ 0.0ns: reporter [] middle
UVM_INFO ./test.sv(1302) @ 10.0ns: reporter [] after

there is no time pass between “before” and “after”.
Can you help me? please. thank you

In reply to whwjez:

by the way, the timescale is “1ns/1ps” in my makefile.

In reply to whwjez:

This is because of the clk=1; statement at time 0 in the second initial block. Remove it and you get rid of the time 0 race between initial blocks and the @cb event at time 0.