You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于UVM的相位累加器测试平台设计疑问及编译错误排查

相位累加器UVM测试平台问题解答

问题1:监控类设计合理性分析

你的设计是合理的,完全适配自由运行型DUT的特性:

  • 自由运行的相位累加器每个时钟沿都会更新输出(phase、cycle_end),因此每个时钟沿采集输出是正确的,能完整捕获DUT的连续输出行为。
  • load信号是配置激励的触发信号,仅在load有效时采集tuning_word和load状态,能精准记录DUT的配置变更点,这比盲目采集所有时钟的输入更高效。

需要注意的是,计分板需要处理激励与连续输出的关联逻辑:每次load触发后,要记录当前生效的tuning_word,后续所有输出都要基于这个tuning_word进行预期值计算,直到下一次load更新配置。这种关联是自由运行DUT验证的核心,也是和单次激励对应单次输出场景的主要区别。

问题2:编译错误原因分析

编译错误的核心原因和解决点如下:

  1. 时钟触发方式错误:
    你用@(vif.clk)会等待时钟信号的任意变化(上升沿+下降沿),而DUT是时钟沿触发更新输出,下降沿时输出尚未更新,且部分仿真器不允许在这种“电平变化触发”的代码块中直接实例化类对象。
    正确的做法是等待时钟上升沿:@(posedge vif.clk),这样只在DUT更新输出后采样,也能避免上下文导致的编译问题。

  2. 代码笔误:

    • out.phase_quadrant = cif.phase_quadrant;中的cif是笔误,应为vif;
    • if (vif.ld)中的ld是笔误,对应DUT的输入信号应为load;
    • stimulus.tunning_word拼写错误,应为stimulus.tuning_word;
    • 虚拟接口声明virtual reg_if vif与config_db中获取的acc_if类型不匹配,应改为virtual acc_if vif。

你提到把实例化放入if(vif.clk)条件块后错误消失,本质是这个条件过滤掉了下降沿的触发(仅在clk为高电平时执行),间接规避了错误的触发时机,但不如直接使用@(posedge vif.clk)规范。


附相关代码

DUT代码(phase_acc模块)

module phase_acc #(
    parameter PHASE_ACC_WIDTH = 16,
    parameter TUNNING_WORD_WIDTH = 8
) (
    input wire clk,
    input wire reset,
    input wire load,
    input wire [TUNNING_WORD_WIDTH-1 : 0] tuning_word,
    output reg [PHASE_ACC_WIDTH-1 : 0] phase,
    output wire cycle_end,
    output wire [1:0] phase_quadrant
);

  assign phase_quadrant = phase[PHASE_ACC_WIDTH-1:PHASE_ACC_WIDTH-2];
  assign cycle_end = (phase + tuning_word) > {PHASE_ACC_WIDTH{1'b1}};

  always @(clk) begin
    if (reset == 1) begin
      phase <= 0;
    end else begin
      phase <= phase + tuning_word;
    end
  end

endmodule

monitor类代码(修正后)

class monitor extends uvm_monitor;
  `uvm_component_utils(monitor)
  function new(string name = "monitor", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  uvm_analysis_port #(acc_stimulus) mon_stimulus_analysis_port;
  uvm_analysis_port #(acc_output) mon_output_analysis_port;
  virtual acc_if vif;
  semaphore sema4;

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if (!uvm_config_db#(virtual acc_if)::get(this, "", "acc_if", vif))
      `uvm_fatal("MON", "Could not get vif")
    sema4 = new(1);
    mon_stimulus_analysis_port = new("mon_stimulus_analysis_port", this);
    mon_output_analysis_port = new("mon_output_analysis_port", this);
  endfunction

  virtual task run_phase(uvm_phase phase);
    super.run_phase(phase);
    forever begin
      fork
        begin
          @(posedge vif.clk);

          // output
          acc_output out = new;
          out.phase = vif.phase;
          out.cycle_end = vif.cycle_end;
          out.phase_quadrant = vif.phase_quadrant;
          `uvm_info(get_type_name(), $sformatf("Monitor found output %s", out.convert2str()),
                    UVM_LOW)
          mon_output_analysis_port.write(out);

        end

        begin
          @(posedge vif.clk);
          // stimulus
          if (vif.load) begin
            acc_stimulus stimulus = new;
            stimulus.tuning_word = vif.tuning_word;
            stimulus.load = vif.load;
            `uvm_info(get_type_name(), $sformatf("Monitor found stimulus  %s",
                                                 stimulus.convert2str()), UVM_LOW)
            mon_stimulus_analysis_port.write(stimulus);
          end
        end
      join
    end
  endtask
endclass

内容的提问来源于stack exchange,提问作者peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:24:22