目次
前
次
信号機エミュレート
交通信号をエミュレートするには、次の基板を使います。
歩行者、車輌を南北と東西に分けての
配置にしています。
交通信号は、シーケンサを利用して定義すれば
よいので、状態遷移図を考えます。
車輌の交通信号は、南北と東西にあるので
状態遷移表でシーケンサの動作を見てみる
なら、次のようになります。
- stat 0 RED(NS) RED(WE)
- stat 1 RED(NS) RED(WE) DELAY
- stat 2 GREEN(NS) RED(WE)
- stat 3 GREEN(NS) RED(WE) DELAY
- stat 4 YELLOW(NS) RED(WE)
- stat 5 YELLOW(NS) RED(WE) DELAY
- stat 6 RED(NS) GREEN(WE)
- stat 7 RED(NS) GREEN(WE) DELAY
- stat 8 RED(NS) YELLOW(WE)
- stat 9 RED(NS) YELLOW(WE) DELAY
全部で10個の状態があるので、シーケンサの
ベースカウンタを、バイナリーカウンタとし
骨格だけをVHDLコードにすると、以下。
-- decoder
iNS <= "001" when ( iSTATE = 2 or iSTATE = 3 ) else
"010" when ( iSTATE = 3 or iSTATE = 4 ) else
"100" ;
iWE <= "001" when ( iSTATE = 6 or iSTATE = 7 ) else
"010" when ( iSTATE = 8 or iSTATE = 9 ) else
"100" ;
-- sequencer
-- iBCLK 0.1Hz
process ( nRESET , iBCLK )
begin
if ( nRESET = '0' ) then
iSTATE <= 0 ;
elsif rising_edge( iBCLK ) then
if ( iSTATE = 9 ) then
iSTATE <= 0 ;
else
iSTATE <= iSTATE + 1 ;
end if ;
end if ;
end process ;
信号は、LEDでエミュレートするので
回路上は、次のようにしておきます。
インバータ(反転器)を利用し、正論理
から負論理に変換しています。
CPLDのドライブ能力が低いときには
外部にTTLを入れて補うのが定石。
車輌の交通信号のシーケンサはできたので
歩行者の交通信号を実現するためデコーダ
を工夫します。
- stat 0 RED(NS) RED(WE) RED(HNS) RED(HWE)
- stat 1 RED(NS) RED(WE) DELAY RED(HNS) RED(HWE)
- stat 2 GREEN(NS) RED(WE) RED(HNS) GREEN(HWE)
- stat 3 GREEN(NS) RED(WE) DELAY RED(HNS) GREEN(HWE)
- stat 4 YELLOW(NS) RED(WE) RED(HNS) flashing(HWE)
- stat 5 YELLOW(NS) RED(WE) DELAY RED(HNS) flashing(HWE)
- stat 6 RED(NS) GREEN(WE) GREEN(HNS) RED(HWE)
- stat 7 RED(NS) GREEN(WE) DELAY GREEN(HNS) RED(HWE)
- stat 8 RED(NS) YELLOW(WE) flashing(HNS) RED(HWE)
- stat 9 RED(NS) YELLOW(WE) DELAY flashing(HNS) RED(HWE)
歩行者の信号で面倒なのは、点滅があること。
この点滅は、発振器の出力を持ってくればよい
と考えると、デコーダは次のように定義すると
よいはず。
-- decoder
iHNS <= "01" when ( iSTATE = 6 or iSTATE = 7 ) else
'0' & iHCLK when ( iSTATE = 8 or iSTATE = 9 ) else
"10" ;
iHWE <= "01" when ( iSTATE = 2 or iSTATE = 3 ) else
'0' & iHCLK when ( iSTATE = 4 or iSTATE = 5 ) else
"10" ;
すべての動作を定義できたので
利用するクロックを生成します。
ブロック図で示すと、以下。
分周処理をVHDLコードに落します。
-- divider
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iACNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iACNT = ACNT_MAX ) then
iACNT <= 0 ;
else
iACNT <= iACNT + 1 ;
end if ;
end if ;
end process ;
-- 1kHz
iACLK <= '1' when ( iACNT < ACNT_HALF ) else '0' ;
process ( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iHCNT <= 0 ;
elsif rising_edge( iACLK ) then
if ( iHCNT = HCNT_MAX ) then
iHCNT <= 0 ;
else
iHCNT <= iHCNT + 1 ;
end if ;
end if ;
end process ;
-- 1Hz
iHCLK <= '1' when ( iHCNT < HCNT_HALF ) else '0' ;
process ( nRESET , iHCLK )
begin
if ( nRESET = '0' ) then
iBCNT <= 0 ;
elsif rising_edge( iHCLK ) then
if ( iBCNT = 9 ) then
iBCNT <= 0 ;
else
iBCNT <= iBCNT + 1 ;
end if ;
end if ;
end process ;
-- 0.1Hz
iBCLK <= '1' when ( iBCNT = 0 ) else '0' ;
まとめると、以下。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity xtsig is
Port (
-- system
nRESET : in std_logic ;
CLOCK : in std_logic ; -- 4MHz
-- monitor
ACLK : out std_logic ;
HCLK : out std_logic ;
BCLK : out std_logic ;
-- output
SHNS : out std_logic_vector(1 downto 0) ;
SHWE : out std_logic_vector(1 downto 0) ;
SNS : out std_logic_vector(2 downto 0) ;
SWE : out std_logic_vector(2 downto 0) --;
);
end xtsig;
architecture Behavioral of xtsig is
--
CONSTANT ACNT_MAX : integer := 3999 ;
CONSTANT HCNT_MAX : integer := 999 ;
CONSTANT ACNT_HALF : integer := 2000 ;
CONSTANT HCNT_HALF : integer := 500 ;
-- divider
signal iACNT : integer range 0 to ACNT_MAX ;
signal iACLK : std_logic ;
signal iHCNT : integer range 0 to BCNT_MAX ;
signal iHCLK : std_logic ;
signal iBCNT : integer range 0 to 9 ;
signal iBCLK : std_logic ;
-- decoder
signal iHNS : std_logic_vector(1 downto 0) ;
signal iHWE : std_logic_vector(1 downto 0) ;
signal iNS : std_logic_vector(2 downto 0) ;
signal iWE : std_logic_vector(2 downto 0) ;
-- sequencer
signal iSTATE : integer range 0 to 9 ;
begin
-- output
SHNS <= iHNS ;
SHWE <= iHWE ;
SNS <= iNS ;
SWE <= iWE ;
-- monitor
ACLK <= iACLK ;
HCLK <= iHCLK ;
BCLK <= iBCLK ;
-- divider
process ( nRESET , CLOCK )
begin
if ( nRESET = '0' ) then
iACNT <= 0 ;
elsif rising_edge( CLOCK ) then
if ( iACNT = ACNT_MAX ) then
iACNT <= 0 ;
else
iACNT <= iACNT + 1 ;
end if ;
end if ;
end process ;
iACLK <= '1' when ( iACNT < ACNT_HALF ) else '0' ;
process ( nRESET , iACLK )
begin
if ( nRESET = '0' ) then
iHCNT <= 0 ;
elsif rising_edge( iACLK ) then
if ( iHCNT = HCNT_MAX ) then
iHCNT <= 0 ;
else
iHCNT <= iHCNT + 1 ;
end if ;
end if ;
end process ;
iHCLK <= '1' when ( iHCNT < HCNT_HALF ) else '0' ;
process ( nRESET , iHCLK )
begin
if ( nRESET = '0' ) then
iBCNT <= 0 ;
elsif rising_edge( iHCLK ) then
if ( iBCNT = 9 ) then
iBCNT <= 0 ;
else
iBCNT <= iBCNT + 1 ;
end if ;
end if ;
end process ;
iBCLK <= '1' when ( iBCNT = 0 ) else '0' ;
-- decoder
iHNS <= "01" when ( iSTATE = 6 or iSTATE = 7 ) else
'0' & iHCLK when ( iSTATE = 8 or iSTATE = 9 ) else
"10" ;
iHWE <= "01" when ( iSTATE = 2 or iSTATE = 3 ) else
'0' & iHCLK when ( iSTATE = 4 or iSTATE = 5 ) else
"10" ;
iNS <= "001" when ( iSTATE = 2 or iSTATE = 3 ) else
"010" when ( iSTATE = 3 or iSTATE = 4 ) else
"100" ;
iWE <= "001" when ( iSTATE = 6 or iSTATE = 7 ) else
"010" when ( iSTATE = 8 or iSTATE = 9 ) else
"100" ;
-- sequencer
process ( nRESET , iBCLK )
begin
if ( nRESET = '0' ) then
iSTATE <= 0 ;
elsif rising_edge( iBCLK ) then
if ( iSTATE = 9 ) then
iSTATE <= 0 ;
else
iSTATE <= iSTATE + 1 ;
end if ;
end if ;
end process ;
end Behavioral;
ピンアサインは、以下。
# system
NET "nRESET" loc = "P39" ;
NET "CLOCK" loc = "P5" ;
# monitor
NET "ACLK" loc = "P1" ;
NET "HCLK" loc = "P2" ;
NET "BCLK" loc = "P3" ;
# North - South
NET "SHNS<0>" loc = "P11" ;
NET "SHNS<1>" loc = "P12" ;
NET "SNS<0>" loc = "P13" ;
NET "SNS<1>" loc = "P14" ;
NET "SNS<2>" loc = "P18" ;
# North - South
NET "SHWE<0>" loc = "P24" ;
NET "SHWE<1>" loc = "P25" ;
NET "SWE<0>" loc = "P26" ;
NET "SWE<1>" loc = "P27" ;
NET "SWE<2>" loc = "P28" ;
目次
前
次