we write a UVM SystemVerilog "req happened until grant received" to our demo case.
// spawn sub procs(threads)
task run_phase(uvm_phase);
fork
sent_req();
sent_grant();
collected_req();
collected_grant();
check_performance();
check_protocol();
join
endtask : run_phase
// sent req
task sent_req();
forever begin
// random wait ....
repeat($urandom_range(8,16)) @(posedge m_vif.CLK);
// sent req
`delay(conf.half_cycle);
m_vif.REQ <= `TRUE;
@(posedge m_vif.CLK);
// wait until grant received
while(!m_vif.GRANT) @(posedge m_vif.CLK);
// free req
`delay(conf.half_cycle);
m_vif.REQ <= `FALSE;
@(posedge m_vif.CLK);
end
endtask : sent_req
// snet grant
task sent grant();
forever begin
// sent unvalid grant
`delay(conf.half_cycle);
m_vif.GRANT <= `FALSE;
@(posedge m_vif.CLK);
// wait until req received
while(!m_vif.REQ) @(posedge m_vif.CLK);
// random wait ...
repeat($urandom_range(8,16)) @(posedge m_vif.CLK);
// sent valid grant to free req
`delay(conf.half_cycle);
m_vif.GRANT <= `TRUE;
@(posedge m_vif.CLK);
end
endtask : sent grant
task collected_req();
forever begin
// @ neg edge check
@(negedge m_vif.CLK iff m_vif.REQ);
// assert only one fifo deep when req/grant case
assert(m_trx_q.size() < 1);
// collect trx
TRX m_trx = new();
m_trx.REQ = m_vif.REQ;
m_trx.TIME = $time;
m_trx_q.push_back(m_trx);
end
endtask : collected_req
task collected_grant();
forever begin
// @ neg edge cehck
@(negedge m_vif.CLK iff m_vif.GRANT);
//assert the queue size must be 1, means the req has been stored in the queue
assert(m_trx.q.size() == 1);
// free queue
m_trx_q.pop_front();
end
endtask : collected_grant
task check_performance();
forever begin
// at each pos edge check
@(posedge m_vif.CLK);
//assert queue
if (m_trx_q.size() == 1) begin
if ($time - m_trx_q[0].TIME > conf.min_offset) begin
`uvm_error(get_full_name(), {$psprintf("out of time %d"), conf.min_offset}, UVM_LOW)
end else begin
`uvm_error(get_full_name(), {$psprintf("req/grant seuence is not valid")}, UVM_LOW)
end
end
end
endtask
沒有留言:
張貼留言