FSM vs カウンタ

[] [] []


簡単な順序回路はステートマシン(FSM)を使わずにカウンタで作ることもできるが、カウンタは十人十色の書き方ができてしまい回路の意図がわかりにくくなる

例として「パルス信号を開始からNクロック間だけONにする」という簡単なロジックを書いてみる

(1) 初心者がよくやるのは、カウンタがある範囲のときだけパルスONにする考え方で、

/* c=0→N,...1,0とカウントダウンして,c!=0のときだけpls=1 */

always @(posedge clk or posedge rst)

    if(rst)       c <= 0;

    else if(開始) c <= N;

    else if(c!=0) c <= c - 1;

always @(posedge clk or posedge rst)

    if(rst)       pls <= 0;

    else if(c!=0) pls <= 1;

    else          pls <= 0;

(2) 別の考え方として、パルスONの間だけカウンタを回して既定値に達したらOFFとしてもよい。

/* pls=1の間だけカウントアップしてN-1クロック数えたらpls=0 */

always @(posedge clk or posedge rst)

    if(rst)         c <= 0;

    else if(pls)    c <= c + 1;

    else            c <= 0;

always @(posedge clk or posedge rst)

    if(rst)         pls <= 0;

    else if(開始)   pls <= 1;

    else if(c==N-1) pls <= 0;

これらをステートマシンで書き直してみると、例2の方が自然な書き方になっている。

(1の書き直し) カウンタの状態をステートと見なす

always @(posedge clk or posedge rst)

    if(rst)

        s <= IDLE;

    else

        case(s)

        IDLE: if(開始) s <= PLS1;

        PLS1: s <= PLS2;

        ...

        PLSN: s <= IDLE;

        endcase

always @(posedge clk or posedge rst)

    if(rst)

       pls <= 0;

    else if(s==PLS1 | s==PLS2 | ... | s==PLSN)

       pls <= 1;

    else

       pls <=0;

(2の書き直し) パルスのON/OFF状態をステートと見なす

always @(posedge clk or posedge rst)

    if(rst)

         c <= 0;

    else if(s==PLS_ON)

         c <= c + 1;

    else

         c <= 0;

always @(posedge clk or posedge rst)

    if(rst)

        s <= PLS_OFF;

    else

        case(s)

        PLS_OFF: if(開始)   s <= PLS_ON;

        PLS_ON:  if(c==N-1) s <= PLS_OFF;

        endcase

assign pls = (s==PLS_ON);


[] [] []