序列检测器:状态转移图+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设计的学习心得(二) 

来自  

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实验——序列检测器的实现 

来自   

 

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

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 

来自   

错误是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并解决了问题。 

来自   

 

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

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

来自   

【参考】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"]      

绘图 

序列检测器:状态转移图+Morrer状态机(三段式)+Modelsim仿真_第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"]    


 

绘图 

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

 

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的简单使用 

来自   

 

 

5、调试修改代码 

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

来自   

 

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

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

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

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

 

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

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

 

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

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

 

还是有延时 

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

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

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

 

改为以下方法,延时消失 

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

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

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

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

 

你可能感兴趣的:(FPGA)