| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- `timescale 1ns/1ps
- module pwm_trace_measure_tb;
- localparam integer CLK_HZ = 25_000_000;
- reg clk = 1'b0;
- reg reset_n = 1'b0;
- reg signal_in = 1'b0;
- wire [31:0] edge_count;
- wire [31:0] period_ticks;
- wire [31:0] high_ticks;
- wire measurement_valid;
- wire signal_present;
- integer errors = 0;
- // 25 MHz => 40 ns period.
- always #20 clk = ~clk;
- pwm_trace_measure #(
- .CLK_HZ(CLK_HZ),
- // Short timeout only for simulation speed.
- .NO_SIGNAL_MS(2)
- ) dut (
- .clk(clk),
- .reset_n(reset_n),
- .signal_in(signal_in),
- .edge_count(edge_count),
- .period_ticks(period_ticks),
- .high_ticks(high_ticks),
- .measurement_valid(measurement_valid),
- .signal_present(signal_present)
- );
- task check_equal;
- input [8*40-1:0] name;
- input [31:0] actual;
- input [31:0] expected;
- begin
- if (actual !== expected) begin
- $display("FAIL %-24s expected=%0d actual=%0d",
- name, expected, actual);
- errors = errors + 1;
- end else begin
- $display("PASS %-24s %0d", name, actual);
- end
- end
- endtask
- // Drive a PWM whose edges occur on clk negative edges.
- // This keeps the asynchronous-input test deterministic while still
- // exercising the two-flop synchronizer in the DUT.
- task drive_pwm_ticks;
- input integer period;
- input integer high;
- input integer pulses;
- integer i;
- begin
- @(negedge clk);
- for (i = 0; i < pulses; i = i + 1) begin
- signal_in = 1'b1;
- repeat (high) @(negedge clk);
- signal_in = 1'b0;
- repeat (period - high) @(negedge clk);
- end
- end
- endtask
- initial begin
- $display("");
- $display("==============================================");
- $display(" PWM TRACE MEASUREMENT CORE TEST");
- $display("==============================================");
- repeat (10) @(posedge clk);
- reset_n = 1'b1;
- repeat (5) @(posedge clk);
- // ------------------------------------------------------------
- // Case A:
- // 25 MHz / 1000 ticks = 25 kHz
- // 250 / 1000 = 25%
- // ------------------------------------------------------------
- $display("");
- $display("[A] 25 kHz, 25%% duty, 8 pulses");
- drive_pwm_ticks(1000, 250, 8);
- repeat (6) @(posedge clk);
- check_equal("edge_count", edge_count, 8);
- check_equal("period_ticks", period_ticks, 1000);
- check_equal("high_ticks", high_ticks, 250);
- if (!measurement_valid || !signal_present) begin
- $display("FAIL valid/present expected 1/1 actual %0d/%0d",
- measurement_valid, signal_present);
- errors = errors + 1;
- end else begin
- $display("PASS measurement_valid/signal_present");
- end
- // ------------------------------------------------------------
- // Case B:
- // 25 MHz / 2500 ticks = 10 kHz
- // 1500 / 2500 = 60%
- // ------------------------------------------------------------
- $display("");
- $display("[B] 10 kHz, 60%% duty, 6 more pulses");
- drive_pwm_ticks(2500, 1500, 6);
- repeat (6) @(posedge clk);
- check_equal("edge_count cumulative", edge_count, 14);
- check_equal("period_ticks", period_ticks, 2500);
- check_equal("high_ticks", high_ticks, 1500);
- // ------------------------------------------------------------
- // Case C: signal disappears.
- // Simulation timeout is configured to 2 ms.
- // Count must remain, frequency/duty data must become invalid.
- // ------------------------------------------------------------
- $display("");
- $display("[C] no-signal timeout");
- signal_in = 1'b0;
- repeat (52000) @(posedge clk); // > 2 ms at 25 MHz
- check_equal("edge_count retained", edge_count, 14);
- check_equal("period cleared", period_ticks, 0);
- check_equal("high cleared", high_ticks, 0);
- if (measurement_valid !== 1'b0 ||
- signal_present !== 1'b0) begin
- $display("FAIL timeout flags expected 0/0 actual %0d/%0d",
- measurement_valid, signal_present);
- errors = errors + 1;
- end else begin
- $display("PASS timeout flags");
- end
- $display("");
- $display("==============================================");
- if (errors == 0) begin
- $display("ALL PWM TRACE CORE TESTS PASSED");
- $display("==============================================");
- $finish;
- end else begin
- $display("PWM TRACE CORE TEST FAILED: %0d error(s)", errors);
- $display("==============================================");
- $fatal(1);
- end
- end
- endmodule
|