pwm_control_demo_tb.v 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. `timescale 1ns/1ps
  2. module pwm_control_demo_tb;
  3. reg clk;
  4. reg reset_n;
  5. reg signed [7:0] cmd;
  6. reg enable;
  7. reg fault;
  8. wire signed [7:0] limited_cmd;
  9. wire direction;
  10. wire [6:0] duty;
  11. wire pwm_out;
  12. integer errors;
  13. integer high_count;
  14. integer i;
  15. pwm_control_demo dut (
  16. .clk(clk),
  17. .reset_n(reset_n),
  18. .cmd(cmd),
  19. .enable(enable),
  20. .fault(fault),
  21. .limited_cmd(limited_cmd),
  22. .direction(direction),
  23. .duty(duty),
  24. .pwm_out(pwm_out)
  25. );
  26. // 100 MHz simulation clock.
  27. // Frequency itself is not important for this demo;
  28. // PWM duty ratio is what we verify.
  29. initial clk = 0;
  30. always #5 clk = ~clk;
  31. task check_control;
  32. input signed [7:0] test_cmd;
  33. input signed [7:0] expected_limit;
  34. input expected_direction;
  35. input [6:0] expected_duty;
  36. begin
  37. cmd = test_cmd;
  38. #1;
  39. if (limited_cmd !== expected_limit) begin
  40. $display("FAIL limiter: cmd=%0d expected=%0d actual=%0d",
  41. test_cmd, expected_limit, limited_cmd);
  42. errors = errors + 1;
  43. end else begin
  44. $display("PASS limiter: cmd=%0d -> %0d",
  45. test_cmd, limited_cmd);
  46. end
  47. if (direction !== expected_direction) begin
  48. $display("FAIL direction: cmd=%0d expected=%0d actual=%0d",
  49. test_cmd, expected_direction, direction);
  50. errors = errors + 1;
  51. end else begin
  52. $display("PASS direction: cmd=%0d direction=%0d",
  53. test_cmd, direction);
  54. end
  55. if (duty !== expected_duty) begin
  56. $display("FAIL duty: cmd=%0d expected=%0d actual=%0d",
  57. test_cmd, expected_duty, duty);
  58. errors = errors + 1;
  59. end else begin
  60. $display("PASS duty: cmd=%0d duty=%0d%%",
  61. test_cmd, duty);
  62. end
  63. end
  64. endtask
  65. task check_pwm;
  66. input [6:0] expected_percent;
  67. begin
  68. high_count = 0;
  69. // Measure exactly one complete 100-clock PWM period.
  70. for (i = 0; i < 100; i = i + 1) begin
  71. @(negedge clk);
  72. if (pwm_out)
  73. high_count = high_count + 1;
  74. end
  75. if (high_count !== expected_percent) begin
  76. $display("FAIL PWM: expected=%0d%% measured=%0d%%",
  77. expected_percent, high_count);
  78. errors = errors + 1;
  79. end else begin
  80. $display("PASS PWM: expected=%0d%% measured=%0d%%",
  81. expected_percent, high_count);
  82. end
  83. end
  84. endtask
  85. initial begin
  86. errors = 0;
  87. reset_n = 0;
  88. cmd = 0;
  89. enable = 0;
  90. fault = 0;
  91. repeat (3) @(posedge clk);
  92. reset_n = 1;
  93. $display("");
  94. $display("========== PWM CONTROL TEST ==========");
  95. // Normal forward command
  96. enable = 1;
  97. fault = 0;
  98. check_control(25, 25, 0, 25);
  99. check_pwm(25);
  100. // Another normal command
  101. check_control(50, 50, 0, 50);
  102. check_pwm(50);
  103. // Upper limiter
  104. check_control(95, 90, 0, 90);
  105. check_pwm(90);
  106. // Reverse command
  107. check_control(-50, -50, 1, 50);
  108. check_pwm(50);
  109. // Lower limiter
  110. check_control(-120, -90, 1, 90);
  111. check_pwm(90);
  112. // Zero command
  113. check_control(0, 0, 0, 0);
  114. check_pwm(0);
  115. // Disable interlock
  116. cmd = 50;
  117. enable = 0;
  118. fault = 0;
  119. #1;
  120. check_pwm(0);
  121. $display("PASS enable=0 forces PWM OFF");
  122. // Fault interlock
  123. enable = 1;
  124. fault = 1;
  125. #1;
  126. check_pwm(0);
  127. $display("PASS fault=1 forces PWM OFF");
  128. $display("");
  129. if (errors == 0) begin
  130. $display("======================================");
  131. $display("ALL TESTS PASSED");
  132. $display("======================================");
  133. $finish;
  134. end else begin
  135. $display("======================================");
  136. $display("TEST FAILED: %0d error(s)", errors);
  137. $display("======================================");
  138. $fatal(1);
  139. end
  140. end
  141. endmodule