user3111358
user3111358

Reputation: 311

UVM: Driving clock through interface

I'd like to be able to control the clock/data pair on a UVC interface. Controlling data is relatively straight-forward. Where I am getting wrapped around the axel is with the clock.

How can I control the clock in the interface such that it can be gated off/on? Should the virtual interface clock assignment to the reference clock be handled in the driver, or elsewhere?

I've found that is the clock assignment is handled in the get_and_drive task, the clock assignment does not occur.

task get_and_drive();
vif.d_in <= 'b0;
vif.clk_in = vif.ref_clk;   // does not work
forever
  begin
    seq_item_port.get_next_item(req);
    send_to_dut(req);
    seq_item_port.item_done();
  end
endtask : get_and_drive

I've done the usual research, and so far, have come up empty.

Upvotes: 1

Views: 2648

Answers (2)

Tudor Timi
Tudor Timi

Reputation: 7573

The simplest thing you can use is a procedural assign. This is a more obscure feature of the standard.

task get_and_drive();
  vif.d_in <= 'b0;
  assign vif.clk_in = vif.ref_clk;   // does not work
  // ...
endtask : get_and_drive

I don't know how you want to disable the clock (probably based on some field of your request, you want to do it in send_to_dut(...)), but here's an example on EDA playground to help you out: http://www.edaplayground.com/x/3RR

For more info on procedural assign statements have a look at the SystemVerilog 2012 standard, section 10.6 Procedural continuous assignments

Note: the standard also mentions that this construct is considered for deprecation.

Upvotes: 1

Tudor Timi
Tudor Timi

Reputation: 7573

If you don't want to use procedural assigns, then you have to add a bit of infrastructure to your driver. You need a method that drives clk_in based on clk_ref and a gating field:

bit clk_on;

task drive_clock();
  forever @(vif.clk_ref iff clk_on)  // sensitive to any change of the clock
    vif.clk_in <= vif.clk_ref;
endtask

You have to fork this method from the run_phase(...) of your driver:

task run_phase(uvm_phase phase);
  fork
    drive_clock();
  join_none

  // do any other stuff here
endtask

I'm guessing that you want to control the clock from inside your send_to_dut(...) task:

task send_to_dut(some_sequence_item req);
  clk_on = req.clk_on;
  // any other driving code here
endtask

Here's a stripped down example on EDA playground that demonstrates this: http://www.edaplayground.com/x/2XV

Upvotes: 1

Related Questions