VHDL でタイマーを作成する方法
以前のチュートリアルでは、wait for
を使用しました シミュレーションで時間を遅らせるステートメント。しかし、生産モジュールはどうですか? wait for
ステートメントはそのために使用できません。回路内の電子に特定の時間一時停止するように指示することはできないため、これはシミュレーションでのみ機能します。では、設計モジュールで時間を追跡するにはどうすればよいでしょうか?
答えは単純にクロック サイクルをカウントすることです。すべてのデジタル設計は、既知の固定周波数で発振するクロック信号にアクセスできます。したがって、クロック周波数が 100 MHz であることがわかっている場合、1 億クロック サイクルを数えることで 1 秒を測定できます。
このブログ投稿は、基本的な VHDL チュートリアル シリーズの一部です。
VHDL で秒数をカウントするには、経過したクロック周期の数をカウントするカウンターを実装できます。このカウンターがクロック周波数の値、たとえば 1 億に達すると、1 秒が経過したことがわかり、別のカウンターをインクリメントする時が来ました。これを秒カウンターと呼びましょう。
分を数えるには、60 秒が経過するとインクリメントする別の Minutes カウンターを実装できます。同様に、時間をカウントするために Hours カウンタを作成し、60 分が経過すると増分します。
日、週、月のカウントについても、このアプローチを続けることができます。基礎となるテクノロジーで利用可能な物理リソースと、クロック周波数に対するカウンターの長さによって制限されます。
カウンターの長さが長くなると、明らかにより多くのリソースを消費します。しかし、一連のイベントが長くなるため、反応も遅くなります。
エクササイズ
このビデオ チュートリアルでは、VHDL でタイマー モジュールを作成する方法を学習します。
タイマー テストベンチ の最終的なコード :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T18_TimerTb is end entity; architecture sim of T18_TimerTb is -- We're slowing down the clock to speed up simulation time constant ClockFrequencyHz : integer := 10; -- 10 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal Seconds : integer; signal Minutes : integer; signal Hours : integer; begin -- The Device Under Test (DUT) i_Timer : entity work.T18_Timer(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, Seconds => Seconds, Minutes => Minutes, Hours => Hours); -- Process for generating the clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); -- Take the DUT out of reset nRst <= '1'; wait; end process; end architecture;
タイマー モジュールの最終的なコード :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T18_Timer is generic(ClockFrequencyHz : integer); port( Clk : in std_logic; nRst : in std_logic; -- Negative reset Seconds : inout integer; Minutes : inout integer; Hours : inout integer); end entity; architecture rtl of T18_Timer is -- Signal for counting clock periods signal Ticks : integer; begin process(Clk) is begin if rising_edge(Clk) then -- If the negative reset signal is active if nRst = '0' then Ticks <= 0; Seconds <= 0; Minutes <= 0; Hours <= 0; else -- True once every second if Ticks = ClockFrequencyHz - 1 then Ticks <= 0; -- True once every minute if Seconds = 59 then Seconds <= 0; -- True once every hour if Minutes = 59 then Minutes <= 0; -- True once a day if Hours = 23 then Hours <= 0; else Hours <= Hours + 1; end if; else Minutes <= Minutes + 1; end if; else Seconds <= Seconds + 1; end if; else Ticks <= Ticks + 1; end if; end if; end if; end process; end architecture;
Seconds
を拡大した波形 シグナル:
Minutes
を拡大した波形 シグナル:
Hours
を拡大した波形 シグナル:
分析
50 時間のシミュレーションを実行するために、コマンド run 50 hr
を指定しました ModelSim コンソールで。 50 時間というのは非常に長いシミュレーションなので、テストベンチのクロック周波数を 10 Hz に下げる必要がありました。 100 MHz のままにしていたら、シミュレーションに何日もかかっていたでしょう。このような調整は、設計をシミュレートできるようにするために必要になる場合があります。
波形のタイムラインを右クリックし、[グリッド、タイムライン、カーソル コントロール] を選択しました。時間単位を ns から秒、分、時間に変更すると、タイマーが実際にリアルタイムで動作していることがわかりました。
シミュレーションの開始時にモジュールがリセットされるため、タイマー時間はシミュレーション時間からわずかにずれています。これは、タイムラインの 60 秒マークが Seconds 信号が 0 に戻る少し前にある最初の波形で確認できます。
シミュレーションでは、カウンター値はクロックの立ち上がりエッジでゼロ時間で更新されることに注意してください。現実の世界では、カウンターの値がカウンターの最初のビットから最後のビットまで伝播するのに時間がかかります。カウンターの長さを長くすると、クロック周期の利用可能な時間が消費されます。
カスケードされたすべてのカウンターの累積長が長くなりすぎると、コンパイル後の配置配線ステップでエラーが発生します。クロック周期全体を消費する前にカウンターを実装できる時間は、FPGA または ASIC アーキテクチャとクロック速度によって異なります。
クロック速度が上がるということは、カウンター チェーンが長くなることを意味します。また、クロック周期の時間が短くなるため、カウンター チェーンが完了するまでの時間がさらに短縮されます。
テイクアウト
- VHDL モジュールでの測定時間は、クロック サイクルをカウントすることで達成されます
- テストベンチでクロック周波数を下げると、シミュレーションが高速化されます
次のチュートリアルに進む »
VHDL