Wanted to understand how do we handle asynchronous reset in driver code in uvm?
In my tb I have writted code for it in the following manner:
task get_and_drive();
@(posedge vif.clk or negedge vif.reset_n)
begin
if(!(vif.reset_n)bnegin
vif.a <= 0;
vif.b <= 0;
vif.in <=0;
end
//Rest of driver code
endtask
When I apply reset some where in the middle of the transaction the code is not entering the if condition and the signals are not becoming zero.
Before this task I have written a reset_phase task. This works when the initial reset is called.
Please help me on this topic. If any code change needs to be done to handle asynchronous reset.
task run_phase( uvm_phase phase);
forever begin
fork
detect_rst();
get_and_drive(); // Has forever loop within the task
join_any
// will come here only when reset is asserted
disable fork;
wait( reset_n == 1 ); // Wait till reset is de-asserted
end
endtask
task detect_rst();
@(negedge vif.reset_n);
vif.a <= 0;
vif.b <= 0;
vif.in <=0;
endtask
task get_and_drive();
//forever @(posedge vif.clk) begin // ORG
forever begin
seq_item_port.get_next_item(req);
@(posedge vif.clk);
// Drive signals via NBA
vif.a <= req.a;
vif.b <= req.b;
vif.in <=req.in;
seq_item_port.item_done();
end
endtask
You are showing us a task called get_and_drive yet there is no mention of how you are getting transactions from the sequencer. Most likely your code is blocked somewhere else when the reset occurs.
If the driver is a single cycle non-pipelined, you can do something like:
forever @(posedge vif.clk or negedge vif.reset_n)
begin
if(!(vif.reset_n) begin
vif.a <= 0;
vif.b <= 0;
vif.in <=0;
end else if (seq_item_port.try_next_item(req)) begin
//Rest of driver code
seq_item_port.item_done();
end
Driving logic that spans multiple clock cycles becomes increasingly complex. To manage those cases, you must terminate any ongoing sequences and exit and restart any loops within the driver. You’ll need to provide more details on how the driver is supposed to behave.
Thanks for the response. One doubt I have, why do we againg need forever inside the get_and_drive task, when that task itself is being called inside a forever loop?
Thanks for the reply.
So in the run_task I have the following code:
forever begin
seq_item_port.get_next_item(req); uvm_info(get_name(),"Seq items is get",UVM_LOW); get_and_drive(); uvm_info(get_name(),“ADC Drive is done”,UVM_LOW);
seq_item_port.item_done();
end
Hi Dave,
While reviewing the above code, for a scenario where reset_n is asserted at the same clock that driver is driving the signals ( i.e get_next_item has unblocked and driver is driving the signals on the nearest posedge of clk )
As driver would be driving the signals via Non-blocking assignment in both of the tasks is there a possibility of race condition ?
One way to overcome this would be to call uvm_wait_for_nba_region()
task get_and_drive();
fork
@(negedge vif.reset_n) begin
if(!(vif.reset_n) begin
vif.a <= 0;
vif.b <= 0;
vif.in <=0;
end
else
@(posedge vif.clk iff vif.reset_n) begin
//Rest of driver code
end
join any
disable fork;
endtask
task get_and_drive();
fork
@(negedge vif.reset_n) begin
if(!(vif.reset_n) begin
vif.a <= 0;
vif.b <= 0;
vif.in <=0;
end
else
@(posedge vif.clk) begin
seq_item_port.get_next_item(req);
vif.a <= req.a;
vif.b <= req.b;
vif.in <=req.in;
seq_item_port.item_done();
end
join any
disable fork;
endtask
If negedge vif.reset_n and posedge vif.clk were true at same instant, assuming that get_next_item unblocks immediately, is the order of non-blocking assignments deterministic ?
In this case when the disable fork executes,is it possible that signals ‘a’ , ‘b’ , ‘in’ have the values from request item and not value of 0 ?
I added @(posedge vif.clk iff vif.reset_n) to make sure the clock never triggers while reset is active. If negedge reset_n occurs afterwards, the ordering of the non-blocking assignments are preserved.
The original post had get_next_item() outside the task call. If you put it inside, there is the potential to miss the reset edge.