Digital PWM circuit: a counter and a comparator, live
A digital PWM (pulse-width modulation) generator makes a square wave whose high time you set with a number. This live one counts 0 to 7 over and over with a 3-bit counter and compares the count with a 3-bit duty value DT: the output PWM is 1 while the count is below DT, so it is high for DT of every 8 clocks, from always off (DT = 0) to 7/8 on (DT = 7).
This is how microcontroller timers make PWM: a counter runs freely, and a comparator turns its output on at the start of each period and off when the count reaches the compare value. The average of the output is the fraction of time it is high, DT/8 here, which is why PWM can dim an LED or set a motor's speed with nothing but on and off. The counter is a 3-bit synchronous counter (D0 = Q0', D1 = Q1 XOR Q0, D2 = Q2 XOR Q1 Q0), and the comparator is the less-than half of a magnitude comparator: count < DT if the top bits decide it, or they are equal and the next bits decide it, and so on down. More bits give finer steps: an 8-bit counter and comparator give 256 levels. The live circuit opens with CLR = 1, holding the count at 0, and DT = 100 (4, a 50% duty cycle): set CLR to 0 and watch PWM follow the count; change DT to change the width. Before the page is built, 40 clocks are checked on the count and on PWM, with DT set to 3, 6, 0 and 7 in turn.
Open this circuit in the lab →
What you need
- 3× D flip-flop with clear: the 3-bit counter Q2 Q1 Q0, on CLK, cleared by CLR
- 2× XOR + 1 AND: the counter's next state: D1 = Q1 XOR Q0, D2 = Q2 XOR (Q1 AND Q0); D0 = Q0'
- 2× XNOR: equality of the top two bits: Q2 XNOR DT2, Q1 XNOR DT1
- 6× AND + 2 OR: count < DT = Q2' DT2 + (Q2 = DT2) Q1' DT1 + (Q2 = DT2)(Q1 = DT1) Q0' DT0
Step by step
- Place a clock
CLK, inputsCLRandDT2toDT0, and probesQ2toQ0andPWM. - Build a 3-bit synchronous counter: D0 = Q0', D1 = Q1 XOR Q0, D2 = Q2 XOR (Q1 AND Q0), all cleared by CLR.
- Build a less-than comparator of the count against DT, starting from the top bit.
- Probe its output as PWM. Clear, then let the clock run: PWM is high for the first DT counts of every 8.
Duty cycle by DT
| DT | PWM high for counts | Duty cycle |
|---|---|---|
| 0 (000) | none | 0/8 = 0% |
| 1 (001) | 0 to 0 | 1/8 = 12.5% |
| 2 (010) | 0 to 1 | 2/8 = 25% |
| 3 (011) | 0 to 2 | 3/8 = 37.5% |
| 4 (100) | 0 to 3 | 4/8 = 50% |
| 5 (101) | 0 to 4 | 5/8 = 62.5% |
| 6 (110) | 0 to 5 | 6/8 = 75% |
| 7 (111) | 0 to 6 | 7/8 = 87.5% |
DT = 8 would mean always on, which needs a fourth bit (or a separate full-on switch); with 3 bits the steps are 12.5% each. The output only changes on clock edges, so the PWM frequency is the clock frequency divided by 8.
You can also read the full theory in the lesson on comparators. Prefer to build it yourself from scratch? Open the digiwleea lab and place the gates on the canvas, or start from the logic gate simulator.
Build more parts from gates
Each of these is one step from a transistor to a working CPU. Build every gate from CMOS transistors and work all the way up in the free digiwleea lab, with the free theory reference alongside.
Open the digital PWM generator in the lab →Frequently asked
How do you make a PWM signal with digital logic?
Run a binary counter continuously and compare its value with a duty-cycle number. The output is 1 while the count is less than the number and 0 for the rest of each period, so the fraction of time it is high is the number divided by the counter's range.
What is the duty cycle of a PWM signal?
The fraction of each period that the signal is high. Here it is DT/8: DT = 4 gives 50%, DT = 2 gives 25%.
What sets the PWM frequency?
The clock frequency divided by the counter's range: with a 3-bit counter each period lasts 8 clocks. A wider counter gives finer duty steps but, at the same clock, a lower PWM frequency.
What is PWM used for?
Controlling average power with a switch that is only ever fully on or fully off: dimming LEDs, setting motor speed, driving servos and, after a filter, making an analog voltage.