ずっとFPGA初心者（その９：イベント発生後の遅延の繰り返し）

# イベント発生後の遅延の繰り返し
今回のお題は、イベント発生後の遅延の繰り返しであり、[その７](https://qiita.com/infinite1oop/items/33f6659436dfb7f10f10)の派生。用いるボードおよび開発環境は、すべて[その１](https://qiita.com/infinite1oop/items/4b0f03b97ed859fbd954)と同じである。

## 具体的には
ボタン押下2秒後に点灯、ボタン押下2秒後に消灯、、、の繰り返しである。

## VHDLコード
```vhdl:ClkLedDelayOnOff.vhd
entity ClkLedDelayOnOff is
	generic (CYCLE : integer := 2*50000000);  -- ①
	port (
		BTN:	in std_logic;
		CLK:	in std_logic;
		LED: 	out std_logic);
end ClkLedDelayOnOff;

architecture RTL of ClkLedDelayOnOff is
signal CNT: integer range 0 to CYCLE-1 := 0;   -- ②
signal CNT2: integer range 0 to CYCLE-1 := 0;  -- ③
signal TimerFlag: std_logic := '0';            -- ④
signal LedFlag: std_logic := '1'; -- Off
	
begin
	process (BTN)	-- for Button  -- ⑤
	begin
		if (BTN'event and BTN='0') then	-- Pushed
			TimerFlag <= not TimerFlag;  -- ⑥
		end if;
	end process;
	
	-- The status does not change when buttoned before counter expires
	
	process (CLK)	-- for Clock  -- ⑦
	begin	
		if (rising_edge(CLK)) then
			if (TimerFlag='1') then  -- ⑧
				CNT2 <= 0;
				if (CNT = CYCLE-1) then
					LedFlag <= '0'; -- On				
					CNT <= 0;
				else
					CNT <= CNT+1;
				end if;
			else  -- TimerFlag='0'  -- ⑨
				CNT <= 0;
				if (CNT2 = CYCLE-1) then
					LedFlag <= '1'; -- Off				
					CNT2 <= 0;
				else
					CNT2 <= CNT2+1;
				end if;
			end if;
		end if;
	end process;
	
	LED <= LedFlag;  -- ⑩
	
end RTL;
```

- ①：2秒の定義（2 x 50MHz）
- ②：LED Onカウンタ（カウンタ満了後、LED On）
- ③：LED Offカウンタ（カウンタ満了後、LED Off）
- ④：動作しているカウンタ（'0'：Offカウンタ、'1'：Onカウンタ）
- ⑤、⑦、⑩：これらは同時に処理される
- ⑥：ボタン押下時に、動作するカウンタを反転させる
- ⑧：Onカウンタ動作中の処理（カウンタインクリメント、カウンタ満了後にLED On、別カウンタ初期化）
- ⑨：Offカウンタ動作中の処理（カウンタインクリメント、カウンタ満了後にLED Off、別カウンタ初期化）

ただし、ボタンを連続押下、2秒以内に複数回押下などのハンドリングは考慮していない。

## シミュレーション
たまには、シミュレーション実施。

### コード
```vhdl:testsim.vhd
library ieee;
use ieee.std_logic_1164.all;

entity testbench is
end testbench;

architecture sim of testbench is 

constant t: time := 1 ps;

signal	BTN: std_logic;
signal	CLK: std_logic;
signal	LED: std_logic;

component ClkLedDelayOnOff
  generic (CYCLE : integer := 2*50000000);
  port (
    BTN: in std_logic;
    CLK: in std_logic;
    LED: out std_logic);
end component;

begin 
  u1 : ClkLedDelayOnOff
    generic map (CYCLE => 2)     -- ⑪
    port map (BTN => BTN, CLK => CLK, LED => LED);
  
  process begin
    BTN <= '1';
    CLK <= '0'; wait for t;
    BTN <= '0';
    CLK <= '1'; wait for t;
    for N in 1 to 2 loop
      CLK <= '0'; wait for t;
      CLK <= '1'; wait for t;
    end loop;

    BTN <= '1';
    CLK <= '0'; wait for t;
    BTN <= '0';
    CLK <= '1'; wait for t;
    for N in 1 to 3 loop
      CLK <= '0'; wait for t;
      CLK <= '1'; wait for t;
    end loop;

    BTN <= '1';
    CLK <= '0'; wait for t;
    BTN <= '0';
    CLK <= '1'; wait for t;

    for N in 1 to 2 loop
      CLK <= '0'; wait for t;
      CLK <= '1'; wait for t;
    end loop;
    BTN <= '1';

    for N in 1 to 5 loop
      CLK <= '0'; wait for t;
      CLK <= '1'; wait for t;
    end loop;

    wait;
  end process;
end sim;

```

シミュレーションで、CLKを2秒分（100万サイクル）実行するのは大変なので、⑪にて2回（サイクル）とした。こういったときに、「generic map」記述は便利らしい（とどこかに書いてあった）。

### 結果
![Simulation結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/2d480992-5838-cc38-d7fe-d30ddbcee0c2.png)
ボタン押下（BTN:'1'->'0'）2サイクル（CLK）後に、LEDが変化していることがわかる。