core-v-verif系列之lib<9>

UVM环境介绍
HEAD commitID: 1f968ef

1. core-v-verif/lib/cv_dv_utils/uvm/clock_gen/clock_config_c.svh


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//  Description : config object to configure the clock 
//                starting_signal_level, clock_frequency, duty_cycle
//                
// 
// ----------------------------------------------------------------------------

class clock_config_c extends uvm_object;


    //////////////////////////////////////////////////////
    //Configuration Parameters
    //To be driven by the driver 
    /////////////////////////////////////////////////////
    rand  bit m_starting_signal_level;
    rand  int m_clock_frequency = 10;   // safe default value in case no randomization is done
    rand  int m_duty_cycle = 50;        // safe default value in case no randomization is done

    constraint c_starting_signal_level { m_starting_signal_level dist { 1'b1 := 5,  1'b0 := 5};};
    constraint c_clock_frequency       { m_clock_frequency  > 0;                     };
    constraint c_duty_cycle            { m_duty_cycle == 50;                         };

     // ------------------------------------------------------------------------
     // Utilities for the variables
     // ------------------------------------------------------------------------
    `uvm_object_utils_begin( clock_config_c )
        `uvm_field_int( m_starting_signal_level,   UVM_DEFAULT )
        `uvm_field_int( m_clock_frequency,         UVM_DEFAULT )
        `uvm_field_int( m_duty_cycle,              UVM_DEFAULT )
    `uvm_object_utils_end

    function new( string name ="" );
        super.new( name );
    endfunction

endclass : clock_config_c

1. 简要介绍
class clock_config_c extends uvm_object;
    // ... 其他代码 ...
endclass : clock_config_c

代码介绍

  • 定义了一个名为 clock_config_c 的类,该类继承自 uvm_object,是 UVM(Universal Verification Methodology)中的对象类。
  • 这个类主要用于配置时钟的相关参数,如起始信号电平、时钟频率和占空比。
2. 接口介绍

此文件中类的主要接口为构造函数和通过 uvm_object_utils 宏实现的 UVM 自动化方法。

function new( string name ="" );
    super.new( name );
endfunction

代码分析

  • function new( string name ="" );:定义了类的构造函数,接受一个可选的字符串参数 name,默认值为空字符串。
  • super.new( name );:调用父类 uvm_object 的构造函数,将传入的 name 参数传递给父类进行初始化。
3. 参数介绍
rand  bit m_starting_signal_level;
rand  int m_clock_frequency = 10;   // safe default value in case no randomization is done
rand  int m_duty_cycle = 50;        // safe default value in case no randomization is done

代码分析

  • rand bit m_starting_signal_level;:声明一个随机的单比特变量 m_starting_signal_level,用于表示时钟的起始信号电平。
  • rand int m_clock_frequency = 10;:声明一个随机的整数变量 m_clock_frequency,表示时钟频率,默认值为 10,在未进行随机化时作为安全默认值。
  • rand int m_duty_cycle = 50;:声明一个随机的整数变量 m_duty_cycle,表示时钟的占空比,默认值为 50,在未进行随机化时作为安全默认值。
4. 模块实现介绍
4.1 约束块
constraint c_starting_signal_level { m_starting_signal_level dist { 1'b1 := 5,  1'b0 := 5};};
constraint c_clock_frequency       { m_clock_frequency  > 0;                     };
constraint c_duty_cycle            { m_duty_cycle == 50;                         };

代码分析

  • constraint c_starting_signal_level { m_starting_signal_level dist { 1'b1 := 5, 1'b0 := 5};};:定义一个约束块 c_starting_signal_levelm_starting_signal_level1'b11'b0 的概率各为 50%。
  • constraint c_clock_frequency { m_clock_frequency > 0; };:定义一个约束块 c_clock_frequency,要求 m_clock_frequency 必须大于 0。
  • constraint c_duty_cycle { m_duty_cycle == 50; };:定义一个约束块 c_duty_cycle,要求 m_duty_cycle 始终为 50。
4.2 UVM 自动化宏
`uvm_object_utils_begin( clock_config_c )
    `uvm_field_int( m_starting_signal_level,   UVM_DEFAULT )
    `uvm_field_int( m_clock_frequency,         UVM_DEFAULT )
    `uvm_field_int( m_duty_cycle,              UVM_DEFAULT )
`uvm_object_utils_end

代码分析

  • uvm_object_utils_begin( clock_config_c )uvm_object_utils_end:这对宏用于将 clock_config_c 类注册到 UVM 工厂中,使其支持 UVM 的自动化功能。
  • uvm_field_int( m_starting_signal_level, UVM_DEFAULT ):将 m_starting_signal_level 字段注册到 UVM 中,使用默认的处理方式。
  • uvm_field_int( m_clock_frequency, UVM_DEFAULT ):将 m_clock_frequency 字段注册到 UVM 中,使用默认的处理方式。
  • uvm_field_int( m_duty_cycle, UVM_DEFAULT ):将 m_duty_cycle 字段注册到 UVM 中,使用默认的处理方式。
5. 总结

clock_config_c.svh 文件定义了一个 UVM 对象类 clock_config_c,用于配置时钟的相关参数。通过随机变量和约束块,可以对时钟的起始信号电平、频率和占空比进行随机化配置。同时,使用 UVM 的自动化宏将类注册到 UVM 工厂,方便在 UVM 验证环境中使用。不过,c_duty_cycle 约束将占空比固定为 50%,可能会限制一些测试场景的灵活性,可以考虑将其修改为一个范围约束以支持更多的测试场景。

2. core-v-verif/lib/cv_dv_utils/uvm/clock_gen/clock_driver_c.svh


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//  Description : driver for clock signal.
//                nominal_clock_period, duty_cycle and starting_signal_level are
//                configurable items, needs to be configured at
//                pre_configure_phase in the test
// 
// ----------------------------------------------------------------------------

class dummy_txn extends uvm_sequence_item;

endclass : dummy_txn

class clock_driver_c extends uvm_driver #( dummy_txn, dummy_txn ) ;

    `uvm_component_utils( clock_driver_c )

    //---------------------------
    // Virtual Interface
    //---------------------------
    virtual xrtl_clock_vif m_v_clock_vif;

    //---------------------------------------------
    // Clock config handle to get 
    // frequency, starting signal level, duty cycle 
    //--------------------------------------------
    clock_config_c    m_clk_cfg; 

    // Give global clock count 
    int global_cycle_count;
    //---------------------------------------------
    // The period ...1/F 
    //--------------------------------------------
    real m_nominal_clock_period;

    function new( string name, uvm_component parent);
        super.new(name,parent);
    endfunction : new

    //---------------------------------------------
    // Build Phase  
    //--------------------------------------------
    function void build_phase( uvm_phase phase );
        super.build_phase( phase);

        if(!uvm_config_db #( virtual xrtl_clock_vif )::get(this, "", get_name(), m_v_clock_vif )) begin
            `uvm_fatal("CLOCK_DRIVER_C", $sformatf("Unable to get clock_if for %s from configuration database", get_name() ) );
        end

    endfunction : build_phase


    //---------------------------------------------
    // Start of simulation phase 
    //--------------------------------------------
    function void start_of_simulation_phase( uvm_phase phase );

    	super.start_of_simulation_phase(phase);
        m_nominal_clock_period               = 1.0/(m_clk_cfg.m_clock_frequency);
        m_v_clock_vif.starting_signal_level = m_clk_cfg.m_starting_signal_level;
        m_v_clock_vif.clk_high	           = (m_nominal_clock_period)*(m_clk_cfg.m_duty_cycle/100.0)*1000000; // ps
        m_v_clock_vif.clk_low		       = (m_nominal_clock_period)*(1.0- (m_clk_cfg.m_duty_cycle/100.0))*1000000; //ps

        // Make sure we don't give a period of zero -> this locks up the simulator!
        if ( ( m_v_clock_vif.clk_high == 0 ) || ( m_v_clock_vif.clk_low == 0 ) ) begin
           `uvm_fatal( "CLOCK_DRIVER_C", $sformatf("Clock periods are zero : %0d %0d",
            m_v_clock_vif.clk_high, m_v_clock_vif.clk_low == 0 )  );
        end // if

        `uvm_info( "CLOCK_DRIVER_C", $sformatf("START clock period = %0f(f) ps, clock duty = %0d(d), low_clock = %0f(f) ps, high_clock = %0f(f) ps", m_nominal_clock_period*1000000, m_clk_cfg.m_duty_cycle, m_v_clock_vif.clk_low*1000000, m_v_clock_vif.clk_high*1000000), UVM_NONE );
    endfunction : start_of_simulation_phase


    virtual task pre_reset_phase( uvm_phase phase );
        fork begin
            start_clock();
        end join
    endtask : pre_reset_phase
    //---------------------------------------------
    // Post shutdown phase  
    //--------------------------------------------
    virtual task post_shutdown_phase( uvm_phase phase );
        phase.raise_objection( this, "Started Post Shutdown");
        `uvm_info( "CLOCK_DRIVER_C", "STARTING POST SHUTDOWN", UVM_NONE );
        #1; // Allow time for any assertions to trigger
        phase.drop_objection( this, "Post Shutdown Completed");
    endtask : post_shutdown_phase

    //---------------------------------------------
    // Extract phase  
    //--------------------------------------------
//    virtual function void extract_phase( uvm_phase phase );
//        `uvm_info( "CLOCK_DRIVER_C", "STOPPING THE CLOCK", UVM_NONE );
//        fork begin
//            stop_clock();
//        end join
//    endfunction : extract_phase

   //================================================================================
   // Global Clock Counter 
   //================================================================================
   task global_cycle_counter();
      forever begin
        m_v_clock_vif.wait_n_clocks(1);
        global_cycle_count++;
      end //forever 
   endtask : global_cycle_counter

   //================================================================================
   // Get Global Clock Counter 
   //================================================================================
   function int get_global_cycle_counter();
     get_global_cycle_counter = global_cycle_count;
   endfunction : get_global_cycle_counter

   //---------------------------------------------
   // Task to start the clock from the uvm class  
   //--------------------------------------------
   virtual task start_clock();
        m_v_clock_vif.start_clock();
   endtask: start_clock

   //---------------------------------------------
   // Task to stop the clock from the uvm class
   //--------------------------------------------
   virtual task stop_clock();
        m_v_clock_vif.stop_clock();
   endtask: stop_clock

endclass : clock_driver_c


1. 简要介绍
class clock_driver_c extends uvm_driver #( dummy_txn, dummy_txn ) ;
    `uvm_component_utils( clock_driver_c )
    // ... 其他成员和方法 ...
endclass : clock_driver_c

代码介绍
此代码定义了一个名为 clock_driver_c 的类,它继承自 uvm_driver,并使用 uvm_component_utils 宏将该类注册到 UVM 工厂中。该类主要用于驱动时钟信号,支持对时钟周期、占空比和起始信号电平的配置。

2. 接口介绍
2.1 构造函数
function new( string name, uvm_component parent);
    super.new(name,parent);
endfunction : new

代码分析

  • function new( string name, uvm_component parent);:定义构造函数,接收两个参数,name 是组件的名称,parent 是该组件的父组件。
  • super.new(name,parent);:调用父类 uvm_driver 的构造函数,完成父类的初始化。
2.2 build_phase 函数
function void build_phase( uvm_phase phase );
    super.build_phase( phase);

    if(!uvm_config_db #( virtual xrtl_clock_vif )::get(this, "", get_name(), m_v_clock_vif )) begin
        `uvm_fatal("CLOCK_DRIVER_C", $sformatf("Unable to get clock_if for %s from configuration database", get_name() ) );
    end
endfunction : build_phase

代码分析

  • super.build_phase( phase);:调用父类的 build_phase 方法,确保父类在构建阶段的操作正常执行。
  • uvm_config_db #( virtual xrtl_clock_vif )::get(this, "", get_name(), m_v_clock_vif ):尝试从 UVM 配置数据库中获取虚拟接口 xrtl_clock_vif 的句柄。如果获取失败,使用 uvm_fatal 宏输出致命错误信息。
2.3 start_of_simulation_phase 函数
function void start_of_simulation_phase( uvm_phase phase );
    super.start_of_simulation_phase(phase);
    m_nominal_clock_period               = 1.0/(m_clk_cfg.m_clock_frequency);
    m_v_clock_vif.starting_signal_level = m_clk_cfg.m_starting_signal_level;
    m_v_clock_vif.clk_high	           = (m_nominal_clock_period)*(m_clk_cfg.m_duty_cycle/100.0)*1000000; // ps
    m_v_clock_vif.clk_low		       = (m_nominal_clock_period)*(1.0- (m_clk_cfg.m_duty_cycle/100.0))*1000000; //ps

    if ( ( m_v_clock_vif.clk_high == 0 ) || ( m_v_clock_vif.clk_low == 0 ) ) begin
       `uvm_fatal( "CLOCK_DRIVER_C", $sformatf("Clock periods are zero : %0d %0d",
        m_v_clock_vif.clk_high, m_v_clock_vif.clk_low )  );
    end

    `uvm_info( "CLOCK_DRIVER_C", $sformatf("START clock period = %0f(f) ps, clock duty = %0d(d), low_clock = %0f(f) ps, high_clock = %0f(f) ps", m_nominal_clock_period*1000000, m_clk_cfg.m_duty_cycle, m_v_clock_vif.clk_low*1000000, m_v_clock_vif.clk_high*1000000), UVM_NONE );
endfunction : start_of_simulation_phase

代码分析

  • super.start_of_simulation_phase(phase);:调用父类的 start_of_simulation_phase 方法。
  • m_nominal_clock_period = 1.0/(m_clk_cfg.m_clock_frequency);:根据时钟频率计算时钟周期。
  • 后续代码将时钟配置信息赋值给虚拟接口的相应成员。
  • if 语句检查时钟高电平和低电平时间是否为 0,如果为 0 则输出致命错误。
  • uvm_info 宏输出时钟的相关配置信息。
3. 参数介绍
virtual xrtl_clock_vif m_v_clock_vif;
clock_config_c    m_clk_cfg; 
int global_cycle_count;
real m_nominal_clock_period;

代码分析

  • virtual xrtl_clock_vif m_v_clock_vif;:声明一个虚拟接口句柄,用于与硬件进行交互。
  • clock_config_c m_clk_cfg;:声明一个 clock_config_c 类的对象,用于获取时钟的配置信息。
  • int global_cycle_count;:用于记录全局时钟周期数。
  • real m_nominal_clock_period;:存储时钟的标称周期。
4. 模块实现介绍
4.1 时钟控制任务
virtual task pre_reset_phase( uvm_phase phase );
    fork begin
        start_clock();
    end join
endtask : pre_reset_phase

virtual task post_shutdown_phase( uvm_phase phase );
    phase.raise_objection( this, "Started Post Shutdown");
    `uvm_info( "CLOCK_DRIVER_C", "STARTING POST SHUTDOWN", UVM_NONE );
    #1; 
    phase.drop_objection( this, "Post Shutdown Completed");
endtask : post_shutdown_phase

virtual task start_clock();
    m_v_clock_vif.start_clock();
endtask: start_clock

virtual task stop_clock();
    m_v_clock_vif.stop_clock();
endtask: stop_clock

代码分析

  • pre_reset_phase 任务在复位前阶段启动时钟。
  • post_shutdown_phase 任务在关闭后阶段进行一些清理操作,通过 raise_objectiondrop_objection 控制 UVM 仿真的生命周期。
  • start_clock 任务调用虚拟接口的 start_clock 方法启动时钟。
  • stop_clock 任务调用虚拟接口的 stop_clock 方法停止时钟。
4.2 全局时钟计数器
task global_cycle_counter();
    forever begin
        m_v_clock_vif.wait_n_clocks(1);
        global_cycle_count++;
    end 
endtask : global_cycle_counter

function int get_global_cycle_counter();
    get_global_cycle_counter = global_cycle_count;
endfunction : get_global_cycle_counter

代码分析

  • global_cycle_counter 任务是一个无限循环,每次等待一个时钟周期后,全局时钟计数器加 1。
  • get_global_cycle_counter 函数用于获取当前的全局时钟周期数。
5. 总结

clock_driver_c.svh 定义了一个 UVM 驱动类,用于驱动时钟信号。它通过 clock_config_c 类获取时钟配置信息,并将这些信息传递给虚拟接口来控制时钟的生成。同时,该类还提供了时钟启动、停止和全局时钟计数等功能,在 UVM 验证环境中起到了重要的时钟驱动作用。不过,代码中 m_clk_cfg 未在 build_phase 中获取,可能会导致空指针异常,需要补充相应的获取逻辑。

3. core-v-verif/lib/cv_dv_utils/uvm/clock_gen/clock_driver_pkg.sv


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//  Description : Package for generic clock generator
//                
// 
// ----------------------------------------------------------------------------

package clock_driver_pkg;

    timeunit 1ns;

    import uvm_pkg::*;

    class dummy_sequence_item_c extends uvm_sequence_item;
    endclass : dummy_sequence_item_c

    `include "uvm_macros.svh";
    `include "clock_config_c.svh";
    `include "clock_driver_c.svh";

endpackage : clock_driver_pkg

clock_driver_pkg.sv

1. 简要介绍
package clock_driver_pkg;
    // 导入必要的包
    import uvm_pkg::*;
    `include "uvm_macros.svh"

    // 包含相关类定义文件
    `include "clock_config_c.svh"
    `include "clock_driver_c.svh"

endpackage : clock_driver_pkg

代码介绍
此代码定义了一个名为 clock_driver_pkg 的包。包是 SystemVerilog 中用于组织代码的一种机制,可将相关的类型、常量、函数、类等封装在一起。该包导入了 UVM 相关的包和宏文件,同时包含了 clock_config_c.svhclock_driver_c.svh 这两个文件,意味着将这两个文件中的定义纳入到该包的作用域中,方便统一管理和使用与时钟驱动相关的类和功能。

2. 接口介绍

由于 clock_driver_pkg 主要是一个包定义,本身没有显式的接口函数或任务,其接口主要体现在对外提供包内包含的类和类型。但从代码结构上,可认为 include 语句和 import 语句间接构成了与外部的交互方式。

import uvm_pkg::*;
`include "uvm_macros.svh"
`include "clock_config_c.svh"
`include "clock_driver_c.svh"

代码分析

  • import uvm_pkg::*;:导入 UVM 包中的所有内容,这样在 clock_driver_pkg 内就可以直接使用 UVM 提供的类、宏和函数等。
  • include "uvm_macros.svh":包含 UVM 宏文件,这些宏用于简化 UVM 组件和对象的定义和注册等操作。
  • include "clock_config_c.svh":包含 clock_config_c.svh 文件,将该文件中定义的 clock_config_c 类引入到当前包中。
  • include "clock_driver_c.svh":包含 clock_driver_c.svh 文件,将该文件中定义的 clock_driver_c 类引入到当前包中。
3. 参数介绍

在提供的代码片段中,clock_driver_pkg 没有显式定义参数。参数通常用于配置模块或类的行为,这里包主要是对代码进行组织,所以没有相关参数。

4. 模块实现介绍
package clock_driver_pkg;
    import uvm_pkg::*;
    `include "uvm_macros.svh"
    `include "clock_config_c.svh"
    `include "clock_driver_c.svh"
endpackage : clock_driver_pkg

代码分析

  • package clock_driver_pkg;:开始定义一个名为 clock_driver_pkg 的包。
  • 中间的 importinclude 语句前面已经分析过,主要是引入外部的包、宏和类定义。
  • endpackage : clock_driver_pkg:结束 clock_driver_pkg 包的定义。整个包的实现逻辑就是将与时钟驱动相关的依赖项进行整合,方便在其他模块或测试平台中使用。
5. 总结

clock_driver_pkg.sv 定义了一个名为 clock_driver_pkg 的包,其主要作用是将 UVM 相关的包、宏以及 clock_config_c.svhclock_driver_c.svh 中的类定义进行整合。通过这种方式,在其他模块或测试平台中只需要导入该包,就可以方便地使用时钟驱动相关的类和功能,提高了代码的可维护性和复用性。不过,该包依赖于外部文件,在使用时需要确保这些文件的路径和内容正确,否则可能会导致编译错误。

4. core-v-verif/lib/cv_dv_utils/uvm/clock_gen/xrtl_clock_vif.sv


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//  Description : XRTL portion of clock agent.
//
//
// ----------------------------------------------------------------------------

interface xrtl_clock_vif ( output bit clock);

timeunit 1ns;
timeprecision 1ps;

//pragma attribute interface_tif partition_interface_xif

   // --------------------------------
   // Clock generation parameters 
   // Extracted from the clock config
   // -------------------------------
   bit enable = 1'b0;
   bit starting_signal_level = 1'b0;
   int clk_high = 10;  // for safety put a non-zero value
   int clk_low = 10;

   always begin
      wait(enable);
      if ( ( clk_high == 0 ) || ( clk_low == 0 ) )  begin
          $display("[FATAL] %m Clock Period is zero : %0d %0d",
                   clk_high, clk_low );
          $finish;
      end // if
      while(enable) begin
         clock = starting_signal_level;
         #(clk_high*1ps);
         clock = ~starting_signal_level;
         #(clk_low*1ps);
      end
   end

   function void start_clock();// pragma tbx xtf
      enable = 1'b1;
   endfunction: start_clock

   function void stop_clock(); // pragma tbx xtf
      enable = 1'b0;
   endfunction: stop_clock


    // ------------------------------------------------------------------------
    // Delay Task
    // ------------------------------------------------------------------------
    task automatic wait_n_clocks( int N );          // pragma tbx xtf
    begin
        @( posedge clock );
        repeat (N-1) @( posedge clock );
    end
    endtask : wait_n_clocks

endinterface : xrtl_clock_vif

1. 简要介绍
interface xrtl_clock_vif ( output bit clock);
    // 接口内的代码...
endinterface : xrtl_clock_vif

代码介绍
此代码定义了一个名为 xrtl_clock_vif 的 SystemVerilog 接口,该接口主要用于生成时钟信号。接口接收一个输出端口 clock,用于输出时钟信号。接口内部实现了时钟生成的逻辑,并且提供了控制时钟启动、停止以及等待时钟周期的方法。

2. 接口介绍
2.1 端口
interface xrtl_clock_vif ( output bit clock);

代码分析

  • output bit clock:定义了一个单比特的输出端口 clock,用于输出生成的时钟信号。
2.2 函数
function void start_clock();// pragma tbx xtf
    enable = 1'b1;
endfunction: start_clock

function void stop_clock(); // pragma tbx xtf
    enable = 1'b0;
endfunction: stop_clock

代码分析

  • start_clock():该函数用于启动时钟生成。将 enable 信号置为 1'b1,触发时钟生成的 always 块开始工作。
  • stop_clock():该函数用于停止时钟生成。将 enable 信号置为 1'b0,使时钟生成的 always 块停止工作。
2.3 任务
task automatic wait_n_clocks( int N );          // pragma tbx xtf
begin
    @( posedge clock );
    repeat (N-1) @( posedge clock );
end
endtask : wait_n_clocks

代码分析

  • wait_n_clocks( int N ):这是一个自动任务,用于等待 N 个时钟周期。首先等待第一个时钟上升沿,然后通过 repeat 语句再等待 N - 1 个时钟上升沿。
3. 参数介绍
bit enable = 1'b0;
bit starting_signal_level = 1'b0;
int clk_high = 10;  // for safety put a non-zero value
int clk_low = 10;

代码分析

  • enable:一个单比特变量,用于控制时钟生成的开关。初始值为 1'b0,表示时钟默认处于停止状态。
  • starting_signal_level:一个单比特变量,用于指定时钟信号的起始电平,初始值为 1'b0
  • clk_high:一个整数变量,代表时钟信号高电平持续的时间(单位为皮秒),初始值为 10,设置非零值以避免时钟周期为零的错误。
  • clk_low:一个整数变量,代表时钟信号低电平持续的时间(单位为皮秒),初始值为 10。
4. 模块实现介绍
4.1 时间单位和精度
timeunit 1ns;
timeprecision 1ps;

代码分析

  • timeunit 1ns;:指定时间单位为 1 纳秒。
  • timeprecision 1ps;:指定时间精度为 1 皮秒。
4.2 时钟生成逻辑
always begin
    wait(enable);
    if ( ( clk_high == 0 ) || ( clk_low == 0 ) )  begin
        $display("[FATAL] %m Clock Period is zero : %0d %0d",
                 clk_high, clk_low );
        $finish;
    end // if
    while(enable) begin
        clock = starting_signal_level;
        #(clk_high*1ps);
        clock = ~starting_signal_level;
        #(clk_low*1ps);
    end
end

代码分析

  • wait(enable);:等待 enable 信号变为 1,当 enable1 时,开始执行后续代码。
  • if ( ( clk_high == 0 ) || ( clk_low == 0 ) ):检查 clk_highclk_low 是否为 0,如果为 0,则输出致命错误信息并终止仿真。
  • while(enable):只要 enable 信号为 1,就持续生成时钟信号。
    • clock = starting_signal_level;:将时钟信号设置为起始电平。
    • #(clk_high*1ps);:保持高电平 clk_high 皮秒。
    • clock = ~starting_signal_level;:将时钟信号取反。
    • #(clk_low*1ps);:保持低电平 clk_low 皮秒。
5. 总结

xrtl_clock_vif.sv 定义了一个用于生成时钟信号的接口,通过 enable 信号控制时钟的启动和停止,支持自定义时钟的起始电平、高电平和低电平持续时间。同时,提供了等待指定时钟周期的任务,方便在验证环境中使用。该接口实现了基本的时钟生成功能,并对时钟周期为零的情况进行了错误处理,增强了代码的健壮性。不过,时钟参数的设置相对固定,可考虑添加更多的接口函数来动态修改这些参数,以提高接口的灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值