160 lines
4.9 KiB
Systemverilog
160 lines
4.9 KiB
Systemverilog
`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 |