使用哪种方式的状态机,不能一概而论,切忌“一棍子打死”和“非黑即白”的思想!根据实际情况,选择合适的状态机方式。
三段式相比于一段式,简洁,方便维护,前提:输入输出比较多,比较复杂的状态机。这种情况下,一段式显得 冗长 ,用三段式就比较方便了,如下对比:
一段式:
module top(clk,rst_n,datain1,datain2,datain3,datain4,
dataout1,dataout2,dataout3,dataout4,dataout5);
input clk;
input rst_n;
input datain1;
input datain2;
input datain3;
input datain4;
output reg [3:0] dataout1,dataout2,dataout3,dataout4,dataout5;
parameter state0=4'd0,state1=4'd1,state2=4'd2,state3=4'd3,state4=4'd4;
reg [3:0] state;
reg [3:0] next_state;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
dataout1<=4'b0;
dataout2<=4'b0;
dataout3<=4'b0;
dataout4<=4'b0;
dataout5<=4'b0;
state<=state0;
end
else case(state)
state0: if(datain1)
begin
state<=state1;
dataout1<=4'd1;
dataout2<=4'd2;
dataout3<=4'd3;
dataout4<=4'd4;
dataout5<=4'd5;
end
else if(datain2)
begin
state<=state2;
dataout1<=4'd2;
dataout2<=4'd3;
dataout3<=4'd4;
dataout4<=4'd5;
dataout5<=4'd6;
end
else if(datain3)
begin
state<=state3;
dataout1<=4'd3;
dataout2<=4'd4;
dataout3<=4'd5;
dataout4<=4'd6;
dataout5<=4'd7;
end
else if(datain4)
begin
state<=state4;
dataout1<=4'd4;
dataout2<=4'd5;
dataout3<=4'd6;
dataout4<=4'd7;
dataout5<=4'd8;
end
state1: if(datain1)
begin
state<=state0;
dataout1<=4'd5;
dataout2<=4'd6;
dataout3<=4'd7;
dataout4<=4'd8;
dataout5<=4'd9;
end
else if(datain2)
begin
state<=state2;
dataout1<=4'd2;
dataout2<=4'd3;
dataout3<=4'd4;
dataout4<=4'd5;
dataout5<=4'd6;
end
else if(datain3)
begin
state<=state3;
dataout1<=4'd3;
dataout2<=4'd4;
dataout3<=4'd5;
dataout4<=4'd6;
dataout5<=4'd7;
end
else if(datain4)
begin
state<=state4;
dataout1<=4'd4;
dataout2<=4'd5;
dataout3<=4'd6;
dataout4<=4'd7;
dataout5<=4'd8;
end
state2: if(datain1)
begin
state<=state1;
dataout1<=4'd1;
dataout2<=4'd2;
dataout3<=4'd3;
dataout4<=4'd4;
dataout5<=4'd5;
end
else if(datain2)
begin
state<=state0;
dataout1<=4'd5;
dataout2<=4'd6;
dataout3<=4'd7;
dataout4<=4'd8;
dataout5<=4'd9;
end
else if(datain3)
begin
state<=state3;
dataout1<=4'd3;
dataout2<=4'd4;
dataout3<=4'd5;
dataout4<=4'd6;
dataout5<=4'd7;
end
else if(datain4)
begin
state<=state4;
dataout1<=4'd4;
dataout2<=4'd5;
dataout3<=4'd6;
dataout4<=4'd7;
dataout5<=4'd8;
end
state3: if(datain1)
begin
state<=state1;
dataout1<=4'd1;
dataout2<=4'd2;
dataout3<=4'd3;
dataout4<=4'd4;
dataout5<=4'd5;
end
else if(datain2)
begin
state<=state2;
dataout1<=4'd2;
dataout2<=4'd3;
dataout3<=4'd4;
dataout4<=4'd5;
dataout5<=4'd6;
end
else if(datain3)
begin
state<=state0;
dataout1<=4'd5;
dataout2<=4'd6;
dataout3<=4'd7;
dataout4<=4'd8;
dataout5<=4'd9;
end
else if(datain4)
begin
state<=state4;
dataout1<=4'd4;
dataout2<=4'd5;
dataout3<=4'd6;
dataout4<=4'd7;
dataout5<=4'd8;
end
state4: if(datain1)
begin
state<=state1;
dataout1<=4'd1;
dataout2<=4'd2;
dataout3<=4'd3;
dataout4<=4'd4;
dataout5<=4'd5;
end
else if(datain2)
begin
state<=state2;
dataout1<=4'd2;
dataout2<=4'd3;
dataout3<=4'd4;
dataout4<=4'd5;
dataout5<=4'd6;
end
else if(datain3)
begin
state<=state3;
dataout1<=4'd3;
dataout2<=4'd4;
dataout3<=4'd5;
dataout4<=4'd6;
dataout5<=4'd7;
end
else if(datain4)
begin
state<=state0;
dataout1<=4'd5;
dataout2<=4'd6;
dataout3<=4'd7;
dataout4<=4'd8;
dataout5<=4'd9;
end
default: state<=state0;
endcase
endmodule
改为三段式:
............
...........
always@(posedge clk or negedge rst_n)
if(!rst_n)
state<=state0;
else state<=next_state;
always@(state or datain1 or datain2 or datain3 or datain4)
case(state)
state0: if(datain1) next_state=state1;
else if(datain2) next_state=state2;
else if(datain3) next_state=state3;
else if(datain4) next_state=state4;
else next_state=state0;
state1: if(datain1) next_state=state0;
else if(datain2) next_state=state2;
else if(datain3) next_state=state3;
else if(datain4) next_state=state4;
else next_state=state1;
state2: if(datain1) next_state=state1;
else if(datain2) next_state=state0;
else if(datain3) next_state=state3;
else if(datain4) next_state=state4;
else next_state=state2;
state3: if(datain1) next_state=state1;
else if(datain2) next_state=state2;
else if(datain3) next_state=state0;
else if(datain4) next_state=state4;
else next_state=state3;
state4: if(datain1) next_state=state1;
else if(datain2) next_state=state2;
else if(datain3) next_state=state3;
else if(datain4) next_state=state0;
else next_state=state4;
default: next_state=state0;
endcase
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
dataout1<=4'b0;
dataout2<=4'b0;
dataout3<=4'b0;
dataout4<=4'b0;
dataout5<=4'b0;
end
else case(next_state)
state0:
begin
dataout1<=4'd5;
dataout2<=4'd6;
dataout3<=4'd7;
dataout4<=4'd8;
dataout5<=4'd9;
end
state1:
begin
dataout1<=4'd1;
dataout2<=4'd2;
dataout3<=4'd3;
dataout4<=4'd4;
dataout5<=4'd5;
end
state2:
begin
dataout1<=4'd2;
dataout2<=4'd3;
dataout3<=4'd4;
dataout4<=4'd5;
dataout5<=4'd6;
end
state3:
begin
dataout1<=4'd3;
dataout2<=4'd4;
dataout3<=4'd5;
dataout4<=4'd6;
dataout5<=4'd7;
end
state4:
begin
dataout1<=4'd4;
dataout2<=4'd5;
dataout3<=4'd6;
dataout4<=4'd7;
dataout5<=4'd8;
end
default: begin
dataout1<=4'd5;
dataout2<=4'd6;
dataout3<=4'd7;
dataout4<=4'd8;
dataout5<=4'd9;
end
endcase
endmodule
程序减少了100多行,简洁了很多 !
可以看到三段式与一段式的最大区别在于:使用一段式建模FSM的寄存器输出的时候,必须要综合考虑现态在何种状态转移条件下会进入哪些次态,然后在每个现态的case分支下分别描述每个次态的输出,这显然不符合思维习惯;而三段式建模描述FSM的状态机输出时,只需指定case 敏感表为次态寄存器,然后直接在每个次态的case分支中描述该状态的输出即可,根本不用考虑状态转移条件。
文章评论(0条评论)
登录后参与讨论