检测输入的数据是否是连续的3个8'h23。

一、问题

检测输入的数据是否是连续的3个8’h23(在成功检测3个之后重新开始计数)

二、思路

1、使用计数器,在reset的情况下计数器的默认值是1。
2、如果成功检测到frame_i信号并且data_i等于8‘h23时计数器加1,否则计数器的值保持默认值1。
3、如果成功检测到frame_i信号并且data_i等于8‘h23时计数器再加1,否则计数器的值变成默认值1。
4、按照步骤3继续检测,待计数器的值等于3,frame_i信号有效并且data_i的值为8’h23是输出一个pulse。
5、计数器的值又变成1,重新开始检测。

三、代码如下

module frame
#(
    parameter DATA_WIDTH  = 8,
    parameter COUNTER_NUM = 3,
    parameter DATA_VALUE  = 8'h23
)
(
    input                  clk_i   ,
    input                  rst_n_i ,
    input                  frame_i ,
    input [DATA_WIDTH-1:0] data_i  ,
    output logic           flag_o   
);

    logic [$clog2(COUNTER_NUM)-1:0] cnt_r;

    always_ff @(posedge clk_i or negedge rst_n_i) begin
        if(!rst_n_i) begin
            cnt_r <= {{($clog2(COUNTER_NUM)-1){1'b0}},1'b1};
        end
        else if(cnt_r >= COUNTER_NUM && frame_i && data_i == DATA_VALUE) begin
            cnt_r <= {{($clog2(COUNTER_NUM)-1){1'b0}},1'b1};
        end
        else if(frame_i) begin
            if(data_i == DATA_VALUE) begin
                cnt_r <= cnt_r + 1'b1;
            end
            else begin
                cnt_r <= {{($clog2(COUNTER_NUM)-1){1'b0}},1'b1};
            end
        end
    end

    assign flag_o = (cnt_r == COUNTER_NUM) && frame_i && (data_i == DATA_VALUE);
    
//**********************************************************************
//Assertion
//**********************************************************************
property check_flag;
    @(posedge clk_i)
    disable iff(!rst_n_i)
    flag_o |-> (data_i == DATA_VALUE) && $past(data_i == DATA_VALUE,1,frame_i) && $past(data_i == DATA_VALUE,2,frame_i);
endproperty

a_check_flag : assert property(check_flag());
c_check_flag : cover property(check_flag());

endmodule

四、testbench如下

module frame_tb;
    parameter DATA_WIDTH  = 8              ;
    parameter COUNTER_NUM = 3              ;
    parameter DATA_VALUE  = 8'h23          ;
    logic                       clk_i      ;
    logic                       rst_n_i    ;
    logic                       frame_i    ;
    logic [DATA_WIDTH-1:0]      data_i     ;
    logic                       flag_o     ;
    logic [1:0][DATA_WIDTH-1:0] data_random;  //这个变量主要是用来产生8'h23和非8'h23的随机数
    
    assign data_random[0] = DATA_VALUE;

    frame
    #(
        .DATA_WIDTH   (DATA_WIDTH ),
        .COUNTER_NUM  (COUNTER_NUM),
        .DATA_VALUE   (DATA_VALUE )
    )
    (
        .clk_i        (clk_i      ),
        .rst_n_i      (rst_n_i    ),
        .frame_i      (frame_i    ),
        .data_i       (data_i     ),
        .flag_o       (flag_o     )  
    );

    always #5 clk_i = ~clk_i;
    task rst;
        begin
            rst_n_i = 1'b0;
            #101;
            rst_n_i = 1'b1;
        end
    endtask

    task frame_input;
        begin
            logic random_a;
            logic random_b;
            data_random[1] = $urandom;
            random_a = $urandom_range(0,1);
            random_b = $urandom_range(0,1);
            @(posedge clk_i);
            frame_i <= random_a;
            data_i  <= {DATA_WIDTH{random_a}} & data_random[random_b];
        end
    endtask
    
    initial
        begin
            clk_i   = 1'b0;
            frame_i = 1'b0;
            data_i  = 'h0 ;
            rst();
            repeat(1000) begin
                frame_input();
            end
            $stop;
        end
endmodule

五、仿真结果如下

posted @ 2021-09-15 15:11  Hardwarer  阅读(113)  评论(0编辑  收藏  举报