序列检测(Verilog)

        为了实现对序列 ‘91520’ 的检测,首先画出其状态转移图,如图所示:

       由上图可以看出,如果在状态不符合转换条件,那么状态机要么回到初始态 pass_one,要么回到状态 pass_two,且每一个状态都有特定的方向,其输出仅由当前状态决定,因此这是一个摩尔型状态机,模块图如下:

       首先,使用独热码对各个状态进行定义。然后,设置好初始状态。依照状态转移图开始状态转移部分的编写。

       当在初始态 pass_one 时,如果检测到有数字 ‘9’ 输入,则跳入 pass_two 状态开始对数字 ‘1’ 的检测,否则保留在 pass_one 状态等待数字 ‘9’ 输入。

       当在状态 pass_two 时,如果检测到有数字 ‘1’ 输入,则进入 pass_three 状态开始进行对数字 ‘5’ 的检测。如果检测到有数字 ‘9’ 输入,则仍然停留在 pass_two 状态等待数字 ‘1’ 输入;如果检测到有其他数字输入时,跳回初始态 pass_one 等待新的一轮检测;否则一直在状态 pass_two 等待数字的输入。

       当在状态 pass_three 时,如果检测到有数字 ‘5’ 输入,则进入 pass_four 状态开始对数字 ‘l’ 的检测;如果检测到有数字 ‘9’ 输入,则跳转到 pass_two 状态等待数字 ‘1’ 输入;如果检测到有其他数字输入时,跳回初始态 pass_one 等待新的一轮检测;否则一直在状态 pass_three 等待数字的输入。

       当在状态 pass_four 时,如果检测到有数字 ‘2’ 输入,则进入 pass_five 状态开始数字 ‘0’ 的检测;如果检测到有数字 ‘9’ 输入,则跳转到 pass_two 状态等待数字 ‘1’ 输入;如果检测到有其他数字输入时,跳回初始态 pass_one 等待新的一轮检测;否则一直在状态 pass_four 等待数字的输入。

       当在状态 pass_five 时,如果检测到有数字 ‘0’ 输入,则说明完成一次 “91520” 的检测,回到初始态等待新的一轮检测,同时控制 key_flag 产生一个时钟脉冲;如果检测到有数字 ‘9’ 输入,则跳转到 pass_two 状态等待数字 ‘1’ 输入;否如果检测到有其他数字输入时,跳回初始态等待新的一轮检测;否则一直在状态 pass_five 等待数字的输入。

实现代码如下:

module password(
    clk,
    rst_n,
    data_in,
    data_valid,
    key_flag
);
   input       clk;
   input       rst_n;
   input [3:0] data_in;
   input       data_valid;
   output reg  key_flag;

 parameter pass_one   = 5'b0_0001;
 parameter pass_two   = 5'b0_0010;
 parameter pass_three = 5'b0_0100;
 parameter pass_four  = 5'b0_1000;
 parameter pass_five  = 5'b1_0000;

   reg [4:0]state;
 always@(posedge clk or negedge rst_n)
     if(!rst_n) begin
         state <= pass_one;
         key_flag <= 0;
     end
     else case(state)
        pass_one:
                    begin
                             key_flag <= 0;
                            if(data_valid)begin
                               if(data_in == 9 )
                                  state <= pass_two;
                               else
                                  state <= pass_one;
                       end
                            else
                               state <= state;   
                  end 

        pass_two:
                     begin   
                             if(data_valid)begin
                                 if(data_in == 1)
                                    state <= pass_three;
                                 else if(data_in == 9)
                                    state <= pass_two;
                                 else 
                                    state <= pass_one;
                        end
                             else
                                state <= state;
                  end 
        pass_three:     
                     begin
                             if(data_valid)begin
                                 if(data_in == 5)
                                    state <= pass_four;
                                 else if(data_in == 9)
                                    state <= pass_two;
                                 else 
                                    state <= pass_one;
                        end
                             else
                                state <= state;

                  end
        pass_four:     
                     begin
                             if(data_valid)begin
                                 if(data_in == 2)
                                    state <= pass_five;
                                 else if(data_in == 9)
                                    state <= pass_two;
                                 else 
                                    state <= pass_one;
                        end
                             else
                                state <= state;
                  end
        pass_five:      
                     begin
                             if(data_valid)begin
                                 if(data_in == 0)begin
                                    key_flag <= 1;
                                    state <= pass_one;
                              end
                                 else if(data_in == 9)
                                    state <= pass_two;
                                 else 
                                    state <= pass_one;
                        end
                             else
                                state <= state;

                  end
         default:state <= pass_one;
     endcase

endmodule 

仿真代码如下:

`timescale 1ns/1ns
`define clk_period 20
module password_tb();

     reg clk;
     reg rst_n;
     reg [3:0] data_in;
     reg data_valid;
     wire key_flag;

  password password(
        .clk(clk),
        .rst_n(rst_n),
        .data_in(data_in),
        .data_valid(data_valid),
        .key_flag(key_flag)
  );

 initial clk = 1;
 always #(`clk_period/2) clk = ~clk;

 initial begin
      rst_n = 0;
      data_valid = 0;
      data_in = 0;
      #(`clk_period*20);
      rst_n = 1;
      #(`clk_period*20 + 1);
   
    repeat(3) begin
      gen_key("9");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("5");
      #(`clk_period);
      gen_key("2");
      #(`clk_period);
      gen_key("0");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("5");
      #(`clk_period);
      gen_key("3");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("5");
      #(`clk_period);
      gen_key("2");
      #(`clk_period);
      gen_key("0");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("2");
      #(`clk_period);
      gen_key("4");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("3");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("4");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("3");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("9");
      #(`clk_period);
      gen_key("1");
      #(`clk_period);
      gen_key("5");
      #(`clk_period);
      gen_key("2");
      #(`clk_period);
      gen_key("0");
      #(`clk_period);
      gen_key("4");
      #(`clk_period);

     end  
      #(`clk_period*10);
      $finish;
 end

   task gen_key;
      input [3:0] key;
      begin 
         data_in = key;
         data_valid = 1;
         #(`clk_period);
         data_valid = 0;
     end
    endtask
initial begin
$fsdbDumpfile("./password_tb.fsdb");
$fsdbDumpvars(0,"password_tb"); 
$fsdbDumpSVA();
end
endmodule

 通过 Verdi 进行仿真,得到如下波形图:

 可以看到,在识别到数字序列 ‘91520’ 时,key_flag 会发出脉冲信号。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值