之前一直烦脑我写的代码好难维护,在网上看多了发现人家说三段状态机多么多么的好,我就马上去查什么是三段式状态机。发现我之前写的全是一段式代码,怪不得我老是没办法提高自己的水平。) O6 b7 ~$ s. M+ b
所以我在网上找到一些特别有用的二段和三段式写法不但是给自己看的也是为提高自己的技术的各位看的。
; s& g2 N1 ~( c9 A w( ?( f( q, ~! B, ]6 }# M
0 x) d0 b; Q/ V# U8 V* ~
Abstract# c O$ [ a5 A9 X* ^
FSM在數位電路中非常重要,藉由FSM,可以讓數位電路也能循序地執行起演算法。本文將詳細討論各種FSM coding style的優缺點,並歸納出推薦的coding style。 Introduction: ~ {7 E( h1 X, h& r
使用環境: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]9 [0 O% c. y0 M4 _* q, a# X' G' ~! w& C
1 /* ; Z5 D! E ]- _+ i2 z
2 (C) OOMusou 2011 http://oomusou.cnblogs.com# Y4 q5 \' J' n+ z) i0 m( l
3 # E: |1 R' W* h4 |/ r$ c5 W
4 Filename : simple_fsm_moore_3_always_best.v8 M$ h% _0 |! G- Q F% S! W/ v
5 Synthesizer : Quartus II 8.1) y. A. ?0 o: e' q7 S
6 Description : 3 always block for moore fsm (BEST)
$ b" Y: z, i# } 7 Release : Jun.05,2011 1.0
% b6 W, y2 u1 f7 ~6 l, Q: ^- o 8 */
0 h2 C/ `5 t! c- C: x% _ 9
+ \# D: I0 {3 @4 C8 A; q) b10 module simple_fsm (
# N, l% o1 P" e11 clk,
! L0 ?* G) s) j1 b12 rst_n,* f4 S" L+ [6 W3 d
13 w_i,
# F5 S* V0 Y& v) J7 K2 P* I14 z_o
% `& H M6 ]- d( G# @5 j# M/ |15 );
9 [ U: g ]5 t6 r( I: j9 I+ b16 ; M z7 y9 H j9 p8 ]% {
17 input clk;0 ~/ @* b& u8 Z
18 input rst_n;
" B( Q' q. _* z/ ?$ v! }# u19 input w_i;2 s; ^. a n1 I% B8 G
20 output z_o;7 D: j1 A: _9 \
21 ) i0 f! Z- v$ ?1 k& @" ] u7 h
22 parameter IDLE = 2'b00;4 O& O2 R7 @: C# B* k1 h3 E
23 parameter S0 = 2'b01;$ a/ Q# O4 z& y2 V t- x. D$ {
24 parameter S1 = 2'b10;6 |5 t7 _6 m6 ?
25
) f; j7 c. p Z26 reg [1:0] curr_state;1 t% D2 U: q- Z
27 reg [1:0] next_state;
1 r! K n* F1 |0 O( H28 reg z_o;
# w" Y+ J1 p: ?! B1 W29
- v S5 o. T# C3 L. U30 // state reg
0 D4 ~! l7 o# R$ u% _31 always@(posedge clk or negedge rst_n)% S0 E. m1 d* C7 _6 Z$ g
32 if (~rst_n) curr_state <= IDLE;
* g) I& M, m8 z3 ~0 t! O9 J6 }33 else curr_state <= next_state;) }4 M2 w) j' G) T4 u! P
34
+ c1 j4 H# e |. I: j6 X35 // next state logic ( ^2 m3 d6 d# q5 p( M( t
36 always@(*)
+ R: ]+ j; F$ f* X8 K37 case (curr_state). j' R: u/ x+ d4 j
38 IDLE : if (w_i) next_state = S0;$ s' O) {* S, E1 W# d0 O
39 else next_state = IDLE;- e% [% n5 n9 K
40 S0 : if (w_i) next_state = S1;5 z- f G9 c# O2 }- j; z6 k) Y
41 else next_state = IDLE;; L( Q: f2 s) a
42 S1 : if (w_i) next_state = S1;2 q5 \; s% k8 i, i" h+ K+ @, p/ @
43 else next_state = IDLE;! y. J, o* e" }8 B n T
44 default : next_state = IDLE;# h; G; k- f9 Y a& [7 X7 M3 Q' m0 N7 I
45 endcase
0 l. V2 ]# P+ ~& w46
7 o* l: B9 q9 F$ a9 F; r: Z47 // output logic
4 j7 _0 s3 X: {) s! Q" V48 always@(*), a/ K: `1 ~2 W9 H
49 case (curr_state)
: m3 r' E& P/ p$ F) z50 IDLE : z_o = 1'b0;: {( e) P5 U$ ~6 x! M# C
51 S0 : z_o = 1'b0;7 j& G8 O1 C$ [& k z' r% ~! U
52 S1 : z_o = 1'b1; t: `* j; z$ W' G# c. {9 d* b% l
53 default : z_o = 1'b0;
! j2 _# }3 k0 ^! G+ L8 O5 ^4 C54 endcase% v) O+ t5 }4 j) l
55
) C% K4 {9 F+ J: m56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]3 \2 n2 b$ r7 d, v4 F1 q7 K: t! V
* G3 z9 ~' U- a+ R6 {* e
35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
& g/ O' A0 d: J# ~" h2 V0 Y+ P/ e// next state logic ^& V5 b- D8 ^) ?, W1 q9 u
always@(*)
. e4 C0 J1 E. z5 p* N case (curr_state)! E4 H% d3 v2 l* }
IDLE : if (w_i) next_state = S0;3 R! k) m% E0 Z; N
else next_state = IDLE;* C8 R. j0 S* r
S0 : if (w_i) next_state = S1;
! f$ v9 w* V3 F. X i else next_state = IDLE;
Z4 h/ o7 F6 ^0 k$ Y- c' p S1 : if (w_i) next_state = S1;
; m5 @! t I" q* H else next_state = IDLE;2 H- B+ ~0 S/ {( v6 P0 k) |
default : next_state = IDLE;
4 y, ?( o6 V$ i" K9 D" W$ J endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]9 { M( ], j: O" y6 G. b: t' ]
2 n* `* H4 A- g6 M ~ K使用1個always描述next state logic,因為是純粹組合邏輯,所以使用blocking。 根據Moore FSM架構圖所示,next state logic的結果與input與目前state有關,所以先用case對目前state做一次大分類,然後每個state再根據input做if判斷。 30行 // state reg. F# `* x. Z7 c3 i& K) {, Z( v
always@(posedge clk or negedge rst_n)- k; T. o: t1 T6 @5 _! j7 \) D
if (~rst_n) curr_state <= IDLE;$ R7 J0 d, N$ a% {6 i5 g+ B8 A
else curr_state <= next_state;
! P9 V6 g3 Q, y% C# k& Y使用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]$ s+ t) ]) l2 p7 d5 U
// output logic
) K& ?7 n, u3 ]always@(*)+ k# Q" ~9 J" u6 D6 e
case (curr_state)' A7 g6 w1 h! o3 h, q) J
IDLE : z_o = 1'b0; O0 [: C, ]' c$ w
S0 : z_o = 1'b0;0 y0 ^% e- {* ^, a! j' _# E
S1 : z_o = 1'b1; s8 x' b! [. s. w
default : z_o = 1'b0;
+ l" J u) e4 @/ B, I endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
z5 D; r' t; K- T# O5 p
. ~5 T- d" `4 r使用1個always描述output logic,因為是純粹組合邏輯,所以使用blocking。 根據Moore FSM架構圖所示,output logic的結果只與目前state有關,所以只需用case對state做一次分類即可。 使用3個always寫法有幾個優點: 1.可忠實地反映出原本的Moore FSM硬體架構
/ |& m2 a2 x f) e$ x' G3 Q9 H8 l2.可輕易地將state diagram改用Verilog表示
: S) x$ y% Q. C& t+ n3.將Next state logic與output logic分開,可降低code的複雜度,便於日後維護
) @1 P( R; m" A( f, g$ m% D/ n2 b3個always是一個推薦的寫法。 Testbench simple_fsm_tb.v / Verilog [url=]http://common.cnblogs.com/images/copycode.gif[/url]* n# U m/ n% K- O
1 /* 5 S) t/ C. g9 y; x6 t% y
2 (C) OOMusou 2011 http://oomusou.cnblogs.com5 d$ J# g5 A5 v' `3 \" k
3
$ N& o4 L k. @ V4 Filename : simple_fsm_tb.v. W7 b9 ]2 s6 y2 v5 h( V8 @
5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9
) q* H6 X p0 H+ J! ~6 Description : testbench for FSM
% e$ h8 t' r% O! N& g7 Release : Jun.05,2011 1.06 b6 V4 }1 X9 p
8 */7 B4 H5 b9 H6 K, `+ X7 F0 [! E, K# u
9 * @ @6 t4 j2 h9 m, A2 M
10 module simple_fsm_tb;
" }% l* F. z. t: ]11
; \; t' T* d6 `+ ]1 W$ x: @12 reg clk = 1'b1;: L. Z9 b! S6 C h
13 reg rst_n = 1'b1;
9 A" @* Z6 D/ m# \3 w14 reg w_i = 1'b0;
, j8 l* }: O( d, D5 n15 wire z_o;
' H0 H: a3 o' n' U16 + f# W# t2 X- m4 L
17 // clk
+ c0 y$ @1 x! @18 always #10 clk = ~clk;
- }( {4 k! ~2 w19 & J" H6 `. t3 I5 |
20 event after_rst;
* l, ^% {% ^9 I1 K21 3 Y) q- o/ u# f6 v
22 // rst_n
7 t) a! V6 n3 U. k" K+ K: W. I1 ~4 a5 i23 initial begin
6 N1 I. `9 Y$ O+ v9 ^$ G24 #6; // 6ns& L$ S7 g3 R( M6 _* L- y7 v
25 rst_n = 1'b0;& H0 s4 R; }- Y e
26 #30; // 36ns
/ }& M5 T$ P/ ~6 Q( F( m( ~; p27 rst_n = 1'b1;
$ F/ T8 ?9 S* G7 y9 o0 a28 ->after_rst;
, j4 X5 A" R% L/ j- @' h e% i29 end
2 t/ {8 x$ r1 z0 h* K$ L30 + D) B4 B" y9 T5 s$ p5 N; N8 d
31 // w_i3 o4 U3 E; X# l, j
32 initial begin$ u. V6 e4 r; e, x
33 @(after_rst); d) V# w( ^* k
34 repeat(2)@(posedge clk); // 60ns
" C! y4 h, s" v, q- H3 f0 p35 w_i <= 1'b1;
[0 D8 Z( Y& P r: Q36 @(posedge clk); // 80 ns
7 I# A! M C- H: K8 |3 f& {37 w_i <= 1'b0;
8 H J2 I6 ?* B1 J y- m38 @(posedge clk); // 100 ns
8 o- V- [7 l" K39 w_i <= 1'b1;
( s+ A! J1 ]2 s* s5 E40 repeat(2)@(posedge clk); // 140 ns& E" \; Q, J1 Z) F
41 w_i <= 1'b0;
; V% w7 v8 _0 s) v" m( v" W! }. p& Y( B42 @(posedge clk); // 160 ns
4 V2 f0 M7 }+ V( m" e43 w_i <= 1'b1;; p9 B0 J( T! J# p( i, g8 @
44 repeat(3)@(posedge clk); // 220 ns0 V- F% V7 I3 X! E, V+ {/ r0 O! i
45 w_i <= 1'b0;" N0 Y2 f& s' t. [! J5 B
46 end3 m7 Z3 v. a: q2 z: e1 e9 ?" |
47
' v* O( \7 I- r48 initial begin
: B4 y; ^- j" ]7 f3 F- y% ?49 $fsdbDumpfile("simple_fsm.fsdb");& b2 Z& O% T, Z8 ]: }
50 $fsdbDumpvars(0, simple_fsm_tb);
9 C3 i9 ^! ]( |- I/ z51 end2 T8 w8 C5 E) q- t
52
8 o. ^3 V6 F( q2 M7 a, u3 E53 simple_fsm u_simple_fsm (
6 n4 O: _# i+ k- R' n- R54 .clk (clk),
0 F/ R8 ~8 ?" k! {3 K4 x0 c55 .rst_n (rst_n),: B6 x5 M4 F1 i! l% a! K
56 .w_i (w_i),
" o! S4 n Q% ^3 Z( C4 I5 }57 .z_o (z_o)- @* x9 m' w; C: ?; _- [0 Z
58 );
+ G V+ B) @8 {/ G6 f& @- U59
8 b7 |: q0 G) P3 D4 ]+ d" ^! D60 endmodule
) ]( l( l8 g, V8 K[url=]http://common.cnblogs.com/images/copycode.gif[/url]
o. Y# u$ s& P0 O/ ]; D: ]# e
0 c; W( x- M t- e' W7 _, v執行結果 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]+ q3 S4 u5 W) ]1 P( N
1 /* 0 Q& L8 ^$ G' R
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
5 m& ?0 U1 ?1 E0 f" o$ C6 d& g 3 & S! K7 B5 S6 a
4 Filename : simple_fsm_moore_2_always_0_cs_ns_good.v
8 o5 @' S2 t- a+ l/ G 5 Synthesizer : Quartus II 8.1' K2 N' L( z# h+ Z4 U9 a
6 Description : 2 always block for moore fsm (GOOD)' \+ C* x, G' O+ T
7 Release : Jun.05,2011 1.0
! D- c: B% A2 Y" r; Q) H; j# Z# [ 8 */
* E* |: N$ C8 M0 ]8 J 9 3 a8 d/ |3 b9 Y5 `
10 module simple_fsm (: r/ w8 Q& p2 ]6 L; K# c. W
11 clk,
- R# F& ^6 {! u9 c( R9 F12 rst_n,1 J7 a. A6 ]' n( _
13 w_i,# z/ ^9 G2 r& n. f
14 z_o
) P% b5 F; A7 @1 A" {8 w15 );6 V6 t& t& H$ ?/ G0 ~; X
16
|6 g" ?5 N; m7 @17 input clk;0 d7 r1 f' t, B& j& _" H
18 input rst_n;
1 G2 A. S& y) p+ J( M+ ~) K19 input w_i;2 ^: ]. k% n7 W2 c& ?8 ?
20 output z_o;
5 m; T/ t, `+ X3 I7 V c: i6 @21 , i' }+ o& y2 H: X6 V$ X, H
22 parameter IDLE = 2'b00;! S9 _3 l4 d6 |0 U$ T8 X$ T
23 parameter S0 = 2'b01;
; \, d) D$ P1 X; y24 parameter S1 = 2'b10;
& _5 _: d8 t* `! A. R5 r+ @25
" T: L9 ~2 y- a0 V% Q4 Y( L2 U26 reg [1:0] curr_state;+ F4 ~& c8 z4 K! o+ y4 p# K& ~
27 reg z_o;6 D8 R0 e% M2 e+ r( Q# b" ]( o
28
. C. ]& D# s7 F29 // state reg + next state logic# \8 G6 N+ G/ T) J1 N+ i
30 always@(posedge clk or negedge rst_n)
- l0 O" h6 }. H8 G/ v. Y31 if (~rst_n) curr_state <= IDLE;
; F2 q( H4 ~ p# @$ q$ V32 else
6 \% k1 k- [# i {8 y4 G33 case (curr_state)
9 [, g8 a3 a- U4 k34 IDLE : if (w_i) curr_state <= S0;
" O, Q/ Z/ {8 g+ V+ \/ t& L. O35 else curr_state <= IDLE;! A6 H b$ X0 q- k8 w, }+ `( f
36 S0 : if (w_i) curr_state <= S1;
L$ [+ r8 K2 x; D( _37 else curr_state <= IDLE;2 x2 ^2 W9 A+ u& j
38 S1 : if (w_i) curr_state <= S1;/ P8 T* `" O# z5 N/ L+ m }% n+ r
39 else curr_state <= IDLE;. p3 U4 e b$ M, k# P
40 default : curr_state <= IDLE;2 V' ]$ x9 b8 b2 ?8 K, P: O
41 endcase1 D. S2 X6 @' d! H* @+ u
42 8 b: Q6 D1 L6 }; ~# Z5 z
43 // output logic
3 B3 F( i1 \* G; o5 g! o h44 always@(*)# n. [* ]% B0 I9 y/ q1 L) I
45 case (curr_state)* I+ s4 R: Y. A. Z1 s
46 IDLE : z_o = 1'b0;/ u. @# E; p# v2 t' W
47 S0 : z_o = 1'b0;
: s0 _( d- e: w- a48 S1 : z_o = 1'b1;) o" V9 \6 ]% g4 ?* i
49 default : z_o = 1'b0;. v( ~5 E9 C7 }9 U; Z5 Y
50 endcase
6 K9 r* s6 [! b% a5 y7 O* w4 x51 6 A8 q8 a+ I! V% z ]
52 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]' E/ [: w% h9 R# ^' A
. s/ Y/ P% _: L$ G+ |+ p6 N6 |8 q29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
# e6 Z7 ]7 M2 y7 F" w- K// state reg + next state logic ~4 z" G9 I& m# o8 i+ l7 M; k' {+ k
always@(posedge clk or negedge rst_n)& i3 ^0 k4 O. @! F* d: H p+ F, F
if (~rst_n) curr_state <= IDLE;
; ?# o1 k9 Z6 l9 f3 T( l7 G4 F$ G; N else: P- R o2 U. [ l$ s8 B( X
case (curr_state)" V8 d+ ?+ \" G( n* i' L
IDLE : if (w_i) curr_state <= S0;
! f) C8 w ~, {# ~: q1 Z9 z8 Y else curr_state <= IDLE;
q# a @/ T, T) n S0 : if (w_i) curr_state <= S1;$ R, l. ?! }8 K( X5 @" d# ~9 [
else curr_state <= IDLE; j0 A4 p; C& G% w/ s6 z. P4 B
S1 : if (w_i) curr_state <= S1;
# S; I, h* q$ U6 S, G else curr_state <= IDLE;+ A L, j- F) z0 @6 }# J
default : curr_state <= IDLE;9 v3 P& V9 O" s$ F5 k' r6 M+ ]5 ?9 h
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
$ V$ [1 z1 J. o2 Z/ n/ C
9 f9 e* m/ E' O6 b將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]
" l! V* T9 L: }8 ?// output logic8 F/ P5 |! D( Q
always@(*)
/ b6 I$ ]0 @1 ]0 q8 C' G( Q/ s1 r case (curr_state)* E5 _ v" H* G* y R, v7 y
IDLE : z_o = 1'b0;
: V4 q5 C: R3 d S0 : z_o = 1'b0;) m) z5 p( K" A5 W' K3 R
S1 : z_o = 1'b1;- Z8 c$ `; a# \; A6 k3 C9 w. q
default : z_o = 1'b0;7 G7 N: W4 d8 \' [1 u3 {/ a
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]& T. h/ s8 H" Q/ ^% \
' L9 N2 _, j0 U$ ^9 w8 l y
使用1個always描述output logic,因為是純粹組合邏輯,所以使用blocking。 根據Moore FSM架構圖所示,output logic的結果只與目前state有關,所以只需用case對state做一次分類即可。 使用2個always (state register與next state logic合一)寫法有幾個優點: 1.程式碼較3個always寫法精簡
+ W: T2 b- x s. o, Q, h; O; a2.可輕易地將state diagram改用Verilog表示5 H% E+ T. i1 C
3.因為state register原本程式碼就不多,將next state logic與state register合一後,next state logic仍與output logic分開,因此不會增加code的複雜度,便於日後維護
2 C) `0 n" K, v w' ^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]/ F+ V4 U+ ]+ |; I' s8 k
1 /* 4 `1 @6 O* J/ X9 |# U
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
; }. j! h* T- I, b/ Z 3
4 U; q! D9 \6 X. k8 J% K 4 Filename : simple_fsm_moore_2_always_1_cs_ol_ng.v
1 q$ N: G" g( z& b2 C, o 5 Synthesizer : Quartus II 8.1
/ i5 I" \# w' m8 s! q 6 Description : 2 always block for moore fsm (NO GOOD)
. m2 e) r" w2 T! [- N6 r4 \# ^; w6 O5 A 7 Release : Jun.05,2011 1.0; ]% L; P! s! B! K
8 */
p; v9 I8 _8 v1 b 9 + y, M# X) i; \" V! X. w
10 module simple_fsm (
* K8 _9 `$ g" ^& ^11 clk,- Z" D1 x- y% `! E- U* M
12 rst_n,- u( ] O" m0 E1 K$ R
13 w_i,
3 n# G$ Q' |. Y; _& N& F14 z_o
; f; C$ G, s" q15 );7 z0 Q5 `" O1 {4 {- f9 M
16
8 C- r% a9 y7 i7 } R17 input clk;
+ M; r0 F! W3 K7 y+ U, c0 j18 input rst_n;, K& f! i- }% J) n3 }
19 input w_i;$ |( n$ b5 T3 I9 w6 W! Y
20 output z_o;& q- C) ]) j) r) R A
21 + [" B% I: ^2 h3 J; }! u9 H
22 parameter IDLE = 2'b00;( z% ^4 s; _ U3 ~/ t! s
23 parameter S0 = 2'b01;9 o: N' d; c/ l! \4 ^
24 parameter S1 = 2'b10;
0 J- Q( v$ S. c. R0 t4 x25
, y: |5 o5 s1 x, d8 A O3 Q26 reg [1:0] curr_state;
% @( k% S4 X% v27 reg [1:0] next_state;9 T: i! J" z( h9 ~
28 reg z_o;! f& E7 ^9 b+ `# w" u( U
29
( V$ q n9 |' D% }$ A5 c4 F9 p30 // state reg + output logic
/ ^ s) d& ^* h; w+ ~0 H1 ]. E31 always@(posedge clk or negedge rst_n)1 R' O6 k' O" [1 ^( N; ]( f. t
32 if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};
2 q, }- I+ |- e+ q8 y6 D: H# Q33 else begin# v" u3 f4 q* c1 @. i# \
34 curr_state <= next_state;# } w- t$ f& Q3 t+ ?
35
5 e6 X' `! }6 X36 case (next_state)- |$ ?+ r0 C5 K: X4 T, n& c
37 IDLE : z_o <= 1'b0;
( X$ T! P3 J3 @; c, F: b' j c8 Y38 S0 : z_o <= 1'b0;- @# J- z- N9 Y2 Q. q2 B. G) u4 {
39 S1 : z_o <= 1'b1;
9 L; ?1 p, ]- k5 Q+ k40 default : z_o <= 1'b0;
* o/ ^8 z7 d, \4 O. c41 endcase$ O$ \9 |; p9 u, i' t
42 end& b' a) _6 r d5 q( C
43 $ o/ Z+ b) m L8 p/ E
44 // next state logic
! n/ q6 [1 g" r2 s. }45 always@(*)( |- ^# i# [4 q* V8 ^, f4 K3 p
46 case (curr_state)
1 }$ \7 y8 d: g47 IDLE : if (w_i) next_state = S0;
3 Z h1 L1 e+ {- G, ~! s48 else next_state = IDLE;
! I5 k ^; z _8 F49 S0 : if (w_i) next_state = S1;4 p$ O+ O X9 H: u, O4 _; S5 c) q
50 else next_state = IDLE;
1 s# t# Y2 f- G0 f& d; t51 S1 : if (w_i) next_state = S1;
G0 f' v+ M! V \52 else next_state = IDLE;# y8 m) U7 {) H0 Y
53 default : next_state = IDLE; U( l6 Z/ T F/ m( n, u6 c) V
54 endcase
' X$ d/ Q) N- c6 @( p- T& s55 0 y! U# U+ J& }
56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]- T) Y+ O% ^6 }* v( t
9 I% R9 L+ ?) R: k7 k Z! V
30行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]4 R; i) b: n. D# {& k) Q
// state reg + output logic
) v C: [- D. X) p& N$ t3 Falways@(posedge clk or negedge rst_n)4 G, F3 v" s$ F f8 ^
if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};5 u6 b% [9 K( V
else begin
+ D; ^/ a7 b, a$ L curr_state <= next_state;, \- |3 d8 i! |0 k& U J1 u" r
$ n& X- i- O- A
case (next_state)9 ?' M( K3 l; D, n+ ^
IDLE : z_o <= 1'b0;
; y1 y( P8 u( V7 Y S0 : z_o <= 1'b0;8 Q' c) F& E; j
S1 : z_o <= 1'b1;: w C4 D. |5 Q5 J8 ?
default : z_o <= 1'b0;
3 C. R$ o/ \9 P; X: v8 L endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
1 K; u) A: l0 J3 s8 t* K x
6 L, g: S! ^# }) ~: G將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]& \; d! H2 V# Y0 B7 |( c
// next state logic
( {6 v6 r# H1 V; U$ n5 b/ \! Ealways@(*)9 ]$ U5 g7 l9 P m
case (curr_state)
) Y2 w) f9 a/ n3 T" b: r IDLE : if (w_i) next_state = S0;, P b8 G+ i/ O4 D1 w a" _
else next_state = IDLE;9 U' c* @& I% U! r0 u
S0 : if (w_i) next_state = S1;# j# I1 W% \0 Z7 E7 Y; h ?8 n
else next_state = IDLE;8 U1 t: w1 M a" Y
S1 : if (w_i) next_state = S1;
# N8 C/ y) G- {3 }$ D else next_state = IDLE;
; Y+ ?: \# p( H/ e7 ?' u- E5 f- a default : next_state = IDLE;
% z" x- {( g8 r9 r! [% i( F& [, u endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
h3 o% Q' ?3 N: v3 }( x/ N3 [& ^, S% Z) A; r0 X. M; ^
使用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 Z5 f7 C% J! m
不推薦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]
1 n! W, F6 O2 u( L5 S 1 /*
, v1 y; G. ~! b6 s; S5 g0 i) I 2 (C) OOMusou 2011 http://oomusou.cnblogs.com9 d( R! y. o; ^. L% c2 S, s
3 |5 @5 o1 E' g* ~# a4 O, J
4 Filename : simple_fsm_moore_2_always_2_ns_ol_ng.v4 i+ }& k$ l G- [4 T. C) `( L
5 Synthesizer : Quartus II 8.18 h! ~4 ]: ?; F9 }6 @2 x
6 Description : 2 always block for moore fsm (NO GOOD)
" D Y" i7 |4 G+ V! C 7 Release : Jun.05,2011 1.0
1 A: l$ q0 L; K' L: H8 W F 8 */
9 r- {2 c# L4 { 9
, u' ?/ R: j3 }4 V6 B t10 module simple_fsm (
. N1 x& `/ X( l! |$ r11 clk,+ c; C# N2 c( F' i4 T5 |
12 rst_n,
/ \0 f! [1 J1 N- m% K/ ?13 w_i,, I: G: V4 _; s4 U
14 z_o1 K# D; z( R6 q& \5 S5 b( x! T! e9 [
15 );
6 `8 l% v& _' L5 T- e16 9 w+ i( ?& \, |: G7 e* d
17 input clk;
4 o% c0 J4 j1 q6 i, I+ A5 z18 input rst_n;
" g2 E8 q% P- R19 input w_i;
! Z; G" T& |% I5 E/ x20 output z_o;' B5 |( f, U: I @
21
3 ?. Q; a# [! c22 parameter IDLE = 2'b00;' U! e* s: ]. g& P/ B& D. z. L
23 parameter S0 = 2'b01;1 w6 p2 \' B, U2 X4 D* ^# d5 @
24 parameter S1 = 2'b10;& r. }, l |9 g& g6 Z; }
25 6 E1 l) d% x! N c4 j2 A# r) |2 [
26 reg [1:0] curr_state;
# `0 U3 f9 m5 k' S27 reg [1:0] next_state;
& a) P2 C* B6 H2 F" ?: e28 reg z_o;6 U6 A) A/ F; E% W+ t. k
29
0 u+ a; b% @& @, H! g# T! r8 j30 // state reg
4 f4 d- e8 w$ o4 r' M31 always@(posedge clk or negedge rst_n)
8 ?& n5 b' i* d5 |& B$ ]7 x& m32 if (~rst_n) curr_state <= IDLE;
8 c" z3 C' I) x! g4 G0 J1 S33 else curr_state <= next_state;
. }" S8 n; p7 n5 y34
# ]1 A5 |9 L& `0 m35 // next state logic + output logic
- y; T8 F* \# g4 C8 b1 F36 always@(*)4 [% E$ a9 x0 l, t, _
37 case (curr_state)
1 v; D0 y+ e) N8 I ^38 IDLE : if (w_i) {next_state, z_o} = {S0 , 1'b0};8 a( Z+ T8 ?0 n0 t; L7 O; X
39 else {next_state, z_o} = {IDLE, 1'b0};
* w \4 c, \, j6 D( F4 O8 \8 ]7 l5 M40 S0 : if (w_i) {next_state, z_o} = {S1 , 1'b0};0 J% q9 U$ w9 W Y( ^7 B
41 else {next_state, z_o} = {IDLE, 1'b0};' r" M$ s* `- t" }' J; q2 X
42 S1 : if (w_i) {next_state, z_o} = {S1 , 1'b1}; // always output 1'b1
5 p# C' M( f. h% \6 K: ~43 else {next_state, z_o} = {IDLE, 1'b1}; // always output 1'b1# H- _. n1 r8 C0 q* ~
44 default : {next_state, z_o} = {IDLE, 1'b0};( o' N m+ U! `+ m
45 endcase
+ I, @/ L( v- O3 F4 b& R46 * Y& t- Z3 p: W( D
47 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url] ^4 D w8 {3 `8 i& h
4 z; s8 J1 ^$ A% a30行 // state reg
) P2 d! w1 F' t9 r( {2 O- salways@(posedge clk or negedge rst_n)
( q* X7 P7 m+ F# [! ` if (~rst_n) curr_state <= IDLE;& L7 c/ P" y! I: {" A% p- o) w
else curr_state <= next_state;& s" R7 z: @$ z, C) K" w
使用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]
8 F8 p) }3 a0 J' d// next state logic + output logic . j$ Z) i1 G {/ i- V) H
always@(*)
8 O4 Q& F2 l- C% B9 S case (curr_state)1 j5 k: `6 o% f7 I& w& p
IDLE : if (w_i) {next_state, z_o} = {S0 , 1'b0};2 `3 u: }- `) M, V. ~
else {next_state, z_o} = {IDLE, 1'b0};
' U- b6 _8 c& D0 Y, ]* u. D S0 : if (w_i) {next_state, z_o} = {S1 , 1'b0};
% `& I. J3 [0 n2 k0 |. P else {next_state, z_o} = {IDLE, 1'b0};! w. z+ \1 d/ U X3 p
S1 : if (w_i) {next_state, z_o} = {S1 , 1'b1}; // always output 1'b1
; x: X- F0 O. J1 Q. m0 m% u else {next_state, z_o} = {IDLE, 1'b1}; // always output 1'b1
. \! ^6 ?, a; ^ u! d/ S1 E default : {next_state, z_o} = {IDLE, 1'b0};9 H: r; L) c5 ? C: @; k- i5 }( H/ D
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]" K2 I- ^" g$ }2 E5 x2 f/ W1 H
8 B! o$ P, o( W3 }: D# O將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的複雜度,日後維護會更加困難7 v8 w6 P4 E" J6 l, o: B
2.很類似Mealy FSM寫法,容易讓人誤以為是Mealy FSM# A7 M7 j+ V0 X0 s5 r3 v
不推薦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]9 ?! {4 X) j* ^# D" x, p
1 /* 1 i: Q: P6 M3 j) b* O: ^0 S
2 (C) OOMusou 2011 http://oomusou.cnblogs.com% r( h$ W0 t: i, E0 i
3
/ |3 o" V# N- \ 4 Filename : simple_fsm_moore_1_always_ng.v0 [9 R H( L/ T3 x9 s+ h
5 Synthesizer : Quartus II 8.18 C/ S- H5 o* K x+ E6 |8 s! b
6 Description : 1 always block for moore fsm (NO GOOD)! M9 f& h3 }+ N0 S" w; w' {$ L
7 Release : Jun.05,2011 1.01 x5 U' G/ T8 X! b' H0 a L! t
8 */; i9 \$ @! L+ B7 J i
9
3 I' G" ^/ K- ?. D' C) \7 ^4 m10 module simple_fsm (
8 A3 A, d4 l% g7 A7 x11 clk,( t& v2 P: Z( o# c# {1 t( H. A0 q
12 rst_n,
& W" J- S5 C9 b" b1 d9 O13 w_i,
8 U; m; z. L1 ]1 a14 z_o2 k$ S& q; [& _. X& Q- V# U
15 );6 l$ m0 ?) R1 y4 g4 L" B& @! _
16 / x/ p2 k3 D9 A" m4 L
17 input clk;7 C7 U9 a1 l' Z9 q' q2 e
18 input rst_n;
. l S0 e2 g. f" ^19 input w_i;3 L1 A2 M' X0 s
20 output z_o;
) ^5 f# @8 e1 G& |9 |8 X21 5 _% H5 s. H# `
22 parameter IDLE = 2'b00;. c9 t C. Q( T- N0 u8 D- W
23 parameter S0 = 2'b01;
, Y; t. e9 L8 \9 b0 j5 C7 x" @24 parameter S1 = 2'b10;
5 J6 A$ ]/ g; f# m" R' U25
2 G+ m. ~$ i) _# y" H# b26 reg [1:0] curr_state;
' D7 a" B1 {8 j0 ~9 l27 reg z_o;7 J. ], C; ?3 T" U9 L8 ?/ ?* L
28 & V; A5 W1 k+ Y8 z
29 always@(posedge clk or negedge rst_n), @4 C, B1 M! }- v. o* G2 `
30 if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};# |7 I3 d0 R) U" U( N) \% O
31 else
! c, _; Q. C$ \32 case (curr_state)
6 ~5 m( b& d. Q2 v# Z. ]( x33 IDLE : if (w_i) {curr_state, z_o} <= {S0, 1'b0};
: k P& Y4 z1 u( H1 h3 W4 O c% V34 else {curr_state, z_o} <= {IDLE, 1'b0};8 N7 X: b+ |$ A! d. @' V9 U
35 S0 : if (w_i) {curr_state, z_o} <= {S1, 1'b1}; //?
# _: ~/ L4 I, f36 else {curr_state, z_o} <= {IDLE, 1'b0};
3 P9 M% t5 l/ ~, b37 S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};3 F: O; T8 g! [& i* v) d' W8 J5 t
38 else {curr_state, z_o} <= {IDLE, 1'b0}; //?6 E4 S4 ~$ w$ a& W
39 default : {curr_state, z_o} <= {IDLE, 1'b0};
5 G5 z# ~" w, E; q7 U, ^40 endcase7 _" c9 F! J8 k% A* R, |
41
% w8 Q- f* |5 Z. X0 t! M* [42 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
( o9 w3 I% H/ n
, }3 o6 P1 W+ @! m9 p29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]9 }# I! g# v" D& k+ B
always@(posedge clk or negedge rst_n)7 B7 d; M, k! j& Z
if (~rst_n) {curr_state, z_o} <= {IDLE, 1'b0};" f$ [5 k3 N" d0 h4 g
else2 F4 a: f* d- b, i% c
case (curr_state)2 y$ p( `1 ] R' p" _
IDLE : if (w_i) {curr_state, z_o} <= {S0, 1'b0};
) ]) d: V5 ?/ Y/ U" J4 [2 C else {curr_state, z_o} <= {IDLE, 1'b0};
1 u5 Z! T1 n/ N4 x- L S0 : if (w_i) {curr_state, z_o} <= {S1, 1'b1}; //?
" q" ?% O9 s1 N else {curr_state, z_o} <= {IDLE, 1'b0};
$ q/ D/ P, c' D5 X5 p2 ^ S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};
4 U- V- Y7 Z6 T4 W: N* V. Y! Z else {curr_state, z_o} <= {IDLE, 1'b0}; //?7 l; U7 t/ i$ D
default : {curr_state, z_o} <= {IDLE, 1'b0};' q5 M* h7 w+ ~4 F: i3 R
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
2 T( {7 ?. {5 c% E- i. p( i, [2 _5 x2 [ @
使用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};) c9 l5 ^9 H5 u* ^& \0 |
當目前state為S0且輸入為1'b1時,output必須提前為1,因為這是在nonblocking內!! 37行 S1 : if (w_i) {curr_state, z_o} <= {S1, 1'b1};( X7 E. E, P) V) j) B
同理,在目前state為S1且輸入為1'b1時,output也必須提前為1,也因為這是在nonblocking內!! 使用1個always寫法的缺點: 1.因為使用nonblocking去描述output logic,所以要提早1個clk判斷,要特別小心處理,一不小心很容易弄錯; C8 q f1 f1 G5 P' [/ c% n$ x+ J
2.1個always內同時包含next state logic與output logic,會增加code的複雜度,日後維護更加困難, B& ~0 t: r7 u }' x' y
不推薦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]8 e( a4 s1 q4 [; h0 a% M% l- z
1 /*
0 Q {# n4 w% k# K! m1 x' C$ G 2 (C) OOMusou 2011 http://oomusou.cnblogs.com
% S. Y5 t' q" z5 P$ | 3
3 j1 ^5 Y- Y! D# `( N 4 Filename : simple_fsm_mealy_3_always_best.v
1 E5 x# l9 R3 T2 y+ z$ W 5 Synthesizer : Quartus II 8.1; M5 a, ]! ?* s+ A& N& a
6 Description : 3 always block for mealy fsm (BEST)8 [& m' t4 j7 d$ ]! @2 X7 Z" M! s
7 Release : Jun.05,2011 1.0
n. u8 V+ N" [) o 8 */
% E5 t1 v' u, P9 M! R 9 ; i3 \ k" d! M# B8 ^) B. k
10 module simple_fsm (2 U6 i! x0 A8 R( o
11 clk,4 Y3 \5 V3 j5 V9 A8 r
12 rst_n,4 F3 W* X, `. c1 Q
13 w_i,
: }# T! W/ l2 y& j8 N; F14 z_o
9 }: B$ ^, u7 ]' H# B15 );
; l: k( X% e4 y16
1 A+ K! ]4 M" N* z. J4 S/ r17 input clk;8 o$ x! x4 S. T" t
18 input rst_n;, y3 ^3 Q2 {* a% c# a
19 input w_i;8 ~7 }3 ~1 C% Q8 W/ p6 w
20 output z_o;/ {# J- p! M: B: L+ P
21
6 b. H" k4 }& w! @- U22 parameter IDLE = 2'b00;. }4 I( a: E* s/ W9 k9 A, G
23 parameter S0 = 2'b01;
x* d8 d: K7 j J; D' x24
$ [* l, @( W6 |( @! k25 reg [1:0] curr_state;
& {: k8 `. Z: ^% u* ]1 L26 reg [1:0] next_state;: B1 i- u( L: Y' i* ~9 g4 j
27 reg z;8 J9 V. y% A4 [$ o3 P
28 reg z_o;7 d+ A/ ]% `# }) Y0 \ b f
29 7 v. E7 o5 I/ m
30 // state reg y+ B$ h; r, z7 U
31 always@(posedge clk or negedge rst_n)
2 w' U: y$ Z8 o1 W) ] k- w3 [32 if (~rst_n) curr_state <= IDLE;
6 N7 s% y' H, \! X" r" @$ K33 else curr_state <= next_state;
6 W9 Q/ s3 T) [: F( f7 {34
9 a) t* \* l Q! h+ k35 // next state logic
+ i% P% b+ [0 h% }36 always@(*)
( ~/ {. Y* p& f9 I; Q: d37 case (curr_state) L6 O/ i k7 `2 x4 M4 z. E
38 IDLE : if (w_i) next_state = S0;
( K7 b3 L5 l9 M: x+ w" U8 c39 else next_state = IDLE;
; R+ ?3 m0 L+ o4 N- ^% ~& R40 S0 : if (w_i) next_state = S0;
: v7 @) l' u1 r8 L41 else next_state = IDLE;
8 Q9 B9 {. D( D) a- D9 D+ ~& L- [# [42 default : next_state = IDLE;
# V( F; S1 F6 J: D3 X43 endcase . a0 c3 _$ n6 ]" r, S) T! X
44 g# P) `. `7 w; P9 v$ S% w
45 // output logic
; E" L/ i* x4 t1 C4 c* ^46 always@(*)
. ]8 L1 {) y$ `4 `47 case (curr_state)
3 e' D( L0 b* k+ ^% N5 x48 IDLE : if (w_i) z = 1'b0;
/ b" O4 S p5 _- k" Y2 G; J! C49 else z = 1'b0; # f- y7 i* ~( w' ^& W1 }
50 S0 : if (w_i) z = 1'b1;* u' O2 j- t) p- K2 l% X
51 else z = 1'b0;
+ J5 |8 `* K5 ?. o4 ~52 default : z = 1'b0;
( m) X9 D& V0 B. O( H# t6 W53 endcase! z$ u8 H+ B% {: |5 j% T6 o% |
54 , b h _5 w6 E
55 // mealy output to delay 1 clk for moore 2 M3 c& ]( ~ f! L( E+ _+ P% X
56 always@(posedge clk or negedge rst_n)
$ f) @9 h1 Z. R# m1 N! c57 if (~rst_n) z_o <= 1'b0;
; p4 N- J- s0 Y: g9 U58 else z_o <= z;6 r4 v# l N8 z# H
59 6 Y4 l3 i2 A, x5 {
60 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]# e9 W1 v# L% `, r
7 k( R) {8 V5 U: V9 y8 Q. V30行 // state reg
7 a* }4 P' b" ralways@(posedge clk or negedge rst_n)
! j- F$ ]3 ]) M3 E) T& `6 D if (~rst_n) curr_state <= IDLE;
6 Y5 a: f9 M! G t( H5 e else curr_state <= next_state;3 b4 A- C: D9 ~0 ^, A# h4 O3 N+ U3 E
使用1個always描述state register。 35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]- f) c; ~8 k Z. q1 e7 t; y, f U4 j9 t, }
// next state logic
: Q4 C: o+ G8 V0 jalways@(*)
0 t1 k# D. d) b$ R& j( m case (curr_state)
$ M4 v/ F8 w) z. I7 i& n% o" }& g IDLE : if (w_i) next_state = S0;: I8 A# z) E$ M1 L0 o$ z. y
else next_state = IDLE;
/ E& b! [) {4 v# U7 }% M S0 : if (w_i) next_state = S0;' l g! p" d' Z9 Y4 ~) _
else next_state = IDLE;
' C0 G% [1 {4 e g default : next_state = IDLE;* B3 [! f7 F/ }* i$ I7 ?
endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
2 t2 m3 k; ^2 {. Q# l# m9 ]) ~3 h3 o' F6 d, @* V0 e% i& h
使用1個always描述next state logic。 45行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]1 v: ]) t# v8 C$ Z8 |
// output logic
9 C/ N6 u5 t! ?6 ], talways@(*)
0 S1 l' Q, U$ G; e( Q case (curr_state)/ @3 Y) H0 R+ _; O$ a/ z
IDLE : if (w_i) z = 1'b0;
% ?$ \- P n8 L# s else z = 1'b0;
2 ^9 S: e- G! w# z/ [ S0 : if (w_i) z = 1'b1;
]0 z# Z6 W k7 Q else z = 1'b0;" q9 O$ |# ]& G( q2 \1 n
default : z = 1'b0;& B% u$ g2 t' \$ X
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
; N( v2 {; _& Z
. i; w3 y( m- v v. ^使用1個always描述output logic。 以上3個always寫法與Moore FSM的3個always並無差異,基本上只要state diagram畫的出來,就能等效地用Verilog描述出來。 55行 // mealy output to delay 1 clk for moore 6 |3 t5 B2 \: b1 Q5 U& U# F% U
always@(posedge clk or negedge rst_n)
& k9 R4 M! C" L( T! |9 n if (~rst_n) z_o <= 1'b0;# |5 w5 v8 Z( n1 m, j$ j. E
else z_o <= z;' M% A" ^. f; r- 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硬體架構
; K) i: F- \# ]9 r `2.可輕易地將state diagram改用Verilog表示! Y3 i3 _$ R1 ~. v
3.將Next state logic與output logic分開,可降低code的複雜度,便於日後維護# z& G0 r j' ~ W8 }
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]
* i& F% r* _& R6 [1 Z 1 /* 0 @+ E9 X) {6 X& V) O/ ]7 a
2 (C) OOMusou 2011 http://oomusou.cnblogs.com8 v) \& X3 E) M" ?
3 ; {- D0 q( q9 u
4 Filename : simple_fsm_mealy_2_always_0_cs_ns_good.v s" I0 a' _. w& O# ? O' E
5 Synthesizer : Quartus II 8.1
8 t2 s' a [% w. ~( F6 z1 | 6 Description : 2 always block for mealy fsm (GOOD)
R9 p9 z* U4 V$ k5 q 7 Release : Jun.05,2011 1.0
$ S6 j: v, e& A' V: ~! z% Z 8 */
1 X3 ?& k$ ~" o# |7 V2 ~ 9
9 |" Q* N) F& D6 k10 module simple_fsm (
# z) X% B+ X! x/ M+ C$ e11 clk,
* F+ N6 W N/ K12 rst_n,
: M2 ^% G4 E' N3 V13 w_i,- ^9 o2 E- Q3 M8 ]
14 z_o
0 }& l- O: d" K! `# [) z15 );
9 e8 c, h! x* W. W* o16 ) o- y v" o" j+ H) k7 |0 Y
17 input clk;# r9 b$ u, {! A/ O: \' ?' c' r
18 input rst_n;7 X* N1 u" p3 `% ^+ U% k
19 input w_i;
3 Y5 k& v9 j" e2 _# a- q6 D20 output z_o;. x' C, x. L* z: ?. I
21
5 o/ @& I0 `7 U$ q& D22 parameter IDLE = 2'b00;8 ]4 P2 {6 E( q: j7 t" m. u
23 parameter S0 = 2'b01;% |# z* _5 H- x- j, G
24 ' }' f- Y6 t% V6 I1 M' K
25 reg [1:0] curr_state;
! u9 ]6 V, K7 P4 v. ?: R! r: h/ k26 reg z;
3 l6 R2 f7 J4 N1 X4 P27 reg z_o; u6 x1 o9 U7 x% S6 H- k: o
28 . L p1 O5 D. H' i
29 // state reg + next state logic
: z, Z% O3 F1 Y+ `7 U, o30 always@(posedge clk or negedge rst_n)
. q! }4 h2 \6 U0 y31 if (~rst_n) curr_state <= IDLE;
; e, z9 S" L8 e9 w/ ?32 else- |" b9 i! |3 Z9 \- ?
33 case (curr_state)
# y9 {; f2 R4 ~7 ]* ^# |34 IDLE : if (w_i) curr_state <= S0;
7 x/ V3 |/ N# @+ {& E; A8 C% s35 else curr_state <= IDLE;
8 h( J+ U& z, ]+ h+ L }) S36 S0 : if (w_i) curr_state <= S0;
6 |0 M* M7 ]0 K% Q% _37 else curr_state <= IDLE;
( Z) @4 `* V- k4 O2 w- O38 default : curr_state <= IDLE;
7 J# V4 ?/ g1 {9 J39 endcase
/ O6 ]/ B) f2 O7 @2 D9 M40 * |3 G2 t% O. K# j! U7 }) w
41 // output logic
0 b3 Q }% o* h0 X/ x42 always@(*)
* `; P7 p+ b, A, s/ h+ ]43 case (curr_state)
9 E6 Q1 I* B* ^. G+ S: }44 IDLE : if (w_i) z = 1'b0;3 a2 W: b" N8 c9 Z
45 else z = 1'b0;8 ]5 q+ X9 I# `2 W: J; n- V2 d+ j
46 S0 : if (w_i) z = 1'b1;) e4 h; [4 h9 |% A: f! a
47 else z = 1'b0;& F8 P8 ^; n6 }0 A [3 B, b) C1 _
48 default : z = 1'b0;# i- f4 k! Q* c1 a% L F
49 endcase
+ `4 O3 ?7 f" T6 u50 4 x) X7 k" _' P# u5 V/ _+ X' `0 d
51 // mealy output to delay 1 clk for moore p% m2 L5 e" s) }; e* j
52 always@(posedge clk or negedge rst_n)
7 f& f% {& k, Z' S53 if (~rst_n) z_o <= 1'b0;
& M! n- Z# ^! r7 W9 I54 else z_o <= z;
3 [5 _6 |" X( ]2 p8 C0 {55
& s# c, T. k6 M C( { ^ D0 i56 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]! b/ Q; G) |8 Q( h& S; H" T
1 Z- a2 p u6 _& b# B29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]- `# k" z C3 x" _4 T; G
// state reg + next state logic
1 L2 ~) O8 q/ d8 o* d3 K( Nalways@(posedge clk or negedge rst_n)" X( }: q: R$ R, e9 [, S* \ |( `
if (~rst_n) curr_state <= IDLE;& R8 o) g, j8 o3 r' a ~" c0 C
else
" y$ @( o( A4 ?3 f case (curr_state)
, a0 p8 S, U* S% d# e b; k IDLE : if (w_i) curr_state <= S0;$ A' s7 Q) [5 J8 B" M
else curr_state <= IDLE;" o1 q1 m/ G0 d
S0 : if (w_i) curr_state <= S0;* j# g2 R: W+ ]3 \+ }8 F1 P# E
else curr_state <= IDLE;2 }, B# \9 i" W7 x! q
default : curr_state <= IDLE;- ]8 w" K& R4 }
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url], ]7 R; ?( r& E; ~' \
0 I4 g3 y8 r4 ~( M2 @: [' c& S# S! f使用1個always同時描述state register與next state logic。 41行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
. `9 U2 y. f) t* M// output logic
! ^# D5 m5 x8 w# g! E1 l2 ealways@(*)- m& d a$ N: G8 b6 s x2 c6 ]
case (curr_state)4 d5 \1 [4 t4 `9 H# ]% j) c: b
IDLE : if (w_i) z = 1'b0;
. }2 D& n) u" v0 r$ \9 m else z = 1'b0;
7 G$ U% c9 d/ V% J3 W S0 : if (w_i) z = 1'b1;
: T% e- g5 s g% S* w else z = 1'b0;
2 l: ^' f! h; Q8 ^ default : z = 1'b0;0 k; W+ q3 M }' g3 z3 T" F
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]0 k+ \! X, z, n O; N. d9 w8 z
: t( P; p# ^1 Q: U& c3 s" h# X使用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
" l- L" {" u' A5 lalways@(posedge clk or negedge rst_n)
+ |$ W9 e* `" ]6 K3 m if (~rst_n) z_o <= 1'b0;
: X2 i/ w* t! }" Z else z_o <= z;
4 l7 l8 Y. s6 H; |5 T. D之前提到使用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寫法精簡) z8 w& b, N4 R- P9 ?: A8 n
2.可輕易地將state diagram改用Verilog表示3 O( j- _: K* f8 }" m1 s2 j1 F
3.因為state register原本程式碼就不多,將next state logic與state register合一後,next state logic仍與output logic分開,因此不會增加code的複雜度,便於日後維護
( O2 o# {7 M6 v* a! c2個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]+ E# x% M( u% J/ o% H; A8 T
1 /* / \$ W' o8 a! H& `* o4 J4 r3 w# M
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
( E" n, O: I- l 3 5 v/ a% \# J+ a1 C) A. S/ ]
4 Filename : simple_fsm_mealy_2_always_2_ns_ol_ng.v
* C% }$ _9 ]" g6 ^& U" k% A 5 Synthesizer : Quartus II 8.1
8 u. I1 F8 h/ ~3 m; n7 Y; ] 6 Description : 2 always block for mealy fsm (NO GOOD)1 O7 k/ Z! H! N4 W( Y
7 Release : Jun.05,2011 1.03 t3 d- ]4 z4 X3 `: Y
8 */
7 U) L' S) K0 }5 }+ _& l: S 9 $ U3 V& p) x% y, K+ A4 T
10 module simple_fsm ($ M- B6 v/ e2 Y* n8 P+ E
11 clk,
4 p( r2 E" i9 ~) C" I9 O0 f) F12 rst_n,
7 z( D- L( b! J% q1 P13 w_i,# G- O/ ?7 y7 @& ]% Y G4 A
14 z_o4 U6 X( K9 V3 X0 R5 B
15 );, o( H0 g- B3 q6 a: R
16
' [' f: e$ l$ e17 input clk;; C2 D. Q+ [6 ?
18 input rst_n;! Q; G+ u/ _/ K& s
19 input w_i;- n" ]5 x* s, B. D3 b0 V0 {
20 output z_o;: L0 {( T8 h9 H: `
21
8 S6 k, U& } u- _& U5 {22 parameter IDLE = 2'b00;7 k0 U- m5 U( c$ P4 V$ T
23 parameter S0 = 2'b01;
( P) l* Q$ x, t7 K$ r1 ~24 * j8 L1 L- |7 O% M4 }5 w
25 reg [1:0] curr_state;
& `( B1 C- p9 f$ ?: D7 {6 D26 reg [1:0] next_state;
& G' }$ I; L6 {! G2 ~27 reg z;& q, T; }( U+ G% Q) b
28 reg z_o;' B/ I& G1 y Z8 f
29 ) j! N& O- g: ~- K) |0 ?7 t4 {
30 // state reg1 ?5 x9 D& B( Q
31 always@(posedge clk or negedge rst_n): }; |# t# G8 M+ }' P0 p
32 if (~rst_n) curr_state <= IDLE;
5 ?2 P9 q. ~- \8 A0 E' [$ n: e33 else curr_state <= next_state;
/ n S {; a1 b$ a. j- ^34 . n# ?* f+ i# g1 \/ h
35 // next state logic + output logic
8 G. n" h- \3 g1 {8 |( K36 always@(*)! V# G3 }! J8 h6 _* Q; ]
37 case (curr_state)" E: L" D: R( u: `/ K# ]( k7 C7 M
38 IDLE : if (w_i) {next_state, z} = {S0 , 1'b0};
/ q' X; f2 O% B0 l1 n) {" `0 P- ]39 else {next_state, z} = {IDLE, 1'b0};
/ j2 Y) W; Z" f, ?& o7 x40 S0 : if (w_i) {next_state, z} = {S0 , 1'b1};- w6 _, J4 Y8 g, r
41 else {next_state, z} = {IDLE, 1'b0};: i' c8 |$ l" f; f/ N8 i4 G
42 default : {next_state, z} = {IDLE, 1'b0};- }5 E* X; [: p5 X2 f2 _7 F
43 endcase
5 p+ m. g: r7 H- y2 x* l' b) I44
: m; }: @5 @" v3 Y9 [/ t0 @" P45 // mealy output to delay 1 clk for moore 8 _, E) z' ^2 p) p, o N( H9 `
46 always@(posedge clk or negedge rst_n)
5 ?' R8 _# {# [; Y9 x% j6 N. w47 if (~rst_n) z_o <= 1'b0;
6 }* F- Z$ F. P0 }48 else z_o <= z;# q2 ^2 ?7 t% e5 n9 O
49 0 V5 q6 M6 |* B/ x& O/ B, J' \* N* a
50 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]
( {/ ~% E1 \" h- Q# H# F
; d9 w, ^: ^# i) q: W30行 // state reg
% r" K7 R n0 P9 z4 `, @9 y, yalways@(posedge clk or negedge rst_n)6 d U" r- m8 N
if (~rst_n) curr_state <= IDLE;( B! R: @' Q- b
else curr_state <= next_state;9 S) {( ~" j3 {1 t O1 ^9 n7 F# X6 R! ?. @
使用1個always描述state register。 35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
7 ?" G5 x% e& r4 b# {// next state logic + output logic & B3 K1 `5 w! J8 E3 v6 i* X
always@(*); ^ I. a {9 ^- `7 Q
case (curr_state)1 M3 j+ G1 s( y2 j9 V
IDLE : if (w_i) {next_state, z} = {S0 , 1'b0};
/ T t4 Z" P6 W else {next_state, z} = {IDLE, 1'b0};0 C% n2 W+ b2 {' ]) d* ^# K, \
S0 : if (w_i) {next_state, z} = {S0 , 1'b1};
2 Q& s, }% I/ q7 G6 C; E else {next_state, z} = {IDLE, 1'b0}; F7 | r* a# @. o8 ~3 B0 j, x- r
default : {next_state, z} = {IDLE, 1'b0};1 F7 C! U: K) F/ e" y
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
# k B5 k. i2 P# ?; W! r. E8 z& X
0 ]( B3 p7 u8 U$ t使用1個always同時描述next state logic與output logic,因為兩者都是純粹的組合邏輯,所以使用blocking。 45行 // mealy output to delay 1 clk for moore . H5 ?$ [9 [2 C* L6 a+ n1 w' `5 \
always@(posedge clk or negedge rst_n)9 }9 k. h* K& @% B J6 u! T; Y6 |
if (~rst_n) z_o <= 1'b0;; v6 L- T) n. ]
else z_o <= z;1 ^/ @5 T* I% z9 K ~
之前提到使用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的複雜度,日後維護會更加困難
/ }0 a$ G( f- H" s不推薦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。
) S9 F Q2 F. _& b6 s/ c實務上推薦的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]7 S( Z0 z. V" b1 F4 k* ^0 a
1 /*
9 ]$ h" ]4 i! Y9 u$ f8 n 2 (C) OOMusou 2011 http://oomusou.cnblogs.com# h7 e; K' }8 r8 I
3 0 R3 ]* r+ c, |5 \+ Z2 m4 @
4 Filename : simple_fsm_moore_2_always_0_cs_ns_good.v* J& W' q/ E! U" i/ E Z$ H
5 Synthesizer : Quartus II 8.1
& r7 v9 u# Q* e 6 Description : 2 always block for moore fsm (GOOD)1 }! p0 S( O! b
7 Release : Jun.05,2011 1.05 Y; n l% Q8 @% Q, Y
8 */
3 ~" F% Z9 E. G: h 9
U& `. s$ u( C: g* @; J- _10 module simple_fsm ($ t' R3 }$ Q% C+ i) k
11 clk,9 P6 y6 N! r2 ^" `
12 rst_n,; m, a& ]5 Q$ a M: g
13 w_i,9 P( y! _$ s' T# ?
14 z_o
: k( l) R# j2 r$ Y15 );
( z u$ @2 G2 \! d3 t8 H1 t16 4 _+ I! v+ c1 h! s
17 input clk;# g+ n6 n2 h* z
18 input rst_n;) [7 q0 W' H; K7 h6 J: b+ ^
19 input w_i;7 E6 [0 e* ^: M/ \ K) j) _
20 output z_o;
% P3 |! O) A8 |# D2 B21 6 [* T( U8 T5 e2 ?
22 parameter IDLE = 2'b00;
8 [% K! O* J0 o& C# r5 D; W23 parameter S0 = 2'b01;
8 R6 b9 U o% D: U$ ? u24 parameter S1 = 2'b10;: ^8 z% O* p: T2 P
25
6 U! } \8 j1 q) a8 X o26 reg [1:0] curr_state;6 g( T( Q1 e5 O8 q
27 reg z_o;
) p1 S8 n: T& L3 V: b28 9 u5 U" W5 F0 r/ K' \+ u
29 // state reg + next state logic
! p# [' ?# u x+ }) B1 p30 always@(posedge clk or negedge rst_n)
# L1 B* w: e6 R( P( z. N) A31 if (~rst_n) curr_state <= IDLE;5 U: \, `# n& t) L: \* R. K6 p( g
32 else u* j/ f& Q3 X [+ z
33 case (curr_state)- R! r2 K7 J) d4 Y$ [1 f8 C7 q
34 IDLE : if (w_i) curr_state <= S0;: t a1 l+ L' _4 G+ ?" M M
35 else curr_state <= IDLE;
, F6 h7 R4 C0 [' o F9 \4 b36 S0 : if (w_i) curr_state <= S1;- t* a5 `# E; _ G" t& g {. B+ z
37 else curr_state <= IDLE;
! }2 I8 C% m7 w0 ]( I" X& G38 S1 : if (w_i) curr_state <= S1;
. C: k( K6 _& C0 ^4 k! I, M39 else curr_state <= IDLE;
2 I8 i) B% Y `# Z/ j3 |4 V40 default : curr_state <= IDLE;$ e C1 j, ^, E: ^" `' X4 x/ f* \
41 endcase
! |$ \) |! s3 v7 T42
. B( x, k0 s# a- I2 L; p" B; J43 // output logic- Z7 P* F3 Q, z+ e1 f1 E/ Q$ l; ?( q
44 always@(posedge clk or negedge rst_n)
# o) ^" z8 w$ C45 if (~rst_n)
' n# G% ^ W1 e- V46 z_o <= 1'b0;
9 \& l" ]+ C" \0 V" A9 g47 else
0 h0 D" G8 M2 \48 case (curr_state)
0 k( R+ T8 X. K1 j: x/ P' }1 d5 @49 IDLE : z_o <= 1'b0;
% C2 ]2 i0 w$ [/ `50 S0 : z_o <= 1'b0;+ m1 @# ]! ~" Q* x+ B
51 S1 : z_o <= 1'b1;0 h* E% I/ q1 Y5 T9 H
52 default : z_o <= 1'b0;
' ]4 [! ^% M( A: O* j# m53 endcase0 ?4 r/ c% N" r+ C: v( J; a+ P
54 ' C4 b: m4 v) y: @( _8 f; k# _
55 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]- [( ^* z" Z! E2 s4 L8 G* g, U& B
/ y+ K3 `* h# e1 U
29行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]+ G- [ u" j* A0 G1 s
// state reg + next state logic
- V, x. I5 H8 X) `& G! G! jalways@(posedge clk or negedge rst_n)
+ D, i7 [' H7 X. z$ D+ |# x if (~rst_n) curr_state <= IDLE;
1 r4 h6 P: d3 D: u9 Q else$ P4 j. m7 s: S% H
case (curr_state)! a, F& d) n; `7 \
IDLE : if (w_i) curr_state <= S0;! O( y" _# V2 w5 B0 S* w! X
else curr_state <= IDLE;
- h) W7 _% q, V. [: j S0 : if (w_i) curr_state <= S1;3 k# ]4 b1 Q, Z, f: z% V
else curr_state <= IDLE;" ~/ a+ T% z8 x6 {
S1 : if (w_i) curr_state <= S1;- p% N' ^) M0 i1 u
else curr_state <= IDLE;
/ _# _$ {1 ~, `5 s! K; V, k default : curr_state <= IDLE;; g+ ^$ v3 C) d# F
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
& C2 L3 ]' X% W4 v/ }/ T Q% L% j. F
使用2個always,且state register與next state logic合一,只要判斷curr_state即可,不用擔心是否要提早1個clk判斷。 43行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
. `# P0 e; N+ a8 }) x// output logic
; R; r' F' }3 Oalways@(posedge clk or negedge rst_n)
$ x, v4 ]$ B) _: c3 [% D if (~rst_n)
. {' h: c$ c, g7 Y2 V0 f# a: c z_o <= 1'b0;
0 v# v3 ?! Z- E/ z. ~1 ~! B1 _& e else0 F, G- f" j) M- Y
case (curr_state)
& Q6 G' s4 E1 B, }2 Y IDLE : z_o <= 1'b0;1 ~' @& k; C3 D7 b4 [2 s& d3 H
S0 : z_o <= 1'b0;
! Q8 b/ P2 p1 j! ~) A4 R" N& K S1 : z_o <= 1'b1;6 J; p% {7 ~/ |& U; o8 r
default : z_o <= 1'b0;& F5 q4 t1 i7 u' }9 Q
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
0 O: ^/ u5 r( [7 k7 P1 _4 G
6 k1 z3 e0 l0 Z7 \* d6 e* M) |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]
F4 S7 m" A- A: I% e7 m7 S/ j 1 /*
0 ~( R" [' b% k5 C0 l 2 (C) OOMusou 2011 http://oomusou.cnblogs.com& z$ M6 N8 i; A! a
3
$ L3 {3 K4 C" r6 @% W- \$ F8 y 4 Filename : simple_fsm_moore_3_always_practical.v/ I7 J% ]& E4 S8 [
5 Synthesizer : Quartus II 8.1
) J9 p# L! y( k 6 Description : 3 always block for moore fsm (BEST). C1 D% h) ^! |( [- K
7 Release : Jun.05,2011 1.09 G- T; L J* m2 O9 ~. b# Y
8 */
4 `8 t6 h" l# q S8 e' b% ~ 9 4 X6 ^$ O% ]2 B; X. ~7 @0 `
10 module simple_fsm (
/ p: N) x$ W$ N. u2 K: X4 [8 t11 clk,
2 @" i7 e1 Q8 t2 {12 rst_n,! u3 t; n7 F; \ W7 C# Y. ]$ i3 w
13 w_i,
" {" M1 c# J( u0 }14 z_o
2 a& \: }+ j! v) x15 );
. a7 W7 z, F! e16 : n0 l- n$ z- L9 G( |, |
17 input clk;
3 ~+ o! ^$ P& x8 |" D3 r18 input rst_n;, q# ^- }- ~6 y- M$ S+ M' c9 X
19 input w_i;. [7 J- u. |, {' l; g
20 output z_o; h( c$ A0 k+ ?' b- f& r) s+ t! z& o
21 7 t( l ?9 A0 C+ U: o/ P2 z& g* o* x' g
22 parameter IDLE = 2'b00;* f( S& g& j& c6 x, N) A- {0 \8 a
23 parameter S0 = 2'b01;
! E: v4 P/ @) O9 }2 Y) a5 ?9 s24 parameter S1 = 2'b10;
' W+ c3 ^) { ?9 |2 r" @1 H25 " L1 L' N# E) U) i
26 reg [1:0] curr_state;
' F( H# C4 Y# Z+ g! \27 reg [1:0] next_state;
% x+ c. A. y2 B8 D3 _- [1 w28 reg z_o;+ Z3 @: o' T4 I, B1 m
29 ; ^/ i. d: E# r- T
30 // state reg5 c9 c/ W$ U$ {3 I5 ^
31 always@(posedge clk or negedge rst_n)- l! J I; f% M3 W2 q) c' z- i, j
32 if (~rst_n) curr_state <= IDLE;( k+ X: N, F o. F. [% t/ v
33 else curr_state <= next_state;6 i0 h2 Z* Q- L
34
9 S/ b9 g, \; j6 o8 B) I e35 // next state logic 3 s* ]- n4 z; @( C- a
36 always@(*)
8 j- R4 b; A0 n( o) E37 case (curr_state)
' `$ ], h( q' N4 b ?+ e38 IDLE : if (w_i) next_state = S0;- b+ ^# R: k! O/ d& U0 U
39 else next_state = IDLE;
9 a8 P1 R, c% e( i$ i5 ^40 S0 : if (w_i) next_state = S1;3 L6 l, K' x q( w8 H
41 else next_state = IDLE;
) V% f6 p/ G( k* B/ }- ?& u42 S1 : if (w_i) next_state = S1;
, b2 I: ~7 p+ V5 l43 else next_state = IDLE;* n3 x' K& b1 s' V" K+ b
44 default : next_state = IDLE;
2 V) n5 |7 h0 s2 }45 endcase 2 l2 Z' `- [ }1 Q" q7 b( Q
46
6 G( h) z9 O3 s- l" s O47 // output logic1 Z. W9 \" ^3 d9 _1 p
48 always@(posedge clk or negedge rst_n), {3 m. n9 |6 f
49 if (~rst_n) z_o <= 1'b0;% c# p; ]. g. {; ]1 `6 D
50 else
( @% y2 p; D$ s7 @/ @ ^. f: E51 case (curr_state)
! G" F/ {( m% n# B* `" n# o52 IDLE : z_o <= 1'b0;
7 L0 x) v& u, g; K. |53 S0 : z_o <= 1'b0;# o4 B9 x/ T" R0 c7 @
54 S1 : z_o <= 1'b1;$ ?: X* K, e$ ?' Z1 Q
55 default : z_o <= 1'b0;3 F# e1 {8 _/ f( V9 k+ A
56 endcase
8 p+ X# M8 X1 u+ W57
; R2 ]- \( |9 n) M- Q0 V0 L58 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]/ C4 P3 z; d5 u. `: ]& A
/ D! A( {$ T, ^
30行 // state reg5 T, a% k( X5 k( D+ F
always@(posedge clk or negedge rst_n)2 S) b) T; s) v
if (~rst_n) curr_state <= IDLE;
# ^: ]5 m8 C, p2 Z else curr_state <= next_state;! a' l. z3 z6 P- [& r. Z, M
使用1個always描述state register。 35行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]) f& p# E- y# r1 o. j7 |
// next state logic / W/ ?$ j6 U1 I+ J: i5 c2 M
always@(*)( {$ A5 r% d( N
case (curr_state)' I: F9 N% x' K
IDLE : if (w_i) next_state = S0;
, S' g% X4 p! n) N( {+ O6 s else next_state = IDLE;
* Z k3 r0 o+ u: H/ }% ^0 D S0 : if (w_i) next_state = S1;
5 I5 w$ O5 H8 G, V( H0 W' D else next_state = IDLE;
9 `8 ~$ m( M& w4 B* M% t! N S1 : if (w_i) next_state = S1;2 m) F) u( _6 i9 g
else next_state = IDLE;" |% X& Z4 y, |$ j* h$ `9 l0 Y z& Y
default : next_state = IDLE;( Y# T* i, l7 @
endcase [url=]http://common.cnblogs.com/images/copycode.gif[/url]
* B3 ?5 d1 ~3 M; A. ~3 k1 m1 m# d7 n$ S# v3 Z8 G
使用1個always描述next state logic,為純粹組合邏輯,所以使用blocking。 47行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
/ n9 ?2 V4 x% E7 h/ O// output logic2 q* `( E3 w* s: X
always@(posedge clk or negedge rst_n)
( _+ y$ I- o& c3 @ O if (~rst_n) z_o <= 1'b0;4 g8 F! g+ `* \ p9 V: i
else
; F6 t7 |; ]) E5 ?' Q1 `, w7 e$ r1 W case (curr_state)0 H2 t5 _4 H& j% m$ m
IDLE : z_o <= 1'b0;
9 E1 H1 e2 m; P1 W6 A- o8 ?4 g S0 : z_o <= 1'b0;
0 M0 A) } [# [) C S1 : z_o <= 1'b1;
4 D$ R" y" a- o4 q% E6 y default : z_o <= 1'b0;, f( {6 V! m% \# a3 x" S
endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]
# L& ~( s; ^4 v( w3 j* f# ~" P. ]) }
+ l" Q' ^' f7 C, v" a使用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]
: u4 G9 M8 x$ A7 D* Q 1 /* ! }- L7 A1 q( ]. [ ?; ^+ R
2 (C) OOMusou 2011 http://oomusou.cnblogs.com: O: C( v. E4 P a
3 6 H) y- a1 b& a: |# }
4 Filename : simple_fsm_moore_3_always_practical2.v
h8 h3 x, ]) c 5 Synthesizer : Quartus II 8.1
1 W1 y! u! y( z' s& i+ B 6 Description : 3 always block for moore fsm (BEST)
) U% v2 |+ o. r# C: H$ V 7 Release : Jun.05,2011 1.05 c; h" q9 U' f0 Y
8 */* {: Z( ?% U( k. N
9 5 R- \% }/ M; J' r; g$ ?1 C8 K
10 module simple_fsm (' ^; ^$ _; d* T1 _2 ]+ Z) C
11 clk,) p4 I3 P: X' Q
12 rst_n,
8 s7 l6 |8 ^( h# s% @' h13 w_i,
# E) J6 k# S1 B' ?14 z_o
& z& D3 [) w0 P" E' H1 W15 );
) J9 |- J* ^: h" I t; ?3 y16
+ R: M- t; u+ E# @2 Y2 H$ D3 ~17 input clk;
& x8 [' N4 K9 k% {18 input rst_n;) V2 i; `. h8 m" m" m/ `; c5 k- S
19 input w_i;
1 U n$ Y. K: r5 O20 output z_o;
W8 p9 V8 z4 I. M' E4 ~9 {21
8 t1 ~' H5 r/ N: J$ ~( {& g2 r22 parameter IDLE = 2'b00;
( N* B' E& O* R5 j# J4 G. c; c23 parameter S0 = 2'b01;3 L# o+ X! d8 J8 U. @! J
24 parameter S1 = 2'b10;: K/ a/ F! W7 t3 V- o
25
$ b- X+ [5 i, ~6 l3 }" a26 reg [1:0] curr_state;( A, t& c3 W9 f J8 P: }1 N
27 reg [1:0] next_state;
( `) J+ P3 r: \9 w5 i3 H# u9 j28 reg z_o;8 h2 _3 j! b7 F3 l! }
29 9 Y% N9 ^, K6 C5 F' n
30 // state reg$ b5 u0 c: z7 O" }( K5 T
31 always@(posedge clk or negedge rst_n)
p# o3 }4 a9 X" U5 w, w32 if (~rst_n) curr_state <= IDLE;8 W6 l) D, S! S- a
33 else curr_state <= next_state;
# i/ s( u/ p& c5 Z4 P3 g34
% P+ Y# H8 Z! Z d$ D% D$ ^35 // next state logic
/ S# k1 O% q6 R8 S0 v# K: y+ T36 always@(*)
3 r, E$ S8 g4 J& R3 a m7 i5 S$ b37 case (curr_state)
8 N# P i0 x) `/ N* E" j38 IDLE : if (w_i) next_state = S0;& m' |3 h" B, H! h6 \& \
39 else next_state = IDLE;
( H, Z0 w7 d! R40 S0 : if (w_i) next_state = S1;
$ R# L5 O: m' h- n6 Q. K41 else next_state = IDLE;
# J: ]+ ~: M$ s9 O" z42 S1 : if (w_i) next_state = S1;
9 t% K, n7 p! a" b. Y. N. m43 else next_state = IDLE;
- D$ u4 v6 J: K2 `' Z5 s7 T. v44 default : next_state = IDLE;
3 i, @" t' v! ?8 N% R9 f9 X45 endcase 6 c- N) M0 C R6 l
46
0 b: W. h4 |: `: L47 // output logic
6 t& l5 _1 b! Q48 always@(posedge clk or negedge rst_n)
( f* E' Y1 ?( d! I* i49 if (~rst_n) z_o <= 1'b0;9 ^ h" o: |7 D7 q# _
50 else
: b& }" R7 P4 h1 U; d; h51 case (next_state): ~0 h' _, Y6 E( \) M+ S% b. X
52 IDLE : z_o <= 1'b0;7 J O2 t" J7 l3 X% R
53 S0 : z_o <= 1'b0;
3 q4 s: g. \8 f! C' c54 S1 : z_o <= 1'b1;
# x" [. ^5 X/ u1 V& \- m: h55 default : z_o <= 1'b0;& q4 c& ^: u$ v
56 endcase8 w' K7 ?6 {) y7 h1 A
57
' ?7 U) ^8 g( s( W9 e( G58 endmodule[url=]http://common.cnblogs.com/images/copycode.gif[/url]3 ^( L8 x( u/ V& y7 Y/ p
8 T5 V" e3 H( W5 j7 X P- B47行 [url=]http://common.cnblogs.com/images/copycode.gif[/url]
1 Y; R" A) @9 E A// output logic
) s0 \/ f2 M8 s, R) C( w2 l9 lalways@(posedge clk or negedge rst_n)
, V: @" W5 X, @! {! |. B/ } if (~rst_n) z_o <= 1'b0;( I0 {* [5 C! V8 e1 _2 S
else 6 J- X. Q1 u! i& G
case (next_state)
5 i; f# _5 D3 s5 ~+ X2 ]0 ~; W IDLE : z_o <= 1'b0;% t- E5 `1 M' A& W3 o @8 p
S0 : z_o <= 1'b0;
0 l7 j: s! }/ T9 F8 R( v, u1 { S1 : z_o <= 1'b1;, E$ y) x" g6 F$ |1 k
default : z_o <= 1'b0;
2 ~; U+ e0 d8 P( N endcase[url=]http://common.cnblogs.com/images/copycode.gif[/url]4 |& K& y6 J3 c! Z! U% {: \# n
+ |6 \4 s. H5 R5 b使用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,很容易出錯,觀念必須非常清楚。 6 R. r8 x6 W# m/ l/ W# }; j
|