Hi all,
I had an issue as below, whenever my driver is asking get_next_item(), my current forever loop in the drive task should get killed and should start with the new values that are sent from the transaction item. How to do this, I need help to resolve this issue. I am putting the current code that i have.
task run_phase(uvm_phase phase)
forever begin
seq_item_port.get_next_item(hss_clock_item_h);
drive(hss_clock_item_h);
seq_item_port.item_done();
end
endtask : run_phase
task drive();
forever begin
#(clock_low) inf.clk =1;
#(clock_high) inf.clk=0;
end
endtask :drive
**Note: Where clock_low and clock_high are calculated depending upon the values that comes form transaction item for every get_next_item
Here, when driver gets first item, it will call drive task, inside than also forever is there, which will caused the issue and i will never allow to call item_done() followed by next get_next_item. so, this is not recommended.
i think following code will serve your requirement.
I am generating a clock which should change on the fly whenever new frequency is assigned to it, So if you remove the forever in the drive task, the task will get executed only once which in turn produces only one clock pulse but i need to generate a free running clock until next frequency is given which is why i gave the forever loop in the drive task.
It is still unclear what the algorithm is to change the clock frequency.
And I’m not sure if generating the clock signal in a driver is a good solution.
Why do you not generate the different clocks in your toplevel module?
If clock generation is the application, then i don’t think that, you need clock sequence for changing the frequency(or ppm, duty cycle etc). i would like to suggest the following code for the same.
// Get the configuration handle for clock driver,
// Add variables/hook up for storing the clock frequency/time/ppm/duty_cycle etc.
task run_phase(uvm_phase phase);
forever
begin
drive();
end
endtask : run_phase
task drive();
//Check the necessary configuration paramter for clock generation and drive according to it.
#(cfg.clock_low) inf.clk =1;
#(cfg.clock_high) inf.clk=0;
endtask :drive
yeah i got it. but i am removing get_next_item from driver. and driving in run_phase forever. i dont need sequence or seq_item for the same. i will get the parameters from configuration class. i think as per my understanding, there is no need/will not affect sequencer driver communication of pulling the sequence, if driver does not have get_next_item.
I don’t believe this will work.
But what you can do is executing a configuration sequence first, configuring the clock ferquency and maybe other details and then continue with a functional sequence providing the data to verify your design.
I do not see it why it will not work. When all objections are dropped, test is going to an end. I agree that standard way is to configure clock and run it but here is different situation.Clock is dependent of current transaction. Could you elaborate a little bit more why two parallel forever begin-end blocks will not work?
task run_phase(uvm_phase phase)
forever begin
seq_item_port.get_next_item(hss_clock_item_h);
// insert code here to calculate clock_high/low
// kills driving process. Does nothing if first time through the loop.
disable fork;
fork
drive(hss_clock_item_h);
join_none
seq_item_port.item_done();
end
endtask : run_phase
task drive();
forever begin
#(clock_low) inf.clk =1;
#(clock_high) inf.clk=0;
end
endtask :drive
fork
begin : process_1
forever begin
seq_item_port.get_next_item(hss_clock_item_h);
// insert code here to calculate clock_high/low
seq_item_port.item_done();
end
end : process_1
begin : process_2
forever begin
#(clock_low) inf.clk =1;
#(clock_high) inf.clk=0;
end
end : process_2
join_none
In reply to Fireblade_uvm:
Yes, the only difference is synchronization of the change. The original question asked for the change to happen immediately.
How about having multiple pre-defined clocks and driver task will just do muxing between that clocks. I mean no need to generate clock in driver class, just do muxing.
task run_phase(uvm_phase phase)
forever begin
seq_item_port.get_next_item(hss_clock_item_h);
drive(hss_clock_item_h);
seq_item_port.item_done();
end
endtask : run_phase
task drive();
begin
case (hss_clock_item_h.clk_freq)
100: inf.clk = inf.clk_100m;
200: inf.clk = inf.clk_100m;
endcase
end
endtask :drive