三種不同狀態機寫法
阿新 • • 發佈:2018-03-25
begin 狀態機 nbsp OS 時鐘 pre 組合 cmd 周期
一段式狀態機:
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 elseif (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)三段式狀態機推薦寫法,代碼易維護,時序邏輯輸出解決了兩段式寫法種組合邏輯的毛刺問題,但是耗費資源多一些且三段式從輸入到輸出比一段式和兩段式會延時一個時鐘周期。
三種不同狀態機寫法