In reply to chr_sue:
Hi Chris,
My Sequence body looks like this:
// Sequence body
task some_seq::body();
// Start item
start_item(item_h);
// finish item
finish_item(item_h);
// wait reponse
get_response(item_h);
endtask
My Driver looks like this:
task drv::run_phase(uvm_phase phase);
@(m_vif.drv_cb iff (m_vif.rst_n === 0));
// Reset signals
reset_signals();
@(m_vif.drv_cb iff (m_vif.rst_n === 1));
// Start driving
get_and_drive();
endtask : run_phase
task drv::get_and_drive();
process main_thread;
process rst_mon_thread;
forever begin
//Don't drive during reset
while(m_vif.rst_n !== 1)
@(m_vif.drv_cb iff (m_vif.rst_n === 1));
//Get the next item from the sequencer
seq_item_port.get_next_item(req);
if(!$cast(rsp, req.clone())) begin
`uvm_fatal(get_type_name(), "run_phase::Cast rsp<-req failed!")
end
rsp.set_id_info(req);
//Drive current transaction
fork
//Drive the transaction
begin
main_thread=process::self();
drive_item(rsp);
if(rst_mon_thread) rst_mon_thread.kill();
end
// Monitor the reset signal
begin
rst_mon_thread=process::self();
@(negedge m_vif.rst_n) begin
if(main_thread) main_thread.kill();
//Do reset
reset_signals();
end
end
join_any
//Send item_done and a response to the sequencer
seq_item_port.item_done();
seq_item_port.put_response(rsp);
end // forever
endtask : get_and_drive
task drv::drive_item(ref item_t item_h);
//Drive the req
if(item_h.m_trans_type == FIRST_TYPE) begin
automatic int delay_cycles = $urandom_range(m_cfg_h.min_dly,m_cfg_h.max_dly);
repeat (delay_cycles)
@(m_vif.drv_cb);
if(some_condition) begin
m_vif.drv_cb.One_Valid <= 1;
m_vif.drv_cb.One_Hdr <= item_h.m_hdr;
end
else begin
automatic item_t auto_item_h = item_h;
check_one_credits_and_drive(auto_item_h); //time consuming task
end
@(m_vif.drv_cb);
m_vif.drv_cb.One_Valid <= 0;
end
else if(item_h.m_trans_type == SECOND_TYPE) begin
automatic int delay_cycles = $urandom_range(m_cfg_h.min_dly,m_cfg_h.max_dly);
repeat (delay_cycles)
if(some_condition) begin
m_vif.drv_cb.Second_Valid <= 1;
m_vif.drv_cb.Second_Hdr <= item_h.m_hdr;
m_vif.drv_cb.Second_Data <= item_h.m_data;
end
else begin
automatic item_t auto_item_h = item_h;
check_two_credits_and_drive(auto_item_h); //time consuming task
end
@(m_vif.drv_cb);
m_vif.drv_cb.Second_Valid <= 0;
end
endtask :drive_item