【牛客网刷题系列 之 Verilog进阶挑战】~ 序列检测专题

0. 前言

对于序列检测的题目,一般可以用两种方法完成:状态机 或者 移位寄存器。

可以参考一下这篇博客,这是我之前写的,现在为了刷题,规整了一下,里边讲解的很清楚了,这里我就不多说了,直接传送门

1. 题目VL25 输入序列连续的序列检测

1.1 题目描述

请编写一个序列检测模块,检测输入信号a是否满足01110001序列,当信号满足该序列,给出指示信号match。

1.1.1 信号示意图

在这里插入图片描述

1.1.2 波形示意图

在这里插入图片描述

1.1.3 输入描述

clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据

1.1.4 输出描述

match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0

1.2 解题思路

该题的状态转移图如下所示:
在这里插入图片描述
其实,这类题写出状态转移图就简单了不少,剩下的就交给状态机,哈哈哈!!!

1.3 代码实现

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);

    parameter
        s0 = 8'b0000_0001,
        s1 = 8'b0000_0010,
        s2 = 8'b0000_0100,
        s3 = 8'b0000_1000,
        s4 = 8'b0001_0000,
        s5 = 8'b0010_0000,
        s6 = 8'b0100_0000,
        s7 = 8'b1000_0000;
    reg [7:0] cur_state, nex_state;
    
    // step one
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           cur_state <= 8'd0; 
        end
        else begin
           cur_state <= nex_state; 
        end
    end
    //step two
    always @ (*) begin
        case(cur_state)
            s0 : nex_state = a ? s1 : s0;
            s1 : nex_state = a ? s2 : s0;
            s2 : nex_state = a ? s3 : s0;
            s3 : nex_state = a ? s0 : s4;
            s4 : nex_state = a ? s1 : s5;
            s5 : nex_state = a ? s1 : s6;
            s6 : nex_state = a ? s7 : s0;
            s7 : nex_state = s0;
            default : nex_state = s0;
        endcase
    end
    //step three
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           match <= 1'b0; 
        end
        else begin
           match <=  (cur_state == s7) ? 1'b1 : 1'b0;
        end
    end
//     assign match = (cur_state == s7) ? 1'b1 : 1'b0;
endmodule

1.4 测试文件

待更新。。。

1.5 仿真波形

待更新。。。

2. VL26 含有无关项的序列检测

2.1 题目描述

请编写一个序列检测模块,检测输入信号a是否满足011XXX110序列(长度为9位数据,前三位是011,后三位是110,中间三位不做要求),当信号满足该序列,给出指示信号match。

2.1.1 信号示意图

在这里插入图片描述

2.1.2 波形示意图

在这里插入图片描述

2.1.3 输入描述

clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据

2.1.4 输出描述

match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0

2.2 解题思路

该题的状态转移图如下所示:
在这里插入图片描述
这个题相比于上一个题而言,多了几个不定态,那变化的地方就是这几个不定态的状态转移图有些变化,只不过不用再判断这几个不定态的输入,就可以直接确定它的下一个状态了,反而简单了不少。
这个题我给出了两种解法,可以参考一下!

2.3 代码实现

2.3.1 状态机法

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);

// ============================状态机法==========================================================
// /*
   parameter
        IDLE = 10'b00_0000_0001,
        s0 = 10'b00_0000_0010,
        s1 = 10'b00_0000_0100,
        s2 = 10'b00_0000_1000,
        s3 = 10'b00_0001_0000,
        s4 = 10'b00_0010_0000,
        s5 = 10'b00_0100_0000,
        s6 = 10'b00_1000_0000,
        s7 = 10'b01_0000_0000,
        s8 = 10'b10_0000_0000;
    reg [9:0] cur_state, nex_state;
    
    // step one
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           cur_state <= IDLE; 
        end
        else begin
           cur_state <= nex_state; 
        end
    end
    //step two
    always @ (*) begin
        case(cur_state)
            IDLE : nex_state = a ? IDLE : s0;
            s0 : nex_state = a ? s1 : s0;
            s1 : nex_state = a ? s2 : s0;
            s2 : nex_state = s3;
            s3 : nex_state = s4;
            s4 : nex_state = s5;
            s5 : nex_state = a ? s6 : s0;
            s6 : nex_state = a ? s7 : s0;
            s7 : nex_state = a ? s0 : s8;
            s8 : nex_state = a ? IDLE : s0;
            default : nex_state = IDLE;
        endcase
    end
    //step three
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           match <= 1'b0; 
        end
        else begin
            match <=  (cur_state == s8 && a == 0) ? 1'b1 : 1'b0;
        end
    end
endmodule

2.3.2 移位寄存器法

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);

    
//==================================寄存器法==================================================

    reg [8:0] val;
     
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            val <= 9'b0;
        end else begin
            val <= {val[7:0],a};
        end
    end
     
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            match <= 1'b0;
        end 
        else begin
            casex (val)
                9'b011xxx110 : match <= 1'b1;
                default : match <= 1'b0;
            endcase
        end
    end
endmodule

2.4 测试文件

待更新。。。

2.5 仿真波形

待更新。。。

3. VL27 不重叠序列检测

3.1 题目描述

请编写一个序列检测模块,检测输入信号(a)是否满足011100序列, 要求以每六个输入为一组,不检测重复序列,例如第一位数据不符合,则不考虑后五位。一直到第七位数据即下一组信号的第一位开始检测。当信号满足该序列,给出指示信号match。当不满足时给出指示信号not_match。

3.1.1 信号示意图

在这里插入图片描述

3.1.2 波形示意图

在这里插入图片描述

3.1.3 输入描述

clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据

3.1.4 输出描述

match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
not_match:当输入信号a不满足目标序列,该信号为1,其余时刻该信号为0

3.2 解题思路

该题的状态转移图如下所示:
在这里插入图片描述

这个题必须使用计数器+状态机(寄存器)来实现,因为题目要求从第一位到第六位。只要有一位不符合那只能等到第七位再进行为期6个数的判断了。

这个题我给出了两种解法,可以参考一下!

3.3 代码实现

3.3.1 状态机法

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
    
     /*
        =============================状态机法===================================================
    */

   parameter
        IDLE = 7'b000_0001,
        s0 = 7'b000_0010,
        s1 = 7'b000_0100,
        s2 = 7'b000_1000,
        s3 = 7'b001_0000,
        s4 = 7'b010_0000,
        s5 = 7'b100_0000;

    reg [6:0] cur_state, nex_state;
    reg [2:0] cnt;
    
    //计数器
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            cnt <= 3'd0;
        end
        else if(cnt == 3'd5) begin
            cnt <= 3'd0;
        end
        else begin
            cnt <= cnt + 3'd1;
        end
    end
    // step one
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           cur_state <= IDLE; 
        end
        else begin
           cur_state <= nex_state; 
        end
    end
    //step two
    always @ (*) begin
        case(cur_state)
            IDLE : nex_state = data ? IDLE : s0;
            s0 : nex_state = data ? s1 : s0;
            s1 : nex_state = data ? s2 : s0;
            s2 : nex_state = data ? s3 : s0;
            s3 : nex_state = data ? IDLE : s4;
            s4 : nex_state = data ? s1 : s5;
            s5 : nex_state = data ? s1 : s0;
            default : nex_state = IDLE;
        endcase
    end
    //step three
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            match <= 1'b0; 
            not_match <= 1'b0;
        end
        else if(cnt == 3'd5) begin
            if(cur_state == s4 && data == 0) begin
                match <=  1'b1;
                not_match <= 1'b0;
            end
            else begin
                match <=  1'b0;
                not_match <= 1'b1;
            end
        end
        else begin
            match <= 1'b0;
            not_match <= 1'b0;
        end
    end
endmodule

3.3.2 移位寄存器法

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);

    /*
        =============================寄存器法===================================================
    */
    reg [2:0] cnt;
    reg [5:0] data_r;
     
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            cnt <= 0;
        else
            cnt <= cnt==5? 0: cnt+1;
    end
     
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_r <= 6'b0;
        else
            data_r <= {data_r[4:0], data};
    end
     
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            match     <= 1'b0;
            not_match <= 1'b0;
        end
        else begin
            match     <= (cnt==5) && ({data_r[4:0], data}==6'b011100);
            not_match <= (cnt==5) && ({data_r[4:0], data}!=6'b011100);
        end
    end
endmodule

3.4 测试文件

待更新。。。

3.5 仿真波形

待更新。。。

4. VL28 输入序列不连续的序列检测

4.1 题目描述

请编写一个序列检测模块,输入信号端口为data,表示数据有效的指示信号端口为data_valid。当data_valid信号为高时,表示此刻的输入信号data有效,参与序列检测;当data_valid为低时,data无效,抛弃该时刻的输入。当输入序列的有效信号满足0110时,拉高序列匹配信号match。

4.1.1 信号示意图

在这里插入图片描述

4.1.2 波形示意图

在这里插入图片描述

4.1.3 输入描述

clk:系统时钟信号
rst_n:异步复位信号,低电平有效
data:单比特信号,待检测的数据
data_valid:输入信号有效标志,当该信号为1时,表示输入信号有效

4.1.4 输出描述

match:当输入信号data满足目标序列,该信号为1,其余时刻该信号为0

4.2 解题思路

该题的状态转移图如下所示:
在这里插入图片描述

这个题和之前的题目不一样的地方在于,有一个有效位判断数据是否有效,这其实就是在状态转移条件那里加一个判断有效无效就行,有效,那就转移,无效,拉到,就是干!!!

这个题我给出了两种解法,可以参考一下!

4.3 代码实现

4.3.1 状态机法

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	input data_valid,
	output reg match
	);
// ============================状态机法==========================================================
parameter
        IDLE = 5'b0_0001,
        s0 = 5'b0_0010,
        s1 = 5'b0_0100,
        s2 = 5'b0_1000,
        s3 = 5'b1_0000;

    reg [4:0] cur_state, nex_state;
    
    // step one
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           cur_state <= IDLE; 
        end
        else begin
           cur_state <= nex_state; 
        end
    end
    //step two
    always @ (*) begin
        case(cur_state)
            IDLE : begin
                if(data_valid) begin
                    nex_state = data ? IDLE : s0;
                end
                else begin
                    nex_state = cur_state;
                end
            end
            s0 : begin
                if(data_valid) begin
                    nex_state = data ? s1 : s0;
                end
                else begin
                    nex_state = cur_state;
                end
            end
            s1 : begin
                if(data_valid) begin
                    nex_state = data ? s2 : s0;
                end
                else begin
                    nex_state = cur_state;
                end
            end
            s2 : begin
                if(data_valid) begin
                    nex_state = data ? IDLE : s3;
                end
                else begin
                    nex_state = cur_state;
                end
            end
            s3 : begin
                if(data_valid) begin
                    nex_state = data ? IDLE : s0;
                end
                else begin
                    nex_state = cur_state;
                end
            end
            default : begin
                if(data_valid) begin
                    nex_state = IDLE;
                end
                else begin
                    nex_state = cur_state;
                end
            end
        endcase
    end
    //step three
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           match <= 1'b0; 
        end
        else begin
            match <=  (cur_state == s2 && data == 0) ? 1'b1 : 1'b0;  //这个是米粒型的(次态与输入和现态有关)
        end
    end
endmodule

4.3.2 移位寄存器法

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	input data_valid,
	output reg match
	);
// ============================寄存器法==========================================================
    reg [3:0] shift_reg;
    
    //shift_reg
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           shift_reg <= 4'd0; 
        end
        else begin
            if(data_valid) begin  //这里很关键!!!
                shift_reg <= {shift_reg[2:0], data}; 
            end
        end
    end
    //compare
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
           match <= 1'b0; 
        end
        else begin
            if(data_valid && shift_reg[2:0] == 3'b011 && !data) begin
               match <= 1'b1; 
            end
            else begin
               match <= 1'b0; 
            end
        end
    end
    
endmodule

4.4 测试文件

待更新。。。

4.5 仿真波形

待更新。。。

声明

本人所有系列的文章,仅供学习,不可商用,如有侵权,请告知,立删!!!

本人主要是记录学习过程,以供自己回头复习,再就是提供给后人参考,不喜勿喷!!!

如果觉得对你有用的话,记得收藏+评论!!!

  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值