ムーアマシンとミーリーマシン

[] [] []


ステートマシンにはムーアマシンとミーリーマシンの2種類がある。構造的には入力信号がステートレジスタをバイパスして出力側の組合せ回路に入っていないかいるかの違いだが、動作的には出力が現在の状態(ステートレジスタの値)だけで決まるか否かという違いがある。

設計としてはムーアマシンを使った方が制御する側と制御される側が明確に分かれるのでよい。もし、ステートマシンの遷移条件に使った信号をデータパスの制御信号にも使ってしまうと(このときミーリーマシンになる)、そもそもステートマシンとデータパスに分けた意図がぼけてしまう。

原則はムーアマシンを使った方がよいが、ムーアマシンは遷移条件の入力信号から制御信号が出るまで必ず1クロック遅れるので、遅れないように現状態でなく次状態を使いたい場合がある(このときミーリーマシンになる)

この場合は、現状態state_regでなく、次状態next_stateを使ってRTL記述するとよい。

/* FSM - 現状態でなく次状態を使う場合 */

reg[2:0] state_reg;   // 現状態

wire[2:0] next_state; // 次状態

localparam IDLE=3'd0;

localparam SA1 =3'd1;

localparam SA2 =3'd2;

localparam SB1 =3'd3;

localparam SB2 =3'd4;

localparam SB3 =3'd5;

 

always @(posedge clk or posedge rst)

    begin

    if(rst)

        state_reg <= IDLE;

    else

        state_reg <= next_state;

    end

 

assign next_state = fsm(.state_reg(state_reg)

                  ,.start_a(start_a)

                  ,.start_b(start_b)

                  ,.done(done));

function[2:0] fsm

    (input[2:0] state_reg

    ,input start_a

    ,input start_b

    ,input done

    );

    case(state_reg)

    IDLE:if(start_a) fsm = SA1;

        else if(start_b) fsm = SB1;

    SA1: fsm = SA2;

    SA2: if(done) fsm = IDLE;

    SB1: fsm = SB2;

    SB2: fsm = SB3;

    SB3: if(done) fsm = IDLE;

    default: fsm = IDLE;

    endcase

    end

endfunction

制御信号には現状態state_regの代わりに次状態next_stateを使う。

// 制御信号に名前をつける場合

assign valid = ((next_state==SA2) | (next_state==SB3));

 

// 制御信号に名前をつけずに使う場合

always @(posedge clk or posedge rst)

    begin

    if(rst)

        count_reg <= 0;

    else if((next_state==SA1) | (next_state==SB1))

        count_reg <= dati;

    else if(next_state!=IDLE)

        count_reg <= count_reg +1'b1;

    end


[] [] []