Reputation: 311
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
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
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