來源:http://www.codesoso.net/Record/101092_95120_21.htmlhtml
來源:http://www.cnblogs.com/oomusou/archive/2011/06/05/fsm_coding_style.html架構
Moore FSM架構ide
通常在寫FSM時,會以Moore FSM爲主,因此先討論Moore。由上圖可知,Moore FSM內部由3個block所構成:Next state logic,State register與Output logic。spa
Next state logic:純粹的組合邏輯,以整個module的input與目前的state爲輸入,目的在產生下一個state值存入state register。.net
State register:由D-FF所構成,將Next state logic所產生的state存入register。設計
Output logic:純粹的組合邏輯,根據目前的state產生整個module的output。code
因此能夠發現,整個Moore FSM事實上是由2塊的組合邏輯與1塊D-FF所構成,咱們常聽到所謂的一段式、二段式與三段式FSM,事實上就是由這3個block排列組合而成。htm
Moore FSM各類coding style比較blog
Moore FSM各類coding style比較ip
爲了要實際比較各類coding style,在此舉一個簡單的例子,若input w_i爲連續2個clk爲high,則output會在下1個clk產生週期爲1 T的high pulse,timing diagram以下圖所示。
所以設計了Moore FSM,state diagram如上圖所示,接下來要作的就是用各類coding style來實現這個Moore FSM。
simple_fsm_moore_3_always_best.v / Verilog
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_moore_3_always_best.v 5 Synthesizer : Quartus II 8.1 6 Description : 3 always block for moore fsm (BEST) 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm ( 11 clk, 12 rst_n, 13 w_i, 14 z_o 15 ); 16 17 input clk; 18 input rst_n; 19 input w_i; 20 output z_o; 21 22 parameter IDLE = 2'b00; 23 parameter S0 = 2'b01; 24 parameter S1 = 2'b10; 25 26 reg [1:0] curr_state; 27 reg [1:0] next_state; 28 reg z_o; 29 30 // state reg 31 always@(posedge clk or negedge rst_n) 32 if (~rst_n) curr_state <= IDLE; 33 else curr_state <= next_state; 34 35 // next state logic 36 always@(*) 37 case (curr_state) 38 IDLE : if (w_i) next_state = S0; 39 else next_state = IDLE; 40 S0 : if (w_i) next_state = S1; 41 else next_state = IDLE; 42 S1 : if (w_i) next_state = S1; 43 else next_state = IDLE; 44 default : next_state = IDLE; 45 endcase 46 47 // output logic 48 always@(*) 49 case (curr_state) 50 IDLE : z_o = 1'b0; 51 S0 : z_o = 1'b0; 52 S1 : z_o = 1'b1; 53 default : z_o = 1'b0; 54 endcase 55 56 endmodule
個always是一個推薦的寫法。
Testbench
simple_fsm_tb.v / Verilog
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_tb.v 5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9 6 Description : testbench for FSM 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm_tb; 11 12 reg clk = 1'b1; 13 reg rst_n = 1'b1; 14 reg w_i = 1'b0; 15 wire z_o; 16 17 // clk 18 always #10 clk = ~clk; 19 20 event after_rst; 21 22 // rst_n 23 initial begin 24 #6; // 6ns 25 rst_n = 1'b0; 26 #30; // 36ns 27 rst_n = 1'b1; 28 ->after_rst; 29 end 30 31 // w_i 32 initial begin 33 @(after_rst); 34 repeat(2)@(posedge clk); // 60ns 35 w_i <= 1'b1; 36 @(posedge clk); // 80 ns 37 w_i <= 1'b0; 38 @(posedge clk); // 100 ns 39 w_i <= 1'b1; 40 repeat(2)@(posedge clk); // 140 ns 41 w_i <= 1'b0; 42 @(posedge clk); // 160 ns 43 w_i <= 1'b1; 44 repeat(3)@(posedge clk); // 220 ns 45 w_i <= 1'b0; 46 end 47 48 initial begin 49 $fsdbDumpfile("simple_fsm.fsdb"); 50 $fsdbDumpvars(0, simple_fsm_tb); 51 end 52 53 simple_fsm u_simple_fsm ( 54 .clk (clk), 55 .rst_n (rst_n), 56 .w_i (w_i), 57 .z_o (z_o) 58 ); 59 60 endmodule
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_moore_3_always_best.v 5 Synthesizer : Quartus II 8.1 6 Description : 3 always block for moore fsm (BEST) 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm ( 11 clk, 12 rst_n, 13 w_i, 14 z_o 15 ); 16 17 input clk; 18 input rst_n; 19 input w_i; 20 output z_o; 21 22 parameter IDLE = 2'b00; 23 parameter S0 = 2'b01; 24 parameter S1 = 2'b10; 25 26 reg [1:0] curr_state; 27 reg [1:0] next_state; 28 reg z_o; 29 30 // state reg 31 always@(posedge clk or negedge rst_n) 32 if (~rst_n) curr_state <= IDLE; 33 else curr_state <= next_state; 34 35 // next state logic 36 always@(*) 37 case (curr_state) 38 IDLE : if (w_i) next_state = S0; 39 else next_state = IDLE; 40 S0 : if (w_i) next_state = S1; 41 else next_state = IDLE; 42 S1 : if (w_i) next_state = S1; 43 else next_state = IDLE; 44 default : next_state = IDLE; 45 endcase 46 47 // output logic 48 always@(*) 49 case (curr_state) 50 IDLE : z_o = 1'b0; 51 S0 : z_o = 1'b0; 52 S1 : z_o = 1'b1; 53 default : z_o = 1'b0; 54 endcase 55 56 endmodule
simple_fsm_moore_3_always_best.v / Verilog
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_tb.v 5 Simulator : ModelSim SE 6.3e + Debussy 5.4 v9 6 Description : testbench for FSM 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm_tb; 11 12 reg clk = 1'b1; 13 reg rst_n = 1'b1; 14 reg w_i = 1'b0; 15 wire z_o; 16 17 // clk 18 always #10 clk = ~clk; 19 20 event after_rst; 21 22 // rst_n 23 initial begin 24 #6; // 6ns 25 rst_n = 1'b0; 26 #30; // 36ns 27 rst_n = 1'b1; 28 ->after_rst; 29 end 30 31 // w_i 32 initial begin 33 @(after_rst); 34 repeat(2)@(posedge clk); // 60ns 35 w_i <= 1'b1; 36 @(posedge clk); // 80 ns 37 w_i <= 1'b0; 38 @(posedge clk); // 100 ns 39 w_i <= 1'b1; 40 repeat(2)@(posedge clk); // 140 ns 41 w_i <= 1'b0; 42 @(posedge clk); // 160 ns 43 w_i <= 1'b1; 44 repeat(3)@(posedge clk); // 220 ns 45 w_i <= 1'b0; 46 end 47 48 initial begin 49 $fsdbDumpfile("simple_fsm.fsdb"); 50 $fsdbDumpvars(0, simple_fsm_tb); 51 end 52 53 simple_fsm u_simple_fsm ( 54 .clk (clk), 55 .rst_n (rst_n), 56 .w_i (w_i), 57 .z_o (z_o) 58 ); 59 60 endmodule
1.使用3個always (三段式)
使用1個always描述state register,由於是D-FF且含clk,因此使用nonblocking。
因爲state register區塊並不包含任何邏輯,因此不會由於不一樣FSM而有不一樣寫法,不一樣FSM只會改變next state logic與output logic的寫法。
使用1個always描述output logic,由於是純粹組合邏輯,因此使用blocking。
根據Moore FSM架構圖所示,output logic的結果只與目前state有關,因此只需用case對state作一次分類便可。
使用3個always寫法有幾個優勢:
1.可忠實地反映出本來的Moore FSM硬件架構
2.可輕易地將state diagram改用Verilog表示
3.將Next state logic與output logic分開,可下降code的複雜度,便於往後維護。
Mealy FSM架構
談完了Moore FSM,接下來談Mealy FSM,與Moore FSM的差異只在於Moore FSM的output logic只由目前state決定,可是Mealy FSM可由目前state與input共同決定。
將以前的例子用Mealy FSM從新改寫,本來在Moore FSM下,若input w_i爲連續2個clk爲high,則output會在下1個clk產生週期爲1 T的high pulse,若改用Mealy FSM,則output會提前1個clk出現,以下圖所示。
本來Moore FSM須要3個state,若改用Mealy FSM後,會只剩下2個state,接下來要用各類coding style來實現Mealy FSM。
1.使用3個always (三段式)
simple_fsm_mealy_3_always_best.v / Verilog
以前提到使用Mealy FSM會少Moore FSM 1個state,且output會早Moore FSM 1個clk,因此最後特別將output在敲一級delay 1個clk,這樣Mealy FSM就會徹底與Moore FSM同樣。
使用3個always寫法有幾個優勢:
1.可忠實地反映出本來的Mealy FSM硬件架構
2.可輕易地將state diagram改用Verilog表示
3.將Next state logic與output logic分開,可下降code的複雜度,便於往後維護
1 /* 2 (C) OOMusou 2011 http://oomusou.cnblogs.com 3 4 Filename : simple_fsm_mealy_3_always_best.v 5 Synthesizer : Quartus II 8.1 6 Description : 3 always block for mealy fsm (BEST) 7 Release : Jun.05,2011 1.0 8 */ 9 10 module simple_fsm ( 11 clk, 12 rst_n, 13 w_i, 14 z_o 15 ); 16 17 input clk; 18 input rst_n; 19 input w_i; 20 output z_o; 21 22 parameter IDLE = 2'b00; 23 parameter S0 = 2'b01; 24 25 reg [1:0] curr_state; 26 reg [1:0] next_state; 27 reg z; 28 reg z_o; 29 30 // state reg 31 always@(posedge clk or negedge rst_n) 32 if (~rst_n) curr_state <= IDLE; 33 else curr_state <= next_state; 34 35 // next state logic 36 always@(*) 37 case (curr_state) 38 IDLE : if (w_i) next_state = S0; 39 else next_state = IDLE; 40 S0 : if (w_i) next_state = S0; 41 else next_state = IDLE; 42 default : next_state = IDLE; 43 endcase 44 45 // output logic 46 always@(*) 47 case (curr_state) 48 IDLE : if (w_i) z = 1'b0; 49 else z = 1'b0; 50 S0 : if (w_i) z = 1'b1; 51 else z = 1'b0; 52 default : z = 1'b0; 53 endcase 54 55 // mealy output to delay 1 clk for moore 56 always@(posedge clk or negedge rst_n) 57 if (~rst_n) z_o <= 1'b0; 58 else z_o <= z; 59 60 endmodule
Conclusion
1.3個always與2個always (state register與next state logic合一)是兩種推薦的寫法,並且這兩種寫法不管要描述Moore FSM或者Mealy FSM都沒問題,其餘寫法都不推薦,我的是比較喜歡2個always寫法(state register + next state logic),由於這種寫法最精簡,各類需求均可描述,也不用擔憂是否要提早一個clk判斷,最爲直覺不易錯。
2.實務上不會特別拘泥使用Moore或者Mealy,只要符合需求便可,通常會以Moore FSM爲正宗。
3.實務上爲了timing更好,會在Moore FSM的output logic多敲一級。
4.Mealy會比Moore少1個state,且output會比Moore早1個clk。
5.Moore與Mealy之間能夠互換,只要在Mealy的output多敲一級便可。