Layout Knowledge Base

Getting started · Chips

Chip tutorial 1: quadrature encoder theory

A/B Gray code, direction, and distance — the mechanical and electrical problem before any RTL.

Last edited: September 21, 2026

Slotted encoder disk with optical sensors A, B, and Index Z

You want a small digital chip that knows which way a slotted disk is turning and how far it has gone, then hands that position to a host over I2C.

Direction is not in either waveform alone. It lives in which of A and B leads. At 180° electrical, B is the inverse of A, only two of the four states ever appear, and direction is gone. A once-per-revolution index, Z, does not add a step. It loads the fixed middle of the unsigned range, 0x80000000, so travel remains in both directions. Later parts have to honor that contract. Nothing here is a mask.

The disk the chip never draws

Slotted encoder disk with optical sensors A, B, and Index Z

Slotted encoder disk on a shaft. Two optical interrupters, A and B, watch one ring of holes about 90° electrical apart. A third mark, Index Z, fires once per revolution. A, B, and Z are the chip's digital inputs.

A hole in the gap lets light through and the digital output sits at one level. Solid material flips it. Place A and B on the same radius so that when A is in the middle of a hole, B sits near a hole edge. Their waveforms then sit about a quarter of one hole period apart. That quarter cycle is electrical degrees of the hole pitch, not 90° of shaft rotation. The drawing shows a few slots. Tutorial examples use on the order of 50 to 1000 holes.

On a real disk, watch one hole period and count the AB combinations. You want all four, in order, with uneven time still allowed. If B is only the inverse of A, you have wired a differential pair, which is the right trick for noise on one channel and the wrong trick for direction. Keep that pair off the quadrature inputs.

One sensor cannot say which way

A single interrupter says that something moved. Reverse the shaft and the pulse train looks the same. Software that assumes forward then walks the position the wrong way, and homing lands on the wrong side of travel. Two sensors fix that when their electrical phase is near a quarter cycle. In one rotation direction A's edges lead B's. In the other, B leads A. The decoder does not measure the lead in nanoseconds. It only needs to see which legal two-bit state follows which.

The Gray ring, counted on both edges of A

Treat A and B as two bits. As the disk turns smoothly, only one bit should change at a time:

00 → 01 → 11 → 10 → 00

Walk the ring one way for one rotation direction and the other way for reverse. A simultaneous jump such as 00 → 11 is noise, bounce, or a missed sample.

Ideal quadrature timing with forward and reverse lead/lag and ×2 edges

Ideal quadrature near 90° electrical. Forward: A leads B. Reverse: B leads A. Arrows mark the ×2 policy: both edges of A count, and B supplies direction.

This series counts both edges of A and uses B for direction. With 100 holes you get 200 steps per revolution. Counting every A and B edge is common in industrial peripherals. We stay at both edges of A so the table stays small. Rising edges of A alone would throw away half the motion A can report.

Gray-ring transition table for ×2 decode

Legal steps change exactly one bit. One sense of the ring increments. The opposite decrements. Diagonal jumps are illegal at the sample instant.

Hardware keeps the previous synchronized sample of A and B and compares it with the new sample. Same state: do nothing. A neighbor on the ring: add or subtract one, in the sense you document. A diagonal: leave the count alone and optionally set a sticky error. Swapped A and B wires still produce a clean counter, with the opposite idea of forward. Write which way is plus one, and do not flip the table later. If the clock samples slower than the edges arrive, legal neighbors collapse into diagonals. Fix the sample rate. Do not rewrite the ring.

Eighty degrees still works. One hundred eighty does not.

Ideal 90° is a target, not a requirement for the ring to be readable. At 80° or 100° electrical the four states still appear in order. Only the time spent in each state becomes uneven. Direction survives.

Non-ideal phase: 80°, 100°, and unusable 180°

(a) 80° and (b) 100° still walk all four states, with uneven intervals. (c) At 180°, B is the inverse of A. Only two combinations appear, so direction cannot be recovered.

At 180° you are back to one channel dressed as two wires. That failure is different from a differential A and A-not pair, which is intentionally 180° so a receiver can reject noise on a long cable. Differential signaling protects one bit. Quadrature needs two bits near a quarter cycle. Mixing those two uses of 180° is how a sensor gets wired so that it pulses and never says which way.

Index loads the middle. The ends saturate.

Power-up leaves an incremental count arbitrary until you home. When Z is qualified, the position register loads 0x80000000. There is no writable mid-scale register. Software that wants a different home subtracts an offset in the host.

uint32 counter saturates at ends; Index Z loads mid-scale

The position register is an unsigned 32-bit counter. It saturates at 0 and at all-ones. It does not wrap. An Index Z event loads 0x80000000.

Further reverse steps at zero leave the count at zero. Further forward steps at all-ones leave it at all-ones. Wrapping hides a runaway axis. Saturate-and-hold makes the end of the numeric budget visible. Motion that reverses after a saturate end walks the count back into the interior. Loading zero on the index would sit on that floor for any reverse motion. The middle leaves headroom both ways.

What one step is worth

Resolution here is how much shaft travel one counter step represents. Accuracy is whether the real edge lands where the geometry promised. A fine counter does not invent a precise disk.

With both edges of A counted, steps per revolution are twice the hole count. Treat diameter d as the teaching stand-in and resolution as π·d divided by the step count. Four teaching rows:

Holes Diameter Steps/rev Resolution uint32 range uint16 range
100 20 mm 200 0.314 mm ~1349 km ~20.6 m
400 5 mm 800 19.6 µm ~84 km ~1.29 m
50 100 mm 100 3.14 mm ~13500 km ~206 m
1000 25 mm 2000 39.3 µm ~169 km ~2.57 m

Four teaching geometries: resolution and uint32 vs uint16 range

Four geometries at this decode policy. The uint16 column is contrast: the same disk can exhaust 16 bits in meters while 32 bits still have kilometers of numeric headroom. This chip uses 32 bits.

The register read, high byte first

I2C here is a two-wire bus for a short board link. SCL is the clock, driven by the host. SDA carries address and data. Both lines are open-drain: a device may pull a line low and must not drive it high. Pull-up resistors return idle lines high. The chip is a slave only, at 7-bit address 0x42. A first bring-up uses the classic 100 kHz mode.

To fetch the position, the host writes a register pointer and then reads. The outline is START, address 0x42 with the write bit, the register address, a repeated START, the address with the read bit, the count bytes, a master NACK on the last byte, and STOP.

I2C register-read sequence for the uint32 count

Host register read: START, address plus write, register pointer, repeated START, address plus read, count bytes, master NACK, STOP. The drawing labels those count bytes MSB then LSB.

The count bytes on that read go out most-significant byte first, then down to the least-significant byte, which is what the drawing labels under the data slot. A host that assembles the first byte as the low eight bits will build a position the chip did not hold. Read all four bytes in one transaction after the pointer write latches the count. Mixing single-byte reads while the disk is moving assembles a value from two different moments.

Offset Name Access Role
0x00–0x03 COUNT R 32-bit position; on the wire, MSB byte then LSB byte
0x04 STATUS R sticky illegal transition
0x05 CTRL R/W soft clear of count, status, or both

Z always loads 0x80000000. Part 2 turns the ring, the saturation, and this read into RTL and checks them in simulation before any layout work begins.

Continue exploring