FPGA开发之状态机设计

状态机是许多数字系统的核心部件,是一类重要的时序逻辑电路。通常包括三个部分:
一是下一个状态的逻辑电路,
二是存储状态机当前状态的时序逻辑电路,
三是输出组合逻辑电路。
通常,状态机的状态数量有限,称为有限状态机(FSM)。由于状态机所有触发器的时钟由同一脉冲边沿触发,故也称之为同步状态机。根据状态机的输出信号是否与电路的输入有关分为 Mealy 型状态机和 Moore 型状态机。电路的输出信号不仅与电路当前状态有关,还与电路的输入有关,称为 Mealy 型状态机,即次态=f( 现状,输入 ) ,输出 =f (现状,输入); 而电路的输出仅仅与各触发器的状态,不受电路输入信号影响或无输入,称为 Moore 型状态机, 即 次态 =f( 现状,输 入) ,输出 =f (现状)。其标准模型如下所示:

状态机的状态转移图,通常也可根据输入和内部条件画出。一般来说,状态机的设计包含下列设计步骤:
• 根据需求和设计原则,确定是 Moore 型还是 Mealy 型状态机;
• 分析状态机的所有状态,对每一状态选择合适的编码方式,进行编码;
• 根据状态转移关系和输出绘出状态转移图;
• 构建合适的状态机结构,对状态机进行硬件描述。
状态机的描述通常有三种方法,称为一段式状态机,二段式状态机和三段式状态机。状态机的描述通常包含以下四部分:
1)利用参数定义语句 parameter 描述状态机各个状态名称,即状态编码。状态编码通常有很多方法包含自然二进制编码,One-hot 编码,格雷编码码等;
2)用时序的 always 块描述状态触发器实现状态存储;
3)使用敏感表和 case 语句(也采用 if-else 等价语句)描述状态转换逻辑;
4)描述状态机的输出逻辑。
下面根据状态机的三种方法,来比较各种方法的优劣。
1、一段式状态机
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<=0;
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;
end
endcase
end
assign out_o=out_r;
endmodule
一段式状态机是应该避免使用的,该写法仅仅适用于非常简单的状态机设计,不符合组合逻辑与时序逻辑分开的原则,整个结构代码也不清晰,不利用维护和修改。
2、两段式状态机
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
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'b1;
Next_state=Next_state;
end
endcase
end
assign out_o=out_r;
endmodule
两段式状态机采用两个 always 模块实现状态机的功能,其中一个 always 采用同步时序逻辑描述状态转移,另一个always 采用组合逻辑来判断状态条件转移。两段式状态机是推荐的状态机设计方法。
3、 三段式状态机
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:
Next_state = S1;
S1:
Next_state = S2;
S2:
Next_state = S3;
S3:
Next_state = Next_state;
default :
Next_state = S0;
endcase
end
// 输出逻辑:让输出 out ,经过寄存器 out_r 锁存后输出,消除毛刺
always@(*)
begin
case(Current_state)
S0,S2:
out_r<=1'b0;
S1,S3:
out_r<=1'b1;
default :
out_r<=out_r;
endcase
end assign out_o=out_r;
三段式状态机在第一个 always 模块采用同步时序逻辑方式描述状态转移,第二个 always 模块采用组合逻辑方式描述状态转移规律,第三个 always 描述电路的输出。通常让输出信号经过寄存器缓存之后再输出,消除电路毛刺。这种状态机也是比较推崇的,主要是由于维护方便,组合逻辑与时序逻辑完全独立。

相关推荐
DS小龙哥7 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师17 小时前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战18 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩1 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技1 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪1 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望1 天前
EDA技术简介
fpga开发
淘晶驰AK1 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发
最好有梦想~1 天前
FPGA时序分析和约束学习笔记(4、IO传输模型)
笔记·学习·fpga开发