SystemVerilog検証テストプラットフォームライティングガイド第4章接続の設計とテストプラットフォーム

設計の検証にはいくつかの手順が必要です。入力刺激の生成、出力応答のキャプチャ、正誤判断、進行状況の測定です。この設計を完了するための最初のステップは、DUT(Design Under Test)をテストプラットフォームに接続する方法です。この章の内容はこの問題を解決します。

4.1テストプラットフォーム
とデザインの分離テストプラットフォームのコードはデザインコードから独立しているため、設計者は仕様を満たすコードを記述し、検証エンジニアはデザインが設計仕様を満たさないシナリオを作成する必要があります。モジュールを使用してテストプラットフォームを保存すると、駆動およびサンプリング中にタイミングの問題が発生することがよくあります。SystemVerilogにプログラムブロックが導入され、テストプラットフォームをロジックおよび時間から分離します。
4.1.1テストプラットフォームとDUT間の通信
設計が複雑になるにつれて、モジュール間の接続も複雑になります。この章では、テストプラットフォームとDUTの間の接続を全員に理解してもらうために、アービターのテストプラットフォームを分析の例として取り上げます。
通常、Verilogのポートの説明はより扱いにくくなっています。この例では、複雑なポートの説明を見てみましょう。
例4.1 Verilogポートの使用アービターモデル

module arb_port (output logic[1:0] grant,
				input logic[1:0] request,
				input logic rst,
				input logic clk );
	always@(posedge clk or posedge rst)
	begin
		if(rst)
			grant<=2'b00;
		else
			......
	end
endmodule

テストプラットフォームは、デザインが配置されているモジュールとは無関係に、別のモジュールで定義されます。通常、テストプラットフォームはポートを介してデザインに接続されます。
例4.2ポートの使用テストプラットフォーム

module test (input logic[1:0],
			input logic clk,
			output logic[1:0] request,
			output logic rst);
	initial begin
			@(posedge clk) request<=2'b01;
			$ display("@%0t:Drove req=01",$ time);
			repeat(2) @(posedge clk);
			if(grant!=2'b01)
				$ diaplay("@%0t:a1:grant!=2'b01",$time);
			......
			$finish;
	end
endmodule

トップレベルのネットリストは、テストプラットフォームとDUTを接続し、シンプルなクロックジェネレーターを含みます。
例4.3インターフェースなしトップネットリスト
module top;
logic [1:0] grant、request;
bit clk、rst;
always#5 clk =〜clk; //クロックジェネレーター

arb_port a1 (grant,request,rst,clk); //例4.1 使用端口的仲裁器模型
test t1 (grant,request,rst,clk); //例4.2 使用端口的测试平台

エンドモジュール
はポートを介して接続されていますが、上記の例はあまり複雑に見えませんが、実際の実際の設計には数百のポート信号が含まれることが多く、信号とポートを宣言するために数ページのコードが必要です。これらの接続はすべてエラーが発生しやすくなります。あなたが望むなら新しい信号を追加します。複数のファイルで定義して接続する必要があります上記の問題に対して、SystemVerilogには対応するソリューションがあります。

4.2インターフェースインターフェース
SystemVerilogは、インターフェースを使用してブロック間の通信をモデル化し、インターフェースはインテリジェントな接続のバンドルと見なされます。インターフェイスには、デザインブロックとテストプラットフォームを接続する2つ以上のブロック間の接続、同期、さらには通信が含まれます。
4.2.1インターフェースを使用して接続を簡素化する
ポートを1つのインターフェースにバンドルします。インターフェースは、テストプラットフォームとDUTの駆動および受信機能モジュールに拡張されます。クロックは、インターフェイスの一部または個別のポートにすることができます。
最も単純なインターフェースは、双方向信号の組み合わせです。これらの信号は論理データ型を使用し、手続き型ステートメントによって駆動できます。
例4.4アービターのシンプルなインターフェース

interface arb_if (input bit clk);
	logic[1:0] grant,request;
	logic rst;
endinterface

例4.5シンプルなインターフェースを使用したアービターモデル

module arb (arb_if arbif); //DUT使用接口,接口实例名arbif
	......
	always@(posedge arbif.clk or posedge arbif.rst)
		begin
		if(arb.rst)
			arb.grant<=2'b00;
		else
		......
		end
endmodule

インスタンス名arbif.requestを使用して、インターフェースのシグナルを参照できます。インターフェイス信号は非ブロッキング割り当てを使用して駆動する必要があります
例4.6シンプルなアービターインターフェイスを使用したテストプラットフォーム

module test (arb_if arbif);
......
	initial 
	begin //此处省略了复位代码
		@(posedge arbif.clk);
		arbif.request<=2'b01;
		$ display("@%0t:Drove req=01",$ time);
		repeat(2) @(posedge arbif.clk);
		if(arbif.grant!=2'b01)
			$ diaplay("@%0t:a1:grant!=2'b01",$time);
		......
		$finish;
	end
endmodule

これらのブロックはすべてインスタンス化され、最上位モジュールに接続されます。
例4.7シンプルなアービターインターフェースを使用したトップモジュール

module  top;
	bit clk;
	always #5 clk=~clk;
	arb_if arbif(clk); //例4.4
	arb a1(arbif); //例4.5
	test t1 (arbif); //例4.6
endmodule:top

最上位モジュールは、モジュールに記述された設計DUT、プログラムブロックのテストプラットフォームTEST、およびインターフェイスインターフェース、ショートカットシンボルを接続します。**(暗黙のポート接続)は、モジュールインスタンスのポートを現在のレベルの特定の信号に自動的に接続できます。ポートと信号の名前とデータタイプが同じである限り。
いくつかの点に注意を払う必要があります:
テストプラットフォームを構築する場合、非ブロッキング割り当てを使用してインターフェイス信号を駆動する必要があります
インターフェイスを使用するときは、モジュールとブロックの外でインターフェイス変数を宣言してください
4.2.2インターフェースとポートの接続インターフェース
の信号をポートに直接接続できます。

module  top;
	bit clk;
	always #5 clk=~clk;
	arb_if arbif(clk);
	arb a1(.grant(arbif.grant), //.port(ifc.signal)
			.request(arbif.request),
			.rst(arbif.rst),
			.clk(arbif.clk));
	test t1 (arbif);
endmodule:top

4.3 modportを使用
したインターフェース内の信号のグループ化前のインターフェース定義では、信号の方向は言及されていませんが、信号方向のないポイントツーポイント接続が使用されています。インターフェイスのmodport構造を使用して信号をグループ化し、方向を指定します
次のコード例のmonitor modportステートメントは、テストプラットフォームが新しく追加されたモニターモジュールに接続できるようにします。
例4.10 modportとのインターフェース

interface arb_if (input bit clk);
	logic[1:0] grant,request;
	logic rst;
	modport TEST(output request,rst,
				input grant, clk);
	modport DUT (input request, rst, clk,
				output grant);
	modport MONITOR(input request,grant,rst,clk);
endinterface

以下は、対応するアービターモデルとテストプラットフォームです。これらはすべて、ポート接続テーブルでmodportを使用します。インターフェース名arb_ifの後ろにmodport名DUTまたはTESTを置く必要があることに注意してください。
例4.11インターフェースでmodportを使用したアービターモデル

module arb (arb_if.DUT arbif);
	......
endmodule

例4.12インターフェイスでmodportを使用したテストプラットフォーム

module test (arb_if.TEST arbif);
	......
endmodule

最上位モジュールは例4.7と同じです。Modportはモジュールヘッダーでのみ指定され、モジュールのインスタンス化中に指定する必要はありません。
注:上記のインターフェースを定義する場合、テストプラットフォームを新しく追加されたモニターモジュールに接続できるmodport MONITOR(例4.10)を使用しました。
例4.13インターフェイスにmodportを使用したアービターモデル

module monitor (arb_if.MONITOR arbif);
	always@(posedge arbif.request[0])
	......
endmodule

4.3刺激タイミング
クロックサイクルレベルのテストプラットフォームでは、クロック信号に対して適切なタイミングで同期信号を駆動および受信する必要があります。運転が遅すぎたり、サンプリングが早すぎたりすると、テストプラットフォームのアクションでクロックサイクルが失われます。SystemVerilogには、通信のタイミング問題の制御に役立ついくつかの構造があります。
4.3.1クロックブロックcbを使用して同期信号のタイミングを制御する
インターフェイスブロックは、クロックブロックを使用して、クロックに対する同期信号のタイミングを指定できます。ほとんどのクロックブロックはテストプラットフォームで使用されます。
クロックブロック内の信号は、同期して駆動またはサンプリングされるため、テストプラットフォームが正しい時間に信号と相互作用することが保証されます。
インターフェイスには複数のクロックブロックを含めることができますが、各ブロックには1つのクロック式しかないため、クロックドメインに対応します。
例4.14クロックブロックとのインターフェース

interface arb_if (input bit clk);
	logic[1:0] grant,request;
	logic rst;
	clocking cb @(posedge clk); //声明cb
		output request;
		input grant;
	endclocking
	modport TEST(clocking cb, //使用cb
		output rst);
	modport DUT (input request, rst,
		output grant);
endinterface

上記の例からわかるように、TEST modportは要求と許可を同期信号として扱います。
クロックブロックでmodportを使用する場合は、同期インターフェイス信号の前にインターフェイス名とクロックブロック名を追加する必要があります。arbif.cb.requestは合法であり、arbif.requestは違法です

//简单的测试平台
module test (arb_if.TEST arbif);
	initial 
	begin
		arbif.cb.request<=0;
		@arbif.cb;
		$ diaplay("@%0t:grant!=%0b",$time,arbif.cb.grant);
	end
endmodule

arbif.cbは、正確なクロック信号とエッジを記述せずに、クロックの有効エッジを表します。arb.cb.request <=0。0の値がクロックの有効なエッジでリクエストに割り当てられることを示します。
インターフェイス信号は非ブロッキング割り当てを使用します。
4.3.2
インターフェースでのロジックとワイヤの比較インターフェースで信号をロジックタイプとして定義することをお勧めします。ロジックタイプステートメントは、プロセスステートメントで割り当てることも、直接駆動することもできます。ワイヤタイプは連続割り当てのみを使用できます。
4.3.4プログラムブロックとタイミング領域の
テストプラットフォームは、ロジックだけでなくタイミングもデザインから独立している必要があります。通常、テストプラットフォームと設計の間には競合状態があります。この問題の根本的な原因は、設計とテストのプラットフォームイベントが同じイベントスライスに混在していることです。
タイムラインでこれらのイベントを分離する方法がある場合は、すべてのイベントが実行された後で、テストプラットフォームが次のアクションを開始できることを確認してください。次に、タイミングの問題をうまく解決します。
SystemVerilogは、テストプラットフォームのイベントを設計されたイベントからどのように分離しますか?
SystemVerilogでは、テストプラットフォームコードはプログラムブロックで、これはモジュールに非常に似ていますが、プログラムブロックに階層レベルを含めることはできません、モジュールインスタンス、インターフェイス、その他のプログラムなど。
SystemVerilogは、タイムスライスを分割する新しい方法を導入します。
アクティブ:シミュレーションモジュールの設計コード
観察された:SystemVerilogアサーションを実行する
反応性:プログラムのテストプラットフォーム部分の実行
延期:テストプラットフォームの入力サンプリングでは、すべての設計アクティビティが読み取り専用期間サンプリング信号で完了します。
例4.27クロックブロックインターフェイスを備えたテストプラットフォームの使用

program automatic test (arbif.TEST arbif);
...
	initial begin
		arbif.cb.request<=2'b01;
		repeat(2) @arbif.cb; //@arbif.cb语句将等待时钟块给出有效沿@(posedge clk)
		if(arbif.cb.grant!=2'b01);
			$ display ("@%0t:a1:grant!=2'b01",$time);
	end
endprogram:test

テストコードは、単一のプログラムブロックに含める必要があります。OOPを使用して、モジュールではなくオブジェクトを介して動的な階層型テストプラットフォームを作成する必要があります。
4.3.4シミュレーションの終了
タイプ1
$の終了終了エンカウンタータイプ2 :プログラムブロックが1つしかない場合、すべての初期ブロックの最後のステートメントが完了すると、シミュレーションが終了します。複数のブロックがある場合、シミュレーションは最後のブロックの終わりで終了します。
3番目のタイプ:$ exitを実行すると、事前に任意のプログラムブロックを終了できます。

4.4インターフェースのドライバーとサンプリング
テストプラットフォームは、主にクロックブロックとのインターフェースを介して行われる、設計された信号を駆動およびサンプリングする必要があります。
4.4.2インターフェース信号のサンプリング
インターフェースによってサンプリングされる情報は、設計された出力信号をサンプリングします。クロックブロックから信号を読み取ると、クロックの前にサンプル値が取得されます。
例4.19モジュール内の同期インターフェースのサンプリングと駆動

'timescale 1ns/1ns;
program test (arcif.TEST arbif);
	initial begin
		$ monitor("@%0t:grant=%h",$time,arbif.cb.grant);
	#50 $display("End of test");
	end
endprogram
module arb(arb_if.DUT arbif);
	initial begin
		#7 arbif.grant=1;
		#10 arbif.grant=2;                        
		#18 arbif.grant=3;
	end
endmodule

arbif.grantはモジュールによって駆動され、ブロッキング割り当てを使用できます。
テストプラットフォームのプログラムブロックでは、クロックブロックでmodportを使用する場合、同期されたインターフェイス信号はすべてarbif.cb.grantの形式にする必要があります。
ここに画像の説明を挿入
4.4.3インターフェース信号の駆動
クロックブロックのデフォルトのタイミングは、#1step遅延後に入力信号をサンプリングし、#0遅延後に出力信号を駆動することです。
#1step遅延は、信号が前のタイムスライスの延期領域にあることを指定します。新しいアクションは以前にサンプリングされます。
#0、クロックモジュールのため、テストプラットフォームの出力信号は同期されているため、デザインに直接送信されます。
例4.22同期インターフェースの駆動

program test(arb_if.TEST arbif);
	initial begin
		#7 arbif.cb.request<=3; //@7ns
		#10 arbif.cb.request<=2; //@17ns
		#18 arbif.cb.request<=1; //@25ns
		#15 finish;
	end
endprogram
module arb(arb_if.DUT arbif);
	initial
		$monitor("@%0t:req=%h", $time,arbif.request);
endmodule

上記の例から、テストプラットフォームがクロックの有効エッジで同期インターフェイス信号を駆動すると、その値がすぐにデザインに転送されることがわかります。
例4.23インターフェイス信号ドライバー

 ##2 arbif.cb,request<=0; //等待两个时钟周期然后赋值
##3;//非法——必须跟赋值语句同时使用

これは、信号を駆動する前に2クロックサイクル待機することを意味します。
4.4.6プログラムでalwaysブロックが許可されないのはなぜですか?
SystemVerilogでは、プログラムで初期ブロックを使用できますが、alwaysブロックは使用できません。これは、デザインでは、alwaysブロックがシミュレーションの最初から各クロックの立ち上がりエッジで実行をトリガーする可能性があるためです。ただし、テストプラットフォームの実行プロセスは、初期化、駆動、対応する設計動作のステップの後に完了します。ここでは、継続的に実行されるalwaysブロックは正しく機能しません。
プログラムブロックにalwaysブロックを追加すると、ブロックが終了することはないため、$ exitを呼び出してプログラムブロックの終了を通知する必要があります
alwaysブロックが本当に必要な場合は、「initial forever」を使用して同じことを達成できます
4.4.7クロックジェネレーター
クロックは、設計よりもテストプラットフォームに密接に統合されているため、クロックジェネレーターは、プログラムブロックではなくモジュールとして定義する必要があります。プログラムにクロックジェネレーターを配置し、Reactiveで送信を開始すると、Activeに到着した一連の信号により、時刻0で競合が発生する可能性があります。したがって、クロックエッジはブロッキング割り当てを使用して生成され、アクティブ領域でイベントの生成をトリガーします。
例4.25ブロック内の誤ったクロックジェネレーター

program bad_generator (output bit clk, out_sig);
	initial
		forever # 5clk=~clk;
	initial
		foever@(posedge clk)
			out_sig<=~out_sig;
endprogram

clkおよびout_sig信号は競合状態を引き起こします。
例4.26モジュールの正しいクロックジェネレーター

module clock_generator(output bit clk);
	initial
		always #5 clk=~clk; //在时间0之后生成时钟沿
endmodule

4.6トップレベルのスコープ
Verilogでは、マクロ定義のみがモジュールの境界を越えることができ、グローバル変数の作成によく使用されます。SystemVerilogは、一緒にコンパイルされたソースファイルの組み合わせであるコンパイルユニットを導入します。モジュール、インターフェース、プログラム、パッケージなどの境界外のスコープは、コンパイルユニットスコープと呼ばれ、$ユニットにもなります。
このスコープのすべてのメンバー(パラメーターなど)は、すべての下位レベルのブロックからアクセスできるため、グローバルメンバーと似ていますが、パラメーターなどの実際のグローバルメンバーとは異なります。他のソースファイルは、コンパイル時に表示されません。次の例は、コンパイル単位のパラメーターとconstの使用法を示しています。
例4.31アービター設計の最上位スコープ

//root.sv
`timescale 1ns/1ns
parameter int TIMEOUT=1_000_000;
const string time_out_msg="ERROR";

module top;
	test t1();
endmodule

program automatic test;
	......
	initial 
	begin
		#TIMEOUT;
		$ display("%s",time_out_msg);
		$ finish;
	end
endprogram

インスタンス名$ rootを使用すると、システム内のメンバー名をトップレベルのスコープから明示的に参照できます。この時点では、Unixファイルシステムの「/」に似ています。$ rootを介した絶対パスを指定して、モジュール間で変数を明示的に指定できます。ここでは、クロスモジュール参照のいくつかの使用法を示します。プログラムブロックで、モジュールtopのclk信号を参照します。
絶対参照:
$ root.top.clk
はマクロ定義を使用します:
'define TOP $ root.top
' top.clk
相対参照:
top.clk
例4.32 $ rootを使用したクロスモジュール参照

`timescale 1ns/1ns
parameter int TIMEOUT=1_000_000;
top t1(); //顶层模块的显示例化
    
module top;
	bit clk;
	test t1(.*);
endmodule
    
'define TOP $root.top
program automatic test;
	......
	initial 
	begin
		//绝对引用
		$ display("clk=%b", $root.top.clk);
		$ display("clk=%b", 'top.clk); //使用宏
		//相对引用
		$ display("clk=%b", top.clk);
endprogram

4.7プログラムとモジュールの相互作用
プログラムブロックは、モジュール内のすべての信号を読み書きでき、モジュール内のすべての履歴を呼び出すことができます。これらの履歴は内部信号の値を変更できますが、モジュールはプログラムブロックを認識できません。これは、テストプラットフォームがデザインにアクセスして制御する必要があるが、デザインはテストプラットフォーム上の何からも独立しているためです。
DUTの関数を使用してテストプラットフォームの情報を取得モジュールの関数は、2つの間の通信をカプセル化し、テストプラットフォームを設計とより簡単に同期させることができます。

4.8 System VerilogアサーションアサーションSVA
は、SystemVerilogアサーション(SVA)を使用してデザインにタイミングアサーションを作成します。エミュレーターは、アクティブ化されているアサーションを追跡するため、これに基づいて機能範囲に関するデータを収集できます。
4.8.1即時アサーション:即時アサーション

bus.cb.request<=1;
repeat(2) @bus.cb;
a1:assert (bus.cb.grant==2'b01);

アサートの内容はtrueであると想定されます。そうでない場合は、エラーメッセージを出力します。ifステートメントに似ていますが、同等の手続き型コードは、これらのアサーションよりもはるかに複雑で時間がかかる場合があります。
4.8.2カスタムアサート動作
a1:アサート(bus.cb.grant == 2'b01)
else $エラー(「Grant not asserted 」);
アサートはオプションのthenおよびelse句をアサートしてデフォルト情報を変更し、独自の情報を追加できます必要な出力情報。
SystemVerilogには、メッセージを出力するための4つの機能があります。$ info $ warning $ error $ fatalこれらの関数は、アサーション内での使用に制限されています。
4.8.3同時アサーション

interface arb_if(input bit clk);
	logic[1:0] grant,request;
	logic rst;

	property request_2state;
		@(posedge clk) disable iff (rst);
		$isunknown(request)==0;//确保没有Z/X值存在
	endproperty
	assert_request_2state:assert property(request_2state);
endinterface

要求信号は、リセット中を除いて、いつでもXまたはZではありません。
1.シミュレーションプロセス全体の信号の値をチェックするのは、継続的に実行されるモジュールです。
2.アサーションでサンプリングクロックが指定されています。

4.8 refポート
SystemVerilogは、新しいポート方向を導入します:ref。Verilogでは、慣れ親しんでいるポートの方向は、入力、出力、入力です。
複数の入出力ポートを使用して信号を駆動する場合、SystemVerilogはすべてのドライバーの値と駆動強度に基づいて最終的な信号値を計算します。
複数の参照ポートが変数を駆動する場合、複数のモジュールのポートが同じ変数を更新する可能性があるため、競合が発生する可能性があります。refポートは実際には(ネットではなく)変数への参照であり、その値は変数に割り当てられた最後の値です。

元の記事を38件公開 29のような 10,000以上の訪問

おすすめ

転載: blog.csdn.net/weixin_45270982/article/details/97526783