Go/Stop装置エミュレータ
Go/Stop装置は、タイムトライアル競技の
スタートの合図を送ります。
写真のGo/Stop装置は、ミニ四駆のコース横に
おいて使っていました。
持っているGo/Stop装置は、内部の電球が切れて
ランプの中の1個が点灯しなくなったのでLEDで
代用してみます。
Go/Stop装置の動作は、次の状態遷移図で表現可能。
状態遷移図では、5状態がなので、ジョンソンカウンタ
を利用してシーケンサを構成します。
状態割当ては以下。
- 000(IDLE) 待機
- 001(LED_3) 最下段のLED点灯
- 011(LED_2) 下から2段目のLED点灯
- 111(LED_1) 上から2段目のLED点灯
- 110(LED_0) 最上段のLED点灯
- 100 最初にもどる
状態割当てを決めたので、シーケンサのVHDLコードを定義。
process (nRESET,iCLK)
begin
if ( nRESET = '0' ) then
iSTATE <= "000" ;
elsif rising_edge(iCLK) then
case conv_integer(iSTATE) is
-- IDLE
when 0 => if ( iTRG = '1' ) then
iSTATE <= "001" ;
else
iSTATE <= "000" ;
end if ;
-- LED_3
when 1 => iSTATE <= "011" ;
-- LED_2
when 3 => iSTATE <= "111" ;
-- LED_1
when 7 => iSTATE <= "110" ;
-- LED_0
when 6 => iSTATE <= "100" ;
-- return first state
when 4 => iSTATE <= "000" ;
-- default
when others =>
iSTATE <= "000" ;
end case ;
end if ;
end process ;
状態遷移の周期は、1秒としておけば充分でしょう。
LEDの点灯は、状態値で制御します。
iLED_0 <= '1' when ( iSTATE = "110" ) else '0' ;
iLED_1 <= '1' when ( iSTATE = "111" ) else '0' ;
iLED_2 <= '1' when ( iSTATE = "011" ) else '0' ;
iLED_3 <= '1' when ( iSTATE = "001" ) else '0' ;
シーケンサにトリガーを与えなければならないので
シフトレジスタを使ったシンクロナイザを用意。
process ( nRESET , iSCLK )
begin
if ( nRESET = '0' ) then
iSFT <= "000" ;
elsif rising_edge( iSCLK ) then
iSFT <= iSFT(1 downto 0) & TRGBTN ;
end if ;
end process ;
iTRG <= '1' when ( iSFT = "011" ) else '0' ;
シンクロナイザーは、ボタンのチャタリング除去も
兼用したいので、iSCLKを2Hz以上とします。
回路は簡単でレジスタを3個、デコーダを1個使います。
光だけでなく、音もあった方がよいのでシステム
クロックを分周して生成しましょう。
Goのときは、880Hzを使い、他はLEDの点灯に
合わせて440Hzとします。また待機では無音に
するので、次のブロック図で制御を定義して
おけばよいでしょう。
1段目の分周器で、システムクロックから880Hz
を生成し、2段目の2分周器で半分にします。
システムクロックを4MHzとすると、880Hzに近い
周波数を生成するため、4545分周します。
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iSCNT = 9090 ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
end if ;
end process ;
iSOUT0 <= '1' when ( iSCNT < 2272 ) else
'1' when ( iSCNT > 4545 and iSCNT < 6817) else
'0' ;
iSOUT1 <= '1' when ( iSCNT > 4545 ) else '0' ;
音を出すためには、セレクタを使います。
シーケンサの状態値を利用して選択。
iSOUT <= iSOUT0 when ( iSTATE = "110" ) else
iSOUT1 when ( iSTATE(0) = '1' ) else
'0' ;
ジョンソンカウンタは、ベースとなるシフトレジスタの
レジスタ値が1クロックで1ビットしか変化しないこと
を利用して、デコードを単純にしています。
シンクロナイザとシーケンサで利用するクロックも定義。
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iCNT = 3_999_999 ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
iCLK <= '1' when ( iCNT < 2_000_000 ) else '0' ;
iSCLK <= '1' when ( iCNT < 1_000_000 ) else
'1' when ( iCNT > 2_000_000 and iCNT < 3_000_000 ) else
'0' ;
次のCPLD基板を利用して、エミュレートします。
XC9572を利用した場合のVHDLコードは、以下。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity gostopx is
port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 4MHz
-- trigger
TRGBTN : in std_logic ;
-- LED out
LOUT : out std_logic_vector(3 downto 0) ;
-- sound out
SOUT : out std_logic --;
) ;
end gostopx;
architecture Behavioral of gostopx is
-- clock generator
signal iCNT : integer range 0 to 3_999_999 ;
-- synchronizer
signal iSCLK : std_logic ;
signal iTRG : std_logic ;
signal iSFT : std_logic_vector(2 downto 0) ;
-- LED
signal iLED_0 : std_logic ;
signal iLED_1 : std_logic ;
signal iLED_2 : std_logic ;
signal iLED_3 : std_logic ;
-- sequencer
signal iCLK : std_logic ;
signal iSTATE : std_logic_vector(2 downto 0) ;
-- sound selector
signal iSOUT : std_logic ;
-- sound generator
signal iSCNT : integer range 0 to 9090 ;
signal iSOUT0 : std_logic ;
signal iSOUT1 : std_logic ;
begin
-- output
LOUT <= iLED_0 & iLED_1 & iLED_2 & iLED_3;
SOUT <= iSOUT ;
-- clock generator
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iCNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iCNT = 3_999_999 ) then
iCNT <= 0 ;
else
iCNT <= iCNT + 1 ;
end if ;
end if ;
end process ;
iCLK <= '1' when ( iCNT < 2_000_000 ) else '0' ;
iSCLK <= '1' when ( iCNT < 1_000_000 ) else
'1' when ( iCNT > 2_000_000 and iCNT < 3_000_000 ) else
'0' ;
-- decoder
iLED_0 <= '1' when ( iSTATE = "110" ) else '0' ;
iLED_1 <= '1' when ( iSTATE = "111" ) else '0' ;
iLED_2 <= '1' when ( iSTATE = "011" ) else '0' ;
iLED_3 <= '1' when ( iSTATE = "001" ) else '0' ;
-- sequencer
process (nRESET,iCLK)
begin
if ( nRESET = '0' ) then
iSTATE <= "000" ;
elsif rising_edge(iCLK) then
case conv_integer(iSTATE) is
-- IDLE
when 0 => if ( iTRG = '1' ) then
iSTATE <= "001" ;
else
iSTATE <= "000" ;
end if ;
-- LED_3
when 1 => iSTATE <= "011" ;
-- LED_2
when 3 => iSTATE <= "111" ;
-- LED_1
when 7 => iSTATE <= "110" ;
-- LED_0
when 6 => iSTATE <= "100" ;
-- return first state
when 4 => iSTATE <= "000" ;
-- default
when others =>
iSTATE <= "000" ;
end case ;
end if ;
end process ;
-- synchronizer
process ( nRESET , iSCLK )
begin
if ( nRESET = '0' ) then
iSFT <= "000" ;
elsif rising_edge( iSCLK ) then
iSFT <= iSFT(1 downto 0) & TRGBTN ;
end if ;
end process ;
iTRG <= '1' when ( iSFT = "011" ) else '0' ;
-- sound selector
iSOUT <= iSOUT0 when ( iSTATE = "110" ) else
iSOUT1 when ( iSTATE(0) = '1' ) else
'0' ;
-- sound generator
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iSCNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iSCNT = 9090 ) then
iSCNT <= 0 ;
else
iSCNT <= iSCNT + 1 ;
end if ;
end if ;
end process ;
iSOUT0 <= '1' when ( iSCNT < 2272 ) else
'1' when ( iSCNT > 4545 and iSCNT < 6817) else
'0' ;
iSOUT1 <= '1' when ( iSCNT > 4545 ) else '0' ;
end Behavioral;
XC9572に入れるために、ピンアサインを決定します。
# system
NET "CLOCK" LOC = "P5" ;
NET "nRESET" LOC = "P39" ;
# button
NET "TRGBTN" LOC = "P1" ;
# sound output
NET "SOUT" LOC = "P9" ;
# LED output
NET "LOUT<0>" LOC = "P11" ;
NET "LOUT<0>" LOC = "P12" ;
NET "LOUT<0>" LOC = "P13" ;
NET "LOUT<1>" LOC = "P14" ;
利用するスイッチは、以下。
スピーカは¥100ショップで入手できるものを利用。
スイッチ、スピーカは、クリップワイヤーを使って
CPLD基板上のピンに接続します。
目次
前
次