题解 | #不重叠序列检测#

不重叠序列检测

http://www.nowcoder.com/practice/9f91a38c74164f8dbdc5f953edcc49cc

2022-4-1:才注意到题目要求使用状态机完成,所以补充了状态机代码。此外,之前的移位寄存器方法我也误以为是右移的,也做了修正。并且Testbench中matchnot_match信号好像比题目要求的提前了一个周期。不过之前错误的方法居然通过了测试。希望牛客能提供更完整的测试波形供大家调试。

状态机

波形图

alt

状态转移图

本程序的状态机在基本的三段式状态机上加入了计数器cnt,并使用cnt对状态转移进行约束,以确保正常工作时,状态机每6个周期循环一次。其中FAIL状态仅在计数器cnt==6时才会切换到别的状态,matchnot_match也仅在cnt==6时才进行更新; ZERO为启动态,系统复位时,处于该状态。

程序

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
    
    parameter ZERO=0, ONE=1, TWO=2, THREE=3, FOUR=4, FIVE=5, SIX=6, FAIL=7;
    reg [2:0] state, nstate;
    reg [2:0] cnt;
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            cnt <= 0;
        else
            cnt <= cnt==6? 1: cnt+1; 
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            state <= ZERO;
        else
            state <= nstate;
    end
    
    always@(*) begin
        if(~rst_n)
            nstate = ZERO;
        else
            case(state)
                ZERO : nstate = data? FAIL : ONE;
                ONE  : nstate = data? TWO  : FAIL;
                TWO  : nstate = data? THREE: FAIL;
                THREE: nstate = data? FOUR : FAIL;
                FOUR : nstate = data? FAIL : FIVE;
                FIVE : nstate = data? FAIL : SIX;
                SIX  : nstate = data? FAIL : ONE;
                FAIL : nstate = cnt==6&&data==0? ONE: FAIL;
                default: nstate = ZERO;
            endcase
    end
    
    always@(*) begin
        if(~rst_n) begin
            match     = 0;
            not_match = 0;
        end
        else begin
            match     = cnt==6&&state==SIX;
            not_match = cnt==6&&state==FAIL;
        end
    end
    
endmodule

移位寄存器

本题要求每6个不重叠的数为一组判断是否符合要求,所以需要在移位寄存器的基础上添加一个计数器。当计数器计数到序列长度时,再判断是否match。

`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
Verilog篇题解 文章被收录于专栏

本人对牛客网verilog篇题目一些理解

全部评论
为什么状态机是cnt==6时,清零,用位移寄存器是cnt==5时清零
1 回复 分享
发布于 2022-07-17 17:22
奇奇怪怪,我match和not_match信号延后一拍就无法通过
1 回复 分享
发布于 2022-07-23 16:04
这个题解错误的,不满足”第一位数据不符合,则不考虑后五位。一直到第七位数据即下一组信号的第一位开始检测“,no match会提前输出
1 回复 分享
发布于 05-08 22:26 陕西
你这个为什么是data_r <= {data, data_r[5:1]}右移,不应该是数据左移吗
点赞 回复 分享
发布于 2022-03-31 10:48
奇怪,我和楼主一样的代码,但是match有一拍延迟。复制楼主的代码就能通过。
点赞 回复 分享
发布于 2023-01-16 19:36 广东
您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
点赞 回复 分享
发布于 2023-05-03 23:19 安徽
奇怪,和楼主一样的代码。自己写的就会报错,说计算量太大,而复制楼主的就可以通过。奇怪。
点赞 回复 分享
发布于 2023-05-03 23:28 安徽
状态转移逻辑的FAIL是不是有点问题。cnt等于6时,时间处于一组数据中最后一个数据;判断data==0时,时间处于下一组的第一个数据
点赞 回复 分享
发布于 2023-06-04 17:31 上海

相关推荐

牛客868257804号:九个中铁八个中建
点赞 评论 收藏
分享
40 11 评论
分享
牛客网
牛客企业服务