ムーア型にするべきか?ミーリ型にするべきか?

前回はムーア型状態機械を用いて順序回路を実現した。
今回はミーリ型状態機械を用いた順序回路の設計をやってみよう。

まずは設計する回路の仕様から。

『プッシュスイッチpush1, push2, push3がある。push1,push2,push3の順に押されたらledが点灯する回路を設計せよ』

で、ムーア型と同じく状態遷移図を書く。
ただし、「条件分岐(入力)」と「出力」を同時に考慮する。
矢印に「条件分岐/そのときの出力」を書く。

fsm_03.jpg

するとこうなる。前回と異なるのは出力も同時に考えていること。

この状態遷移図は

  1. reset==1ならばstate0に遷移しled=0(あ、上の図に描き忘れてる…)
  2. state0のとき、push1==1ならばstate1に遷移し, led=0。そうでなければstate0のままで, led=0。
  3. state1のとき、push2==1ならばstate2に遷移し, led=0。そうでなければstate1のままで, led=0。
  4. state2のとき、push3==1ならばstate3に遷移し, led=1。そうでなければstate2のままで, led=0。
  5. state3のとき、state3に遷移し, led=1

要は出力を考えるとき、現在の状態と現在の入力を同時に考慮する。
図で描くとこうなる。

seq_02.jpg

一方、前回のムーア型では

seq_01.jpg

意図する回路がはっきり異なっているのがわかる。

両者の長所短所は

  • ムーア型
    • 長所:コンパクトな回路を合成できる。その結果速くなる。
    • 短所:状態数がミーリ型より多くなりがち
  • ミーリ型
    • 長所:状態数がムーア型より少なくなることが多い。verilogで書きやすい。
    • 短所:回路が大きくなりがち。

verilogで書きやすいのは私の完全な主観なので反論はあって当然だと思う。
でも私はミーリ型で書くことをおすすめする。
どうしても速さを求めたり、コンパクトな回路を設計したい場合はムーア型で。
なぜ、ミーリ型のほうが記述が楽かというと、always文の中で出力と状態遷移を一度に記述できるからだ。

というわけで、実際にverilogを書いていこう。

この符号が記憶素子で保持する変数になるから、reg宣言で宣言する。
もちろん順序回路だからclock, resetを用意する。
従って、モジュール宣言部は

module seq_circuit( clock, reset, push1, push2, push3, led);
endmodule

であり、入出力信号・reg信号を宣言すると

module seq_circuit( clock, reset, push1, push2, push3, led);
  input clock, reset;
  input push1, push2, push3;
  output led;

  reg [1:0]state;
  reg led;
endmodule

ここで注意してもらいたいのはledという信号をreg,output両方で宣言していることだ。
(always文内ではレジスタ信号のみしか代入できないというルールがあるため)

次に順序回路を記述していこう。クロックが立ち上がるたびに記憶素子を更新していくので、

module seq_circuit( clock, reset, push1, push2, push3, led);
  input clock, reset;
  input push1, push2, push3;
  output led;

  reg [1:0]state;
  reg led;
  
  always@( posedge clock or posedge reset)begin
  end

endmodule

となる。もちろん記憶素子は初期化しなければならないので

module seq_circuit( clock, reset, push1, push2, push3, led);
  input clock, reset;
  input push1, push2, push3;
  output led;

  reg [1:0]state;
  reg led;
  
  always@( posedge clock or posedge reset)begin
    if( reset == 1'b1)begin
      state <= 2'b00;
      led   <= 1'b0;
    end else begin
      
    end
  end

endmodule

状態遷移図をコードに起こす。さきほど示した箇条書きに従って論理を記述していこう。

module seq_circuit( clock, reset, push1, push2, push3, led);
  input clock, reset;
  input push1, push2, push3;
  output led;

  reg [1:0]state;
  reg led;
  
  always@( posedge clock or posedge reset)begin
    if( reset == 1'b1)begin
      state <= 2'b00;
      led   <= 1'b0;
    end else begin
      if( state == 2'b00)begin
        if( push1 == 1'b1)begin
          state <= 2'b01;
          led   <= 1'b0;
        end
      end else if( state == 2'b01)begin
        if( push2 == 1'b1)begin
          state <= 2'b10;
          led   <= 1'b0;
        end      
      end else if( state == 2'b10)begin
        if( push3 == 1'b1)begin
          state <= 2'b11;
          led   <= 1'b1;
        end else 
          led   <= 1'b0;
      end else if( state == 2'b11)begin
        led <= 1'b1;
      end       
    end
  end

endmodule

ミーリ型マシンの設計法は

  1. 仕様から状態遷移図を起こす。遷移は(条件/出力)を同時に考える。
  2. 状態遷移図に二進符号を割当てる。
  3. モジュール宣言・ポート宣言を書く。クロックとリセットを忘れずに。
  4. 入出力宣言とreg宣言を書く。出力はreg宣言にも書く。
  5. always文を書く。イベント文には記憶素子を更新するタイミング(クロック)を書く。
  6. もちろんリセットで初期化することも忘れずに。
  7. 状態遷移図からif文を使って状態遷移を記述。出力も記述。

状態遷移図を描ければだいたい記述は進むはず。
あとは慣れか。
次回は細かいことを学んでいこう。

たまには同期式リセットのことも思い出してあげてください【Altera DE0】へ進む
Verilog入門へ戻る


トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-04-13 (水) 11:58:33 (2233d)