There's something wrong with the phase part of the rotary encoder section. It might be that a lot of folks have damaged chips, but it is hard to tell from afar. Need to revisit and/or revise that part, as it inhibits the counter part.

Actually, maybe we should drop the flip-flops and work with ADCs again. Then they could input data into the FPGA that way to better illustrate their use cases. For instance, we could do something to implement a filter via FPGA and send it right back out. Worth consideration.

Pages 588-596

D Flip Flops: Giving Circuits Memory

Now, digital logic isn't all that helpful without the ability to store any data, so let's work with some basic memory circuits.  There are a whole lot of variants, but we'll be starting with the D flip-flop.  This circuit is implemented with a single chip (the SN74HCT74N) which has four inputs (Set, Reset, Data, and >, the Clock) and two outputs($Q$ and $\overline{Q}$), as shown below. Note that there are two flip-flops per chip.

Pinout for the SN74HCT74N dual D flip-flop chip.  Note that each side of pins has an independent flip-flop circuit. Original courtesy of

In typical operation, the output $Q$ is the same as the last voltage seen at the data input $D$ when the clock signal > made a transition to high.  Typically the other output $\overline{Q}$ is the negation of $Q$ (i.e. if $Q$ is high, $\overline{Q}$ is low). The Set and Reset inputs are typically held high, but when they're pulled low (0V) S will set $Q$ high and $\overline{Q}$ low and R will do the opposite. This happens regardless of the clock or data inputs.

For our purposes, we're using this chip as a single bit of memory: the output $Q$ remembers the input $D$ when the clock > transitions to +5 V.

This lab will have you building the most interconnected circuit you've made all quarter. It will help to be methodical in your wiring to make it easier to follow what you've done.

Flip Flop Basics

To start off, we'll want to rebuild our logic-level button similarly to the previous lab.

}  |
| Logic button circuit  | 

Connect the button's output to the clock $\gt$ input, and one LED to the  $Q$ output of the flip-flop.  Finally, connect the function generator to both the other LED indicator and the $D$ input, as shown in the block diagram below:

<div figure wide>
| {{:phylabs:lab_courses:phys-226-wiki-home:lab_14_flip_flops_alt:flipflop_test_3x.png|
A circuit for saving the last clock state, controlled by a button. Note that Set and Reset should be connected to 5V for this to work at all.

With the function generator set up to produce a slow (1Hz) 0-5V square wave, let's try a few things

You need to change your square wave to either have a 2.5V offset, or you can directly set the min/max levels. Failure to do this will make your circuit behave unpredictably.

Verify that the output $Q$ only changes when you press the button AND the function generator signal is the opposite of $Q$, and that it otherwise saves its state. In other words, pushing the button should set $Q$ to the function generator's state (+5V or 0).
Use a wire to pull the $S$et input to ground, and verify that $Q$ behaves as it should

Looking for Changes: Reprising the Rotary Encoder

Last lab we made some discrete logic circuits that would tell us the exact state that our encoder circuit was in. Using a Flip-flop we can do something else useful: generate a signal whenever an encoder output changes. By doing this we can sync the information about changes in the state of the encoder with our clock, making the information much more usable by digital systems.

To start, let's consider the circuit shown below:

A D-flip-flop circuit (left) used as input for an XOR logic gate (right). The eXclusive OR operation outputs high if the inputs are different and low if they are the same.

Construct and test your circuit, verifying that the output Q1 of the XOR circuit only changes for one clock cycle when the input changes. This might be clearest if you hook both the function generator and Q1 up to LED circuits; the Q1 LED will light up after changing the dial slightly until the next time the function generator output is high.

Next, repeat the same for the other output of the encoder:

Detecting changes

Now that we can detect if either A or B changes, we can take those to outputs together into another OR gate (or XOR, since we should never have both to change at once) to make a “change detected” output

Chain your outputs from the flip-flop circuit into another XOR gate, and verify that there are outputs on Q3 whenever either A or B change state. Since it can be hard to turn the encoder slowly enough, up your clock rate from the function generator to 10Hz or so.

Who's in charge here? Digital Signal Phase

So, if A is always changing state before B, then our encoder is turning clockwise. Likewise, if B is leading A, then we're turning counterclockwise. While this is simple to put into words, it will take a bit to put it into logic circuitry.

A visualization of a turning rotary encoder. Note that the outer ring represents A and the inner ring represents B.

Let's consider the following circuit:

Here, we are using an eXclusive OR (XOR) gate to check if exactly one of A or B is high, and if so to output a signal. If A is leading B, then this gate will change from low to high whenever A changes state.

0 0 0 0
1 1 0 1 A Changed
2 1 1 0
3 0 1 1 A Changed

Likewise, if B is leading A, then the gate will change from low to high whenever B changes state.

0 0 0 0
1 0 1 1 B Changed
2 1 1 0
3 1 0 1 B Changed

Hook up your rotary encoder outputs $V_{out,A}$ and $V_{out,B}$ to an XOR gate and verify that the output Q4 changes in sync with the signal that is leading. You may need to adjust the function generator frequency to help you observe things.

Using that memory

Now, we would like to make something that tells us both which signal is leading (for direction) at the instant that a change in state occurs. However, you may notice a problem here. Our direction indicator changes at the same time that our signal changes! If there's any delay in our circuit this could end up resulting in very unreliable behavior.

As a fix, let's consider a case where we save the state of B at a rate quick enough that it happens between changes in either B or A. We'll call the saved value B' here. Now the behavior is much more robust, resulting in the values we'd expect every time (i.e., A XOR B' is always 1 at times when a value is changing and A leads B, and always 0 at times when a value is changing and B leads A.)

0 0 0 0
0.5 0 0 0
1 1 0 0 1 1
1.5 1 0 0
2 1 1 0 0 1
2.5 1 1 1
3 0 1 1 1 1
3.5 0 1 1
4 0 0 1 0 1

Now consider the other direction:

0 0 0 0
0.5 0 0 0
1 0 1 0 1 0
1.5 0 1 1
2 1 1 1 0 0
2.5 1 1 1
3 1 0 1 1 0
3.5 1 0 1
4 0 0 0 0 0

Test what happens for XORing A and B'

Do they behave as expected?

Leave your circuit built!

Digital Counters

Counting back and forth: the SN74HCT191 chip

By counting the state changes from our rotary encoder and noting the direction, we can record how far it has been displaced from its starting point. While we could chain multiple flip-flops together to make a counter with one bit per flip-flop, that would get cumbersome quite quickly. Furthermore, a basic flip-flop counter can only count upwards. Fortunately for us, there are already purpose-made chips that do what we need!  Here's the setup for a 4-bit counter, the 74HCT191:

Full pinout of our 4 bit counter. Configuration to turn your chip into an up/down binary counter.  It isn't nearly as bad as you'd think!

While this chip has quite a few features, we'll configure it to do two: count up and down in binary.  Wire up the chip as shown above at right.

Using the function generator as a clock input on pin 14, (and grounding pin 5 to make the counter increase) watch each of the outputs A,B,C, and D and verify that the frequency they change at decreases by a factor of two for each one.

Instead of looking at each output on the scope, we can use LEDs as indicators here to show what's going on visually

Test the counter by using a series of LEDs as outputs

A Lab Cliffhangar

In addition to just counting upwards endlessly like a flip-flop clock, we can also count downwards with the 74HCT191. Whenever the Up/Down pin is low the chip counts up, and when it is high it will count down.

In combination with our logic that we've created for our rotary encoder, we can now build a circuit that should count how many fractional turns we've made from when it is initialized.

As you might have guessed, there can be issues with this setup so don't be surprised if it behaves oddly. We'll work on fixing it next week.

Build and test your counter by hooking up your encoder logic to the CLOCK and UP/DOWN inputs of the counter chip.

Now, unless you're exceptionally lucky, it probably didn't work at all as intended. To see why, hook up your scope to the D/U and CLK (5 & 14) pins of your counter and zoom your scope in to a 500ns timescale. While some signal transitions will look nice, you'll see some here that others will have high frequency (10's of MHz) noise. Our rotary encoder does not provide as clean of a signal as our function generator, if you look at $V_{out,A}$ or B on the scope at around a 100 $\mu$s time scale you can find instances where the output changes multiple times in a row. This can be due to the mechanical contacts vibrating in the encoder, which is a hard thing to eliminate entirely. There are ways to “debounce” the signal (hello Schmitt trigger!) that could help here, but this is the end of today's lab.

While we could buy fancier chips or start chaining multiple ones together, implementing this in hardware can become tedious quickly. However, this is exactly the sort of problem that FPGAs are great at addressing, as it is straightforward to have it simulate numerous logic family chips all at once. Of course, you could also write software to read and interpret inputs to accomplish the same task. But if you either need speed (FPGAs can do some operations much quicker than an equivalently priced microcontroller) or capacity (FPGAs also tend to have many inputs that can receive data in parallel) then an FPGA might be the solution for you.