I 三段式状态机:
包含:
当前状态,下一状态,输出状态。
一个always模块采用同步时序的方式,描述状态转移。
一个always采用组合逻辑的方式判断状态转移条件,描述状态转移规律。
其他always模块使用同步时序电路来设计每一个状态的输出。
三段状态机的好处:既可以用现态current_state 作为条件,也可以用次态next_state作为条件。用现态current_state 作为条件会比用次态next_state作为条件晚一个时钟周期
1 第一段状态机
描述次态寄存器迁移到现态寄存器。(时序)
复位就去初始状态,否则的话就把次态赋给现态。
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
2 第二段状态机
描述状态转移条件的判断(组合)
always@(*)begin
case(current_state)begin
IDLE:begin
if(???) //填补判断条件
next_state = S1;
else
next_state = IDLE;
S1:begin
if(???) //填补判断条件
next_state = S2;
else
next_state = S1;
end
S2:begin
??? //填补所需状态
default:
next_state = IDLE;
endcase
end
3 第三段状态机
可以是一个或多个always块(时序)
描述对应状态的输出
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
//此处写各种输出的初始化
end
else if (current_state == S1)begin
??? <= ???; //此处写达到该状态并满足某条件的话应该输出什么
end
else begin
??? <= ???; //此处写如果没有达到该状态或不满足某条件 输出应该保持什么值
end
end
II 小例题
状态机有三个状态,IDLE,S1和S2。在IDLE状态,如果en=1,则跳到S1状态,否则保持不变。在S1状态,如果en=1,则跳到S2状态,否则保持不变。在S2状态,如果en=1,输出vld=1,并且跳回到IDLE状态,否则保持不变。
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)begin
IDLE:begin
if(en == 1)
next_state = S1;
else
next_state = IDLE;
S1:begin
if(en == 1)
next_state = S2;
else
next_state = S1;
end
S2:begin
if(en == 1)
next_state = IDLE;
else
next_state = S2;
default:
next_state = IDLE;
endcase
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
vld = 1'b0;
end
else if (current_state == S2 && en ==1)begin
vld = 1'b1;
end
else begin
vld = 1'b0;
end
end