关于时钟模块完备性验证方法第二章

系列文章目录


第二章 时钟频率检查



前言

众所周知,时钟模块为整个SOC系统中各个模块提供相应的时钟,在大部分情况下,各个模块的时钟频率各不相同,这也是为了更好的管理芯片的功耗问题,当系统需要跑到高频阶段时,软件可以通过配置分频控制字将时钟切换到高频,同理当芯片需要进行相对低的功耗时,就需要把各个模块的频率切换到低频去工作。因此,在系统工作过程中,软件会频繁切换相关模块的时钟频率。关于时钟无毛刺切换设计,我已在其他篇文章中做了详细介绍,这里我们主要介绍如何验证时钟切换过程中频率是否符合要求的问题。

针对系统中进行时钟频率切换,本文介绍了一种验证方法,专门对切换过程中时钟频率是否满足要求添加了自动化的验证checker,不管是验证debug过程中,还是后续回归测试,该自动化检查checker可以随时上报频率异常的问题,极大的加快了芯片验证的流程。

一、什么是时钟频率检查?

所谓时钟频率检查,即是根据设计需求,对所有设计支持的频率范围进行全方位的动态检查,一旦系统运行过程中,时钟频率违反了指定的频率,即刻向testbench上报时钟频率错误信息,方便debug。

二、使用步骤

1.自动化check代码代码如下:

`define CLK_FREQ_CHK(chk_clk,chk_freq,sign)
begin
  real t_last,t_now,t_starat,cycle_now,chk_cycle;
  int cnt;
  chk_cycle = 1000.000/chk_freq;
  t_last = 0.0;
  t_now  = 0.0;
  cnt = 0;
  t_start = $realtime;
  fork
     begin
       while(1)begin
          @(posedge clk_ref);
          if(clk_check==0)begin
             cnt = 0;
             break;
          end
       end
     end
     begin
       while(1)begin
          @(posedge chk_clk);
          t_now = $realtime;
          if(cnt==0)begin
          end
          else if((t_last >0) &&(cnt>1))begin
             cycle_now = t_now - t_last;
             if((cycle_now > (0.99*chk_cycle)) &&(cycle_now < (1.01*chk_cycle)))begin
             end
             else begin
                $display("clk_freq_err, %0s, exp_freq=%0f,act_freq=%0f,expect cycle=%0f,
                actual cycle=%0f, at time 
                %0f",sign,chk_freq,1000.000/cycle_now,chk_cycle,cycle_now,%time);
                err_num++;
             end
          end
          begin
             t_last = $realtime;
             cnt ++;
          end
       end
     end
  join_any
  disable fork;
end

2. 代码解析

首先是这部分代码的主体结构,如下:

`define CLK_FREQ_CHK(chk_clk,chk_freq,sign)
begin
  real t_last,t_now,t_starat,cycle_now,chk_cycle;
  int cnt;
  chk_cycle = 1000.000/chk_freq;
  t_last = 0.0;
  t_now  = 0.0;
  cnt = 0;
  t_start = $realtime;
  fork
     begin
       xxx;
     end
     begin
       xxx;
     end
  join_any
  disable fork;
end

这部分主体代码建立了一个fork join的并行执行语句,当两个begin end语句中任意一个执行完毕后退出检查。这样做的目的是为了更好的控制整个flow,第一个begin end语句中我们添加了使能信号,当clk_check为0时,退出检查,这样可以在更上层testbench中随时使能或关闭,第二个begin end为计算频率的算法结构部分,通过计算的时钟频率与目标时钟频率进行比较,当误差范围超过设定的偏差值时,向testbench上报频率检查错误。

以下代码为第二个begin end算法结构:


       while(1)begin
          @(posedge chk_clk);
          t_now = $realtime;
          if(cnt==0)begin
          end
          else if((t_last >0) &&(cnt>1))begin
             cycle_now = t_now - t_last;
             if((cycle_now > (0.99*chk_cycle)) &&(cycle_now < (1.01*chk_cycle)))begin
             end
             else begin
                $display("clk_freq_err, %0s, exp_freq=%0f,act_freq=%0f,expect cycle=%0f,
                actual cycle=%0f, at time 
                %0f",sign,chk_freq,1000.000/cycle_now,chk_cycle,cycle_now,%time);
                err_num++;
             end
          end
          begin
             t_last = $realtime;
             cnt ++;
          end
       end
 

首先,当待check的时钟chk_clk上升沿到来时,我们记录下当前的时间,然后下一个时钟上升沿到来后记录当前时间为t_last,后续根据每个当前时钟时间减去上一个时钟沿的时间,来计算时钟周期cycle_now,最后根据cycle_now的数值跟传参chk_cycle进行比较,当误差范围小于0.01倍的时钟周期时,检查通过;否则检查fail,并向testbench上报错误信息。


 `CLK_FREQ_CHK(clk_target,100,"clk_target freq")
 

在整个验证体统中通过调用上述宏定义来对所有待检查时钟进行实例化。如上是我们需要检查clk_target的时钟频率为100M的实例化调用。


总结

这里对文章进行总结:

通过宏定义的方式对检查进行主体建模,然后在验证bench中对所有待检查的时钟进行扩展建模,很大程度上减少代码的复杂度,使代码通俗易懂,易维护。同时,通过这种自动化的时钟频率检查,可以检查出任意时刻,当时钟频率不满足设定的目标频率时随时向testbench上报错误信息,大大提高验证效率。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

love混世_魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值