牛客网 Verilog刷题 序列检测专题1:连续序列的检测

本专题共六道题,基本把牛客网序列检测的题型都覆盖到了。

序列检测主要分为两类:

1)连续序列的检测;

2)定长序列或不连续序列的检测。

连续序列的检测:

连续序列的检测首先要定义两个reg类型变量cs(current state)和ns(next state),再定义n个parameter(n = 待检测序列的位数 + 1);step one:定义复位状态(cs <= IDLE;)和正常状态(cs <= ns;);step two:case块通过cs状态决定ns状态;step three:输出match。

VL25 输入序列连续的序列检测

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

 请使用Verilog HDL实现以上功能,并编写testbench验证模块的功能。

输入描述:

clk:系统时钟信号

rst_n:异步复位信号,低电平有效

a:单比特信号,待检测的数据

输出描述:

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

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
    reg [8:0] cs;
    reg [8:0] ns;
    parameter IDLE = 9'b000000001;
    parameter S0   = 9'b000000010; 
    parameter S1   = 9'b000000100;
    parameter S2   = 9'b000001000;
    parameter S3   = 9'b000010000;
    parameter S4   = 9'b000100000;
    parameter S5   = 9'b001000000;
    parameter S6   = 9'b010000000;
    parameter S7   = 9'b100000000;
    //one step
    always @ (posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            cs <= IDLE;
        end
        else begin
            cs <= ns;
        end
    end
    //two step
    always @ (*) begin
        case( cs )
            IDLE : ns = (a == 1'b0) ? S0 : IDLE;
            S0   : ns = (a == 1'b1) ? S1 : S0;
            S1   : ns = (a == 1'b1) ? S2 : S0;
            S2   : ns = (a == 1'b1) ? S3 : S0;
            S3   : ns = (a == 1'b0) ? S4 : IDLE;
            S4   : ns = (a == 1'b0) ? S5 : S1;
            S5   : ns = (a == 1'b0) ? S6 : S1;
            S6   : ns = (a == 1'b1) ? S7 : S0;
            S7   : ns = (a == 1'b1) ? IDLE : S0;
        	default : ns = IDLE;
        endcase
    end
    wire match_tmp;
    assign match_tmp = (cs == S7);
    //three step
    always @ (posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            match <= 1'b0;
        end
        else begin
           match <= match_tmp; 
        end
    end
endmodule

 注:step two部分是否需要变量match_tmp由波形图决定,变量match_tmp作用是拿到输出信号延迟一个clk上升沿给match(见波形图)。

注意assign match_tmp = (cs == S7);这里满足cs == S7是在序列的最后一个数字的下一周期,此时match_tmp为1,但match的赋值要等待上升沿来临,所以下一个周期match拉高,如波形所示。

VL26 含有无关项的序列检测

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

 程序的功能时序图如下:

请使用Verilog HDL实现以上功能,并编写testbench验证模块的功能。 要求代码简洁,功能完整。

输入描述:

clk:系统时钟信号

rst_n:异步复位信号,低电平有效

a:单比特信号,待检测的数据

输出描述:

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

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
parameter IDLE   = 10'b0000000001;
parameter S0     = 10'b0000000010;
parameter S1     = 10'b0000000100;
parameter S2     = 10'b0000001000;
parameter S3     = 10'b0000010000;
parameter S4     = 10'b0000100000;
parameter S5     = 10'b0001000000;
parameter S6     = 10'b0010000000;
parameter S7     = 10'b0100000000;
parameter S8     = 10'b1000000000;
    reg [9:0] cs, ns;
// one step
always @ (posedge clk or negedge rst_n) 
begin 
    if( ~rst_n ) begin
        cs <= IDLE;
    end 
    else begin 
        cs <= ns;
    end 
end 
//  two step
always @ (*) 
begin
    case(cs)
        IDLE : ns = (a == 1'b0) ? S0 : IDLE;
        S0   : ns = (a == 1'b1) ? S1 : S0; 
        S1   : ns = (a == 1'b1) ? S2 : S0;
        S2   : ns = (a == 1'b1 | a == 1'b0) ? S3 : S0;
        S3   : ns = (a == 1'b1 | a == 1'b0) ? S4 : S0;
        S4   : ns = (a == 1'b1 | a == 1'b0) ? S5 : S0;
        S5   : ns = (a == 1'b1) ? S6 : S0;
        S6   : ns = (a == 1'b1) ? S7 : S0;
        S7   : ns = (a == 1'b0) ? S8 : S0;
        S8   : ns = (a == 1'b0) ? IDLE : S0;
        default : ns = IDLE;
    endcase
end 
wire match_tmp;
    assign match_tmp = (cs == S8);
// three step
always @ (posedge clk or negedge rst_n) 
begin 
    if( ~rst_n ) begin
        match <= 1'b0;
    end 
    else begin 
        match <= match_tmp;
    end 
end 
endmodule

本题与上题区别仅在于中间三位数为0或1都可使状态继续向下转移,所以代码层面仅在step two有所 改动。

VL35 状态机-非重叠的序列检测

设计一个状态机,用来检测序列 10111,要求:

1、进行非重叠检测   即101110111 只会被检测通过一次

2、寄存器输出且同步输出结果

注意rst为低电平复位

信号示意图:

 波形示意图:

输入描述:

输入信号 clk rst data 
类型 wire

输出描述:

输出信号  flag
类型  reg

`timescale 1ns/1ns
module sequence_test1(
	input wire clk  ,
	input wire rst  ,
	input wire data ,
	output reg flag
);
    parameter IDLE = 6'b000001;
    parameter S0 = 6'b000010;
    parameter S1 = 6'b000100;
    parameter S2 = 6'b001000;
    parameter S3 = 6'b010001;
    parameter S4 = 6'b100000;
    reg [5:0] cs;
    reg [5:0] ns;
    //step one
    always @ (posedge clk or negedge rst) begin
        if(~rst) begin
            cs <= IDLE;
        end
        else begin
           cs <= ns; 
        end
    end
    //step two
    always @ (*) begin
        case(cs)
            IDLE : ns = (data == 1'b1) ? S0 : IDLE;
            S0 :   ns = (data == 1'b0) ? S1 : S0;
            S1 :   ns = (data == 1'b1) ? S2 : IDLE;
            S2 :   ns = (data == 1'b1) ? S3 : S1;
            S3 :   ns = (data == 1'b1) ? S4 : S1;
            S4 :   ns = (data == 1'b1) ? S0 : IDLE;
            default : ns = IDLE;
        endcase
    end
    //step three
    always @ (posedge clk or negedge rst) begin
        if(~rst) begin
            flag <= 1'b0;
        end
        else begin
            if(ns == S4) begin
                flag <= 1'b1;
            end
            else begin
                flag <= 1'b0;
            end
        end
    end
endmodule

本题是非重叠的序列检测:检测序列 10111,101110111 只会被检测通过一次。重点在于case块中最后一句ns的状态决定,满足10111后要从头开始,而不是接着前一序列的最后一个数1继续。

注:此题序列满足要求后下一周期match立即拉高,所以不需要match_tmp变量,if(ns == S4)条件在序列的最后一个数字所在周期满足,match等待上升沿来临后恰好在下一周期拉高。 

VL36 重叠序列检测

设计一个状态机,用来检测序列 1011,要求:

1、进行重叠检测   即10110111 会被检测通过2次

2、寄存器输出,在序列检测完成下一拍输出检测有效

注意rst为低电平复位

信号示意图:

 波形示意图:

输入描述:

输入信号 clk rst data 
类型 wire

输出描述:

输出信号  flag
类型  reg

`timescale 1ns/1ns
module sequence_test2(
	input wire clk  ,
	input wire rst  ,
	input wire data ,
	output reg flag
);
    reg [4:0] cs;
    reg [4:0] ns;
    parameter IDLE = 5'b00001;
    parameter S0 = 5'b00010;
    parameter S1 = 5'b00100;
    parameter S2 = 5'b01000;
    parameter S3 = 5'b10000;  
    always @ (posedge clk or negedge rst) begin
        if(~rst) begin
            cs <= IDLE;
        end
        else begin
            cs <= ns;
        end
    end
    always @ (*) begin
        case(cs)
            IDLE : ns =(data == 1'b1) ? S0 : IDLE;
            S0 : ns =(data == 1'b0) ? S1 : S0;
            S1 : ns =(data == 1'b1) ? S2 : IDLE;
            S2 : ns =(data == 1'b1) ? S3 : S1;
            S3 : ns =(data == 1'b1) ? IDLE : S1;
            default : ns = IDLE;
        endcase
    end
    wire flag_tmp;
    assign flag_tmp = (cs==S3);
    always @ (posedge clk or negedge rst) begin
        if(~rst) begin
            flag <= 1'b0;
        end
        else begin
           flag <= flag_tmp; 
        end
    end
endmodule

 本题为重叠检测:即检测序列 1011,10110111会被检测通过2次。case块中满足1011后下一个数若为0则直接跳到S1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值