【3段式状态机】— 序列检测器(序列可重叠)


序列检测器是个啥

检测输入的一串二进制代码中,是否存在与事先设定的码组一致的代码串,检测电路输出高电平,否则输出低电平

序列检测器用在什么地方:

检测通信系统中的同步码、提取所需信号

要做的事:

使用状态机检测出一串数字序列中的指定6位数据:101011

 实践:

S0:IDLE

S1:检测1

S2:检测10

S3:检测101

S4:检测1010

S5:检测10101

S6:检测101011

《关于状态需要返回去东山再起》

  • 是否需要返回:不满足检测序列就需要返回
  • 前面几位能用:有几位满足检测序列顺序
  • 自己能否作为起点:自己和序列第1 位相同就能作为起点

一、设计文件

module seq_1010110
(
input clk                    ,
input rst_n                    ,
input data                    ,

output reg flage
);

reg [2:0]state ;// 下面对状态编码用了1-7,所以这里需要用3位的位宽
reg [2:0]next_state;

parameter S0 = 3'd1;// IDLE 
parameter S1 = 3'd2;
parameter S2 = 3'd3;
parameter S3 = 3'd4;
parameter S4 = 3'd5;
parameter S5 = 3'd6;
parameter S6 = 3'd7;

always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    state <= S0;
else 
    state <= next_state;
end

always@(*)
    case(state)
        S0:
        if(data == 1)
            next_state <= S1;
        else 
            next_state <= S0;
        S1:
        if(data == 0)
            next_state <= S2;
        else 
            next_state <= S0;
        S2:
        if(data == 1)
            next_state <= S3;
        else 
            next_state <= S0;
        S3:
        if(data == 0)
            next_state <= S4;
        else 
            next_state <= S1;
        S4:
        if(data == 1)
            next_state <= S5;
        else 
            next_state <= S0;
        S5:
        if(data == 1)
            next_state <= S6;
        else 
            next_state <= S4;
        S6:
        if(data == 0)
            next_state <= S2;
        else 
            next_state <= S1;
        
    endcase 

always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)
    flage <= 1'b0;    
else if(state == S6 && data == 0) // Mealy状态机:输出由输入和状态共同决定   
    flage <= 1'b1;
else 
    flage <= 1'b0;        
end    

endmodule 

二、测试文件

`timescale 1ns/1ps

module sequence1010110_tb();
reg                            clk;
reg                            rst_n;
reg                            data;

wire                           flag;
reg             [15:0]        ascii_state;//用了2位字符S0-S6,1位字符8bit,所以这里位宽是16
wire             [2:0]            tb_state;

assign tb_state = seq_1010110_inst.state;

always@(*)begin // 在波形图上能看到用S表示的状态ascii_state
  case(tb_state)
        3'd1    :    ascii_state = "S0";
        3'd2    :    ascii_state = "S1";
        3'd3    :    ascii_state = "S2";
        3'd4    :    ascii_state = "S3";
        3'd5    :    ascii_state = "S4";
        3'd6    :    ascii_state = "S5";
        3'd7    :    ascii_state = "S6";
        default :  ascii_state = "NO";
  endcase
end

initial begin 
 
 clk = 1'b0;
 rst_n = 1'b0;
 data = 1'b0;
 #10;
 rst_n = 1'b1;
 end
 always #10 clk = ~ clk;
 
 
 always begin
 #20;
 data = 1'b1;
 #20;
 data = 1'b0;
  #20;
 data = 1'b1;
  #20;
 data = 1'b0;
  #20;
 data = 1'b1;
  #20;
 data = 1'b1;
  #20;
 data = 1'b0;
  #20;
 data = 1'b1;
 
 end

    seq_1010110 seq_1010110_inst(
        .clk                 (clk),
        .rst_n               (rst_n),
        .data                (data),

        .flage                    (flag)
    );

endmodule

三、波形图

怎么看波形:

  • 重点看state和data,next_state只是用来给state传递数据的,可以不用重点看
  • 重点看flag在什么时候被拉高,除了要在时钟上升沿,还需要注意是否需要比 (state == S6 && data == 0) 慢一拍

四、RTL图


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM