目錄
狀態(tài)機介紹
狀態(tài)機類型
Moore 型狀態(tài)機
Mealy 型狀態(tài)機
狀態(tài)機設(shè)計流程
自動售賣機
狀態(tài)機設(shè)計:3 段式(推薦)
實例
實例
狀態(tài)機修改:2 段式
實例
狀態(tài)機修改:1 段式(慎用)
實例
狀態(tài)機修改:Moore 型
實例
實例
?文章來源地址http://www.zghlxwxcb.cn/news/detail-768240.html
狀態(tài)機介紹
有限狀態(tài)機(Finite-State Machine,F(xiàn)SM),簡稱狀態(tài)機,是表示有限個狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動作等行為的數(shù)學(xué)模型。狀態(tài)機不僅是一種電路的描述工具,而且也是一種思想方法,在電路設(shè)計的系統(tǒng)級和 RTL 級有著廣泛的應(yīng)用。
都說狀態(tài)機是 FPGA 設(shè)計的靈魂,可見其重要之處,在 Verilog 的設(shè)計中,狀態(tài)機其實可以等同于 if 語句和 case 語句,但是由于在某些情況下,狀態(tài)的種類多且復(fù)雜,各種狀態(tài)跳轉(zhuǎn)起來非常麻煩,所以 一般利用狀態(tài)機設(shè)計是一種可靠便捷的方法。
規(guī)范的狀態(tài)機代碼可以極大地提高設(shè)計效率, 在減少狀態(tài)出錯可能的同時縮短調(diào)試時間, 從而設(shè)計出穩(wěn)健的系統(tǒng)。
在設(shè)計狀態(tài)機時,最好能夠滿足以下要求:
- 通用的設(shè)計方法, 針對簡單或復(fù)雜的狀態(tài)機設(shè)計都能滿足;
- 步驟清晰易懂, 每步只考慮一個問題;
- 狀態(tài)機代碼嚴謹規(guī)范, 不容易出錯;
- 設(shè)計的狀態(tài)機結(jié)構(gòu)簡單且穩(wěn)定。
狀態(tài)機類型
Verilog 中狀態(tài)機主要用于同步時序邏輯的設(shè)計,能夠在有限個狀態(tài)之間按要求和規(guī)律切換時序電路的狀態(tài)。狀態(tài)的切換方向不但取決于各個輸入值,還取決于當前所在狀態(tài)。 狀態(tài)機可分為兩類:
- Moore 狀態(tài)機
- Mealy 狀態(tài)機
Moore 型狀態(tài)機
Moore 型狀態(tài)機的輸出只與當前狀態(tài)有關(guān),與當前輸入無關(guān)。
輸出會在一個完整的時鐘周期內(nèi)保持穩(wěn)定,即使此時輸入信號有變化,輸出也不會變化。輸入對輸出的影響要到下一個時鐘周期才能反映出來。這也是 Moore 型狀態(tài)機的一個重要特點:輸入與輸出是隔離開來的。
?文章來源:http://www.zghlxwxcb.cn/news/detail-768240.html
?
Mealy 型狀態(tài)機
Mealy 型狀態(tài)機的輸出,不僅與當前狀態(tài)有關(guān),還取決于當前的輸入信號。
Mealy 型狀態(tài)機的輸出是在輸入信號變化以后立刻發(fā)生變化,且輸入變化可能出現(xiàn)在任何狀態(tài)的時鐘周期內(nèi)。因此,同種邏輯下,Mealy 型狀態(tài)機輸出對輸入的響應(yīng)會比 Moore 型狀態(tài)機早一個時鐘周期。
?
?
狀態(tài)機設(shè)計流程
根據(jù)設(shè)計需求畫出狀態(tài)轉(zhuǎn)移圖,確定使用狀態(tài)機類型,并標注出各種輸入輸出信號,更有助于編程。一般使用最多的是 Mealy 型 3 段式狀態(tài)機,下面用通過設(shè)計一個自動售賣機的具體實例來說明狀態(tài)機的設(shè)計過程。
自動售賣機
自動售賣機的功能描述如下:
飲料單價 2 元,該售賣機只能接受 0.5 元、1 元的硬幣??紤]找零和出貨。投幣和出貨過程都是一次一次的進行,不會出現(xiàn)一次性投入多幣或一次性出貨多瓶飲料的現(xiàn)象。每一輪售賣機接受投幣、出貨、找零完成后,才能進入到新的自動售賣狀態(tài)。
該售賣機的工作狀態(tài)轉(zhuǎn)移圖如下所示,包含了輸入、輸出信號狀態(tài)。
其中,coin = 1 代表投入了 0.5 元硬幣,coin = 2 代表投入了 1 元硬幣。
狀態(tài)機設(shè)計:3 段式(推薦)
狀態(tài)機設(shè)計如下:
- (0) 首先,根據(jù)狀態(tài)機的個數(shù)確定狀態(tài)機編碼。利用編碼給狀態(tài)寄存器賦值,代碼可讀性更好。
- (1) 狀態(tài)機第一段,時序邏輯,非阻塞賦值,傳遞寄存器的狀態(tài)。
- (2) 狀態(tài)機第二段,組合邏輯,阻塞賦值,根據(jù)當前狀態(tài)和當前輸入,確定下一個狀態(tài)機的狀態(tài)。
- (3) 狀態(tài)機第三段,時序邏輯,非阻塞賦值,因為是 Mealy 型狀態(tài)機,根據(jù)當前狀態(tài)和當前輸入,確定輸出信號。
實例
module??vending_machine_p3 ?(
? ??input?? ? ? ? ? clk?,
? ??input?? ? ? ? ? rstn?,
? ??input?[1:0]?? ? coin?,?? ??
output?[1:0]?? ?change?, //找零
? ??output?? ? ? ? ?sell ? ? //輸出飲料
? ??);
? ??//machine state decode
? ??parameter?? ? ? ? ? IDLE ??=?3'd0?;
? ??parameter?? ? ? ? ? GET05 ?=?3'd1?;
? ??parameter?? ? ? ? ? GET10 ?=?3'd2?;
? ??parameter?? ? ? ? ? GET15 ?=?3'd3?;
? ?
?
? ??reg??[2:0]?? ? ? ? ?st_next?;
? ??reg??[2:0]?? ? ? ? ?st_cur?;
? ??reg??[1:0]?? change_r?;
? ??reg?? ? ? ? ? sell_r?;
? ??//第一段狀態(tài)機,時序邏輯 非阻塞賦值
? ??always?@(posedge?clk?or?negedge?rstn)?begin
? ? ? ??if?(!rstn)?begin
? ? ? ? ? ? st_cur <=?'b0?;
? ? ? ??end
? ? ? ??else?begin
? ? ? ? ? ? st_cur <=?st_next?;
? ? ? ??end
? ??end
? ??//第二段狀態(tài)機?,組合邏輯 阻塞賦值 ?
? ??always?@(*)?begin
? ? ? ??st_next = st_cur ; //如果條件選項考慮不全,可以賦初值消除latch
? ? ? ??case(st_cur)
? ? ? ? ? ? IDLE:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET05?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET10?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?IDLE?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET05:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET10?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET15?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?GET05?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET10:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET15?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?IDLE?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?GET10?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET15:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01,2'b10:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?st_next?=?IDLE?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?GET15?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ??default:??st_next?=?IDLE?;
? ? ? ??endcase
? ??end
? ??//第三段狀態(tài)機,時序邏輯 非阻塞賦值
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
? ? ? ? ? ? change_r <=?2'b0?;
? ? ? ? ? ? sell_r ? <=?1'b0?;
end
else begin
case (st_cur)
IDLE:
begin
change_r <=?2'b0?;
sell_r ? <=?1'b0?;
end
GET05:
begin
change_r <=?2'b0?;
sell_r ? <=?1'b0?;
end
GET10:
begin
if (coin?==2'd2) begin
change_r <=?2'b0?;
sell_r ? <=?1'b1?;
end
else begin
change_r <=?2'b0?;
sell_r ? <=?1'b0?;
end
end
GET15:
begin
if (coin?==2'h1) begin
change_r <=?2'b0?;
sell_r ? <=?1'b1?;
end
else if (coin?==?2'h2) begin
change_r <=?2'b1?;
sell_r ? <=?1'b1?;
end
else begin
change_r <=?2'b0?;
sell_r ? <=?1'b0?;
end
end
default:
begin
change_r <=?2'b0?;
sell_r ? <=?1'b0?;
end
endcase
end
end
? ??assign??sell =?sell_r?;
? ??assign??change =?change_r?;
endmodule
testbench 設(shè)計如下。仿真中模擬了 4 種情景,分別是:
case1 對應(yīng)連續(xù)輸入 4 個 5 角硬幣;case2 對應(yīng) 1 元 - 5 角 - 1 元的投幣順序;case3 對應(yīng) 5 角 - 1 元 - 5 角的投幣順序;case4 對應(yīng)連續(xù) 3 個 5 角然后一個 1 元的投幣順序。
實例
`timescale?1ns/1ps
module?test?;
? ??reg?? ? ? ? ?clk;
? ??reg?? ? ? ? ?rstn?;
? ??reg?[1:0]?? ?coin?;
? ??wire?[1:0]?? change?;
? ??wire?? ? ? ? sell?;
? ??//clock generating
? ??parameter?? ?CYCLE_200MHz?=?10?;?
? ??always?begin
? ? ? ? clk?=?0?;?#(CYCLE_200MHz/2)?;
? ? ? ? clk?=?1?;?#(CYCLE_200MHz/2)?;
? ??end
? ??//motivation generating
? ??reg?[9:0]?? ?buy_oper?;
? ??initial?begin
? ? ? ? buy_oper ?=?'h0?;
? ? ? ? coin ? ? ?=?2'h0?;
? ? ? ? rstn ? ? ?=?1'b0?;
? ? ? ??#8?rstn ??=?1'b1?;
? ? ? ??@(negedge?clk)?;
? ? ? ??//case(1) 0.5 -> 0.5 -> 0.5 -> 0.5
? ? ? ??#16?;
? ? ? ? buy_oper ?=?10'b00_0101_0101?;
? ? ? ??repeat(5)?begin
? ? ? ? ? ??@(negedge?clk)?;
? ? ? ? ? ? coin ? ? ?=?buy_oper[1:0]?;
? ? ? ? ? ? buy_oper ?=?buy_oper?>>?2?;
? ? ? ??end
? ? ? ??//case(2) 1 -> 0.5 -> 1, taking change
? ? ? ??#16?;
? ? ? ? buy_oper ?=?10'b00_0010_0110?;
? ? ? ??repeat(5)?begin
? ? ? ? ? ??@(negedge?clk)?;
? ? ? ? ? ? coin ? ? ?=?buy_oper[1:0]?;
? ? ? ? ? ? buy_oper ?=?buy_oper?>>?2?;
? ? ? ??end
? ? ? ??//case(3) 0.5 -> 1 -> 0.5
? ? ? ??#16?;
? ? ? ? buy_oper ?=?10'b00_0001_1001?;
? ? ? ??repeat(5)?begin
? ? ? ? ? ??@(negedge?clk)?;
? ? ? ? ? ? coin ? ? ?=?buy_oper[1:0]?;
? ? ? ? ? ? buy_oper ?=?buy_oper?>>?2?;
? ? ? ??end
? ? ? ??//case(4) 0.5 -> 0.5 -> 0.5 -> 1, taking change
? ? ? ??#16?;
? ? ? ? buy_oper ?=?10'b00_1001_0101?;
? ? ? ??repeat(5)?begin
? ? ? ? ? ??@(negedge?clk)?;
? ? ? ? ? ? coin ? ? ?=?buy_oper[1:0]?;
? ? ? ? ? ? buy_oper ?=?buy_oper?>>?2?;
? ? ? ??end
? ??end
? ?//(1) mealy state with 3-stage
? ? vending_machine_p3 ? ?u_mealy_p3 ? ??(
? ? ? ? .clk ? ? ? ? ? ? ?(clk),
? ? ? ? .rstn ? ? ? ? ? ??(rstn),
? ? ? ? .coin ? ? ? ? ? ??(coin),
? ? ? ? .change ? ? ? ? ??(change),
? ? ? ? .sell ? ? ? ? ? ??(sell)
? ? ? ??);
? ?//simulation finish
? ?always?begin
? ? ??#100;
? ? ??if?($time?>=?10000)??$finish?;
? ?end
endmodule?
仿真結(jié)果如下:
由圖可知,代表出貨動作的信號 sell 都能在投幣完畢后正常的拉高,而代表找零動作的信號 change 也都能根據(jù)輸入的硬幣場景輸出正確的是否找零信號。
?
狀態(tài)機修改:2 段式
將 3 段式狀態(tài)機 2、3 段描述合并,其他部分保持不變,狀態(tài)機就變成了 2 段式描述。
修改部分如下:
實例
reg??[1:0]?? change_r?;
reg?? ? ? ? ?sell_r?;
always?@(*)?begin?
? ??case(st_cur)
? ? ? ? IDLE:?begin
? ? ? ? ? ? change_r ? ??=?2'b0?;
? ? ? ? ? ? sell_r ? ? ??=?1'b0?;
? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET05?;
? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET10?;
? ? ? ? ? ? ? ??default:?? st_next?=?IDLE?;
? ? ? ? ? ??endcase?
? ? ? ??end
? ? ? ? GET05:?begin
? ? ? ? ? ? change_r ? ??=?2'b0?;
? ? ? ? ? ? sell_r ? ? ??=?1'b0?;
? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET10?;
? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET15?;
? ? ? ? ? ? ? ??default:?? st_next?=?GET05?;
? ? ? ? ? ??endcase?
? ? ? ??end
? ? ? ? GET10:
? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ??2'b01:?? ??begin
? ? ? ? ? ? ? ? ? ? st_next ? ? ?=?GET15?;
? ? ? ? ? ? ? ? ? ? change_r ? ??=?2'b0?;
? ? ? ? ? ? ? ? ? ? sell_r ? ? ??=?1'b0?;
? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ??2'b10:?? ??begin
? ? ? ? ? ? ? ? ? ? st_next ? ? ?=?IDLE?;
? ? ? ? ? ? ? ? ? ? change_r ? ??=?2'b0?;
? ? ? ? ? ? ? ? ? ? sell_r ? ? ??=?1'b1?;
? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ??default:???begin
? ? ? ? ? ? ? ? ? ? st_next ? ? ?=?GET10?;
? ? ? ? ? ? ? ? ? ? change_r ? ??=?2'b0?;
? ? ? ? ? ? ? ? ? ? sell_r ? ? ??=?1'b0?;
? ? ? ? ? ? ? ??end
? ? ? ? ? ??endcase?
? ? ? ? GET15:
? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ??2'b01:?begin
? ? ? ? ? ? ? ? ? ? st_next ? ??=?IDLE?;
? ? ? ? ? ? ? ? ? ? change_r ? ?=?2'b0?;
? ? ? ? ? ? ? ? ? ? sell_r ? ? ?=?1'b1?;
? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ??2'b10:?? ??begin
? ? ? ? ? ? ? ? ? ? st_next ? ??=?IDLE?;
? ? ? ? ? ? ? ? ? ? change_r ? ?=?2'b1?;
? ? ? ? ? ? ? ? ? ? sell_r ? ? ?=?1'b1?;
? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ??default:???begin
? ? ? ? ? ? ? ? ? ? st_next ? ??=?GET15?;
? ? ? ? ? ? ? ? ? ? change_r ? ?=?2'b0?;
? ? ? ? ? ? ? ? ? ? sell_r ? ? ?=?1'b0?;
? ? ? ? ? ? ? ??end
? ? ? ? ? ??endcase
? ? ? ??default:??begin
? ? ? ? ? ? st_next ? ??=?IDLE?;
? ? ? ? ? ? change_r ? ?=?2'b0?;
? ? ? ? ? ? sell_r ? ? ?=?1'b0?;
? ? ? ??end
? ??endcase
end
將上述修改的新模塊例化到 3 段式的 testbench 中即可進行仿真,結(jié)果如下:
由圖可知,出貨信號 sell 和 找零信號 change 相對于 3 段式狀態(tài)機輸出提前了一個時鐘周期,這是因為輸出信號都是阻塞賦值導(dǎo)致的。
如圖中紅色圓圈部分,輸出信號都出現(xiàn)了干擾脈沖,這是因為輸入信號都是異步的,而且輸出信號是組合邏輯輸出,沒有時鐘驅(qū)動。
實際中,如果輸入信號都是與時鐘同步的,這種干擾脈沖是不會出現(xiàn)的。如果是異步輸入信號,首先應(yīng)當對信號進行同步。
?
狀態(tài)機修改:1 段式(慎用)
將 3 段式狀態(tài)機 1、 2、3 段描述合并,狀態(tài)機就變成了 1 段式描述。
修改部分如下:
實例
? ??reg??[1:0]?? change_r?;
? ??reg?? ? ? ? ?sell_r?;
? ??always?@(posedge?clk?or?negedge?rstn)?begin
? ? ? ??if?(!rstn)?begin
? ? ? ? ? ? st_cur ? ??<=?'b0?;
? ? ? ? ? ? change_r ??<=?2'b0?;
? ? ? ? ? ? sell_r ? ??<=?1'b0?;
? ? ? ??end
? ? ? ??else?begin
? ? ? ? ? ??case(st_cur)
? ? ? ? ? ? IDLE:?begin
? ? ? ? ? ? ? ? change_r ?<=?2'b0?;
? ? ? ? ? ? ? ? sell_r ? ?<=?1'b0?;
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_cur?<=?GET05?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_cur?<=?GET10?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ??end
? ? ? ? ? ? GET05:?begin
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_cur?<=?GET10?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_cur?<=?GET15?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ??end
? ? ? ? ? ? GET10:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_cur ??<=??GET15?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ??begin
? ? ? ? ? ? ? ? ? ? ? ? st_cur ??<=?IDLE?;
? ? ? ? ? ? ? ? ? ? ? ? sell_r ??<=?1'b1?;
? ? ? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET15:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ??begin
? ? ? ? ? ? ? ? ? ? ? ? st_cur ??<=?IDLE?;
? ? ? ? ? ? ? ? ? ? ? ? sell_r ??<=?1'b1?;
? ? ? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ? ? ??2'b10:?? ??begin
? ? ? ? ? ? ? ? ? ? ? ? st_cur ??<=?IDLE?;
? ? ? ? ? ? ? ? ? ? ? ? change_r?<=?2'b1?;
? ? ? ? ? ? ? ? ? ? ? ? sell_r ??<=?1'b1?;
? ? ? ? ? ? ? ? ? ??end
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ??default:??begin
? ? ? ? ? ? ? ? ? st_cur ? ?<=?IDLE?;
? ? ? ? ? ??end
? ? ? ? ? ??endcase?// case (st_cur)
? ? ? ??end?
? ??end
將上述修改的新模塊例化到 3 段式的 testbench 中即可進行仿真,結(jié)果如下:
由圖可知,輸出信號與 3 段式狀態(tài)機完全一致。
1 段式狀態(tài)機的缺點就是許多種邏輯糅合在一起,不易后期的維護。當狀態(tài)機和輸出信號較少時,可以嘗試此種描述方式。
?
狀態(tài)機修改:Moore 型
如果使用 Moore 型狀態(tài)機描述售賣機的工作流程,那么還需要再增加 2 個狀態(tài)編碼,用以描述 Mealy 狀態(tài)機輸出時的輸入信號和狀態(tài)機狀態(tài)。
3 段式 Moore 型狀態(tài)機描述的自動售賣機 Verilog 代碼如下:
實例
module??vending_machine_moore ? ?(
? ??input?? ? ? ? ? clk?,
? ??input?? ? ? ? ? rstn?,
? ??input?[1:0]?? ? coin?,?? ??
? ??output?[1:0]?? ?change?,
? ??output?? ? ? ? ?sell ? ?
? ??);
? ??parameter?? ? ? ? ? ?IDLE ??=?3'd0?;
? ??parameter?? ? ? ? ? ?GET05 ?=?3'd1?;
? ??parameter?? ? ? ? ? ?GET10 ?=?3'd2?;
? ??parameter?? ? ? ? ? ?GET15 ?=?3'd3?;
? ??parameter?? ? ? ? ? ?GET20 ?=?3'd4?;
? ??parameter?? ? ? ? ? ?GET25 ?=?3'd5?;
? ??reg?[2:0]?? ? ? ? ? ?st_next?;
? ??reg?[2:0]?? ? ? ? ? ?st_cur?;
? ??//(1) state transfer
? ??always?@(posedge?clk?or?negedge?rstn)?begin
? ? ? ??if?(!rstn)?begin
? ? ? ? ? ? st_cur ? ? ?<=?'b0?;
? ? ? ??end
? ? ? ??else?begin
? ? ? ? ? ? st_cur ? ? ?<=?st_next?;
? ? ? ??end
? ??end
? ??always?@(*)?begin?//all case items need to be displayed completely
? ? ? ??case(st_cur)
? ? ? ? ? ? IDLE:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET05?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET10?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?IDLE?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET05:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET10?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET15?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?GET05?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET10:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET15?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET20?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?GET10?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET15:
? ? ? ? ? ? ? ??case?(coin)
? ? ? ? ? ? ? ? ? ??2'b01:?? ? st_next?=?GET20?;
? ? ? ? ? ? ? ? ? ??2'b10:?? ? st_next?=?GET25?;
? ? ? ? ? ? ? ? ? ??default:?? st_next?=?GET15?;
? ? ? ? ? ? ? ??endcase
? ? ? ? ? ? GET20:?? ? ? ? st_next?=?IDLE?;
? ? ? ? ? ? GET25:?? ? ? ? st_next?=?IDLE?;
? ? ? ? ? ??default:?? ? ? st_next?=?IDLE?;
? ? ? ??endcase
? ??end?
? ??reg??[1:0]?? change_r?;
? ??reg?? ? ? ? ?sell_r?;
? ??always?@(posedge?clk?or?negedge?rstn)?begin
? ? ? ??if?(!rstn)?begin
? ? ? ? ? ? change_r ? ? ??<=?2'b0?;
? ? ? ? ? ? sell_r ? ? ? ??<=?1'b0?;
? ? ? ??end
? ? ? ??else?if?(st_cur?==?GET20?)?begin
? ? ? ? ? ? sell_r ? ? ? ??<=?1'b1?;
? ? ? ??end
? ? ? ??else?if?(st_cur?==?GET25)?begin
? ? ? ? ? ? change_r ? ? ??<=?2'b1?;
? ? ? ? ? ? sell_r ? ? ? ??<=?1'b1?;
? ? ? ??end
? ? ? ??else?begin
? ? ? ? ? ? change_r ? ? ??<=?2'b0?;
? ? ? ? ? ? sell_r ? ? ? ??<=?1'b0?;
? ? ? ??end
? ??end
? ??assign?? ? ? sell ? ?=?sell_r?;
? ??assign?? ? ? change ?=?change_r?;
endmodule
將上述修改的 Moore 狀態(tài)機例化到 3 段式的 testbench 中即可進行仿真,結(jié)果如下:
由圖可知,輸出信號與 Mealy 型 3 段式狀態(tài)機相比延遲了一個時鐘周期,這是因為進入到新增加的編碼狀態(tài)機時需要一個時鐘周期的時延。此時,輸出再用非阻塞賦值就會導(dǎo)致最終的輸出信號延遲一個時鐘周期。這也屬于 Moore 型狀態(tài)機的特點。
?
輸出信號賦值時,用阻塞賦值,則可以提前一個時鐘周期。
輸出邏輯修改如下。
實例
? ??reg??[1:0]?? change_r?;
? ??reg?? ? ? ? ?sell_r?;
? ??always?@(*)?begin
? ? ? ? change_r ?=?'b0?;
? ? ? ? sell_r ? ?=?'b0?;?//not list all condition, initializing them
? ? ? ??if?(st_cur?==?GET20?)?begin
? ? ? ? ? ? sell_r ? ? ? ??=?1'b1?;
? ? ? ??end
? ? ? ??else?if?(st_cur?==?GET25)?begin
? ? ? ? ? ? change_r ? ? ??=?2'b1?;
? ? ? ? ? ? sell_r ? ? ? ??=?1'b1?;
? ? ? ??end
? ??end
輸出信號阻塞賦值的仿真結(jié)果如下:
由圖可知,輸出信號已經(jīng)和 3 段式 Mealy 型狀態(tài)機一致。
?
?
?
到了這里,關(guān)于【狀態(tài)機設(shè)計】Moore、Mealy狀態(tài)機、三段式、二段式、一段式狀態(tài)機書寫規(guī)范的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!