1.1 状态机设计
状态机是许多数字系统的核心部件,是一类重要的时序逻辑电路。通常包括三个部分:一是下一个状态的逻辑电路,二是存储状态机当前状态的时序逻辑电路,三是输出组合逻辑电路。通常,状态机的状态数量有限,成为有限状态机(FSM)。由于状态机的所有触发器的时钟由同一脉冲边沿触发,故也称之位有限状态机。
根据状态机的输出信号是否与电路的输入有关分为Mealy型状态机和Moore型状态机。电路的输出信号不仅与电路的当前状态有关,还与电路的输入有关,称为Mealy型状态机。相反,电路的输出仅仅与各触发器的状态有关,不受电路输入信号的影响,称为Moore型状态机。其标准模型如下所示:
状态机的状态转移图,通常可以根据输入和内部条件画出。一般来说,状态机的设计包括以下设计步骤:
- 根据需求和设计原则,确定是Mealy型还是Moore型状态机。
- 分析状态机的所有状态,对每一状态选择合适的编码方式,进行编码。
- 根据状态转移关系和输出绘出状态转移图。
- 构建何使的状态机结构,对状态机进行硬件描述。
状态机的描述通常由三种描述方法,称为一段式状态,二段式状态机和三段式状态机。状态机的描述通常包括以下四个部分:
- 利用参数定义语句parameter 描述状态机的各个状态名称,即状态编码。状态编码通常有很多种方法,包括自然二进制编码、One-hot编码、格雷编码等。
- 用时序的always 块描述状态触发器实现状态存储。
- 使用敏感表和case语句(也可采用if-else)描述状态转换逻辑。
- 描述状态机的输出逻辑。
下面根据状态机的三种方法,来比较各种方法的优劣。
1.2 一段式状态机
`timescale 1ns / 1ps
module detect_1(
input clk_i,
input rst_n_i,
output out_o
);
reg out_r;
//状态声明和状态编码
reg [1:0] state;
parameter [1:0] S0 = 2'b00;
parameter [1:0] S1 = 2'b01;
parameter [1:0] S2 = 2'b10;
parameter [1:0] S3 = 2'b11;
//一段式状态机
always @(posedge clk_i)
begin
if(!rst_n_i) begin
state <= S0;
out_r <= 1'b0;
end
else
case(state)
S0:
begin
out_r <= 1'b0;
state <= S1;
end
S1:
begin
out_r <= 1'b1;
state <= S2;
end
S2:
begin
out_r <= 1'b0;
state <= S3;
end
S3:
begin
out_r <=1'b1;
state <= S0;
end
endcase
end
assign out_o = out_r;
endmodule
1.3 两段式状态机
`timescale 1ns / 1ps
//两段式状态机
module detect_2(
input clk_i,
input rst_n_i,
output out_o
);
reg out_r;
//状态声明和状态编码
reg [1:0] Current_state;
reg [1:0] Next_state;
parameter [1:0] S0 = 2'b00;
parameter [1:0] S1 = 2'b01;
parameter [1:0] S2 = 2'b10;
parameter [1:0] S3 = 2'b11;
//时序逻辑:描述状态转换
always @(posedge clk_i)
begin
if(!rst_n_i)
Current_state <= 0;
else
Current_state <= Next_state;
end
always @(*)
begin
out_r =1'b0;
case(Current_state)
S0:
begin
out_r = 1'b0;
Next_state = S1;
end
S1:
begin
out_r = 1'b1;
Next_state = S2;
end
S2:
begin
out_r =1'b0;
Next_state = S3;
end
S3:
begin
out_r = 1'b0;
Next_state = Next_state;
end
default:
begin
out_r =1'b0;
Next_state = S0;
end
endcase
end
endmodule
1.4 三段式状态机
`timescale 1ns / 1ps
module detect_3(
input clk_i,
input rst_n_i,
output out_o
);
reg out_r;
//状态声明和状态编码
reg [1:0] Current_state;
reg [1:0] Next_state;
parameter [1:0] S0 = 2'b00;
parameter [1:0] S1 = 2'b01;
parameter [1:0] S2 = 2'b10;
parameter [1:0] S3 = 2'b11;
//时序逻辑:描述状态转换
always @(posedge clk_i)
begin
if(!rst_n_i)
Current_state <= 0 ;
else
Current_state <= Next_state;
end
//组合逻辑:描述下一状态
always @(*)
begin
case(Current_state)
S0:
begin
Next_state <= S1;
end
S1:
begin
Next_state <= S2;
end
S2:
begin
Next_state <= S3;
end
S3:
begin
Next_state <= Next_state;
end
default:
Next_state = S0;
endcase
end
//输出逻辑
always @(posedge clk_i)
begin
if(!rst_n_i)
out_r <= 1'b0;
else
begin
case(Current_state)
S0,S2:
out_r <= 1'b0;
S1,S3:
out_r <= 1'b1;
default:
out_r <= out_r;
endcase
end
end
endmodule