A.20 时序逻辑实例四:状态机(三段式描述)
什么叫做三段式描述的状态机?
三段,可以理解为三个always程序块。
(1)第一个always程序块
采用同步时序逻辑电路描述状态转移。
(2)第二个always程序块
采用组合逻辑电路判断状态转移条件并描述状态转移规律。
(3)第三个always程序块
采用同步时序逻辑将结果寄存后输出。
两者的区别是将原先第二个always程序块中对y和z的组合逻辑输出改为了第三个always块的时序逻辑的寄存输出。
其实就这么简单,不少网络以及相关书籍上把它讲复杂了,甚至还给讲错了。
网络上随便搜索“三段式状态机”,基本给出的第三段always块的例子基本都是基于next_state输出的,很少看到有基于current_state输出的,这就形成了一种思维定势,认为三段式的第三段只能基于next_state描述,其实这是不对的。
应该说不管基于current_state还是next_state,目的都是要将最后输出的结果进行时钟同步后寄存器输出,并不拘泥于实现的形式,比如本节给出的例子中的第三个always块就并不是像书上和网络上那样都基于next_state来描述实现的。
这种错误的地方,除了网上以外,书本上要么没讲,要么提到的地方存在问题,至少我看到的地方有出现这种类似的错误,比如:EDA先锋工作室的《设计与验证Verilog HDL》就出现了这种错误。
下面用二段式改三段式的过程来给大家说明这两种描述方式的区别。
两段式改三段式过程
这是原本的两段式实现的代码:
//文件路径:a.19/src/sell.v
module sell(clk,rst_n,a,b,y,z);
parameter S0 = 1'b0;
parameter S1 = 1'b1;
input clk;
input rst_n;
input a,b;
output reg y,z;
reg current_state;
reg next_state;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
current_state <= S0;
else
current_state <= next_state;
end
always@(current_state or a or b)begin
y = 0;
z = 0;
case(current_state)
S0: begin
if((a == 1'b0) && (b == 1'b1))begin
y = 1;
next_state = S0;
end
else if((a == 1'b1) && (b == 1'b0))
next_state = S1;
else
next_state = S0;
end
S1: begin
if((a