Clocking block sampling

Hi,

when I try to sample packets from my monitor using the clocking block I declared in my Interface (pkt.value = vif.cb.value) I get a compilation error.

is it allowed to sample signals using clocking blocks? if so how do I do it?

Thanks,
Moshiko

1 Like

In reply to moshiko:

It is difficult to determine with the little information you provided. Please provide more code along with the exact error message you are getting.

In reply to cgales:
my interface:

interface ram_interface(input bit clk);
  
  logic[4-1 : 0] addr;
  logic[32-1: 0] data;
  logic          cs  ;
  logic          we  ;
  logic          oe  ;
  
  
  clocking cb @(posedge clk);
    
    output #50ps addr,cs,we,oe;
    input #2ps output #50ps data;
  endclocking
  
  modport TB (input clk, clocking cb);
  
endinterface: ram_interface

my monitor:

class ram_monitor extends uvm_monitor;
  `uvm_component_utils(ram_monitor)
  
  function new(name = "ram_monitor", uvm_component parent);
    super.new(name, parent);
  endfunction:new
  
  virtual ram_interface vif;
  ram_seq_item pkt;
  uvm_analysis_port #(ram_seq_item) mon_port;  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if(!(uvm_config_db #(virtual ram_interface)::get(this, "*", "intf", vif)))
      `uvm_fatal(get_type_name(), $psprintf("couldn't get an interface"))
      mon_port = new("mon_port", this);
  endfunction:build_phase
  
  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
  endfunction:connect_phase
  
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    forever begin
      @(vif.cb);
      if(vif.cs == 1 && vif.we == 1)
        begin
          pkt = ram_seq_item::type_id::create("pkt");
          pkt.addr    = vif.addr;
          pkt.data    = vif.data;
          pkt.cs      = vif.cs;
          pkt.we      = vif.we;
          pkt.oe      = vif.oe;
          mon_port.write(pkt);
        end
      if(vif.cs == 1 && vif.oe == 1)
        begin
          pkt = ram_seq_item::type_id::create("pkt");
          pkt.addr = vif.addr;
          pkt.cs   = vif.cs;
          pkt.we   = vif.we;
          pkt.oe   = vif.oe;
          @(vif.cb);
          pkt.data = vif.data; 
          mon_port.write(pkt);          
        end
    end
    
  endtask: run_phase  
endclass:ram_monitor

I mean that pkt.addr = vif.cb.addr is not allowed while in my driver when I drive the DUT using my interface vif.cb.addr <= pkt.addr is allowed.

Thanks!

In reply to moshiko:

Several issues:

  • You will want to create different clocking blocks for different functionality. The directionality of the signals is critical for correct functionality. For a driver clocking block, the signals like ‘addr’ will be outputs. For a monitor clocking block, the signals will all be inputs. Make sure you reference the correct clocking block in each component.
  • When using clocking blocks, all references need to be made using the clocking block (vif.cb.signal). Don’t refer to the signals directly (vif.signal).
  • Don’t use modports. They are design constructs and aren’t used for verification.
  • When assigning values to clocking block signals, you need to use non-blocking assignments.

In reply to cgales:

Thanks for answering!
in the last point you raise you meant that in case of driving I need to use ‘<=’ instead of ‘=’?
If so, that’s exactly what I’m doing in my driver.
another question that I have regrading that(I saw different answer for this but I didn’t completely understood), why when we sampling we use blocking assignment and when we are driving we use non blocking assignments (I know it’s related to racing conditions but I can’t understand this completely, if you have some example I’d love to see it).

and last question regarding clocking block, when we sample a signal we sample it a bit before the clock edge, but what if in the signal’s value changes @(posedge)? it seems like we sample an old value of the signal, am I missing something?

Thanks again!

In reply to moshiko:

You sample with blocking assignments as you are putting values into a testbench structure. You assign with non-blocking assignments as the clocking block uses the output skew to assign the clocking block values to the associated signals.

Clocking blocks are designed to prevent race conditions where signals change at the same time as the clock. You are correct that the input skew will sample all values prior to the clock edge. This ensures that you get the values for all signals correctly and don’t have a mismatch of some signals that have changed and some that haven’t.