定期的にLEDオンオフの繰り返し
ここでは、1秒おきにLEDのオンオフを繰り返す事例の紹介。用いるボードおよび開発環境は、すべてその1と同じである。
ピンアサイン
ピンの確認
時間を扱うため、用いるボードのクロックピンを確認する。回路図によると、
50MHzのクロックはF13ピンに割り当てられている(LED0はL13ピン)。
QuartusでのPin Planner
VHDLコード
まずは不適切な例+α
下記コードは、アルゴリズムとしては問題ない。
library ieee;
use ieee.std_logic_1164.all;
entity ClkLed is
port (
CLK: in std_logic;
LED: out std_logic);
end ClKLed;
architecture RTL of ClkLed is
constant CYCLE : integer := 50000000; -- ①
signal CNT: integer range 0 to CYCLE-1;
begin
process (CLK)
begin
if (rising_edge(CLK)) then -- ②
if (CNT = CYCLE-1) then -- ③
CNT <= 0;
LED <= '0'; -- 点灯
else
CNT <= CNT+1;
LED <= '1'; -- 消灯
end if;
end if;
end process;
end RTL;
不適切な理由を説明する前に、少々コードの説明。
- ①で50MHzの設定、クロック(CLK)50M回の繰り返しで1秒となる。
- ②のrising_edge(CLK)、CLKの立ち上がりを検出している。
- ③で「CYCLE」ではなく「CYCLE-1」で比較している理由は、process内で代入した値は、センシティビティリスト内信号に変化があったとき(次のProcess開始時)に更新されるため。(とどこかに書いてあった。)
で、不適切な理由としては、③のTrue処理は、50M回(1秒間)の内の1回しか行われず、点灯を「目で」確認することができないということである。なので、①のCYCLE数を減らせば確認できるはず。「CYCLE=5」(5Hz)のケースでは、次のような点灯状況であり、
「CYCLE=100」(100Hz)のケースでは、次のような点灯状況である。
このように、CYCLE数(繰り返し数)が増えると、LED点灯色が薄くなるのがわかる。
適切に見える例
内部信号(flag)を設け、それをLED信号と結びつけ、CYCLE数が最大値に達する度(1秒毎)に「flag」を反転させることとした。その2で紹介した、同時処理文と順次処理文とを組み合わせている。
library ieee;
use ieee.std_logic_1164.all;
entity ClkLed is
port (
CLK: in std_logic;
LED: out std_logic);
end ClKLed;
architecture RTL of ClkLed is
constant CYCLE : integer := 50000000;
signal CNT: integer range 0 to CYCLE-1;
signal flag: std_logic := '0';
begin
process (CLK) -- ④
begin
if (rising_edge(CLK)) then
if (CNT = CYCLE-1) then
CNT <= 0;
flag <= not flag;
else
CNT <= CNT+1;
end if;
end if;
end process;
LED <= flag; -- ⑤
-- ④と⑤とは同時に処理される
end RTL;
これにより、1秒毎にLEDのオンオフが繰り返されているように見える!(自明なので、写真や動画省略)
なお、
- 内部信号CNTへの代入は、同一Process文内で行わないとエラー
のようだ。
別の例ではあるが、例えば
Error (10028): Can't resolve multiple constant drivers for net "TimerFlag" at ClkLedDelay.vhd(28)
のようなエラーで怒られる。この記事あたりも参考になるかも。
ソフト屋には難しい、、、。だが、少しずつ賢くなっている気がする。でも、ずっと初心者。