`timescale 1ns / 1ps module pulse_cnt #( parameter CLK_FREQ = 50_000_000 ) ( input wire clk, input wire rst_n, input wire sig_in, input wire [23:0] win_us, output reg [23:0] cnt_out, output reg vld_out ); reg [31:0] window_cnt; // 当前时钟周期计数 reg [31:0] target_cnt; // 当前窗口所需时钟周期数 // 脉冲计数(宽度与输出一致,防止溢出) reg [23:0] pulse_cnt; // 标志:是否正在计算新的 target_cnt(避免组合逻辑环路) reg calc_done; reg sig_sync1, sig_sync2, sig_sync3; wire sig_rise = sig_sync2 & ~sig_sync3; always @(posedge clk) begin sig_sync1 <= sig_in; sig_sync2 <= sig_sync1; sig_sync3 <= sig_sync2; end // 主控制逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin window_cnt <= 0; pulse_cnt <= 0; cnt_out <= 0; vld_out <= 0; target_cnt <= 24'd50_000; end else begin vld_out <= 1'b0; target_cnt <= ( {40'd0, win_us} * CLK_FREQ) / 1_000_000 ; // 窗口计数结束条件:当前计数值到达 target_cnt if (window_cnt >= target_cnt) begin cnt_out <= pulse_cnt; vld_out <= 1'b1; // 复位窗口计数器与脉冲计数器,并触发重新计算目标值 window_cnt <= 0; pulse_cnt <= 0; end else begin window_cnt <= window_cnt + 1; if (sig_rise) pulse_cnt <= pulse_cnt + 1; end end end endmodule