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
沒有留言:
張貼留言