目次


信号機エミュレータ

 知人から信号機をエミュレーションする
 CPLD基板を貰いました。



 VHDLコードで通常の信号機とスクランブル
 交差点を実現したそうです。製作は大学生
 で、半田付けとHDLの演習に利用したとか。

 スクランブル交差点を入れてみるかとFPGA上で
 エミュレーションしてから、CPLDに回路を実装
 してみます。

 FPGA基板は、いつものSpartan3Eを利用します。



 スクランブル交差点の動作を、次のように決めました。



 動作から必要なブロックを抽出し、図を描きます。



 スクランブル交差点の動作を確定するのは
 ステートマシンなので、カウンタとしては
 ジョンソンカウンタを利用して定義。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity xstate is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- output
    DOUT   : out std_logic_vector(3 downto 0) --;
  );
end xstate ;

architecture Behavioral of xstate is
  signal iSTATE : std_logic_vector(3 downto 0);
begin
  -- output
  Dout <= iSTATE ;

  -- state machine
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSTATE <= "0000";
    elsif rising_edge(CLOCK) then
      case conv_integer(iSTATE) is
        -- 001 001
        when 0  => iSTATE <= "0001" ;
        -- 001 001
        when 1  => iSTATE <= "0011" ;
        -- 100 001
        when 3  => iSTATE <= "0111" ;
        -- 010 001
        when 7  => iSTATE <= "1111" ;
        -- 001 001
        when 15 => iSTATE <= "1110" ;
        -- 001 100
        when 14 => iSTATE <= "1100" ;
        -- 001 010
        when 12 => iSTATE <= "1000" ;
        -- 001 001
        when 8  => iSTATE <= "0000" ;
        -- default
        when others =>
                   iSTATE <= "0000" ;
      end case ;
    end if ;
  end process ;

end Behavioral;

 ステートマシンの状態を使い、東西南北の
 信号機の状態を確定します。4入力6出力
 の組合せ回路で定義。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity news is
  port (
    -- input
    Din  : in  std_logic_vector(3 downto 0) ;
    -- output
    Dout : out std_logic_vector(5 downto 0) --;
  );
end news ;

architecture Behavioral of news is
  signal iDin  : std_logic_vector(3 downto 0);
  signal iDout : std_logic_vector(5 downto 0);
begin
  -- output
  Dout <= iDout ;

  -- input
  iDin <= Din ;

  -- decoder 
  iDout <= "001001" when ( iDin = "0000" ) else 
           "001001" when ( iDin = "0001" ) else 
           "100001" when ( iDin = "0011" ) else 
           "010001" when ( iDin = "0111" ) else 
           "001001" when ( iDin = "1111" ) else 
           "001100" when ( iDin = "1110" ) else 
           "001010" when ( iDin = "1100" ) else 
           "001001" when ( iDin = "1000" ) else 
           "001001" ;

end Behavioral;

 ステートマシンの状態を使い、歩行者の
 信号機の状態を確定します。ブリンクに
 クロックディバイダから来るクロックを
 使えばよいと考えました。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mwalk is
  port (
    -- system
    CLOCK : in  std_logic ;
    -- input
    Din   : in  std_logic_vector(3 downto 0) ;
    -- output
    Dout  : out std_logic_vector(1 downto 0) --;
  );
end mwalk ;

architecture Behavioral of mwalk is
  -- input
  signal iDin  : std_logic_vector(3 downto 0);
  -- output
  signal iDout : std_logic_vector(1 downto 0);
begin
  -- output
  Dout <= iDout ;

  -- input
  iDin <= Din ;

  -- decoder and selector
  iDout <= "01"          when ( iDin = "0000" ) else
           ('0' & CLOCK) when ( iDin = "0001" ) else
           (CLOCK & '0') when ( iDin = "1000" ) else
           "10" ;

end Behavioral;

 FPGA基板には、50MHzクロックがあるので
 分周して、ステートマシンを0.1Hzで動作
 させます。また、点滅は0.3Hz程度にして
 おきます。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mdivider is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- output
    COUT0  : out std_logic ;
    COUT1  : out std_logic -- ;
  );
end mdivider ;

architecture Behavioral of mdivider is
  -- constant value
  constant CNT1_MAX : integer := 49999999 ;
  constant CNT2_MAX : integer := 9 ;
  -- clock divider
  signal iCNT   : std_logic_vector(25 downto 0);
  signal iCLK   : std_logic ;
  signal iCNT1  : integer range 0 to CNT1_MAX ;
  signal iCNT2  : integer range 0 to CNT2_MAX ;
  signal iSCLK  : std_logic ;
  signal iBLINK : std_logic ;
begin
  -- output
  COUT0 <= iSCLK ;
  COUT1 <= iCLK  ;

  -- internal input
  iDin <= iSTATE ;

  --clock divider for flashing
  process (nRESET,CLOCK)
  begin
   if ( nRESET = '0' ) then
      iCNT <= (others => '0') ;
    elsif rising_edge( CLOCK ) then
      iCNT <= iCNT + '1' ;
    end if ;
  end process ;
  iCLK <= iCNT(25) ;

  --clock divider for blink
  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iCNT1 <= 0 ;
    elsif rising_edge( CLOCK ) then
      if ( iCNT1 = CNT1_MAX ) then
        iCNT1 <= 0 ;
      else
        iCNT1 <= iCNT1 + 1;
      end if;
    end if ;
  end process ;
  iBLINK <= '1' when ( iCNT1 = 0 ) else '0';

  --clock divider for state machine
  process (nRESET,iBLINK)
  begin
    if ( nRESET = '0' ) then
      iCNT2<= 0 ;
    elsif rising_edge( iBLINK ) then
      if ( iCNT2 = CNT2_MAX ) then
        iCNT2 <= 0 ;
      else
        iCNT2 <= iCNT2 + 1 ;
      end if;
    end if ;
  end process ;
  iSCLK <= '1' when ( iCNT2 = 0 ) else '0';

end Behavioral;

 トップレベルでは、各VHDLコードをコンポーネント
 として利用します。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity scramble is
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- output
    DOUT   : out std_logic_vector(7 downto 0) --;
  );
end scramble ;

architecture Behavioral of scramble is
  -- state machine component
  component xstate is
    port (
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- output
      DOUT   : out std_logic_vector(3 downto 0) --;
    );
  end component ;
  -- automobile decoder component
  component news is
    port (
      -- input
      Din  : in  std_logic_vector(3 downto 0) ;
      -- output
      Dout : out std_logic_vector(5 downto 0) --;
    );
  end component ;
  -- walker decoder and selector component
  component mwalk is
    port (
      -- system
      CLOCK : in  std_logic ;
      -- input
      Din   : in  std_logic_vector(3 downto 0) ;
      -- output
      Dout  : out std_logic_vector(1 downto 0) --;
    );
  end component ;
  -- clock divider component
  component mdivider is
    port (
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- output
      COUT0  : out std_logic ;
      COUT1  : out std_logic -- ;
    );
  end component ;
  -- decoder
  signal iCAR  : std_logic_vector(5 downto 0);
  signal iWALK : std_logic_vector(1 downto 0);
  -- state machine
  signal iSTATE : std_logic_vector(3 downto 0);
  -- clock divider
  signal iSCLK  : std_logic ;
  signal iBLINK : std_logic ;
begin
  -- state machine
  STATEX : xstate port map (nRESET,iSCLK,iSTATE) ;
  -- automobile decoder component
  XNEWS : news port map (iSTATE,iCAR) ;
  -- walker decoder and selector component
  WALKER : mwalk port map (iBLINK,iSTATE,iWALK) ;
  -- clock divider component
  SDIVIER : mdivider port (nRESET,iSCLK,iBLINK) ;

  -- output
  Dout <= iCAR & iWALK;

end Behavioral;

 エミュレーションするために、UCFファイルを作成します。

# system
NET "nRESET" LOC = "P107" ;
NET "CLOCK"  LOC = "P56"  ;

# sramble traffic signals
NET "Dout<0>" LOC = "P132" ;
NET "Dout<1>" LOC = "P124" ;
NET "Dout<2>" LOC = "P113" ;
NET "Dout<3>" LOC = "P112" ;
NET "Dout<4>" LOC = "P117" ;
NET "Dout<5>" LOC = "P116" ;
NET "Dout<6>" LOC = "P123" ;
NET "Dout<7>" LOC = "P122" ;

 CPLD基板には、XC9572が実装されているので
 Spartan3EからXC9572にリターゲットします。
 さらに、クロックディバイダのカウント値を
 変更して完成です。


目次

inserted by FC2 system