赞
踩
状态机是硬件电路设计的常用的描述工具,也是电路设计的重要思想。很早之前我就知道mealy状态机和moore状态机,但是对两者的差别不是非常的清楚,最近在学习系列检测器的设计时对这两种状态机和一段式、三段式状态机有了更深刻的了解,在这里分享自己的见解给大家。有什么理解不准确的地方也希望大家指正。
在介绍两种状态机之前首先先介绍一下序列检测器。
序列检测器:从一串数据流中找到需要检测的序列号。例如如下一串数据流,需要检测的序列为11010,则每一次检测到11010时序列检测器需要输出一次使能。
设计该电路就可以使用状态机来实现。接下来讲解两种状态机区别和用这两种状态机实现该电路的状态图。
mealy状态机:输出由当前状态机状态和控制信号共同决定。
moore状态机:输出仅仅取决于当前的状态机状态。
下图时两种状态机的状态转移图
首先解释两种状态机的工作:
1.mealy状态机:s0状态表示一个最初状态,该状态检测到1表示序列11010的第一个1被检测到,跳转到s1,此时需要检测11010的第二个1,当在检测到第二个1时,跳转到s2,一次类推到跳转到s4,此时如果下一时刻检测到0,则表示检测到了所需要的序列,输出正确。
具体状态解释:s0:等待检测第一个需要的序列
s1:已经检测到1,等待检测到第二位1
s2:已经检测到11,等待检测第三位0
s3:已经检测到110, 等待检测第四位1
s4:已经检测到1101,等待检测第五位0
检测成功条件:状态机处于s4状态,并且下一个时刻输入的检测信号是0
2.moore状态机:s0表示一个空闲状态,该状态等待第一位1的到来,当检测到第一个1后,跳转到s1,等待检测第二位1,一次类推直到跳转到s5。
具体状态解释:s0:等待检测第一个需要的序列
s1:已经检测到1,等待检测到第二位1
s2:已经检测到11,等待检测第三位0
s3:已经检测到110, 等待检测第四位1
s4:已经检测到1101,等待检测第五位0
s5:已经检测到11010
检测成功条件:状态机处于s5状态。
在该电路中,两种状态机本质上,moore状态机是比mealy多一个s5状态,moore状态机就是通过判定是否处于该状态来判定条件是否正确,而mealy状态机则时通过s4状态以及下一个时刻的条件信号是否有效来判定条件是否正确。
- module sequence_11010_chack (
- input clk ,
- input rst_p ,
- input sequence_num ,
- output num_en
- );
-
- localparam s0 = 5'd0 ;
- localparam s1 = 5'd1 ;
- localparam s2 = 5'd2 ;
- localparam s3 = 5'd4 ;
- localparam s4 = 5'd8 ;
- localparam s5 = 5'd16 ;
-
- reg [ 4 : 0 ] cur_state ;
- reg chack_right ;
-
- reg [ 4 : 0 ] next_state ;
-
- //-----------------------------------------------------------------------
- //-----mealy状态机
- //---三段式实现
- //--序列11010检测
- //-----------------------------------------------------------------------
-
- //第一段
- always @(posedge clk) begin
- if(rst_p)
- cur_state <= 5'd0 ;
- else
- cur_state <= next_state ;
- end
-
- //第二段
- always @( *) begin
- case(cur_state)
- s0 : next_state = (sequence_num) ? s1 : s0 ;
- s1 : next_state = (sequence_num) ? s2 : s0 ;
- s2 : next_state = (sequence_num) ? s2 : s3 ;
- s3 : next_state = (sequence_num) ? s4 : s0 ;
- s4 : next_state = (sequence_num) ? s1 : s0 ;
- default : next_state = s0 ;
- endcase
- end
-
- //第三段
- always @(posedge clk) begin
- if(rst_p)
- chack_right <= 1'b0 ;
- else begin
- case(cur_state)
- s4 : chack_right <= (sequence_num) ? 1'b0 : 1'b1 ;
- default : chack_right <= 1'b0 ;
- endcase
- end
- end
-
- assign num_en = chack_right ;

mealy状态机输出与当前状态以及输入信号有关 可以看到代码中chack_right信号是由cur_state和sequence_num共同决定的。
- module sequence_11010_chack (
- input clk ,
- input rst_p ,
- input sequence_num ,
- output num_en
- );
-
- localparam s0 = 5'd0 ;
- localparam s1 = 5'd1 ;
- localparam s2 = 5'd2 ;
- localparam s3 = 5'd4 ;
- localparam s4 = 5'd8 ;
- localparam s5 = 5'd16 ;
-
- reg [ 4 : 0 ] cur_state ;
- reg chack_right ;
-
- //-----------------------------------------------------------------------------
- //----------Moore状态机
- //---三段式
- //--序列11010检测
- //-----------------------------------------------------------------------------
- reg [ 4 : 0 ] next_state ;
-
- //第一段
- always @(posedge clk) begin
- if(rst_p)
- cur_state <= 5'd0 ;
- else
- cur_state <= next_state ;
- end
-
- //第二段
- always @( *) begin
- case(cur_state)
- s0 : next_state = (sequence_num) ? s1 : s0 ;
- s1 : next_state = (sequence_num) ? s2 : s0 ;
- s2 : next_state = (sequence_num) ? s2 : s3 ;
- s3 : next_state = (sequence_num) ? s4 : s0 ;
- s4 : next_state = (sequence_num) ? s2 : s5 ;
- s5 : next_state = (sequence_num) ? s1 : s0 ;
- default : next_state = s0 ;
- endcase
- end
-
- //第三段
- always @(*) begin
- case(cur_state)
- s5 : chack_right = 1'b1 ;
- default : chack_right = 1'b0 ;
- endcase
- end
-
- assign num_en = chack_right ;

moore状态机输出只与当前状态有关,从代码中表示就是输出chack_right信号只要当cur_state处于s5就输出1,反之就输出0。
- `timescale 1ns/1ps
-
- module sequence_11010_chack_tb;
-
- // Parameters
-
- //Ports
- reg clk=0;
- reg rst_p=1;
- reg sequence_num=0;
- reg [4:0] tb_data = 5'b11010;
- wire num_en;
-
- sequence_11010_chack sequence_11010_chack_inst (
- .clk(clk),
- .rst_p(rst_p),
- .sequence_num(sequence_num),
- .num_en(num_en)
- );
-
- always #5 clk = ! clk ;
-
- initial begin
- #201;
- rst_p = 1'b0 ;
-
- //1
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //2
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //3
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //4
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //5
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //6
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //7
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[3:0],tb_data[4]};
- end
-
- //移位方向改变
-
- //1
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[0],tb_data[4:1]};
- end
-
- //2
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[0],tb_data[4:1]};
- end
-
- //3
- @(posedge clk)begin
- sequence_num <= tb_data[4] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[3] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[2] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[1] ;
- end
- @(posedge clk)begin
- sequence_num <= tb_data[0] ;
- tb_data <= {tb_data[0],tb_data[4:1]};
- end
-
- #100;
- $stop;
- end
-
- endmodule

仿真结果如下:
本文参考了csdn、知乎上相关文章。如果存在什么问题请指正!!!
完成工程和仿真代码如下链接免费下载:【免费】verilog序列检测器,序列11010,(mealy状态机和moore状态机)资源-CSDN文库
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。