短脉冲计数
短脉冲计数
现有如下要求:时钟clk为20MHz,但是有一个pulse脉冲信号(脉宽最小为5ns),如何设计Verilog代码,可以计算脉冲的个数。
当脉冲信号(pulse)的最小脉宽(5ns)小于时钟周期时,直接使用时钟采样可能会导致脉冲被遗漏,因为脉冲可能出现在时钟边沿之间,无法被采样到。为了解决这个问题,需要设计一个可靠的脉冲计数电路,使用异步捕捉和同步处理机制。
设计思路:
设计思路
- 异步捕捉:通过一个异步置位的寄存器(
captured
)实现。当脉冲的上升沿发生时,立即设置该寄存器为高电平,无论时钟状态如何。 - 同步处理:捕捉到的异步信号需要同步到时钟域,以避免亚稳态问题。使用两级触发器同步器(双触发器同步)来处理异步信号。
- 边沿检测与计数:同步后的信号通过边沿检测(检测上升沿)来生成一个时钟周期的使能信号,用于增加计数器。这确保每个脉冲只被计数一次。
- 清除机制:计数后,需要清除异步捕捉标志,以便捕捉新的脉冲。这通过生成一个同步清除信号(
clear
)实现,该信号异步清除捕捉标志。
代码:
`timescale 1ns/1nsmodule test (input clk , input rst_n , input pulse , // 脉冲信号,最小脉宽5nsoutput reg [7:0] count // 脉冲计数器
);//当脉冲上升沿时异步置位,当清除信号或复位时异步清除
reg captured;
wire clear; // 清除信号,用于清除captured//捕捉逻辑:敏感于pulse的上升沿、clear的上升沿
always @(posedge pulse or posedge clear or negedge rst_n) beginif (!rst_n) begincaptured <= 1'b0; // 复位时清除end else if (clear) begincaptured <= 1'b0; // 清除信号有效时清除end else begincaptured <= 1'b1; // 脉冲上升沿时置位end
end//同步
reg captured_sync1, captured_sync2,captured_sync3;always @(posedge clk or negedge rst_n) beginif (!rst_n) begincaptured_sync1 <= 1'b0;captured_sync2 <= 1'b0;captured_sync3 <= 1'b0;end else begincaptured_sync1 <= captured; // 第一级同步captured_sync2 <= captured_sync1; // 第二级同步captured_sync3 <= captured_sync2;end
end//边沿检测与计数逻辑
wire capture_pos;
assign capture_pos = captured_sync2 & !captured_sync3;always @(posedge clk or negedge rst_n) beginif(!rst_n) count <= 8'b0;else if(capture_pos)count <= count + 1'b1;else count <= count;
end// 生成清除信号
assign clear = capture_pos;endmodule
TB:
`timescale 1ns / 1psmodule sim();reg clk ;
reg rst_n ;
reg pulse ;wire [7:0] count ;initial clk = 1;
always #25 clk <= ~clk; //20MHZtest u_test(.clk (clk ), .rst_n (rst_n ),.pulse (pulse ),.count (count ));initial beginrst_n = 0;pulse = 0;#200;rst_n = 1;#100;pulse = 1;#10;pulse = 0;#200;pulse = 1;#100;pulse = 0;#400;pulse = 1;#5;pulse = 0;#321;pulse = 1;#30;pulse = 0;end
endmodule
仿真结果: