pwm_trace_measure_tb.v 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. `timescale 1ns/1ps
  2. module pwm_trace_measure_tb;
  3. localparam integer CLK_HZ = 25_000_000;
  4. reg clk = 1'b0;
  5. reg reset_n = 1'b0;
  6. reg signal_in = 1'b0;
  7. wire [31:0] edge_count;
  8. wire [31:0] period_ticks;
  9. wire [31:0] high_ticks;
  10. wire measurement_valid;
  11. wire signal_present;
  12. integer errors = 0;
  13. // 25 MHz => 40 ns period.
  14. always #20 clk = ~clk;
  15. pwm_trace_measure #(
  16. .CLK_HZ(CLK_HZ),
  17. // Short timeout only for simulation speed.
  18. .NO_SIGNAL_MS(2)
  19. ) dut (
  20. .clk(clk),
  21. .reset_n(reset_n),
  22. .signal_in(signal_in),
  23. .edge_count(edge_count),
  24. .period_ticks(period_ticks),
  25. .high_ticks(high_ticks),
  26. .measurement_valid(measurement_valid),
  27. .signal_present(signal_present)
  28. );
  29. task check_equal;
  30. input [8*40-1:0] name;
  31. input [31:0] actual;
  32. input [31:0] expected;
  33. begin
  34. if (actual !== expected) begin
  35. $display("FAIL %-24s expected=%0d actual=%0d",
  36. name, expected, actual);
  37. errors = errors + 1;
  38. end else begin
  39. $display("PASS %-24s %0d", name, actual);
  40. end
  41. end
  42. endtask
  43. // Drive a PWM whose edges occur on clk negative edges.
  44. // This keeps the asynchronous-input test deterministic while still
  45. // exercising the two-flop synchronizer in the DUT.
  46. task drive_pwm_ticks;
  47. input integer period;
  48. input integer high;
  49. input integer pulses;
  50. integer i;
  51. begin
  52. @(negedge clk);
  53. for (i = 0; i < pulses; i = i + 1) begin
  54. signal_in = 1'b1;
  55. repeat (high) @(negedge clk);
  56. signal_in = 1'b0;
  57. repeat (period - high) @(negedge clk);
  58. end
  59. end
  60. endtask
  61. initial begin
  62. $display("");
  63. $display("==============================================");
  64. $display(" PWM TRACE MEASUREMENT CORE TEST");
  65. $display("==============================================");
  66. repeat (10) @(posedge clk);
  67. reset_n = 1'b1;
  68. repeat (5) @(posedge clk);
  69. // ------------------------------------------------------------
  70. // Case A:
  71. // 25 MHz / 1000 ticks = 25 kHz
  72. // 250 / 1000 = 25%
  73. // ------------------------------------------------------------
  74. $display("");
  75. $display("[A] 25 kHz, 25%% duty, 8 pulses");
  76. drive_pwm_ticks(1000, 250, 8);
  77. repeat (6) @(posedge clk);
  78. check_equal("edge_count", edge_count, 8);
  79. check_equal("period_ticks", period_ticks, 1000);
  80. check_equal("high_ticks", high_ticks, 250);
  81. if (!measurement_valid || !signal_present) begin
  82. $display("FAIL valid/present expected 1/1 actual %0d/%0d",
  83. measurement_valid, signal_present);
  84. errors = errors + 1;
  85. end else begin
  86. $display("PASS measurement_valid/signal_present");
  87. end
  88. // ------------------------------------------------------------
  89. // Case B:
  90. // 25 MHz / 2500 ticks = 10 kHz
  91. // 1500 / 2500 = 60%
  92. // ------------------------------------------------------------
  93. $display("");
  94. $display("[B] 10 kHz, 60%% duty, 6 more pulses");
  95. drive_pwm_ticks(2500, 1500, 6);
  96. repeat (6) @(posedge clk);
  97. check_equal("edge_count cumulative", edge_count, 14);
  98. check_equal("period_ticks", period_ticks, 2500);
  99. check_equal("high_ticks", high_ticks, 1500);
  100. // ------------------------------------------------------------
  101. // Case C: signal disappears.
  102. // Simulation timeout is configured to 2 ms.
  103. // Count must remain, frequency/duty data must become invalid.
  104. // ------------------------------------------------------------
  105. $display("");
  106. $display("[C] no-signal timeout");
  107. signal_in = 1'b0;
  108. repeat (52000) @(posedge clk); // > 2 ms at 25 MHz
  109. check_equal("edge_count retained", edge_count, 14);
  110. check_equal("period cleared", period_ticks, 0);
  111. check_equal("high cleared", high_ticks, 0);
  112. if (measurement_valid !== 1'b0 ||
  113. signal_present !== 1'b0) begin
  114. $display("FAIL timeout flags expected 0/0 actual %0d/%0d",
  115. measurement_valid, signal_present);
  116. errors = errors + 1;
  117. end else begin
  118. $display("PASS timeout flags");
  119. end
  120. $display("");
  121. $display("==============================================");
  122. if (errors == 0) begin
  123. $display("ALL PWM TRACE CORE TESTS PASSED");
  124. $display("==============================================");
  125. $finish;
  126. end else begin
  127. $display("PWM TRACE CORE TEST FAILED: %0d error(s)", errors);
  128. $display("==============================================");
  129. $fatal(1);
  130. end
  131. end
  132. endmodule