本篇文章描述狀態機的一段式、二段式、三段式區別
一、狀態機
再次給出狀態機的示意圖:
1.1、摩爾型,輸出只與狀態寄存器的輸出狀態有關
1.2、米粒型,輸出不僅與狀態寄存器的輸出狀態有關,還與組合邏輯的輸入有關

二、一段式、二段式、三段式區別
根據狀態機的結構,狀態機描述方式 可分為:一段式、二段式、三段式
1.1、一段式
整個狀態機寫到一個 always 模塊里面。在該模塊中既描述狀態轉移,又描述狀態的輸入和輸出。
1.2、二段式
用兩個 always 模塊來描述狀態機。
1.2.1、其中一個 always 模塊采用同步時序描述狀態轉移;
1.2.2、另一個 always模塊采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律及其輸出,注意組合邏輯輸出要用阻塞賦值。
1.3、三段式
在兩個 always 模塊描述方法基礎上,使用三個 always 模塊。
1.3.1、 一個 always 模塊采用同步時序描述狀態轉移;
1.3.2、一個 always 采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律,注意組合邏輯輸出要用阻塞賦值;
1.3.3、另一個 always 模塊描述狀態輸出(可以用組合電路輸出,也可以時序電路輸出),注意組合邏輯輸出要用阻塞賦值。
1.4、綜合
可以看出兩段式有限狀態機與一段式有限狀態機的區別是將時序部分(狀態轉移)和組合部分(判斷狀態轉移條件和產生輸出)分開,寫為兩個always語句,即為兩段式有限狀態機。將組合部分中的判斷狀態轉移條件和產生輸出再分開寫,則為三段式有限狀態機。
三、自動售貨機、一段式
module auto_sell(
input clk,
input rst_n,
input coin_one,
input coin_half,
output reg water,
output reg coin_back
);
parameter ZERO = 3'b000;
parameter HALF = 3'b001;
parameter ONE = 3'b010;
parameter ONE_HALF = 3'b011;
parameter TWO = 3'b100;
//一段式狀態機
reg [2:0] status;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
status <= ZERO;
water <= 0;
coin_back <= 0;
end
else
case(status)
ZERO :
begin
water <= 0;
coin_back <= 0;
if(coin_half)
status <= HALF;
else if(coin_one)
status <= ONE;
else
status <= status;
end
HALF :
begin
water <= 0;
coin_back <= 0;
if(coin_half)
status <= ONE;
else if(coin_one)
status <= ONE_HALF;
else
status <= status;
end
ONE :
begin
water <= 0;
coin_back <= 0;
if(coin_half)
status <= ONE_HALF;
else if(coin_one)
status <= TWO;
else
status <= status;
end
ONE_HALF :
begin
if(coin_half)
begin
status <= TWO;
water <= 1'b0;
coin_back <= 1'b0;
end
else if(coin_one)
begin
status <= ZERO;
water <= 1'b1;
coin_back <= 1'b0;
end
else
begin
status <= status;
water <= 1'b0;
coin_back <= 1'b0;
end
end
TWO :
begin
if(coin_half)
begin
status <= ZERO;
water <= 1'b1;
coin_back <= 1'b0;
end
else if(coin_one)
begin
status <= ZERO;
water <= 1'b1;
coin_back <= 1'b1;
end
else
begin
status <= status;
water <= 1'b0;
coin_back <= 1'b0;
end
end
default:
begin
status <= ZERO;
water <= 1'b0;
coin_back <= 1'b0;
end
endcase
end
endmodule
四、自動售貨機、二段式
1.1、二段式,寫法一
module auto_sell(
input clk,
input rst_n,
input coin_one,
input coin_half,
output reg water,
output reg coin_back
);
parameter ZERO = 3'b000;
parameter HALF = 3'b001;
parameter ONE = 3'b010;
parameter ONE_HALF = 3'b011;
parameter TWO = 3'b100;
//--------------------二段式 1 ok--------------------------
//二段式狀態機
reg [2:0] c_status;
reg [2:0] n_status;
//狀態轉移
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
c_status <= ZERO;
else
c_status <= n_status;
end
//描述狀態轉移規律以及輸出
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
n_status <= ZERO;
water <= 1'b0;
coin_back <= 1'b0;
end
else
case(c_status)
ZERO :
begin
water <= 1'b0;
coin_back <= 1'b0;
if(coin_half)
n_status <= HALF;
else if(coin_one)
n_status <= ONE;
else
n_status <= ZERO;
end
HALF :
begin
water <= 1'b0;
coin_back <= 1'b0;
if(coin_half)
n_status <= ONE;
else if(coin_one)
n_status <= ONE_HALF;
else
n_status <= HALF;
end
ONE :
begin
water <= 1'b0;
coin_back <= 1'b0;
if(coin_half)
n_status <= ONE_HALF;
else if(coin_one)
n_status <= TWO;
else
n_status <= ONE;
end
ONE_HALF :
begin
water <= 1'b0;
coin_back <= 1'b0;
if(coin_half)
n_status <= TWO;
else if(coin_one)
begin
n_status <= ZERO;
water <= 1'b1;
coin_back <= 1'b0;
end
else
n_status <= ONE_HALF;
end
TWO :
begin
water <= 1'b0;
coin_back <= 1'b0;
if(coin_half)
begin
n_status <= ZERO;
water <= 1'b1;
coin_back <= 1'b0;
end
else if(coin_one)
begin
n_status <= ZERO;
water <= 1'b1;
coin_back <= 1'b1;
end
else
n_status <= TWO;
end
default:
n_status <= ZERO;
endcase
end
endmodule
1.2、二段式,寫法二
module auto_sell(
input clk,
input rst_n,
input coin_one,
input coin_half,
output reg water,
output reg coin_back
);
parameter ZERO = 3'b000;
parameter HALF = 3'b001;
parameter ONE = 3'b010;
parameter ONE_HALF = 3'b011;
parameter TWO = 3'b100;
//---------------------二段式 2 ok--------------------------------------
//二段式狀態機
reg [2:0] status;
//狀態轉移
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
status <= ZERO;
else
begin
case(status)
ZERO :
begin
if(coin_half)
status <= HALF;
else if(coin_one)
status <= ONE;
else
status <= ZERO;
end
HALF :
begin
if(coin_half)
status <= ONE;
else if(coin_one)
status <= ONE_HALF;
else
status <= HALF;
end
ONE :
begin
if(coin_half)
status <= ONE_HALF;
else if(coin_one)
status <= TWO;
else
status <= ONE;
end
ONE_HALF :
begin
if(coin_half)
status <= TWO;
else if(coin_one)
begin
status <= ZERO;
end
else
status <= ONE_HALF;
end
TWO :
begin
if(coin_half)
begin
status <= ZERO;
end
else if(coin_one)
begin
status <= ZERO;
end
else
status <= TWO;
end
default:
status <= ZERO;
endcase
end
end
//輸出 時序邏輯
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
water <= 1'b1;
coin_back <= 1'b0;
end
else
case(status)
ONE_HALF:
begin
if(coin_one)
begin
water <= 1'b1;
coin_back <= 1'b0;
end
else
begin
water <= 1'b0;
coin_back <= 1'b0;
end
end
TWO:
begin
if(coin_half)
begin
water <= 1'b1;
coin_back <= 1'b0;
end
else if(coin_one)
begin
water <= 1'b1;
coin_back <= 1'b1;
end
else
begin
water <= 1'b0;
coin_back <= 1'b0;
end
end
default:
begin
water <= 1'b0;
coin_back <= 1'b0;
end
endcase
end
endmodule
五、自動售貨機、三段式
module auto_sell(
input clk,
input rst_n,
input coin_one,
input coin_half,
output reg water,
output reg coin_back
);
parameter ZERO = 3'b000;
parameter HALF = 3'b001;
parameter ONE = 3'b010;
parameter ONE_HALF = 3'b011;
parameter TWO = 3'b100;
//三段式狀態機
reg [2:0] c_status;
reg [2:0] n_status;
//狀態轉移
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
c_status <= ZERO;
else
c_status <= n_status;
end
//狀態轉移規律及狀態輸出,組合邏輯輸出只與輸入有關
//如果有n_status = n_status,電路會出錯;
always@(*)begin
case(c_status)
ZERO :
begin
if(coin_half)
n_status = HALF;
else if(coin_one)
n_status = ONE;
else
n_status = ZERO;
end
HALF :
begin
if(coin_half)
n_status = ONE;
else if(coin_one)
n_status = ONE_HALF;
else
n_status = HALF;
end
ONE :
begin
if(coin_half)
n_status = ONE_HALF;
else if(coin_one)
n_status = TWO;
else
n_status = ONE;
end
ONE_HALF :
begin
if(coin_half)
n_status = TWO;
else if(coin_one)
n_status = ZERO;
else
n_status = ONE_HALF;
end
TWO :
begin
if(coin_half)
n_status = ZERO;
else if(coin_one)
n_status = ZERO;
else
n_status = TWO;
end
default:
n_status = ZERO;
endcase
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
begin
water = 1'b1;
coin_back = 1'b0;
end
else
case(c_status)
ONE_HALF:
begin
if(coin_one)
begin
water = 1'b1;
coin_back = 1'b0;
end
else
begin
water = 1'b0;
coin_back = 1'b0;
end
end
TWO:
begin
if(coin_half)
begin
water = 1'b1;
coin_back = 1'b0;
end
else if(coin_one)
begin
water = 1'b1;
coin_back = 1'b1;
end
else
begin
water = 1'b0;
coin_back = 1'b0;
end
end
default:
begin
water = 1'b0;
coin_back = 1'b0;
end
endcase
end
endmodule
六、仿真腳本
`timescale 1ns/1ps module auto_sell_tb; reg clk; reg rst_n; reg coin_one; reg coin_half; wire water; wire coin_back; initial begin clk = 0; rst_n = 0; coin_one = 0; coin_half = 0; #20; rst_n = 1; //延時200us #10000 //投2.5元 coin_half = 1; #20; coin_half = 0; #20; coin_one = 1; #20; coin_one = 0; #20; coin_half = 1; #20; coin_half = 0; #20; coin_half = 1; #20; coin_half = 0; #20; //延時200us #10000 //投3元 coin_half = 1; #20; coin_half = 0; #20; coin_one = 1; #20; coin_one = 0; #20; coin_half = 1; #20; coin_half = 0; #20; coin_one = 1; #20; coin_one = 0; #20; //延時200us #10000 $stop; end auto_sell auto_sell_inst( .clk (clk), .rst_n (rst_n), .coin_one (coin_one), .coin_half (coin_half), .water (water), .coin_back (coin_back) ); always #10 clk = ~clk; endmodule
七、仿真結果



-
寄存器
+關注
關注
31文章
5608瀏覽量
129957 -
仿真
+關注
關注
54文章
4482瀏覽量
138237 -
時序電路
+關注
關注
1文章
114瀏覽量
22293 -
狀態機
+關注
關注
2文章
499瀏覽量
29138
原文標題:筆記連載精選 |【狀態機:一段式、二段式、三段式】 【原理及verilog仿真】篇
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
“三段式”過電流保護含意
徹底搞懂狀態機(一段式、兩段式、三段式)!一個實例,三種方法對比看!!!(程序)
Verilog三段式狀態機描述及模版
Verilog三段式狀態機描述及模版
Verilog三段式狀態機描述(轉載)
雙電源自動轉換開關基礎知識(工作原理、工作步驟、選型、二段式和三段式的區別)
狀態機的一段式、二段式、三段式的區別
評論