`timescale 1ns / 1ps module tb_pulse_cnt(); // 参数定义 localparam CLK_FREQ = 50_000_000; // 50 MHz 时钟 localparam CLK_PERIOD = 20ns; // 1/50MHz = 20ns // 信号声明 reg clk; reg rst_n; reg [23:0] win_us; reg sig_in; wire [23:0] cnt_out; wire vld_out; // 实例化被测模块 pulse_cnt #( .CLK_FREQ(CLK_FREQ) ) dut ( .clk (clk), .rst_n (rst_n), .sig_in (sig_in), .win_us (win_us), .cnt_out(cnt_out), .vld_out(vld_out) ); // 时钟生成 initial begin clk = 0; forever #(CLK_PERIOD/2) clk = ~clk; end // 测试激励 initial begin // 初始化 rst_n = 0; win_us = 24'd1000; // 默认窗口 1000 us = 1 ms sig_in = 0; // 释放复位 repeat(5) @(posedge clk); rst_n = 1; repeat(2) @(posedge clk); // -------------------------------------------------- // 测试1:窗口内无脉冲 // -------------------------------------------------- $display("Test 1: No pulse, expect cnt_out = 0 after window"); win_us = 24'd1000; // 1 ms 窗口 wait (vld_out); $display(" cnt_out = %0d (expected 0)", cnt_out); #(CLK_PERIOD*2); // -------------------------------------------------- // 测试2:固定频率脉冲 50 kHz (周期 20 us) // -------------------------------------------------- $display("Test 2: 50 kHz pulse, window = 1 ms -> expected 50 pulses"); fork begin : pulse_gen forever begin #10us sig_in = 1; #10us sig_in = 0; end end join_none wait (vld_out); $display(" cnt_out = %0d (expected 50)", cnt_out); #(CLK_PERIOD*2); disable pulse_gen; // -------------------------------------------------- // 测试3:脉冲频率 250 kHz (周期 2 us),窗口 1 ms -> 250 个脉冲 // -------------------------------------------------- $display("Test 3: 250 kHz pulse, window = 1 ms -> expected 250 pulses"); fork begin : pulse_gen2 forever begin #2us sig_in = 1; #2us sig_in = 0; end end join_none wait (vld_out); $display(" cnt_out = %0d (expected 250)", cnt_out); #(CLK_PERIOD*2); disable pulse_gen2; // -------------------------------------------------- // 测试4:动态改变窗口宽度 (2 ms),脉冲频率 250 kHz // -------------------------------------------------- $display("Test 4: 250 kHz pulse, window = 2 ms -> expected 500 pulses"); win_us = 24'd2000; // 2 ms // 重新启动一个脉冲生成进程 fork begin : pulse_gen3 forever begin #2us sig_in = 1; // 250 kHz -> 周期 4 us #2us sig_in = 0; end end join_none wait (vld_out); $display(" cnt_out = %0d (expected 500)", cnt_out); #(CLK_PERIOD*2); disable pulse_gen3; // -------------------------------------------------- // 测试5:边界情况 - 窗口极小 (1 us) // -------------------------------------------------- $display("Test 5: 500 kHz pulse, window = 1 us -> expected 0.5? rounded to 0 or 1?"); win_us = 24'd2; // 重新启动一个脉冲生成进程 fork begin : pulse_gen4 forever begin #1us sig_in = 1; #1us sig_in = 0; end end join_none wait (vld_out); $display(" cnt_out = %0d (expected 500)", cnt_out); #(CLK_PERIOD*2); disable pulse_gen4; // -------------------------------------------------- // 测试6:复位过程中行为 // -------------------------------------------------- $display("Test 6: Assert reset mid-window, check output goes to 0"); win_us = 24'd1000; #(500us); // 窗口中间复位 rst_n = 0; repeat(5) @(posedge clk); rst_n = 1; wait (vld_out); $display(" cnt_out = %0d (should be fresh measurement)", cnt_out); #(10us); $display("Simulation finished."); $finish; end // 监控输出有效标志并打印结果 always @(posedge vld_out) begin $display("[%t] vld_out asserted, cnt_out = %0d", $time, cnt_out); end // 可选:波形转储 initial begin $dumpfile("tb_pulse_cnt.vcd"); $dumpvars(0, tb_pulse_cnt); end endmodule