下圖是教材中的例子,教材採用四種方法建模,具體隨後道來:
方法一:
(1)、建模
module fsm1(Clock,Reset,A,K1,K2);
input Clock,Reset,A;
output K1,K2;
reg K1,K2;
reg [1:0]state;
//Gray碼
parameter Idle=2'b00;
parameter Start=2'b01;
parameter Stop=2'b10;
parameter Clear=2'b11;
always @(posedge Clock)
if(!Reset)
begin
state<=Idle;
K1=0;
K2=0;
end
else
case(state)
Idle:if (A)
begin
state<=Start;
K1<=0;
end
else
begin
state<=Idle;
K1<=0;
K2<=0;
end
Start:if (A)
begin
state<=Start;
K1<=0;
K2<=0;
end
else
begin
state<=Stop;
end
Stop:if (A)
begin
state<=Clear;
K2<=1;
end
else
begin
state<=Stop;
K2<=0;
K1<=0;
end
Clear:if (A)
begin
state<=Clear;
K2<=0;
K1<=0;
end
else
begin
state<=Idle;
K2<=0;
K1<=1;
end
default: state<=2'bxx;
endcase
endmodule
(2)仿真圖:
方法二:
module fsm2(Clock,Reset,A,K1,K2);
input Clock,Reset,A;
output K1,K2;
reg K1,K2;
//reg [1:0]state;
reg [1:0]state;
//這種方法與方法一,其實是一樣的,只是在對state狀態的編碼方法不同,方法一採取的是格雷碼,方法二採取的是獨熱碼,採用FPGA實現的有限狀態機更適合採用獨熱碼。但在此例中,開始不知爲何採用獨熱碼,k1和k2一直爲0,仿真不出來結果。後來才發現,是上面這行藍色代碼的錯誤,state採用獨熱碼編寫,總共有四位,但,[1:0]state只有兩位,仿真結果肯定錯誤。
parameter Idle=4'1000;
parameter Start=4'b0100;
parameter Stop=4'b0010;
parameter Clear=4'b0001;
always @(posedge Clock)
if(!Reset)
begin
state<=Idle;
K1=0;
K2=0;
end
else
case(state)
Idle:if (A)
begin
state<=Start;
K1<=0;
end
else
begin
state<=Idle;
K1<=0;
K2<=0;
end
Start:if (A)
begin
state<=Start;
K1<=0;
K2<=0;
end
else
begin
state<=Stop;
end
Stop:if (A)
begin
state<=Clear;
K2<=1;
end
else
begin
state<=Stop;
K2<=0;
K1<=0;
end
Clear:if (A)
begin
state<=Clear;
K2<=0;
K1<=0;
end
else
begin
state<=Idle;
K2<=0;
K1<=1;
end
default: state<=2'bxx;
endcase
endmodule
方法三:將state狀態也設置爲輸出,通過state輸出的編碼,反映k1和k2的變化,在狀態轉換建模上,方法三與方法二,方法一都是一致的:
module fsm3(Clock,Reset,A,K1,K2,state);
input Clock,Reset,A;
output K1,K2;
output [4:0]state;
reg [4:0]state;
//???k1?k2??wire???
assign K1=state[0];
assign K2=state[4];
//k1,k2????????state?
parameter Idle=5'b0_0_0_0_0;
parameter Start=5'b0_0_0_1_0;
parameter Stop=5'b0_0_1_0_0;
parameter Clear=5'b0_1_0_1_0;
//??????????k1?k2?????state?????
parameter Stop_Clear=5'b1_1_0_0_0;
parameter Clear_Idle=5'b0_0_1_1_1;
always @(posedge Clock)
if(!Reset)
begin
state<=Idle;
end
else
//?????????k1?k2????????????
//???k2?k1???????state????
case(state)
Idle:if (A)
begin
state<=Start;
//K1<=0;
end
else
begin
state<=Idle;
//K1<=0;
//K2<=0;
end
Start:if (A)
begin
state<=Start;
//K1<=0;
//K2<=0;
end
else
begin
state<=Stop;
end
Stop:if (A)
begin
state<=Stop_Clear;
//K2<=1;
end
else
begin
state<=Stop;
//K2<=0;
//K1<=0;
end
Stop_Clear:state<=Clear;
Clear:if (A)
begin
state<=Clear;
//K2<=0;
//K1<=0;
end
else
begin
state<=Clear_Idle;
//K2<=0;
//K1<=1;
end
Clear_Idle: state<=Idle;
default: state<=2'bxx;
endcase
endmodule
(2)仿真圖:
方法四:
(1)、建模:這種方法相對前面幾種一個方法添加了一個nextstate變量,然後建模時,一個always過程反映當前的state狀態改變,即上升沿到來時,state<=nextstate;但沒有指明這個nextstate具體是什麼。第二個always過程是根據state和A的變化,設定nextstate變量值的變化。第三個always過程是反映k1的變化,第四個always過程是反映k2的變化。(分過程快反映個變量的變化,而前面方面都是在一個過程塊中反映所有變量的變化)
module fsm4(Clock,Reset,A,K1,K2);
input Clock,Reset,A;
output K1,K2;
reg K1,K2;
reg [1:0]state,nextstate;
//Gray????
parameter Idle=2'b00;
parameter Start=2'b01;
parameter Stop=2'b10;
parameter Clear=2'b11;
//????????????????
always @(posedge Clock)
if(!Reset)
state<=Idle;
else
state<=nextstate;
//??state?A???????????????
always @(state,A)
case(state)
Idle:if (A)
begin
nextstate<=Start;
//K1<=0;
end
else
begin
nextstate<=Idle;
//K1<=0;
//K2<=0;
end
Start:if (A)
begin
nextstate<=Start;
//K1<=0;
//K2<=0;
end
else
begin
nextstate<=Stop;
end
Stop:if (A)
begin
nextstate<=Clear;
//K2<=1;
end
else
begin
nextstate<=Stop;
//K2<=0;
//K1<=0;
end
Clear:if (A)
begin
nextstate<=Clear;
//K2<=0;
//K1<=0;
end
else
begin
nextstate<=Idle;
//K2<=0;
//K1<=1;
end
default: nextstate<=2'bxx;
endcase
//????K1??????
always @(state,A,Reset)
if(!Reset)
K1=0;
else
if(state==Clear&&!A)
K1=1;
else
K1=0;
//????K2??????
always @(state,A,Reset)
if(!Reset)
K2=0;
else
if(state==Stop&&A)
K2=1;
else
K2=0;
endmodule
(2)仿真波形:
2、testbench編碼:
`timescale 1ns/1ns
`include "fsm3.v"
module Stimulus_fsm;
reg Clock,Reset,A;
wire K1,K2;
wire [4:0]state;
//fsm2 ff(Clock,Reset,A,K1,K2);
fsm3 ff(Clock,Reset,A,K1,K2,state);
initial
begin
A=0;
Reset=1;
Clock=0;
#22 Reset=0;
#133 Reset=1;
end
always #50 Clock=~Clock;
always @(posedge Clock )
begin
#30 A={$random}%2;
end
endmodule