Clocking blocks in UVM and sampling in UVM monitor

Here is my interface for a BRAM:

--------------------------------------
//interface
interface ram_if(input logic clk);
  logic            wr_en;
  logic [ADDR-1:0] wr_addr;
  logic [DATA-1:0] wr_data;
  logic[ADDR-1:0] rd_addr;
  logic [DATA-1:0] rd_data;

clocking driver_cb @(posedge clk);
  default input #1 output #1;  
  output wr_en;
  output wr_addr;
  output wr_data;
  output rd_addr;
  input rd_data;  
endclocking

clocking monitor_cb @(posedge clk);
  default input #1 output #1;  
  input wr_en;
  input wr_addr;
  input wr_data;
  input rd_addr;
  input rd_data;  
endclocking
endinterface
 -----------------------------Monitor code --------------------
 virtual task run_phase(uvm_phase phase);
 forever begin
   @(posedge ram_vif.clk);
     if(ram_vif.wr_en) begin
       seq_item_collected.wr_en = ram_vif.wr_en;
       seq_item_collected.wr_addr = ram_vif.wr_addr;
       seq_item_collected.wr_data = ram_vif.wr_data;
     end
   seq_item_collected.rd_addr = ram_vif.rd_addr;
   //wait for a read to be effective
   @(posedge ram_vif.monitor_cb);     
   seq_item_collected.rd_data = ram_vif.rd_data;

   trans_collected_port.write(seq_item_collected);

end //forever
endtask : run_phase
-------------------------------------

How important is it to have clocking blocks?
I have gone through lot of info about clocking blocks. Still not clear, when to have them?
Is i/p and o/p skew specified depends on the design?
What values to mention, if i dont have any specific values?
I read somewhere that, monitor must have clocking block? How about driver?

In above monitor sampling:
@(posedge ram_vif.monitor_cb);
seq_item_collected.rd_data = ram_vif.rd_data;

If i do:
@(posedge ram_vif.monitor_cb);
seq_item_collected.rd_data = ram_vif.monitor_cb.rd_data;

I dont get expected data. ram_vif.rd_data works fine. Any reason?
This is the case with many other modules too.
Not sure, if i am missing something. Please clarify.

In reply to uvmsd:

Two things only:
(1) clocking blocks are an automatic mean to avoid races between testbench and DUT. I consider this as an option.
(2) When using a clocking block you are süecifying ind the clocking block definition the sampling event. Synchronizing on the clocking block does not need a posedge/hegedge. It is simply

@(ram_vif.monitor_cb);

In reply to chr_sue:

Hi ,

Need your suggestions in verifying a Moore FSM .

On Sampling signal "a" high on posedge of clock , the State Machine would enter State HIGH_A ( from lets say a Default State ) and drive Output Signal OPA High .

Now this OPA signal could either be Driven through Blocking Assignment ( i.e Combinationally Driven ) or through Non-Blocking Assignment ( i.e Sequentially Driven )

Now my Monitor also Samples signals on posedge of clk . I want to check inside Monitor whether Signal OPA is High or Not ( Error Condition ) on entering State HIGH_A

(a) Am I correct in believing there is a potential race condition between OPA being Driven ( either through Blocking or Non-Blocking Assignment ) and the Monitor Sampling OPA on observing signal “a” high on posedge of clock ?

(b) How could Clocking Blocks be helpful in Sampling OPA correctly ? There is always a possibility that signal a goes low before next posedge of clock , so DUT has entered State HIGH_A and if monitor missed out sampling a High on posedge of clock , it would be left back

(c) One Possibility I see is through #0 input skews which Sample Values in Observed Regions .
But I have read its not a recommended approach although I don’t understand why so ? . It certainly would help my monitor in Sampling Correct Value of OPA Signal in this case

Thanks ,
Himanshu Valecha

In reply to chr_sue:

@chr_sue

Thanks for the clarification!
I will change my code accordingly. Somehow it didn’t report any error/issue so far.

Will @(ram_vif.monitor_cb); just synchronizes or adds any delay?

If i have to wait for 2 clock cycles in monitor before sampling, how do i mention?

In above monitor sampling:
@(ram_vif.monitor_cb);
seq_item_collected.rd_data = ram_vif.rd_data;

If i do:
@(ram_vif.monitor_cb);
seq_item_collected.rd_data =ram_vif.monitor_cb.rd_data;

In my code, the later doesn’t seem to work. Not sure if it was because of posedge that i had used earlier.

Please let me know.Thanks in advance!