SystemVerilog Assertion (SVA) のノウハウまとめ

随時更新予定です。



SystemVerilog Assertion (SVA) とは


SVAは論理回路の検証手法
  • 自動検証によるヒューマンエラー削減
  • 仕様変更による影響範囲の確認
  • 検証エビデンスとして明確
などのメリットが得られる

SVAの仕様詳細は以下SystemVerilogの仕様書を参照

SVA簡易実装例:
  • Signal_A がアサートされてから 4 cycle以内に Signal_B がアサートを確認


SystemVerilog:
bind TB sva_module u_sva_module();

`define DUT_PATH TB.top

module sva_module();
    localparam N = 4;
    
    property p_A_to_B_within_N(
        logic clk
    ,   logic rstn
    ,   logic sig_a
    ,   logic sig_b
    );
    @(posedge clk) disable iff (!rstn)
        $rose(sig_a) |-> ##[1:N] $rose(sig_b);
    endproperty

    assert property (p_A_to_B_within_N (
        .clk    (`DUT_PATH.clk)
    ,   .rstn   (`DUT_PATH.rstn)
    ,   .sig_a  (`DUT_PATH.Signal_A)
    ,   .sig_b  (`DUT_PATH.Signal_B)
    ))
    else $error("Signal_B did not assert within %0d cycles after Signal_A", N);
endmodule


並列アサーション

  • 時系列のパターンを記載するシーケンス部分をプロパティとして定義することで記述 (上の例)
  • シミュレーションと並行して、クロックエッジ(もしくは他信号のエッジ)をトリガーに条件をチェックを実施

即時アサーション


アサーションを有効にしている間チェックされ続ける並列アサーションと違い、コード中に記述した特定のタイミングでのみチェック

記載例:
initial begin
    #100us;
    sva_state : assert (TB.top.Block_A.y === TB.top.Block_B.y)  $info ("[SVA] OK");
                else                                            $error("[SVA] ERROR");
end

次のようにalways_combを使って記載することで「信号の接続検証」も可能
always_comb begin
    sva_connect : assert (TB.top.yyy.y === TB.top.xxx.y);
end



SVAチェック可能な代表条件


条件
Aは常にB@(posedge clk) disable iff (reset)
(enable == 1)
AはBにならない@(posedge clk) disable iff (reset)
not (error == 1)
AのときB@(posedge clk) disable iff (reset)
(req == 1) |-> (enable == 1)
Aのとき次のサイクルでB@(posedge clk) disable iff (reset)
(req == 1) |=> (ack == 1)
Aのときnクロック以内にB//- reqが1のとき2サイクル以内にackは1
@(posedge clk) disable iff (reset)
(req == 1) |-> (ack == 1)(within 1'b1[*2])
Aが続くのはnサイクル以内//- reqが1になったら最大2サイクルの間は1のまま
@(posedge clk) disable iff (reset)
($rose (req) |-> req[*1:2] ##1 !req)
少なくともnサイクルはAが続く@(posedge clk) disable iff (reset)
($rose (req) |-> req[*3])
Aのときn秒以内にBrealtime current_time;
@(posedge clk) disable iff (reset)
(current_time = $realtime) => ($realtime - current_time < n)



SVAで使用される演算子


プロパティ演算子


プロパティ演算子説明
s1 and s2s1, s2ともに真(&でも可)
s1 or s2s1, s2いづれかが真(|でも可)
not s1反転
if (b1) s1 else s2条件切り替え
disable iff (b1) s1プロパティのアボート条件
b1が偽でs1をチェック
s1 |-> s2s1が発生したサイクルでs2をチェック
s1 |=> s2s1が発生した次のサイクルでs2をチェック
##nnサイクル経過
s1 intersect s2s1, s2をともに満たす(同時終了の制約あり)
first_match s1s1にて複数のシーケンスを含む場合に最初に満たしたシーケンスのみ使用
t1 throughout s1s1を満たしているときはt1の条件を満たすこと
s1 within s2s2を満たしているときのs1を満たすこと

遅延


シーケンス構文説明
s1 ##n s2s1のnサイクル後にs2
s1 ##[n:m] s2s1のn~mサイクル後にs2
s1 ##[n:$] s2s1のn~有限サイクル後にs2
s1 ##[*] s2s1 ##[0:$] s2と同じ
s1 ##[+] s2s1 ##[1:$] s2と同じ

繰り返し


シーケンス構文説明
s [*n]sがn回"連続"一致, (n => n => n...と同じ)
s [*n:m]sがn~m回"連続"一致
s [*n:$]sがn~有限サイクル回"連続"一致
s [*]s [*0:$]と同じ
s [+]s [*1:$]と同じ
s [->n]sがn回一致(n => ... => n => ... => n...と同じ)
s [->n:m]sがn~m回一致
s [=n]sがn回一致
s [=n:m]sがn~m回一致


その他演算子


ended メソッド


あるシーケンスAと、あるシーケンスBに順序関係がある場合、endedメソッドを使用して片方のシーケンスAの終了を待って、もう片方のシーケンスBの開始条件を定義できる。

例:
Writeアクセスのシーケンスが完了してから、Readアクセスのシーケンスへ移行
// Write Check シーケンス
sequence write_seq;
    wr_req ##[1:2] wr_ack;
endsequence

// Read Check シーケンス
sequence read_seq;
    rd_req ##[1:3] (rd_valid && rdata == wdata);
endsequence

// Writeが完了してからRead条件の確認
property write_then_read_check;
    @(posedge clk)
    write_seq.ended |-> read_seq;
endproperty

triggered メソッド


シーケンスが成立したイベントを検出して、次のシーケンスの確認を実施

例:
Req/Ackのイベントが発生したことを確認して、Responceの確認へ移行
// Req-Ack 成立
sequence req_seq;
    req ##1 ack;
endsequence

// Responce Check
property resp_check;
    @(posedge clk)
    req_seq.triggered |-> ##[1:5] resp;
endproperty

strong メソッド

シーケンスの完了を必ず保障するための演算子として用います。評価途中でSimulationが終了した場合もErrorを発火させることが可能

例:
// req が起きたら ack が"必ず"成立する
assert property (@posedge clk req |-> strong(##1 ack));



Assertion関連システムタスク


システム関数使用例説明
$onehot$onehot(信号A)信号の内あるbitだけが1(H)のとき真
$onehot0$onehot0(信号A)信号の内あるbitだけが1(H)、または全て0のとき真
$isunknown$isunknown(信号A)いずれかのbitが不定(x)のとき真
$countones$countones(信号A)1となっているbitの数を返す
$sampled$sampled(信号A)信号のプロパティ評価時の値をサンプリングして返す
$rose$rose(信号A)信号の最下位bitの立ち上がり時に真
$fell$fell(信号A)信号の最下位bitの立下り時に真
$stable$stable(信号A)信号が前サイクルから不変の場合は真
$past
$past(信号A)1サイクル前の信号の値を返す
$past(信号A, n)nサイクル前の信号の値を返す
$past(信号A, n, 信号B)信号Bが真となっているnサイクル前の信号Aの値を返す
$changed$changed(信号A)信号が変化したときに真
$realtime$realtime現在のシミュレーション時間を`timescaleのunit時間で取得


重大度のレベルとメッセージ出力


システム関数使用例説明重大度
$write$write("表示内容")コンソール及びlogへ表示(改行なし)、処理続行
$display$display("表示内容")コンソール及びlogへ表示(改行込み)、処理続行
$info$info("表示内容")コンソール及びlogへ表示、処理続行
$warning$warning("表示内容")コンソール及びlogへ表示、処理続行
$error$error("表示内容")コンソール及びlogへ表示、処理続行
$fatal$fatal("表示内容")コンソール及びlogへ表示、処理停止

失敗の重大度を示すメッセージと、指定したテキストを表示します。主に次のような情報がLogに出力されます。
  • アサーション名
  • アサーションの実装されている階層
  • アサーションの実装されているファイル名、行番号
  • アサーションによるチェックの行われたシミュレーション時間

$fatalが呼び出されると、暗黙的に$finishが呼び出されて処理が終了します。


SVAの有効無効切り替え制御


SystemVerilogのシステムタスク ON/OFF

システム関数使用例説明
$asserton$asserton(0, top.assert.<ラベル名>)指定したアサーションの実行を有効にする
$assertoff$asseryoff(0, top.assert.<ラベル名>)指定したアサーションを停止、$assertonで再度有効化
$assertkill$assertkill(0, top.assert.<ラベル名>)指定したアサーションを実行中含め停止、$assertonで再度有効化

使用例:
$asserton (<階層の深さ>, <基準階層>)

基準階層
  • 階層で指定する場合 :  (top.assertのように階層指定)
  • 特定アサーションのみ指定する場合 : 階層+ラベル名を指定

階層の深さ
  • 基準階層以下全て:0
  • 基準階層以下から指定した深さ:0以外


SVAの応用記述


シーケンスに対応した命令実行


(シーケンス, 命令分) のように記載することで、あるシーケンス成立時に特定の命令を付与することが可能です。

実装例:
// シーケンスに対応した命令実行
property prop_sequence_example;
  ($rose(req), $display("Detect assert Req")) |-> ##1 (ack, $display("Detect req ##1 ack"));  
endproperty

プロパティ内で変数の宣言


プロパティの宣言内で、変数を宣言することが可能です。外部に宣言した変数をプロパティ内部で参照することはできないため、そのような場合には、引数として値を引き込む必要があります。

下記では、t_reqという変数を時間の保存用として宣言しています。

実装例:
// プロパティ内で変数宣言
property req_ack_within_time;
    realtime t_req;
    @(posedge clk)
    // req発生時に時刻保存
    (req, t_req = $realtime)
    // ackが来たとき時間差チェック
    |-> ##[0:$] (ack && ($realtime - t_req <= 100ns));
endproperty





参考:
このエントリーをはてなブックマークに追加