秒カウンタ
LEDを用いて経過時間(秒)を表現する。
環境
その1からずっとOdyssey MAX10 FPGA Eval KitおよびQuartus利用。
具体的には
本Kit(ボード)には7個のLEDがある。それぞれを2進数のビットとして扱い、0-63秒を表現、LED0をLSB、LED7をMSBとする。例えば、スタートから6秒後に、LED1及びLED2を点灯させる(00000110)。スタートはボタン押下で行い、再押下でストップ(リセット)する。
ソースコード
sectest.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all; -- necessary for conv_std_logic_vector
entity SecTest is
port (
CLK, BTN : in std_logic;
LED0, LED1, LED2, LED3, LED4, LED5, LED6, LED7 : out std_logic);
end;
architecture RTL of SecTest is
constant CYCLE : integer := 50000000; -- ①
signal CNT : integer range 0 to CYCLE-1 := 0; -- ②
signal SEC : integer := 0; -- ③
signal BtnFlag : std_logic := '0'; -- ④
signal LED: std_logic_vector(7 downto 0) := "11111111"; -- Off ⑤
begin
LED0 <= LED(0); LED1 <= LED(1); LED2 <= LED(2); LED3 <= LED(3); -- ⑥
LED4 <= LED(4); LED5 <= LED(5); LED6 <= LED(6); LED7 <= LED(7); -- ⑦
process (SEC) -- ⑧
begin
LED <= not conv_std_logic_vector(SEC,8); -- ⑨
end process;
process (BTN) -- ⑩
begin
if (BTN'event and BTN='0') then
--SEC <= 0; -- NG ⑪
BtnFlag <= not BtnFlag; -- ⑫
end if;
end process;
process (CLK) -- ⑬
begin
-- if (BTN'event and BTN='0') then -- NG ⑭
if (BtnFlag = '1') then -- ⑮
if (rising_edge(CLK)) then -- ⑯
if (CNT = CYCLE-1) then -- ⑰
CNT <= 0;
SEC <= SEC+1;
else
CNT <= CNT+1;
end if;
end if;
else -- ⑱
CNT <= 0;
SEC <= 0;
end if;
end process;
end RTL;
- ①:1秒の定義(50MHzクロック)
- ②:クロック用カウンタ
- ③:秒カウンタ
- ④:ボタンフラグ
- ⑤:LEDフラグ配列および初期化(負論理)
- ⑥、⑦、⑧、⑩、⑬:これらは同時に処理される
- ⑥、⑦:LEDフラグをLEDピンに代入
- ⑧、⑨:秒カウンタ(数値)を論理ビット化し、LEDフラグに代入
- ⑩、⑫:ボタン押下状況をボタンフラグに反映('1':押下、'0':未押下)
- ⑮、⑯、⑰:ボタンフラグが'1'のときは、クロックの立ち上がり時に、クロック用カウンタインクリメント、または、1秒経過時に秒カウントインクリメント
- ⑱:ボタンフラグが'0'のときは、カウンタリセット
- ⑪、⑭:(参考:これがあるとVHDL文法エラー)
ピンアサイン
ボタン(BTN)、クロック(CLK)、LEDのピンアサインについては、Odyssey MAX10の回路図を参照。