順序回路の応用として,ステートマシンの設計をしてみましょう.ステートマ シンの動作は一般的に状態遷移図によって表されます.ステートマシンは,マ イクロプロセッサの動作の基本となる制御信号の生成に使われたり,いろいろ な制御回路の中心的な役割を果たす順序回路といえます.
ステートマシンをゲートレベルで設計する場合には,カウンタ回路をフリップ フロップによって構成してクロックに同期したタイミング信号を生成させます. そして,そのタイミング信号に論理ゲートを組み合わせて,目的の制御信号を 生成します.VHDLでは,「状態」の定義と「その状態の時に何をするか」を記 述するだけで,目的のステートマシンを表現できます.つまり,状態遷移図と VHDLによる記述が,ほぼ1対1に対応するのです.
ここでは,クロック信号に同期して動作する制御回路を設計してみましょう. <図:ステート・マシン(a)>に目的の制御回路を,(b)にタイミング・チャート を,(c)にその状態遷移図を示します
図:ステート・マシン
この制御回路は特に意味を持った制御信号を出すわけではありません.あくま で例題です.制御回路への入力信号は,回路の動作を開始させるSTART,状態 を初期状態へ戻すRST,ある状態をとばすJP,そしてクロック信号CLKです.同 図(b)のタイミング・チャートは,この制御回路の動作例を示しています.(c) の状態遷移図がすべての動作を表しています.なお,状態の遷移はすべてクロッ ク信号の立ち上がりで行なうとします.
では,<図:ステート・マシン>に示した制御回路をVHDLで記述しましょう.次に示すのが,VHDLで記述した制御回路です.アーキテクチャ本体では,まず状態変数STATEの使用を宣言します.
type STATE_T is (S0,S1,S2,S3); signal STATE: STATE_T;
次に状態遷移の記述をします.これは状態遷移の記述と出力信号の記述の2つ の部分に分けて記述します.まず,状態遷移の記述です.
STATE_UPDATES: process(CLK)
これで状態の遷移の記述はできました.次の記述は,
OUTPUT_DESCRIPTION: process(STATE)
以上のように制御回路の設計は非常に簡単にできることがおわかり頂けたこ とでしょう.状態遷移図と出力表を決めれば,記述は簡単です.ここで例にし た制御回路は非常に簡単なものですが,制御回路の設計にあたっては,ここに 述べた記述を理解していればいくらでも複雑な回路を記述できます.あなたは すでに,マイクロプロセッサの心臓部でもある制御回路を記述する能力を身に つけていることでしょう.
-- ライブラリ宣言 library IEEE; use IEEE.std_logic_1164.all; -- エンティティ宣言 entity sequencer is port ( START, JP, RESET, CLK : in std_logic; RA, RB, TM : out std_logic ); end sequencer; -- アーキテクチャ本体 architecture sequencer_body of sequencer is type STATE_T is ( S0, S1, S2, S3 ); signal STATE : STATE_T; begin STATE_UPDATES: process( CLK, RESET ) begin if RESET = '1' then -- 非同期リセット STATE <= S0; elsif CLK'event and CLK = '1' then -- クロックの立ち上がりの検出 case STATE is when S0 => if START = '1' then STATE <= S1; -- 動作開始 else STATE <= S0; end if; when S1 => if (JP = '1') then STATE <= S3; -- 状態のジャンブ else STATE <= S2; end if; when S2 => STATE <= S3; when S3 => STATE <= S0; -- 初期状態へ end case; end if; end process; -- 該当状態時の出力信号の記述 OUTPUT_DESCRIPTION: process( STATE ) begin case STATE is when S0 => RA <= '0'; RB <= '0'; TM <= '0'; when S1 => RA <= '1'; RB <= '0'; TM <= '0'; when S2 => RA <= '1'; RB <= '1'; TM <= '0'; when S3 => RA <= '0'; RB <= '0'; TM <= '1'; end case; end process; end sequencer_body;
-- 該当状態時の出力信号の記述 OUTPUT_DESCRIPTION: process( STATE ) begin RA <= '0'; -- まず,全てを '0' にしておいて… RB <= '0'; TM <= '0'; case STATE is -- '1' に変化するところだけを記述 when S1 => RA <= '1'; when S2 => RA <= '1'; RB <= '1'; when S3 => TM <= '1'; when others => null; -- なにも変化しない時 ( 忘れずに ) end case; end process;