UVM driver: bắt tay với sequencer

Khoảng 20 phútMức 2/3Bản nháp: một số khẳng định chưa đối chiếu spec

Sau bài này bạn sẽ

  • Mô tả vòng get_next_item → drive → item_done
  • Chẩn đoán test treo do handshake sai

Vòng lặp driver

Testbench tối thiểu

UVM testbench tối thiểu: driver handshake, monitor, scoreboard, factory override

Khung UVM đầy đủ vai trò nhưng nhỏ nhất có thể để soi get_next_item/item_done và luồng analysis port.

tb_uvm.sv UVM
// UVM tối thiểu: item/sequence/driver/monitor/scoreboard/agent/env/test,// config_db truyền virtual interface, factory override, objection.`include "uvm_macros.svh"interface reg_if (input logic clk);  logic we; logic [7:0] wdata; logic [7:0] q;endinterfacemodule dut (reg_if bus);  // thanh ghi 8-bit đơn giản  always_ff @(posedge bus.clk) if (bus.we) bus.q <= bus.wdata;endmodulepackage tb_pkg;  import uvm_pkg::*;  class item extends uvm_sequence_item;    rand bit [7:0] data;    `uvm_object_utils(item)    function new(string name = "item"); super.new(name); endfunction  endclass  class item_odd extends item;              // dùng để thử factory override    constraint c_odd { data[0] == 1; }    `uvm_object_utils(item_odd)    function new(string name = "item_odd"); super.new(name); endfunction  endclass  class seq extends uvm_sequence #(item);    `uvm_object_utils(seq)    function new(string name = "seq"); super.new(name); endfunction    task body();      repeat (8) begin        item it = item::type_id::create("it");        start_item(it); if (!it.randomize()) `uvm_error("SEQ", "randomize failed") finish_item(it);      end    endtask  endclass  class drv extends uvm_driver #(item);    `uvm_component_utils(drv)    virtual reg_if vif;    function new(string n, uvm_component p); super.new(n, p); endfunction    function void build_phase(uvm_phase phase);      if (!uvm_config_db#(virtual reg_if)::get(this, "", "vif", vif)) `uvm_fatal("DRV", "no vif")    endfunction    task run_phase(uvm_phase phase);      vif.we <= 0;      forever begin        seq_item_port.get_next_item(req);        @(negedge vif.clk); vif.we <= 1; vif.wdata <= req.data;        @(negedge vif.clk); vif.we <= 0;        seq_item_port.item_done();      end    endtask  endclass  class mon extends uvm_monitor;    `uvm_component_utils(mon)    virtual reg_if vif; uvm_analysis_port #(item) ap;    function new(string n, uvm_component p); super.new(n, p); ap = new("ap", this); endfunction    function void build_phase(uvm_phase phase);      void'(uvm_config_db#(virtual reg_if)::get(this, "", "vif", vif));    endfunction    task run_phase(uvm_phase phase);      forever begin        @(posedge vif.clk);        if (vif.we) begin item t = item::type_id::create("t"); t.data = vif.wdata; ap.write(t); end      end    endtask  endclass  class sb extends uvm_scoreboard;    `uvm_component_utils(sb)    uvm_analysis_imp #(item, sb) imp; int n, odd;    function new(string n_, uvm_component p); super.new(n_, p); imp = new("imp", this); endfunction    function void write(item t); n++; odd += t.data[0]; endfunction    function void report_phase(uvm_phase phase);      `uvm_info("SB", $sformatf("C12 RESULT observed=%0d odd=%0d (override → expect odd==observed==8)", n, odd), UVM_NONE)    endfunction  endclass  class env extends uvm_env;    `uvm_component_utils(env)    uvm_sequencer #(item) sqr; drv d; mon m; sb s;    function new(string n, uvm_component p); super.new(n, p); endfunction    function void build_phase(uvm_phase phase);      sqr = uvm_sequencer#(item)::type_id::create("sqr", this);      d = drv::type_id::create("d", this); m = mon::type_id::create("m", this); s = sb::type_id::create("s", this);    endfunction    function void connect_phase(uvm_phase phase);      d.seq_item_port.connect(sqr.seq_item_export); m.ap.connect(s.imp);    endfunction  endclass  class test extends uvm_test;    `uvm_component_utils(test)    env e;    function new(string n, uvm_component p); super.new(n, p); endfunction    function void build_phase(uvm_phase phase);      item::type_id::set_type_override(item_odd::get_type());      e = env::type_id::create("e", this);    endfunction    task run_phase(uvm_phase phase);      seq s = seq::type_id::create("s");      phase.raise_objection(this); s.start(e.sqr); #20; phase.drop_objection(this);    endtask  endclassendpackagemodule tb;  import uvm_pkg::*; import tb_pkg::*;  logic clk = 0; always #5 clk = ~clk;  reg_if bus(clk); dut u(bus);  initial begin uvm_config_db#(virtual reg_if)::set(null, "*", "vif", bus); run_test("test"); endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Elaborate cùng thư viện Accellera UVM (pyslang 12.1.0)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Verilator 5.050, 2-state)

Output phải khớp: C12 RESULT observed=8 odd=8^UVM_ERROR :\s+0$^UVM_FATAL :\s+0$

Mô phỏng bằng Verilator 5.050 + Accellera uvm-core 2020.3.1 với +define+UVM_NO_DPI: tắt kiểm tra tên component bằng regex và các hàm DPI (uvm_hdl backdoor, regex). 2 UVM_WARNING (NO_DPI_USED, NO_VISIT_CHECK) là dự kiến.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-06), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

Kiểm tra

Driver handshake

  1. Driver gọi get_next_item(req) nhưng quên item_done(). Điều gì xảy ra?

Nguồn và mức độ đối chiếu

  1. IEEE 1800.2-2017 UVM Language Reference Manual, sequencer/driver interface. Chưa đối chiếu với văn bản nguồn (mới xem thông tin xuất bản).
  2. IEEE 1800.2-2017 UVM Language Reference Manual, sequencer/driver interface (chưa xác định mục). Chưa đối chiếu với văn bản nguồn (mới xem thông tin xuất bản).
  3. ChipVerify — UVM tutorial, §8 Sequences and the Driver Handshake. Trích dẫn; nguồn mới xem mục lục. danh mục chủ đề
  4. IEEE 1800.2-2017 UVM Language Reference Manual, sequencer/driver handshake. Chưa đối chiếu với văn bản nguồn (mới xem thông tin xuất bản).