スロットマシン
スイッチと7セグメントLEDが載ったボードで、電子サイコロを
作ったので、これを3つ並べると、スロットマシンができると
思いつきました。
4つあるプッシュボタンを、左からBegin、stopA、stopB、stopCと使います。
Beginボタンを押して、3つの7セグメントLEDが
勝手に賽の目を表示します。
stopAボタンを押して、左の7セグメントLEDの
賽の目を止めます。
stopBボタンを押して、中央の7セグメントLEDの
賽の目を止めます。
stopCボタンを押して、右の7セグメントLEDの
賽の目を止めます。
この動作を実現するためのブロック図で動作を考えます。
3個の10進カウンタを用意し、シンクロナイザからの
信号で、カウンタを一斉に動かします。個々のカウンタ
を、STOP信号で止めらると、スロットマシンになります。
3個の10進カウンタは、0〜9の賽の目を出すので、
7セグメントLEDの出力ビットパターンへの変換用
デコーダを用意します。
利用ボードには、7セグメントLEDが6個あるので
ダイナミック点灯で、3個を点灯するセレクタを
設けます。
ボードでは50MHzクロックがあるので、1kHz程度まで
周波数を下げて利用します。そのために、クロック
ジェネレータを使います。
各処理ブロックを定義していきます。
10進カウンタ
開始、停止ができる10進カウンタは、電子サイコロで
利用したコードを、呼び出して使います。
component指定で、dcntx.vhdの内容を指定します。
component dcntx is
port(
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- trigger
BTRG : in std_logic ; -- begin trigger
STRG : in std_logic ; -- stop trigger
-- output
COUT : out std_logic_vector(3 downto 0) --;
);
end component ;
内部で利用する信号を定義し、呼び出します。
-- counter
signal iCOUNTX : std_logic_vector(3 downto 0) ;
signal iCOUNTY : std_logic_vector(3 downto 0) ;
signal iCOUNTZ : std_logic_vector(3 downto 0) ;
-- internal digit counter
XCOUNTER : dcntx port map (nRESET,iCLOCK2,iBTRG,iSTRG(0),iCOUNTX);
YCOUNTER : dcntx port map (nRESET,iCLOCK2,iBTRG,iSTRG(1),iCOUNTY);
ZCOUNTER : dcntx port map (nRESET,iCLOCK2,iBTRG,iSTRG(2),iCOUNTZ);
componentで指定するVHDLコードの内部に、シンクロナイザを
定義してあるので、トリガー信号を渡してカウンタを動かします。
iBTRG <= not BTRG ;
iSTRG <= not STRG ;
10進カウンタを、目で追える程度のスピードで動かすため
50MHzを分周し、iCLOCK2とします。
デコーダ
デコーダは、電子サイコロで定義したコードを、呼び出し使います。
component指定で、ledx.vhdの内容を指定します。
component ledx is
port (
-- input
DIN : in std_logic_vector(3 downto 0);
-- output
DOUT : out std_logic_vector(6 downto 0) --;
);
end component ;
内部で利用する信号を定義し、呼び出します。
-- 7 segment LED
signal iLOUTX : std_logic_vector(6 downto 0) ;
signal iLOUTY : std_logic_vector(6 downto 0) ;
signal iLOUTZ : std_logic_vector(6 downto 0) ;
-- internal decoder
XSLED : ledx port map (iCOUNTX,iLOUTX);
YSLED : ledx port map (iCOUNTY,iLOUTY);
ZSLED : ledx port map (iCOUNTZ,iLOUTZ);
セレクタ
6けた分の7セグメントLEDがあるので、ダイナミック点灯する
ために、6進カウンタを用意します。
カウンタで0、1、2のとき、イネーブル信号を出します。
同時に、デコーダの出力を端子に印加します。
-- output
SEGOUT <= iLOUTX when ( iLCNT = 0 ) else
iLOUTY when ( iLCNT = 1 ) else
iLOUTZ when ( iLCNT = 2 ) else
"1111111" ;
SEGSEL <= "111011" when ( iLCNT = 0 ) else
"111101" when ( iLCNT = 1 ) else
"111110" when ( iLCNT = 2 ) else
"111111" ;
6進カウンタは、バイナリカウンタで構成します。
process (nRESET,iCLOCK)
begin
if ( nRESET = '0' ) then
iLCNT <= 0 ;
elsif rising_edge( iCLOCK ) then
if ( iLCNT = 6 ) then
iLCNT <= 0 ;
else
iLCNT <= iLCNT + 1 ;
end if ;
end if ;
end process ;
クロックジェネレータ
自作IPで説明した内容を利用します。
全体
各コンポーネントを活用し、スロットマシンにまとめます。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity slot is
generic (
TOPX : integer := 15 ;
RMAX : integer := 25000 ;
TOPY : integer := 5 ;
CMAX : integer := 27 --;
);
port(
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- trigger
BTRG : in std_logic ;
STRG : in std_logic_vector(2 downto 0) ;
-- output
DP : out std_logic ;
SEGSEL : out std_logic_vector(5 downto 0) ;
SEGOUT : out std_logic_vector(6 downto 0) --;
);
end slot;
architecture Behavioral of slot is
-- clock generate component
component clkgenx is
generic (
TOPX : integer ;
RMAX : integer --;
);
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- output
CLKOUT : out std_logic -- ;
);
end component;
-- digit counter component
component dcntx is
port(
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ;
-- trigger
BTRG : in std_logic ; -- begin trigger
STRG : in std_logic ; -- stop trigger
-- output
COUT : out std_logic_vector(3 downto 0) --;
);
end component ;
-- 7 segment LED component
component ledx is
port (
-- input
DIN : in std_logic_vector(3 downto 0);
-- output
DOUT : out std_logic_vector(6 downto 0) --;
);
end component ;
-- internal clock
signal iCLOCK : std_logic ;
signal iCLOCK2 : std_logic ;
-- trigger
signal iBTRG : std_logic ;
signal iSTRG : std_logic_vector(2 downto 0) ;
-- counter
signal iCOUNTX : std_logic_vector(3 downto 0) ;
signal iCOUNTY : std_logic_vector(3 downto 0) ;
signal iCOUNTZ : std_logic_vector(3 downto 0) ;
-- 7 segment LED
signal iLOUTX : std_logic_vector(6 downto 0) ;
signal iLOUTY : std_logic_vector(6 downto 0) ;
signal iLOUTZ : std_logic_vector(6 downto 0) ;
signal iLCNT : integer range 0 to 6 ;
begin
-- internal clock (1kHz)
XCLK : clkgenx generic map (TOPX,RMAX) port map (nRESET,CLOCK,iCLOCK);
YCLK : clkgenx generic map (TOPY,CMAX) port map (nRESET,iCLOCK,iCLOCK2);
-- internal digit counter
XCOUNTER : dcntx port map (nRESET,iCLOCK2,iBTRG,iSTRG(0),iCOUNTX);
YCOUNTER : dcntx port map (nRESET,iCLOCK2,iBTRG,iSTRG(1),iCOUNTY);
ZCOUNTER : dcntx port map (nRESET,iCLOCK2,iBTRG,iSTRG(2),iCOUNTZ);
-- internal decoder
XSLED : ledx port map (iCOUNTX,iLOUTX);
YSLED : ledx port map (iCOUNTY,iLOUTY);
ZSLED : ledx port map (iCOUNTZ,iLOUTZ);
-- input
iBTRG <= not BTRG ;
iSTRG <= not STRG ;
-- output
SEGOUT <= iLOUTX when ( iLCNT = 0 ) else
iLOUTY when ( iLCNT = 1 ) else
iLOUTZ when ( iLCNT = 2 ) else
"1111111" ;
SEGSEL <= "111011" when ( iLCNT = 0 ) else
"111101" when ( iLCNT = 1 ) else
"111110" when ( iLCNT = 2 ) else
"111111" ;
DP <= '1' ;
-- LED selector
process (nRESET,iCLOCK)
begin
if ( nRESET = '0' ) then
iLCNT <= 0 ;
elsif rising_edge( iCLOCK ) then
if ( iLCNT = 6 ) then
iLCNT <= 0 ;
else
iLCNT <= iLCNT + 1 ;
end if ;
end if ;
end process ;
end Behavioral;
ピン割当て
ボードで動かすためには、FPGAのI/Oボードと接続している
信号のピンをUCFファイルの中に記述します。
# system
NET "CLOCK" LOC = "P56" ;
NET "nRESET" LOC = "P107" ;
# trigger
NET "STRG<2>" LOC = "P6" ;
NET "STRG<1>" LOC = "P10" ;
NET "STRG<0>" LOC = "P18" ;
NET "BTRG" LOC = "P24" ;
# 7 segment LED charactor
NET "DP" LOC = "P91" ;
NET "SEGOUT<0>" LOC = "P92" ;
NET "SEGOUT<1>" LOC = "P87" ;
NET "SEGOUT<2>" LOC = "P88" ;
NET "SEGOUT<3>" LOC = "P85" ;
NET "SEGOUT<4>" LOC = "P86" ;
NET "SEGOUT<5>" LOC = "P81" ;
NET "SEGOUT<6>" LOC = "P82" ;
# 7 segment LED selector
NET "SEGSEL<0>" LOC = "P98" ;
NET "SEGSEL<1>" LOC = "P83" ;
NET "SEGSEL<2>" LOC = "P75" ;
NET "SEGSEL<3>" LOC = "P74" ;
NET "SEGSEL<4>" LOC = "P77" ;
NET "SEGSEL<5>" LOC = "P76" ;