verilog 状态机的分类及编写方式
本节主要谈一谈Verilog的状态机实现模板,并浅析比较。
1 一段式状态机 (单always块结构):
-
always @(posedge clk or posedge rst) begin
-
if(rst)
-
FSM <= S0
-
else begin
-
case(FSM)
-
S0:begin
-
Out_0; //输出
-
if(condition1) FSM<= S1;//状态转移
-
else if (condition2) FSM<= S2;//状态转移
-
end
-
S1:begin
-
Out_1; //输出
-
if(condition3) FSM<= S3;//状态转移
-
else if (condition4) FSM <=S4;
-
end
-
default: begin
-
Out_0; //输出
-
if(condition0) FSM<= S0;//状态转移
-
end
-
endcase
-
end
-
end
单always块把组合逻辑和时序逻辑放在一个时序always块描述。输出时为寄存器输出,所以无毛刺。但是这种方式会产生多余的触发器(因为把组合逻辑也放在时序逻辑中实现),而且代码难以修改调试。对于那些简单的状态机,一段式方便理解。但是对于复杂状态机,代码难于更改,条件复杂带来电路开销大,工作性能(电路最高频率)亦受限,因此实际中这种结构很少使用。
2 两段式状态机 (双always块结构):
-
//时序逻辑,这段一般是不变的,描述从现态转移到次态
-
always @ (posedge clk or posedge rst ) begin
-
if(rst)
-
current_state <= S0;
-
else
-
current_state<=next_state;
-
end
-
//组合逻辑,包括转移条件以及输出
-
always @ (current_state) begin
-
case(current_state)
-
S0:begin
-
Out_0; //输出
-
if(condition1) next_state <= S1;//状态转移
-
else if (condition2) next_state <= S2;//状态转移
-
else next_state <= S0;
-
end
-
S1:begin
-
Out_1; //输出
-
if(condition3) next_state <= S3;//状态转移
-
else if (condition4) next_state <=S4;
-
end
-
default: begin
-
Out_0; //输出
-
if(condition0) next_state <= S0;//状态转移
-
end
-
endcase
-
end
二段式中,一个always块采用同步时序描述状态转移;另一个采用组合逻辑判断转移条件,以及描述输出。二段式便于阅读,理解和维护,有利于综合出更少的资源。但是由于采用的是组合逻辑输出,容易产生毛刺,且不利于约束,也不利于布局布线。
3 三式状态机 (三always块结构):
-
//第一个always块,时序逻辑,描述现态转移到次态
-
always @ (posedge clk or negedge rst) begin
-
if(rst_n)
-
current_state<=S0;
-
else
-
current_state<=next_state;
-
end
-
//第二个always块,组合逻辑,描述状态转移的条件
-
always @ (current_state) begin
-
case(current_state)
-
S0:begin
-
if(condition1) next_state <= S1;//状态转移
-
else if (condition2) next_state <= S2;//状态转移
-
else next_state <= S0;
-
end
-
S1:begin
-
if(condition3) next_state <= S3;//状态转移
-
else if (condition4) next_state <=S4;
-
end
-
default: begin
-
if(condition0) next_state <= S0;//状态转移
-
end
-
endcase
-
end
-
//第三个always块,时序逻辑,描述输出
-
always @ (posedge clk or negedge rst) begin
-
if(rst)
-
out0;
-
else
-
case(current_state)
-
S0: out0
-
S1: out1;
-
default:Out0;
-
endcase
-
end
三段式结构中,2个时序always块分别用来描述状态跳转和输出。组合always块用于描述状态转移条件。虽然使用的硬件资源较多,但输出采用寄存器结构,无毛刺,而且代码更清晰易读,对于复杂的状态机来说逻辑清晰,是一种比较流行的状态机结构。
另外,对于更为复杂的状态机模型,并不限于以上结构,状态可能直接硬件多个电路,状态中包含子状态等,都会派生出更为复杂的写法。但一般来讲,小组合、大时序,状态跳转、状态转移条件判定,状态机输出分开描述,既可以做到逻辑清晰,也能控制电路的复杂度。
————————————————