三種不同狀態機寫法


一段式狀態機:

復制代碼
 1 reg[3:0]  cs, ns;
 2 always @(posedge clk or negedge rst_n) begin
 3     if (!rst_n) begin
 4         cs    <=  IDLE;
 5         cmd <=  3'b111;
 6     end
 7     else begin
 8         case (cs)
 9             IDLE :   if (wr_req) begin cs <= WR_S1; cmd <= 3'b011; end
10                 else if (rd_req) begin cs <= RD_S1; cmd <= 3'b011; end
11                 else             begin cs <= IDLE;  cmd <= 3'b111; end
12             WR_S1:               begin cs <= WR_S2; cmd <= 3'b101; end
13             WR_S2:               begin cs <= IDLE;  cmd <= 3'b111; end
14             RD_S1:   if (wr_req) begin cs <= WR_S2; cmd <= 3'b101; end
15                      else        begin cs <= RD_S2; cmd <= 3'b110; end
16             RD_S2:   if (wr_req) begin cs <= WR_S1; cmd <= 3'b011; end
17                      else        begin cs <= IDLE;  cmd <= 3'b111; end
18             default :                  cs <= IDLE;
19         endcase
20     end
21 end
復制代碼

兩段式狀態機:

復制代碼
 1 reg[3:0]  cs, ns;
 2 //----------   時序邏輯   ------------------
 3 always @(posedge clk or negedge rst_n) begin
 4     if (!rst_n)
 5         cs    <=  IDLE;
 6     else 
 7         cs    <=  ns;
 8 end
 9 //----------   組合邏輯   ------------------
10 always @(*) begin
11     case (cs)
12         IDLE :   if (wr_req) begin cs <= WR_S1; cmd <= 3'b011; end
13             else if (rd_req) begin cs <= RD_S1; cmd <= 3'b011; end
14             else             begin cs <= IDLE;  cmd <= 3'b111; end
15         WR_S1:               begin cs <= WR_S2; cmd <= 3'b101; end
16         WR_S2:               begin cs <= IDLE;  cmd <= 3'b111; end
17         RD_S1:   if (wr_req) begin cs <= WR_S2; cmd <= 3'b101; end
18                  else        begin cs <= RD_S2; cmd <= 3'b110; end
19         RD_S2:   if (wr_req) begin cs <= WR_S1; cmd <= 3'b011; end
20                  else        begin cs <= IDLE;  cmd <= 3'b111; end
21         default :                  cs <= IDLE;
22     endcase
23 end
復制代碼

三段式狀態機:

復制代碼
 1 reg[3:0]  cs, ns;
 2 //----------   時序邏輯   ------------------
 3 always @(posedge clk or negedge rst_n) begin
 4     if (!rst_n)
 5         cs    <=  IDLE;
 6     else 
 7         cs    <=  ns;
 8 end
 9 //----------   組合邏輯   ------------------
10 always @(*) begin
11     case (cs)  //現態
12         IDLE :   if (wr_req) begin cs <= WR_S1; end
13             else if (rd_req) begin cs <= RD_S1; end
14             else             begin cs <= IDLE;  end
15         WR_S1:               begin cs <= WR_S2; end
16         WR_S2:               begin cs <= IDLE;  end
17         RD_S1:   if (wr_req) begin cs <= WR_S2; end
18                  else        begin cs <= RD_S2; end
19         RD_S2:   if (wr_req) begin cs <= WR_S1; end
20                  else        begin cs <= IDLE;  end
21         default :                  cs <= IDLE;
22     endcase
23 end
24 //----------   時序邏輯   ------------------
25 always @(posedge clk or negedge rst_n) begin
26     if (!rst_n)
27         cmd    <=  3'b011;
28     else begin
29         case (ns)  //次態
30             IDLE :   if (wr_req) begin cmd <= 3'b011; end
31                 else if (rd_req) begin cmd <= 3'b011; end
32                 else             begin cmd <= 3'b111; end
33             WR_S1:               begin cmd <= 3'b101; end
34             WR_S2:               begin cmd <= 3'b111; end
35             RD_S1:   if (wr_req) begin cmd <= 3'b101; end
36                      else        begin cmd <= 3'b110; end
37             RD_S2:   if (wr_req) begin cmd <= 3'b011; end
38                      else        begin cmd <= 3'b111; end
39             default : ;
40         endcase 
41     end
42 end
復制代碼

 

三種寫法對比:

    (1)一段式狀態機不利於維護(簡單狀態機可以用);

    (2)兩段式狀態機是常見寫法,時序邏輯進行狀態切換,時序邏輯實現各個輸入、輸出以及狀態判斷,利於維護,不過組合邏輯容易出現毛刺等常見問題;

    (3)三段式狀態機推薦寫法,代碼易維護,時序邏輯輸出解決了兩段式寫法種組合邏輯的毛刺問題,但是耗費資源多一些且三段式從輸入到輸出比一段式和兩段式會延時一個時鍾周期。

轉載:http://www.cnblogs.com/yllinux/p/8641634.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM