序列检测器:状态转移图+Morrer状态机(三段式)+Modelsim仿真 

序列检测器:状态转移图+Morrer状态机(三段式)+Modelsim仿真 

 

目录 

    - 1、绘制状态转移图 

        - 1.1、在Sublime 中用Graphviz绘制状态转移图 

        - 1.2、在Notepad++ 中用Graphviz绘制状态转移图 

        - 1.2、Morrer与Mealy型状态机的状态转移图对比 

    - 2、Morrer状态机代码 

    - 3、仿真TestBench代码 

    - 4、Modelsim仿真 

    - 5、调试修改代码 

    - 6、仿真和调试问题以及解决思路 

 

 

【参考文章】 

1、第6章  如何写好状态机  节选自《Verilog设计与验证》 作者:吴继华、王诚   

下载PDF看原文  http://read.pudn.com/downloads328/ebook/1442931/A.pdf 

或者看总结  Verilog FSM设计的学习心得(二) 

来自 <https://www.cnblogs.com/freeny/archive/2012/04/15/2450168.html

2、【 FPGA 】序列检测器的Moore状态机实现 

https://blog.csdn.net/Reborn_Lee/article/details/85763185 

3、【 FPGA 】序列检测器的Mealy状态机实现 

https://blog.csdn.net/Reborn_Lee/article/details/85798105 

4、Verilog实现--序列检测器、自动饮料售卖机 

https://blog.csdn.net/qq_34070723/article/details/100737225 

5、第一次verilog实验——序列检测器的实现 

来自 <https://www.cnblogs.com/yulongchen/archive/2013/02/13/2911046.html>  

 

【注意】《如何写好状态机》中的模板有适用范围 

Altera模块声明如下: 

module state (  

    nrst,clk, 

    i1,i2, 

    o1,o2, 

);  

input          nrst,clk;  

input          i1,i2, 

output        o1,o2;     

reg             o1,o2;   

 

Xilinx的模块声明如下: 

module state (  

    input nrst,clk, 

    input  i1,i2, 

    output reg o1,o2,err 

);  

 

【目标】设计一个序列检测器(无重叠检测),检测序列1101,检测到输出1,否则输出0 

 

1、绘制状态转移图 

1.1、在Sublime 中用Graphviz绘制状态转移图 

【参考】Graphviz 安装及结合sublime 

来自 <https://zhuanlan.zhihu.com/p/22820399>  

错误是file or directory not found, 

但报告的内容path看起来有些混乱-即它不包括macports放置可执行文件的目录。 

看着https://forum.sublimetext.com/t/how-to-set-path-on-os-x-so-sublime-can-see-it/11842 

重新启动Sublime并解决了问题。 

来自 <https://gist.github.com/olange/6834323ffc613b2ba25f>  

 

1.2、在Notepad++ 中用Graphviz绘制状态转移图 

【参考】NppGraphViz,一个Notepad ++插件,可将当前选项卡的文档发送到GraphViz预览窗口。 

来自 <https://github.com/jrebacz/NppGraphViz>  

【参考】NppGraphViz不添加语法突出显示,但是可以在此处使用该功能: https://github.com/signmotion/graphviz-syntax-highlighting 

 

1.2、Morrer与Mealy型状态机的状态转移图对比 

 

 

Morrer型状态机:摩尔状态机的输出仅仅依赖于当前状态,而与输入条件无关 

Graphviz 代码Sequencer-Moore.gv 如下 

digraph fsm { 

    "IDLE"   -> "IDLE"   [label= "0"] 

    "IDLE"   -> "S1"     [label= "1"]        

 

    "S1"     -> "IDLE"   [label= "0"] 

    "S1"     -> "S2"     [label= "1"]        

    

    "S2"     -> "S2"     [label= "1"] 

    "S2"     -> "S3"     [label= "0"]  

    

    "S3"     -> "S4"     [label= "1"] 

    "S3"     -> "IDLE"   [label= "0"] 

    

    "S4"     -> "IDLE"   [label= "0"] 

    "S4"     -> "S1"     [label= "1"]      

绘图 

 

 

 

米勒状态机:空闲态+中间3态,输出时由当前态S3+输入态,共同决定 

Graphviz 代码Sequencer-Mealy.gv 如下 

digraph fsm { 

    "IDLE"   -> "IDLE"   [label= "0"] 

    "IDLE"   -> "S1"     [label= "1"]        

 

    "S1"     -> "IDLE"   [label= "0"] 

    "S1"     -> "S2"     [label= "1"]        

    

    "S2"     -> "S2"     [label= "1"] 

    "S2"     -> "S3"     [label= "0"]  

    

    "S3"     -> "IDLE"   [label= "1"] 

    "S3"     -> "IDLE"   [label= "0"]    


 

绘图 

 

2、Morrer状态机代码 

Sequencer_Morrer.v 源代码如下: 

`timescale 1ns / 1ps 

SourceCode:Logic 

// Company:  

// Engineer:  

//  

// Create Date: 2019/01/04 11:16:29 

// Design Name:  

// Module Name: seq_det_moore 

// Project Name:  

// Target Devices:  

// Tool Versions:  

// Description:   Sequencer  Detection - Moore FSM 

// 设计一个序列检测器,检测序列1101,检测到输出1,否则输出0 

// 摩尔状态机的输出仅仅依赖于当前状态,而与输入条件无关 

// Dependencies:  

//  

// Revision: 

// Revision 0.01 - File Created 

// Additional Comments: 

//  

// 

`define UD #1  //定义变量,可跨工程调用 UD  user delay,初始化#1 

module seq_det_moore( 

    input   i_clk, 

    input   i_rst_n,     //系统复位,低电平有效 

    input   i_data, 

    output  reg o_out 

); 

 

//================================================= 

//input dalay:输入打一拍 

//================================================= 

reg i_data_reg = 1'b0; 

always @ (posedge i_clk) 

begin 

//    if(i_rst_n) 

    i_data_reg <= i_data; 

end 

//================================================= 

// state FSM:状态声明,4个有效状态+1个空闲状态 

//================================================= 

reg [3:0]   CS,NS;    //CS:Current State; NS:Next State 

localparam [3:0]    //one hot with zero idle 

    IDLE  = 4'b0000, 

    S1    = 4'b0001, 

    S2    = 4'b0010, 

    S3    = 4'b0100, 

    S4    = 4'b1000; 

 

//================================================= 

// FSM input 

//================================================= 

//1st always block:sequential state transition 

//现态与次态转换  时序电路 

always @(posedge i_clk)  

begin 

    if (!i_rst_n)    begin 

        CS <= IDLE;   // reset 

//        i_data_reg <= 1'b0;     //复位态,数据首位,赋值为0,则状态判断延时2clk 

    end 

    else 

        CS <= NS; 

end 

 

//2nd always block:combinational condition judgment  

//第二段:各种状态间的跳变。 组合电路  

always @ (*)  

begin 

    case(CS)   //状态转移,判断当前状态"CS" 

    IDLE:begin 

            if  (i_data_reg)    NS = S1;    //第一位1,din == 1'b1 

            else                NS = IDLE;  //din == 1'b0 

        end 

    S1: begin 

            if  (i_data_reg)    NS = S2;    //1,  11     

            else                NS = IDLE;  //10,回到原点 

        end             

    S2: begin 

            if  (~i_data_reg)   NS = S3;    //0,  110     

            else                NS = S2;    //111,等待/循环,11101 

        end         

    S3: begin 

            if  (i_data_reg)    NS = S4;    //1,  1101     

            else                NS = IDLE;  //1100,回到原点 

        end 

    S4: begin 

            if  (i_data_reg)    NS = S1;    //下一组,第一位1    

            else                NS = IDLE;  //下一组,第一位0,回原点  

        end         

    default:                    NS = IDLE; 

    endcase 

end 

 

//================================================= 

// FSM output: Moore型,输出只与当前状态有关 

//================================================= 

//3rd always block:the sequential FSM output 

//第三段:确定最终的状态 

always @(posedge i_clk)  

begin 

    if ( CS == S4)  o_out <= 1; 

    else            o_out <= 0;         

end 

 

endmodule 

 

 

3、仿真TestBench代码 

TB_Sequencer_Morrer.v 源代码如下: 

`timescale 1ns / 1ps 

//SimulationCode:Test Bench/ 

// Company:  

// Engineer:  

//  

// Create Date: 2019/01/04 15:24:59 

// Design Name:  

// Module Name: seq_det_moore_tb 

// Project Name:  

// Target Devices:  

// Tool Versions:  

// Description:  

// 数据一开始就发送过去,第一个clk上升沿就接到信号,开始判断,但当前状态一直循环为空 

//就等解除复位态,下一个数据过来,进入下一状态 

//最终输出没有延时,相当于前4个clk上升沿输入信号,第5个clk上升沿 输出结果 

// Dependencies:  

//  

// Revision: 

// Revision 0.01 - File Created 

// Additional Comments: 

//  

// 

`define UD #1 

module seq_det_moore_tb; 

 

reg sim_clk; 

reg sim_rst_n; 

reg sim_i_data;   //输入序列,缓冲,赋值 

wire sim_o_out; 

 

// Note: CLK must be defined as a reg when using this method 

parameter CLK_PERIOD = 10;     //仿真周期10ns=100M 

parameter RST_CYCLE = 5;        //复位周期数 

parameter RST_TIME = RST_CYCLE * CLK_PERIOD;    //复位时间:5个时钟周期 

parameter IN_SEQ = 21'b1_1011_1010_1101_0010_1101; 

//时钟  10ns 

always #(CLK_PERIOD/2) sim_clk = ~sim_clk; 

/* 

//时钟:写法2 

always begin 

     i_clk = 1'b0; 

     #(CLK_PERIOD/2) clk = 1'b1; 

     #(CLK_PERIOD/2); 

end 

*/ 

reg [4:0]cnt; 

//过程赋值,一次性复位信号??????????? 

initial  

begin 

    sim_clk = 1'b0; 

    sim_rst_n = 1'b0;                //复位再拉低,有效,保持足够长时间(5个clk) 

    #RST_TIME sim_rst_n = 1'b1;      //复位 

    sim_i_data = 1'b0;              //测试变量,赋初值 

end 

//过程赋值,循环,每次只改变数据的位数cnt 

always @(posedge sim_clk) 

begin 

    if(!sim_rst_n)    begin 

        cnt <= 1'b0; 

//        sim_i_data <= 1'b0;     //复位态,数据首位,保持0 

    end 

    else begin 

        cnt <= cnt +1'b1; 

        sim_i_data <= IN_SEQ[cnt];      

        //sim_i_data不输出,sim_i_data与IN_SEQ[cnt]有1个clk的延时,仅用于原始信号变化 

    end 

end 

    //模块实例,调用 

    seq_det_moore u1( 

        .i_clk     ( sim_clk       ),//input       clk, 

        .i_rst_n   ( sim_rst_n     ),//input       rstn, 

        .i_data    ( IN_SEQ[cnt]   ), 

        //每次送一位数据,第0位数据在复位态就已经发送,第1位数据在解除复位后发送 

        //.i_data    ( sim_i_data   ), 

        //解除复位后,才发送数据 

        .o_out     ( sim_o_out     ) 

    ); 

endmodule 

 

4、Modelsim仿真 

【参考】Modelsim的简单使用 

来自 <https://mp.weixin.qq.com/s/rTdjYNQV8Q1OnIuFYI0IPA>  

 

 

5、调试修改代码 

【参考】修改代码后如何使用 modelsim 仿真 

来自 <https://blog.csdn.net/qq_40793742/article/details/82830513>  

 

6、仿真和调试问题以及解决思路 

主要问题是输入序列到输出结果之间有延时 

下图写错了,应该是检测1101,延时分别为3.5clk 与 1.5clk 

 

原因1、Testbench文件中,赋值为循环,一次性送完数据,时间长 

 

2、改为循环中每次只改变送的数据位,每次送一位数据 

 

还是有延时 

Q1、复位态不发送数据,解除复位态后才发送, 

输入数据打一拍,FSM第二阶段判断也要clk等,延时有4个clk 

 

改为以下方法,延时消失 

Q2: 数据一开始就发送过去,第一个clk上升沿就接到信号,开始判断,但当前状态一直循环为空 

就等解除复位态,下一个数据过来,进入下一状态 

最终输出没有延时,相当于前4个clk上升沿输入信号,第5个clk上升沿 输出结果 

 

  • 4
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计一个110101序列检测器,可以使用有限状态机(Finite State Machine)来实现。 首先,我们需要定义状态集合和状态转移条件: 状态集合:S = {A, B, C, D, E, F} 状态转移条件: - 输入为0时,从状态A、B、C、D、E、F转移状态A、B、C、D、E、F; - 输入为1时,从状态A转移状态B,从状态B转移状态C,从状态C转移状态D,从状态D转移状态E,从状态E转移状态F,从状态F转移状态B。 根据以上状态集合和状态转移条件,我们可以画出状态转移: ![110101 FSM](https://i.imgur.com/0qk9BZ3.png) 其中,圆圈表示状态,箭头表示状态转移条件,标注在箭头上的数字表示输入信号。 最后,我们需要将状态转移转换状态转移表: | 状态 | 输入0 | 输入1 | |------|------|------| | A | A | B | | B | A | C | | C | A | D | | D | A | E | | E | A | F | | F | A | B | 状态转移表中,每一行代表一个状态,列代表输入信号。在状态转移表中,我们可以找到当前状态和输入信号,然后查找对应的下一状态。 通过状态转移表,我们可以写出代码实现110101序列检测器: ```python # 定义状态集合 S = ['A', 'B', 'C', 'D', 'E', 'F'] # 定义状态转移表 transitions = { 'A': {'0': 'A', '1': 'B'}, 'B': {'0': 'A', '1': 'C'}, 'C': {'0': 'A', '1': 'D'}, 'D': {'0': 'A', '1': 'E'}, 'E': {'0': 'A', '1': 'F'}, 'F': {'0': 'A', '1': 'B'} } # 定义初始状态 current_state = 'A' # 定义输入序列 input_sequence = '110101' # 逐个读取输入信号,进行状态转移 for input_signal in input_sequence: next_state = transitions[current_state][input_signal] current_state = next_state # 判断最终状态是否为F if current_state == 'F': print('输入序列包含110101') else: print('输入序列不包含110101') ``` 这样,我们就实现了一个基于有限状态机的110101序列检测器

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值