last updated: 2022-05-10
Song of this chapter: Supertramp > Breakfast in America > The logical song
As seen we can split the logic up in time-independent logic, where no memory is needed called the combinational logic, and the sequential logic.
In sequential logic the output depends on the present input but also on the history of the input. Sequential logic has memory!
Modern computing would not be possible without sequential logic (memory). Often circuits are a mixture of combinational and sequential logic.
We distinguish synchronous and asynchronous circuits in digital sequential logic.
Synchronous circuits have a clock signal and the state of the device changes only if the clock signal changes. Asynchronous circuits respond to changing inputs.
Let's begin with the basic circuit named flip-flop
. Flip-flops can be asynchronous (transparent, level triggered) or synchronous (clocked). Commonly the more simple asynchronous flip-flops are named latches
. The synchronous flip-flops using a clock signal are named flip-flops
.
In asynchronous sequential logic we don't find a clock signal. A changing level at an input triggers with a very short delay a reaction of an output level. The very short delay depends of the manufacturing process, the temperature, the complexity of the circuit etc. and is never equal for two circuits.
If we combine two incoming signals and one signal comes slightly later than the other, the state the receiving circuit goes into will depend on which signal gets to the gate first. Depending on very small differences in the delays the circuit can go into the wrong state. This is called a race condition.
Asynchronous sequential logic can be faster than synchronous logic because it must not wait for the clock signal. This logic is used only in a few critical circuits relying on speed, as small parts of microprocessors and digital signal processing circuits.
Asynchronous logic is difficult to design and problematic to use, so normally only synchronous circuits with clock signal are used in devices and computers.
So why a chapter on latches? They provide the possibility to fill the gap between combinational logic and synchronous sequential logic. Latches are building blocks of sequential circuits. They are build from logic gates and they help to understand how synchronous circuits work.
The latch is a memory element.
Memory can only be created with a feedback from the output to the input.
The two inputs of the latch are named Set
and Reset
, thus SR-latch.
Let's look at a very simple circuit to understand how it works, the SR-latch with AND
and OR
gates:
First we omit the feedback line and will successively change the states from Idle
(R = S = 0) to SET
(S = 1) and RESET
(R = 1), keeping in mind, that the F
input takes the state of the Q
output.
The following is no normal truth table, but a time related table!
F |
| | R |
S |
| | Q |
| | remark |
---|---|---|---|---|---|---|---|
0 | | | 0 |
0 |
| | 0 | | | system idle (at rest) |
0 | | | 0 | 1 |
| | 1 |
| | Set S HIGH → output Q HIGH, F gets HIGH |
1 |
| | 0 | 1 | | | 1 |
| | output Q stays HIGH |
1 | | | 0 |
0 |
| | 1 |
| | system idle : Q stays HIGH even when S goes back to LOW → memory state! |
1 | | | 1 |
0 | | | 0 |
| | Reset R HIGH → output Q LOW, F gets LOW |
0 |
| | 1 | 0 | | | 0 |
| | output Q stays LOW |
0 | | | 0 |
0 |
| | 0 |
| | system idle : Q stays LOW even when R goes back to LOW → memory state! |
As F = Q
let's connect the feedback line:
If we take a closer look at our table we see that Q
is HIGH
if S
OR
(NOT
R
AND
F
).
The Boolean formula for this circuit will be:
This circuit is for learning purpose, because real latches are not build from 3 different gates. Let's change the circuit to NOR
only gates:
Let's replace the AND
using the De Morgan law:
Now we can realize an SR-latch with only two NOR
gates, but we get an negated output!
But let's look at the system idle
states (R = S = 0
) of the table above.
Both NOR
gates have one input on 0
. Remember the truth table of a NOR
. If input B is 0
we see that input A is inverted.
B |
A |
| | Z |
---|---|---|---|
0 |
0 |
| | 1 |
0 |
1 |
| | 0 |
1 |
0 |
| | 0 |
1 |
1 |
| | 0 |
So the output of the first NAND (with R input) is a double negation of Q and with this circuit we also get a non inverted output!!
Redrawing the circuit gives us the typical circuit of a SR-NOR-latch
:
S |
R |
| | Q |
state |
---|---|---|---|---|
0 |
0 |
| | 0/1 |
hold previous state (memory) |
0 |
1 |
| | 0 |
reset |
1 |
0 |
| | 1 |
set |
1 |
1 |
| | X |
not allowed |
Case number 4 (S = R = 1) in the truth table is a forbidden case, because if both inputs are 1
, both NOR
's outputs are 0
. But than Q
can not be the same as ¬Q
.
A similar circuit is the SR-NAND-latch
. The NAND
-latch is active-low meaning the inputs are inverted:
NAND
-latch beginning with an SR-latch with AND and OR, by replacing the OR using the De Morgans law. The steps are similar to the steps we took to get the SR-NOR
-latch (draw the 3 circuits by hand!).Use the following program to count the bouncing of a switch. Document the output (Screenshot).
// Count bouncing
const byte PIN_IN = 1;
bool old_value = HIGH;
bool new_value;
int count = 0;
void setup() {
Serial.begin(115200);
delay(500);
pinMode(PIN_IN,INPUT_PULLUP); // HIGH if switch not pressed
}
void loop() {
Serial.println("Press the button now!");
while (old_value == HIGH) { //switch not pressed, wait
old_value = digitalRead(PIN_IN);
}
for (int i=0 ; i<1000; i++) {
new_value = digitalRead(PIN_IN);
if (new_value != old_value) {
count++;
old_value = new_value;
}
}
Serial.print("Number of bounces: ");
Serial.println(count/2);
count = 0;
while (old_value == LOW) { //switch pressed, wait
old_value = digitalRead(PIN_IN);
}
}
The bouncing of switches can easily be corrected in a software program with a delay()
and a subsequent control of the switch state. Another option is to resolve the problem with hardware. And here our NAND
-latch comes handily. Build and document a debounce circuit (draw the circuit by hand) with a single pole double-throw switch (SPDT) two external pull-up resistors (10k) and a NAND
-latch. Test the circuit with the program from above (without internal pull-up!). Note your findings.
As seen for the SR-latch we have two problems:
HIGH
, both NOR's output 0
. But than Q
can not be the same as ¬Q
.LOW
simultaneously after the forbidden case we get a race condition. The output gets either 1 or 0 depending on the propagation time relations between the gates.To solve the problems, we can add combinational logic gates to the inputs to convert the last case S = R = 1 to the first (memory), second (reset) or third case (set). The first possibility is called an E-latch and seldom used, the second possibility is an R dominated latch and the third possibility an S dominated latch.
An alternative would be to make the restricted combination (S = R = 1) toggle the output. This circuit is named a JK-latch (see JK-flip-flop).
Latches are transparent, meaning that changes to the input signal cause immediate changes in output. With additional logic we can make it non-transparent when an "Enable" input (E
) is not active. This can be done with two supplementary AND-gates to pass the inputs only if the enable signal is HIGH
:
Another good possibility is to use two NAND
's with a NAND
-latch:
Such a latch is named a gated SR-latch.
With E
LOW
the latch is closed (opaque) and remains in the state it was left the last time E
was high.
The gated SR-latch is level-sensitive to the level of the clock signal (most flip-flops are edge-sensitive to the clock), so we don't name the input clock but "Enable".
R
dominant gated SR-latch with only NAND
's (draw the circuit by hand) and test the latch on a breadboard. Document the truth table.If the S
input is HIGH
, the R
input is LOW
and vice versa. By connecting the S
input through an inverter to the R
input, we eliminate one input and we get a gated D-latch:
Note: In the symbol the Enable input is named 1C
, even it is not a edge-sensitive clock.
Gated D-latches can be found in the 74xx75
chip.
Timing diagrams help to understand the behaviour of sequential logic circuits.
S
dominant gated SR-latch and a gated D-latch.As already mentioned asynchronous logic is difficult to design and problematic to use.
If there are changes in the data of a gated D-latch when the enable pulse is HIGH
, the output Q changes in sympathy with D. It remembers only the last input state that occurred during the clock pulse. This effect is called "Ripple Through", and is not a desirable property, because states are not really predictable. In programmed logic (CPLD
, FPGA
) we even don't find cells with gated latches.
So normally only synchronous circuits with clock signal are used in devices and computers.
Flip-flops
are the building blocks of sequential and synchronous circuits. They change their output only at times determined by the clock. Most flip-flops are edge triggered, meaning that the output changes when there is a change in the clock pulse.
Flip-flops have a clock signal and change the their output only when the clock signal changes (edge triggered).
A simple clock circuit could be build with a high pass filter as seen in [ELEctronic FUndamentals)(http://weigu.lu/tutorials/electronics/06capacitorinductor/index.html).
Positive edge triggered flip-flops get a triangle in the symbol. Here the symbols for a D-FF with a positive edge triggered clock and a negative edge triggered clock:
The D-FF is simple and useful. Upon a clock edge (normally rising) the input is passed to the output. It's often used as basic element in programmable logic design.
D-FFs can be found in the 74xx74
chip (with an additional S and R input) or the 74xx174
.
With D-FFs we are able to build our first register, the base memory element of a computer.
The data is memorised in the register only when the clock signal rises from 0
to 1
.
An 8 bit edge triggered D-FF register can be found in IC's like the 74xx374
or 74xx574
.
Register can easily be enlarged to interesting other circuits with a little combinational logic like the following shift register.
We have seen the shift operators in Arduino. The same shifting can also easily be done in hardware.
We find shift registers with both parallel and serial inputs and outputs. Especially interesting are PISO
(Parallel-In, Serial-Out) and SIPO
(Serial-In, Parallel-Out) register, because they allow to convert a parallel stream to serial and back, a feature needed for serial bus interfaces like EIA232
, I²C
and SPI
.
They also allow to multiply the output and input pins of our microcontroller.
Each rising edge of the D-FF's reads the input and shifts the content 1 bit to the right as seen in the timing diagram. A problem is the changing of the value at the parallel output for each clock pulse. If we drive e.g. 4 relays at the parallel output, they will change clatter for each change. To avoid this behaviour we add a normal register to the output.
After shifting for times (4x SRCLK
), the rising edge of the register clock (RCLK
) passes the shifted nibble to the output.
The SIPO
is often used to get more output pins for our microcontroller circuits. One pin on our microcontroller can drive 8 or more (by combining the shift register) output pins.
An 8 bit SIPO can be found in the IC 74xx595
.
We want to drive 8 LED's with one pin. A handy chip for this is the 74xx595
. What role plays the /OE
-pin (explain what tristate means)?
Build and test the following circuit (add a photo) with 8 LED's. Explain in detail what happens in the software (function shiftx8()
) respectively in the SIPO
-Chip (look at the time diagrams in the data sheet!).
In Arduino an integrated function named shiftOut()
(look here), does quite the same thing than our shiftx8()
function. Change the program and use the shiftOut()
-function instead of shiftx8()
.
// SIPO_75595.ino
// /OE to GND
const byte PIN_SER = 0; // SER = serial in
const byte PIN_RCLK = 1; // RCLK = register clock (STORE, load)
const byte PIN_SRCLK = 2; // SRCLK = shift register CLK
const byte PIN_SRCLR = 3; // SRCLR = shift register clear = /RESET
const byte pattern[16] = {0xC0, 0x60, 0x30, 0x18, 0x24, 0x42, 0x81, 0x42,
0x24, 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18 };
byte sipo_byte, bit_to_shift, i, j;
void setup() {
pinMode(PIN_SER, OUTPUT);
pinMode(PIN_SRCLK, OUTPUT);
pinMode(PIN_RCLK, OUTPUT);
pinMode(PIN_SRCLR, OUTPUT);
digitalWrite(PIN_SRCLK, LOW); // CLK = low
digitalWrite(PIN_RCLK, LOW); // STORE = low
digitalWrite(PIN_SRCLR, HIGH); // RESET = high (active low)
}
void loop() {
for (j=0; j<16; j++) {
sipo_byte = pattern[j];
shiftx8(sipo_byte);
delay(100);
}
}
void shiftx8(byte sipo_byte) {
for (i=0; i<8; i++) {
bit_to_shift = sipo_byte & 0x80; // mask MSB
if (bit_to_shift == 0) {
digitalWrite(PIN_SER,LOW); // data in
}
else {
digitalWrite(PIN_SER, HIGH);
}
digitalWrite(PIN_SRCLK, HIGH); // clock positive edge SRCLK
digitalWrite(PIN_SRCLK, LOW);
sipo_byte <<= 1; // left shift data byte
}
digitalWrite(PIN_RCLK, HIGH); // store to register
digitalWrite(PIN_RCLK, LOW);
}
To load data parallel to our shift register we need multiplexer.
The first serial input (IN) is only needed if cascading PISO
to bigger register.
If LOAD
is LOW
, the input nibble is switched to the D-FF's inputs. After a CLK
signal, the nibble is loaded into the FF's. Than LOAD
can go to HIGH
, so that the shift register can work, and the nibble can be shifted out.
Serial.print()
on our serial monitor. We will use the 74HC165
IC. Use the following link as help: https://playground.arduino.cc/Code/ShiftRegSN74HC165N/.Other interesting and important circuits, that can be realised with flip-flops are FIFO
and LIFO
shift register, counters (asynchronous, synchronous, modulo, ring), frequency divider (T-FF
) etc..