使用Moore状态机和Mealy状态机设计序列检测器 I
- 问题:分别使用Moore状态机和Mealy状态机设计序列检测器。该序列检测器将检测序列“101001”,当检测到该序列时,状态机的输出为1
1. 使用visio软件绘制状态转移图(采用Moore状态机)
2. 设计核心源代码(采用Moore状态机)
以下是状态机的状态及其转换逻辑:
S0:初始状态(IDLE)
S1:状态1
S2:状态101
S3:状态1010
S4:状态10100
S5:状态101001
S6:输出状态(OUT)
状态转换逻辑如下:
在 S0 状态,如果 data_in 为1,则转移到 S1;如果为0,则保持在 S0。
在 S1 状态,如果 data_in 为0,则转移到 S2;如果为1,则保持在 S1。
在 S2 状态,如果 data_in 为1,则转移到 S3;如果为0,则回到 S0。
在 S3 状态,如果 data_in 为0,则转移到 S4;如果为1,则跳转到 S1。
在 S4 状态,如果 data_in 为0,则转移到 S5;如果为1,则跳转到 S1。
在 S5 状态,如果 data_in 为1,则转移到 S6(输出状态);如果为0,则回到 S0。
在 S6 状态,无论 data_in 是1还是0,都会分别跳转到 S1 或 S2。
输出信号 data_out 的逻辑如下:
如果当前状态是 S6,则 data_out 为高电平(1’b1)。
1、在其他状态下,data_out 为低电平(0)。
2、状态机的这种设计可能用于序列检测,其中在检测到特定的输入序列后,状态机进入 S6 状态,并产生一个输出脉冲。
parameter S0 = 3'D0 ; // IDLE
parameter S1 = 3'D1 ; // 1
parameter S2 = 3'D2 ; // 101
parameter S3 = 3'D3 ; // 1010
parameter S4 = 3'D4 ; // 10100
parameter S5 = 3'D5 ; // 101001
parameter S6 = 3'D6 ; // OUT
always@( * )
begin
if( !rst_n )
n_state = 0 ;
else begin
case( c_state )
S0 : if( data_in == 1)
n_state = S1 ;
else
n_state = S0 ;
S1 : if( data_in == 0)
n_state = S2 ;
else
n_state = S1 ;
S2 : if( data_in == 1)
n_state = S3 ;
else
n_state = S0 ;
S3 : if( data_in == 0)
n_state = S4 ;
else
n_state = S1 ;
S4 : if( data_in == 0)
n_state = S5 ;
else
n_state = S1 ;
S5 : if( data_in == 1)
n_state = S6 ;
else
n_state = S0 ;
S6 : if( data_in == 1)
n_state = S1 ;
else
n_state = S2 ;
default : n_state = S0 ;
endcase
end
end
assign data_out = ( c_state == S6) ? 1'b1 : 0 ;
3. 测试核心源代码(采用Moore状态机)
这段Verilog代码是一个测试平台,用于仿真一个数字电路。它包括一个initial块来初始化输入信号并提供测试激励,以及一个always块来生成时钟信号。以下是代码的行为描述:
1、初始化输入:
clk 初始化为0,表示初始时钟信号为低电平。
rst_n 初始化为0,表示开始时复位信号为低电平,通常表示复位状态。
data_in 初始化为0,表示初始输入数据为低电平。
复位序列:
在仿真开始后100纳秒(#100),rst_n 变为1,表示复位结束。
输入激励:
2、复位结束后,通过一系列#20延迟,交替给data_in赋值1和0。这模拟了输入信号的变化,用于测试电路对这些变化的响应。
时钟信号生成:
3、always块中的#10 clk = ~clk;表示每10纳秒时钟信号取反,生成周期性的时钟信号。由于初始值为0,因此时钟信号的周期为20纳秒,对应于50MHz的频率。
4、仿真结束:
在输入了一系列的data_in信号变化后,使用#40延迟40纳秒,然后通过$finish;命令结束仿真。
这个测试平台特别适用于测试状态机或其他对时序敏感的逻辑电路。通过观察波形图或仿真结果,可以验证电路在特定输入序列下的行为是否符合预期。代码中的initial块是一次性执行的,用于仿真开始时的初始化和测试激励的施加,而always块是重复执行的,用于生成连续的时钟信号。
initial begin
// Initialize Inputs
clk = 0;
rst_n = 0;
data_in = 0;
#100 rst_n = 1;
// Wait 100 ns for global reset to finish
#20 data_in = 1 ; // Add stimulus here
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#20 data_in = 0 ;
#20 data_in = 0 ;
#20 data_in = 1 ;
#40 $finish ;
end
always #10 clk = ~clk ;
4 功能仿真波形图
5.时序仿真波形图
6.总结
有限状态机(FSM)是时序电路设计中经常用到的一种方式,尤其适用于设计数字系统的控制模块,其配合Verilog的case语句尅很好的描述基于状态机的设计。根据输出信号的产生方法的不同,可以将状态机分为 Mealy型和Moore型。简单的来说,Mealy型的输出跟当前的状态以及当前的输入是有关的,而Moore型的输出只跟当前的状态有关系。 即 当Moore型的状态机输入有变化时,需要等到时钟的到来,才会使Moore型状态机的输出变化,依赖于时钟的同步。
本文采用了Moore型的状态机去设计序列检测器,采用Mealy型状态机的设计在后文 《使用Moore状态机和Mealy状态机设计序列检测器 II 》
注:本文的源码以及状态转移图的Visio原图在下面资源中可直接下载
FPGA设计之 使用Moore状态机 设计序列检测器“101001”