三段式状态机(三段式状态机你用对了吗)
三段式状态机(三段式状态机你用对了吗)curr_state <= next_state;elsealways @(posedge clk or negedge rst_n)beginif(~rst_n)curr_state <= S_IDLE;
相信学习过硬件描述语言(如Verilog)的小伙伴对3段式状态机一定不陌生。但在工作过程中,我遇到过不少初级工程师、中级工程师乃至工作过7年左右的高级工程师 在这个使用上出现过问题。下面,我以Verilog语言描述3段式状态机,与大家分享。
顾名思义,三段式状态机是由3段组成,每一段包括一个always 模块。第一段使用时序逻辑描述状态的转移;第二段使用组合逻辑描述不同条件下的状态跳转;第三段描述状态输出,可以是组合逻辑,也可以是时序逻辑(推荐)。
1、三段式状态机描述
// 第一段,使用时序逻辑描述次级状态向当前状态转移
always @(posedge clk or negedge rst_n)begin
if(~rst_n)
curr_state <= S_IDLE;
else
curr_state <= next_state;
end
// 第二段,使用组合逻辑描述状态的跳转
always @( * )begin
case(curr_state)
S_IDLE:
if(条件1)
next_state = S_FIRST;
else
next_state = curr_state;
S_FIRST:
if(条件2)
next_state = S_SEC;
else
next_state = curr_state;
S_SEC:
if(条件3)
next_state = S_IDLE;
else //else 不能省略
next_state = curr_state;
default: next_state = S_IDLE; //default,必须写 否则会生成锁存器
endcase
end
//第三段,使用时序逻辑描述状态输出
always @(posedge clk or negedge rst_n)begin
if(~rst_n)
r_output_0 <= 1'b0;
else if(curr_state == S_FIRST)
r_output_0 <= 1'b1;
else if(curr_state == S_SEC)
r_output_0 <= 1'b0;
end
2、常见错误写法
1)第二段中,出现下述写法:
always @( * )begin
if(~rst_n) //不能使用复位,因为会把复位信号当做数据信号使用
next_state = S_IDLE;
else
case(curr_state)
S_IDLE:
......
encase
2)第二段中,出现下述情况:
case中的default 或 其他分支里if else 不是成对出现,这样会生成锁存器,对后端时序收敛不友好。