verilog实现序列检测(状态机和移位寄存器实现)

前言

用Verilog描述一个可综合的序列检测器用于检测输入数据码流中的特定序列。本文介绍了使用状态机来直接描述和采用移位寄存器的方式进行检测的两种方法。同时,也给出了tb文件和仿真波形图。

状态机方法

本文实现了对序列“1010”的检测,第一种方法我们采用状态机的写法进行检测。 首先画出状态转移图,如下: 含义描述如下:A状态相当于idle状态,此刻若输入一个1,则会转移至下一状态,否则保持此状态,同理,当依次输入1010时,状态转移至E,且输出为1,表示检测到序列1010,随后若再次输入1,则会重新跳转至A状态,开始新的序列检测。 下面给出代码:

//check_sequence FSM
`timescale 1ns/1ns
module tb();
  wire out;
  reg clk, rst;
  reg data_in;

  check_sequence dut(.clk(clk), 
                     .rst(rst),
                     .ina(data_in),
                     .out(out)
                    );
  initial begin
    clk <= 0;
    forever begin 
      #5 clk <= ~clk;
    end
  end

  initial begin//给出一段码流数据
    #20 data_in = 1;
    #20 data_in = 0;
    #20 data_in = 1;
    #20 data_in = 0;
    #20 data_in = 0;
    #20 data_in = 0;
    #20 data_in = 1;
    #20 data_in = 0;
    #20 data_in = 1;
    #20 data_in = 0;
    #500 $stop;
    $display("check finished");
  end

  initial begin
    #10 rst <= 0;
    #20 rst <= 1;
  end
endmodule

module check_sequence(input clk, input rst, input ina, output out); 
  reg[1:0] state, next_state;
  reg out;
  
  parameter A = 3b000, B = 3b001, C = 3b010, D = 3b011, E = 3b100;

  always @(posedge clk or negedge rst)
    if (!rst)
      state <= A;
    else 
      state <= next_state;

  always @(state or ina)//state transition
    begin
      next_state <= A;
      case(state)
        A: begin
          if (ina == 1)
            next_state <= B;
          else 
            next_state <= A;
            out <= 0;
           end
        B: begin
          if (ina==1)
            next_state <= B;
          else
            next_state <= C;
            out <= 0;
           end
        C: begin
          if (ina==1)
            next_state <= D;
          else
            next_state <= C;
            out <= 0;
           end
        D: begin
          if (ina==1)
            next_state <= D;
          else
            next_state <= E;
            out <= 1;
           end
        E: begin
          if (ina==1)
            next_state <= A;
          else
            next_state <= E;
            out <= 0;
           end
        default: next_state <= A;
      endcase
    end
 endmodule

仿真波形如下: 可以看到,当检测到1010时,out信号会拉高。

移位寄存器方法

此方法的基本思路就是利用移位寄存器作为检测窗口,每进来一个数就跟目标序列进行比较。 直接给出代码如下:

//shift regeister detection
//test sequence: 1010

`timescale 1ns/1ns
module tb();
  wire check_rst, ina;
  reg clk, rst;
  reg [23:0] data;//give data in sequence

  assign ina = data[23];
  check_sequence1 dut(.clk(clk), 
                      .rst(rst), 
                      .check_rst(check_rst),
                      .ina(ina)
                     );

  initial begin
    clk <= 0;
    forever begin
      #5 clk <= ~clk;
    end
  end

  initial begin
    #10 rst <= 0;
    repeat(2) @(posedge clk);
    rst <= 1;
  end

  initial begin

    data = 24b1100_1010_0011_1101_1010_1011;
    #500 $stop;
  end
  always @(posedge clk) begin

    #2 data = {
          
   data[22:0],data[23]};
  end
endmodule

module check_sequence1 (input ina, input clk, input rst, output check_rst);
  parameter check_sq = 4b1010;//check_sequence
  reg [3:0] buffer;

  assign check_rst = (buffer == check_sq)? 1:0;
  always @(posedge clk or negedge rst) begin
    if (!rst)
      buffer <= 4b0000;
    else 
      buffer <= {
          
   buffer[2:0],ina};
    end
endmodule

仿真波形如下:

经验分享 程序员 微信小程序 职场和发展