目次

VHDLステートマシン記述作成(AWK)

 VHDLを利用して、CPLD/FPGA内部にデジタル回路の
 情報を記述します。

 VHDLを使うのは、ステートマシンを簡単に記述できる
 ことが挙げられます。これで、マイコンのような動作
 をデジタル回路で実現できます。

 ステートマシンは、状態遷移図に相当する動作と
 等価な動きをします。状態遷移図の例は、以下。



 ステートマシンは、カウンタを利用しますが
 外部からの指定条件で、カウンタの動作を止
 めたり、次の値に遷移するのを待たせること
 ができます。

 カウンタはクロックで動きますが、クロックが
 入ったとしても、次の値に遷移するか、現在値
 に留まるのかを、条件により指定します。

 簡単なステートマシンの記述は、以下。

  process (nRESET,CLOCK)
  begin
    if ( nRESET = '0' ) then
      iSTATE  <= "00" ;
      iGSTATE <= '0' ;
    elsif rising_edge(CLOCK) then
      case conv_integer(iSTATE) is
        -- wait trigger
        when 0 => if ( iSTRG = '1' ) then
                    iSTATE <= "01" ;
                  else
                    iSTATE <= "00" ;
                  end if ;
        -- reset and send trigger
        when 1 => iSTATE <= "11" ;
        -- wait trigger
        when 3 => if ( iURES = '1' ) then -- answer back
                    iSTATE  <= "10" ;
                    iGSTATE <= '1' ;
                  elsif ( iTOUT = '1' ) then -- time out
                    iSTATE  <= "10" ;
                    iGSTATE <= '0' ;
                  else
                    iSTATE <= "11" ;
                  end if ;
        -- return first state
        when 2 => iSTATE <= "00" ;
        -- default
        when others => 
                  iSTATE <= "00" ;
      end case ;
    end if ;
  end process ;

 ステートマシンは、ベースとなるカウンタのビット数を
 2から5程度にしますが、4ステートを扱うことが多い
 ので、2ビットとして考えます。

 2ビットカウンタは、状態変化するビットが1個に限定
 したジョンソンカウンタを使います。状態は、2進数で
 見ると00→01→11→10と変化します。

 この方式でスクリプトを作成しました。

{
  printf("process (nRESET,CLOCK)\n")
  printf("begin\n")
  printf("  if ( nRESET = '0' ) then\n")
  printf("    %s <= \"00\" ;\n",$1)
  printf("  elsif rising_edge(CLOCK) then\n")
  printf("    case conv_integer( %s ) is\n",$1)
  printf("      -- wait trigger \n")
  printf("      when 0 => if ( %s = '1' ) then\n",$2)
  printf("                  %s <= \"01\" ;\n",$1)
  printf("                else\n")
  printf("                  %s <= \"00\" ;\n",$1)
  printf("                end if ;\n")
  printf("      -- \n")
  printf("      when 1 => %s <= \"11\" ;\n",$1)
  printf("      -- \n")
  printf("      when 3 => %s <= \"10\" ;\n",$1)
  printf("      -- return first state\n")
  printf("      when 2 => %s <= \"00\" ;\n",$1)
  printf("      -- default\n")
  printf("      when others => \n")
  printf("                %s <= \"00\" ;\n",$1)
  printf("    end case ;\n")
  printf("  end if ;\n")
  printf("end process ;\n")
}

 2つのパラメータを利用します。

 カウンタを扱う変数名と条件を指定する変数を
 用意し、テキストファイルに入れ当てはめます。

 条件が増えたり、遷移の仕方が複雑になるときは
 テキストエディタで変更すればよいと割切ります。

 叩き台になるコードを短時間で作成することを
 考え、複雑な処理に変更するのは叩き台を利用
 するとします。

 次のようにCUIで使います。



 パラメータは、テキストファイルに入れています。
 内容は、以下としました。

iSTATE iTRG


 生成されるコードは、I/Oリダイレクトを使い
 テキストファイルに保存すれば、使い回しが
 効きます。

 パラメータを次のように変更しての動作確認も
 してあります。

iBSTA iWTRG



 ステート値が順番に+1される場合のAWKスクリプトは
 以下とします。

BEGIN {
  print "process (nRESET,CLOCK)"
  print "begin"
  print "  if ( nRESET = '0' ) then"
}
{
  last = $2
  printf("    %s <= 0 ;\n",$1)
  printf("  elsif rising_edge(CLOCK) then\n")
  printf("    case %s is\n",$1)
  for ( i = 0 ; i < last ; i++ ) {
    printf("      -- \n")
    printf("      when %d => %s <= ",i,$1)
    if ( i == last-1 ) {
      printf(" 0 ;\n")
    } else {
      printf(" %d ;\n",i+1)
    }
  }
  printf("      -- default\n")
  printf("      when others => %s <= 0 ;\n",$1)
  printf("    end case ;\n")
}
END {
  print "  end if ;"
  print "end process ;"
}

 パラメータを次のように指定して動作確認します。

iSTATE 4

 CUIでは、次のようになります。




目次

inserted by FC2 system