Basic Pulse Width Modulator
Digital control of analog systems like LEDs and motors relies on pulse width modulation (PWM) to approximate continuous voltage levels using discrete digital switching. A PWM generator translates a digital duty cycle value into a high-frequency switching signal, allowing a microcontroller to dim a light or control motor speed without a digital-to-analog converter.
The module maintains a free-running 8-bit internal counter that increments on every clock cycle. It compares this counter against the requested 8-bit duty cycle. When the counter is strictly less than the duty cycle, the output is driven high. When the counter reaches or exceeds the duty cycle, the output is driven low. To ensure true 0% and 100% states, a duty cycle of 8'd0 must force the output to 0 continuously, and a duty cycle of 8'd255 must force the output to 1 continuously.
Clock edge: posedge clk Reset type: Asynchronous Reset polarity: Active-low (rst_n) Output values on reset: The internal counter is cleared to 8'd0 and pwm_out is driven to 1'b0. Priority rules: Reset takes priority over all other operations. Both the internal counter and pwm_out are updated on the positive edge of clk. During this update, pwm_out is evaluated using the counter's value *before* it increments.
Worked Trace: Cycle 1: rst_n=0 → cnt=0, pwm_out=0 (async reset) Cycle 2: rst_n=1, duty=2 → cnt=1, pwm_out=1 (evaluates 0 < 2) Cycle 3: duty=2 → cnt=2, pwm_out=1 (evaluates 1 < 2) Cycle 4: duty=2 → cnt=3, pwm_out=0 (evaluates 2 >= 2) Cycle 5: duty=2 → cnt=4, pwm_out=0 (evaluates 3 >= 2)
{ "signal": [
{ "name": "clk", "wave": "p........" },
{ "name": "rst_n", "wave": "01......." },
{ "name": "duty", "wave": "=========...", "data": ["2","2","2","2","2","2","2","2","2"] },
{ "name": "cnt", "wave": "=.=.=.=.=.=.=.=.", "data": ["0","1","2","3","4","5","6","7"] },
{ "name": "pwm_out", "wave": "0.1...0........." }
], "head": { "text": "PWM generation with duty=2." } }| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset; clears counter and output to 0 | | duty | input | 8 | Desired duty cycle (0 to 255) | | pwm_out | output | 1 | Registered PWM output |
Constraints
clkis positive-edge triggered.rst_nis asynchronous and active-low.- On reset, the internal counter must be
8'd0andpwm_outmust be1'b0. pwm_outmust be a registered output, updating on the same clock edge that the counter increments.- If
dutyis8'd0,pwm_outmust remain1'b0continuously. - If
dutyis8'd255,pwm_outmust remain1'b1continuously. - The 8-bit counter naturally wraps from 255 to 0; no explicit reset of the counter is needed at 255.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.