記事一覧

ルーレットをつくる ~ ルーレットの完成

2013年06月21日(金)21時51分

今まで作ったパーツを元にルーレットを組み立てていきます。

まず、いままでのパーツの復習は以下のとおりです。

divider.vhd

oneshot.vhd

slot.vhd

roullet.vhd

reach.vhd

reach_ctl.vhd

bingo_ctl.vhd

ring.vhd

bingo_ast.vhd

dec_7segled.vhd

何やらいっぱいある感じですが、機能に分割しているからです。

で、トップエンティティは次になります。

slot_game.vhd

-- SLOT TOP Entity
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SLOT_GAME is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        SW          : in  std_logic_vector(2 downto 0);
        LED1        : out std_logic_vector(7 downto 1);
        LED2        : out std_logic_vector(7 downto 1);
        LED3        : out std_logic_vector(7 downto 1);
        DOUT        : out std_logic_vector(3 downto 0);
        ASSIST_LED  : out std_logic
    );
end SLOT_GAME;

architecture RTL of SLOT_GAME is

component DIVIDER
    port(
        CLK         : in  std_logic;
        DIV_CLK_2HZ : out std_logic;
        DIV_CLK_8HZ : out std_logic;
        DIV_CLK_16HZ: out std_logic
    );
end component;

component SLOT
    port(
        DIV_CLK     : in  std_logic;
        RESET       : in  std_logic;
        SW          : in  std_logic;
        STOP_OUT    : out std_logic;
        HIT         : out std_logic_vector(3 downto 0)
    );
end component;

component REACH_CTL
    port(
        REACH_CLK: in  std_logic;    -- リーチ状態の点滅用クロック
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP3       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        HIT3        : in  std_logic_vector(3 downto 0);
        LED_CLK1    : out std_logic;    -- 7SegLEDの点滅クロック
        LED_CLK2    : out std_logic;    -- 7SegLEDの点滅クロック
        LED_CLK3    : out std_logic    -- 7SegLEDの点滅クロック
    );
end component;

component BINGO_CTL
    port(
        RESET       : in  std_logic;
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP3       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        HIT3        : in  std_logic_vector(3 downto 0);
        BINGO_STATUS: out std_logic    -- BINGO 0:× 1:○
    );
end component;

component BINGO_AST
    port(
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP3       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        HIT3        : in  std_logic_vector(3 downto 0);
        BINGO_ASSIST: out std_logic    -- BINGO_ASSIST の点滅
    );
end component;

component RING
    port(
        DIV_CLK     : in  std_logic;
        ENABLE      : in  std_logic;
        DOUT        : out std_logic_vector(3 downto 0)
    );
end component;

component DEC_7SegLED
    port(
        ENABLE      : in  std_logic;
        RESET       : in  std_logic;
        COUNTER     : in  std_logic_vector(3 downto 0);
        LED_7SEG    : out std_logic_vector(7 downto 1)
    );
end component;


signal CLK_2HZ      : std_logic;
signal CLK_8HZ      : std_logic;
signal CLK_16HZ     : std_logic;
signal STOP         : std_logic_vector(2 downto 0);
signal HIT1_TMP     : std_logic_vector(3 downto 0);
signal HIT2_TMP     : std_logic_vector(3 downto 0);
signal HIT3_TMP     : std_logic_vector(3 downto 0);
signal BINGO_STATUS : std_logic;
signal LED_TMP      : std_logic_vector(2 downto 0);

begin

    U1:DIVIDER      port map (CLK,CLK_2HZ,CLK_8HZ,CLK_16HZ);
    S1:SLOT         port map (CLK_16HZ,RESET,SW(0),STOP(0),HIT1_TMP);
    S2:SLOT         port map (CLK_16HZ,RESET,SW(1),STOP(1),HIT2_TMP);
    S3:SLOT         port map (CLK_16HZ,RESET,SW(2),STOP(2),HIT3_TMP);
    U2:REACH_CTL    port map (CLK_2HZ,STOP(0), STOP(1), STOP(2), HIT1_TMP,HIT2_TMP, HIT3_TMP,LED_TMP(0), LED_TMP(1), LED_TMP(2));
    U3:BINGO_CTL    port map (RESET,STOP(0), STOP(1), STOP(2), HIT1_TMP,HIT2_TMP, HIT3_TMP,BINGO_STATUS);
    U4:BINGO_AST    port map (STOP(0),STOP(1), STOP(2), HIT1_TMP,HIT2_TMP, HIT3_TMP,ASSIST_LED);
    U5:RING         port map (CLK_16HZ,BINGO_STATUS,DOUT);
    D1:DEC_7SegLED  port map (LED_TMP(0),'1',HIT1_TMP,LED1);
    D2:DEC_7SegLED  port map (LED_TMP(1),'1',HIT2_TMP,LED2);
    D3:DEC_7SegLED  port map (LED_TMP(2),'1',HIT3_TMP,LED3);

end RTL;

ここで、次のように

    D1:DEC_7SegLED  port map (LED_TMP(0),'1',HIT1_TMP,LED1);
    D2:DEC_7SegLED  port map (LED_TMP(1),'1',HIT2_TMP,LED2);
    D3:DEC_7SegLED  port map (LED_TMP(2),'1',HIT3_TMP,LED3);

RESETに'1'をつなげているのは、
リセットを押した時に7セグが消えずに0を表示させるためです。

チャタリングカットを入れていないのは、
スイッチを一度押せばカウンタは止まってしまうので、
チャタリングを考慮する必要がないからです。

コンパイルした結果が下図です。
ファイル 95-1.jpg

回路図(RTL_VIWER)は下図です。
ファイル 95-2.jpg

ピン配置は下記です。
ファイル 95-3.jpg

ルーレットをつくる ~ ビンゴアシストの作成

2013年06月21日(金)19時13分

リーチの時にビンゴのタイミングでLEDが点灯するようにします。
目押しができないので、つくってみました。ズルと言われれば、それまでですが(^_^;)

reach.vhd を利用しています。

bingo_ast.vhd

-- BINGO ASSIST
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity BINGO_AST is
    port(
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP3       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        HIT3        : in  std_logic_vector(3 downto 0);
        BINGO_ASSIST: out std_logic    -- BINGO_ASSIST
    );
end BINGO_AST;

architecture RTL of BINGO_AST is

component REACH
    port(
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        REACH_STATUS: out std_logic    -- リーチ状態 0:× 1:○
    );
end component;

signal REACH_TMP        : std_logic; -- リーチ 0:× 1:○
signal BINGO_TMP        : std_logic; -- ビンゴ 0:× 1:○
signal BINGO_ASSIST_TMP : std_logic;
signal REACH_STATUS     : std_logic_vector(2 downto 0);

begin
    -- どれかの組合せがリーチの時 = リーチ
    REACH_TMP <= REACH_STATUS(0) or REACH_STATUS(1) or REACH_STATUS(2);

    -- 全ての組合せがリーチの時 = ビンゴ
    BINGO_TMP <= REACH_STATUS(0) and REACH_STATUS(1) and REACH_STATUS(2);

    process(BINGO_TMP,REACH_TMP,HIT1,HIT2,HIT3)
    begin
        if(BINGO_TMP = '1') then --ビンゴの時はビンゴアシストのLEDは消す
            BINGO_ASSIST_TMP <= '0';
        else
            if (REACH_TMP = '1' and HIT1 = HIT2 and HIT2 = HIT3) then
                BINGO_ASSIST_TMP <= '1';
            else
                BINGO_ASSIST_TMP <= '0';
            end if;
        end if;
    end process;
    
    -- LEDは負論理なので、反転
    BINGO_ASSIST <= not BINGO_ASSIST_TMP;
    
    U1 : REACH    port map (STOP1, STOP2, HIT1, HIT2, REACH_STATUS(0)); 
    U2 : REACH    port map (STOP2, STOP3, HIT2, HIT3, REACH_STATUS(1)); 
    U3 : REACH    port map (STOP3, STOP1, HIT3, HIT1, REACH_STATUS(2));     
    
end RTL;

ルーレットをつくる ~ ビンゴの判定、動作

2013年06月21日(金)17時00分

ビンゴの判定は簡単です。
全て止まった状態のルーレットが一致していることですね。

bingo_ctl.vhd

-- Bingo Control
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity BINGO_CTL is
    port(
        RESET       : in  std_logic;
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP3       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        HIT3        : in  std_logic_vector(3 downto 0);
        BINGO_STATUS: out std_logic    -- BINGO 0:× 1:○
    );
end BINGO_CTL;

architecture RTL of BINGO_CTL is

signal ALL_STOP     : std_logic;

begin

    ALL_STOP <= STOP1 and STOP2 and STOP3;

    process(RESET,ALL_STOP,HIT1,HIT2,HIT3)
    begin
        if (RESET = '0') then
            BINGO_STATUS <= '0';
        else
            if (ALL_STOP = '1') then
                if (HIT1 = HIT2 and HIT2 = HIT3) then
                    BINGO_STATUS <= '1';
                else
                    BINGO_STATUS <= '0';
                end if;
            else
                BINGO_STATUS <= '0';
            end if;
        end if;
    end process;
    
end RTL;

ビンゴした時の動作ですが、
LEDがくるくる光るようにしてみます。

ファイル 93-1.jpg

ring.vhd

-- Ring Counter
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity RING is
    port(
        DIV_CLK : in  std_logic;
        ENABLE  : in  std_logic;
        DOUT    : out std_logic_vector(3 downto 0)
    );
end RING;

architecture RTL of RING is
    signal DATA : std_logic_vector(3 downto 0);    

begin
    -- Ring Counter
    process(DIV_CLK,ENABLE)
    begin
        if (DIV_CLK'event and DIV_CLK='1') then
            if(ENABLE = '1') then
                DATA(0) <= not (DATA(0) or DATA(1) or DATA(2));
                DATA(1) <= DATA(0);
                DATA(2) <= DATA(1);
                DATA(3) <= DATA(2);
            else
                DATA <= "0000";
            end if;
        end if;
    end process;
    -- Ring Counter end

    DOUT <= not DATA;
    
end RTL;

LEDの出力は負論理なので、最後でデータを反転しています。

ルーレットをつくる ~ リーチの判定、動作

2013年06月21日(金)10時48分

リーチかどうか判定します。

リーチである条件は
1.3個のルーレットの内、止まっている2個が一致
2.3個とも止まっていればリーチではない
で、

リーチの動作は7セグを点滅させます。

1.の判定を reach.vhd で行います。
2.の判定及び点滅を reach_ctl.vhd で行います。

reach.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity REACH is
    port(
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        REACH_STATUS: out std_logic     -- リーチ状態 0:× 1:○
    );
end REACH;

architecture RTL of REACH is
    signal STOP_TMP    : std_logic;
    
begin
    
    STOP_TMP <= STOP1 and STOP2;

    process(STOP_TMP,HIT1,HIT2)
    begin
        if (STOP_TMP = '1') then
            if (HIT1 = HIT2) then
                REACH_STATUS <= '1';
            else
                REACH_STATUS <= '0';
            end if;
        else
            REACH_STATUS <= '0';
        end if;
    end process;
    
end RTL;

reach_ctl.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity REACH_CTL is
    port(
        REACH_CLK: in  std_logic;    -- リーチ状態の点滅用クロック
        STOP1    : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2    : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP3    : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1     : in  std_logic_vector(3 downto 0);
        HIT2     : in  std_logic_vector(3 downto 0);
        HIT3     : in  std_logic_vector(3 downto 0);
        LED_CLK1 : out std_logic;    -- 7SegLEDの点滅クロック
        LED_CLK2 : out std_logic;    -- 7SegLEDの点滅クロック
        LED_CLK3 : out std_logic     -- 7SegLEDの点滅クロック
    );
end REACH_CTL;

architecture RTL of REACH_CTL is

component REACH
    port(
        STOP1       : in  std_logic;    -- ルーレットが 0:動 1:止
        STOP2       : in  std_logic;    -- ルーレットが 0:動 1:止
        HIT1        : in  std_logic_vector(3 downto 0);
        HIT2        : in  std_logic_vector(3 downto 0);
        REACH_STATUS: out std_logic    -- リーチ状態 0:× 1:○
    );
end component;

signal REACH_STOP   : std_logic_vector(2 downto 0);
signal REACH_STATUS : std_logic_vector(2 downto 0);

begin

    REACH_STOP(0) <= REACH_STATUS(0) and not STOP3;
    REACH_STOP(1) <= REACH_STATUS(1) and not STOP1;
    REACH_STOP(2) <= REACH_STATUS(2) and not STOP2;
    

    process(REACH_STOP)
    begin
        if (REACH_STOP(0) = '1') then
            LED_CLK1 <= REACH_CLK;
            LED_CLK2 <= REACH_CLK;
            LED_CLK3 <= '1';
        elsif (REACH_STOP(1) = '1') then
            LED_CLK2 <= REACH_CLK;
            LED_CLK3 <= REACH_CLK;
            LED_CLK1 <= '1';
        elsif (REACH_STOP(2) = '1') then
            LED_CLK3 <= REACH_CLK;
            LED_CLK1 <= REACH_CLK;
            LED_CLK2 <= '1';
        else
            LED_CLK1 <= '1';
            LED_CLK2 <= '1';
            LED_CLK3 <= '1';
        end if;
    end process;
    
    U1 : REACH    port map (STOP1, STOP2, HIT1, HIT2, REACH_STATUS(0)); 
    U2 : REACH    port map (STOP2, STOP3, HIT2, HIT3, REACH_STATUS(1)); 
    U3 : REACH    port map (STOP3, STOP1, HIT3, HIT1, REACH_STATUS(2));     
    
end RTL;