[SV]Check某個信號電平保持時間的一種方案

                  Check某個信號電平保持時間的一種方案

                                      ----暨SV中Time類型變量比較大小中的注意事項

       引言:在數字驗證中,我們經常會Check某個信號在某Event時,會保持多長時間,本文將介紹該Scenario涉及到的基礎知識以及一種測試方案。

一、背景知識

 1.1、Timescale task list

   No.                             Task                                                         Description
   1 $printtimescale [ (hierarchical_name) ];

displays the time scale of the specified module.

When no hierarchical name is specified, it displays the time scale of the module that is in the current scope.

   2 $timeformat [ (unit, precision, "suffix", min_field_width) ];

defines the format used by the %t text format specifier.

Unit is an integer between 0 and -15 and defines the base that time is to be displayed,

precision是小數點之後的時間精度

suffix是時間數值之後的字符串

min_field_width是顯示數值的最小寬度

 1.2、時間單位查找表(Time unit Lookuptab)

No.   Int num                                 Unit   No.        Int num                               Unit
1 0 1sec 10 -9 1ns
2 -1 100ms 11 -10 100ps
3 -2 10ms 12 -11 10ps
4 -3 1ms 13 -12 1ps
5 -4 100us 14 -13 100fs
6 -5 10us 15 -14 10fs
7 -6 1us 16 -15 1fs
9 -7 100ns 17 - -
9 -8 10ns 18 - -
  • Precision is the number of decimal digits to display(精度是要顯示的小數位數). 
  • Suffix is a string appended to the time(後綴是添加到時間后的字符串). 
  • Min field width is the minimum number of characters that will be displayed.
  • 如果没有为$timeformat指定参数,则使用默认值。默认单位为仿真精度;精度为0;后缀是空字符串;min_field_width是20个字符。

 1.3、應用案例

initial begin
  $printtimescale(top.u1);
  $timeformat(-9, 2, " ns", 15);
end

二、SystemVerilog中的時間類型變量的運算

 2.1、SystemVerilog中時間類型變量比較大小

  • 直接看案例,從下面的案例我們可以分析出:
  • 使用Verilog的仿真時間系統函數所取得的Time數值,其實是以`timescale中指定的單位來存儲的,如本例中,a在系統中的存儲形式其實是:1.23456ns,所以第一個initial塊只會走else if分支
  • 我們看到$display()打印的時間是1234567fs,那是應為$timeformat()函數起的作用
`timescale 1ns/10fs

module cmp_time_time_test();

  realtime            a;
  realtime            b = 1.234569ns;
  realtime            c = 1ns;

  int                 d = 1_000_000;

  initial begin
    #1.234567ns;  //1_124_567fs
    $display("Simulation Time: %0t", $realtime);

    a = $realtime();

    if(a >= d) begin
      $display("True a = %0t, d = %0d\n", a, d);
    end
    else if(a >= b) begin
      $display("False a = %0t, b = %0t\n", a, b);
    end
    else begin
      $display("Fatal a = %0t, b = %0t\n", a, b);
    end
  end

  initial begin
    #1.234567ns;  //1_124_567fs
    $display("Simulation Time: %0t", $realtime);

    if(a >= 1_234_567) begin
      $display("True a = %0t, d = %0d\n", a, d);
    end
    else if(a >= 1.23456789) begin
      $display("False a = %0t, b = %0t\n", a, b);
    end
    else begin
      $display("Fatal a = %0t, b = %0t\n", a, b);
    end    

  end

  initial begin
    $fsdbDumpvars(0, 0);
    $timeformat(15, 0, "fs", 20);
  end

endmodule

 2.2、結論

  • 當對系統時間比較大小時,注意timescale的設定,默認保存單位是timescale設定的單位(注意:不是精度)
  • 如果要使用到時間參數,請聲明為realtime類型,然後用timescale制動的單位進行賦值,不要自己做單位轉換,例如:realtime a_max = 1.1ns
  • 一切不帶時間單位的延時(Delay)都是耍流氓
  • 對Time類型的變量做運算,請帶上單位(timescale中指定的),不要自己做單位換算
  • 在Log中看的時間打印信息其實是經過$timeformat()函數處理過的

三、Check信號電平保持時間的案例

 3.1、Scenario:在@posedge sync時u,clk會keep一段時間,並且keep時間在[6:8]ns之間

 3.2、代碼實現

realtime            keep_time_min = 6.00000ns;
realtime            keep_time_max = 8.00000ns;
realtime            half_cycle = 1.0012ns;
bit [7:0]           clk_keep_cnt;

task clk_keep_time_check();
  realtime      t1_posedge;
  realtime      t2_negedge;
  realtime      keep_time;

  @(posedge sync);
  clk_keep_cnt = 0;

  do begin
    fork
      begin
        @(posedge clk);
        t1_posedge = $realtime();
      end

      begin
        @(negedge clk);
        t2_negedge = $realtime();
      end

    join

    if(t1_posedge >= t2_negedge) begin
      keep_time = t1_posedge - t2_negedge;
    end
    eles if(t1_posedge < t2_negedge) begin
      keep_time = t2_negedge - t1_posedge;
    end

    if((keep_time >= keep_time_min) && (keep_time <= keep_time_max)) begin
      clk_keep_cnt += 1'b1;    
    end
    else if((keep_time >= half_cycle + 1ps) && (keep_time <= keep_time_min - 1ps)) begin
      `uvm_error()
    end
    else if(keep_time > keep_time_max) begin
      `uvm_error()
    end
    else begin
      `uvm_info()
    end
  end while(sync === 1'b1);

endtask : clk_keep_time_check
原创文章 228 获赞 180 访问量 6万+

猜你喜欢

转载自blog.csdn.net/gsjthxy/article/details/105735350