A **tri-state buffer** gate controls whether the input affects the circuit at all. When the controlling input is off, the input is disconnected from the rest of the system, leaving the output of the buffer as a third state **Z** (high impedance).
Tri-state buffers are often used to implement **select inputs** or **multiplexers** — setting the mux switch in one direction or another only allows signals from one input to pass through.
NAND and NOR are **universal gates** — some combination of them can form any other logic gate. Constructions of other gates using only these gates are called **NAND-NAND realisations** or **NOR-NOR realisations**.
This is useful in SOP as if two ANDs feed into an OR, all can be turned into NANDs to achieve the same result.
!!! example
NOT can be expressed purely with NAND as $A$ NAND $A$:
The **synthesis** of an algebraic formula represents its implementation via logic gates. In this course, its total cost is the sum of all inputs to all gates and the number of gates, *excluding* initial inputs of "true" or an initial negation.
In order to deduce an algebraic expression from a truth table, **OR** all of the rows in which the function returns true and simplify.
The **minterm** $m$ is a **product** term where all variables in the function appear once. There are $2^n$ minterms for each function, where $n$ is the number of input variables.
To determine the relevant function, the subscript can be converted to binary and each function variable set such that:
- if the digit is $1$, the complement is used, and
- if the digit is $0$, the original is used.
$$m_j=x_1+x_2+\dots x_n$$
!!! example
For a function that accepts three variables:
- there are eight minterms, from $m_0$ to $m_7$.
- the sixth minterm $m_6=xyz'$ because $6=0b110$.
For a sample function defined by the following minterms:
$$
\begin{align*}
f(x_1,x_2,x_3)&=\sum m(1,2,5) \\
&=m_1+m_2+m_5 \\
&=x_1x_2x_3' + x_1x_2'x_3 + x_1'x_2x_3'
\end{align*}
$$
The **maxterm** $M$ is a **sum** term where all variables in the function appear once. It is more or less the same as a minterm, except the condition for each variable is **reversed** (i.e., $0$ indicates the complement).
$$M_j=x_1+x_2+\dots +x_n$$
!!! example
For a sample function defined by the following maxterms:
\begin{align*}
f(x_1,x_2,x_3,x_4)&=\prod M(1,2,8,12) \\
&=M_1M_2M_8M_{12} \\
\end{align*}
??? example
Prove that $\sum m(1,2,3,4,5,6,7)=x_1+x_2+x_3$: **(some shortcuts taken for visual clarity)**
Binary is represented in hardware via switches called **transistors**. Above a certain voltage threshold, its output is $1$, whlie it is $0$ if below a threshold instead.
A transistor has three inputs/outputs:
- A ground
- An input **source**, which has voltage that determines whether the circuit is connected to the ground
- An output **drain**, which will either be grounded or have a voltage depending on whether the switch is closed.
A **field-programmable gate array** (FPGA) is hardware that does not come with factory-fabricated AND and OR gates, requiring the user to set them up themselves. It contains:
- input/output pads
- routing channels (to connect with physical wires and switches)
- logic blocks (that are user-programmed to behave like gates)
- lookup tables (LUTs) inside the logic gates, which are a small amount of memory
The Gray code is a binary number system that has any two adjacent numbers differing by **exactly one bit**. It is used to optimise the number of gates in a function.
The 1-bit Gray code is $0, 1$. To convert an $n$-bit Gray code to an $n+1$-bit Gray code:
- Mirror the code: $0,1,1,0$
- Add $0$ to the original and $1$ to the new ones: $00, 01, 11, 10$
Sorting truth table inputs in the order of the Gray code makes optimisation easier to do.
A **"don't care"** is represented by a $d$ in truth tables. It is used for optimisation if the state of that output doesn't matter, and can be treated as a one or a zero as desired.
It can be more efficient to optimise two different functions differently such that they are more optimised when combined.
Each 1 square is effectively a minterm, and finding the least number of rectangles that only cover "1"s allows for the simplest algebraic form of the truth table to be deduced. If needed, rectangles can wrap around on any side. The same rules apply to optimise for maxterms (product of sums), or $f'$, by optimising for zeros.
A **binary encoder** takes $2^n$ inputs and $n$ outputs, with the binary representation of the $n$ outputs indicating the inputs enabled by binary index.
- A **combinatorial circuit** is dependent on present signals.
- A **sequential circuit** is dependent on past and present signals, using storage elements to track state.
**Synchronous** sequential circuits only change signals at discrete times, such as with clock signals. Asynchronous circuits change whenever.
### Clocks
!!! definition
- The **period** $t$ is the duration of one clock cycle.
- The **frequency** $f$ is the reciprocal of the period.
- The **rising edge** is the instant a clock changes from $0$ to $1$.
- The **falling edge** is the instant a clock changes from $1$ to $0$.
### Storage elements
A **basic latch** changes based on its input signal level such that it is level-sensitive.
A **gated latch** is a basic latch as well as a control input that locks the current state. The latch is only togglable when the control input is on.
A **flip-flop** contains two gated latches and a control input. The state is only adjustable during the edges of the control signal, so it can only change up to once per cycle.
An **RS-NOR** basic latch has a *set* input that must be *reset* before being set again, with one output representing each state. Setting both to one resets both outputs to zero.
An **RS-NAND** basic latch operates the same way, and looks practically the same, except shifting to $(1, 1)$ resets both to zero instead, and $(0, 0)$ causes no change.
### Synchronous latches
A **NAND gated latch** only allows changes when the clock control input *clk* is on.
A **gated D latch** effectively stores $R$ and $S$ by assuming that they are the complement for each other, setting $R$ as $D$ and $S$ as $D'$ or vice versa. This **level-sensitive** latch is commonly used to store past state as there is no change when *clk* is zero.