Skip to main content

Waiting on clocking block signals

Its a good practice to use the clocking blocks for creating verification components.

There are some scenarios, where you have to wait on change on some values. As an example, when DUT drives the valid signal, in monitor you wait for valid signal and then read other signal on next clock.

Lets say the DUT drives a valid signals and in your monitor you have to wait till valid is high and wait for two clocks. Then in your montior, you do something like this:

wait (interface.cb.valid == 1'b1);
@interface.cb;
@interface.cb;

What do you expect?
when valid happens, then wait for two clock cycles. But this may not happen. the first wait and then @interface.cb may happen in same cycle.
This is because the clocking block events are synchronous. The wait and the @() statement will execute in same delta.

Instead, the best way is to use this:

@(tif1.cb iff tif1.cb.data);

In this way, you wait every clock only if the cb.data is high.

Code: https://www.edaplayground.com/x/5Cev


interface tif(input clk);

logic data;

clocking cb@(posedge clk);
input data;

endclocking

endinterface

module test;

reg clk;
tif tif1(clk);

initial begin
    tif1.data = 1'b0;
    #12;
    tif1.data <= 1'b1;
end

initial begin
    //wait(tif1.cb.data == 1'b1);  //This happens on 15ns. (12ns assignment. 15ns on posedge of clock)
    @(tif1.cb iff tif1.cb.data);
    $display("[%t]:: After waiting for cb.data",$time); //Here time is 15ns.
    @(tif1.cb); //Expect this to happen at next clock edge
    $display("[%t]:: After waiting for cb",$time); //Here time is 15ns. //expect the time here to be 25ns. one posedge later.
end

initial
begin
#1000 $finish;
end
initial
begin
    clk <= 1'b0;
    forever
    begin
        #5;
        clk <= ~clk;
    end
end
endmodule

Be careful with when using @(clocking_block). This is not same as @(posedge clk)

  1. All samples and drives to clocking block inputs and outputs respectively must be synchronized to the clocking block event (cb). Do not use any other events or waits other than @cb or @(cb iff signal==1)
  2. The clock event used to trigger the clocking block must not come from a program. (we do not recommend using program blocks anyways)
  3. Once you start using clocking blocks in an interface, do not reference those signals from anything other than the clocking block in your testbench.

Comments