笔试题解 | 输入序列连续的序列检测

最近牛客网开启了数字IC的题库,本着凑热闹的原则做了一道题,发现有一道题看上去不难,还是很有思考价值的

题目:

题目是这样的:

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

模块的时序图如下:

请使用Verilog HDL实现以上功能,要求使用状态机实现,画出状态转化图。并编写testbench验证模块的功能。
输入描述:
clk:系统时钟信号
rst_n:异步复位信号,低电平有效
a:单比特信号,待检测的数据
输出描述:
match:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
not_match:当输入信号a不满足目标序列,该信号为1,其余时刻该信号为0

看到题目之后,首先第一想法肯定是状态机,但是状态机一定不是容易也不是资源最小的,结合之前的序列检测的想法

方法一:RAM+Counter

但是这个是并非确定6个一组,所以shift_reg有点浪费,不如直接使用RAM+counter,手边使用Vivado简单看了一下资源使用情况。

`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] ram;
     
    always@(posedge clk&nbs***bsp;negedge rst_n)begin
        if(! rst_n)
            cnt  <=  3'd0;
        else if(cnt == 3'd5)
            cnt  <=  3'd0;
        else
            cnt  <=  cnt  + 3'd1;
    end
     
    always@(posedge clk&nbs***bsp;negedge rst_n)begin
        if(! rst_n)
            ram  <=  6'd0;
        else
            case(cnt)
                3'd0:ram <= {ram[5:1],data};
                3'd1:ram <= {ram[5:2],data,ram[0]};
                3'd2:ram <= {ram[5:3],data,ram[1:0]};
                3'd3:ram <= {ram[5:4],data,ram[2:0]};
                3'd4:ram <= {ram[5],data,ram[3:0]};
                3'd5:ram <= {data,ram[4:0]};
            endcase
    end
                 
    always@(posedge clk&nbs***bsp;negedge rst_n) begin
        if(! rst_n)
                match <= 1'd0;
        else if((ram == 6'b001110 )&&(cnt == 3'd5))
                match <= 1'd1;
        else
                match <= 1'd0;
    end
                 
     always@(posedge clk&nbs***bsp;negedge rst_n) begin
        if(! rst_n)
                not_match <= 1'd0;
         else if((ram != 6'b001110)&&(cnt == 3'd5))
                not_match <= 1'd1;
        else
                not_match <= 1'd0;
    end
endmodule


但是这并不是最简单的,如何进一步优化呢?

方法二:MUX+Counter

如果能够使用数选器,使用计数器选择每一位与当前输入的同或,那么原来6位寄存器存的数据只需要一个寄存器和数选器就可以做出来,资源使用如下

可以看到资源大大的减少。

`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 cmp;
    reg  detect_cmp;
    parameter detect = 6'b011100;
     
    always@(posedge clk or negedge rst_n)begin
        if(! rst_n) 
            cnt  <=  3'd0;
        else if(cnt == 3'd5)
            cnt  <=  3'd0;
        else 
            cnt  <=  cnt  + 3'd1;
    end
    always@(*)begin
        case(cnt)
        3'd0: cmp = 1'd0;
        3'd1: cmp = 1'd1;
        3'd2: cmp = 1'd1;
        3'd3: cmp = 1'd1;
        3'd4: cmp = 1'd0;
        3'd5: cmp = 1'd0;
        default: cmp = 1'd0;
        endcase
    end
     
    always@(posedge clk or negedge rst_n) begin
        if(! rst_n)
                detect_cmp <= 1'd1;
        else if(cnt == 3'd5)
                detect_cmp <= 1'd1;
        else
                detect_cmp <= detect_cmp && (~( cmp^ data));
    end
                 
    always@(posedge clk or negedge rst_n) begin
        if(! rst_n)
                match <= 1'd0;
        else if((detect_cmp )&&(cnt == 3'd5))
                match <= 1'd1;
        else
                match <= 1'd0;
    end
                 
     always@(posedge clk or negedge rst_n) begin
        if(! rst_n)
                not_match <= 1'd0;
         else if((!detect_cmp)&&(cnt == 3'd5))
                not_match <= 1'd1;
        else
                not_match <= 1'd0;
    end
endmodule        

这仅仅是我的一个小小的想法,如果有大佬能提出我的代码还有那些问题,或者更好的解题思路,希望不吝赐教!


#笔试题##学习路径##数字IC设计工程师#
全部评论
第一个代码乱码了
点赞 回复 分享
发布于 2022-03-18 17:32

相关推荐

3 9 评论
分享
牛客网
牛客企业服务