Double edge counter verilog design (detailed description)

A dual-edge counter is a counter that counts on both the rising and falling edges of the clock. Therefore, two counts are needed, namely a rising edge counter and a falling edge counter as auxiliary, as shown in the figure below:
Insert image description here
It can be observed that a dual-edge counter can be obtained by adding the rising edge and falling edge counters. A more complicated situation is the setting condition of the two counters. Now suppose we make a double-edge counter with a maximum value of 17, as shown in the figure below: Insert image description here
We can see that when the two accelerators are added to the maximum value, one counter needs to be set to 0 and the other counter to be set to 1. If it is on the rising edge When it is detected that the sum is the maximum value, the rising edge counter is set to 0. Otherwise, the falling edge counter is set to 0. Therefore, it is necessary to declare two set 1 signals for these two counters. If the set 1 signal is high, the corresponding counter will be set to 1 in the next clock cycle. In addition, it needs to be explained that the maximum counting value of each of these two counters is half of the maximum counting value of both edges. The specific code is as follows, with detailed comments:

//function:实现双边沿的计数器
//date:2022/08/31

module double_edge_cnt #(
    parameter   MAX         =   100    //计数的最大值   
)

(
    input   wire                clk     ,
    input   wire                rst_n   ,

    output  wire    [31:0]      d_cnt 
);

wire                even_flag       ;       //偶数标志
wire    [31:0]      HALF_MAX        ;

reg     [31:0]      cnt_posedge     ;       //上升沿计数器
reg     [31:0]      cnt_negedge     ;       //下降沿计数器
reg                 set_one_flag_pos;       //上升沿计数器置1信号
reg                 set_one_flas_neg;       //下降沿计数器置1信号

assign even_flag = (MAX[0] == 1'b0) ? 1'b1 : 1'b0;          //判断MAX是不是偶数
assign HALF_MAX = even_flag ? MAX >> 1 : (MAX >> 1) + 1'b1; //MAX一半

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_posedge <= 32'd0;
        set_one_flag_pos <= 1'b0;
    end
    else if((cnt_negedge + cnt_posedge == MAX)) begin       //上升沿检测到加和最大值,
        cnt_posedge <= 32'd0;
    end
    else if(cnt_negedge + cnt_posedge == MAX - 1'b1) begin  //上升沿检测到加和最大值减1,说明会在下降沿检测到最大值
        set_one_flag_pos <= 1'b1;                           //因此拉高置1信号
        cnt_posedge <= cnt_posedge + 1'b1;
    end
    else if(set_one_flag_pos) begin                         //置1信号为高,置位
        set_one_flag_pos <= 1'b0;
        cnt_posedge <= 32'd1;
    end
    else begin
        cnt_posedge <= cnt_posedge + 1'b1;
    end
end

always @(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_negedge <= 32'd0;
        set_one_flas_neg <= 1'b0;
    end
    else if(cnt_negedge + cnt_posedge == MAX) begin         //下降沿检测到最大值
        cnt_negedge <= 32'd0;
    end
    else if(cnt_negedge + cnt_posedge == MAX - 1'b1) begin  //下降沿检测到最大值减1,说明会在上升沿检测到最大值
        set_one_flas_neg <= 1'b1;                           //因此拉高下降沿计数器置1信号
        cnt_negedge <= cnt_negedge + 1'b1;
    end
    else if(set_one_flas_neg) begin                         //置1信号为高
        set_one_flas_neg <= 1'b0;
        cnt_negedge <= 32'd1;
    end
    else begin
        cnt_negedge <= cnt_negedge + 1'b1;
    end
end

//为双边沿计数器赋值
assign d_cnt = (((cnt_posedge == HALF_MAX) && (cnt_negedge == 'd0)) || ((cnt_posedge == 'd0) && (cnt_negedge == HALF_MAX))) ? 32'd0 : cnt_negedge + cnt_posedge; 

endmodule

The testbench is as follows:

`timescale 1ns/1ns
`define CLK_CYCLE 20
module tb_double_edge_cnt;

    reg                 clk     ;
    reg                 rst_n   ;

    wire    [31:0]      d_cnt   ;

double_edge_cnt #
(
    99
)u_double_edge_cnt(
    .clk    (clk)   ,
    .rst_n  (rst_n) ,

    .d_cnt  (d_cnt)
);


initial begin
     clk = 1'b0;
     rst_n = 1'b0;
     #200
     rst_n = 1'b1;
     #40000;
     //$finish;
end

always # (`CLK_CYCLE/2) clk = ~clk;


endmodule

Simulation waveform diagram:
Insert image description here

Guess you like

Origin blog.csdn.net/weixin_45614076/article/details/126630588