前面寫的博客《有限狀態機--售報機》有錯。
如上圖,我們可以發現,本來在30ns時,news_out就應該輸出1,但直到下一個上升沿到來時,news_ou才輸出1。這種能編譯並仿真出來,但沒有達到預期效果的,肯定就是邏輯錯誤啦。下面這個圖是教材中,正確的仿真圖:
下面,我們來說說上面這個程序的問題所在,就在pres_state=s2這條分支上:
原來寫的是:如左圖 改正後:如右圖
本來s2代表目前已經投入了一塊錢,那麼當再投入5毛或者1一塊錢的時候,就已經完成投入一塊五,售報機應該售報了,即rnews_out=1,且next_state應該立馬變爲初始狀態s0;但上面左圖寫的時,next_state=s3,rnews_out=0;那麼在s2狀態下,投入一塊或五毛達到總幣大於等於一塊五後,只能等下一個上升沿到來時,才能檢測pres_state=s3,並給rnews_out賦值爲1;因此,原程序的仿真圖總延遲了一個時鐘。
修改後仿真圖如下:
(1)、建模代碼如下:
module fsm5(clock,reset,coin,news_out);
input clock,reset;
input [1:0]coin;
output news_out;
reg [1:0]pres_state;
reg news_out;
parameter s0=2'd0;
parameter s1=2'd1;
parameter s2=2'd2;
parameter s3=2'd3;
always @(posedge clock)
begin
if(!reset)
pres_state<=s0;
else
case(pres_state)
s0 :
case(coin)
2'd0 :
begin
pres_state<=s0;
news_out<=0;
end
2'd1 :
begin
pres_state<=s1;
news_out<=0;
end
2'd2 :
begin
pres_state<=s2;
news_out<=0;
end
endcase
s1 :
case(coin)
2'd0 :
begin
pres_state<=s1;
news_out<=0;
end
2'd1 :
begin
pres_state<=s2;
news_out<=0;
end
2'd2 :
begin
pres_state<=s0;
news_out<=1;
end
endcase
s2 :
case(coin)
2'd0 :
begin
pres_state<=s2;
news_out<=0;
end
2'd1 :
begin
pres_state<=s0;
news_out<=1;
end
2'd2 :
begin
pres_state<=s0;
news_out=1;
end
endcase
s3 :
begin
news_out=1;
pres_state<=s0;
end
endcase
end
endmodule
(2)、仿真代碼:
`include "fsm5.v"
module fsm5_stimulus;
reg CLK,Rst;
reg [1:0]coin;
wire newspaper;
fsm5 f(CLK,Rst,coin,newspaper);
initial
begin
CLK=1'b1;
Rst=0;
coin=2'd0;
#5 Rst=1;
#200 Rst=0;
#215 Rst=1;
//#500 $stop;
end
always #5 CLK=~CLK;
always @(posedge CLK)
#20 coin={$random}%3;
//這塊將coin設置成隨機數,更好
endmodule