一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4269|回复: 5

一段二段三段状态机(FSM)之间的区别

[复制链接]
发表于 2013-9-7 09:23 | 显示全部楼层 |阅读模式
之前一直烦脑我写的代码好难维护,在网上看多了发现人家说三段状态机多么多么的好,我就马上去查什么是三段式状态机。发现我之前写的全是一段式代码,怪不得我老是没办法提高自己的水平。
) j, i! ~) Z: F8 F; X所以我在网上找到一些特别有用的二段和三段式写法不但是给自己看的也是为提高自己的技术的各位看的。! _6 m9 ^& ^( m% c* |
4 C4 g4 J; b0 j, O0 [
! E! P! K' F0 o: d( ]3 u

Abstract7 j5 Z" a! c  e- t0 Y4 k/ }
FSM在數位電路中非常重要,藉由FSM,可以讓數位電路也能循序地執行起演算法。本文將詳細討論各種FSM coding style的優缺點,並歸納出推薦的coding style。

Introduction8 x( L! o; |) k+ Q: ?0 U, E
使用環境:Debussy 5.4 v9 + ModelSim SE 6.3e + Quartus II 8.1

本文將討論以下主題:

1.Moore FSM的架構

2.Moore FSM各種coding style比較

3.Mealy FSM架構

4.Mealy FSM各種coding style比較

5.實務上推薦的coding style

6.Conclusion

若要讓數位電路也能循序地執行演算法,最簡單的方式可以使用D-FF產生counter,根據counter的值去決定要執行不同的程式碼,如此也能達到使數位電路循序執行演算法的目的,不過這種方式僅適用於很簡單的演算法,在一般規模的演算法若使用counter方式,程式碼將不容易維護,所以實務上會使用FSM方式來實現演算法。

其實FSM方式也是利用counter來實現,所謂的counter,並不是只有counter = counter + 1才算是counter,FSM的state register就是廣義的counter,只是這種counter不是一直加1而已,而是有自己的遞增規則。FSM只是提供了一種較為高階與較容易維護的方式來實現演算法。

Moore FSM架構

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106052038383584.gif

一般在寫FSM時,會以Moore FSM為主,所以先討論Moore。由上圖可知,Moore FSM內部由3個block所構成:Next state logic,State register與Output logic。

Next state logic:純粹的組合邏輯,以整個module的input與目前的state為輸入,目的在產生下一個state值存入state register。

State register:由D-FF所構成,將Next state logic所產生的state存入register。

Output logic:純粹的組合邏輯,根據目前的state產生整個module的output。

所以可以發現,整個Moore FSM事實上是由2塊的組合邏輯與1塊D-FF所構成,我們常聽到所謂的一段式、二段式與三段式FSM,事實上就是由這3個block排列組合而成。

Moore FSM各種coding style比較

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106052038396027.gif

為了要實際比較各種coding style,在此舉一個簡單的例子,若input w_i為連續2個clk為high,則output會在下1個clk產生周期為1 T的high pulse,timing diagram如上圖所示。

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106062055393332.gif

因此設計了Moore FSM,state diagram如上圖所示,接下來要做的就是用各種coding style來實現這個Moore FSM。

1.使用3個always (三段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106052154153519.gif

simple_fsm_moore_3_always_best.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]% R( \; j! l- X# r$ u9 I; C! o- f: K, Y& u
1 /* * n+ g) j9 ~) {; b
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
6 S9 `. @1 D: Y2 F  A
3 ! r+ r5 m, |* Q
4 Filename    : simple_fsm_moore_3_always_best.v3 H# h! A' W+ S2 |6 W7 t
5 Synthesizer : Quartus II 8.1
0 n" I) x9 l+ n, J" t) O
6 Description : 3 always block for moore fsm (BEST). G5 K1 e; U2 t* ~- F1 [
7 Release     : Jun.05,2011 1.07 ^  N0 Q2 j+ c0 P+ i
8 */$ E8 i! ~0 D) @& Z' {7 D; C
9 , O( t' y1 L- ~8 j: b4 M
10 module simple_fsm (
) }! G9 L- `6 T3 G. ]11   clk,  B  s8 J* {3 O- k  K4 y
12   rst_n,0 w" L4 k3 r) k. }1 q% O( s
13   w_i,
0 f4 d0 ^1 }1 k, |4 U6 \14   z_o
6 \9 j! I8 x2 f2 M; y: [& ?15 );
9 ^2 w' I9 A9 O16 ' i2 u1 `: A6 S0 R
17 input  clk;/ m' ~9 H0 q% P) i7 ^1 }
18 input  rst_n;4 b# A$ q, Z4 H- u2 v
19 input  w_i;. }0 ~; A- B) b. n$ [
20 output z_o;" n. B9 q( D( L$ C
21 - f% T. |1 A! K, [* H, d' \
22 parameter IDLE = 2'b00;
& s- H( M0 z: R/ P' x2 d
23 parameter S0   = 2'b01;4 w. Q6 q  ?0 C5 l! t4 G3 p
24 parameter S1   = 2'b10;9 u$ ^" E* ]- F+ F3 M
25 8 S- v: y9 F8 x# i9 E9 N
26 reg [1:0] curr_state;' @, [7 ^* b7 R) S" g
27 reg [1:0] next_state;
" }: m2 E" B7 m  g( z" s  \" p28 reg z_o;  G! m1 a  b, s1 L
29
' J) c3 r7 r! C+ _30 // state reg
4 S/ G3 H. T% f/ u, R
31 always@(posedge clk or negedge rst_n)
( P4 R+ T/ N* w, ^9 S7 u/ w; Z" t32   if (~rst_n) curr_state <= IDLE;
5 z3 w7 L' S4 K. p. u8 K33   else        curr_state <= next_state;! S, c4 U6 N; H( J$ C
34     
# z. e+ l0 {& E6 @35 // next state logic    $ c7 X! O1 G9 O: D8 |- R! b
36 always@(*)5 z; y4 x; G4 x
37   case (curr_state)$ W3 B, ]  a" i$ K; s- y
38     IDLE    : if (w_i) next_state = S0;9 G" T5 W6 m3 b& z- F
39               else     next_state = IDLE;: p, S) b( P1 T5 o+ ]) @0 F
40     S0      : if (w_i) next_state = S1;, Z. W7 |" s% s. V- R
41               else     next_state = IDLE;1 K0 s' x. q8 C
42     S1      : if (w_i) next_state = S1;
* o: `( s1 ]* J0 c1 O$ \3 C43               else     next_state = IDLE;9 I! d, C8 t! N+ i
44     default :          next_state = IDLE;
  J! h: f' Y& h" @# d5 H45   endcase   
& a% U7 N4 U) F; c8 d- K46
4 ~2 e4 \8 N7 W# D6 z. J& z47 // output logic
, _+ ~  {) ]* M' ]
48 always@(*)
: D% N# i  v' g8 B6 p& j49   case (curr_state)
& }: u, J( T8 y9 ]8 W( e7 c' r; D6 Q! d* Q50     IDLE    : z_o = 1'b0;2 Q, V* M6 Z9 Y) H' }% b" e
51     S0      : z_o = 1'b0;9 I$ d; v9 a$ c; v
52     S1      : z_o = 1'b1;
# M0 ~8 b2 J/ p5 s  \
53     default : z_o = 1'b0;- V4 S, g  L% W+ A' P
54   endcase' }# ?& Q  F. Z" q' X4 j
55   
8 n9 w; W0 n  r" q/ }# f( J56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
# R& q$ m1 J3 j8 V0 O2 I) k' E* M

9 ?7 j7 c! I: \/ \; t  a: z

35行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
5 k# {8 V& R7 e! o// next state logic    7 Q  Z7 q  W2 Z0 e* o, B7 G* r7 f  O
always@(*)7 u. v8 n7 r" f5 j
  case (curr_state)* Y- n7 Z! Z9 H
    IDLE    : if (w_i) next_state = S0;. y  Q" }( y* P9 c' E" F8 O
              else     next_state = IDLE;: M7 b; \: a8 F9 \: H$ [
    S0      : if (w_i) next_state = S1;
( e# z# g! A# t              else     next_state = IDLE;
2 p  ^8 X* t* q% d" c% a    S1      : if (w_i) next_state = S1;
+ v+ M$ x. D0 S              else     next_state = IDLE;# e+ g; A2 y0 V- H) C7 [1 c  K
    default :          next_state = IDLE;. a  Y3 I0 o( B  N4 I
  endcase   [url=]http://common.cnblogs.com/images/copycode.gif[/url]$ I. S- [* R4 }: D2 Z! {, L

0 ]- |! r  R: W/ d9 ^! \3 @" N

使用1個always描述next state logic,因為是純粹組合邏輯,所以使用blocking。

根據Moore FSM架構圖所示,next state logic的結果與input與目前state有關,所以先用case對目前state做一次大分類,然後每個state再根據input做if判斷。

30行

// state reg
# q* w8 \  d8 d/ V3 o) Z
always@(posedge clk or negedge rst_n)
2 N, T. h, B+ g  if (~rst_n) curr_state <= IDLE;
. b  M8 w" I' Q$ [% d  else        curr_state <= next_state;

+ T0 l. K4 Q1 A" P5 C1 w

使用1個always描述state register,因為是D-FF且含clk,所以使用nonblocking。

由於state register區塊並不包含任何邏輯,所以不會因為不同FSM而有不同寫法,不同FSM只會改變next state logic與output logic的寫法。

47行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]1 }2 H; T( e" p, [
// output logic& U: g$ S! z' p1 t) r0 t
always@(*)
- T% ~& r4 C8 i3 u; q0 c  case (curr_state)! Y8 ~8 s  {% H( r/ P, Y/ e, k
    IDLE    : z_o = 1'b0;0 y; C" m& E1 U. Y
    S0      : z_o = 1'b0;. l" e6 F! O0 u1 p+ E) h
    S1      : z_o = 1'b1;9 Q3 x5 q9 u3 [8 ~, w
    default : z_o = 1'b0;  I/ L& \* }7 W5 r. X
  endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
+ m: S- s0 U) ], B% w

% U4 b/ ~$ P" N0 G7 r5 ^) z

使用1個always描述output logic,因為是純粹組合邏輯,所以使用blocking。

根據Moore FSM架構圖所示,output logic的結果只與目前state有關,所以只需用case對state做一次分類即可。

使用3個always寫法有幾個優點:

1.可忠實地反映出原本的Moore FSM硬體架構
6 ^" ^2 Q( h; F6 p2.可輕易地將state diagram改用Verilog表示
( Q. b5 K# p# D1 z3.將Next state logic與output logic分開,可降低code的複雜度,便於日後維護
" n; d2 `! I! R% f6 N

3個always是一個推薦的寫法。

Testbench

simple_fsm_tb.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]& \! O* [6 N! i6 Q) W! [/ B
1 /*
+ }1 n. _) [; s% R8 c0 U) O5 Z
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
( ]: V+ f8 j! g' k- Y7 W+ L4 T' Q6 L
3 % a0 Z% u% p5 B6 n
4 Filename : simple_fsm_tb.v4 k9 [8 F* h' i$ L
5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9
& i( I$ `2 F9 @: _* _
6 Description : testbench for FSM5 Q$ p+ b% [1 |
7 Release : Jun.05,2011 1.0
- a% ]0 e2 Y# y3 W1 h
8 */
- m# \. J! j: J% }9
% N9 v" V: n2 S" @10  module simple_fsm_tb;7 }3 ~6 M2 ~. x; o
11
! s* m1 \8 J: ^3 D8 R4 `( p12  reg clk = 1'b1;# p6 U" p0 P* O
13 reg rst_n = 1'b1;9 {8 ]. a3 a7 k6 u; d$ f" H
14 reg w_i = 1'b0;
% P1 e% ~  ^* q8 M
15 wire z_o;
+ t) \" M, ~& X( F16
+ R, I2 p1 I5 `4 h17  // clk: o  }0 i$ {6 {
18 always #10 clk = ~clk;
( o' [3 c2 E7 A. {2 t3 @2 C  Y3 d19 / h. j  g" f9 h, j3 t5 H& c
20  event after_rst;
1 @- g9 Y( A7 n- I; }$ c21 & p' g9 u- h; s, ?# a
22  // rst_n; L+ |9 U  z5 q
23 initial begin
6 ^- X8 j! L! K24   #6; // 6ns0 U4 t4 o/ j% [" {
25 rst_n = 1'b0;! f! i& {! V8 _3 T, c& d3 E
26 #30; // 36ns
: u7 X" `/ p% e! \
27 rst_n = 1'b1;
# t8 T) \' T) E2 F  f4 [" F
28 ->after_rst; 9 J6 F  N1 _3 j* v- v3 ]6 M: [
29  end
- c: u: c) z" u, H7 e* G) Y30 ( A$ J6 @# h7 H
31  // w_i, [" V9 ~: `3 h* Y! j3 ~
32 initial begin  S0 b9 q) Y1 w) f5 d: `
33   @(after_rst);- X1 t' H! g- z% u& x! u
34   repeat(2)@(posedge clk); // 60ns
* \+ e7 x. P* }+ ?( r. W; e
35 w_i <= 1'b1;# j  W$ J8 p0 A0 m! X% N" D. O) A
36 @(posedge clk); // 80 ns# `# t/ w3 C& c* T3 A
37 w_i <= 1'b0;* k& O' K( f" F9 E6 ?9 A
38 @(posedge clk); // 100 ns
4 ^* {, E) s; S( C0 U2 z
39 w_i <= 1'b1;  V: |9 a% f; ]* m$ [3 F
40 repeat(2)@(posedge clk); // 140 ns
: d% s) ~; A2 O4 j
41 w_i <= 1'b0;( s. K" e  U# P& n
42 @(posedge clk); // 160 ns
1 M0 T  v0 K8 @6 o. L
43   w_i <= 1'b1;, \& L% U5 o# T0 |& I
44   repeat(3)@(posedge clk); // 220 ns
" \# i3 u7 T. s* K# f  b/ I
45   w_i <= 1'b0;, X4 v6 \) H$ u$ _# w4 F
46 end
% B" w( b7 c) S  j# k' g3 U47 8 h+ P4 m+ Z$ c3 k( Y
48 initial begin
7 G: K; {; X/ _1 q: c49   $fsdbDumpfile("simple_fsm.fsdb");
: c- O; m7 ^" w  e. d+ A  P! ]50   $fsdbDumpvars(0, simple_fsm_tb);
- I# ^+ o, [" T) k* j2 s3 q( r51 end% q, o: v4 J9 s% j- P% X
52 5 X& H1 ^) f' I2 r! \
53 simple_fsm u_simple_fsm (7 v/ v1 c# `. t- o
54   .clk (clk),) l0 K0 D4 Q+ r9 m( r
55   .rst_n (rst_n),  ~" k4 ]  s: H! N7 A
56   .w_i (w_i),
3 w5 @1 B/ b6 f5 z1 l57   .z_o (z_o)/ `1 M# w: _) C. E) D3 a" K
58 );; b% Z; R4 R' \5 L' W7 {: E
59 1 R9 ^( U1 l% E2 [( I
60 endmodule8 s: D9 A3 h1 W9 q7 ^) |. M9 e
[url=]http://common.cnblogs.com/images/copycode.gif[/url]
" I: E; u# Z) N  a: T

. M' U8 T+ Y  f" t

執行結果

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106060949236708.gif

2.使用2個always (二段式)

由於要使用2個always去描述3個block,根據排列組合原理,C3取2,共有3種可能,我們一個一個討論。

2.1 state register與next state logic合一

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106061010415140.gif

simple_fsm_moore_2_always_0_cs_ns_good.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]0 Q+ P6 O) X8 Y7 E' o' W3 f2 J* c
1 /* $ G2 K5 O! j9 i6 ?: M
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
  k! Y0 M7 N# x) ^0 J
3 / }6 v( e" @9 Q0 ]4 l+ L$ D, ~
4 Filename    : simple_fsm_moore_2_always_0_cs_ns_good.v7 f/ g6 ?1 i& p# O6 }/ v
5 Synthesizer : Quartus II 8.16 \: ~8 @; a9 V0 L1 ]; M- f
6 Description : 2 always block for moore fsm (GOOD)) u; T) s" B, \: A4 e: N- i  X
7 Release     : Jun.05,2011 1.0
& I; s" R$ _. H1 [
8 */) f: W5 e/ G( H$ y9 h# q1 U6 B
9
! n) J6 S8 M5 s2 B' K4 b10 module simple_fsm (2 T4 C  g) g% D" z/ L/ I7 w
11   clk,0 f, P5 Q8 M* t9 K
12   rst_n,6 I3 @0 m: Q6 R6 l% M
13   w_i,
+ S( T" S: ~( E3 e14   z_o" X/ a$ A; B8 K2 a# w3 L
15 );
3 V: ]" c1 a  g5 a/ E! y16 ) w$ R2 N* s7 p1 @5 p( S
17 input  clk;
! L2 N/ b" `! ?3 ?18 input  rst_n;+ x9 l4 y& N  }$ y7 r1 y
19 input  w_i;
, V9 I8 Z2 V( A- n( f20 output z_o;
: U, E5 y7 C  R, A) D( v21 ; x6 n" s$ y# r3 S5 _
22 parameter IDLE = 2'b00;0 f! |  S, R2 N& e/ @7 g- O' J
23 parameter S0   = 2'b01;
% e* o3 W+ T2 b. J  [4 L
24 parameter S1   = 2'b10;
4 ~3 g$ }& I. \
25 7 n% G. q" n. X9 n$ `3 s
26 reg [1:0] curr_state;
$ F  d2 |$ a8 S  J27 reg z_o;' ~. w2 n. K) c) s" M3 u7 \: }5 Q
28 . r% O; j( A- ^; h
29 // state reg + next state logic
9 }* W$ W+ V' R, X  @; ]1 A1 h1 w
30 always@(posedge clk or negedge rst_n)3 u3 v: G7 o4 V, i$ Q* T$ o6 U+ z
31   if (~rst_n) curr_state <= IDLE;/ T- a* t, j% T% O+ B2 Q6 Y8 N
32   else. {; h1 B" \: l- J5 g$ K
33     case (curr_state)( p9 n- }% V+ y" a2 s: C) e" N
34       IDLE    : if (w_i) curr_state <= S0;$ j, e- D0 ~' \  W
35                 else     curr_state <= IDLE;  z0 D- T4 z" T: D9 c
36       S0      : if (w_i) curr_state <= S1;1 [' K9 n$ ?0 G
37                 else     curr_state <= IDLE;
' ?2 S' L8 c0 b6 [8 `  M38       S1      : if (w_i) curr_state <= S1;
- i7 v5 R0 u/ q39                 else     curr_state <= IDLE;' t7 }  D! R7 w# `" N! }
40       default :          curr_state <= IDLE;: E) C% d, g9 v, |
41     endcase
# m% S* S4 F& e- k42     
0 E' A$ |5 o. f2 ^; h: b43 // output logic
3 |" F- o0 J7 X: a
44 always@(*)& i. N0 T* @2 \" d/ V1 ^
45   case (curr_state)
/ I' j! z$ X8 U; Z5 A+ V' T46     IDLE    : z_o = 1'b0;
# m6 x/ S9 n# s1 @
47     S0      : z_o = 1'b0;, u' O" _' Z6 D; s7 _
48     S1      : z_o = 1'b1;4 {2 H1 c( O7 @0 @9 {1 N
49     default : z_o = 1'b0;3 a8 m/ ]1 k7 Q% k! J# R8 E6 _
50   endcase
8 L$ V" _& |% _# H6 C51   
" U! P- v: J4 h5 h0 w6 ?" H) @1 ^52 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
( j: N2 c2 W" s, z3 J5 F

3 A, K, J6 b# M0 ?" [; `

29行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
' f7 R! m% \/ e( j// state reg + next state logic0 B; B) g: {4 s, l4 _+ j3 G
always@(posedge clk or negedge rst_n)
. N1 i$ O* g7 Z# s9 K& O3 Q2 s  if (~rst_n) curr_state <= IDLE;
7 Q) K* c' \3 o8 e: e" [7 r. X& i  else
. v2 E. t2 x$ j7 A    case (curr_state)
& k  x! i5 u8 V/ y- n# _      IDLE    : if (w_i) curr_state <= S0;
0 X- ^9 @/ T0 \  q6 C                else     curr_state <= IDLE;9 e- Q7 a% }# O) c% l, v) h
      S0      : if (w_i) curr_state <= S1;3 p  F1 n8 X; V3 H$ O- d* D1 {& f
                else     curr_state <= IDLE;
5 V  _, f( [+ J( v      S1      : if (w_i) curr_state <= S1;
9 t  [& H1 \/ v& R6 f0 r                else     curr_state <= IDLE;; B$ T& p8 e2 w. Q
      default :          curr_state <= IDLE;  @6 j! G5 R% k" h
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]& G. L* \: s+ \0 u6 G0 u/ u! L
% d5 P5 W( e5 f1 h9 x4 v2 W

將state register與next state logic合起來用1個always去描述,雖然next state logic是純粹的組合邏輯,為了遷就於帶clk的state register,且要用一個always描述,就必須改用nonblocking。

由於state register與next state logic合一,所以可以少宣告next_state reg,不過這並不會影響合成結果,只是可以少打幾個字而已。

因為next state logic由input與state所構成,所以先用case對state做一次大分類,然後每個state再根據input做if判斷。

43行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]) H4 c' T. r; r7 a4 n& Q# Q
// output logic) J. u& k. \8 S9 I+ C
always@(*)3 ]3 ]1 [$ O/ i
  case (curr_state)
7 {8 Q& u: A6 E- ]2 U    IDLE    : z_o = 1'b0;
7 c0 K9 |% X( l
    S0      : z_o = 1'b0;6 h' `+ b& Y$ }) F( M% G7 S- M
    S1      : z_o = 1'b1;
8 T5 O$ h' G* C" f: j8 ^; l
    default : z_o = 1'b0;
7 W$ n- _4 G) |- t. X; g
  endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]. I; {1 X9 N; U, I0 m! i

0 c  s3 l- J0 l. n& F9 l# {

使用1個always描述output logic,因為是純粹組合邏輯,所以使用blocking。

根據Moore FSM架構圖所示,output logic的結果只與目前state有關,所以只需用case對state做一次分類即可。

使用2個always (state register與next state logic合一)寫法有幾個優點:

1.程式碼較3個always寫法精簡
! g( d0 M# V9 V5 y2.可輕易地將state diagram改用Verilog表示
+ r+ j$ x& |* b- w; n3.因為state register原本程式碼就不多,將next state logic與state register合一後,next state logic仍與output logic分開,因此不會增加code的複雜度,便於日後維護

: \  P; j1 ]- C8 E; Y" {

2個always (state register與next state logic合一)也是一個推薦的寫法。

接下來要討論的都是不推薦的寫法,主要目的是了解為什麼不推薦的原因。

2.2 state register與output logic合一

http://images.cnblogs.com/cnblogs_com/oomusou/201106/2011060610403484.gif

simple_fsm_moore_2_always_1_cs_ol_ng.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
# s5 \/ n8 h0 a4 \) m2 {% ] 1 /* # Q5 `9 J6 b" q: [$ {
2 (C) OOMusou 2011 http://oomusou.cnblogs.com0 N, R0 r0 ^) ^
3 & V. n- d. N! r. ~  {
4 Filename    : simple_fsm_moore_2_always_1_cs_ol_ng.v" C9 R8 ]/ W8 @
5 Synthesizer : Quartus II 8.1
9 T5 o+ y2 k9 a! ^9 S  a
6 Description : 2 always block for moore fsm (NO GOOD)
8 Y' O, O1 g, M0 V7 W
7 Release     : Jun.05,2011 1.0/ \# ?  }) v! X2 u$ S& m0 D  q) j
8 */( `. h2 r+ F3 O' s3 K; Q. P6 G  @
9 : W! N/ P+ t  Q5 i0 A
10 module simple_fsm (
! [: |4 H8 n8 y# M11   clk,
0 P* s7 F8 F; D12   rst_n," @: V: ], @  m
13   w_i,3 v3 t$ G* N3 o3 V
14   z_o2 l- ^2 @: q/ N5 ?' z* m9 u
15 );  ?* ^5 p+ ^! S+ t' H8 e" M
16   S8 F; d) k) \3 B" ^" c- }
17 input  clk;, n3 Y, t: P2 f; G, C. v8 R! u, G2 A
18 input  rst_n;
7 B6 Y. {! h$ Z3 m19 input  w_i;
$ p8 ~8 k1 }: `3 Y1 q20 output z_o;: h1 ^( f2 ]" ]8 k+ Q* t6 Z& v" ~
21
" [0 i1 }: i4 Q: n22 parameter IDLE = 2'b00;/ J$ S/ m1 W" ]/ l. R
23 parameter S0   = 2'b01;
# N# C" n6 A& H9 L" t
24 parameter S1   = 2'b10;8 v3 ^7 r  J; M! L4 ^# o, M' D! o) x
25 : ?8 P% c# L" Z5 d1 j
26 reg [1:0] curr_state;* Z: Q  B" [5 V- F! W
27 reg [1:0] next_state;
7 L) x) q% x* z/ [7 ^  C. \28 reg z_o;
  U  |! ^* d  `3 h+ a29
0 W+ b1 s. Y2 T* B( t6 Q1 ]& L30 // state reg + output logic9 Q! Z; s" Y8 u! y' K/ M) M
31 always@(posedge clk or negedge rst_n)
- v/ m. M  B" C7 g* O5 \- |( ]32   if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};/ f- _; @9 z8 ^6 G
33   else begin
/ k7 d- ]0 ^' E' H; f34     curr_state <= next_state;! n/ K( v- Z5 m; ?6 @& q6 D: U
35     
1 @6 J  V) l4 z1 t# z36     case (next_state)7 S; ], \  ?$ B( @/ W5 S
37       IDLE    : z_o <= 1'b0;7 w! o- ^$ g; \" \
38       S0      : z_o <= 1'b0;9 ?- N" p3 n7 \# C2 V
39       S1      : z_o <= 1'b1;
, m8 B+ y2 v  C- k  E
40       default : z_o <= 1'b0;% x. G7 Y3 @3 M
41     endcase  F! ]7 m9 X/ q. @
42   end
/ j' p% l+ }% X5 J9 M  K43
7 ?6 b5 n& ?( u, ^% [% H44 // next state logic   
; P6 N5 O# [# Q
45 always@(*)
1 j+ o: e: X$ g1 a46   case (curr_state)# E, B4 I: r+ D4 P. T3 H7 v4 H. f
47     IDLE    : if (w_i) next_state = S0;
. n3 m; K7 ]' K& J9 q* ]% l48               else     next_state = IDLE;. g* z, }8 m1 {3 m( q: L9 i; y" G
49     S0      : if (w_i) next_state = S1;( i9 W" `4 S8 ]& q- P, @
50               else     next_state = IDLE;
7 M8 x( t" f+ M. a5 V( _4 V# P1 T51     S1      : if (w_i) next_state = S1;. C/ e- R1 }# C6 w, J; O
52               else     next_state = IDLE;
& i3 [( N7 Y, _/ m' A, l53     default :          next_state = IDLE;
' C# W- e! V. i" m, o54   endcase   
* [" p* ~$ e4 I3 `  I55 4 u& Y5 J* q. u. q
56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]( o. E/ N  }2 o$ i1 l/ C! c) d
' Y3 G. w$ g. l! y

30行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
4 @' Y% _  B( b' {// state reg + output logic! m' X* N. o5 \. [" l# e3 G
always@(posedge clk or negedge rst_n); W+ m! i& r  h; q! D
  if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
* D: H; B  D5 ]6 _, i3 a) {' `- I  p6 f
  else begin
+ k% v' `' l' g1 O    curr_state <= next_state;+ Z0 Q( g* A6 f  R- W
    1 }) |7 K7 l7 @# y' I: T
    case (next_state)
) A4 Y" n  j2 A+ ?) W* P      IDLE    : z_o <= 1'b0;
! k& x5 }$ c$ \# g5 n/ S+ ~
      S0      : z_o <= 1'b0;
$ `) V5 y/ g+ G) u( L
      S1      : z_o <= 1'b1;
. D3 r; d  R2 I4 j( J
      default : z_o <= 1'b0;
+ y6 j+ U' A# N& n: K0 {
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
- x. Z$ C! c5 G: j2 \+ }% p4 S! a" s
% W* x0 [1 R9 q

將state register與output logic合起來用1個always去描述,雖然output logic是純粹的組合邏輯,為了遷就於帶clk的state register,且要用一個always描述,就必須改用nonblocking。

因為output logic只與state有關,所以只用case對state做一次分類即可。

這種寫法最大的問題是:output logic必須用next_state去判斷!!

依照Moore FSM的架構圖得知,output logic只與目前state有關,之前的幾種FSM寫法,output logic也是由目前state去判斷,為什麼這種寫法要靠next_state去判斷呢?

主要原因是根據Moore FSM的定義,output logic只與目前state有關,且是個純粹的組合邏輯,但目前強迫將state register與output logic放在同一個always,迫使output logic必須使用nonblocking的方式呈現,也就是若output logic仍然使用目前state去做判斷,則output logic會多delay 1個clk,為了讓output logic結果正常,只好提前1個clk做判斷,也就是提前到next_state去做判斷

所以當我們從state diagram換成Verilog表示時,若使用2個always,且是state register與output logic合一時,必須很小心要使用next_state去做output logic判斷,因為這個地方很不直覺,很容易出錯,所以不推薦這種寫法

44行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
* _8 f" T6 M0 e1 S* S( B// next state logic    ! f  e9 Z+ u! ]/ g- V
always@(*)
1 I' U( {& `( |9 z4 _  case (curr_state)
" c/ E4 T8 k( O5 w6 |% C  i    IDLE    : if (w_i) next_state = S0;) P$ p% {( l8 ]: k# E5 m* d( v
              else     next_state = IDLE;5 d1 [+ N$ M) G7 u) b
    S0      : if (w_i) next_state = S1;
0 n0 Y. C2 H5 y5 J. d8 Z              else     next_state = IDLE;6 _9 ^! N/ f- }( X8 }8 q8 Z
    S1      : if (w_i) next_state = S1;
8 r, p4 w+ H+ {) M9 C& f) q              else     next_state = IDLE;: w; @% E: }5 y1 g% J# Q
    default :          next_state = IDLE;2 Q1 \) U) {1 @/ K1 A. p# Q
  endcase    [url=]http://common.cnblogs.com/images/copycode.gif[/url]
3 a2 i' o6 m# G1 P2 b

# K6 {: @6 e1 ?0 Z/ r

使用1個always描述next state logic,因為是純粹組合邏輯,所以使用blocking。

根據Moore FSM架構圖所示,next state logic的結果與input與目前state有關,所以先用case對目前state做一次大分類,然後每個state再根據input做if判斷。

使用2個always (state register與output logic合一)寫法的缺點:

當使用1個always去描述state register與output logic時,output logic必須使用next_state做判斷,而非用目前state判斷,由於寫法不直覺,一不小心很容易弄錯0 ~: j) c" ^) _' ]* a( n

不推薦2個always (state register與output logic合一)寫法。

或許你會說,在實務上卻常看到state register與output logic合一的寫法,為什麼不會出問題?那是因為儘管是用Moore FSM,我們為了timing更好,常會在output時多敲一個D-FF,讓Output Logic的組合邏輯不要與其他module的input的組合邏輯合併,避免造成critical path,假如是這種需求,state register與output logic合一後,可以直接判斷curr_state,不用提早一個clk判斷next_state。

2.3 next state logic與output logic合一

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106061539099897.gif

simple_fsm_moore_2_always_2_ns_ol_ng.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]- I3 j) V( l, K) E% y; o) g
1 /* 8 g' O# n  U2 N
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
8 N7 _9 B$ |( e7 z/ w7 v) g' j& W
3 / D" m+ ^, b$ W. Q1 C. f
4 Filename    : simple_fsm_moore_2_always_2_ns_ol_ng.v
# e/ J( S! q- R  l5 q
5 Synthesizer : Quartus II 8.1- E; I1 B  c. }/ [. M7 s. R
6 Description : 2 always block for moore fsm (NO GOOD)
' T/ l6 m* g) P0 ^0 j% i! |) S' d+ t3 Y
7 Release     : Jun.05,2011 1.0- a2 \  n  D( p9 S$ r
8 */: a8 Q5 B, y" \% }6 S
9
+ ^8 P4 Z& f) c0 k* M10 module simple_fsm (. x& A& q, i: ~! T( i, J( T0 A; o
11   clk,
6 O) g* U( u' l# j# o5 a9 b/ r12   rst_n,
! w6 A; Z- m& z# y7 I) k& T# L13   w_i,- C# M% a) N, T  _4 ~
14   z_o. y% }/ k# q% A% W6 ~
15 );5 k0 r: [. M5 n& ?" U% I' M
16
7 L, x/ @+ {. e9 C! R& F+ C17 input  clk;
5 J4 u  P0 y# l6 ^1 Z" Q18 input  rst_n;
% J" Z) O6 [  z! R6 g19 input  w_i;  E  y* f# k/ {" e
20 output z_o;
2 N+ ^) n6 w$ c+ U: a21 6 |0 ?2 p$ ^+ Q7 l- `3 t
22 parameter IDLE = 2'b00;
3 j4 g  k9 |2 W  z/ X
23 parameter S0   = 2'b01;
6 w- t/ L6 ~4 N$ _+ v
24 parameter S1   = 2'b10;
9 q9 l5 M; W" b1 t: a
25
" c* j7 X# v, s4 |2 ^% Z26 reg [1:0] curr_state;( d8 K$ K: M% x& F" _$ }  H
27 reg [1:0] next_state;
6 Z4 M. p3 K0 F28 reg z_o;
* w) l6 D$ n. {) `! d5 `& z29 5 L* H. L7 T$ D
30 // state reg" i! w1 R" w( ], e9 l  t7 `
31 always@(posedge clk or negedge rst_n)
2 J0 w+ z2 ?8 X, o/ j+ [1 w32   if (~rst_n) curr_state <= IDLE;1 t% O" U' n9 \3 Q! i0 v+ i
33   else        curr_state <= next_state;7 l( ^- @" P  C& u0 t6 @# L
34     
! t- i1 y# }: x" k) m35 // next state logic + output logic # O8 s- Y: M- z  ~3 t9 E% s0 @
36 always@(*)$ _3 G% P2 A& `/ X
37   case (curr_state)
/ i1 l8 p* `! i8 \2 j$ n38     IDLE    : if (w_i)   {next_state, z_o} = {S0  , 1'b0};
+ y! [/ o( l- n2 n* i
39               else       {next_state, z_o} = {IDLE, 1'b0};
# [: k, @5 F! g
40     S0      : if (w_i)   {next_state, z_o} = {S1  , 1'b0};+ S/ `( Q6 Y0 l% M; d" M; a% E. j
41               else       {next_state, z_o} = {IDLE, 1'b0};7 r" {2 x1 ~6 ?" [) b: r- ^
42     S1      : if (w_i)   {next_state, z_o} = {S1  , 1'b1}; // always output 1'b1( q: H* q: W' v2 G% S" r
43               else       {next_state, z_o} = {IDLE, 1'b1}; // always output 1'b11 k: C5 ?; y! W7 S; z( u
44     default :            {next_state, z_o} = {IDLE, 1'b0};
4 Z$ G% ^$ c9 d% ?6 t
45   endcase
8 p) s$ l' y' O- U$ `! k; D  w* r/ t46
1 A1 ?8 \; ], c4 I47 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
. o- X* C  v- `9 X9 j- f
' H5 g7 J, @; t: v' O" k) c

30行

// state reg
+ w" _2 t5 g! `" n/ ]8 d- k( C
always@(posedge clk or negedge rst_n)
* `) f; N$ ^) X! j# E: q  if (~rst_n) curr_state <= IDLE;8 ~! l& k$ |# J, }
  else        curr_state <= next_state;

3 s( G$ S/ @! C7 l& w  [6 ^

使用1個always描述state register,因為是D-FF且含clk,所以使用nonblocking。

由於state register區塊並不包含任何邏輯,所以不會因為不同FSM而有不同寫法,不同FSM只會改變next state logic與output logic的寫法。

35行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]2 ]0 \. a, r, p
// next state logic + output logic
, |1 n  Q/ Z; G+ K2 m) p
always@(*)
/ s- x, N8 V. d9 l% Z3 F  case (curr_state)
- `# O9 b% a% r/ Y: U1 k    IDLE    : if (w_i)   {next_state, z_o} = {S0  , 1'b0};
# m# {) D+ _# k8 k7 t% J& l: t
              else       {next_state, z_o} = {IDLE, 1'b0};( N9 z; S3 y- W' r, W5 ?
    S0      : if (w_i)   {next_state, z_o} = {S1  , 1'b0};% J/ v% z3 j, v
              else       {next_state, z_o} = {IDLE, 1'b0};3 m- E  a) Z# R/ h% W
    S1      : if (w_i)   {next_state, z_o} = {S1  , 1'b1}; // always output 1'b14 G1 E# i6 W7 j! R9 f" N
              else       {next_state, z_o} = {IDLE, 1'b1}; // always output 1'b1
: f' S& T$ j4 ~1 Y- E4 Y    default :            {next_state, z_o} = {IDLE, 1'b0};' P6 `% @. e, b; a% O, W  y" ^
  endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
( W2 E1 z1 S1 A2 A: M
# U0 N' f- G1 g9 L

將next state logic與output logic使用同一個always去描述,由於next state logic與output logic都是純粹的組合邏輯,所以使用blocking描述沒有問題。

由於next state logic與input與目前state有關,但output logic卻只與目前state有關,因為都是先用目前state做case判斷,然後再對input做if判斷,所以會出現output兩次都出現1的情形,起因於output logic只與目前state有關,與input無關,固任何input都會出現1。

使用2個always (next state logic與output logic合一)寫法的缺點:

1.將next state logic與output logic合一只會增加code的複雜度,日後維護會更加困難
8 ^: l0 ?6 ]# X5 z2.很類似Mealy FSM寫法,容易讓人誤以為是Mealy FSM
& B& s7 M  A; Z5 E. M3 I9 Q

不推薦2個always (next state logic與output logic合一)寫法。

3.使用1個always (一段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106052038403910.gif

simple_fsm_moore_1_always_ng.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]. q' N0 k, ^; z. a: E
1 /*
- v5 l3 \$ o  D" e5 q& \. n
2 (C) OOMusou 2011 http://oomusou.cnblogs.com  L: M9 C* ^# X, g5 W/ A9 u
3 # i$ K, D0 C' H* ~* _' h% f" G
4 Filename    : simple_fsm_moore_1_always_ng.v" Q+ M# }5 }7 E& v: R
5 Synthesizer : Quartus II 8.1+ t' x4 u1 ], K$ d" A$ j- B+ Z
6 Description : 1 always block for moore fsm (NO GOOD)
6 g. h0 t! G" i7 h: V: C
7 Release     : Jun.05,2011 1.0$ j6 \7 `7 \6 C3 [8 m
8 */: w( W- A  k0 m  o" B
9 / Q2 b3 i$ `- y3 {& j+ t* n
10 module simple_fsm (
8 m6 b/ B6 ~1 n8 M: |, T' J' M# X' G11   clk,, |* t" K6 k1 N3 w! d, r
12   rst_n,
. C, A; K4 H2 i" C13   w_i,3 v- _& h$ }" E1 C& j  ^; l
14   z_o
( q1 Z/ l" R0 v/ J15 );# C# u! [; k( E1 g/ p
16 , z2 z& m. Z, U( k. b
17 input  clk;
; j$ K% N8 z! ^/ }1 L/ \18 input  rst_n;/ }. h" \6 L) s7 Z5 s) L3 h% q
19 input  w_i;
) S1 w7 M5 e- J20 output z_o;
# N8 _$ w9 Q' S. x6 n5 ?. {21
2 c7 `/ x2 x: Y+ R6 D- S) h22 parameter IDLE  = 2'b00;% W5 S- k0 b) }9 L2 N0 g0 `' f
23 parameter S0    = 2'b01;; z/ i7 I* w: i3 l9 g) [
24 parameter S1    = 2'b10;
  ?# p3 s4 x5 o8 E/ Z4 t! z+ z! J
25
0 B% n7 j; {, j1 b$ X" s1 z) d+ G26 reg [1:0] curr_state;* e. ]7 \/ O' M9 u* v
27 reg z_o;& L0 D5 ^! q" R1 O& F  Q1 ~
28 7 \8 x1 e' I" |% |; t
29 always@(posedge clk or negedge rst_n)) y8 G% ]# Z/ C! S1 z
30   if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
( m+ y* W1 b6 f0 j
31   else$ _  X8 e8 ~: Z+ g4 M- u) [
32     case (curr_state)& I, K3 H6 J" W: N- V
33       IDLE    : if (w_i) {curr_state, z_o} <= {S0,   1'b0};
# i  J" P( y6 x* P9 Q8 s( Z$ C
34                 else     {curr_state, z_o} <= {IDLE, 1'b0};
4 M" a: g+ ]0 i8 M
35       S0      : if (w_i) {curr_state, z_o} <= {S1,   1'b1}; //?
& I( k2 n  c* N
36                 else     {curr_state, z_o} <= {IDLE, 1'b0};. m. k6 V( }; P" [5 y
37       S1      : if (w_i) {curr_state, z_o} <= {S1,   1'b1};1 @# ?% J  M+ ~( D. O4 F: s9 {
38                 else     {curr_state, z_o} <= {IDLE, 1'b0}; //?
# ^& N; \3 g0 m
39       default :          {curr_state, z_o} <= {IDLE, 1'b0};+ E3 g% @" ^, x' K! ?. c6 x
40     endcase5 J. G- @% ]% y! _. }3 R% d3 i: ^
41 ! [( X2 K% }3 S; l( Y
42 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
' J- Y  U; s) w9 E" c
8 W  [/ u& t) B, f( H. x( k2 k" E  ^

29行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]% o3 Y1 q' {" V% B2 ^' Y
always@(posedge clk or negedge rst_n)
$ Y) f! Z1 h- e1 [  if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};. v+ ]0 B: _2 ]! S+ d& y
  else
: }7 t. n7 |' S* g    case (curr_state)4 [6 m! i( w- h$ i
      IDLE    : if (w_i) {curr_state, z_o} <= {S0,   1'b0};, F* ^8 r  I& a  M
                else     {curr_state, z_o} <= {IDLE, 1'b0};
% N* r; r  u- C* F  E8 t0 D
      S0      : if (w_i) {curr_state, z_o} <= {S1,   1'b1}; //?0 ~! x- c! g* F8 U( S0 S& P. ^
                else     {curr_state, z_o} <= {IDLE, 1'b0};
; L  r" A* b" ]* w7 R
      S1      : if (w_i) {curr_state, z_o} <= {S1,   1'b1};
4 }4 U3 g! v& N( C3 ~0 @
                else     {curr_state, z_o} <= {IDLE, 1'b0}; //?
* _+ T+ m/ K' Z9 l9 ^$ K
      default :          {curr_state, z_o} <= {IDLE, 1'b0};
- [. M. w5 X. \0 K1 n$ l- W
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]" a) J( P$ \9 r) b5 }- i5 p% Z

7 O' e. A, o1 ?" M- b  L/ p& U

使用1個always同時描述next state logic、state register與output logic,雖然next state logic與output logic是純粹的組合邏輯,但為了遷就於帶clk的state register,所以必須使用nonblocking。

根據之前的經驗,由於Moore FSM的output logic只與目前state state有關,且是純粹的組合邏輯,若硬要與state register用同一個always去描述,判斷上會出現一些問題,需提早1個clk用next state判斷(在state register與output logic合一時曾經遇過)。

在1個always內,連next_state也省了,所以在35行

S0 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};
8 K; J+ ^$ V0 e' T

當目前state為S0且輸入為1'b1時,output必須提前為1,因為這是在nonblocking內!!

37行

S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};
% h4 F' j/ h" ~1 r7 L% C) x

同理,在目前state為S1且輸入為1'b1時,output也必須提前為1,也因為這是在nonblocking內!!

使用1個always寫法的缺點:

1.因為使用nonblocking去描述output logic,所以要提早1個clk判斷,要特別小心處理,一不小心很容易弄錯
/ L, y4 U  `$ _4 O7 S. |2.1個always內同時包含next state logic與output logic,會增加code的複雜度,日後維護更加困難
! L" j/ Y/ [* N6 h- D! O/ Z

不推薦1個always寫法。

Mealy FSM架構

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106062055403233.gif

談完了Moore FSM,接下來談Mealy FSM,與Moore FSM的差別只在於Moore FSM的output logic只由目前state決定,但是Mealy FSM可由目前state與input共同決定。

Mealy FSM各種coding style比較

http://images.cnblogs.com/cnblogs_com/oomusou/201106/20110606205541692.gif

將之前的例子用Mealy FSM重新改寫,原本在Moore FSM下,若input w_i為連續2個clk為high,則output會在下1個clk產生週期為1 T的high pulse,若改用Mealy FSM,則output會提早1個clk出現,如上圖所示。

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106062055418151.gif

原本Moore FSM需要3個state,若改用Mealy FSM後,會只剩下2個state,接下來要用各種coding style來實現Mealy FSM。

1.使用3個always (三段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106062106115936.gif

simple_fsm_mealy_3_always_best.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]. @9 @+ l4 S3 p+ O. n- C7 y. J# f. P
1 /*
) {: l( J, E# ~/ s1 K# N
2 (C) OOMusou 2011 http://oomusou.cnblogs.com: h7 c6 s# C" ^, N2 r
3 $ M6 T) X: \# L7 M
4 Filename    : simple_fsm_mealy_3_always_best.v
/ W$ M+ Q) _  |' @$ k3 [0 R
5 Synthesizer : Quartus II 8.1
8 k: N' r: ~9 q3 X: [
6 Description : 3 always block for mealy fsm (BEST)0 j! N( g# u4 v# }5 G& H: F6 T
7 Release     : Jun.05,2011 1.0
& s0 n- S2 T$ r# f* V
8 */4 u: b! j/ Q# U0 q. I0 n
9
# c. D4 F$ z9 _0 k0 z& h* d10 module simple_fsm (- o8 X. o4 s& W" W
11   clk,
0 d! j& `$ e6 ^+ ]; c12   rst_n,& J# ?0 V4 a. ^( p% [) `* j0 p
13   w_i,9 H6 g5 ]/ m1 c
14   z_o
$ R, f2 l. R$ O( Q- I% D1 w7 G3 d6 @15 );# ?% L) E' W. B  M0 |
16 . {& }. @4 H; L5 B/ ^5 f5 m
17 input  clk;
& x& [4 [/ }6 j9 S/ m) ~18 input  rst_n;
3 v* t$ p8 D; u/ X; k2 v! `2 `19 input  w_i;- o/ p/ {/ e( u, r  p% t7 T
20 output z_o;& ^* V# D) v# ?% K. M+ E* n
21
5 E% ~! p3 |( g5 r8 j" z1 k22 parameter IDLE = 2'b00;
( r/ o+ R+ ?$ D
23 parameter S0   = 2'b01;+ N- u/ d7 k7 l" i7 k
24 5 u7 V* {8 \" _
25 reg [1:0] curr_state;+ s9 C4 E& h' P$ R! j. w0 P; X
26 reg [1:0] next_state;
0 n4 R& D! d$ ~' b- G% v27 reg z;' p8 a+ C: ]4 V1 t" ~# v
28 reg z_o;
9 _7 y* N) f. z29
5 v; Q. H6 [* y2 j30 // state reg
- L6 R& `. F) u- G! I
31 always@(posedge clk or negedge rst_n)
4 q2 R# x+ X6 [3 f, Z32   if (~rst_n) curr_state <= IDLE;/ [, W: @' c* J
33   else        curr_state <= next_state;
# b9 B" E1 X+ F34     7 u+ H, e0 u8 T7 i8 v. M# S
35 // next state logic   
, h+ @7 v( ^: ?
36 always@(*)% f' E/ z( F7 r4 u  x
37   case (curr_state)
9 l( H* F, y/ f4 }38     IDLE    : if (w_i) next_state = S0;9 v+ J% ~! m/ U+ k1 E
39               else     next_state = IDLE;
3 M1 h  r+ i* k+ D40     S0      : if (w_i) next_state = S0;
3 P. {$ J) }: x% o" _0 J41               else     next_state = IDLE;
& F! T2 {$ O$ Q- u" ?42     default :          next_state = IDLE;
2 a( H4 p, T: o, |) I' ?6 [43   endcase   
) M: Q  C  q5 Z2 `  o0 M' B44 . N4 R+ B8 c- o" B9 m$ k
45 // output logic+ }$ S( B/ S! F$ }
46 always@(*)
5 h; S, N9 h+ N" o; f7 y- |47   case (curr_state)
  F4 W) a- {" ~( a6 d) ]48     IDLE    : if (w_i) z = 1'b0;* t$ B# L9 Q- K. U
49               else     z = 1'b0;      
4 T- T% U2 T$ z# w$ H' g, x
50     S0      : if (w_i) z = 1'b1;
* o& f, w: J9 u' p* x
51               else     z = 1'b0;! T: l8 R( J% I5 n5 T2 ~0 h* r2 a
52     default :          z = 1'b0;
5 t+ X% ~! G7 a& l! L0 `5 v* @
53   endcase+ a5 ~' Q  a( [; A7 ]' I
54 ' @% v' {1 e1 f9 m& M
55 // mealy output to delay 1 clk for moore  9 T/ ]" _/ d/ K1 t) @' F: J
56 always@(posedge clk or negedge rst_n)
" ], k* O2 _9 H( n. _3 B& X* |57   if (~rst_n) z_o <= 1'b0;
5 a( _0 X: r4 Q8 t9 T
58   else        z_o <= z;
: Q: M' X, X# t. p" d" ~59     9 b" D& u+ c/ q. K& [+ c. o
60 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
3 [" O8 Y/ l; z& S  N# A+ J1 V

6 V) W4 [. j. g: u7 k6 K* J! V; {

30行

// state reg; F7 x) ~, K+ f/ ^+ B
always@(posedge clk or negedge rst_n)4 b. R2 O& R( H/ r  E* w
  if (~rst_n) curr_state <= IDLE;
. _3 `8 q1 z7 p9 @! V9 f  else        curr_state <= next_state;

6 N" C" i5 L! a+ ~3 _' l

使用1個always描述state register。

35行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
$ N) ^, i. [4 _// next state logic   
1 m7 B  K5 Z0 C1 x0 K3 \$ n
always@(*)
7 H! E% [3 Q- r  case (curr_state)6 x' B  }9 b( L8 X2 L
    IDLE    : if (w_i) next_state = S0;7 x: B/ P' M+ Q
              else     next_state = IDLE;
) t3 n9 ?, y/ ~0 Y8 S. F    S0      : if (w_i) next_state = S0;
# U& o4 H, r; @* P5 f              else     next_state = IDLE;, ^; n: t! \5 f, Q
    default :          next_state = IDLE;- a. C7 ]7 T9 ^
  endcase  [url=]http://common.cnblogs.com/images/copycode.gif[/url]8 s5 ?4 B* X' t4 I
; Q4 F/ x; _( T) N4 k( V4 e

使用1個always描述next state logic。

45行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
' ^; l; m% ?6 E4 s" Y! P// output logic
# h/ v* \& `" D3 f+ y; S8 Z
always@(*)* Y; D. f1 ^( J% ~. L) n  `
  case (curr_state)
0 m4 e! j0 E6 m+ z8 @. D) N2 v    IDLE    : if (w_i) z = 1'b0;2 C* L: B' D: m5 F% c9 B
              else     z = 1'b0;      
3 C) e* m9 I* Y" a  c; M% C7 H0 T+ n
    S0      : if (w_i) z = 1'b1;
5 i7 P3 j% Q5 w0 d  g
              else     z = 1'b0;3 U. x5 x+ e, ~' }: y3 g
    default :          z = 1'b0;
- `9 T5 R* O& C# y2 K& M% n
  endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
8 q* n) e2 w5 \' |. Q" s' u) q  Q
+ ^4 `/ R( ]6 Y

使用1個always描述output logic。

以上3個always寫法與Moore FSM的3個always並無差異,基本上只要state diagram畫的出來,就能等效地用Verilog描述出來。

55行

// mealy output to delay 1 clk for moore  
+ P7 ^0 s4 f" X' Z6 X
always@(posedge clk or negedge rst_n)
6 B  ~. e8 x2 L9 i* T- s  if (~rst_n) z_o <= 1'b0;/ G( r: O0 F2 E: u
  else        z_o <= z;
- |. p4 u, v+ A% r2 o% [+ Y: U

之前提到使用Mealy FSM會少Moore FSM 1個state,且output會早Moore FSM 1個clk,所以最後特別將output在敲一級delay 1個clk,這樣Mealy FSM就會完全與Moore FSM一樣。

使用3個always寫法有幾個優點:

1.可忠實地反映出原本的Mealy FSM硬體架構3 K1 W; W$ w, w) Z: M* x
2.可輕易地將state diagram改用Verilog表示+ K0 v# d/ u% T0 E4 K
3.將Next state logic與output logic分開,可降低code的複雜度,便於日後維護
/ G4 L# I( \" r  V0 U$ x$ ^5 N

3個always是一個推薦的寫法。

2.使用2個always (兩段式)

由於要使用2個always去描述3個block,根據排列組合原理,C3取2,共有3種可能,我們一個一個討論。

2.1 state register與next state logic合一

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106062204201676.gif

simple_fsm_mealy_2_always_0_cs_ns_good.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]- w: V" r, G& e' ^
1 /*
- H- @, _) `) E
2 (C) OOMusou 2011 http://oomusou.cnblogs.com0 Y  n6 [% [/ `2 F8 [. A
3 : j# q+ D7 g- H
4 Filename    : simple_fsm_mealy_2_always_0_cs_ns_good.v* ^/ |2 B; j7 a% n0 I
5 Synthesizer : Quartus II 8.1
( k  n% u/ M+ P2 S/ b. {
6 Description : 2 always block for mealy fsm (GOOD)
; f  a0 Y3 x+ `1 g) j  C" t; D( R9 L
7 Release     : Jun.05,2011 1.01 c- Q/ M) a9 [# U
8 */
/ ^+ G9 ?: z2 j# t% ?- S) O 9 - P2 e" g8 u$ p8 r) @
10 module simple_fsm (
2 E6 u. {3 S) G8 C* Y9 `$ L! V# h11   clk,: i/ I2 P1 U+ g" M! E
12   rst_n,
& |7 V  _3 w3 c% V- S. n13   w_i,6 ^0 C7 c# i- f- {2 z  Z3 @+ A2 ?* F
14   z_o
% O6 r$ e; P# \9 G- t% G15 );( y! S' _0 T6 J, X/ _; S  [
16
/ |/ N9 G2 O' X0 `' m# e17 input  clk;: W1 v8 B7 d) P8 C# E+ B. W2 H
18 input  rst_n;- G) M, |' y; m* c7 M- P
19 input  w_i;
; e- e! y* r1 N6 x: n! f  `, P20 output z_o;
( a( Q6 t2 g1 v+ r; E' k! n21 " M2 C) k; B0 q0 e' n  r
22 parameter IDLE = 2'b00;
& k+ y! N+ U( g5 T3 r# t, }6 f
23 parameter S0   = 2'b01;
  @. v. G6 i2 N; J$ |
24
9 E( S: V) Z" v' j25 reg [1:0] curr_state;
; F1 P( V8 P& y+ v! W9 p5 x( T26 reg z;
- i; }" I- d/ q% i# Z4 A8 p; d27 reg z_o;
2 D+ \. I7 G5 A" C; _7 W+ w* H28 4 ?. d) ?) {7 B0 x- D0 M" ~
29 // state reg + next state logic5 U3 u% C, C! h
30 always@(posedge clk or negedge rst_n)
$ _- x6 O3 J* M& W1 l31   if (~rst_n) curr_state <= IDLE;
" Z- y1 C7 m/ F: L32   else
' P' \  O* O. M/ V+ Z33     case (curr_state)! h/ }9 e+ F+ q. M% j
34       IDLE    : if (w_i) curr_state <= S0;
+ d# H" {  @! U. ~35                 else     curr_state <= IDLE;" B/ j# V( |  t$ k' q& X2 T1 Q
36       S0      : if (w_i) curr_state <= S0;
9 {/ t* y' \, w/ \37                 else     curr_state <= IDLE;/ J! v3 P0 u  _9 W1 C. C
38       default :          curr_state <= IDLE;, E; V, \! L0 `& d5 T+ i9 @& S; Q
39     endcase7 E2 _) @9 K$ s" y. k. a8 P
40     $ X1 l7 E" E- a3 e; d! T
41 // output logic
1 I% `6 E4 ^. ]! H# J; c% |4 \% [
42 always@(*)! G6 G# S$ c  ]' {- Y% x; g
43   case (curr_state)7 I/ B  y3 j* d3 \  Y0 n( Z* |2 L
44     IDLE    : if (w_i) z = 1'b0;
+ }( h1 [" n5 K% \/ {/ X2 i  N
45               else     z = 1'b0;- A% s2 ^1 E2 B: V+ m
46     S0      : if (w_i) z = 1'b1;1 \0 |' `) N7 v2 l2 a$ D2 W
47               else     z = 1'b0;% X  R) d: O3 T9 v# S; j
48     default :          z = 1'b0;+ @* I' S3 r7 e8 ?! W) P6 x
49   endcase
- U; f( |2 q. k+ Q6 _3 B0 s50 ; Q. T% M0 d& b2 X: V4 E: g
51 // mealy output to delay 1 clk for moore  
! O& v& E* K8 G7 p7 f0 k& z+ C! @
52 always@(posedge clk or negedge rst_n)
( P1 `4 @0 F( ~53   if (~rst_n) z_o <= 1'b0;
2 o  g- O/ D9 @
54   else        z_o <= z;( @: i- S1 N" F7 v7 O
55
0 [: Y2 F2 E5 ^4 d; X# L: [  P56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
5 a  _" d* e% Q! n1 P# U0 n

- v" V7 A/ Z; _" q& ^" I9 r

29行

[url=]http://common.cnblogs.com/images/copycode.gif[/url], K2 O4 V; @: u0 D
// state reg + next state logic
& A) p) p+ c0 g7 m- }
always@(posedge clk or negedge rst_n)$ f7 R7 `! u3 F3 k6 K, L5 V# v& K
  if (~rst_n) curr_state <= IDLE;
! U+ K- I( N! \# e) h: _7 ^9 P! w$ A  else
/ b$ l1 u( V' J/ [) J    case (curr_state)
, f9 O( G7 p% i  B      IDLE    : if (w_i) curr_state <= S0;
5 t5 N3 N6 u, j- h% C3 f8 y                else     curr_state <= IDLE;8 W  t$ _4 u; g2 |- p; [( ]
      S0      : if (w_i) curr_state <= S0;) e7 r7 D- s  Q7 J1 J
                else     curr_state <= IDLE;1 Q2 z$ p+ w# u; J: }; i8 L8 }
      default :          curr_state <= IDLE;
/ ?( A* r! {) o2 W! x0 P) b    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
6 e( H4 z& \4 h9 w, L- k

" k0 [$ F1 U  A& W$ j# H, K& u

使用1個always同時描述state register與next state logic。

41行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
9 V( f- o! I/ K( v5 g// output logic
& ^) D* g' b; Y6 {: O5 N2 n
always@(*)
! F# G: c  g' M5 g7 C3 u7 s5 \  case (curr_state)
+ P2 N) C- J8 C8 E; o    IDLE    : if (w_i) z = 1'b0;
8 D) L1 j! p6 ~. o4 N2 i# R
              else     z = 1'b0;0 G3 q9 |0 ]6 A1 A5 [) O
    S0      : if (w_i) z = 1'b1;8 q2 Q  I  ^4 M7 Z+ `, {
              else     z = 1'b0;% o: A  l. a$ Q1 t# M: a  i: C' C
    default :          z = 1'b0;- e% t- N& z' W3 e& s: B
  endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]0 w# B4 y# Q: j1 R- B+ _7 W
) `# t' x! T) M& _$ j

使用1個always描述output logic。

以上2個always寫法(state register與next state logic合一)與Moore FSM的2個always寫法(state register與next state logic合一)並無差異,基本上只要state diagram畫的出來,就能等效地用Verilog描述出來。

51行

// mealy output to delay 1 clk for moore  
. w$ A5 U0 X) s& n) ?
always@(posedge clk or negedge rst_n)# o, c! F! e' [/ G
  if (~rst_n) z_o <= 1'b0;6 @8 l8 t1 i: K6 G
  else        z_o <= z;

/ s: W- j8 i6 t9 Y7 J

之前提到使用Mealy FSM會少Moore FSM 1個state,且output會早Moore FSM 1個clk,所以最後特別將output在敲一級delay 1個clk,這樣Mealy FSM就會完全與Moore FSM一樣。

使用2個always (state register與next state logic合一)寫法有幾個優點:

1.程式碼較3個always寫法精簡
  H  X; `5 F- ~. N2 X0 ], o; ~2.可輕易地將state diagram改用Verilog表示. T& Z4 m9 w9 T# z8 B5 n% L5 z
3.因為state register原本程式碼就不多,將next state logic與state register合一後,next state logic仍與output logic分開,因此不會增加code的複雜度,便於日後維護

3 E( F: ^9 a! ^' h8 m* ]3 X9 v! n

2個always (state register與next state logic合一)也是一個推薦的寫法。

接下來要討論的都是不推薦的寫法,主要目的是了解為什麼不推薦的原因。

2.2 state register與output logic合一

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106070634371434.gif

雖然理論上可以用1個always同時描述state register與output logic,但實際上做不到,因為Mealy FSM的output logic是目前state與input的純粹組合邏輯,與state register合一後,就必須使用nonblocking描述,之前Moore FSM還可以提前一個state去做判斷,但Mealy FSM還有input,該如何提前1個clk去判斷input呢?

2個always (state register與output logic合一)無法描述Mealy FSM。

2.3 next state logic與output logic合一

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106070634388892.gif

simple_fsm_mealy_2_always_2_ns_ol_ng.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]/ S6 n+ n" h8 x; Q$ w2 v
1 /*
2 B% W/ s- Y1 ^6 _3 S, S
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
# T9 ~0 N8 _+ @: h# v! u; K
3
: i. k( r4 T) `3 D
4 Filename    : simple_fsm_mealy_2_always_2_ns_ol_ng.v( \# ?1 h4 X7 h$ J( D' S* C& ]
5 Synthesizer : Quartus II 8.1
6 }( }$ f- d7 V9 r* O8 M, r
6 Description : 2 always block for mealy fsm (NO GOOD)
" p/ j( V* `& X0 P: t( O6 W
7 Release     : Jun.05,2011 1.0
+ K5 h5 ]3 F# B  g* C
8 */
+ w7 b$ y9 k9 u2 e* X- w4 d 9 % E" i7 K5 v3 r% I5 w6 N6 w1 ?) M
10 module simple_fsm (
1 s/ `0 b7 B- o, U+ m/ N11   clk,( }3 F. s2 g2 R
12   rst_n,
. t+ ^( `# l8 @# m# }13   w_i,
6 ]1 K" B9 n! H. }. d5 M14   z_o& t7 u! {3 }" ?2 p# {& V4 R
15 );( }' _) S3 p# e- B7 z
16 ' T. l0 h8 I, ~
17 input  clk;
5 \8 p/ }( v+ e% K- R" |; s9 F18 input  rst_n;
  p" W" O) g& @19 input  w_i;
! C/ q- J, t* l! E( G! V* n20 output z_o;
0 Z' T; H0 z" U+ M0 U7 F+ U21
: F3 \( o  u# j22 parameter IDLE = 2'b00;- B) j0 k8 S0 l
23 parameter S0   = 2'b01;& A2 ^) |4 v; A# Y( [  h
24 : c5 D9 g+ R  a8 H
25 reg [1:0] curr_state;; g" E! @$ S9 r7 ^$ r: |3 T
26 reg [1:0] next_state;4 r, I0 n; m3 o# _
27 reg z;
3 Y( M. }! @! W2 U0 t8 _! X8 A' L28 reg z_o;
. v9 p! C+ F; ~4 X" f29 ' T  U) c9 I$ I
30 // state reg8 A4 k! G$ D; \  @+ x3 b4 I
31 always@(posedge clk or negedge rst_n)
- n9 R' P  A5 Z8 u! _" Q% y32   if (~rst_n) curr_state <= IDLE;! Z# t% B% w, r2 K; b7 k! o
33   else        curr_state <= next_state;- F: v0 w/ X# x5 Y  O
34     
. ^0 m2 s- a$ f. k2 s35 // next state logic + output logic   
; e0 W6 r, c  @/ K6 [; g( f' H
36 always@(*)
2 z8 z. ]) B  W0 `* g3 ~37   case (curr_state)
7 f2 u' a1 ^7 i( ], A* ~) m1 L38     IDLE    : if (w_i)   {next_state, z} = {S0  , 1'b0};9 A9 M9 L. O! ~. ~7 P" N: r  }* R
39               else       {next_state, z} = {IDLE, 1'b0};9 d! e+ l$ ~+ g# ?7 c1 c0 R  u
40     S0      : if (w_i)   {next_state, z} = {S0  , 1'b1};
* T# |2 c9 K1 n: q& d- `
41               else       {next_state, z} = {IDLE, 1'b0};
+ ~2 u, ], q) e1 w) q
42     default :            {next_state, z} = {IDLE, 1'b0};+ e- L# }5 I* p2 U) C$ ^
43   endcase9 N- T. Y& d& u& w. u7 Z* H+ D
44
. O8 X! L& s. S: B45 // mealy output to delay 1 clk for moore  
' P8 p4 p9 F" S! h) }% W8 c1 D/ n9 z& X
46 always@(posedge clk or negedge rst_n)
) e9 d- W/ c7 V5 ^+ @5 B47   if (~rst_n) z_o <= 1'b0;
7 P7 Y. d3 D- h8 Z2 n
48   else        z_o <= z;8 a0 t5 G1 }1 X
49 / ?/ I8 u. q# w1 I
50 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]- f: O4 _2 N9 Y' t: S$ u" ~
# w! F  z( T; T/ Q* r& ]( ?

30行

// state reg2 h* A: m1 h" E7 S; @& J
always@(posedge clk or negedge rst_n)  \& D# V+ n& ?: Z% X
  if (~rst_n) curr_state <= IDLE;
9 u- s/ V7 P3 g3 c- [. {2 m  else        curr_state <= next_state;

0 M3 k- s) t" B" R

使用1個always描述state register。

35行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]! r3 ~; \1 [8 \! W3 n
// next state logic + output logic   7 G9 t6 A& g9 k7 }2 h+ d* ?( f
always@(*)4 n( H- ^2 f& ]7 k
  case (curr_state)1 d4 @# L8 o; ~) T5 M9 U
    IDLE    : if (w_i)   {next_state, z} = {S0  , 1'b0};
0 j8 s$ N3 _$ r8 D1 O0 Z
              else       {next_state, z} = {IDLE, 1'b0};! I8 Q' e7 _4 O  p( h
    S0      : if (w_i)   {next_state, z} = {S0  , 1'b1};
0 q% s+ \, P6 `* r9 g/ s5 m
              else       {next_state, z} = {IDLE, 1'b0};
- E: M" v  ^9 y: ]5 o; q
    default :            {next_state, z} = {IDLE, 1'b0};) ~! a3 V+ ]6 t  R! b
  endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]) j9 W1 W& D& ?( X

2 \" ^# u  n: ^! s( }; [

使用1個always同時描述next state logic與output logic,因為兩者都是純粹的組合邏輯,所以使用blocking。

45行

// mealy output to delay 1 clk for moore  
8 A6 x# k% P/ ~% o: ~
always@(posedge clk or negedge rst_n)- P) H! G# e+ \# e
  if (~rst_n) z_o <= 1'b0;  l' g' D( j9 X2 O2 O
  else        z_o <= z;

$ ^( E* ?  J' H5 a

之前提到使用Mealy FSM會少Moore FSM 1個state,且output會早Moore FSM 1個clk,所以最後特別將output在敲一級delay 1個clk,這樣Mealy FSM就會完全與Moore FSM一樣。

使用2個always (next state logic與output logic合一)寫法的缺點:

將next state logic與output logic合一只會增加code的複雜度,日後維護會更加困難
6 V) x5 _& t# \9 J

不推薦2個always (next state logic與output logic合一)寫法。

3.使用1個always (一段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201106/201106070654206414.gif

理論上存在使用1個always同時描述next state logic、state register與output logic,但實際上做不到,理由與2個always (state register與output logic合一)的理由一樣,1個always必須使用nonblocking描述,而Mealy FSM的output logic是目前state與input的組合邏輯,我們無法提前1個clk去判斷input,所以無法使用1個always去描述。

1個always 無法描述Mealy FSM。

只要output logic使用nonblocking去描述,就無法實現Mealy FSM output。% E3 U: q+ I8 E3 O" h7 w

實務上推薦的coding style

如之前所述,實務上為了timing更好,常在Moore FSM的output logic再多敲一級,以下為推薦的coding style:

http://images.cnblogs.com/cnblogs_com/oomusou/201107/201107192248215766.gif

1.使用2個always (兩段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201107/201107192137268414.gif

simple_fsm_moore_2_always_0_cs_ns_good_pratical.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]5 U1 r, G# f9 ]/ S) q+ y  ^
1 /* & b3 H+ s' ?$ I
2 (C) OOMusou 2011 http://oomusou.cnblogs.com- d  g4 v- d1 t- y0 l  D
3 " @8 W% l4 J# q, v: \
4 Filename    : simple_fsm_moore_2_always_0_cs_ns_good.v% k' H+ t( Q% u2 g2 ^* N  M; h! M
5 Synthesizer : Quartus II 8.1
6 C/ s* ^  U' T' R; }/ ]
6 Description : 2 always block for moore fsm (GOOD)/ G) B/ H: A9 a3 c8 k8 X
7 Release     : Jun.05,2011 1.09 d% [" |* g  ?( v7 X/ H
8 */) ^' \% P. A& P! a! i
9
4 b! N* V& ]  R10 module simple_fsm (& V' \8 M- d0 M1 m9 |
11   clk,
) h. F6 L, V# H4 C) n3 z' s3 j1 b12   rst_n,
" _! }: O5 y& \13   w_i,
# L- P* o$ y' Y! G$ i6 o14   z_o
$ {8 z, e) V  C$ f9 w8 i9 |15 );% ]7 F. L: O' J4 G( z" B4 n- e7 X
16
- T0 n; k7 c7 N& i5 o17 input  clk;
; K% o6 y, X6 T/ Q3 \4 D) G' J  e18 input  rst_n;
+ L# Q& N( V& @! |. E) E19 input  w_i;
8 ^% O9 ?! }- y# R) \# n20 output z_o;" Q- @/ @8 z; y7 j
21
, g7 Q1 I) T+ s4 I: k1 e2 x22 parameter IDLE = 2'b00;
6 X# B/ X8 x  c9 }9 Z0 K6 Q% G
23 parameter S0   = 2'b01;
9 [  X2 |. `6 h% b1 ?# i$ O! H) y
24 parameter S1   = 2'b10;5 O+ d, d% q% g8 t8 j$ Z( w: M+ B* @
25
# Y. J3 x! C7 j$ y- J26 reg [1:0] curr_state;# W# t' r! X, U1 m' ~! B) V
27 reg z_o;
4 V% m0 _3 \0 c% b/ P) I28 ; J4 n! _/ O* c' J* `
29 // state reg + next state logic9 p, p) ~2 o" k& f7 e2 o
30 always@(posedge clk or negedge rst_n)5 W& {" h; `# t& t8 T9 f. V% S
31   if (~rst_n) curr_state <= IDLE;& a; z3 X' v$ k- R- O
32   else
4 m8 T: y: _9 ?) f4 G33     case (curr_state)
3 e  E- U3 U' y% o& r" g34       IDLE    : if (w_i) curr_state <= S0;
5 R0 m7 |! P( j/ t. @8 [35                 else     curr_state <= IDLE;
5 x4 i4 f7 @+ o! X9 _6 i36       S0      : if (w_i) curr_state <= S1;
3 m! }6 o2 O# A+ P+ f37                 else     curr_state <= IDLE;
, y; L2 F4 i0 }4 B, b' k; ]38       S1      : if (w_i) curr_state <= S1;& x! T  a, P$ i( }! m& L
39                 else     curr_state <= IDLE;9 U4 Z9 M6 @3 P0 t( P- `
40       default :          curr_state <= IDLE;
  b0 ]4 F# C$ u( d41     endcase; e8 u" _9 _8 Q0 m0 n" q( {: R
42     
2 T3 P; Q& I/ w7 B$ v43 // output logic1 F5 s$ O7 S/ I; v. X. s
44 always@(posedge clk or negedge rst_n)2 C0 J1 r7 F3 Y9 ~' e) `8 B
45   if (~rst_n)
; W/ F% R. u/ K. o46     z_o <= 1'b0;
( D' C  {9 W/ ?4 \" M5 _
47   else$ V, h. [; I7 a: d4 ]& J
48     case (curr_state)0 G. {, q: @9 q3 J
49       IDLE    : z_o <= 1'b0;
$ ^( Y* H3 n% R. B9 C: V
50       S0      : z_o <= 1'b0;6 j0 L! v! M! W# f+ h
51       S1      : z_o <= 1'b1;
! R$ C7 [& N4 r6 c* a* v- L& ^
52       default : z_o <= 1'b0;
7 u9 t& v' ]2 m0 X* v; G
53     endcase
& E- t2 G3 d9 q" R% o54   7 c: x' X- H( }
55 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]. s# B, E" h. K' _
! G, e# j5 w2 d; F# f0 `

29行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]2 @2 L+ u. p: H# m; m) {- v
// state reg + next state logic9 W% |4 J! }% \4 G
always@(posedge clk or negedge rst_n)  h; \9 _6 E- q' v% z# V: N. X
  if (~rst_n) curr_state <= IDLE;
& F6 n# V, m# P! ]$ l1 g& b4 q  else# a, @9 b& l- L0 W! f$ Y* h
    case (curr_state)
& l- |0 t/ S0 X, x% ^      IDLE    : if (w_i) curr_state <= S0;: {9 v, w+ v# s
                else     curr_state <= IDLE;
3 S& m8 ~! K& U      S0      : if (w_i) curr_state <= S1;+ j( Q0 u/ N4 t  P' n
                else     curr_state <= IDLE;+ }/ F& I" i6 k5 x/ D7 ^' x
      S1      : if (w_i) curr_state <= S1;' h6 P' w0 n) q  m. }* g9 }3 b, n
                else     curr_state <= IDLE;
2 Y' ~. s- B0 A( L' F      default :          curr_state <= IDLE;$ j: E% Y6 f5 z9 H5 O' z4 A
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]$ i1 u, g$ c' w& C

# {/ v5 d1 |! _/ V$ X1 \0 i

使用2個always,且state register與next state logic合一,只要判斷curr_state即可,不用擔心是否要提早1個clk判斷。

43行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
+ k6 n* Y! n) f// output logic; U; o& F. ]3 M& n% W
always@(posedge clk or negedge rst_n)
7 O: O+ |$ O; ]  if (~rst_n)' ]1 ^/ u1 o$ K3 l. c  O; d
    z_o <= 1'b0;
, ~/ B8 N2 |; h; n& h/ l( f5 u
  else7 N$ m5 G6 a% ]" {6 x  @
    case (curr_state)$ y4 [0 j' s9 \# V6 R) C8 j' d; K
      IDLE    : z_o <= 1'b0;/ ]2 ^- l( \& J3 q
      S0      : z_o <= 1'b0;# K$ e& q% `7 R  [) n
      S1      : z_o <= 1'b1;, u8 p2 u( z# r8 ~9 s
      default : z_o <= 1'b0;0 `" ~0 P9 J& G' A# b. {
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]8 h4 z% ]" \" t% _0 k% x4 R4 C

! [9 }) H4 ~5 M6 g- l

output logic也敲clk,只要判斷curr_state即可,不用擔心是否要提早1個clk判斷。

2.使用3個always (三段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201107/201107192138251792.gif

simple_fsm_moore_3_always_practical.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]9 ~  \% \2 @1 s6 L- {: f5 b$ Q5 i! `9 m& G
1 /*
8 p3 P7 I& m  m" |6 T9 X9 J) j
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
9 b( b! v  n+ C* \" p3 ]) E
3 2 Q4 O& Z8 T0 }: X# Q4 C
4 Filename    : simple_fsm_moore_3_always_practical.v: V1 w" k) e& D( H+ |+ T& G* {
5 Synthesizer : Quartus II 8.13 I7 R- U/ `, o6 h6 F& V0 r
6 Description : 3 always block for moore fsm (BEST)7 R6 R" r% [' a+ U1 z
7 Release     : Jun.05,2011 1.0& r1 ~7 Y1 u; ^( g" s6 Q8 ~
8 */6 x% T" K- R1 V* A/ F( O$ c0 Y
9 8 T& B" ?+ k* o6 O4 I  L
10 module simple_fsm (
" @4 a. s  i4 a. h2 }11   clk,
9 I% B- e8 X! }: [12   rst_n,) k$ d! y; F4 j) @
13   w_i,( |9 t- L6 k. \1 T" j$ f+ {
14   z_o
0 U: _0 I5 g, R  G, j( A15 );
+ P2 v' Y7 b- w2 E. R16 " s  d5 _$ f5 W* I! B
17 input  clk;. }6 p% T% K' g6 Q4 e
18 input  rst_n;
; h1 |" X1 `1 m: _* N" P4 D19 input  w_i;+ ~& P7 g' B! f! H( c1 F/ f$ _' s0 v
20 output z_o;. N$ `. W- s1 R* P3 F
21 ! m% F; t& G% j' m1 D$ T, o
22 parameter IDLE = 2'b00;
" ^3 ~- Z7 R) T1 U( ~  l* ^# e% S/ D9 e% y
23 parameter S0   = 2'b01;
" }! {" j! G* C
24 parameter S1   = 2'b10;
' }! f! D/ x) b
25
5 K6 t. w* e4 ^* J% F9 H1 v! n2 f26 reg [1:0] curr_state;4 F5 m- C! w' w1 ~" O  D  n
27 reg [1:0] next_state;( l: y9 ?& y5 b: J
28 reg z_o;% f5 S- R! O4 g" l$ f0 t
29
4 E# m$ ?# X3 W; @30 // state reg3 n3 X# P( |0 P7 i9 E/ s
31 always@(posedge clk or negedge rst_n)
! ]/ S. G7 D2 ]- f6 `$ g  x32   if (~rst_n) curr_state <= IDLE;2 g, f  o3 Q3 C) i( b" N
33   else        curr_state <= next_state;; c2 J, E* `+ O1 |0 n# E+ g, Y6 P
34     
* `4 n8 r! B. f5 l) i35 // next state logic   
# @# ~0 c: X: u! v/ r1 M- Z
36 always@(*)+ I* P9 B- d8 W0 ?' w
37   case (curr_state)
# O: I: C) a3 H5 v! N  Q& v) {38     IDLE    : if (w_i) next_state = S0;3 J9 X  r+ Q2 @+ r/ E" E- \
39               else     next_state = IDLE;
5 r" V, H0 u) k- j2 H) q8 V$ d) f40     S0      : if (w_i) next_state = S1;' I8 Q( D( i# w8 b" B# R- \5 e
41               else     next_state = IDLE;
5 p: A4 g5 `. }+ A42     S1      : if (w_i) next_state = S1;
8 i: e: B! W- p4 F43               else     next_state = IDLE;* c" c6 S7 C1 H0 {5 a
44     default :          next_state = IDLE;/ I, E9 i- E7 {4 {6 R/ k( A! \
45   endcase    2 o0 P. s4 f4 G5 u6 i' [
46
4 P) z. [" V- A/ y) S8 r$ o% Y) d7 G0 s47 // output logic- y9 _3 G1 Z" t) M
48 always@(posedge clk or negedge rst_n)
# P3 y. h6 G; n/ K; h49   if (~rst_n) z_o <= 1'b0;' v. P; Y  D7 r/ d; j) K
50   else
4 r: {4 D2 K% J& j+ }! c/ B51     case (curr_state)$ p2 ]. W- J7 r! p) ]! F$ }; C0 w
52       IDLE    : z_o <= 1'b0;
! y3 G5 n" g+ \- \7 h1 R6 u
53       S0      : z_o <= 1'b0;
+ |8 f* s+ K% ]6 Z( V
54       S1      : z_o <= 1'b1;: u1 T  p% z/ u, R6 w* r5 N& C
55       default : z_o <= 1'b0;3 h& }/ W* h+ p( b) N9 x% b
56     endcase7 E& Y6 T1 ^2 l8 q% h
57   ; k- `1 w, c% f' i' B6 y
58 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]) j" ]' {1 x. F6 v
3 N, k8 a( O  ^! v3 A6 ^

30行

// state reg
) L* q$ t3 |! O5 _3 U: x* T
always@(posedge clk or negedge rst_n)/ Q7 f) c6 ?; H* n: y% H# G
  if (~rst_n) curr_state <= IDLE;! f2 ?0 _! X1 Q' v! ^
  else        curr_state <= next_state;
" p3 z8 h$ A8 Z- L0 G+ S) |

使用1個always描述state register。

35行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
( u0 |- X) J6 k( L- t; u/ }// next state logic    . `* ^4 O* Z: I# J5 U) h
always@(*)9 ~( q% A, X0 P, J
  case (curr_state)
5 {* b4 e( I, m. h( b  E    IDLE    : if (w_i) next_state = S0;
) J) u; B7 s' u7 O  Y              else     next_state = IDLE;
6 ]+ m3 U, N+ L8 w! u; X1 [    S0      : if (w_i) next_state = S1;5 v: r/ l& b2 I6 G( z
              else     next_state = IDLE;
( X* M3 X5 R& d' E' y/ V    S1      : if (w_i) next_state = S1;
* q9 F3 J3 |6 ~# G' v              else     next_state = IDLE;# t& G; ]3 H& r3 P  k$ o
    default :          next_state = IDLE;; Q% |* H% i% [% C- ?
  endcase  [url=]http://common.cnblogs.com/images/copycode.gif[/url]
2 t6 }% D, [4 p2 U: f7 Z0 _
" [! b# V! B7 T! X( F  M

使用1個always描述next state logic,為純粹組合邏輯,所以使用blocking。

47行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]
2 \: Q0 c+ v* N9 ?. |// output logic
) @# U% \) ~! C. w1 x3 m
always@(posedge clk or negedge rst_n)4 g9 R7 L+ \+ [3 ~
  if (~rst_n) z_o <= 1'b0;, k* h( j+ X. m$ P& {5 T
  else 4 e8 W( T  |. U4 x  [' [9 k$ Z
    case (curr_state)! t: R, I# c7 X; q( Z2 [* Q
      IDLE    : z_o <= 1'b0;
! ~7 Z5 h% ^3 Q2 {% w- @5 v# t
      S0      : z_o <= 1'b0;0 }: s1 \$ e: X) h
      S1      : z_o <= 1'b1;. }# S% e) O/ _6 S% r6 j
      default : z_o <= 1'b0;
) R8 u6 w: n) _# m, W! s0 B) D
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]5 X) l. m# s3 a% O. L! i3 y
7 ^! {' s! C5 Q' F( H1 L( y

使用1個always描述output logic,因為output logic也敲clk,只要判斷curr_state即可,不用擔心是否要提早1個clk判斷。

看到這裡,或許你會問:『為了timing好,多敲一級會多delay一個clk,若我output logic提前1個clk用next_state判斷,不就既可有較好的timing,也不會多delay一個clk?』

http://images.cnblogs.com/cnblogs_com/oomusou/201107/20110719225555853.gif

1.使用3個always (三段式)

http://images.cnblogs.com/cnblogs_com/oomusou/201107/201107192310123304.gif

simple_fsm_moore_3_always_practical2.v / Verilog

[url=]http://common.cnblogs.com/images/copycode.gif[/url]) p& @* L3 e  i2 o7 `+ X7 h6 V0 u
1 /*
3 N% \$ q% s! E' y* L4 A
2 (C) OOMusou 2011 http://oomusou.cnblogs.com, ^' a6 f, X3 }; ]+ T
3 ) t) W7 E) w+ _5 |# s
4 Filename    : simple_fsm_moore_3_always_practical2.v
9 q% G' s2 N2 j3 ?& d
5 Synthesizer : Quartus II 8.1
1 M- g* O; f- G! h$ y5 {+ |
6 Description : 3 always block for moore fsm (BEST)! ^/ m4 B8 k7 K/ z/ M+ R. R
7 Release     : Jun.05,2011 1.0
' u/ w; m+ Q% t6 [
8 *// X% b1 h: }" k4 u& s$ F
9
$ @0 ^, f2 `! Q; S9 A  J10 module simple_fsm (* t+ C- h- Q- Y$ g( Y
11   clk,: G2 s! B$ L( H" [9 X0 p
12   rst_n," t+ C$ ]& q& f# I0 v2 I& a
13   w_i,5 F+ k5 |9 W# M. w' p+ t
14   z_o
' [1 _4 i3 b- ]. Q3 H- g15 );
% p, O8 k/ `& C7 w$ v0 M8 [$ K* m, V16 ' t/ e. z2 O% M* Z
17 input  clk;2 Z+ d! P2 r, p3 m7 S: E
18 input  rst_n;
$ Z: O) u; u) a$ ^$ `19 input  w_i;
; O; y0 i+ Q2 J" z) J8 Y20 output z_o;: p8 Z+ }4 @3 {0 N. c2 O( K
21 6 G2 f& R6 \2 X: e, D( J4 [& }# R" S
22 parameter IDLE = 2'b00;
6 ~# p. T9 K& `/ R" R2 X6 m8 W
23 parameter S0   = 2'b01;
" L" N4 p( s/ {( V7 s* d% ^) O
24 parameter S1   = 2'b10;. ~6 z2 Q6 A% q! n0 z
25
) j. `4 z& a$ H+ p26 reg [1:0] curr_state;/ n. q5 O  ^" p! w/ S0 i. z
27 reg [1:0] next_state;
5 S- o8 m0 B) A+ G" {5 [28 reg z_o;+ ~- ?/ n, {$ L( l+ G8 @
29 * d2 e) ?* c7 x: b. h5 h0 ?2 Z. {
30 // state reg
1 d8 r) I+ c% R& e$ G% D
31 always@(posedge clk or negedge rst_n)
) U8 Z+ l; M1 S9 Q/ \! S. H32   if (~rst_n) curr_state <= IDLE;) v; {* ?0 }$ A: ^- [
33   else        curr_state <= next_state;
" G7 l# m* V" V  p+ D& ~  O0 ]34     1 E9 }3 _$ l  _  ~- D- h- ~
35 // next state logic    : K6 y2 D! b2 k1 S
36 always@(*)
* N" `5 k8 |' w& J; F7 g) q/ n7 J37   case (curr_state)8 C8 O: Z0 e% N: C  P
38     IDLE    : if (w_i) next_state = S0;/ F, g3 s6 g" i. W2 w7 o
39               else     next_state = IDLE;
1 y* j+ K- ]2 w/ Z$ B( n* ^# {40     S0      : if (w_i) next_state = S1;
; |. S$ K0 R5 ?8 B* G  N41               else     next_state = IDLE;0 {& O1 [8 Q- H, B
42     S1      : if (w_i) next_state = S1;9 j" V8 {3 l4 c6 Z( t5 K; X
43               else     next_state = IDLE;" Y# C% S  K6 Q( m9 r% K
44     default :          next_state = IDLE;6 l5 z. p. ~2 Z  D, M2 c/ b
45   endcase   
( s) U6 Z! u! d0 r* _46
1 K) k" \* M1 m# r47 // output logic. f: E. X" i4 |% U7 m7 m
48 always@(posedge clk or negedge rst_n)& q8 u5 n8 Z8 I, n
49   if (~rst_n) z_o <= 1'b0;
/ X3 h8 \6 ]4 v; |5 U  Q
50   else
3 L1 \! J: S1 C( ]; I8 I6 u4 }51     case (next_state)
0 p' f( f. p, r! O/ ^# j52       IDLE    : z_o <= 1'b0;
3 B+ c8 X- V, a* M9 d
53       S0      : z_o <= 1'b0;
$ C$ s1 |; t- i/ V
54       S1      : z_o <= 1'b1;: B' ?+ u* F0 b
55       default : z_o <= 1'b0;
6 ^# H5 F" M8 B+ }" ^
56     endcase
1 U& ^  L6 Q/ o57   
$ J( }* E: L) H2 e, a( ^. `" c58 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
+ S9 e8 O$ d4 S% o

0 v8 b: y# _9 q' r

47行

[url=]http://common.cnblogs.com/images/copycode.gif[/url]/ V; q! P( s. E5 l  P
// output logic( A9 O. f) ^! b+ h% m7 Q2 H
always@(posedge clk or negedge rst_n)
9 S% P3 L) j) _' X  if (~rst_n) z_o <= 1'b0;3 H1 ?( S9 ?' Q# o- l# j% q+ s
  else
" y3 S# C: i' F    case (next_state)
4 k2 g* Q1 t* M7 Z! F. r( p% S      IDLE    : z_o <= 1'b0;9 P' Z9 k( w' _/ {# ]. E* u
      S0      : z_o <= 1'b0;# y; V6 a% s/ Y, Y
      S1      : z_o <= 1'b1;! a8 @6 B% ]! a; z
      default : z_o <= 1'b0;3 T; t- X9 B! M" j
    endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
1 A9 }0 N+ x4 j! J+ d- M3 L
1 W6 z" U7 r: T: x+ Z$ u/ J

使用1個always去描述output logic,重點是,使用next_state去判斷,因此可以提早一個clk,這樣無論是在Simulator或者經過Synthesizer合成後的結果都會一樣,而且既可在output敲過D flip-flop,也不會多delay一個clk。

不過這種寫法也不是沒有缺點,由於next_state本身是一個純粹的組合邏輯,拿來當output logic的判斷,timing會稍微差一點,很可能critical path就出現在這裡,前一個例子的output logic用的是curr_state,是一個D flip-flop,沒有組合邏輯,所以timing比較好。

另外一個缺點是output logic必須判斷next_state,很容易出錯,觀念必須非常清楚。


" d2 w: S: z. p& v: z1 x4 p2 z# t
 楼主| 发表于 2013-9-7 09:26 | 显示全部楼层
原文在这里: i5 f/ Z9 ^- r; A; d; ~+ z) z
http://www.cnblogs.com/oomusou/a ... m_coding_style.html
回复

使用道具 举报

发表于 2013-9-7 09:42 | 显示全部楼层
是不是就是我们常用的有限状态机而已。2 j6 }9 Q2 ^0 \
有“状态”“输入”“输出”这几个要素?
7 v+ F! ^  D. x! O; H什么是一段二段三段啊?
  H- f& d* o- N  o虽然我本身也是说粤语的,但是这些香港(台湾)的表达方式真的不大适应。
回复

使用道具 举报

发表于 2013-9-7 10:39 | 显示全部楼层
其实就是根据信号做任务
- B9 s* K- ^( x话说很少见讨论Verilog的帖子
回复

使用道具 举报

 楼主| 发表于 2013-9-7 16:13 | 显示全部楼层
跟粤语没关系的的确是为一段二段三段状态机。# g  p. B; B6 P% n4 [" {6 q, R1 J, `0 C
也就是说一段由一个always 构成 二段就是两上always 三个就是3个always 哦。8 Q6 n' Q. U' l  @# p5 B* M  n
一个问题把它拆分越细综合越好,一般由二段和三段为多也有更多的,这个要看需要了。
9 {/ T0 k0 H& }: k但CPLD和FPGA由综合器综合后三个不同的段是完全不同的结果时序和毛刺是否能达标,以后修改和移植是否容易等等都有好大的关系的。
回复

使用道具 举报

 楼主| 发表于 2013-9-7 16:17 | 显示全部楼层
之前帮人开发的第一代产品中用一段式维护好难老是有一些小问题,可以用但用起来不爽。
5 B3 ]% C3 I# t3 S, p现在要改一下编法最起码从思维上改变一下。
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2026-2-25 15:07 , Processed in 0.047054 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表