前面写的博客《有限状态机--售报机》有错。
如上图,我们可以发现,本来在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