之前一直烦脑我写的代码好难维护,在网上看多了发现人家说三段状态机多么多么的好,我就马上去查什么是三段式状态机。发现我之前写的全是一段式代码,怪不得我老是没办法提高自己的水平。
! P0 R5 ~1 F) X' N: v所以我在网上找到一些特别有用的二段和三段式写法不但是给自己看的也是为提高自己的技术的各位看的。
2 W1 l. |8 j& x Y5 B6 T! d* x' b; M; {, b( B5 Z
6 O B' s h0 J9 zAbstract3 N; |2 e0 g# S0 A- b2 C
FSM在數位電路中非常重要,藉由FSM,可以讓數位電路也能循序地執行起演算法。本文將詳細討論各種FSM coding style的優缺點,並歸納出推薦的coding style。 Introduction* N# {$ R9 d) I4 O* V
使用環境: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]6 P# o2 k% Z. k+ f3 x& U/ Q! D
1 /*
+ ]' j$ w& d7 w: R" \) E* M& p 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
, g* }3 f! e* Q2 W 3 $ K( x$ x; Q' R* g
4 Filename : simple_fsm_moore_3_always_best.v* J6 C8 c$ ]( @/ j6 {
5 Synthesizer : Quartus II 8.1
' S, F+ @1 g9 l: Q2 c% o, s! g 6 Description : 3 always block for moore fsm (BEST)
2 P' q5 e- [ g% J% }, d 7 Release : Jun.05,2011 1.0
/ x/ _ s+ d$ `: {8 t" ^; Z+ g' C 8 */) h) _! d g1 G; N8 ~1 \1 ?, e
9 # b/ B( a1 _( k1 Q; V
10 module simple_fsm (3 i& k" U( }1 W+ k
11 clk,
$ v d- j" Q* ?1 o! X) f! f( z9 G12 rst_n,
: `: O" D* o h; }13 w_i,
; A4 O: N2 n" ~. m0 F' R14 z_o) H3 z# Z; B; Q) w+ t
15 );# u! n- ` b# Y4 l
16 7 J B; V. j2 c# w2 Q/ @
17 input clk;
; b# b* t$ R+ a0 C ]4 T8 `18 input rst_n;
+ W/ d: Y/ B, [" V0 {, x19 input w_i;+ e4 l8 S2 Y. E9 a
20 output z_o;! W" x/ l9 _$ {/ Z
21 ! Q' @+ N% h! n2 E. r
22 parameter IDLE = 2'b00;
1 D+ E5 H" h- ] `9 Q6 [23 parameter S0 = 2'b01;2 a8 G% @( ~/ h' `$ l7 O$ z
24 parameter S1 = 2'b10;
. {& t* [+ M2 _5 r3 O2 E25
5 {6 M# h; N! n26 reg [1:0] curr_state;3 h- X& c, X) L- a- n4 G3 S, K* \3 z
27 reg [1:0] next_state;
! G; f. k3 R: z; C* n28 reg z_o;
3 U& e, u9 L! E2 _9 Z; b29 " P9 R2 w6 d) I# p" d$ a: f
30 // state reg
1 u2 c$ L* b9 P31 always@(posedge clk or negedge rst_n)
; E6 O! x; B: F32 if (~rst_n) curr_state <= IDLE;
3 D8 V" C. n/ `! @3 N33 else curr_state <= next_state;
5 P! `5 m, d) v$ U/ h( ^34
" U7 |1 [7 n/ T( A6 c4 p35 // next state logic
- a# ?# x4 v' T7 o0 f. Y, l1 i, K36 always@(*)
5 `, Y3 c( N; ^7 j( m8 s37 case (curr_state)+ ], C |& N9 L# z% m
38 IDLE : if (w_i) next_state = S0;
9 J, ~( i! T W( P" U8 x39 else next_state = IDLE;
% m( ^" S' F) e5 v; Z5 I40 S0 : if (w_i) next_state = S1;, R9 H. Q" a& N, C
41 else next_state = IDLE;
9 L) S3 b) i0 G- I% u" _, w8 Y42 S1 : if (w_i) next_state = S1;, f* K/ b" h9 j" Q& H( F- O
43 else next_state = IDLE;
7 ~( J! @+ C5 [3 B# ` e* ?$ E44 default : next_state = IDLE;
) ^3 F9 N- k6 _" c45 endcase ) H$ f A1 {' X% J2 o* q* ?
46
$ I* A$ B; r( \1 m$ \1 d47 // output logic
8 |' I9 _7 O+ { O5 q* W9 }48 always@(*)
6 N, v' I1 x9 k1 L9 w( O49 case (curr_state)$ q( b( O. O& H6 A1 q# V; {
50 IDLE : z_o = 1'b0;
1 f, @# ^) E* C: u( ]+ \ w7 U( e51 S0 : z_o = 1'b0;
! x& ~' s M4 Y& H4 {52 S1 : z_o = 1'b1;
( g7 e" s) F, o* d3 ?53 default : z_o = 1'b0;
7 T0 s; N8 O C1 a3 J54 endcase3 E1 A2 L, o% y# b
55
& m$ o- @+ a9 w4 V56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
& ]7 d1 g( r6 ]9 C7 E
2 r$ n6 _ N0 l7 t' i- n( w35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]6 K, f4 [- H* @& g3 ]! i
// next state logic : Y4 I U1 r, ~8 k/ f
always@(*)
9 x, y7 x0 K8 P6 I z case (curr_state)' ]& D! ?# m X! `+ D. m- r9 _
IDLE : if (w_i) next_state = S0;0 v) p- z+ H" H8 t1 x- p# }
else next_state = IDLE;
+ f0 d6 Z$ k b, |* s& D, M S0 : if (w_i) next_state = S1;
3 P* [( d! j* D* \ Q else next_state = IDLE;0 Z: b! A) N7 V- c) p K+ D% B
S1 : if (w_i) next_state = S1;
* S; |3 E+ a6 E7 B else next_state = IDLE;
]+ | J: h7 Y! ? default : next_state = IDLE;
1 }9 U) C2 e; a A endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
+ o5 Q2 V ?/ l- \: o! W
9 O, ?: y- ?1 d% ~' n5 K9 E使用1個always描述next state logic,因為是純粹組合邏輯,所以使用blocking。 根據Moore FSM架構圖所示,next state logic的結果與input與目前state有關,所以先用case對目前state做一次大分類,然後每個state再根據input做if判斷。 30行 // state reg
. p# K0 I6 U+ U' T: O. J+ R, lalways@(posedge clk or negedge rst_n)
' R, {; ]6 C* p& w+ Q if (~rst_n) curr_state <= IDLE;
9 }8 u: m' L0 p" E2 U: f1 u else curr_state <= next_state;
. S) T% K3 s! t5 t [使用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]
' K1 k( G$ J) V4 l t2 k2 l// output logic3 P6 B8 q. B3 i9 U& L) f6 [
always@(*): i q0 y* r% [' \% H: u, ~5 M% E
case (curr_state)8 @+ l$ D% z8 i
IDLE : z_o = 1'b0;- B$ g; a$ _8 n3 I& P! P. M: l
S0 : z_o = 1'b0;
3 Y9 }* O9 ^9 b; _- p( l% w- t S1 : z_o = 1'b1;6 l- W& M$ Z7 o3 y0 Q
default : z_o = 1'b0;- d: c4 x* a6 w2 q9 T9 t3 X
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]5 ?# y+ W: z' R8 P$ B/ v
1 w( C2 _$ P/ z4 _7 K& i! E2 P
使用1個always描述output logic,因為是純粹組合邏輯,所以使用blocking。 根據Moore FSM架構圖所示,output logic的結果只與目前state有關,所以只需用case對state做一次分類即可。 使用3個always寫法有幾個優點: 1.可忠實地反映出原本的Moore FSM硬體架構 P' I1 h6 y/ C
2.可輕易地將state diagram改用Verilog表示
8 m" _( z% k1 {2 d3.將Next state logic與output logic分開,可降低code的複雜度,便於日後維護
) r# v( R( b4 O) J) n' r2 W2 n3個always是一個推薦的寫法。 Testbench simple_fsm_tb.v / Verilog [url=]http://common.cnblogs.com/images/copycode.gif[/url]
7 v7 }+ W# V T% q1 /*
* o# E; A5 d1 u% n; L/ V5 O2 (C) OOMusou 2011 http://oomusou.cnblogs.com
9 d2 p0 e# J* g3 ) p; ^& v. f, o" Q
4 Filename : simple_fsm_tb.v
, w& s- K7 h- v5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9
0 O- u$ A+ E! f4 i6 G- N. [. F6 Description : testbench for FSM# t* F+ n0 y& z5 G5 h; r; a0 Q
7 Release : Jun.05,2011 1.0$ c' \5 u' b+ g* ?) P9 u# o
8 */0 c, x0 y7 g2 K' P7 F& N) M& q
9
5 A! Q( ^ u. I10 module simple_fsm_tb;7 U" ]) t0 G8 W# m( k4 a% T3 g
11
% x+ I* d9 R& P1 w5 @12 reg clk = 1'b1;" w r# ?, C* L; t& @
13 reg rst_n = 1'b1;1 C+ y& w1 x( g$ R
14 reg w_i = 1'b0;- Y9 F5 w( F0 {, s2 `
15 wire z_o;* ^; ?5 ?3 e" v3 L& l# S \0 |9 K* U
16
& H: ~; q2 X/ [+ r1 V" A5 U17 // clk# |! }0 Y0 b, r, H
18 always #10 clk = ~clk;, ]7 }# g5 p1 X
19
8 p) P" _6 T) U9 D- f$ U0 i20 event after_rst;
* a0 K# @3 z, R0 Z s6 H21
! M) p; p ] O: K- J; Q, g22 // rst_n
9 q2 ?- q: ^9 W% |23 initial begin
7 _* [, D& E0 e, u: |# b0 i, D9 S24 #6; // 6ns
2 J6 m; d G, {+ {* O/ q* l25 rst_n = 1'b0;
+ N, L; L* ^) I; a M8 ?; L26 #30; // 36ns' v H) b5 ~+ u, c
27 rst_n = 1'b1;2 R! i- G4 ~7 o$ {6 d' R" @/ Q+ k
28 ->after_rst;
+ e: z" A( h* R+ A& W5 ~& h; i" z29 end ?: i6 D/ @+ L! d. q( m* B1 ^
30
6 c: n7 E5 K0 o& K31 // w_i5 l6 O2 V4 F, m
32 initial begin, m3 ^# s4 d: }! v+ D
33 @(after_rst);
8 x6 J; u+ d8 K3 l6 s34 repeat(2)@(posedge clk); // 60ns# X4 [/ `' H" I( F; T- O
35 w_i <= 1'b1;
5 Q2 B( M1 {5 u. j6 [, k36 @(posedge clk); // 80 ns
! J+ ?: p7 X0 q" D2 R37 w_i <= 1'b0;
/ q+ x* b) }# b. O8 [38 @(posedge clk); // 100 ns( G/ ~6 S, ~3 m: l6 J* p
39 w_i <= 1'b1;6 |" S/ M5 ]4 X9 h7 m
40 repeat(2)@(posedge clk); // 140 ns
3 e3 R' _) E4 Q+ ^; y7 [41 w_i <= 1'b0;
( \" k& c, d6 ^6 J6 z, ~42 @(posedge clk); // 160 ns
0 M' I" X |7 i5 Q43 w_i <= 1'b1;
& `4 V& A, \7 Z44 repeat(3)@(posedge clk); // 220 ns
( H+ ~! R/ [4 K- J+ V2 l45 w_i <= 1'b0;/ i: o! j: {' S& }& D a
46 end
( z- a2 `0 a) o! O" O47
) W+ k1 e0 @2 l0 ~48 initial begin
! F* V" l6 ]3 [4 u* j- |49 $fsdbDumpfile("simple_fsm.fsdb");$ z- [. z, e* g* M" X# @8 \6 H, w
50 $fsdbDumpvars(0, simple_fsm_tb);
; M; V* a7 t2 u7 [ i51 end7 a( h8 I+ \& I% L) e
52 $ v6 O, d; O4 A% {" \
53 simple_fsm u_simple_fsm (
8 U8 }* y8 F l5 o54 .clk (clk),. b$ i! j S. h
55 .rst_n (rst_n),
2 H! }% W/ U' \, N/ C. ~: v56 .w_i (w_i),
9 i S- m* J! B57 .z_o (z_o)
( r7 C4 [. e* n2 _7 \2 n: `+ C8 t58 );
4 P* o: L: Q. {/ d# D59
/ H2 }8 m( j+ y) D: l) d60 endmodule
0 z$ W4 j: N$ ~) c6 L/ g[url=]http://common.cnblogs.com/images/copycode.gif[/url]8 `. A2 m- I1 n( O
0 v- ^" i' e& u* j* ]' B4 Z
執行結果 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]! ~& b7 Z1 n$ M- \* \; Y9 g
1 /* 5 O+ B# n6 P9 c) V
2 (C) OOMusou 2011 http://oomusou.cnblogs.com8 z8 a/ E" E( x7 h9 \! E
3 5 d" R9 I: r( B* e2 f* b/ ^6 g+ d
4 Filename : simple_fsm_moore_2_always_0_cs_ns_good.v
0 O: b1 I% K0 f5 m* E( l- R 5 Synthesizer : Quartus II 8.17 a# k$ _- h% T$ Y, W$ k
6 Description : 2 always block for moore fsm (GOOD)
6 |0 H" i9 y$ Z9 p4 T$ J4 x 7 Release : Jun.05,2011 1.02 X, l: E, G; z% Z* C
8 */
. T+ l6 \# V9 j1 @$ P 9 ; _4 y z2 A2 ~% R0 ~
10 module simple_fsm (
- n$ X- P( k% m! q" Y' q11 clk,
! y$ W% H l! w3 E) S12 rst_n,! @+ C6 X& x' w* Q' c0 i
13 w_i,
7 C1 J, ?3 [( ?8 K/ Z; s! f14 z_o
. q$ M# _7 _& Y/ x* ?15 );8 P# T2 V* C4 t5 ]3 H2 H0 P' z
16 / X- K9 L# L* @( K& J' T7 X
17 input clk;
7 p! h% n# V* Y7 x9 {* }/ u J18 input rst_n;
/ Z1 D: k% J: m) [- ]: e19 input w_i;1 p1 t8 p1 t" V' j/ S1 k9 Q
20 output z_o;4 h) D) \9 I Q2 M6 W
21
( s# F0 B" F8 R- U22 parameter IDLE = 2'b00;
- u1 o+ x* }; k8 k+ m; o23 parameter S0 = 2'b01;
$ A' ~3 \8 W4 F: ^/ `24 parameter S1 = 2'b10;
% Y2 M- h9 p0 s/ p1 U25 # P; Y, j$ I9 y2 F/ S; R5 a% i( m
26 reg [1:0] curr_state;- c* W5 A# b$ T
27 reg z_o;
+ E& i. u) M% R3 l; C6 p6 V28
1 l& J% R& G' A& p: Z3 m% }29 // state reg + next state logic! N, j/ F" c% w) v. C! F
30 always@(posedge clk or negedge rst_n)
* _6 i$ Q" a6 B- |31 if (~rst_n) curr_state <= IDLE;( L% W. w8 Y2 F# M/ }' f5 U. b) D
32 else
* q# i0 J$ |+ G+ e1 @5 \% Z33 case (curr_state)
, z4 j1 ~6 f# A8 ?34 IDLE : if (w_i) curr_state <= S0;9 z3 }+ l; x' b: w! _7 B
35 else curr_state <= IDLE;2 U0 H9 s$ R( k! P8 @$ F( i7 }# }
36 S0 : if (w_i) curr_state <= S1;# U3 _% K# q& q& G9 V+ B
37 else curr_state <= IDLE;
5 Z* ]# g* N* q2 J" X# A* G* w38 S1 : if (w_i) curr_state <= S1;0 n" n4 [: ]) C
39 else curr_state <= IDLE;* j% l7 f, P9 d* g4 f' W
40 default : curr_state <= IDLE; a, M! }- N1 }
41 endcase/ ]) H! G/ f8 l# l1 h5 i4 ?
42 9 K7 W& Z! H$ f' R1 E
43 // output logic% m: ~; ?- r6 A
44 always@(*)
* o# Q6 U1 n( d- W! T2 f45 case (curr_state)
% z6 Z/ {" {- E2 n7 V1 t `46 IDLE : z_o = 1'b0;
9 s& m1 [( d( N; ]5 Q' n* B& a47 S0 : z_o = 1'b0;
" E/ ^+ B/ m0 ^( e v8 p% Y, M48 S1 : z_o = 1'b1;
$ {3 |& a+ e9 _! ?49 default : z_o = 1'b0;
% ] k5 g2 J6 Y* ~' y50 endcase. s4 }% h; y% G8 D- t
51 % L" ^* h2 W% R0 l$ h
52 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
2 f# M' @- z1 V) t1 q1 n+ k) w3 L9 W; D- N5 |' r7 N3 \( S
29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
7 Z7 y) ^6 r8 \1 e8 J// state reg + next state logic; m+ |5 v/ H& @5 |" H
always@(posedge clk or negedge rst_n)- q: V8 c o2 Y; R1 c# y( g
if (~rst_n) curr_state <= IDLE;
0 ^, U4 {$ z3 A% [ n- e3 v8 @5 Y else
# A# o: e- \' l6 f' l' g case (curr_state)
5 H; m H; e0 E8 N IDLE : if (w_i) curr_state <= S0;) `$ \- A1 y/ s& q
else curr_state <= IDLE;
' n2 c, m% H0 h0 l S0 : if (w_i) curr_state <= S1;
- H) y) e | S2 e' l/ ` else curr_state <= IDLE;, f2 L( }3 h9 x E. x
S1 : if (w_i) curr_state <= S1;7 {' R' J0 d2 S6 Y9 M( E3 K
else curr_state <= IDLE;
) M" }& Y6 k% x* O% c2 q7 d* v7 _ default : curr_state <= IDLE;
- C# |. \7 `0 P3 C0 @, P& }+ c endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url], B4 k8 e3 E- |' H( I
) Y0 l* a2 p: O6 b4 v
將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]
4 ~0 j5 p; D/ h. P8 q7 U// output logic
9 n5 e2 {. b( C, `always@(*)" G, o7 t1 k; F9 V7 x
case (curr_state)* e$ s) `" }2 C7 G" e
IDLE : z_o = 1'b0;3 y; Y B) N" @+ o, ?: h5 R) |
S0 : z_o = 1'b0;9 C9 N5 U! V, v. t& g& S0 u7 R1 [
S1 : z_o = 1'b1;
+ _) z4 l% j2 [. c2 F default : z_o = 1'b0;6 u5 J/ d; L4 \; C `8 W
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]/ F/ ^4 G7 B7 N) z
6 e) |+ a' K& n4 c5 r, I使用1個always描述output logic,因為是純粹組合邏輯,所以使用blocking。 根據Moore FSM架構圖所示,output logic的結果只與目前state有關,所以只需用case對state做一次分類即可。 使用2個always (state register與next state logic合一)寫法有幾個優點: 1.程式碼較3個always寫法精簡
; L& e$ X& v4 Y2.可輕易地將state diagram改用Verilog表示$ [/ D7 ^1 u5 P: h/ V" u* c
3.因為state register原本程式碼就不多,將next state logic與state register合一後,next state logic仍與output logic分開,因此不會增加code的複雜度,便於日後維護
4 Q7 t* I/ T, t5 s# g1 j6 u/ a2 ^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]
! J0 l0 Z6 r% K9 ^! Q 1 /*
' b, q" R+ n; t% ?7 C8 |0 v; G& I3 k 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
' | t1 m! F9 \8 h6 Z 3
& l7 n8 h* ?9 R; x8 s 4 Filename : simple_fsm_moore_2_always_1_cs_ol_ng.v% j, b0 @) v4 ], |
5 Synthesizer : Quartus II 8.15 i! s+ _6 R; H( v s
6 Description : 2 always block for moore fsm (NO GOOD)( w: o/ |2 D( m
7 Release : Jun.05,2011 1.0
9 r. o/ L# J+ t, v1 X% }* U 8 */
' e6 d N8 `9 E1 s+ H" T" _ 9 5 t" N! C; ~% G
10 module simple_fsm (
" s' g% l8 H7 @- I3 }11 clk,3 S3 D0 T% K/ U! ~# i8 @5 n
12 rst_n,9 n S2 D1 S( Q3 y
13 w_i,& O F% M: `# o( g$ [5 ]
14 z_o
7 |: A2 k: u; K( e6 e( | h15 );$ p+ b, V' k0 j [$ y1 `
16 $ ]# R% A1 R& [& [- h: k' X
17 input clk;
) e; `4 [+ f. @* ?18 input rst_n;% F8 }7 ?/ C# v, h
19 input w_i;
. u6 `- o4 k* S: g) E- \- M+ R20 output z_o;4 k8 p. Y& E& ~. b6 m
21 ~) x' \: T- o& W# Y2 G; D
22 parameter IDLE = 2'b00;/ l1 r% } y9 V* j9 T
23 parameter S0 = 2'b01;
6 w2 ?, t8 B' ~24 parameter S1 = 2'b10;
$ A& Z$ Q: _8 E25 3 \( s3 K( e9 r! l# d
26 reg [1:0] curr_state;
" ]5 |9 o3 t* t1 a3 G27 reg [1:0] next_state;
6 G5 T) D! r) b1 U) ]28 reg z_o;
; Z/ w v) b0 Y K0 `. \+ M29
3 m @9 B; T7 D! T4 `3 |0 Y \% i30 // state reg + output logic! ]/ H/ n5 `- ~: s, Q' A
31 always@(posedge clk or negedge rst_n). r3 U7 @: a0 O9 }
32 if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
" [6 _( P- x+ c% a33 else begin4 y' Z) T/ ?7 H4 S- G# A2 Z; } t6 z
34 curr_state <= next_state;, L7 } u% t0 e; T
35 8 j1 {4 _2 ^ }6 G+ U( `
36 case (next_state)( x& o8 P v6 ]7 N* L+ P3 M& M8 y
37 IDLE : z_o <= 1'b0;
5 ]& l5 U. Q" y38 S0 : z_o <= 1'b0;+ L# ?( w; _/ F+ S4 p# `
39 S1 : z_o <= 1'b1;
6 ]) c* q8 J6 D) T( W) l40 default : z_o <= 1'b0;
) q4 g" `2 @, y41 endcase
* g: l. D$ s. d: P9 G5 Y- Y42 end
- }6 F* [/ T! _( a* ?. {43
3 ~* K# U. M# K% S44 // next state logic
' B" b3 A+ p3 S U8 I) k45 always@(*)
3 P F y5 |& i+ d7 \- W s i' ]46 case (curr_state)
- K. s! P5 p& F$ a, p+ o47 IDLE : if (w_i) next_state = S0;
`, M* b. l J! W5 ~; ^/ F y48 else next_state = IDLE;' M5 O, Q9 r" c [, D: N
49 S0 : if (w_i) next_state = S1;
9 I: D2 \ D! F" u; e; X8 [$ }& `50 else next_state = IDLE;
* g- ?5 x- E( R3 J6 ~0 k51 S1 : if (w_i) next_state = S1;
% [% V& ?: g- }, I9 y1 ~; ]1 X52 else next_state = IDLE;
( b3 V3 Y% c" T. d: E) Y53 default : next_state = IDLE;
" O1 f9 O8 v' S" [" }54 endcase
/ G, [* n% @: {+ J1 Q% k; x+ N55
! G- L: l4 g$ c+ A! O4 L8 \ M56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
* c0 k8 _4 Y7 s) ~) k- L8 D( t+ [& L3 ?! T
30行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
# ?0 A/ b9 V! `- a4 _! s/ w// state reg + output logic* n* U# z4 y9 K: x7 [0 I' T* W
always@(posedge clk or negedge rst_n)! A( {, A1 z9 G3 r" Z% s/ H. I c
if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
' z* w9 ]: N, J/ M" K. Y else begin" r# m0 x- m5 a O4 h
curr_state <= next_state;
' c: e v- Y; y4 c- O' y2 j1 ?
. b7 P7 i5 @! y; j case (next_state)+ P P S3 Z0 y9 D/ d$ ^" W
IDLE : z_o <= 1'b0;2 a. u2 U( I$ o1 |* }3 O
S0 : z_o <= 1'b0;9 E1 h6 A. f! ~* A8 z8 N2 t) W
S1 : z_o <= 1'b1;- E- z3 s5 y! d; p5 ]! }
default : z_o <= 1'b0;
8 f, ^/ E- m+ a. H! W endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
1 n( J' e$ M8 d' V2 Q' |1 b3 e4 O+ o. u! q/ C" y
將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]% j- w" W; u. P7 A$ G% d3 }
// next state logic / j8 V1 D7 C6 M( C7 l
always@(*)
q, ^9 e- z$ K* F case (curr_state)" G* y8 D2 K5 W1 |) Z
IDLE : if (w_i) next_state = S0;
0 x2 K2 r8 `4 k else next_state = IDLE;. o8 Q9 {- t# H8 H. P: R9 G
S0 : if (w_i) next_state = S1;0 g, U9 h7 p+ F* | X0 M. @2 R* O O6 e" U
else next_state = IDLE;
" Y. Y4 s9 x2 Q. u7 E S1 : if (w_i) next_state = S1;
2 s9 F( _$ L6 y. O5 S' w else next_state = IDLE;
& Y: s. x9 n7 |! }9 ? default : next_state = IDLE;* v2 H+ n. p+ `- E
endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
d+ U% G, v/ F( \% ]9 B6 k; Y6 e% g6 K; u6 A
使用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判斷,由於寫法不直覺,一不小心很容易弄錯! }' f# v; q8 M O, C
不推薦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]
' ?7 [ c _; a7 d3 }: o9 V. }2 [ 1 /* / D, I( ]6 @1 a
2 (C) OOMusou 2011 http://oomusou.cnblogs.com3 I/ ~1 \) G$ {
3 3 n& H3 r9 F0 c3 m2 ^8 V; ^
4 Filename : simple_fsm_moore_2_always_2_ns_ol_ng.v
8 y8 E& N7 Z; s/ ]( ?# L% k 5 Synthesizer : Quartus II 8.10 K" G6 J- t2 c) N! m
6 Description : 2 always block for moore fsm (NO GOOD)7 Z0 K) B `* l" Z
7 Release : Jun.05,2011 1.0
6 T8 F' R9 ]; J3 L8 g, Q/ S 8 */' s3 C8 U1 Q3 E
9
1 t: \( t" R' u( [: f3 t4 U6 H2 @ |10 module simple_fsm (
6 K, ~2 Z( V0 B% l' J% B11 clk,
" r' A! o `, d) \12 rst_n,& |0 Q$ N2 T$ L1 [6 Z5 J2 J S
13 w_i,
) M; O- C, l4 s6 R+ W D+ Y2 `14 z_o8 V: B& {/ r" _1 s2 Y9 X7 J
15 );
+ v. K2 i/ M2 N1 L, o c16 8 r( ~; ]6 x- i1 N+ u% T
17 input clk;& u" b9 k. L/ c m, ?' {
18 input rst_n;9 X e/ E n* J
19 input w_i;! J) y# o! o( e7 N3 O1 k
20 output z_o;, i8 U2 k8 V6 t6 T" u$ O+ K" ~3 p
21
& f# R; G: _, j* C+ f9 u2 J8 y22 parameter IDLE = 2'b00;, ?+ ?7 k6 a2 G& Q+ N( k: _
23 parameter S0 = 2'b01; {6 ` D6 j5 N* T
24 parameter S1 = 2'b10;% Y4 h, C/ q' I. F+ y1 f
25
8 C+ X* `! O/ v5 x8 N9 [26 reg [1:0] curr_state;( N- z0 i' E# c. T o
27 reg [1:0] next_state;
& @7 f# `5 b" T3 n28 reg z_o;
7 _; k8 `! S/ A8 Y* R- Y6 N s5 \0 |29
: H: k/ S) c$ P0 I- Y3 v5 Y30 // state reg/ a+ C. e# L- q3 `. u+ {
31 always@(posedge clk or negedge rst_n)
0 t, ^9 u# l% o) Y; B; L32 if (~rst_n) curr_state <= IDLE;5 l* Q; x7 \+ ?3 f- A- Q W
33 else curr_state <= next_state;
m# T7 k! J1 ?& x i, w7 _# X, U34
/ z% s/ w/ F2 K8 T9 l z35 // next state logic + output logic / Z% s, S, `. S* p9 W) z$ b; G% T. M
36 always@(*)4 p0 u" g. y5 f9 P6 r) u: v
37 case (curr_state)
, [* g4 g% J* \1 R0 ^1 O* q38 IDLE : if (w_i) {next_state, z_o} = {S0 , 1'b0};
. C1 ], j( i$ o; K39 else {next_state, z_o} = {IDLE, 1'b0};
2 p, M& T2 [0 o, Z/ B! \40 S0 : if (w_i) {next_state, z_o} = {S1 , 1'b0};) s k# l' r6 S4 D ~% K; L- N
41 else {next_state, z_o} = {IDLE, 1'b0};
7 Z4 g9 X! h s" m+ S2 _42 S1 : if (w_i) {next_state, z_o} = {S1 , 1'b1}; // always output 1'b1
& v8 m+ R2 [5 a. t43 else {next_state, z_o} = {IDLE, 1'b1}; // always output 1'b1
3 k! Z$ T2 R" i1 P3 V44 default : {next_state, z_o} = {IDLE, 1'b0};
* z: U4 F% k3 x" t45 endcase
7 J( W1 m- H: A# O( O: J; w1 ]46 ! p% P' \: d1 U* A- _
47 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
' m( T8 h4 }) e. E- m( l" Z
, {0 C# W$ X' j- l9 T7 S, a30行 // state reg
! m/ p& w) a2 m' w; m7 Falways@(posedge clk or negedge rst_n): O. N3 G# j. W! w3 s1 X
if (~rst_n) curr_state <= IDLE;( `6 z4 W' b j, A! h8 }0 u
else curr_state <= next_state;$ `+ S" g1 ]+ F5 |2 ^4 }# C
使用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]3 [, g, Q7 f7 P6 W
// next state logic + output logic
! u9 g! p4 U8 x; D0 |4 n0 S$ Oalways@(*)2 d% m# s* f* [, V% f4 R1 E
case (curr_state)4 C' e) U4 f B: ~) h$ g
IDLE : if (w_i) {next_state, z_o} = {S0 , 1'b0};
6 z( q, E* ~$ M* K" n else {next_state, z_o} = {IDLE, 1'b0};3 o. r6 y4 x. D5 }- d: r
S0 : if (w_i) {next_state, z_o} = {S1 , 1'b0};! E2 F' s' T- F8 S
else {next_state, z_o} = {IDLE, 1'b0};+ @( H8 f: e5 r
S1 : if (w_i) {next_state, z_o} = {S1 , 1'b1}; // always output 1'b1
w6 N) i$ m9 ^5 b s0 a else {next_state, z_o} = {IDLE, 1'b1}; // always output 1'b1
4 l0 s0 y: O r _7 ^ default : {next_state, z_o} = {IDLE, 1'b0};
+ o# K( Y3 [- O0 z- l endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]& F7 ]7 {. T. V1 ~: z0 y
0 h: t" K) r5 Z: a t }- S& k; H
將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的複雜度,日後維護會更加困難% ~5 B! `% Z; O) ?% Y& T; s' O. e
2.很類似Mealy FSM寫法,容易讓人誤以為是Mealy FSM" [# ] L0 t1 a+ ]( l
不推薦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]
! J9 A) `) L- Q8 x$ O 1 /* 3 S8 X8 }: _) g V. J) d8 c
2 (C) OOMusou 2011 http://oomusou.cnblogs.com$ Q2 p1 D4 a/ y" p( f" J
3
$ ~& \, c i+ l% v$ q* `) _ 4 Filename : simple_fsm_moore_1_always_ng.v! k# f, i& Q F: j' S
5 Synthesizer : Quartus II 8.16 l7 t" f( z s
6 Description : 1 always block for moore fsm (NO GOOD)
" L2 [2 D) U- l$ N& |1 u+ O, b 7 Release : Jun.05,2011 1.0
, V1 s: ^3 [6 x* |- }* C* @ 8 */* ]7 b7 k* ^+ u* g
9
# ]7 f+ `8 D. c, s, L6 M10 module simple_fsm (
* d0 d" U! a0 \& ~11 clk,9 O; N3 I9 W1 [4 { m
12 rst_n,1 G0 w I4 M Q, \
13 w_i,6 l% M1 Y5 |, ~4 B4 r: w
14 z_o$ A; t/ U" \$ A! c- E) Y
15 );
' Y$ L6 U4 X- g( L( p16
( E; ?1 ~! o. e* h17 input clk;
3 J" ~5 d; \- v18 input rst_n;
, p5 l, \7 r. m+ R! e/ |1 m& a19 input w_i;" |/ e' c0 p* s8 {9 c& Y
20 output z_o;
& [3 W" h. x c& o; y% V% S* y21
8 B" `% d" K. |/ H0 |22 parameter IDLE = 2'b00;
) r# z- L5 w& d) N/ k23 parameter S0 = 2'b01;
8 t: i2 ]; i2 B; I. M/ `& m' w6 F24 parameter S1 = 2'b10;* I) P, @+ {5 J
25 1 {- d- V, y# m$ M
26 reg [1:0] curr_state;; N& O" v, U: S
27 reg z_o;
4 |& I3 I9 r0 x( e, i- V* I3 S28 1 R* O- Y( O& a& R" t0 S6 T
29 always@(posedge clk or negedge rst_n)2 _+ G. @% A ^: e& K& F& F2 Z
30 if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
5 n& J5 ]( R+ \) F31 else
4 ~! |" t/ g3 i; {9 N' t1 e! |32 case (curr_state)
; B* H$ v8 N X. o33 IDLE : if (w_i) {curr_state, z_o} <= {S0, 1'b0};
$ u+ @1 \3 c$ }" B& [2 H4 e3 ?3 U34 else {curr_state, z_o} <= {IDLE, 1'b0};
4 b9 t7 O: z' o" u! ~; G35 S0 : if (w_i) {curr_state, z_o} <= {S1, 1'b1}; //?
6 s1 O+ l- o$ b% y3 \8 g& p1 x36 else {curr_state, z_o} <= {IDLE, 1'b0};
" t# O# E, k) ^37 S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};/ o/ c! c8 F5 A: j0 j. c4 z& @$ o
38 else {curr_state, z_o} <= {IDLE, 1'b0}; //?& Y k0 _: Q+ O7 `# Y6 |
39 default : {curr_state, z_o} <= {IDLE, 1'b0};; |# w* v* i1 ~
40 endcase
! q; C, I: V0 j" Z9 D( D41
3 D( X" N. S- B8 D42 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
3 o9 z: q7 D! v
3 T8 u6 E; V; W7 b' g29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
/ G& G+ x. n8 [) ialways@(posedge clk or negedge rst_n)
8 Z/ G$ m- g/ z; K1 D; e- y if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
" u# {+ t& y' B else
! H! K# f# A9 a5 Q8 I case (curr_state)
: t/ ~3 Y. v2 O$ N/ G& O$ g IDLE : if (w_i) {curr_state, z_o} <= {S0, 1'b0};' O( W6 T& ^0 `. a2 q! a8 ^
else {curr_state, z_o} <= {IDLE, 1'b0};
% I7 l7 \5 H) j( H; b$ U& m9 _ S0 : if (w_i) {curr_state, z_o} <= {S1, 1'b1}; //?2 U! _7 A+ \& }+ F+ e( t
else {curr_state, z_o} <= {IDLE, 1'b0};" b1 }9 R8 Q& ^- [. s E
S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};
+ Q; @3 N% p. z" v, F6 Y else {curr_state, z_o} <= {IDLE, 1'b0}; //?
' a5 K7 q3 U, }! B1 K' c5 o2 w/ k default : {curr_state, z_o} <= {IDLE, 1'b0};. t$ Y$ U1 n. A) b
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
, H4 P# L1 Z+ |$ S7 L& O
) [% ^# C2 B+ j3 o+ D2 W! a使用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}; c; h, G- K+ D5 T& r
當目前state為S0且輸入為1'b1時,output必須提前為1,因為這是在nonblocking內!! 37行 S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};
) a3 _8 L0 }" `7 Y. n! w& ^同理,在目前state為S1且輸入為1'b1時,output也必須提前為1,也因為這是在nonblocking內!! 使用1個always寫法的缺點: 1.因為使用nonblocking去描述output logic,所以要提早1個clk判斷,要特別小心處理,一不小心很容易弄錯. _' _3 y5 a6 @, e: `
2.1個always內同時包含next state logic與output logic,會增加code的複雜度,日後維護更加困難3 D$ M2 `8 q1 \6 O- b( u8 f' q
不推薦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]
+ M5 T3 G- M$ I) d 1 /*
5 i# E+ F5 u) y0 x: ^3 I9 U 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
4 H, F" _9 z( K- W6 B \$ _9 s' ^ 3
# n( \ P" ^* Z6 l, t" y% c 4 Filename : simple_fsm_mealy_3_always_best.v8 U( l" @2 ^1 z/ n/ k
5 Synthesizer : Quartus II 8.12 S/ M6 S |6 Z+ k. |
6 Description : 3 always block for mealy fsm (BEST)7 n8 }% F. p8 W
7 Release : Jun.05,2011 1.0
/ T4 e& V+ j9 S. U N 8 */
/ i- Z! g# q( ~ 9 : i, P. C0 B3 C. C% r& P
10 module simple_fsm (
7 C8 K4 ~9 m# J( t5 x9 B- k: S11 clk,
L1 k. Y! V" i. u. l' O12 rst_n,, k! I8 u; T* l2 n+ }3 A, }0 f
13 w_i,
0 u4 v: h9 O+ X# I14 z_o2 Y1 \: B9 n Y/ I" Y
15 );
" Z8 e; X) ]4 u: u. I16
7 l% d q) `$ |" @$ H4 i( p17 input clk;' [5 \" x+ }7 u( c! u
18 input rst_n;
u5 t* k" }- x9 U* b19 input w_i;0 N0 b8 W+ g8 ^* g x
20 output z_o;7 M, p& X$ V6 O9 R8 p
21
# W' R6 F# Z8 e/ Z: U22 parameter IDLE = 2'b00;" T8 ^" w# F" n4 w
23 parameter S0 = 2'b01;
1 @: U$ x7 ] ^# e2 N5 O: }24 1 P' ?) g/ y& N% e9 x
25 reg [1:0] curr_state;" {) C0 ~; B! Z0 j
26 reg [1:0] next_state;4 p. ]& P" l4 U
27 reg z;
7 J+ R: t( i! X! K' ~/ \1 v% K' C28 reg z_o;5 q) O3 o+ {, I) i3 ^
29
6 l+ W L7 |2 j9 h3 z30 // state reg7 |% c/ ?/ p% D
31 always@(posedge clk or negedge rst_n)# G- `7 {+ v' W: H9 s! j, ?
32 if (~rst_n) curr_state <= IDLE;: c S, p! X, w, u0 o' _
33 else curr_state <= next_state;( @: m1 _7 u1 F
34 ( ] m4 a, ?; j$ R5 z
35 // next state logic ; K, q! b h' [+ t
36 always@(*)
4 D% {4 M/ D1 W0 e37 case (curr_state)# w" {1 F0 Q8 h0 q2 O
38 IDLE : if (w_i) next_state = S0;
# ^0 v- T4 @( R- _39 else next_state = IDLE;- }* ^9 \2 I/ n* [9 Y3 J
40 S0 : if (w_i) next_state = S0;
: q! d( S/ j. R' l6 ?; ]41 else next_state = IDLE;
% z7 t. }. R$ k7 \# Q/ z42 default : next_state = IDLE;
+ t* }8 z% x/ x0 M: S7 l43 endcase
" x; X5 r0 I7 ?- G- {! K& o' p44
, C$ t5 D% p: a% S% A1 B% k45 // output logic3 \; k( ?6 l* s- N1 _; K
46 always@(*)
D; o: n3 I* c7 V% q47 case (curr_state)/ Q4 k- F# o T+ c
48 IDLE : if (w_i) z = 1'b0;, y. ^% I0 y5 ]3 [
49 else z = 1'b0;
! v0 `; z3 W2 a9 }50 S0 : if (w_i) z = 1'b1; q2 B8 ^, H& ` A% w9 m. k
51 else z = 1'b0;& ]4 H" r# U3 b% R# Q- }6 S
52 default : z = 1'b0;2 u1 r' j$ e/ U( X
53 endcase
% R+ E4 m" U) O6 \% i, @54
$ |7 w8 s- m B: \+ q, r55 // mealy output to delay 1 clk for moore
G) I( t$ [2 N) T+ v2 _# w56 always@(posedge clk or negedge rst_n)
( E; r8 F0 L& A2 O% G6 K# ^57 if (~rst_n) z_o <= 1'b0;5 P3 k7 k# L) y0 f: d" T, T$ Y
58 else z_o <= z;) f- C2 Z2 X( M8 {% `5 J/ h
59
. n) E( p: `" R/ F/ h60 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
- S; A" N2 o" Q1 K$ y. T/ M7 |
* W q7 p: `" R" J( r' q6 I30行 // state reg
$ f6 e! T) h) balways@(posedge clk or negedge rst_n)
! g+ R( m8 a! P+ A if (~rst_n) curr_state <= IDLE;% k/ D" a0 e5 I0 O) k5 x
else curr_state <= next_state;
* s; o, J8 p2 ~使用1個always描述state register。 35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
6 @) {8 D- ` W) g5 y2 ]// next state logic
# ?2 D- }; b" q7 _$ p& ?$ O. W8 Valways@(*)+ ^2 ]7 s7 c* }: f3 H5 u# K* h
case (curr_state)& S- V- g9 U5 t- c" L" [
IDLE : if (w_i) next_state = S0;4 r# q4 W6 B# a: D* d
else next_state = IDLE;
4 J6 \+ x. w {: z3 |) r# T; l* X* P S0 : if (w_i) next_state = S0;
3 o! C' @* O. y3 X: D, v/ C/ x else next_state = IDLE;
2 L/ {4 {; @; D0 \" E8 q% U default : next_state = IDLE;
) |) L- d5 F( ^$ G4 F* j$ q1 ` endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
1 ]7 r! X/ I/ S, H3 T4 x( x8 c9 y3 v) @$ ^0 }/ z
使用1個always描述next state logic。 45行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
9 d: t: B; \7 `* r5 X// output logic
1 ^9 T4 [+ F, o9 b/ s. T* halways@(*)- k# A# w- E2 ~, p# z* g
case (curr_state)! v5 e& }# ~1 R% i7 d% e; J
IDLE : if (w_i) z = 1'b0;6 r: H. r3 s. w `/ }/ C# E
else z = 1'b0;
9 l+ H; ]3 H! ]% R, b0 b( R# c S0 : if (w_i) z = 1'b1;
4 ~ Q, o( V! E+ n) k. T else z = 1'b0;/ _9 H8 O2 X4 r" }& k# Y
default : z = 1'b0;
! A1 |3 g8 k$ Y2 ^/ Y endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]$ z- v/ I/ q! k
0 Y) B: Z1 c% @# n
使用1個always描述output logic。 以上3個always寫法與Moore FSM的3個always並無差異,基本上只要state diagram畫的出來,就能等效地用Verilog描述出來。 55行 // mealy output to delay 1 clk for moore
! H( L0 V: w& h2 Nalways@(posedge clk or negedge rst_n)2 z6 N* X ~; @& @8 M5 w. f" B
if (~rst_n) z_o <= 1'b0;% H5 C" h. {* t2 e# d( q0 G6 m% ?
else z_o <= z;% y: v$ d. O" q' y: w- X: e
之前提到使用Mealy FSM會少Moore FSM 1個state,且output會早Moore FSM 1個clk,所以最後特別將output在敲一級delay 1個clk,這樣Mealy FSM就會完全與Moore FSM一樣。 使用3個always寫法有幾個優點: 1.可忠實地反映出原本的Mealy FSM硬體架構7 u+ C+ s. C- ~; Z3 Q9 i" {/ E
2.可輕易地將state diagram改用Verilog表示
6 X+ x) c3 ^# R* x' j/ w4 Q3.將Next state logic與output logic分開,可降低code的複雜度,便於日後維護4 ~* g0 j" U2 {0 y
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]
: x3 m/ x3 D9 ^" i5 O5 V 1 /*
$ J( Z9 L1 \" q6 E- N 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
" Q3 e" w3 B9 j1 G# M3 c. [ 3
% v% D# H e0 l 4 Filename : simple_fsm_mealy_2_always_0_cs_ns_good.v% \. T# N* R+ g8 t7 T3 m7 h
5 Synthesizer : Quartus II 8.1
8 w7 b7 D9 q6 } 6 Description : 2 always block for mealy fsm (GOOD)
; u" z4 c0 R) M0 t6 Y, t& @ 7 Release : Jun.05,2011 1.0- W1 E) U" P/ u8 `% Q
8 */
3 t; R& Q4 ]2 B/ Z0 A7 X# Y K& \! Z 9 6 J" O3 Q' W3 N3 L: ]6 |
10 module simple_fsm ($ Q2 W& v+ i. h) f% n V' |7 _2 x
11 clk,
: u/ w, j2 D2 s/ C( R, ?- a) t12 rst_n,
6 r' W* I( `- K& I) Z5 a. |13 w_i,
0 p/ ?8 k* H( l8 a14 z_o3 {- O+ H1 o# D2 e, ^9 u, ^% c
15 );$ p: s- c# u& I4 P6 I# l7 ]
16
b; R/ Y% B3 |17 input clk;% d6 V% V, Z! z
18 input rst_n;
2 D5 i% e, M/ P4 m3 `( U7 e1 K19 input w_i;
3 h6 B) M! W+ j$ a2 H+ c8 B20 output z_o;
' s6 R" L! E, T21
+ J2 U" N& b* ?6 R22 parameter IDLE = 2'b00;, {9 O4 j5 |! L9 V
23 parameter S0 = 2'b01;
/ b* H) `5 I1 A- K) w# z6 v24 2 x% {: H/ `5 v9 Z7 s, X
25 reg [1:0] curr_state;
1 e% e4 ^/ i# l% P. z& L26 reg z;) ~4 O# Y' Y: t, D. _4 h
27 reg z_o;
) {4 j! h F1 n28
5 J. M! U; P2 f8 R29 // state reg + next state logic
1 S0 |" V4 g- b! h30 always@(posedge clk or negedge rst_n)
w( {' k5 R! \2 M! O31 if (~rst_n) curr_state <= IDLE;
: I- b k; N( T# C R& S% o2 {4 ]/ T32 else
- F. C2 X4 f+ g! N" V33 case (curr_state) m7 p4 u0 O' }9 H6 v
34 IDLE : if (w_i) curr_state <= S0;7 d" i7 j5 ]' m" y$ b* L
35 else curr_state <= IDLE;
p, a5 }/ }3 J. t! R36 S0 : if (w_i) curr_state <= S0;
: v X" u$ S" o* r, s8 V/ y. N) f37 else curr_state <= IDLE;
" g+ |+ x$ }5 L38 default : curr_state <= IDLE;
- E% M3 u& l7 t2 n39 endcase$ y9 U, S5 K3 c4 h5 I8 k# f0 F
40 & Q+ _) o) E# M
41 // output logic( m8 j/ S( u( p& ~) \4 g
42 always@(*)) P+ R$ B: a9 Z8 b
43 case (curr_state)
$ K4 v/ h; t) m& f+ P4 f' d! Z( b/ y( K44 IDLE : if (w_i) z = 1'b0;9 Y% |; y* A7 z: e. u
45 else z = 1'b0;
H, f# Y+ |% ~4 P3 {' Q% v46 S0 : if (w_i) z = 1'b1;& l4 J7 }/ K* }+ a" [
47 else z = 1'b0;! b4 k: o- d1 I
48 default : z = 1'b0;
: s, R# n" l2 t+ G& Q; r% E49 endcase# V% B' d3 ^( @9 e& L1 p4 k0 d
50 ( {# G p* g4 H: e9 H; E
51 // mealy output to delay 1 clk for moore
% u, F: q+ X' O52 always@(posedge clk or negedge rst_n). G2 A- x: D) f% E
53 if (~rst_n) z_o <= 1'b0;. ]; o5 k! @% y0 H+ J0 j }
54 else z_o <= z;$ e4 a7 ?7 d6 B( W/ b/ A* @
55
* P1 M- |/ C0 \ \. a# b6 x56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]0 t! m3 S9 N! d
* v% J0 m$ j% u+ H. r" R* N" Z P/ f$ N29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
3 Z( L( P8 P. U. q$ W$ B4 Q// state reg + next state logic
( V! y, s; X. f& w) H/ ~5 |always@(posedge clk or negedge rst_n)
; X V# n( S: p B2 x, l if (~rst_n) curr_state <= IDLE;
) g3 \0 ?1 r1 ` else, {1 [6 B; t6 K3 w
case (curr_state)) U9 T! j. N* x" V, }# Q5 T
IDLE : if (w_i) curr_state <= S0;4 t( f; j7 X, S8 Q8 d
else curr_state <= IDLE;1 _/ y1 t- W6 d% a
S0 : if (w_i) curr_state <= S0;
* z7 ]4 g" J1 K+ @8 H7 m9 @, r/ t else curr_state <= IDLE;
! k! Z" r; k& a2 p default : curr_state <= IDLE;6 g6 i }# f5 s2 U' l& @
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]* u' w6 W% S! ]1 I# F+ q' E
$ r, Z4 `+ ]+ O* O, c使用1個always同時描述state register與next state logic。 41行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]4 ^; B# f/ Y% a8 M* s: X
// output logic) l' {, k$ M/ R# l* D4 Q
always@(*)
* T+ o/ w7 ^1 V3 Z. E case (curr_state)% m7 E: k, P8 ^2 w+ [
IDLE : if (w_i) z = 1'b0;/ p0 `6 ~# I/ T _9 y8 @
else z = 1'b0;- K& g) Q8 J" D7 x( |
S0 : if (w_i) z = 1'b1;3 T1 @2 r# |3 t4 a% b0 ?3 M: F
else z = 1'b0;; {+ h5 z; I9 H
default : z = 1'b0;
" }4 W, M" E& M% P, L" c0 @6 H endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]& C. I t l9 x# l
2 F1 Q* i* G* L% T5 L9 ]
使用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
; j @& `6 x2 M9 }4 R+ A" }always@(posedge clk or negedge rst_n)
) n: U |2 I2 @+ Z if (~rst_n) z_o <= 1'b0;
. s% _. h. U- I0 c3 E else z_o <= z;
) l" r8 k3 M+ B5 }6 r4 p: ^之前提到使用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寫法精簡$ V) Y) R- T; ]) N
2.可輕易地將state diagram改用Verilog表示+ B8 Y0 c8 v3 f# K2 }
3.因為state register原本程式碼就不多,將next state logic與state register合一後,next state logic仍與output logic分開,因此不會增加code的複雜度,便於日後維護
, D; L% l( i. r* U2個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]* M+ E) d5 Q. V: t/ m
1 /*
6 l/ `$ N6 l# j) i/ _ ^: c) v 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
# I( S9 p$ g$ [) k& }/ t 3
6 |8 _# R5 O* z a& Z$ l 4 Filename : simple_fsm_mealy_2_always_2_ns_ol_ng.v
- @6 `1 E8 o0 p 5 Synthesizer : Quartus II 8.1! q/ V2 u* o, P! x8 H0 S+ F
6 Description : 2 always block for mealy fsm (NO GOOD)% b Q6 e1 Z/ A4 b- C
7 Release : Jun.05,2011 1.0
R: W/ w0 ]" n5 ?5 Q+ c- v+ J 8 */
( D. d2 `" V) ] 9
% h' ~9 P6 a" C; `4 e5 n5 x `1 [10 module simple_fsm (% k0 O7 W5 C8 A% t9 N
11 clk,. h+ _" x+ L+ ]. Q
12 rst_n,- @0 M( l/ A( H- U# J3 f) K
13 w_i,
0 a( `( S. J3 O/ z14 z_o
0 U7 u; U/ r# W! p15 );
, G6 ~6 j- t: C! `/ `/ \, D( K1 K b16 ( Z9 n" C3 @0 |. H2 ~( m+ ]
17 input clk;
$ O& t6 M3 m# M5 W! ^% E9 e5 j* Z18 input rst_n;8 ~7 K8 L3 K B! G% E/ B, `; [
19 input w_i;
2 P8 Y: n6 t4 r20 output z_o;8 U# n: w4 c8 p' A- u
21 " S ~% ^1 I) T" \1 K9 ?5 p# N0 r0 E2 O
22 parameter IDLE = 2'b00;
: f/ w. ?5 @1 U& S) b* j23 parameter S0 = 2'b01;
0 t' o. C" H! N1 X% w24 & C. l/ R. S$ A- @1 A, i8 b( `; [
25 reg [1:0] curr_state;
8 {5 A" q4 V8 I8 S- ]26 reg [1:0] next_state;# d+ ~6 A* D+ Z, M' F
27 reg z;
4 c2 _) Z( U: C" D28 reg z_o;
# S+ R' s, s$ R+ {9 \& V6 H3 _& G" x29
4 V: h0 Z$ ^1 t- z30 // state reg
6 E, ~6 m! [4 p" Z0 K7 q, k31 always@(posedge clk or negedge rst_n)% i/ }# k* r8 G: E
32 if (~rst_n) curr_state <= IDLE;
- }/ E* L8 G3 \33 else curr_state <= next_state;
% X2 q7 L. @# N% I/ ^8 f34 4 }: X4 B; a( E, T) E
35 // next state logic + output logic % K! t0 U, c+ _
36 always@(*)
, j2 T% }! F( ]! k, g37 case (curr_state)8 V! v+ x9 g- _% ~. Z# J
38 IDLE : if (w_i) {next_state, z} = {S0 , 1'b0};
; q# p* n* W E( s3 F39 else {next_state, z} = {IDLE, 1'b0};
! A( S5 {5 J( _7 {40 S0 : if (w_i) {next_state, z} = {S0 , 1'b1};
' j( L& \# g! C7 c& Z0 g41 else {next_state, z} = {IDLE, 1'b0};
& b; T& [9 ?* X9 u) x+ M42 default : {next_state, z} = {IDLE, 1'b0};3 T1 p4 n! q, |( S# h9 k
43 endcase
9 ?' {6 E; r O) P/ j44
- f% z% j3 a) I$ E) W45 // mealy output to delay 1 clk for moore 9 v% X& E9 Z- e3 H
46 always@(posedge clk or negedge rst_n)' _. W0 D3 U' d: e c& m
47 if (~rst_n) z_o <= 1'b0;; G" F/ L# W! d" u! n
48 else z_o <= z;
5 T9 M5 u; a% r8 _9 _49
- `6 b) {/ P0 B! R1 Q. S' s) D& t; e- I50 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]$ Q K# H6 o% `1 o
7 G- C" [, i3 y4 U30行 // state reg
9 s2 H9 E" w- h- n3 a5 X7 S* G; \always@(posedge clk or negedge rst_n)3 _# @/ J( E+ ~: z# {
if (~rst_n) curr_state <= IDLE;+ o+ M- E; a" _5 D8 G. r
else curr_state <= next_state;
5 v- I+ k3 { k5 s7 O# [; P使用1個always描述state register。 35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
/ o1 k) p" N( F j1 b9 u// next state logic + output logic ; b4 }7 k4 ]' S& I7 i- H
always@(*)
3 K. d! a) H/ g& \. L case (curr_state), f! r `4 w& R0 R) E) F2 ]
IDLE : if (w_i) {next_state, z} = {S0 , 1'b0};
( _9 w9 w. N1 y- r2 S else {next_state, z} = {IDLE, 1'b0};: ] p! Y: h* C! D7 I. e2 v7 s# D
S0 : if (w_i) {next_state, z} = {S0 , 1'b1};
3 b! m5 C1 z/ S" l9 V* x else {next_state, z} = {IDLE, 1'b0};
- i) H2 B+ `# N4 q' d4 Y default : {next_state, z} = {IDLE, 1'b0};
5 A' p$ S, |( y# r5 y endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
6 l7 x t9 l; N! P+ s0 r8 J, v' Z6 Z8 x& `
使用1個always同時描述next state logic與output logic,因為兩者都是純粹的組合邏輯,所以使用blocking。 45行 // mealy output to delay 1 clk for moore ! _6 C$ T0 h. x# t% [" A. a
always@(posedge clk or negedge rst_n)
1 B9 a3 ?1 q. }7 h. b9 ^ if (~rst_n) z_o <= 1'b0;1 ]- C7 d* I) t) ?
else z_o <= z;
* N( L1 ?2 B' d% L! ?之前提到使用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的複雜度,日後維護會更加困難. D+ E" \# R9 S( s" F" l' P
不推薦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。
& {( X; O4 `& f實務上推薦的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]- i y5 b! y" |* v2 S3 z5 U
1 /* $ D5 l4 `4 J+ V, a; ~/ _4 H/ y
2 (C) OOMusou 2011 http://oomusou.cnblogs.com# z0 Z! c1 ~* A
3 ; d, i: y" d4 C0 y
4 Filename : simple_fsm_moore_2_always_0_cs_ns_good.v
3 K5 a9 M4 K+ s4 w( c 5 Synthesizer : Quartus II 8.1* M) D/ n" r) H8 v
6 Description : 2 always block for moore fsm (GOOD)
, z3 R7 R; W- x- a" S$ n" d* a 7 Release : Jun.05,2011 1.04 _8 V7 l; `% \" o0 }# l7 L
8 */& u# x) C7 n& B4 J' B8 y
9 + m0 i+ g& M+ j) M1 N' E: e
10 module simple_fsm (
- s r3 ^; b6 [11 clk,
, U& P! D. r; v8 S; K! g12 rst_n,% T4 t4 z, w2 |
13 w_i,
- y0 o$ `% |0 }" U3 O; \14 z_o8 b% ^9 a& P4 i: @( c0 F' M& w
15 );
* |* E* N' g2 k" H16
% C5 w6 m/ X- f: A; _. W, _17 input clk;. Y( L8 G/ s5 a, E+ N+ g- _
18 input rst_n;
, X( }. B( f& q/ P# S p19 input w_i;# x' ]$ m' \9 j z5 z' [. P
20 output z_o;
. a8 D( X0 r, n$ v( y7 Z' t21
# y7 i9 e( c9 Q4 E2 F9 B! w: q0 f22 parameter IDLE = 2'b00;6 H( C" V: o; A4 z: ^
23 parameter S0 = 2'b01;, h4 e9 W# D% i8 B3 H- P
24 parameter S1 = 2'b10;
, ? A: f% ?9 [+ F, r8 d/ y25
! J2 p3 L+ f/ B+ t, e2 p26 reg [1:0] curr_state;
# v% U \/ N. Z( Z) A _3 r27 reg z_o;
9 L5 v e% K/ o) ^/ _28 . R* }7 Q; o% ~' M8 M* W
29 // state reg + next state logic
) E: K+ G& z e0 ~30 always@(posedge clk or negedge rst_n)* s; t$ l$ E6 x) x
31 if (~rst_n) curr_state <= IDLE;4 g: P4 o1 z: F) m, j& l4 [
32 else
c! ]: F# x6 S9 `33 case (curr_state)* J6 }7 g' A6 C8 j$ V5 ?
34 IDLE : if (w_i) curr_state <= S0;7 w- `1 }' e( g' b: b
35 else curr_state <= IDLE;1 O' V. |. g8 [* G7 f3 p
36 S0 : if (w_i) curr_state <= S1;
1 H& I q9 f3 \37 else curr_state <= IDLE;
+ v* }5 s z# [8 V, k8 i P38 S1 : if (w_i) curr_state <= S1;# [! C4 Y. }) n' p$ ^6 `& R# K8 g
39 else curr_state <= IDLE;1 S* N( V v1 H- d3 n! |
40 default : curr_state <= IDLE;
. V/ y }8 ]/ X( m1 W1 e3 m. w5 \41 endcase g8 Z$ F2 P# ]. R$ M1 |; Z( m
42 + p2 G# R, @/ Q2 v
43 // output logic
( T$ z- z7 @( E4 h% I ?4 ]) w44 always@(posedge clk or negedge rst_n)
" [" h4 X5 J8 }+ d8 L- x0 D45 if (~rst_n)
8 k. ~! \. ]: d46 z_o <= 1'b0;/ }$ J1 J/ U. L& M3 t
47 else% U( Y* `4 X- ~5 d7 B
48 case (curr_state) C' n& M; K- F0 v; J- B
49 IDLE : z_o <= 1'b0;& {6 l' r8 I8 ^3 y- g/ Q e4 H! e+ t
50 S0 : z_o <= 1'b0;8 b3 w' G9 D1 r* x* N* B! \
51 S1 : z_o <= 1'b1;
' z |, s% L5 K- ?* G9 j) y52 default : z_o <= 1'b0;8 W% V, u: A3 z, l; G
53 endcase
& I u" J3 T1 @, ~5 n54
7 R) r$ T _7 Z! I: S$ @55 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
9 s4 e/ A! Z& t9 N+ p- p& e' l- J3 T% ~1 ]5 i: p: d
29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]9 A, c/ J1 s+ C7 H. K
// state reg + next state logic& g" q: t. A9 ?7 ?! s" N- J" |2 U
always@(posedge clk or negedge rst_n)
+ R& r0 G) l, L6 x/ M( r if (~rst_n) curr_state <= IDLE;
+ ]- f" t' e8 i5 n else4 b" X# r% @% r0 g3 h9 }+ B
case (curr_state)) h& q, ~% A* j, P- M' g- h( r
IDLE : if (w_i) curr_state <= S0;8 q3 r8 ` L9 l8 l" |
else curr_state <= IDLE;' U5 l, e- L: Q- R
S0 : if (w_i) curr_state <= S1;* }+ \& e4 ]) q3 o J3 X
else curr_state <= IDLE;3 S* {6 l6 O$ @) o/ v4 q
S1 : if (w_i) curr_state <= S1;6 @$ s) N; H+ j- x t K8 p! p4 d
else curr_state <= IDLE;
" |6 M" \* s* l default : curr_state <= IDLE;
$ F* u2 M+ |* ^ endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
0 w: C4 w: z. A. t- _1 h9 a5 I2 Z" e) `1 I, Z- j
使用2個always,且state register與next state logic合一,只要判斷curr_state即可,不用擔心是否要提早1個clk判斷。 43行 [url=]http://common.cnblogs.com/images/copycode.gif[/url] ]6 _' g, g8 c
// output logic( l; P; x7 r* c, Q
always@(posedge clk or negedge rst_n)
* Z) O5 \) M" h; D! z4 J/ [0 B if (~rst_n)8 S2 r" p' b6 x; W" _8 }
z_o <= 1'b0;
# e; ~- v& w2 I/ I( y else
5 A, ^1 h: L+ D; x8 u case (curr_state)
7 d+ y: ?' Y+ @$ i% |9 e IDLE : z_o <= 1'b0;
5 @1 `6 o3 d5 x S0 : z_o <= 1'b0;6 i3 q" G# {) u f
S1 : z_o <= 1'b1;: d6 l7 h6 T2 P, N
default : z_o <= 1'b0;
# G$ z/ _3 k9 m2 Y8 R5 W5 l endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]* b2 m* r$ ]# C
( r- l3 U# j5 Q( W( ?7 Z
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]
4 {5 I3 N/ e/ J- m 1 /* W9 S+ f' J$ G& Z' L! A
2 (C) OOMusou 2011 http://oomusou.cnblogs.com& k8 F3 O' `% Z& \8 [! m; O
3 ( R# C& a; M3 R5 m8 }
4 Filename : simple_fsm_moore_3_always_practical.v
% i5 B* M+ Y; E6 ?! R8 j& V 5 Synthesizer : Quartus II 8.1+ {! U( a3 g" [$ j3 `& P
6 Description : 3 always block for moore fsm (BEST)
! }0 \. `& q3 F6 Q 7 Release : Jun.05,2011 1.0
6 }9 y; w, F% l+ v! _ 8 */7 t9 f4 L% M, r+ H/ T/ p* O
9
, X8 [+ t; I5 u, O4 l8 j9 f10 module simple_fsm (
8 f, B, M3 t( x! Q1 w11 clk,
1 c: p3 C5 g' J, t g12 rst_n,
" A9 q$ `4 n% W13 w_i,
# o9 X6 f7 w/ n: r v0 X/ `14 z_o' h/ v0 d8 N+ t' E7 u
15 );* X) o$ i4 y* r. L
16 " |3 [7 S( e' r' {$ _' u$ @# k
17 input clk;
" n8 N6 l" |1 d, w18 input rst_n;+ {# M9 C% U, A! R% |
19 input w_i;
& ]/ l3 P: w. G6 g. P" `9 a20 output z_o;
. y7 {# k7 \( Z r% T t' u21
5 o( s! r- p+ U5 E" ~. g3 L& p22 parameter IDLE = 2'b00;8 p% j) H0 q, l2 G1 U0 y
23 parameter S0 = 2'b01;) J2 F7 i7 n' w0 c$ W' N9 k
24 parameter S1 = 2'b10;
0 \- O: H# k8 _& g* x! f% R/ |25 ; \' g. C* N5 G3 P# a
26 reg [1:0] curr_state;
: q' L' F5 i" m$ i0 N$ ^27 reg [1:0] next_state;3 L$ X: }' q8 b Y% A
28 reg z_o;
8 {0 @# n3 o% T) ] F29
5 H& W+ F5 B7 o8 j% \. ?" ^30 // state reg/ O8 [3 R# K9 o6 E/ g
31 always@(posedge clk or negedge rst_n)
3 M+ m! i3 X. @% E* W$ M- ~32 if (~rst_n) curr_state <= IDLE;' a j1 i' k4 x: a* |) I7 ]6 x% D* Q
33 else curr_state <= next_state;5 U7 I& p% o, N% T5 L: s, j4 l
34
+ |' y/ D' K0 ]35 // next state logic & q+ S+ t! |5 n1 K6 {& }8 I+ ?
36 always@(*)$ I& P1 W8 J- \# m( h
37 case (curr_state)* V) D! w: n' Q* e
38 IDLE : if (w_i) next_state = S0;
0 g# n5 h2 l9 d K1 a39 else next_state = IDLE;- |4 V2 T8 v. j. V- x- r
40 S0 : if (w_i) next_state = S1;
# g- e7 d! J' ~4 h& O% q% G41 else next_state = IDLE;7 |) L* l+ ^3 w; e$ y3 G8 t/ n, T
42 S1 : if (w_i) next_state = S1;" C! l, ?# M; {2 C$ q; u; e
43 else next_state = IDLE;
( S8 i! R* s7 o) O# a: [44 default : next_state = IDLE;, H" f2 q' Q9 ^
45 endcase
) A6 P$ O" |6 i/ Q# S. j3 m7 w' q46
: J7 D+ D [) y- }" f8 A0 ]2 S47 // output logic
; T# u) J5 D) h6 L' C48 always@(posedge clk or negedge rst_n)( f; I. x- D4 m' N6 Y1 t
49 if (~rst_n) z_o <= 1'b0;
) ?- x# a: Z0 S6 o, I50 else : K0 n/ Y. ]! I' ^: n
51 case (curr_state)
$ h6 `5 x/ |/ c. Q E52 IDLE : z_o <= 1'b0;
/ d3 B7 Z% \& \* G! }% ?+ j53 S0 : z_o <= 1'b0;" l2 [7 |' h" W. O& _7 y
54 S1 : z_o <= 1'b1;9 p' E: \4 S7 ^, C0 J9 T2 X4 F8 h
55 default : z_o <= 1'b0;/ b1 |0 X5 _- F0 c
56 endcase
# S) v) f5 H, C" \* E( A57
$ P3 T; `9 C4 q( S5 H: a58 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]" @) c% ?' x* o. u* Z l/ x. D
5 V9 P$ W8 @6 B' w& f2 x30行 // state reg: o$ x/ H1 }% I. v2 G0 F* U
always@(posedge clk or negedge rst_n)
( ]5 I- r4 C1 v if (~rst_n) curr_state <= IDLE;
, H6 ?! X% f( s: z else curr_state <= next_state;9 |3 g$ P! B- f4 Y& Q
使用1個always描述state register。 35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]! J1 u2 r) Q3 p9 c- H
// next state logic ( n! K8 y+ q4 L$ c3 V3 t7 T
always@(*): ]; `" F. }, j
case (curr_state)" _# o& }1 v" M' T4 x4 Z
IDLE : if (w_i) next_state = S0;
0 H- r G6 P1 _, I; z6 n else next_state = IDLE;
# C7 y7 r/ s2 u5 W S0 : if (w_i) next_state = S1;
4 U) d9 J* k% k8 ]: ^% k' {% Z) S: ] else next_state = IDLE;. A: x4 j. M& c: H
S1 : if (w_i) next_state = S1;$ J# [1 g5 r. w3 Z( t9 S, @0 G
else next_state = IDLE;( {* m4 G* Y) v3 `; y; X
default : next_state = IDLE;0 ^: R6 u& g. M/ X; N p o* n
endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
: e; q3 u$ X9 F/ g1 n4 @& a+ t5 L: O/ F
使用1個always描述next state logic,為純粹組合邏輯,所以使用blocking。 47行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
: l& E) s5 E; H* }// output logic8 `4 _3 l/ W2 x9 [( s
always@(posedge clk or negedge rst_n)7 ^1 w& \" v8 l. `1 h( E# }
if (~rst_n) z_o <= 1'b0;- |% c8 p6 K/ C2 g; Z# P9 m
else
) T2 A: ?7 b; T/ x& ?+ {5 J; b! _) a case (curr_state)
! m6 B0 t/ N: U% | IDLE : z_o <= 1'b0;% m, P9 f& d0 q! g" t
S0 : z_o <= 1'b0;# ]6 C* y% M1 k( o& @
S1 : z_o <= 1'b1;) u! v/ x! Q9 ^! e0 z
default : z_o <= 1'b0;: Q5 T( s( \( U
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]" D3 v5 W8 X' [8 e7 g' y: Q
0 K: q0 O2 u+ `* z
使用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]
& r7 o& ]3 a8 J& Z0 H% V 1 /*
0 [% c: _. ]: U( `8 o9 k 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
, I' n! {1 B4 E/ a" {+ n 3 : {- Z7 Y, n9 V: H7 B# C! L
4 Filename : simple_fsm_moore_3_always_practical2.v
0 C, G6 N( u* E: F; N' |) o U* L 5 Synthesizer : Quartus II 8.1
2 \" V. o4 _; m- K' o' V 6 Description : 3 always block for moore fsm (BEST)6 ^4 N9 b& A$ C8 c! O9 J
7 Release : Jun.05,2011 1.0- _- ?6 V* k7 ^' ^% Z m, @& T
8 */( W! G. Q6 c+ ]- [1 Q7 O/ w& Y
9
1 A9 P3 | D G- x+ a10 module simple_fsm (
1 n7 L: X$ {- J$ Y11 clk,
9 f5 l( `* _( p1 f12 rst_n,- v: z( M- ]# R2 Y
13 w_i,7 s) N8 U3 Q4 [, Y. _
14 z_o
& [+ D @ u& V% x15 ); N3 c4 c8 K, b2 n" M: e
16
: m5 r1 W9 ?; @& C$ J17 input clk;% Y# v- {/ N" A. ~) H4 @7 `" F
18 input rst_n;8 D. {9 x7 I5 K5 T+ h: u
19 input w_i;
8 t6 d8 \; D0 E20 output z_o;$ i6 H" z0 o1 c8 J8 L$ B. X
21 : L- X9 ~$ I' Z
22 parameter IDLE = 2'b00;
2 }( [- v& f$ @& g/ f23 parameter S0 = 2'b01;
) Q# Z. l, H: V! Z6 u6 K2 Y: `24 parameter S1 = 2'b10;
8 [$ m* x9 ]* h" ^& m4 Y! o/ Z. H25 ( @( J6 ]+ B. y' R3 M6 v ]
26 reg [1:0] curr_state;! h% \. u1 y1 u9 v
27 reg [1:0] next_state;8 O* q( O% X' Y" U# D
28 reg z_o;
' ?- r# T; @; b! V29
0 }( s$ N+ P' q2 g, v30 // state reg
$ \( @! |+ f* Z4 l) k \31 always@(posedge clk or negedge rst_n)
, R2 z r. q/ S: i- X6 \5 E32 if (~rst_n) curr_state <= IDLE;
8 l; E+ C, ]1 w+ F33 else curr_state <= next_state;
3 c8 O) r8 |, E7 v+ S0 v34
5 {2 W% q% Q# f8 M& U7 B8 z5 a! A. y35 // next state logic 1 q) ]6 `# E, m
36 always@(*)
+ g: o* h- \, Z6 T4 Y1 ~+ S9 C+ s37 case (curr_state)
, ~* w- o( ?8 }38 IDLE : if (w_i) next_state = S0;
/ P) y9 p0 C1 y; A& m3 s0 o2 y1 O8 ?39 else next_state = IDLE;/ o2 N- j$ H5 t/ q- L4 S8 j- w
40 S0 : if (w_i) next_state = S1;
/ B! W6 {8 ]" J- H |: k1 \9 \4 C41 else next_state = IDLE;/ l! S# B& x9 U2 F* P
42 S1 : if (w_i) next_state = S1;4 P: c. ~6 }# g( F* `! M0 y% n
43 else next_state = IDLE;
( A* I; o* \7 q4 p9 j! ]+ N44 default : next_state = IDLE;
" u8 b; d1 M8 h; V6 Q$ K/ s( z45 endcase
+ e; Y; J$ o6 I/ p) l4 Y: G46 7 B5 B8 l! k1 Y- A& N4 X
47 // output logic
' j6 y% |5 J T( m8 \3 {" R# S48 always@(posedge clk or negedge rst_n)+ Y, a& m( U2 b8 j7 |
49 if (~rst_n) z_o <= 1'b0;
' M8 Q) P% X4 v0 j( {50 else 5 F5 K! r2 a5 Z
51 case (next_state)
+ h" t' \/ k" X$ ^- d52 IDLE : z_o <= 1'b0;
/ E6 |; S3 n& i53 S0 : z_o <= 1'b0;+ v# r! u0 M5 ?8 D) g( C
54 S1 : z_o <= 1'b1;' I6 v4 z" C3 ?% |/ A1 x' J1 \" S
55 default : z_o <= 1'b0;$ q6 }1 G2 k$ S" b% G2 Y
56 endcase
2 w) m9 {% P9 w% M; R57
5 x( R$ v) @9 [+ }58 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
/ `& x2 u, o! W2 w$ s0 h8 R+ W5 d
47行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]! v# u) k7 \7 O4 a9 K
// output logic
1 {$ z1 e3 ]) u4 Lalways@(posedge clk or negedge rst_n)
" s& l; m" A$ S; a# W& Y if (~rst_n) z_o <= 1'b0;
* ]& w+ ^" W' M) r% m! F: d else * c: Y& _* m, ]
case (next_state)2 `1 H) r- @& D( C
IDLE : z_o <= 1'b0; e Z. m y; N |0 G' n4 a
S0 : z_o <= 1'b0;
+ h! _" B: _( m S1 : z_o <= 1'b1;+ F+ n3 W) y. J9 x0 s
default : z_o <= 1'b0;& c# y* J S" G2 G4 l$ D
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
5 }) I. }4 ?' L& j, F& h( }6 W7 }. p. I8 a
使用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,很容易出錯,觀念必須非常清楚。 ! i. ^5 ^. m; Y: }0 D7 S
|