`timescale 1ns/1ps module pwm_control_demo_tb; reg clk; reg reset_n; reg signed [7:0] cmd; reg enable; reg fault; wire signed [7:0] limited_cmd; wire direction; wire [6:0] duty; wire pwm_out; integer errors; integer high_count; integer i; pwm_control_demo dut ( .clk(clk), .reset_n(reset_n), .cmd(cmd), .enable(enable), .fault(fault), .limited_cmd(limited_cmd), .direction(direction), .duty(duty), .pwm_out(pwm_out) ); // 100 MHz simulation clock. // Frequency itself is not important for this demo; // PWM duty ratio is what we verify. initial clk = 0; always #5 clk = ~clk; task check_control; input signed [7:0] test_cmd; input signed [7:0] expected_limit; input expected_direction; input [6:0] expected_duty; begin cmd = test_cmd; #1; if (limited_cmd !== expected_limit) begin $display("FAIL limiter: cmd=%0d expected=%0d actual=%0d", test_cmd, expected_limit, limited_cmd); errors = errors + 1; end else begin $display("PASS limiter: cmd=%0d -> %0d", test_cmd, limited_cmd); end if (direction !== expected_direction) begin $display("FAIL direction: cmd=%0d expected=%0d actual=%0d", test_cmd, expected_direction, direction); errors = errors + 1; end else begin $display("PASS direction: cmd=%0d direction=%0d", test_cmd, direction); end if (duty !== expected_duty) begin $display("FAIL duty: cmd=%0d expected=%0d actual=%0d", test_cmd, expected_duty, duty); errors = errors + 1; end else begin $display("PASS duty: cmd=%0d duty=%0d%%", test_cmd, duty); end end endtask task check_pwm; input [6:0] expected_percent; begin high_count = 0; // Measure exactly one complete 100-clock PWM period. for (i = 0; i < 100; i = i + 1) begin @(negedge clk); if (pwm_out) high_count = high_count + 1; end if (high_count !== expected_percent) begin $display("FAIL PWM: expected=%0d%% measured=%0d%%", expected_percent, high_count); errors = errors + 1; end else begin $display("PASS PWM: expected=%0d%% measured=%0d%%", expected_percent, high_count); end end endtask initial begin errors = 0; reset_n = 0; cmd = 0; enable = 0; fault = 0; repeat (3) @(posedge clk); reset_n = 1; $display(""); $display("========== PWM CONTROL TEST =========="); // Normal forward command enable = 1; fault = 0; check_control(25, 25, 0, 25); check_pwm(25); // Another normal command check_control(50, 50, 0, 50); check_pwm(50); // Upper limiter check_control(95, 90, 0, 90); check_pwm(90); // Reverse command check_control(-50, -50, 1, 50); check_pwm(50); // Lower limiter check_control(-120, -90, 1, 90); check_pwm(90); // Zero command check_control(0, 0, 0, 0); check_pwm(0); // Disable interlock cmd = 50; enable = 0; fault = 0; #1; check_pwm(0); $display("PASS enable=0 forces PWM OFF"); // Fault interlock enable = 1; fault = 1; #1; check_pwm(0); $display("PASS fault=1 forces PWM OFF"); $display(""); if (errors == 0) begin $display("======================================"); $display("ALL TESTS PASSED"); $display("======================================"); $finish; end else begin $display("======================================"); $display("TEST FAILED: %0d error(s)", errors); $display("======================================"); $fatal(1); end end endmodule