VHDLでボタンの長押しと短押しを検出
ボタンの長押しと短押しとをロジック的に実現する。深い意図はなく、何かに役に立つかどうかも考えていない。
環境
その1と同じOdyssey MAX10 FPGA Eval KitおよびQuartus利用。
サンプル
長押しと短押しとで、異なるLEDを用いて、押下状況を把握する。ここでは、2秒以上押された時、長押しとした。
ソースコード
LongPush.vhd
library ieee;
use ieee.std_logic_1164.all;
entity LongPush is
port (
CLK, BTN : in std_logic;
LED0, LED1 : out std_logic);
end;
architecture RTL of LongPush is
constant CYCLE : integer := 2*50000000; -- 2 seconds (50MHz) -- ①
signal CNT : integer range 0 to CYCLE-1 := 0; -- ②
signal TWOSEC : integer := 0; -- ③
signal BtnFlag : std_logic := '0'; -- Off -- ④
signal LED: std_logic_vector(1 downto 0) := "11"; -- Off -- ⑤
begin
LED0 <= LED(0); LED1 <= LED(1); -- ⑥
process (BTN, TWOSEC) -- ⑦
begin
-- if (BTN'event and BTN='0') then -- NG -- ⑧
if (BTN='0') then -- Pushed -- ⑨
BtnFlag <= '1'; -- On
LED(0) <= '0'; -- On
if (TWOSEC > 0) then -- Over 2 sec
LED(1) <= '0'; -- On
else
LED(1) <= '1'; -- Off
end if;
else -- Not pushed -- ⑩
BtnFlag <= '0'; -- Off
LED(0) <= '1'; -- Off
LED(1) <= '1'; -- Off
end if;
end process;
process (CLK, BtnFlag) -- ⑪
begin
if (BtnFlag = '1') then -- ⑫
if (rising_edge(CLK)) then
if (CNT = CYCLE-1) then
CNT <= 0;
TWOSEC <= TWOSEC+1;
else
CNT <= CNT+1;
end if;
end if;
else -- ⑬
CNT <= 0;
TWOSEC <= 0;
end if;
end process;
end RTL;
- ①:2秒の定義
- ②:クロック用カウンタ
- ③:2秒経過フラグ
- ④:ボタンフラグ
- ⑤:LEDフラグ(1:Off, 0:On)
- ⑥、⑦、⑪:同時処理
- ⑥:信号LEDへのLEDフラグ代入
- ⑦:ボタン押下時および2秒経過フラグ変化時の処理
- ⑧:⑨の代わりに用いると文法エラー
- ⑨:ボタン押下時、ボタンフラグOn、LED0 On、2秒経過時にはLED1 On
- ⑩:ボタン非押下時、ボタンフラグOff、LED0およびLED1はOff
- ⑪:クロック変化時およびボタンフラグ変化時の処理
- ⑫:ボタン押下時にクロック毎にカウンタインクリメントおよび2秒経過時に2秒経過フラグOn(インクリメント)
- ⑬:ボタン非押下時、カウンタおよび2秒経過フラグの初期化
ピンアサインメント
コード上のLED0はボード上もLED0にアサインしているが、LED1はボード上ではLED4にアサインしている。