目次

信号機エミュレート

 交通信号をエミュレートするには、次の基板を使います。



 歩行者、車輌を南北と東西に分けての
 配置にしています。

 交通信号は、シーケンサを利用して定義すれば
 よいので、状態遷移図を考えます。



 車輌の交通信号は、南北と東西にあるので
 状態遷移表でシーケンサの動作を見てみる
 なら、次のようになります。

 全部で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を入れて補うのが定石。

 車輌の交通信号のシーケンサはできたので
 歩行者の交通信号を実現するためデコーダ
 を工夫します。

 歩行者の信号で面倒なのは、点滅があること。
 この点滅は、発振器の出力を持ってくればよい
 と考えると、デコーダは次のように定義すると
 よいはず。

  -- 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" ;


目次

inserted by FC2 system