目次

机上デバッグ

 MCR-VCマシンの試走は、コースと場所が必要で
 気軽に走らせるようにはなっていない。

 自分の場合、物置の2Fが使えるので25m程度の
 コースは常設である。しかし、北海道では冬期間に
 物置の2Fで費やせる時間は長くない。

 暖房を入れれば問題解決するが、節電や省資源の点
 からストーブは焚きたくない。灯油を燃料にするコンロ
 があるが、場所路をとるのでコースが短くなってしまう。

 戸外は氷点下の気温でも、物置の2Fは室温が10℃
 前後なので、30分程度ならばテスト走行やデバッグ
 はできる。

 そこで、走行だけに常設コースを使うことにして
 なるべく自室でテスト、デバッグするように工夫
 してみました。

 マシンを載せる台を、健康食品の入っていた箱の
 上にのせます。タイヤは自由に回転できるように
 なっています。



 タイヤの回転数がわかると、直進、右回転、左回転
 を判断できるので、2チャネルの周波数カウンタを
 用意しました。



 左右のタイヤの回転数は、フォトインタラプタを
 利用してON/OFF信号に変換後、カウンタに
 接続します。




 周波数カウンタは、1秒あたりのパルス数をカウント
 しているので、1秒あたりのタイヤ回転数を見れば
 マシンのおおよその動きを判断できます。

 MCR-VCマシンは、路面センサーからもたらされる情報を
 活用して移動するので、センサー情報を出力する装置が
 必要になります。

 CPLDのCoolRunnerIIを利用し、1秒ごとに8ビットの
 路面センサー情報を出力することにしました。



 利用したVHDLコードは、以下です。

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

entity gensen is
  generic (
    TOPX : integer := 10 ; 
    RMAX : integer := 921 ;
    TOPY : integer := 10 ; 
    YMAX : integer := 500 --;
  ) ;
  port (
    -- system 
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- trigger input 
    SETRG  : in  std_logic ; -- start or exit flag
    -- OUTPUT 
    SMON   : out std_logic_vector(7 downto 0) ;
    SOUT   : out std_logic_vector(7 downto 0) ;
    GLED   : out std_logic ;
    RLED   : out std_logic ;
    LED    : out std_logic --;
  );
end gensen;

architecture behavioral of gensen is
  -- clock generator
  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 ;
  -- sensor information generator
  component senx is
    port (
      -- input
      DIN  : in  std_logic_vector(3 downto 0) ;
      -- output
      JOUT : out std_logic_vector(7 downto 0) --;
    );
  end component ;
  -- clock
  signal iMCLK  : std_logic ;
  signal iPCLK  : std_logic ;
  -- parent sequencer
  signal iPSTATE : std_logic_vector(1 downto 0) ;
  signal iENABLE : std_logic ;
  -- trigger
  signal iSETRG     : std_logic ;
  signal iSETRG_SFT : std_logic_vector(2 downto 0) ;
  signal iTRG_R     : std_logic ;
  -- counter
  signal iCNT  : std_logic_vector(3 downto 0) ;
  signal iJOUT : std_logic_vector(7 downto 0) ;
begin
  -- clock
  CLKX : clkgenx generic map (TOPX,RMAX) port map (nRESET,CLOCK,iMCLK) ;
  CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iMCLK,iPCLK) ;
  -- judge
  SENOUT : senx port map (iCNT,iJOUT) ;

  -- input
  iSETRG <= not SETRG ;

  -- output
  SOUT <= iJOUT ;
  SMON <= not iJOUT ;
  LED  <= iPCLK ;
  GLED <= iPCLK ;
  RLED <= not iPCLK ;

  -- trigger sequencer
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iSETRG_SFT <= "000" ;
    elsif rising_edge(iMCLK) then
      iSETRG_SFT <= iSETRG_SFT(1 downto 0) & iSETRG ;
    end if ;
  end process ;
  iTRG_R <= '1' when ( iSETRG_SFT = "011" or iSETRG_SFT = "001" ) else '0' ;

  -- parent sequencer
  process (nRESET,iMCLK)
  begin
    if ( nRESET = '0' ) then
      iPSTATE <= "00" ;
    elsif rising_edge(iMCLK) then
      case conv_integer(iPSTATE) is
        -- wait RFLAG rising edge
        when 0 => if ( iTRG_R = '1' ) then
                    iPSTATE <= "01" ;
                  else
                    iPSTATE <= "00" ;
                  end if ;
        -- send blind run trigger
        when 1 => iPSTATE <= "11" ;
        -- wait blind run flag
        when 3 => if ( iTRG_R= '1' ) then
                    iPSTATE <= "10" ;
                  else
                    iPSTATE <= "11" ;
                  end if ;
        -- return first state
        when 2 => iPSTATE <= "00" ;
        -- default
        when others => 
                  iPSTATE <= "00" ;
      end case ;
    end if ;
  end process ;
  iENABLE <= iPSTATE(0) ;

  -- trigger sequencer
  process (nRESET,iPCLK)
  begin
    if ( nRESET = '0' ) then
      iCNT <= "0000" ;
    elsif rising_edge(iPCLK) then
      if ( iENABLE = '1' ) then
        iCNT <= iCNT + '1' ;
      end if ;
    end if ;
  end process ;

end behavioral;

 内容は単純で、トリガーを受けたら、4ビットの
 バイナリカウンタをインクリメントします。

 バイナリカウンタの出力(0〜15)を入力すると
 対応した8ビットのデータを出力します。

 8ビットデータ出力は、別ファイルで定義しています。

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

entity senx is
  port (
    -- input
    DIN  : in  std_logic_vector(3 downto 0) ;
    -- output
    JOUT : out std_logic_vector(7 downto 0) --;
  );
end senx;

architecture Behavioral of senx is
  signal iJOUT : std_logic_vector(7 downto 0);
begin
  -- output
  JOUT <= iJOUT ;

  -- convert
  iJOUT <= X"18" when ( DIN = X"0" ) else -- center
           X"38" when ( DIN = X"1" ) else -- center
           X"1C" when ( DIN = X"2" ) else -- center
           X"0C" when ( DIN = X"3" ) else -- tiny_right
           X"0C" when ( DIN = X"4" ) else -- tiny_right
           X"18" when ( DIN = X"5" ) else -- center
           X"30" when ( DIN = X"6" ) else -- tiny_left
           X"30" when ( DIN = X"7" ) else -- tiny_left
           X"60" when ( DIN = X"8" ) else -- left
           X"18" when ( DIN = X"9" ) else -- center
           X"06" when ( DIN = X"A" ) else -- right
           X"1C" when ( DIN = X"B" ) else -- center
           X"60" when ( DIN = X"C" ) else -- left
           X"38" when ( DIN = X"D" ) else -- center
           X"18" when ( DIN = X"E" ) else -- center
           X"18" ;

end Behavioral;

 出力パターンを変更したい場合、上のVHDLコードで
 記述しているデコードテーブルを変えます。

 16パターンで足りないときには、バイナリカウンタを
 5ビット、6ビット、7ビットとし、デコード内容を
 増やします。

 メインとなるVHDLコードには、出力しているセンサー情報を
 LEDに出力して、目視できるようにしてあります。

 JICA研修で利用したMCR制御基板を使い、CPLDのVHDLコード
 が設計通りに動いているのかを確認します。


 CPLDが出力するセンサー情報を10ピンケーブルでFPGAに
 接続します。



 MCR-VCマシンの移動には、FPGA内部のシーケンサで
 センサー情報を判断し、左右のモータ回転数を制御
 します。
 このシーケンサが、CPLDが出力する情報を利用する
 ので、情報を確実に受取ったかをモニタします。



 もう1枚のMCR制御基板を使い、入力したセンサー情報を
 表示します。センサー情報を正しく受けとって、はじめて
 コース上を移動できるので、センサー情報をモニタする
 ことは、デバッグの基本となります。

 センサー情報モニタを実現するのは、簡単で次のVHDLコード
 を入れるだけです。
    -- input
    iJSENSOR <= SENSOR ;

    -- output
    SOUT  <= not iJSENSOR ;

 正論理で判断できるように、出力を反転しています。
 MCR制御基板のLEDにはインバータがないので、この
 操作を入れます。
 PLDでは、必要なデジタル回路の着脱はデバイスを
 半田付けする必要がないので、楽です。

 MCR制御基板上に、スタート/ゴールプッシュスイッチを
 実装しているので、ゲートセンサーが反応しない場合には
 このスイッチを押すと、マシンが動き出します。

 FPGA内部のシーケンサは、以下の4モードのいずれかに
 なるようにしてあります。

 スタート/ゴールプッシュスイッチを押してから
 どのモードにいるのかを確認できるよう、16個の
 LEDを利用して、状態を表示させます。



 FPGAから、モードと状態の情報をMCR制御基板上の
 LEDに出力します。

 モードは、以下のように状態に分割しています。

 モードと状態の組合せで、どのモードのどんな処理を
 実行しているのかがわかるようにします。

 処理は、8ビットで表現しました。

  STATUS <= not iSTATUS ;

  iSTATUS <= "10000000" when ( iSTATE = 1 ) else -- blind run set   duty  10%
             "10000000" when ( iSTATE = 2 ) else -- blind run delay duty  10%
             "01000000" when ( iSTATE = 3 ) else -- blind run set   duty  25%
             "01000000" when ( iSTATE = 4 ) else -- blind run delay duty  25%
             "00100000" when ( iSTATE = 5 ) else -- blind run set   duty  35%
             "00100000" when ( iSTATE = 6 ) else -- blind run delay duty  35%
             "00010000" when ( iSTATE = 7 ) else -- blind run set   duty  50%
             "00010000" when ( iSTATE = 8 ) else -- blind run delay duty  50%
             "00000001" when ( iSTATE = 10 ) else -- NORMAL get sensor data
             "00000010" when ( iSTATE = 11 ) else -- NORMAL judge
             "00000100" when ( iSTATE = 12 ) else -- NORMAL delay
             "00000001" when ( iSTATE = 13 ) else -- NORMAL return first state 
             "00000001" when ( iSTATE = 20 ) else -- CRANK slow move
             "00000001" when ( iSTATE = 21 ) else -- CRANK slow move (delay)
             "00000010" when ( iSTATE = 22 ) else -- CRANK get road states
             "00000100" when ( iSTATE = 23 ) else -- CRANK judge
             "00001000" when ( iSTATE = 24 ) else -- CRANK turn
             "00010000" when ( iSTATE = 25 ) else -- CRANK turn
             "00010000" when ( iSTATE = 26 ) else -- CRANK turn (delay)
             "00100000" when ( iSTATE = 27 ) else -- CRANK judge center 
             "00100000" when ( iSTATE = 28 ) else -- CRANK judge center 
             "01000000" when ( iSTATE = 29 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 30 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 31 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 32 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 33 ) else -- CRANK complete turn
             "00000001" when ( iSTATE = 40 ) else -- LANE  slow move
             "00000001" when ( iSTATE = 41 ) else -- LANE  slow move (delay)
             "00000010" when ( iSTATE = 42 ) else -- LANE  get road state
             "00000010" when ( iSTATE = 43 ) else -- LANE  get road state (delay)
             "00000100" when ( iSTATE = 44 ) else -- LANE  turn
             "00000100" when ( iSTATE = 45 ) else -- LANE  turn (delay)
             "00001000" when ( iSTATE = 46 ) else -- LANE  center move
             "00001000" when ( iSTATE = 47 ) else -- LANE  center move (delay)
             "00010000" when ( iSTATE = 48 ) else -- LANE  get road state
             "00010000" when ( iSTATE = 49 ) else -- LANE  get road state (delay)
             "00100000" when ( iSTATE = 50 ) else -- LANE  turn
             "00100000" when ( iSTATE = 51 ) else -- LANE  turn (delay)
             "01000000" when ( iSTATE = 52 ) else -- LANE  center move
             "01000000" when ( iSTATE = 53 ) else -- LANE  center move (delay)
             "10000000" when ( iSTATE = 54 ) else -- LANE  return NORMAL
             "00000000" ;

 モードは、4ビットで表示します。

  MODEX <= not iMODEX ;

  iMODE <= 0 when ( iSTATE < 10 )                 else -- BLIND_RUN
           1 when (  9 < iSTATE and iSTATE < 14 ) else -- NORMAL
           2 when ( 19 < iSTATE and iSTATE < 40 ) else -- CRANK
           3 ;

  iMODEX <= "0001" when ( iMODE = 0 ) else -- BLIND_RUN
            "0010" when ( iMODE = 1 ) else -- NORMAL
            "0100" when ( iMODE = 2 ) else -- CRANK
            "1000" when ( iMODE = 3 ) else -- LANE_CHANGE
            "0000" ;

 モードと状態の組合せをLEDに出力する処理は、実走行には
 関係ありません。テスト、デバッグのときだけに必要になり
 ます。テスト、デバッグが必要なくなったときは、10ピン
 ケーブルをFPGA基板から外すだけです。

 マイコン利用では、プログラム実行のため、テスト、デバッグ
 用コードは、処理を遅くすることになりますが、PLDを使うと
 並列動作なので、処理が遅くなることはありません。

 この机上デバッグで、次の3つのバグを発見できました。

 机上デバッグが終わった時点のFPGAのVHDLコードは
 次のようになりました。

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

entity mcrvcx0 is
  generic (
    TOPX : integer := 2  ;
    RMAX : integer := 3  ;
    TOPY : integer := 3  ;
    YMAX : integer := 4 ;
    TOPZ : integer := 9  ;
    ZMAX : integer := 500 --;
  );
  port (
    -- system
    nRESET : in  std_logic ;
    CLOCK  : in  std_logic ;
    -- sensor input
    SENSOR : in  std_logic_vector(7 downto 0) ;
    -- sensor output
    SOUT   : out std_logic_vector(7 downto 0) ;
    -- PWM , trigger and direciton
    POUTR  : out std_logic ; -- right motor duty ratio
    POUTL  : out std_logic ; -- left  motor duty ratio
    SGTRG  : in  std_logic ; -- start goal trigger
    GLED   : out std_logic ; -- run
    RLED   : out std_logic ; -- cross white line
    -- output
    MODEX  : out std_logic_vector(3 downto 0) ;
    LDIR   : out std_logic ;
    RDIR   : out std_logic ;
    STATUS : out std_logic_vector(7 downto 0) --;
  );
end mcrvcx0;

architecture Behavioral of mcrvcx0 is
  -- component clock generator
  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 ;
  -- judge
  component judge is
    port (
      -- input
      DIN  : in  std_logic_vector(7 downto 0) ;
      -- output
      JOUT : out std_logic_vector(3 downto 0) --;
    );
  end component ;
  -- component PWM
  component pwmx is 
    port(
      -- system
      nRESET : in  std_logic ;
      CLOCK  : in  std_logic ;
      -- input
      PRATER : in  std_logic_vector(5 downto 0) ;
      PRATEL : in  std_logic_vector(5 downto 0) ;
      -- output
      POUTR  : out std_logic ;
      POUTL  : out std_logic --;
    );
  end component ;
  -- clock 
  signal iMCLK  : std_logic ;
  signal iPCLK  : std_logic ;
  signal iPWCLK : std_logic ;
  -- divider
  signal iDCLK  : std_logic ;
  signal iDCNT  : integer range 0 to 50 ;
  -- trigger
  signal iSGTRG_SFT : std_logic_vector(2 downto 0) ;
  signal iTRG_R     : std_logic ;
  -- sensor
  signal iSENSOR : std_logic_vector(7 downto 0) ;
  -- master sequencer
  signal iSTATE     : integer range 0 to 54;
  signal iDIRECTION : std_logic_vector(1 downto 0) ;
  -- judge run sequencer
  signal iJSENSOR : std_logic_vector(7 downto 0) ;
  signal iJOUT    : std_logic_vector(3 downto 0) ;
  signal iMODE    : integer range 0 to 3 ;
  signal iMODEX   : std_logic_vector(3 downto 0) ;
  signal iJCNT    : integer range 0 to 60 ;
  -- 
  signal iSTATUS : std_logic_vector(7 downto 0) ;
  -- PWM 
  signal iPRATER : std_logic_vector(5 downto 0) ;
  signal iPRATEL : std_logic_vector(5 downto 0) ;
  signal iPOUTR  : std_logic ;
  signal iPOUTL  : std_logic ;
  signal iGLED   : std_logic ;
  signal iRLED   : std_logic ;
begin
  -- component clock generator (48MHz/6 = 8MHz)
  CLKX : clkgenx generic map (TOPX,RMAX) port map (nRESET,CLOCK,iMCLK);
  -- component clock generator ( 8MHz/8 = 1MHz)
  CLKY : clkgenx generic map (TOPY,YMAX) port map (nRESET,iMCLK,iPCLK);
  -- component clock generator ( 1MHz/1000 = 1kHz)
  CLKZ : clkgenx generic map (TOPZ,ZMAX) port map (nRESET,iPCLK,iPWCLK);
  -- judge
  JUDGEX : judge port map (iSENSOR,iJOUT) ;
  -- component PWM
  PWM : pwmx port map (nRESET,iPWCLK,iPRATER,iPRATEL,iPOUTR,iPOUTL);

  -- input
  iJSENSOR <= SENSOR ;

  -- output
  SOUT  <= not iJSENSOR ;
  POUTR <= iPOUTR ;
  POUTL <= iPOUTL ;
  GLED  <= not iGLED ;
  RLED  <= not iRLED ;
  MODEX <= not iMODEX ;

  LDIR  <= not iDIRECTION(1) ;
  RDIR  <= not iDIRECTION(0) ;

  -- monitor
  STATUS <= not iSTATUS ;

  iGLED <= '1' when ( iSTATE > 0 ) else '0' ;
  iRLED <= '1' when ( iJSENSOR = X"FF" ) else '0' ;

  -- internal status
  iSTATUS <= "10000000" when ( iSTATE = 1 ) else -- blind run set   duty  10%
             "10000000" when ( iSTATE = 2 ) else -- blind run delay duty  10%
             "01000000" when ( iSTATE = 3 ) else -- blind run set   duty  25%
             "01000000" when ( iSTATE = 4 ) else -- blind run delay duty  25%
             "00100000" when ( iSTATE = 5 ) else -- blind run set   duty  35%
             "00100000" when ( iSTATE = 6 ) else -- blind run delay duty  35%
             "00010000" when ( iSTATE = 7 ) else -- blind run set   duty  50%
             "00010000" when ( iSTATE = 8 ) else -- blind run delay duty  50%
             "00000001" when ( iSTATE = 10 ) else -- NORMAL get sensor data
             "00000010" when ( iSTATE = 11 ) else -- NORMAL judge
             "00000100" when ( iSTATE = 12 ) else -- NORMAL delay
             "00000001" when ( iSTATE = 13 ) else -- NORMAL return first state 
             "00000001" when ( iSTATE = 20 ) else -- CRANK slow move
             "00000001" when ( iSTATE = 21 ) else -- CRANK slow move (delay)
             "00000010" when ( iSTATE = 22 ) else -- CRANK get road states
             "00000100" when ( iSTATE = 23 ) else -- CRANK judge
             "00001000" when ( iSTATE = 24 ) else -- CRANK turn
             "00010000" when ( iSTATE = 25 ) else -- CRANK turn
             "00010000" when ( iSTATE = 26 ) else -- CRANK turn (delay)
             "00100000" when ( iSTATE = 27 ) else -- CRANK judge center 
             "00100000" when ( iSTATE = 28 ) else -- CRANK judge center 
             "01000000" when ( iSTATE = 29 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 30 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 31 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 32 ) else -- CRANK complete turn
             "10000000" when ( iSTATE = 33 ) else -- CRANK complete turn
             "00000001" when ( iSTATE = 40 ) else -- LANE  slow move
             "00000001" when ( iSTATE = 41 ) else -- LANE  slow move (delay)
             "00000010" when ( iSTATE = 42 ) else -- LANE  get road state
             "00000010" when ( iSTATE = 43 ) else -- LANE  get road state (delay)
             "00000100" when ( iSTATE = 44 ) else -- LANE  turn
             "00000100" when ( iSTATE = 45 ) else -- LANE  turn (delay)
             "00001000" when ( iSTATE = 46 ) else -- LANE  center move
             "00001000" when ( iSTATE = 47 ) else -- LANE  center move (delay)
             "00010000" when ( iSTATE = 48 ) else -- LANE  get road state
             "00010000" when ( iSTATE = 49 ) else -- LANE  get road state (delay)
             "00100000" when ( iSTATE = 50 ) else -- LANE  turn
             "00100000" when ( iSTATE = 51 ) else -- LANE  turn (delay)
             "01000000" when ( iSTATE = 52 ) else -- LANE  center move
             "01000000" when ( iSTATE = 53 ) else -- LANE  center move (delay)
             "10000000" when ( iSTATE = 54 ) else -- LANE  return NORMAL
             "00000000" ;

  -- divider 1kHz / 100 = 10Hz
  process (nRESET,iPWCLK)
  begin
    if ( nRESET = '0' ) then
      iDCNT <= 0   ;
      iDCLK <= '0' ;
    elsif rising_edge(iPWCLK) then
      if ( iDCNT = 50 ) then
        iDCNT <= 0 ;
        iDCLK <= not iDCLK ;
      else
        iDCNT <= iDCNT + 1 ;
      end if ;
    end if ;
  end process ;

  -- trigger
  process (nRESET,iDCLK)
  begin
    if ( nRESET = '0' ) then
      iSGTRG_SFT <= "000" ;
    elsif rising_edge(iDCLK) then
      iSGTRG_SFT <= iSGTRG_SFT(1 downto 0) & (not SGTRG) ;
    end if ;
  end process ;
  iTRG_R <= '1' when ( iSGTRG_SFT = "011" or iSGTRG_SFT = "001" ) else '0' ;

  -- master sequencer
  process (nRESET,iDCLK)
  begin
    if ( nRESET = '0' ) then
      iSTATE     <= 0 ;
      iDIRECTION <= "00" ;
    elsif rising_edge(iDCLK) then
      case conv_integer(iSTATE) is
        -- wait RFLAG rising edge
        when 0 => if ( iTRG_R = '1' ) then
                    iSTATE <= 1 ;
                  end if ;
        -- send blind run trigger (10%)
        when 1 => iSTATE  <= 2 ;
                  iPRATER <= conv_std_logic_vector(10,6) ;
                  iPRATEL <= conv_std_logic_vector(10,6) ;
                  iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
        -- delay blind run (10%)
        when 2 => if ( iJCNT = 0 ) then
                    iSTATE <= 3 ;
                  else
                    iJCNT  <= iJCNT - 1 ;
                    iSTATE <= 2 ;
                  end if ;
        -- send blind run trigger (25%)
        when 3 => iSTATE  <= 4 ;
                  iPRATER <= conv_std_logic_vector(25,6) ;
                  iPRATEL <= conv_std_logic_vector(25,6) ;
                  iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
        -- delay blind run (25%)
        when 4 => if ( iJCNT = 0 ) then
                    iSTATE <= 5 ;
                  else
                    iJCNT  <= iJCNT - 1 ;
                    iSTATE <= 4 ;
                  end if ;
        -- send blind run trigger (35%)
        when 5 => iSTATE  <= 6 ;
                  iPRATER <= conv_std_logic_vector(35,6) ;
                  iPRATEL <= conv_std_logic_vector(35,6) ;
                  iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
        -- delay blind run (35%)
        when 6 => if ( iJCNT = 0 ) then
                    iSTATE <= 7 ;
                  else
                    iJCNT  <= iJCNT - 1 ;
                    iSTATE <= 6 ;
                  end if ;
        -- send blind run trigger (50%)
        when 7 => iSTATE  <= 8 ;
                  iPRATER <= conv_std_logic_vector(50,6) ;
                  iPRATEL <= conv_std_logic_vector(50,6) ;
                  iJCNT   <= 20 ; -- 2sec 10Hz = 100ms
        -- delay blind run (50%)
        when 8 => if ( iJCNT = 0 ) then
                    iSTATE <= 9 ;
                  else
                    iJCNT  <= iJCNT - 1 ;
                    iSTATE <= 8 ;
                  end if ;
        -- branch NORMAL run
        when 9 => iSTATE <= 10 ;
        -- NORMAL (get sensor data)
        when 10 => iSENSOR <= iJSENSOR ;
                   iSTATE  <= 11 ;
        -- NORMAL (judge)
        when 11 => if ( iJCNT = 10 ) then -- all_white
                     iSTATE <= 20 ;
                   elsif ( iJCNT = 8 ) then -- left_white
                     iDIRECTION <= "10" ; -- left
                     iSTATE     <= 40 ;
                   elsif ( iJCNT = 9 ) then -- right_white
                     iDIRECTION <= "01" ; -- right
                     iSTATE     <= 40 ;
                   elsif ( iJCNT = 4 ) then -- center
                     iPRATER <= conv_std_logic_vector(35,6) ;
                     iPRATEL <= conv_std_logic_vector(35,6) ;
                     iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   elsif ( iJCNT = 1 ) then -- tiny_right
                     iPRATER <= conv_std_logic_vector(35,6) ;
                     iPRATEL <= conv_std_logic_vector(15,6) ;
                     iJCNT   <= 5 ; -- 0.5sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   elsif ( iJCNT = 2 ) then -- right
                     iPRATER <= conv_std_logic_vector(35,6) ;
                     iPRATEL <= conv_std_logic_vector( 5,6) ;
                     iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   elsif ( iJCNT = 3 ) then -- big_right
                     iPRATER <= conv_std_logic_vector(45,6) ;
                     iPRATEL <= conv_std_logic_vector( 5,6) ;
                     iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   elsif ( iJCNT = 5 ) then -- tiny_left
                     iPRATER <= conv_std_logic_vector(15,6) ;
                     iPRATEL <= conv_std_logic_vector(35,6) ;
                     iJCNT   <= 5  ; -- 0.5sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   elsif ( iJCNT = 6 ) then -- left
                     iPRATER <= conv_std_logic_vector( 5,6) ;
                     iPRATEL <= conv_std_logic_vector(35,6) ;
                     iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   elsif ( iJCNT = 7 ) then -- big_left
                     iPRATER <= conv_std_logic_vector( 5,6) ;
                     iPRATEL <= conv_std_logic_vector(45,6) ;
                     iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   else
                     iDIRECTION <= "00" ; -- center
                     iJCNT   <= 10 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 12 ;
                   end if ;
        -- NORMAL (delay)
        when 12 => if ( iJCNT = 0 ) then
                     iSTATE <= 13 ;
                   else
                     iJCNT <= iJCNT - 1 ;
                     iSTATE <= 12 ;
                   end if ;
        -- NORMAL (return first state)
        when 13 => if ( iTRG_R = '1' ) then
                     iSTATE <=  0 ;
                   else
                     iSTATE <= 10 ;
                   end if ;
        -- CRANK (slow move)
        when 20 => iSTATE  <= 21 ;
                   iPRATER <= conv_std_logic_vector(15,6) ;
                   iPRATEL <= conv_std_logic_vector(15,6) ;
                   iJCNT   <= 30 ; -- 3sec 10Hz = 100ms
        -- CRANK (delay)
        when 21 => if ( iJCNT = 0 ) then
                     iSTATE <= 22 ;
                   else
                     iJCNT <= iJCNT - 1 ;
                     iSTATE <= 21 ;
                   end if ;
        -- CRANK (get road information)
        when 22 => iSENSOR    <= iJSENSOR ;
                   iDIRECTION <= "00" ; -- center
                   iSTATE     <= 23 ;
        -- CRANK (judge)
        when 23 => -- right_white
                   if ( iJOUT = 8 ) then
                     iSTATE     <= 25 ;
                     iDIRECTION <= "01" ; -- right
                   -- left_white
                   elsif ( iJOUT = 9 ) then
                     iSTATE     <= 25 ;
                     iDIRECTION <= "10" ; -- left
                   else
                     iPRATER <= conv_std_logic_vector(15,6) ;
                     iPRATEL <= conv_std_logic_vector(15,6) ;
                     iJCNT   <= 1 ; -- 1sec 10Hz = 100ms
                     iSTATE  <= 24 ;
                   end if ;
        -- CRANK (delay)
        when 24 => if ( iJCNT = 0 ) then
                     iSTATE <= 22 ;
                   else
                     iSTATE <= 24 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- CRANK (turn)
        when 25 => iSTATE <= 26 ;
                   iJCNT  <= 2 ; -- 2sec 10Hz = 100ms
                   -- right_turn
                   if ( iDIRECTION = "01" ) then
                     iPRATER <= conv_std_logic_vector( 0,6) ;
                     iPRATEL <= conv_std_logic_vector(30,6) ;
                   -- left_white
                   elsif ( iDIRECTION = "10" ) then
                     iPRATER <= conv_std_logic_vector(30,6) ;
                     iPRATEL <= conv_std_logic_vector( 0,6) ;
                   end if ;
        -- CRANK (turn delay)
        when 26 => if ( iJCNT = 0 ) then
                     iSTATE <= 27 ;
                   else
                     iSTATE <= 26 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- CRANK (get road information)
        when 27 => iSENSOR <= iJSENSOR ;
                   iSTATE  <= 28 ;
        -- CRANK (judge center)
        when 28 => -- center
                   if ( iJOUT = 4 ) then
                     iSTATE <= 29 ;
                   else
                     iJCNT  <= 1 ; -- 1sec 10Hz = 100ms
                     iSTATE <= 28 ;
                   end if ;
        -- CRANK (turn delay center)
        when 29 => if ( iJCNT = 0 ) then
                     iSTATE <= 30 ;
                   else
                     iSTATE <= 29 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- CRANK (complete turn)
        when 30 => 
                   iSTATE <= 31 ;
                   iJCNT  <= 2 ; -- 2sec 10Hz = 100ms
                   -- right_turn
                   if ( iDIRECTION = "01" ) then
                     iPRATER <= conv_std_logic_vector(30,6) ;
                     iPRATEL <= conv_std_logic_vector(15,6) ;
                   -- left_white
                   elsif ( iDIRECTION = "10" ) then
                     iPRATER <= conv_std_logic_vector(15,6) ;
                     iPRATEL <= conv_std_logic_vector(30,6) ;
                   end if ;
        -- CRANK (delay exit turn)
        when 31 => if ( iJCNT = 0 ) then
                     iSTATE <= 32 ;
                   else
                     iSTATE <= 31 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- CRANK (center move)
        when 32 => iSTATE  <= 33 ;
                   iPRATER <= conv_std_logic_vector(15,6) ;
                   iPRATEL <= conv_std_logic_vector(15,6) ;
                   iJCNT   <= 20 ; -- 2sec 10Hz = 100ms
        -- CRANK (delay center move)
        when 33 => if ( iJCNT = 0 ) then
                     iSTATE <= 34 ;
                   else
                     iSTATE <= 33 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- return NORMAL run
        when 34 => iSTATE <= 10 ;
        -- LANE (blind run)
        when 40 => iSTATE  <= 41 ;
                   iPRATER <= conv_std_logic_vector(15,6) ;
                   iPRATEL <= conv_std_logic_vector(15,6) ;
                   iJCNT   <= 20 ; -- 2sec 10Hz = 100ms
        -- LANE (blind run delay)
        when 41 => if ( iJCNT = 0 ) then
                     iSTATE <= 42 ;
                   else
                     iSTATE <= 41 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- LANE (get sensor data)
        when 42 => iSENSOR <= iJSENSOR ;
                   iSTATE  <= 43 ;
        -- LANE (judge all black)
        when 43 => if ( iJOUT = 0 ) then
                     iSTATE <= 44 ;
                   else
                     iSTATE <= 42 ;
                   end if ;
        -- LANE (turn)
        when 44 => iSTATE <= 45 ;
                   iJCNT  <= 20 ; -- 2sec 10Hz = 100ms
                   -- right_turn
                   if ( iDIRECTION = "01" ) then
                     iPRATER <= conv_std_logic_vector( 0,6) ;
                     iPRATEL <= conv_std_logic_vector(30,6) ;
                   -- left_white
                   elsif ( iDIRECTION = "10" ) then
                     iPRATER <= conv_std_logic_vector(30,6) ;
                     iPRATEL <= conv_std_logic_vector( 0,6) ;
                   end if ;
        -- LANE (turn delay)
        when 45 => if ( iJCNT = 0 ) then
                     iSTATE <= 46 ;
                   else
                     iSTATE <= 45 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- LANE (center move)
        when 46 => iSTATE  <= 47 ;
                   iJCNT   <= 20 ; -- 2sec 10Hz = 100ms
                   iPRATER <= conv_std_logic_vector(15,6) ;
                   iPRATEL <= conv_std_logic_vector(15,6) ;
        -- LANE (turn delay)
        when 47 => if ( iJCNT = 0 ) then
                     iSTATE <= 48 ;
                   else
                     iSTATE <= 47 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- LANE (get sensor data)
        when 48 => iSENSOR <= iJSENSOR ;
                   iSTATE  <= 49 ;
        -- LANE (judge center)
        when 49 => if ( iJOUT = 4 ) then
                     iSTATE <= 50 ;
                   else
                     iSTATE <= 48 ;
                   end if ;
        -- LANE (turn)
        when 50 => iSTATE <= 51 ;
                   iJCNT  <= 20 ; -- 2sec 10Hz = 100ms
                   -- right_turn
                   if ( iDIRECTION = 1 ) then
                     iPRATER <= conv_std_logic_vector(30,6) ;
                     iPRATEL <= conv_std_logic_vector( 0,6) ;
                   -- left_white
                   elsif ( iDIRECTION = 2 ) then
                     iPRATER <= conv_std_logic_vector( 0,6) ;
                     iPRATEL <= conv_std_logic_vector(30,6) ;
                   end if ;
        -- LANE (turn delay)
        when 51 => if ( iJCNT = 0 ) then
                     iSTATE <= 52 ;
                   else
                     iSTATE <= 51 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- LANE (center move)
        when 52 => iSTATE  <= 53 ;
                   iJCNT   <= 20 ; -- 2sec 10Hz = 100ms
                   iPRATER <= conv_std_logic_vector(15,6) ;
                   iPRATEL <= conv_std_logic_vector(15,6) ;
        -- LANE (turn delay)
        when 53 => if ( iJCNT = 0 ) then
                     iSTATE <= 54 ;
                   else
                     iSTATE <= 53 ;
                     iJCNT  <= iJCNT - 1 ;
                   end if ;
        -- return NORMAL run
        when 54 => iSTATE     <= 10 ;
                   iDIRECTION <= "00" ; -- center
        -- default
        when others => 
                   iSTATE <= 0 ;
      end case ;
    end if ;
  end process ;
  iMODE <= 0 when ( iSTATE < 10 )                 else -- BLIND_RUN
           1 when (  9 < iSTATE and iSTATE < 14 ) else -- NORMAL
           2 when ( 19 < iSTATE and iSTATE < 40 ) else -- CRANK
           3 ;

  iMODEX <= "0001" when ( iMODE = 0 ) else -- BLIND_RUN
            "0010" when ( iMODE = 1 ) else -- NORMAL
            "0100" when ( iMODE = 2 ) else -- CRANK
            "1000" when ( iMODE = 3 ) else -- LANE_CHANGE
            "0000" ;

end Behavioral;

 コース情報を、実際の路面から拾い出すのは面倒
 なので、乱数を利用し、大まかな内容を生成する
 スクリプトを記述しました。

for {set i 0} {$i < 32} {incr i} {
  # generate 
  set ans [lindex [split [expr rand()*17] "."] 0]
  # 2 columns
  set ans [format "%2d" $ans]
  # generate strings
  set tmp ""
  set sdat "0x00"
  if { $ans == 0 } {
    set tmp "all_black"
  }
  if { $ans == 1 } {
    set tmp "tiny_right"
    set sdat "0x0C"
  }
  if { $ans == 2 } {
    set tmp  "right"
    set sdat "0x06"
  }
  if { $ans == 3 } {
    set tmp  "big_right"
    set sdat "0x03"
  }
  if { $ans == 4 } {
    set tmp "center0"
    set sdat "0x18"
  }
  if { $ans == 5 } {
    set tmp  "center1"
    set sdat "0x1C"
  }
  if { $ans == 6 } {
    set tmp  "center2"
    set sdat "0x38"
  }
  if { $ans == 7 } {
    set tmp  "tiny_left"
    set sdat "0x30"
  }
  if { $ans == 8 } {
    set tmp  "left"
    set sdat "0x60"
  }
  if { $ans == 9 } {
    set tmp  "big_left"
    set sdat "0xC0"
  }
  if { $ans == 10 } {
    set tmp  "left_white0"
    set sdat "0xE0"
  }
  if { $ans == 11 } {
    set tmp  "left_white1"
    set sdat "0xF0"
  }
  if { $ans == 12 } {
    set tmp  "left_white2"
    set sdat "0xF8"
  }
  if { $ans == 13 } {
    set tmp  "right_white0"
    set sdat "0x07"
  }
  if { $ans == 14 } {
    set tmp  "right_white1"
    set sdat "0x0F"
  }
  if { $ans == 15 } {
    set tmp  "right_white2"
    set sdat "0x1F"
  }
  if { $ans == 16 } {
    set tmp  "all_white"
    set sdat "0xFF"
  }
  puts "$ans $sdat $tmp"
}

 センサー情報は、8ビットデータで生成するので
 乱数により0〜16の整数、文字列、16進数の
 データに変換します。

 テキストファイルに出力すると、次のようになります。

 9 0xC0 big_left
 3 0x03 big_right
10 0xE0 left_white0
 9 0xC0 big_left
12 0xF8 left_white2
15 0x1F right_white2
 3 0x03 big_right
 8 0x60 left
 3 0x03 big_right
12 0xF8 left_white2
15 0x1F right_white2
14 0x0F right_white1
 6 0x38 center2
 2 0x06 right
16 0xFF all_white
14 0x0F right_white1
12 0xF8 left_white2
16 0xFF all_white
13 0x07 right_white0
10 0xE0 left_white0
10 0xE0 left_white0
 3 0x03 big_right
 2 0x06 right
 6 0x38 center2
 8 0x60 left
 0 0x00 all_black
 3 0x03 big_right
 1 0x0C tiny_right
15 0x1F right_white2
 5 0x1C center1
 9 0xC0 big_left
11 0xF0 left_white1

 この内容を、実際のコースに合わせて、矛盾の
 ない並びに変換して、VHDLコードの中に埋込み
 デバッグに利用します。

目次

inserted by FC2 system