記事一覧

野球ゲームをつくる ~ 12.野球ゲームの完成

野球ゲームをつくる ~ 12.野球ゲームの完成

これまで、モジュールを作成してきましたが、つなぎあわして野球ゲームを完成させます。

まず、ボードのInput/Outputをおさらいします。
野球ゲームをつくる ~ 1.仕様の作成 にある仕様を元にボードの配置は下図のとおりです。

ファイル 107-1.jpg

ピン配置は下図です。

ファイル 107-2.jpg

回路図(RTL)は下図です。

ファイル 107-3.jpg

baseball_game.vhd

-- BASEBALL GAME TOP Entity
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity BASEBALL_GAME is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        STARTSTOP_SW: in  std_logic;
        INING_SW    : in  std_logic;
        MODE_SW     : in  std_logic;
        LED_TEAM1   : out std_logic;
        LED_TEAM2   : out std_logic;
        LED_ASSIST  : out std_logic;
        LED_MODE    : out std_logic;
        LED_BASE    : out std_logic_vector(2 downto 0);
        LED_OUT     : out std_logic_vector(1 downto 0);
        LED_SCORE1  : out std_logic_vector(7 downto 1);
        LED_SCORE2  : out std_logic_vector(7 downto 1);
        LED_BATTING_OR_INING    : out std_logic_vector(7 downto 1)
    );
end BASEBALL_GAME;

architecture RTL of BASEBALL_GAME is
    
component DIVIDER
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;    
        DIV_CLK_2HZ : out std_logic;
        DIV_CLK_8Hz : out std_logic;
        DIV_CLK_16Hz: out std_logic;        
        DIV_CLK_32HZ: out std_logic
    );
end component;

component CHATTERING_CUT
    port(
        SW   : in  std_logic;
        CLK  : in  std_logic;
        RESET: in  std_logic;
        COUT : out std_logic
    );
end component;

component TOGLE
    port(
        TIN     : in  std_logic;
        RESET   : in  std_logic;
        TOUT    : out std_logic
    );
end component;

component BATTING_ROULLET
    port(
        CLK      : in  std_logic;
        RESET    : in  std_logic;
        STARTSTOP: in  std_logic;
        MODE     : in  std_logic;
        BATTING  : out std_logic_vector(2 downto 0);
        ASSIST   : out std_logic
    );
end component;

component BASE
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        SELECTOR: in  std_logic;
        CHANGE  : in  std_logic;
        BATTING : in  std_logic_vector(2 downto 0);
        RUNNER  : out std_logic_vector(2 downto 0);
        SCORE1  : out std_logic_vector(3 downto 0);
        SCORE2  : out std_logic_vector(3 downto 0);
        TEAM1   : out std_logic;
        TEAM2   : out std_logic;
        BLINK   : out std_logic
    );
end component;

component BLINK 
    port(
        CLK   : in  std_logic;
        ENABLE: in  std_logic;
        BLINK : out  std_logic
    );
end component;

component OUT_COUNTER
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        BATTING : in  std_logic_vector(2 downto 0);
        OUT_LED : out std_logic_vector(1 downto 0);
        CHANGE  : out std_logic
    );
end component;

component INING_COUNTER
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        COUNT   : out std_logic_vector(3 downto 0)
    );
end component;

component LUCKY7
    port(
        RESET       : in  std_logic;
        INING_COUNT : in std_logic_vector(3 downto 0);
        LED_ASSIST  : out std_logic
    );
end component;

component BATTING_DECODER
    port(
        RESET       : in  std_logic;
        COUNTER     : in  std_logic_vector(2 downto 0);
        LED         : out std_logic_vector(7 downto 1)
    );
end component;

component SCORE_DECODER
    port(
        DIV_CLK : in  std_logic;
        ENABLE  : in  std_logic;
        RESET   : in  std_logic;
        COUNTER : in  std_logic_vector(3 downto 0);
        LED     : out std_logic_vector(7 downto 1)
    );
end component;

component INING_DECODER
    port(
        RESET       : in  std_logic;
        COUNTER     : in  std_logic_vector(3 downto 0);
        LED         : out std_logic_vector(7 downto 1)
    );
end component;

signal CLK2HZ           : std_logic;
signal CLK8HZ           : std_logic;
signal CLK16HZ          : std_logic;
signal CLK32HZ          : std_logic;
signal STARTSTOP_CUT    : std_logic;
signal MODE_CUT         : std_logic;
signal STARTSTOP_TMP    : std_logic;
signal MODE_TMP         : std_logic;
signal BATTING_TMP      : std_logic_vector(2 downto 0);
signal SCORE1_TMP       : std_logic_vector(3 downto 0);
signal SCORE2_TMP       : std_logic_vector(3 downto 0);
signal CHANGE_TMP       : std_logic;
signal TOGLE_TEAM_TMP   : std_logic;
signal RESET_OR_CHANGE  : std_logic;
signal SELECT1_TMP      : std_logic;
signal SELECT2_TMP      : std_logic;
signal INING_COUNT_TMP  : std_logic_vector(3 downto 0);
signal INING_LED_OUT    : std_logic_vector(7 downto 1);
signal BATTING_LED_OUT  : std_logic_vector(7 downto 1);
signal BATTING_ASSIST   : std_logic;
signal LUCKY7_ASSIST    : std_logic;
signal BLINK_CLK        : std_logic;
signal BLINK_ENABLE     : std_logic;
signal BLINK_TMP        : std_logic;

begin
    
    RESET_OR_CHANGE <= RESET and CHANGE_TMP;
    SELECT1_TMP <= not TOGLE_TEAM_TMP;
    SELECT2_TMP <= TOGLE_TEAM_TMP;
    BLINK_ENABLE <= BLINK_TMP and not STARTSTOP_TMP;
    LED_ASSIST <= not (BATTING_ASSIST and LUCKY7_ASSIST);

    process(INING_SW,INING_LED_OUT,BATTING_LED_OUT)
    begin
        if (INING_SW = '0') then
            LED_BATTING_OR_INING <= INING_LED_OUT;
        else
            LED_BATTING_OR_INING <= BATTING_LED_OUT;
        end if;
    end process;
        
    process(RESET,MODE_TMP)
    begin
        if (RESET = '0') then
            LED_MODE <= '1';
        elsif (MODE_TMP = '1') then
            LED_MODE <= '0';
        else
            LED_MODE <= '1';
        end if;
    end process;
    
    CLK_DIVIDER :DIVIDER            port map (CLK,RESET,open,CLK8HZ,open,CLK32HZ);
    STARTSTOP_CT:CHATTERING_CUT     port map (STARTSTOP_SW,CLK,RESET,STARTSTOP_CUT);
    MODE_CT     :CHATTERING_CUT     port map (MODE_SW,CLK,RESET,MODE_CUT);  
    STARTSTOP_T :TOGLE              port map (STARTSTOP_CUT,RESET,STARTSTOP_TMP);
    MODE_T      :TOGLE              port map (MODE_CUT,RESET,MODE_TMP); 
    INING_T     :TOGLE              port map (CHANGE_TMP,RESET,TOGLE_TEAM_TMP);
    ROULLET_UNIT:BATTING_ROULLET    port map (CLK32HZ,RESET_OR_CHANGE,STARTSTOP_TMP,MODE_TMP,BATTING_TMP,BATTING_ASSIST);
    BASE_UNIT   :BASE               port map (STARTSTOP_TMP,RESET,TOGLE_TEAM_TMP,CHANGE_TMP,BATTING_TMP,LED_BASE,SCORE1_TMP,SCORE2_TMP,LED_TEAM1,LED_TEAM2,BLINK_TMP);
    BLINK_UNIT  :BLINK              port map (CLK8Hz,BLINK_ENABLE,BLINK_CLK);
    LUCKY7_UNIT :LUCKY7             port map (RESET,INING_COUNT_TMP,LUCKY7_ASSIST);
    COUNTER1    :OUT_COUNTER        port map (STARTSTOP_TMP,RESET_OR_CHANGE,BATTING_TMP,LED_OUT,CHANGE_TMP);
    COUNTER2    :INING_COUNTER      port map (TOGLE_TEAM_TMP,RESET,INING_COUNT_TMP);
    DECORDER1   :BATTING_DECODER    port map (RESET,BATTING_TMP,BATTING_LED_OUT); 
    DECORDER2   :SCORE_DECODER      port map (BLINK_CLK,SELECT1_TMP,RESET,SCORE1_TMP,LED_SCORE1);
    DECORDER3   :SCORE_DECODER      port map (BLINK_CLK,SELECT2_TMP,RESET,SCORE2_TMP,LED_SCORE2);
    DECORDER4   :INING_DECODER      port map (RESET,INING_COUNT_TMP,INING_LED_OUT);
end RTL;

野球ゲームをつくる ~ 11.ラッキー7の攻撃

ラッキー7の攻撃の時には、ホームランのタイミングでアシスト用のLEDが点滅するようにしてみます。*1

lucky7.vhd

-- Lucky7
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity LUCKY7 is
    port(
        RESET       : in  std_logic;
        INING_COUNT : in std_logic_vector(3 downto 0);
        LED_ASSIST  : out std_logic
    );
end LUCKY7;

architecture RTL of LUCKY7 is

begin

    process(RESET,INING_COUNT)
    begin
        if (RESET = '0') then
            LED_ASSIST <= '0';
        elsif (INING_COUNT = "0111") then
            LED_ASSIST <= '1';
        else
            LED_ASSIST <= '0';
        end if;
    end process;
    
end RTL;

*1:ズルと言えばそれまでですが、ルーレットは早いので、目押しはまず無理です。

野球ゲームをつくる ~ 10.進塁ベース・得点追加の作成

ヒット、フォアボール、ホームランによる塁の状態の変化と得点の追加を作成します。

この野球ゲームの中で、重要なパーツの1つです。

項目が多いので、入力信号・出力信号と分けて考察します。

まず、入力信号です。

1.打者の結果:BATTING
打者の結果によって、塁の状態と得点は変化します。
例えば、ランナー2塁で1塁打が出れば、ランナー1、3塁となり、
2塁打がでれば、ランナー2塁となり1点追加になります。
ということで、状態遷移(ステートマシン)を使用します。
全ての塁の状態と打者の結果の組合せがあるので、組合せのもれがないようにしないといけません。

アウトカウントは 野球ゲームをつくる ~ 6.アウトカウントとチェンジ
でカウントしています。

2.イニングの表裏:SELECTOR
先攻・後攻どちらの攻撃なのか、得点時に必要となります。
得点が相手チームに追加されては困りますよね。

3.チェンジ:CHANGE
チェンジになれば、ランナーはいなくなり、イニングが進みます。
リセットととは違います。

次に出力信号です。

1.塁の状態:RUNNER
2.先攻・後攻の各得点:SCORE1 SCORE2
の2つで充分ですが、

7SegLEDの小数点を
3.どちらの攻撃:TEAM1 TEAM2
かの表示に使用します。

また、得点が入った時にわかりやすいように
4.得点時に点滅用信号:BLINK
を出力します。

野球ゲームをつくる ~ 9.得点表示の点滅 が点滅用モジュールです。

base.vhd

-- BASE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BASE is
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        SELECTOR: in  std_logic;
        CHANGE  : in  std_logic;
        BATTING : in  std_logic_vector(2 downto 0);
        RUNNER  : out std_logic_vector(2 downto 0);
        SCORE1  : out std_logic_vector(3 downto 0);
        SCORE2  : out std_logic_vector(3 downto 0);
        TEAM1   : out std_logic;
        TEAM2   : out std_logic;
        BLINK   : out std_logic
    );
end BASE;

architecture RTL of BASE is
type STATE_TYPE is (S0,S1,S2,S3,S12,S13,S23,S123);
signal STATE    : STATE_TYPE;
signal SCORE1_TMP   : std_logic_vector(3 downto 0);
signal SCORE2_TMP   : std_logic_vector(3 downto 0);
signal RUNNER_TMP   : std_logic_vector(2 downto 0);

begin
    process (CLK,RESET,CHANGE)
    begin
        if (RESET = '0') then
            STATE <= S0;
            SCORE1_TMP <= "0000";
            SCORE2_TMP <= "0000";
        elsif (CHANGE = '0') then    --- 0:3OUTChange
            STATE <= S0;
        elsif (CLK'event and CLK = '0') then
            case (STATE) is
                when S0 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S1;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S2;
                            BLINK <= '0';
                        when "011" =>
                            STATE <= S3;
                            BLINK <= '0';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S1;
                            BLINK <= '0';
                        when others =>
                            STATE <= S0;
                            BLINK <= '0';
                    end case;
                when S1 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S12;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S23;
                            BLINK <= '0';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S12;
                            BLINK <= '0';
                        when others =>
                            STATE <= S1;
                            BLINK <= '0';
                    end case;
                when S2 =>
                    case (BATTING) is
                        when "001" => 
                            STATE <= S13;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S2;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S12;
                            BLINK <= '0';
                        when others =>
                            STATE <= S2;
                            BLINK <= '0';
                    end case;
                when S3 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S1;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S2;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S13;
                            BLINK <= '0';
                        when others =>
                            STATE <= S3;
                            BLINK <= '0';
                    end case;
                when S12 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S23;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when others =>
                            STATE <= S12;
                            BLINK <= '0';
                    end case;
                when S13 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S12;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S23;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when others =>
                            STATE <= S13;
                            BLINK <= '0';
                    end case;
                when S23 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S13;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S2;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when others =>
                            STATE <= S23;
                            BLINK <= '0';
                    end case;
                when S123 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S123;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S23;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 4;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 4;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when others =>
                            STATE <= S123;
                            BLINK <= '0';
                    end case;
                when others =>
                    STATE <= S0;
                    BLINK <= '0';
            end case;
        else
        null;
        end if;
    end process;
        
    SCORE1 <= SCORE1_TMP;
    SCORE2 <= SCORE2_TMP;
        
    process(STATE)
    begin
        case (STATE) is
            when S0   => RUNNER_TMP <= "000";
            when S1   => RUNNER_TMP <= "001";
            when S2   => RUNNER_TMP <= "010";
            when S3   => RUNNER_TMP <= "100";
            when S12  => RUNNER_TMP <= "011";
            when S13  => RUNNER_TMP <= "101";
            when S23  => RUNNER_TMP <= "110";
            when S123 => RUNNER_TMP <= "111";
            when others => RUNNER_TMP <= "000";
        end case;
    end process;
    
    RUNNER <= not RUNNER_TMP

    process(RESET,SELECTOR)
    begin
        if (RESET = '0') then
            TEAM1 <= '1';
            TEAM2 <= '1';
        elsif (SELECTOR = '0') then
            TEAM1 <= '0';
            TEAM2 <= '1';
        else
            TEAM1 <= '1';
            TEAM2 <= '0';
        end if;
    end process;
    
    end RTL;

補足説明ですが、

type STATE_TYPE is (S0,S1,S2,S3,S12,S13,S23,S123);

が塁の状態で、
S0:ランナーなし
S1:ランナー1塁
S2:ランナー2塁
・・・・・・
S123:ランナー満塁
です。
省略したものは何になるか想像できますよね。

で、出力信号は下記にしています。
負論理なので、0:点灯 1:消灯です。*1
最上位ビットから3塁、2塁、1塁です。

    process(STATE)
    begin
        case (STATE) is
            when S0   => RUNNER_TMP <= "000";
            when S1   => RUNNER_TMP <= "001";
            when S2   => RUNNER_TMP <= "010";
            when S3   => RUNNER_TMP <= "100";
            when S12  => RUNNER_TMP <= "011";
            when S13  => RUNNER_TMP <= "101";
            when S23  => RUNNER_TMP <= "110";
            when S123 => RUNNER_TMP <= "111";
            when others => RUNNER_TMP <= "000";
        end case;
    end process;
    
    RUNNER <= not RUNNER_TMP

また、

        elsif (CHANGE = '0') then    --- 0:3OUTChange
            STATE <= S0;

チェンジの出力信号は、リセット同様負論理にしています。
野球ゲームをつくる ~ 6.アウトカウントとチェンジ と関連しています。

*1:しつこいですが、電子回路では重要です。

野球ゲームをつくる ~ 9.得点表示の点滅

得点が入った時に得点表示を点滅させてみます。
ただ、ずっと点滅し続けるとうっとうしいので、
5回点滅させることにします。*1

また、点滅させるかどうかの入力信号が必要なので、
ENABLEを入れています。

blink.vhd

-- Blink
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BLINK is
    port(
        CLK     : in  std_logic;
        ENABLE  : in  std_logic;
        BLINK       : out  std_logic
    );
end BLINK;

architecture RTL of BLINK is

signal BLINK_CNT    : std_logic_vector(2 downto 0);
signal BLINK_TMP    : std_logic;

begin

    process(CLK,ENABLE)
    begin
        if (ENABLE = '1') then
            if (CLK'event and CLK = '0') then   
                if (BLINK_CNT = "101") then
                    BLINK_TMP <= '1';
                else
                    BLINK_CNT <= BLINK_CNT + 1;
                    BLINK_TMP <= not BLINK_TMP;
                end if;
            end if;
        else
            BLINK_TMP <= '1';
            BLINK_CNT <= (others => '0');
        end if;
    end process;
    
    BLINK <= BLINK_TMP;
    
end RTL;

*1:クロックが早いとあっという間かもしれません。

野球ゲームをつくる ~ 8.イニングの表示

イニングは通常9回で終了ですが、7SegLEDは16進を表現できるので、
15(F)まで表示します。

ining_decoder.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity INING_DECODER is
    port(
        RESET   : in  std_logic;
        COUNTER : in  std_logic_vector(3 downto 0);
        LED     : out std_logic_vector(7 downto 1)
    );
end INING_DECODER;

architecture RTL of INING_DECODER is
begin

    process (RESET,COUNTER)
    begin
        if (RESET = '0') then
            LED <= "1111111";
        else
            case COUNTER is
                when "0000" => LED <= "0000001"; -- 0
                when "0001" => LED <= "1001111"; -- 1
                when "0010" => LED <= "0010010"; -- 2
                when "0011" => LED <= "0000110"; -- 3
                when "0100" => LED <= "1001100"; -- 4
                when "0101" => LED <= "0100100"; -- 5
                when "0110" => LED <= "0100000"; -- 6
                when "0111" => LED <= "0001101"; -- 7
                when "1000" => LED <= "0000000"; -- 8
                when "1001" => LED <= "0000100"; -- 9
                when "1010" => LED <= "0001000"; -- A
                when "1011" => LED <= "1100000"; -- b
                when "1100" => LED <= "0110001"; -- C
                when "1101" => LED <= "1000010"; -- d
                when "1110" => LED <= "0110000"; -- E
                when "1111" => LED <= "0111000"; -- F
                when others => LED <= "1111110"; -- '-'
            end case;
        end if;
    end process;

end RTL;

野球ゲームをつくる ~ 7.イニングカウンターの作成

イニングカウンターは単純に10進数のカウンターです。

ining_counter.vhd

-- INING Counter
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity INING_COUNTER is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        COUNT       : out std_logic_vector(3 downto 0)
    );
end INING_COUNTER;

architecture RTL of INING_COUNTER is
signal COUNT_TMP    : std_logic_vector(3 downto 0);

begin

    process (CLK,RESET)
    begin
        if (RESET = '0') then
            COUNT_TMP <= "0001";
        elsif (CLK'event and CLK = '0') then
            COUNT_TMP <= COUNT_TMP + 1;
        end if;
    end process;

    COUNT <= COUNT_TMP;
        
end RTL;

野球ゲームをつくる ~ 6.アウトカウントとチェンジ

打撃結果がアウトの場合、
アウトカウントはひとつづつ増え、
スリーアウトでチェンジします。

out_counter.vhd

-- OUT Counter
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity OUT_COUNTER is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        BATTING     : in  std_logic_vector(2 downto 0);
        OUT_LED     : out std_logic_vector(1 downto 0);
        CHANGE      : out std_logic
    );
end OUT_COUNTER;

architecture RTL of OUT_COUNTER is
signal OUT_COUNT_TMP    : std_logic_vector(1 downto 0);
signal OUT_LED_TMP      : std_logic_vector(1 downto 0);

begin
    process (CLK,RESET)
    begin
        if (RESET = '0') then
            OUT_COUNT_TMP <= "00";
        elsif (CLK'event and CLK = '0') then
            if (BATTING = "000") then
                OUT_COUNT_TMP <= OUT_COUNT_TMP + 1;
            end if;
        end if;
    end process;
    
    process(OUT_COUNT_TMP)
    begin
        case (OUT_COUNT_TMP) is
            when "00" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '1';
            when "01" =>
                OUT_LED_TMP <= "01";
                CHANGE <= '1';
            when "10" =>
                OUT_LED_TMP <= "11";
                CHANGE <= '1';
            when "11" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '0';
            when others =>
                OUT_LED_TMP <= null;
                CHANGE <= null;
        end case;
    end process;

    OUT_LED <= OUT_LED_TMP;

end RTL;

ここで、

            when "11" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '0';

アウトカウントが3の時のCHANGE信号は負論理にしています。
通常、信号を送出する場合、1を出力しますが、CHANGEはリセットと同じような効果を与えるので、RESETと論理を同じにして、0を出力しています。

また、

            when "11" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '0';

の OUT_LED_TMP <= "00"; を忘れていました。*1
3アウトチェンジでアウトカウントはリセットされるので、動作上は影響ないのですが、全ての場合を網羅しないと、ラッチ回路が作成されてしまいます。*2

*1:2015.06.10 修正
*2:実は、Warningで気づきました。