狀態(tài)機(jī)由狀態(tài)寄存器和組合邏輯電路構(gòu)成,能夠根據(jù)控制信號(hào)按照預(yù)先設(shè)定的狀態(tài)進(jìn)行狀態(tài)轉(zhuǎn)移,程序的運(yùn)行其本質(zhì)也是狀態(tài)機(jī),根據(jù)輸入完成輸出,得到新的狀態(tài)。
在平時(shí)硬件電路的設(shè)計(jì)中經(jīng)常需要用到狀態(tài)機(jī),例如CPU的取指、譯碼、執(zhí)行,這個(gè)流程可以使用狀態(tài)機(jī)來(lái)控制,相比于流水線能夠有效的較少資源的消耗,再或者序列檢測(cè)上,也可以使用狀態(tài)機(jī)。
狀態(tài)機(jī)有一段、二段、和三段式,三段式的寫法復(fù)雜些,但是相比于兩段式可以使輸出信號(hào)由寄存器來(lái)驅(qū)動(dòng),能夠有效的消除組合邏輯的不穩(wěn)定與毛刺等隱患。
首先給出三段式狀態(tài)機(jī)的通用形式:
三段式狀態(tài)機(jī)
Mealy型(米勒型)三段式狀態(tài)機(jī)
當(dāng)前輸出與當(dāng)前狀態(tài)和輸入有關(guān)
parameter S0=3'b000,
state1=3'b001,
state2=3'b010,
S3=3'b011;
reg [2:0] current_state;
reg [2:0] next_state;
//在第一個(gè)always塊中只實(shí)現(xiàn)狀態(tài)的遷移,將第二個(gè)always塊中計(jì)算出的次態(tài)在時(shí)鐘上升沿復(fù)制給current_state
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
current_state<=0;
next_state<=0;
end
else
begin
current_state<=next_state;
end
end
//在第二個(gè)always塊中計(jì)算next_state,使用組合邏輯來(lái)完成
always @(*)
begin
case(current_state)
S0:
if(..) //當(dāng)然此刻的if判斷也能用三目運(yùn)算法來(lái)實(shí)現(xiàn),看上去會(huì)更便捷一些:
next_state=S1;
else
next_state=S0;
S1:
if(..)
next_state=state?;
else
next_state=state?;
S2:
if(..)
next_state=state?;
else
next_state=state?;
S3:
if(..)
next_state=state?;
else
next_state=state?;
default:
next_state=S0;
endcase
end
//在第三個(gè)always塊中計(jì)算輸出,在滿足什么情況下輸出
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
signal_out<=0;
end
else
begin
if(current_state==state?&&signal_in==?)
signal_out<=1;
else
signal_out<=0;
end
end
Moore型(摩爾型)三段式狀態(tài)機(jī)
當(dāng)前輸出僅僅與當(dāng)前狀態(tài)有關(guān)
parameter S0=3'b000,
state1=3'b001,
state2=3'b010,
S3=3'b011;
reg [2:0] current_state;
reg [2:0] next_state;
//在第一個(gè)always塊中只實(shí)現(xiàn)狀態(tài)的遷移,將第二個(gè)always塊中計(jì)算出的次態(tài)在時(shí)鐘上升沿復(fù)制給current_state
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
current_state<=0;
next_state<=0;
end
else
begin
current_state<=next_state;
end
end
//在第二個(gè)always塊中計(jì)算next_state,使用組合邏輯來(lái)完成
always @(*)
begin
case(current_state)
S0:
if(..) //當(dāng)然此刻的if判斷也能用三目運(yùn)算法來(lái)實(shí)現(xiàn),看上去會(huì)更便捷一些:
next_state=S1;
else
next_state=S0;
S1:
if(..)
next_state=state?;
else
next_state=state?;
S2:
if(..)
next_state=state?;
else
next_state=state?;
S3:
if(..)
next_state=state?;
else
next_state=state?;
default:
next_state=S0;
endcase
end
//在第三個(gè)always塊中計(jì)算輸出,在滿足什么情況下輸出
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
signal_out<=0;
end
else
begin
if(current_state==state?)
signal_out<=1;
else
signal_out<=0;
end
end
兩種三段式狀態(tài)機(jī)的狀態(tài)圖會(huì)有區(qū)別
測(cè)試用例
接下來(lái)我們使用具體的場(chǎng)景來(lái)介紹兩者不同
設(shè)計(jì)一個(gè)狀態(tài)機(jī),用來(lái)檢測(cè)序列 10111,要求:
1、進(jìn)行非重疊檢測(cè) 即101110111 只會(huì)被檢測(cè)通過(guò)一次
2、寄存器輸出且同步輸出結(jié)果
信號(hào)示意圖:
輸入描述:
輸入信號(hào) clk rst data
類型 wire
輸出描述:
輸出信號(hào) flag
類型 reg
首先第一件事就是畫出狀態(tài)轉(zhuǎn)移,在此刻我們一定要注意到,flag是在檢測(cè)完成的這一個(gè)周期拉高的,而不是下個(gè)周期
Mealy型(米勒型)狀態(tài)圖——輸出與輸入和現(xiàn)態(tài)有關(guān)
這個(gè)時(shí)候我們來(lái)解析這張圖
復(fù)位之后當(dāng)前狀態(tài)是S0,假設(shè)在第一個(gè)時(shí)鐘上升沿之前,data輸入1,則通過(guò)第二個(gè)always組合邏輯塊,會(huì)計(jì)算出next_state=S1,在第一個(gè)時(shí)鐘上升沿,next_state=S1就會(huì)被賦值給current_state,也就是說(shuō)從第一個(gè)上升沿之后到第二個(gè)上升沿之前,current會(huì)一直保持S1的狀態(tài)。
假設(shè)在第一個(gè)上升沿之后到第二個(gè)上升沿之前,data輸入變?yōu)榱?,那么同理,組合邏輯會(huì)計(jì)算出新的next_state=S2,在第二個(gè)時(shí)鐘上升沿倘若data不發(fā)生變化,則新的next_state會(huì)被賦值給current_state,從第二個(gè)上升沿之后到第三個(gè)上升沿之前,current會(huì)一直保持S2的狀態(tài)。
假設(shè)在第二個(gè)上升沿之后到第三個(gè)上升沿之前,data輸入變?yōu)榱?,那么同理,組合邏輯會(huì)計(jì)算出新的next_state=S3,在第三個(gè)時(shí)鐘上升沿倘若data不發(fā)生變化,則新的next_state會(huì)被賦值給current_state,從第三個(gè)上升沿之后到第四個(gè)上升沿之前,current會(huì)一直保持S3的狀態(tài)。
假設(shè)在第三個(gè)上升沿之后到第四個(gè)上升沿之前,data輸入變?yōu)榱?,那么同理,組合邏輯會(huì)計(jì)算出新的next_state=S4,在第四個(gè)時(shí)鐘上升沿倘若data不發(fā)生變化,則新的next_state會(huì)被賦值給current_state,從第四個(gè)上升沿之后到第五個(gè)上升沿之前,current會(huì)一直保持S4的狀態(tài)。
假設(shè)在第四個(gè)上升沿之后到第五個(gè)上升沿之前,data輸入變?yōu)榱?,此時(shí)注意,前面我們談到過(guò),在這個(gè)題目中,在完成序列檢測(cè)的這一個(gè)周期,flag就要拉高,此時(shí)我們需要第五個(gè)上升沿將flag拉高,因此需要在第三個(gè)always語(yǔ)句塊中定位到這個(gè)時(shí)刻,也就是current_state= =S4&&data= =1,這也就是輸出和現(xiàn)態(tài)以及輸入都有關(guān),之后current_state將變?yōu)镾0,重新進(jìn)行一輪新的檢測(cè)。
`timescale 1ns/1ns
module sequence_test1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
parameter S0=0,
S1=1,
S2=2,
S3=3,
S4=4,
S5=5;
reg [2:0] current_state;
reg [2:0] next_state;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
current_state<=0;
next_state<=0;
end
else
begin
current_state<=next_state;
end
end
always @(*)
begin
case(current_state)
S0:begin
next_state<=data==1?S1:S0;
end
S1:begin
next_state<=data==0?S2:S0;
end
S2:begin
next_state<=data==1?S3:S0;
end
S3:begin
next_state<=data==1?S4:S0;
end
S4:begin
next_state<=S0;
end
end
default:
nex_state<=S0;
endcase
end
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
flag<=0;
end
else
begin
if(current_state==S4&&data==1)
flag<=1;
else
flag<=0;
end
end
endmodule
Moore型(摩爾型)狀態(tài)圖——輸出只與現(xiàn)態(tài)有關(guān)
Moore型(摩爾型)狀態(tài)機(jī)與米勒型稍有不同,下面我們嘗試用摩爾狀態(tài)機(jī)來(lái)解決這個(gè)問(wèn)題
倘若在某個(gè)時(shí)鐘上升沿時(shí),當(dāng)前current_state=S4時(shí),此時(shí)若data=1,按照題目的要求,在這個(gè)上升沿結(jié)束之后flag就應(yīng)該立刻拉高,而Moore型狀態(tài)機(jī)的輸出只與現(xiàn)態(tài)有關(guān),在這個(gè)時(shí)刻current_state=S4,僅僅根據(jù)這個(gè)條件我們無(wú)法判斷輸出是0還是1,若將flag拉高了,但是data為0,那就是錯(cuò)誤的,因此在當(dāng)前時(shí)刻必須結(jié)合輸入才能得出正確的輸出,在下一個(gè)時(shí)鐘上升沿,檢測(cè)到current_state=S5時(shí)才能將flag拉高,這是才是正確的,因此Moore型狀態(tài)機(jī)相比Mealy狀態(tài)機(jī)會(huì)延遲一個(gè)周期。
代碼如下
`timescale 1ns/1ns
module sequence_test1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
parameter S0=0,
S1=1,
S2=2,
S3=3,
S4=4,
S5=5;
reg [2:0] current_state;
reg [2:0] next_state;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
current_state<=0;
next_state<=0;
end
else
begin
current_state<=next_state;
end
end
always @(*)
begin
case(current_state)
S0:begin
next_state<=data==1?S1:S0;
end
S1:begin
next_state<=data==0?S2:S0;
end
S2:begin
next_state<=data==1?S3:S0;
end
S3:begin
next_state<=data==1?S4:S0;
end
S4:begin
next_state<=data==1?S5:S0;
end
S5:begin
next_state<=S0;
end
default:
nex_state<=S0;
endcase
end
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
flag<=0;
end
else
begin
if(current_state==S5) ,
flag<=1;
else
flag<=0;
end
end
endmodule
修改后的Moore型(摩爾型)狀態(tài)機(jī)
我們可以通過(guò)將判斷條件改為next_state==S5,這種方式將輸出提前一個(gè)周期,因?yàn)閚ext_state本就是根據(jù)current_state和data得出的,所以提前一個(gè)周期用也無(wú)妨。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-762283.html
`timescale 1ns/1ns
module sequence_test1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
parameter S0=0,
S1=1,
S2=2,
S3=3,
S4=4,
S5=5;
reg [2:0] current_state;
reg [2:0] next_state;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
current_state<=0;
next_state<=0;
end
else
begin
current_state<=next_state;
end
end
always @(*)
begin
case(current_state)
S0:begin
next_state<=data==1?S1:S0;
end
S1:begin
next_state<=data==0?S2:S0;
end
S2:begin
next_state<=data==1?S3:S0;
end
S3:begin
next_state<=data==1?S4:S0;
end
S4:begin
next_state<=data==1?S5:S0;
end
S5:begin
next_state<=S0;
end
default:
nex_state<=S0;
endcase
end
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
flag<=0;
end
else
begin
if(next_state==S5) ,
flag<=1;
else
flag<=0;
end
end
endmodule
這種方法相比于Mealy機(jī)多了一個(gè)狀態(tài)S5文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-762283.html
到了這里,關(guān)于FPGA開發(fā)基礎(chǔ)之三段式狀態(tài)機(jī)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!