Skip to content
digiwleeaTools
LearnGlossaryAboutCheat sheetHow a CPU worksToolsOpen the lab →

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.

Big circuit: pinch, scroll or tap + to zoom in, then drag to move around.

Live circuit: click the inputs to toggle them and watch the outputs update. It runs the real simulator, right here on the page.

Open this circuit in the lab →

What you need

Step by step

  1. Place a clock CLK, inputs CLR and DT2 to DT0, and probes Q2 to Q0 and PWM.
  2. Build a 3-bit synchronous counter: D0 = Q0', D1 = Q1 XOR Q0, D2 = Q2 XOR (Q1 AND Q0), all cleared by CLR.
  3. Build a less-than comparator of the count against DT, starting from the top bit.
  4. 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

DTPWM high for countsDuty cycle
0 (000)none0/8 = 0%
1 (001)0 to 01/8 = 12.5%
2 (010)0 to 12/8 = 25%
3 (011)0 to 23/8 = 37.5%
4 (100)0 to 34/8 = 50%
5 (101)0 to 45/8 = 62.5%
6 (110)0 to 56/8 = 75%
7 (111)0 to 67/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

half adderfull adderhalf subtractorfull subtractor2:1 multiplexer4:1 multiplexerXOR gate from NAND gates2-to-4 decoderSR latchD flip-flopJK flip-flopT flip-flop4-bit shift register4-bit ripple carry adderD latch1-to-4 demultiplexer4-bit magnitude comparator4-bit ring counter4-bit Johnson counter4-to-2 priority encoder4-bit synchronous counter3-to-8 decoder8-to-1 multiplexer4-bit carry lookahead adderhalf adder from NAND gates2-bit comparatorBCD to 7-segment decoder4-bit up/down counterdecade counter2-bit multiplier4-bit ALU4-bit array multiplierNOT, AND, OR and NOR from NANDNOT, OR, AND and XOR from NORfull adder from NAND gatesSR latch from NAND gatesparity generator and checker4-bit adder/subtractorBCD adder4-bit universal shift registermod-6 counter4-bit ripple counterbinary to Gray code converterhalf adder from NOR gatesfull adder from NOR gates4-bit register with parallel load1011 sequence detectorbinary to BCD converterD flip-flop from NAND gates1-bit ALUCMOS inverterCMOS NAND gateCMOS NOR gatePISO shift registerSR flip-flop from NAND gatesBCD to excess-3 code converterHamming (7,4) code encoder and correctortraffic light controller4-bit barrel shifterCMOS AND gateCMOS OR gateCMOS XOR gate1-bit magnitude comparatorhalf subtractor from NAND gatesfull subtractor from NAND gates8-to-3 encoderGray to binary converter4-to-16 decoderfull adder using 4:1 multiplexersedge detectorserial adder4-bit carry-select adder4-bit Kogge-Stone adder4-bit carry-skip adder4x4 Wallace tree multiplier8-bit adderfrequency divider (by 2, 4 and 3)switch debouncer (SR latch)3-bit Gray code counterMealy machine (1011 detector)master-slave JK flip-flop (NAND)half subtractor from NOR gates1-to-8 demultiplexerexcess-3 to BCD code convertervending machine FSM4-bit carry-save adder3-bit synchronous counter (JK)CMOS transmission gatetri-state buffer (CMOS)2-to-1 mux from transmission gatesmod-5 counterflip-flop conversion (JK to D)8-bit ALUdecimal to BCD encoderBCD to decimal decoder4-to-1 mux from 2-to-1 muxesXOR gate from NOR gates4-bit LFSR74LS138 decoderBCD subtractor74181 ALUCMOS AOI gate (AOI21)D latch vs D flip-flop74LS47 BCD to 7-segment decoder74HC595 shift register7400 quad NAND gate chip7402 quad NOR gate chip7404 hex inverter chip7408 quad AND gate chip7432 quad OR gate chip7486 quad XOR gate chip7474 dual D flip-flop74HC165 shift registerCD4017 decade counter74LS283 4-bit adder74LS90 decade counter74HC161 4-bit counter74HC151 8-to-1 multiplexer74HC157 quad 2-to-1 multiplexer74HC139 dual 2-to-4 decoderCD4511 BCD to 7-segment decoder7492 divide-by-12 counter7493 4-bit binary counter74HC244 octal bufferRace-around condition (JK latch)74HC373 octal latch74HC374 octal D flip-flopTurnstile state machine1-to-2 demultiplexerhalf adder using 2:1 multiplexersregister file (4 x 4-bit)CD4013 dual D flip-flop74LS76 dual JK flip-flop7410 triple 3-input NAND chip7411 triple 3-input AND chip7420 dual 4-input NAND chipCD4011 quad 2-input NAND chipCD4001 quad 2-input NOR chipCD4081 quad 2-input AND chipCD4069 hex inverter chip74HC164 8-bit shift register7485 4-bit magnitude comparator74HC125 quad tri-state bufferCD4040 12-stage binary counterCD4060 14-stage counter and oscillator74LS193 4-bit up/down counterelectronic dice circuitmemory address register (MAR) and MDRhardware stack with a stack pointerdirect-mapped cache8-bit Brent-Kung adder4x4 Dadda multiplierbinary clock circuit

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.