VHDLでの時間計算

はじめに

VHDLは重要な時間計算を試みる場合、いくつかの問題を引き起こすかもしれない時間のかなりユニークな概念を使用します。このドキュメントでは、有益な機能を提供するaldec_toolsパッケージに組み込まれた時間データタイプの設置と機能の両方の使用方法について説明します。

"time"タイプ

HDLは、下記の様に組み込みの時間タイプを定義しています:

	type time is range -2147483647 to 2147483647
		units
			fs;
			ps = 1000 fs;
			ns = 1000 ps;
			us = 1000 ns;
			ms = 1000 us;
			sec = 1000 ms;
			min = 60 sec;
			hr = 60 min;
	end units;

これはプライマリユニットがある物理的なタイプに関する典型的な例です: 時間までのフェムト秒とセカンダリユニット。タイプ値の範囲は、real 型ではなく32ビット符号付きinteger を使用して記述されているのでご注意ください。VHDLの時間の精度は、1fsより高いことができないことを意味します:セカンダリタイムユニットが使用される場合、時間の少数のみが発生する可能性があります。

ここでするべき質問は以下の通りです:どんな単位が使用されていても、シミュレータが時間値を格納するために32ビットの数を使用できますか? 確認して見ましょう:

  • 1時間は、3.6x1018 フェムト秒を持っています。

  • 32ビットの符号付きintegerで表現できる最大値は、231-1 = 2147483647 = 2.15x109

32ビットが全て所定の時間単位をカバーするのに十分ではないことを意味します。 2.15マイクロ秒に達した後、範囲を使い果たします!それはシミュレータが時間を表すのに32ビットの整数を使用していない主な理由です。

32ビットで無い場合は何?次に一般的なサイズ integers = 64 bit を確認してみましょう:

  • 64ビットの符号付きintegerで表現できる最大値は、263-1 = 9223372036854775807 = 9.22x1018

  • 3.6x1018で割った場合、2.5620477880152 を提供します。

64ビットの符号付き整数が、2.56時間以上の範囲への1フェムト秒以内の時間値(アプリケーションの大部分で妥当に見える)をカバーすることができることを意味します.VHDLシミュレータは、一般的に64ビットの時間表現を使用する理由です。

シミュレーション中に必要とされる最小遅延が100ピコ秒であり、100マイクロ秒へ達するまでシミュレートする場合、シミュレータが105~1011範囲内で時間値を使用することを意味します。すなわち、常に時間値の終わりに下位に5つ0があるでしょう。確実に経済的でない!この小さな問題を解決するために、シミュレータは一般的にシミュレーションレゾリューションの概念を使用します:シミュレータが特定のシミュレーションセッション中、最小の時間値を認識することが義務付けられています。1フェムト秒よりも大きなシミュレーションのレゾリューションを指定する1つのペナルティーで、シミュレーションを高速化することができます:レゾリューションよりも小さい任意の時間値はゼロに切り捨てられます。

時間の変換

テストベンチを記述するとき、VHDL ユーザーは時間と抽象的な数値タイプ(integerreal)の間の変換を余儀なくされることがあります。最も単純な変換は、integer から時間になります:

	-- Time_value := Int_value * Time_unit;
	timeout := intmax * 1 ns;

real から時間への変換は、キャスト(型変換)に追加が必要です:

	-- Time_value := integer(Real_value) * Time_unit;
	timeout := integer(realmax) * 1 ns;>

(realの値に保持したい小数部分がある場合、値の縮尺を変更し適切な時間単位に調整する必要があります。)

それらは除算演算を必要とするので、逆方向の変換がより困難である。 多くの場合、この操作は問題なく実行することができますが、まれにゼロまたはオーバーフロー問題の引き金となることがあります。

時間値を抽象値に変換する第一段階は、時間単位による時間値の除算を必要とするストリッピングユニットになります。この操作は、必要に応じてrealへのタイプキャストおよび再縮尺でinteger型が得られます:

	Int_pico := curr_time / 1 ns * 1000;
	Real_pico := real(curr_time / 1 ns) * 1000.0;>

シミュレーションのレゾリューションが変換に使用される除数よりも大きな値に設定した場合はどうなりますか?もちろんゼロに切り捨てられます。それはシミュレーションで「ゼロによる除算」エラーおよび終了を引き起こすでしょう。

(除数単位)時間値は、上記のサンプルコードの中で231-1(例えばcurr_time=3秒)以上である場合はどうなりますか? 除算結果が整数で処理できる範囲外であるためオーバーフローが発生します。それは必ずしもシミュレーションの終了が、正しい変換(整数値の符号ビットとして扱い、除算結果の最上位ビット)を意味するものではありません 。

aldec_tools パッケージ

ALDECは、最新のシミュレータリリースでアルデックライブラリにaldec_tools パッケージが用意されています。他の特徴の中では、3つの便利な機能を含んでいます:

	function to_real ( time_val : in time ) return real;
	function to_time ( real_val : in real ) return time;
	function get_resolution return real;>

get_resolution関数(パラメータ無し)は、秒単位でのシミュレーションのレゾリューションを表すreal値を返します。シミュレータのレゾリューションが1ピコ秒に設定されている場合、この関数は10-12を返します。

to_real関数は、現在のレゾリューションの単位でパラメータを縮尺したreal値を返します。 シミュレーションのレゾリューションが10ピコ秒である場合、to_real(1 ns)は100.0を返します。

to_time機能は、シミュレーションのレゾリューション単位数として引数を処理し、そのreal値の引数に対する時間値を返します。 シミュレーションのレゾリューションが1ナノ秒に設定した場合、to_time(44.4)が44 nsを返します。

一般的なテストベンチ環境では、to_real とget_resolution の組み合わせが最も有効です。ステミュラスを発生させるためにMATH_REAL パッケージからSIN関数を使用したいとします。この関数はreal 値がパラメータに必要ですが、VHDL のシステム変数 NOW は現在のシミュレーション時間の時間タイプ値を返します。秒単位でリアルタイム値を計算するためにto_real(NOW)* get_resolution 式を使用するとシミュレーション中でゼロによる除算およびオーバーフロー問題が無いことを保証します。さらにユーザは、シミュレーションのレゾリューション変更時にテストベンチコードの変更が必要ありません。

使用例

このドキュメントの最後に記載されたVHDLコードは、aldec_toolsパッケージからビルトインの言語機能と関数を使用しリアルタイムの変換の違いを示します。コードでは時間値をreal値に変換するために二つの関数を定義しています:

  • 14行目のファンクション rtは、以前に示した除算/タイプキャスト/乗法アプローチを使用しています。

  • 20行目のファンクション realtimeは、結果を計算するためにto_real(t) * get_resolution(tは時間値である)を使用しています。

アーキテクチャ本体のプロセス文は現在のシミュレーション時間を表示後、全ての時間単位からrt およびcファンクションを使用して時間値からreal 値に変換した結果を表示します:1フェムト秒から1時間へ。

コンパイル、および1 psのシミュレーションレゾリューションでシミュレーション(設定するために Design Settings ダイアログ、またはasimコマンドに-tスイッチを使用)した場合、コードは次の様な結果が得られます:

# KERNEL: Current resolution of simulation in seconds is: 1.000000e-012
# KERNEL: For time: 0 ns
# KERNEL: VHDL time->real: 0.000000e+000? ALDEC time->real: 0.000000e+000
# KERNEL: For time: 0.001 ns
# KERNEL: VHDL time->real: 1.000000e-012? ALDEC time->real: 1.000000e-012
# KERNEL: For time: 1 ns
# KERNEL: VHDL time->real: 1.000000e-009? ALDEC time->real: 1.000000e-009
# KERNEL: For time: 1000 ns
# KERNEL: VHDL time->real: 1.000000e-006? ALDEC time->real: 1.000000e-006
# KERNEL: For time: 1000000 ns
# KERNEL: VHDL time->real: 1.000000e-003? ALDEC time->real: 1.000000e-003
# KERNEL: For time: 1000000000 ns
# KERNEL: VHDL time->real: -7.273800e-004? ALDEC time->real: 1.000000e+000
# KERNEL: For time: 60000000000 ns
# KERNEL: VHDL time->real: -6.931251e-004? ALDEC time->real: 6.000000e+001
# KERNEL: For time: 3600000000000 ns
# KERNEL: VHDL time->real: 1.362166e-003? ALDEC time->real: 3.600000e+003

ファンクション rt の変換結果は、時間単位での時間値の除算中のオーバーフローで不正確な秒、分、時間であることに注意してください。ファンクション realtimeは、すべての範囲で正しい結果(1フェムト秒の引数が1ピコ秒のレゾリューションで0に丸められます。そのため変換結果0.0は正しいです)が生成されています。

もし、コードの10行目のsimres を1 fs、11行目のresreal を1.0e-15 に変換し、再コンパイルと1 fsでシミュレーションを実行した場合、フェムト秒が1.0e-15に切り替えたことに気付きますが、ファンクション にはミリ秒、および巨大なタイムユニットに関する問題があります。

コードを変更せずにシミュレーションレゾリューションを1ナノ秒に変更した場合、下記を受信します:

# KERNEL: Current resolution of simulation in seconds is: 1.000000e-009
# KERNEL: For time: 0 ns
# RUNTIME: Fatal Error: RUNTIME_0058 timetests.vhd (16): Division by zero.
# KERNEL: Time: 0 ns, Iteration: 0, TOP instance, Process: tsttm.
# KERNEL: stopped at delta: 0 at time 0 ns.

シミュレーションレゾリューションがその値よりも大きい場合、エラーは16行目simres の除算が0に丸められたことによって引き起こされます。

結論

時間の計算のためのaldec_toolsパッケージを使用することは、時間値のすべての範囲のための時間変換の正しい結果を保証し、シミュレーションレゾリューション変更によるコードへの影響を防ぎます。

timetest.vhd のリスト:

library aldec;
use aldec.aldec_tools.all;
use STD.TEXTIO.all;

entity timetests is
	
end entity timetests;

architecture behavior of timetests is
	
	-- constants used inside function 'rt'
	constant simres : time := 1 ps; -- simulation resolution (time)
	constant resreal : real := 1.0e-12; -- simulation resolution (real)
	
	-- returns real value of time parameter using pure VHDL
	function rt(t : time) return real is
	begin
		return real(t/simres) * resreal;
	end;
	
	-- returns real value of time parameter using 'aldec_tools' package
	function realtime (t : time) return real is
	begin
		return to_real(t) * get_resolution;
	end;
	
	-- prints time parameter and its real value obtained in two ways:
	-- via 'rt' function and 'realtime' function
	procedure printreals(t : in time) is
		variable lb : line;
	begin
		write(lb, "For time: ");
		write(lb, t);
		writeline(output, lb);
		write(lb, "VHDL time->real: ");
		write(lb, rt(t));
		write(lb, "? ALDEC time->real: ");
		write(lb, realtime(t));
		writeline(output, lb);
	end;
	
	-- prints current simulation resolution reported by the simulator
	procedure greeting is
		variable lb : line;
	begin
		write(lb, "Current resolution of simulation in seconds is: ");
		write(lb, get_resolution);
		writeline(output, lb);
	end;
	
begin
	tsttm:process
	begin
		greeting;
		printreals(1 fs);
		printreals(1 ps);
		printreals(1 ns);
		printreals(1 us);
		printreals(1 ms);
		printreals(1 sec);
		printreals(1 min);
		printreals(1 hr);
		wait;
	end process;
	
end architecture behavior;
Ask Us a Question
x

Ask Us a Question

x
Captcha ImageReload Captcha
Incorrect data entered.
Thank you! Your question has been submitted. Please allow 1-3 business days for someone to respond to your question.
Internal error occurred. Your question was not submitted. Please contact us using Feedback form.