工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Verilog

Verilog 遅延制御

Verilog には 2 種類のタイミング制御があります - delay そしてイベント 式。 遅延 制御は、シミュレーターがステートメントを検出してから実際に実行するまでの間に遅延を追加する方法にすぎません。 イベント式 ネットまたは変数の値の変更などのシミュレーション イベントが発生するまで、ステートメントを遅延させることができます (暗黙的なイベント ) または別の手順でトリガーされる明示的に名前が付けられたイベント。

シミュレーション時間は、次のいずれかの方法で進めることができます。

内部遅延を持つようにモデル化されたゲートとネットも、シミュレーション時間を進めます。

遅延制御

遅延式が不明または高インピーダンス値に評価される場合、ゼロ遅延として解釈されます。負の値に評価される場合、時間変数と同じサイズの 2 の補数の符号なし整数として解釈されます。

  
  
`timescale 1ns/1ps

module tb;
  reg [3:0] a, b;
  
  initial begin
    {a, b} <= 0;
    $display ("T=%0t a=%0d b=%0d", $realtime, a, b);
    
    #10;
    a <= $random;
    $display ("T=%0t a=%0d b=%0d", $realtime, a, b);
    
    #10 b <= $random;
    $display ("T=%0t a=%0d b=%0d", $realtime, a, b);
    
    #(a) $display ("T=%0t After a delay of a=%0d units", $realtime, a);
    #(a+b) $display ("T=%0t After a delay of a=%0d + b=%0d = %0d units", $realtime, a, b, a+b);
    #((a+b)*10ps) $display ("T=%0t After a delay of %0d * 10ps", $realtime, a+b);
    
    #(b-a) $display ("T=%0t Expr evaluates to a negative delay", $realtime);
    #('h10) $display ("T=%0t Delay in hex", $realtime);
    
    a = 'hX;
    #(a) $display ("T=%0t Delay is unknown, taken as zero a=%h", $realtime, a);
    
    a = 'hZ;
    #(a) $display ("T=%0t Delay is in high impedance, taken as zero a=%h", $realtime, a);
    
    #1ps $display ("T=%0t Delay of 10ps", $realtime);
  end
  
endmodule

  

タイムスケールの精度は 1ps 単位であるため、$realtime であることに注意してください。 遅延式 (a+b)*10ps を使用してステートメントの精度値を表示する必要があります。

シミュレーションログ
xcelium> run
T=0 a=x b=x
T=10000 a=0 b=0
T=20000 a=4 b=0
T=24000 After a delay of a=4 units
T=29000 After a delay of a=4 + b=1 = 5 units
T=29050 After a delay of 5 * 10ps
T=42050 Expr evaluates to a negative delay
T=58050 Delay in hex
T=58050 Delay is unknown, taken as zero a=x
T=58050 Delay is in high impedance, taken as zero a=z
T=58051 Delay of 10ps
xmsim: *W,RNQUIE: Simulation is complete.

イベント コントロール

ネットと変数の値の変更は、他の手続き型ステートメントの実行をトリガーする同期イベントとして使用でき、暗黙的 イベント。イベントは、0 に向かって negedge になるような変化の方向に基づくこともできます。 1 に向かって変更すると、posedge になります。 .

同じ状態から同じ状態への遷移は、エッジとは見なされません。 posedge や negedge などのエッジ イベントは、ベクトル信号または変数の LSB でのみ検出できます。式が同じ結果に評価される場合、それはイベントとは見なされません。

  
  
module tb;
  reg a, b;

  initial begin
    a <= 0;
    
    #10 a <= 1;
    #10 b <= 1;

    #10 a <= 0;
    #15 a <= 1; 
  end

  // Start another procedural block that waits for an update to
  // signals made in the above procedural block
  
  initial begin 
    @(posedge a); 
    $display ("T=%0t Posedge of a detected for 0->1", $time); 
    @(posedge b); 
    $display ("T=%0t Posedge of b detected for X->1", $time);
  end 
  
  initial begin
    @(posedge (a + b)) $display ("T=%0t Posedge of a+b", $time);

    @(a) $display ("T=%0t Change in a found", $time);
  end
endmodule

  
シミュレーションログ
ncsim> run
T=10 Posedge of a detected for 0->1
T=20 Posedge of b detected for X->1
T=30 Posedge of a+b
T=45 Change in a found
ncsim: *W,RNQUIE: Simulation is complete.

名前付きイベント

キーワード event 名前付きを宣言するために使用できます 明示的にトリガーできるイベント。 event データを保持できず、期間がなく、特定の時間に発生させることができます。名前付きイベントは -> によってトリガーされます 演算子は、名前付きイベント ハンドルの前にプレフィックスとして付けます。 @ を使用して、名前付きイベントを待機できます。

  
  
module tb;
  event a_event;
  event b_event[5];
  
  initial begin
    #20 -> a_event;
    
    #30;
    ->a_event;
    
    #50 ->a_event;
    #10 ->b_event[3];
  end
  
  always @ (a_event) $display ("T=%0t [always] a_event is triggered", $time);
  
  initial begin
    #25;
    @(a_event) $display ("T=%0t [initial] a_event is triggered", $time);
    
    #10 @(b_event[3]) $display ("T=%0t [initial] b_event is triggered", $time);
  end
endmodule

  

名前付きイベントを使用して、同時に実行されている 2 つ以上のプロセスを同期できます。たとえば、always ブロックと 2 番目の initial ブロックは a_event によって同期されます。イベントは、サイズ 5 の配列である b_event の場合のように配列として宣言でき、インデックス 3 はトリガーと待機の目的で使用されます。

シミュレーションログ
ncsim> run
T=20 [always] a_event is triggered
T=50 [always] a_event is triggered
T=50 [initial] a_event is triggered
T=100 [always] a_event is triggered
T=110 [initial] b_event is triggered
ncsim: *W,RNQUIE: Simulation is complete.

イベントまたは演算子

or 演算子を使用して、リストされたイベントのいずれかが式でトリガーされるまで待機できます。コンマ , or の代わりに使用することもできます

  
  
module tb;
  reg a, b;
  
  initial begin
    $monitor ("T=%0t a=%0d b=%0d", $time, a, b);
    {a, b} <= 0;
    
    #10 a <= 1;
    #5  b <= 1;
	#5  b <= 0;
  end
  
  // Use "or" between events
  always @ (posedge a or posedge b) 
    $display ("T=%0t posedge of a or b found", $time);
  
  // Use a comma between
  always @ (posedge a, negedge b)
    $display ("T=%0t posedge of a or negedge of b found", $time);
  
  always @ (a, b) 
    $display ("T=%0t Any change on a or b", $time);
endmodule

  
シミュレーションログ
ncsim> run
T=0 posedge of a or negedge of b found
T=0 Any change on a or b
T=0 a=0 b=0
T=10 posedge of a or b found
T=10 posedge of a or negedge of b found
T=10 Any change on a or b
T=10 a=1 b=0
T=15 posedge of a or b found
T=15 Any change on a or b
T=15 a=1 b=1
T=20 posedge of a or negedge of b found
T=20 Any change on a or b
T=20 a=1 b=0
ncsim: *W,RNQUIE: Simulation is complete.

暗黙のイベント式リスト

センシティビティ リストまたはイベント式リストは、多くの場合、RTL の多くの機能エラーの一般的な原因です。これは、プロシージャル ブロックに新しいシグナルを導入した後、ユーザーがセンシティビティ リストを更新するのを忘れる可能性があるためです。

  
  
module tb;
	reg a, b, c, d;
	reg x, y;
	
	// Event expr/sensitivity list is formed by all the
	// signals inside () after @ operator and in this case
	// it is a, b, c or d
	always @ (a, b, c, d) begin
		x = a | b;
		y = c ^ d;
	end
	
	initial begin
		$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b x=%0b y=%0b", $time, a, b, c, d, x, y);
		{a, b, c, d} <= 0;
	
		#10 {a, b, c, d} <= $random;
		#10 {a, b, c, d} <= $random;
		#10 {a, b, c, d} <= $random;
	end
endmodule

  
シミュレーションログ
ncsim> run
T=0 a=0 b=0 c=0 d=0 x=0 y=0
T=10 a=0 b=1 c=0 d=0 x=1 y=0
T=20 a=0 b=0 c=0 d=1 x=0 y=1
T=30 a=1 b=0 c=0 d=1 x=1 y=1
ncsim: *W,RNQUIE: Simulation is complete.

ユーザーが新しいシグナル e を追加し、逆を z にキャプチャすることを決定した場合、e もセンシティビティ リストに追加するように特別な注意を払う必要があります。

  
  
module tb;
	reg a, b, c, d, e;
	reg x, y, z;
	
  // Add "e" also into sensitivity list
  always @ (a, b, c, d, e) begin
		x = a | b;
		y = c ^ d;
    	z = ~e;
	end
	
	initial begin
      $monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b", 
                				$time, a, b, c, d, e, x, y, z);
      {a, b, c, d, e} <= 0;
	
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
	end
endmodule

  
シミュレーションログ
ncsim> run
T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1
T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1
T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0
T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0
ncsim: *W,RNQUIE: Simulation is complete.

Verilog では、機密リストを * に置き換えることができるようになりました これは、以下に示すように、statemnt によって読み取られるすべてのネットと変数を追加することで、これらの問題を解消する便利な省略形です。

  
  
module tb;
	reg a, b, c, d, e;
	reg x, y, z;
	
  // Use @* or @(*)
  always @ * begin
		x = a | b;
		y = c ^ d;
    	z = ~e;
	end
	
	initial begin
      $monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b", 
                				$time, a, b, c, d, e, x, y, z);
      {a, b, c, d, e} <= 0;
	
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
      #10 {a, b, c, d, e} <= $random;
	end
endmodule

  
シミュレーションログ
ncsim> run
T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1
T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1
T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0
T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0
ncsim: *W,RNQUIE: Simulation is complete.

レベル センシティブ イベント コントロール

手続き型ステートメントの実行は、条件が真になるまで遅らせることもでき、wait で達成できます。 キーワードであり、レベルに依存するコントロールです。

待機ステートメントは条件を評価し、それが偽の場合、条件が真になるまで後続の手続きステートメントはブロックされたままになります。

  
  
module tb;
  reg [3:0] ctr;
  reg clk;
  
  initial begin
    {ctr, clk} <= 0;
    
    wait (ctr);
    $display ("T=%0t Counter reached non-zero value 0x%0h", $time, ctr);
    
    wait (ctr == 4) $display ("T=%0t Counter reached 0x%0h", $time, ctr);
    
    $finish;
  end
  
  always #10 clk = ~clk;
  
  always @ (posedge clk) 
    ctr <= ctr + 1;
  
endmodule

  
シミュレーションログ
ncsim> run
T=10 Counter reached non-zero value 0x1
T=70 Counter reached 0x4
T=90 Counter reached 0x5
T=170 Counter reached 0x9
Simulation complete via $finish(1) at time 170 NS + 1


Verilog

  1. Verilog チュートリアル
  2. Verilog 連結
  3. Verilog 割り当て
  4. Verilog ブロッキング &ノンブロッキング
  5. Verilog 制御ブロック
  6. Verilog 関数
  7. Verilog タスク
  8. Verilog インターおよびイントラ割り当て遅延
  9. Verilog ゲート遅延
  10. Verilog クロック ジェネレーター
  11. Verilog 数学関数