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:
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:
In this way, you wait every clock only if the cb.data is high.
Code: https://www.edaplayground.com/x/5Cev
Be careful with when using @(clocking_block). This is not same as @(posedge clk)
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)
- 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)
- The clock event used to trigger the clocking block must not come from a program. (we do not recommend using program blocks anyways)
- 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
Post a Comment