Clock Generator

Hi.

I try to create a clock generator with UVM. I want to the driver enable or disable the clock.

I read that is better put the gen_clk in to the interface.

My first problem is when I want set the ena_clk in the interface through to driver.

what’s wrong with this code?

//INTERFACE ///////////////////////////////////
interface clk_interface();
import clk_rst_agent_pkg::*;

//control
logic start_clk;
//output interrfaced
logic clk_o;
logic rst_o;

always
begin
while(start_clk == 1’b1)
begin
#12.5ns;
clk_o = ~clk_o;
end
end
endinterface: clk_rst_interface

//DRIVER ////////////////////////////////

task run_phase(uvm_phase phase);
vif.start_clk = 1’b0; //Disable clk
forever begin
clk_rst_seq_item seq_item;
seq_item_port.get_next_item(seq_item);
phase.raise_objection(this);
case (seq_item.cmd)
START : begin
vif.start_clk = 1’b1; //Enable clk
end
STOP : begin
vif.start_clk = 1’b0; //Disable clk
end
endcase
`uvm_info(“CLK Driver”, seq_item.convert2string(), UVM_HIGH)
seq_item_port.item_done();
phase.drop_objection(this);
end
endtask
////////////////////////////////////////////////////////////////////

Thanks!

Let’s take these one at a time:

//INTERFACE ///////////////////////////////////
 interface clk_interface();
 import clk_rst_agent_pkg::*;

 //control
 logic start_clk;
 //output interrfaced
 logic clk_o;
 logic rst_o;

 always 
begin
 while(start_clk == 1'b1)
 begin
 #12.5ns;
 clk_o = ~clk_o; end
 end 
endinterface: clk_rst_interface

The first problem is that you’re not initializing the 4-state value clk_o, so

clk_o = ~clk_o;

will always yield an ‘x’ value.

Your second problem is in your driver:

task run_phase(uvm_phase phase);
 vif.start_clk = 1'b0; //Disable clk
 forever begin
   clk_rst_seq_item seq_item;
   seq_item_port.get_next_item(seq_item);
   phase.raise_objection(this);
   case (seq_item.cmd)
     START : begin
       vif.start_clk = 1'b1; //Enable clk
     end
     STOP : begin
       vif.start_clk = 1'b0; //Disable clk 
     end
   endcase 
  `uvm_info("CLK Driver", seq_item.convert2string(), UVM_HIGH)
   seq_item_port.item_done(); 
   phase.drop_objection(this);
   end
 endtask

First problem: get_next_item() is blocking, so if there’s any delay in returning, the run_phase() will terminate before you can raise the objection. You must call raise_objection() before any blocking call.
Second problem: You are raising and dropping the objection once for each get_next_item/item_done call, which means that you’ll exit run_phase immediately after processing the first transaction (unless you raise another objection somewhere else). We don’t recommend raising and dropping objections inside the driver anyway, so you can just remove these. Instead, you should raise the run_phase objection from your test before starting the sequence that will issue the instructions. That way you don’t have to worry about the forever loop keeping run_phase going forever.
You should implement phase_ready_to_end in your driver if you want to make sure that you turn off the clock before exiting the phase. See the Cookbook for more detail on phase_ready_to_end.

Ok!
Thank you very much!