VHDLでストップウォッチ

# 概要
題名通り、遊びとしてストップウォッチをVHDLで作りました。以下では、実行環境と作成したプログラムを示します。

# 実行環境
次に実行環境を示します。

| Soft and Hard  |       バージョン | 
|:-----------------:|:------------------:|
| VHDL         |            1076-2008 |  
| Quartus Ⅱ   |     9.0        |  
| EDA-002            |         Rev2      | 

VHDLのシミュレーション及び評価ボード書きこみ用途して、Quartus Ⅱを用いました。QuartusがPrimeより古いものを使用している理由としましては、評価ボードにPrimeで書き込めなかったからです。また、評価ボードは有限会社ヒューマンデータのEDA-002を使用しました。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/169342/8a2da99d-6b8d-929e-6e47-d17061f91518.png)


# VHDLコード
以下に作成したコードを示します。作成したストップウォッチでは、小数点第1位から10の桁まで表示します。

```VHDL:stopwatch.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity HIROSE_STOP_WATCH_2 is

    Port(
            CLK          : in std_logic;
            RESET        : in std_logic;
            STOP_SIG     : in std_logic;
            RESTART_SIG  : in std_logic;
            LED          : out std_logic_vector( 7 downto 0 );
            Position_LED : out std_logic_vector( 3 downto 0 )
            );

end HIROSE_STOP_WATCH_2;

architecture Behavioral of HIROSE_STOP_WATCH_2 is

    signal DD : std_logic_vector(15 downto 0 );
    signal CE : std_logic;
    signal inter_LED : std_logic_vector( 7 downto 0);
    signal decimal_under_two : std_logic_vector( 3 downto 0);
    signal decimal_under_two_flg : std_logic;
    signal decimal_under_one : std_logic_vector( 3 downto 0);
    signal decimal_under_one_flg : std_logic;
    signal WORK : std_logic_vector(3 downto 0);
    signal unit_flg : std_logic;
    signal ten_digit : std_logic_vector( 3 downto 0 );
    signal ten_digit_flg : std_logic;
    signal select_SegLED : std_logic_vector( 2 downto 0);
    signal Division_Hz : std_logic_vector( 9 downto 0 );
    signal STOP_flg : std_logic;
    signal START_flg : std_logic;
    
begin

process(CLK)
begin
    if (CLK'event and CLK='1') then
        Division_Hz <= Division_Hz + '1';
        if(Division_Hz = "1111101000") then
             select_SegLED <= select_SegLED + '1';
             if(select_SegLED = "001") then
                decimal_under_two_flg <= '1';
                decimal_under_one_flg <= '0';
                unit_flg <= '0';
                ten_digit_flg <= '0';
             elsif(select_SegLED = "010") then
                decimal_under_two_flg <= '0';
                decimal_under_one_flg <= '1';
                unit_flg <= '0';
                ten_digit_flg <= '0';
             elsif(select_SegLED = "011") then
                 decimal_under_two_flg <= '0';
                decimal_under_one_flg <= '0';
                unit_flg <= '1';
                ten_digit_flg <= '0';
             elsif(select_SegLED = "100") then
                 decimal_under_two_flg <= '0';
                decimal_under_one_flg <= '0';
                unit_flg <= '0';
                ten_digit_flg <= '1';
                select_SegLED <= "000";
             end if;
             Division_Hz <= "0000000000";
        end if;
    end if;
end process;

process(CLK)
begin
    if (CLK'event and CLK='1') then

        if(RESTART_SIG = '0') then
            START_flg <= '1';
            STOP_flg <= '0';
        end if;
-- 
        if(START_flg = '1') then
            DD <= DD + '1';
        end if;
-- 
        if(STOP_SIG = '0') then
            STOP_flg <= '1';
            START_flg <= '0';
        end if;

        if(DD = "1110101001100000") then
            DD <= "0000000000000000";
        end if;
    end if;    
end process;

process(CLK)
begin

  if(DD = "1110101001100000") then
        CE <= '1';
    else
        CE <= '0';
    end if;
    
end process;

process(CLK)
begin

    if(CE'event and CE='1') then

        if(RESET = '0') then
            decimal_under_two <= "0000";
            decimal_under_one <= "0000";
            WORK <= "0000";
            ten_digit <= "0000";
        end if;

        if(STOP_flg = '0' and START_flg = '1') then
            decimal_under_two  <= decimal_under_two + '1';
            if(decimal_under_two = "1001") then
                decimal_under_two <= "0000";
                decimal_under_one  <= decimal_under_one + '1';

                if(decimal_under_one = "1001") then
                    decimal_under_one <= "0000";
                    WORK <= WORK + '1';
                    if(WORK = "1001") then
                        WORK <= "0000";
                        ten_digit <= ten_digit + '1';
                    
                         if(ten_digit = "1001") then
                             ten_digit <= "0000";
                          end if;
                    end if;
                end if;
            end if;
        end if;
    end if;
end process;

process(CLK)
begin
    if( decimal_under_two_flg = '1') then
        Position_LED <= "ZZZ0";
        case decimal_under_two is
            when "0000" => LED <= "11000000";
            when "0001" => LED <= "11111001";
            when "0010" => LED <= "10100100";
            when "0011" => LED <= "10110000";
            when "0100" => LED <= "10011001";
            when "0101" => LED <= "10010010";
            when "0110" => LED <= "10000010";
            when "0111" => LED <= "11011000";
            when "1000" => LED <= "10000000";
            when "1001" => LED <= "10010000";
            when others => LED <= null;
        end case;
    elsif( decimal_under_one_flg = '1') then
        Position_LED <= "ZZ0Z";
        case decimal_under_one is
            when "0000" => LED <= "11000000";
            when "0001" => LED <= "11111001";
            when "0010" => LED <= "10100100";
            when "0011" => LED <= "10110000";
            when "0100" => LED <= "10011001";
            when "0101" => LED <= "10010010";
            when "0110" => LED <= "10000010";
            when "0111" => LED <= "11011000";
            when "1000" => LED <= "10000000";
            when "1001" => LED <= "10010000";
            when others => LED <= null;
        end case;
    elsif( unit_flg = '1') then
        Position_LED <= "Z0ZZ";
        case WORK is
            when "0000" => LED <= "01000000";
            when "0001" => LED <= "01111001";
            when "0010" => LED <= "00100100";
            when "0011" => LED <= "00110000";
            when "0100" => LED <= "00011001";
            when "0101" => LED <= "00010010";
            when "0110" => LED <= "00000010";
            when "0111" => LED <= "01011000";
            when "1000" => LED <= "00000000";
            when "1001" => LED <= "00010000";
            when others => LED <= null;
        end case;
    elsif( ten_digit_flg = '1') then
        Position_LED <= "0ZZZ";
        case ten_digit is
            when "0000" => LED <= "11000000";
            when "0001" => LED <= "11111001";
            when "0010" => LED <= "10100100";
            when "0011" => LED <= "10110000";
            when "0100" => LED <= "10011001";
            when "0101" => LED <= "10010010";
            when "0110" => LED <= "10000010";
            when "0111" => LED <= "11011000";
            when "1000" => LED <= "10000000";
            when "1001" => LED <= "10010000";
            when others => LED <= null;
        end case;
    end if;
end process;


end Behavioral;
```

ピン配置は、ご自由にしてください。7segとPushボタンを使っています。


# まとめ
パワーエレクトロニクスしている某企業のエンジニアの方いわく、if文を乱用するのはセンスが無いそうです。。。
もっと勉強したいと思います。また、間違っているところや、追加したほうがいい、こういう書き方の方がいいよ！という箇所がありましたら、お教え頂けるととても嬉しいです。