FSM要安全,稳定性高(最重要,优先级最高),即FSM不会进入死循环,特别是不会进入非预知的状态,即要求FSM的综合实现结果无毛刺等扰动,要求状态机要完备; FSM速度快,满足设计的频率要求; FSM面积小,满足设计的面积要求; FSM设计要清晰易懂,易维护;
概述:整个电路用一个进程描述,包含状态转移条件判断、状态输出和状态寄存器转移。
缺点:A、不符合时序和组合逻辑分开描述的代码风格;B、不利于修改、维护;C、不利于附加约束;D、不利于综合器和布局布线器对设计的优化;E、代码冗长。
概述:从左往右:第二个进程(纯组合逻辑always模块),描述状态转移条件的判断;第一个进程(同步时序always模块),格式化描述次态到现态的转移;一般情况下是组合逻辑输出,如果时序允许,尽量寄存器输出。
缺点:其输出一般使用组合逻辑描述,而组合逻辑易产生毛刺等不稳定因素。
Moore型状态机:状态机的输出至于当前的状态有关,如下图所示。
Mealy型状态机:状态机的输出不仅与当前的状态有关,还与当前的输入有关,如下图所示。
注意点:以上说明moore型状态机和mealy型状态机的区别所用的是两段式状态机,也就是状态输出都是采用组合逻辑输出。
如果状态输出采用寄存器输出,则需要在输出端加一个寄存器,这样会多消耗一个时钟周期,但是功能不会发生错误。
三段式状态机中为了不消耗一个额外的时钟周期,采用next_state作为判断条件,但是如果采用mealy型状态机,则此时的输入将会和next_state一起作为判断条件来判断输出,这样就会发生功能错误,如下图所示。
正确的做法是将输出_temp与当前输入再用组合逻辑输出,如下图所示,这样功能不会发生错误。
但是其实这种做法是多此一举的,因为这样做输出还是组合逻辑,没有采用寄存器输出,并且这条通路的时序相对紧张。
博主这样的画法只是想说明保证三段式mealy状态机功能正确的做法。
本节中,博主选择了两道HDLbits中的题目,来为大家更好的描述三种状态机写法以及moore、mealy状态机之间的差异。
三种描述风格
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output reg out);//
parameter A=1'b0, B=1'b1;
reg state;
always@(posedge clk or posedge areset)begin
if(areset)begin
state <= B;
out <= 1'b1;
end
else begin
case(state)
B:begin
if(in == 1'b1)begin
state <= B;
out <= 1'b1;
end
else begin
state <= A;
out <= 1'b0;
end
end
A:begin
if(in == 1'b1)begin
state <= A;
out <= 1'b0;
end
else begin
state <= B;
out <= 1'b1;
end
end
default:begin
state <= B;
out <= 1'b1;
end
endcase
end
end
endmodule
输出写在下一状态转移组合逻辑中。
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output reg out);//
parameter A=1'b0, B=1'b1;
reg current_state, next_state;
always@(posedge clk or posedge areset)begin
if(areset)begin
current_state <= B;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
B:begin
if(in == 1'b1)begin
next_state = B;
end
else begin
next_state = A;
end
out = 1'b1;
end
A:begin
out = 1'b0;
if(in == 1'b1)begin
next_state = A;
end
else begin
next_state = B;
end
out = 1'b0;
end
endcase
end
endmodule
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output reg out);//
parameter A=1'b0, B=1'b1;
reg current_state, next_state;
always@(posedge clk or posedge areset)begin
if(areset)begin
current_state <= B;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
B:begin
if(in == 1'b1)begin
next_state = B;
end
else begin
next_state = A;
end
end
A:begin
if(in == 1'b1)begin
next_state = A;
end
else begin
next_state = B;
end
end
endcase
end
always@(*)begin
if(current_state == B)begin
out = 1'b1;
end
else begin
out = 1'b0;
end
end
/*
//second way
//assign out = (current_state == B);
*/
/*
//third way
always@(*)begin
case(current_state)
B:begin
out = 1'b1;
end
A:begin
out = 1'b0;
end
endcase
end
*/
endmodule
module top_module(
input clk,
input areset, // Asynchronous reset to state B
input in,
output reg out);//
parameter A=1'b0, B=1'b1;
reg current_state, next_state;
always@(posedge clk or posedge areset)begin
if(areset)begin
current_state <= B;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
B:begin
if(in == 1'b1)begin
next_state = B;
end
else begin
next_state = A;
end
end
A:begin
if(in == 1'b1)begin
next_state = A;
end
else begin
next_state = B;
end
end
endcase
end
always@(posedge clk or posedge areset)begin
if(areset)begin
out <= 1'b1;
end
else if(next_state == B)begin
out <= 1'b1;
end
else begin
out <= 1'b0;
end
end
endmodule
说明
大家要注意,这两种写法映射到电路中没有任何区别。有一点困扰的地方是大家通常将第二种写法叫做三段式状态机的第三段。
从广义上来讲,这种叫法没有错,因为毕竟这三段分割明显,每一段做什么事情都很好理解,但是更细化,从电路结构来讲,这种写法只能称为两段式状态机,next_state到current_state采用时序逻辑,状态转移和输出采用组合逻辑,这是两段式状态机的标志。
moore型状态机:状态转移图如下:
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output reg z );
parameter S0 = 2'd0, S1 = 2'd1, S2 = 2'd2, S3 = 2'd3;
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk or negedge aresetn)begin
if(aresetn == 1'b0)begin
current_state <= S0;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
S0:begin
next_state = x ? S1 : S0;
end
S1:begin
next_state = x ? S1 : S2;
end
S2:begin
next_state = x ? S3 : S0;
end
S3:begin
next_state = x ? S1 : S2;
end
default:begin
next_state = S0;
end
endcase
end
always@(posedge clk or negedge aresetn)begin
if(aresetn == 1'b0)begin
z <= 1'b0;
end
else begin
if(next_state == S3)begin
z <= 1'b1;
end
else begin
z <= 1'b0;
end
end
end
endmodule
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
parameter S0 = 2'd0, S1 = 2'd1, S2 = 2'd2;
reg [1:0]current_state;
reg [1:0]next_state;
always@(posedge clk or negedge aresetn)begin
if(aresetn == 1'b0)begin
current_state <= S0;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
S0:begin
next_state = x ? S1 : S0;
end
S1:begin
next_state = x ? S1 : S2;
end
S2:begin
next_state = x ? S1 : S0;
end
default:begin
next_state = S0;
end
endcase
end
assign z = ((current_state == S2) && (x == 1'b1)) ? 1'b1 : 1'b0;
/*
//second way
always@(*)begin
case(current_state)
S0:begin
z = 1'b0;
end
S1:begin
z = 1'b0;
end
S2:begin
z = x;
end
endcase
end
*/
endmodule
上面两组代码就是mealy型状态机分别使用“两段式状态机”和“三段式状态机”完成的写法,这里加了引号,因为不是标准的两段式和三段式,我们最常用的两段式和三段式主要都是针对moore型状态机所说。
今天的这篇博客,基于博主自己对状态机的理解所写,包括博主曾经踩过的一些坑。
博客中对三种状态机写法,两类状态机都有一些直观的描述,其中三种状态机的写法那部分参考了邸志雄老师在慕课的课程《芯动力——硬件加速设计方法》,感兴趣的同学可以去慕课观看,希望能给大家带来帮助。
版权声明:本文为CSDN博主「wangkai_2019」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangkai_2019/article/details/107692192
以上内转载自:CSDN博主「wangkai_2019」,版权归原作者,如需转载本文,请联系原作者,文章中其它相关链接也请去原文链接内获取,欢迎大家留言讨论,谢谢!
扫码关注
动动你的发财手,给个“在看”呗!
暂无评论哦,快来评论一下吧!