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