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); |