eifueo/docs/1b/ece124.md
2023-10-30 15:47:39 -04:00

592 lines
24 KiB
Markdown

# ECE 124: Digital Circuits
## Base / radix conversion
Please see [ECE 150: C++#Non-decimal numbers](/1a/ece150/#non-decimal numbers) for more information.
## Binary logic
A **binary logic variable** is a variable that has exactly two states:
- 0, or false (switch open)
- 1, or true (switch closed)
**Binary logic functions** are any function that satisfies the following type signature:
```python
BoolFunc = Callable[[bool | BoolFunc, ...], bool]
```
In other words:
- it must accept a number of booleans and/or other logic functions, and
- it must return exactly one boolean.
These can be expressed via truth table inputs/outputs, algebraically, or via a logical circuit schematic.
### Logical operators
Operator precedence is () > NOT > AND > OR.
The **AND** operator returns true if and only if **all** arguments are true.
$$A\cdot B \text{ or }AB$$
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b9/AND_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)
The **OR** operator returns true if and only if **at least one** argument is true.
$$A+B$$
<img src="https://upload.wikimedia.org/wikipedia/commons/1/16/OR_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)</img>
The **NOT** operator returns the opposite of its singular input.
$$\overline A \text{ or } A'$$
<img src="https://upload.wikimedia.org/wikipedia/commons/6/60/NOT_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)</img>
The **NAND** operator is equivalent to **NOT AND**.
$$\overline{A\cdot B}$$
<img src="https://upload.wikimedia.org/wikipedia/commons/e/e6/NAND_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)</img>
The **NOR** operator is equivalent to **NOT OR**.
$$\overline{A+B}$$
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c6/NOR_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)</img>
The **XOR** operator returns true if and only if the inputs are not equal to each other.
$$A\oplus B$$
<img src="https://upload.wikimedia.org/wikipedia/commons/1/17/XOR_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)</img>
The **XNOR** operator is equivalent to **NOT XOR**.
$$\overline{A\oplus B}$$
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b8/XNOR_ANSI_Labelled.svg" width=200>(Source: Wikimedia Commons)</img>
### Buffer gates
The **buffer** gate returns the input without any changes, and is usually used for adding delays into circuits.
<img src="https://upload.wikimedia.org/wikipedia/commons/7/75/Digital_buffer.svg" width=200>(Source: Wikimedia Commons</img>
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).
One example of a tri-state buffer is a switch.
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c0/Tristate_buffer.svg" width=400>(Source: Wikimedia Commons)</img>
!!! example
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.
<img src="https://upload.wikimedia.org/wikipedia/commons/1/16/Multiplexer2.svg" width=400>(Source: Wikimedia Commons)</img>
### NAND/NOR completeness
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$:
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3f/NOT_from_NAND.svg" width=150>(Source: Wikimedia Commons)</img>
### Postulates
In binary algebra, if $x,y,z\in\mathbb B$ such that $\mathbb B=\{0, 1\}$:
The **identity element** for **AND** $1$ is such that any $x\cdot 1 = x$.
The **identity element** for **OR** $0$ is such that any $x + 0 = x$.
In this space, it can be deduced that $x+x'=1$ and $x\cdot x'=0$.
**De Morgan's laws** are much easier to express in boolean algebra, and denote distributing a negation by flipping the operator:
$$
(x\cdot y)'=x'+y' \\
(x+y)=x'\cdot y'
$$
Please see [ECE 108: Discrete Math 1#Operator laws](/1b/ece108/#operator-laws) for more information.
AND and OR are commutative.
- $x\cdot y=y\cdot x$
- $x+y=y+x$
AND and OR are associative.
- $x\cdot(y\cdot z)=(x\cdot y)\cdot z)$
- ...
AND and OR are distributive with each other.
- $x\cdot (y+z)=x\cdot y+z\cdot z$
A term that depends on another term ORed together can be "absorbed".
- $x+x\cdot y=x$
- $x\cdot(x+y)=x$
If a term being true also results in other ORed terms being true, it is redundant and can be eliminated via consensus.
- $x\cdot y+y\cdot z+x'\cdot z=x\cdot y+x'\cdot z$
- if y and z are true, at least one of the other two terms must be true
- $(x+y)\cdot (y+z)\cdot(x'+z)=(x+y)\cdot (x'+z)$
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.
??? example
Prove that $(x+y)\cdot(x+y')=x$:
\begin{align*}
\tag{distributive property}(x+y)\cdot(x+y')&=xx+xy'+yx+yy' \\
\tag{$yy'$ = 0, $xx=x$}&=x + xy' + yx \\
\tag{distributive, commutative properties}&= x(1+y'+y) \\
\tag{1 + ... = 1}&= x(1) \\
&=x
\end{align*}
Prove that $xy+yz+x'z=xy+x'z$:
\begin{align*}
\tag{$x+x'=1$}xy+yz+x'z&=xy+yz(x+x')+x'z \\
\tag{distributive property}&=xy+xyz+x'yz+x'z \\
\tag{distributive property}&=x(y+yz) + x'(yz+z) \\
\tag{distributive property}&=xy(1+z) + x'z(y+1) \\
\tag{$1+k=1$}&=xy(1) + x'z(1) \\
\tag{$1\cdot k=k$}&= xy+x'z
\end{align*}
### Minterms and maxterms
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)**
\begin{align*}
\sum m(1,2,3,4,5,6,7) &=001+011+111+010+110+100+000 \\
\tag{SIMD distribution}&=001+010+100 \\
&=x_1+x_2+x_3
\end{align*}
A **canonical sum of products (SOP)** is a function expressed as a sum of minterms.
$$f(x_1,x_2,\dots)=\sum m(a,b, \dots)$$
A **canonical product of sums (POS)** is a function expressed as a product of maxterms.
$$f(x_1,x_2,\dots)=\prod M(a,b,\dots)$$
## Transistors
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.
<img src="https://upload.wikimedia.org/wikipedia/commons/6/61/IGFET_N-Ch_Enh_Labelled_simplified.svg" width=200>(Source: Wikimedia Commons)</img>
A **negative logic** transistor uses a NOT bubble to represent that it is closed while the voltage is **below** a threshold.
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c4/IGFET_P-Ch_Enh_Labelled_simplified.svg" width=200>(Source: Wikimedia Commons)</img>
## Hardware
!!! definition
- A **programmable logic gate** does shit
- A **programmable logic array** does more shit
- **Programmable array logic** is the shit being done
### FPGAs
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
## Gray code
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.
### K-maps
Karnaugh maps are an alternate representation of truth tables arranged by the Gray code.
- Coordinates are the input values to the function
- The output square of the coordinates is the output value of the function
- Headers are sorted by Gray code (multiple variables can be combined by increasing the number of bits in the Gray code)
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.
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b7/K-map_6%2C8%2C9%2C10%2C11%2C12%2C13%2C14.svg" width=500>(Source: Wikimedia Commons)</img>
A K-map for five variables can be expressed in two maps for four variables — one with the fifth variable set to zero, and the other set to 1.
### Multiplexers
An $n$-input mux has $\lceil\log_2 n\rceil$ **select inputs** all in the same mux.
!!! example
A 4-1 multiplexer. $f=s_0's_1A+s_0's_1B+s_0s_1'C+s_0s_1D$
<img src="https://upload.wikimedia.org/wikipedia/commons/7/75/Multiplexer_4-to-1.svg" width=300>(Source: Wikimedia Commons)</img>
**Shannon's expansion theorem** states that any function can be turned into a function that purely uses multiplexers:
$$
\begin{align*}
f(w_1,\dots, w_n) &=w_1f_{w_1} + w_1'f_{w_1'} \\
&= w_1f(1, \dots, w_n) = w_1'f(0, \dots, w_n)
\end{align*}
$$
A **demultiplexer** has one input, $n$ select inputs, and up to $2^n$ outputs that carry the input signal depending on the select input.
<img src="https://upload.wikimedia.org/wikipedia/commons/4/48/Demultiplexer.png" width=400>(Source: Wikimedia Commons)</img>
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.
## Sequential circuits
!!! definition
- 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.
### Asynchronous latches
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.
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c6/R-S_mk2.gif" width=300>(Source: Wikimedia Commons)</img>
| $R$ | $S$ | $Q$ | $Q'$ |
| --- | --- | --- | --- |
| 0 | 0 | no change | no change |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 1 | 0 | 0 |
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.
<img src="https://upload.wikimedia.org/wikipedia/commons/e/e1/SR_%28Clocked%29_Flip-flop_Diagram.svg" width=400>(Source: Wikimedia Commons)</img>
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.
<img src="https://upload.wikimedia.org/wikipedia/commons/c/cb/D-type_Transparent_Latch_%28NOR%29.svg" width=400>(Source: Wikimedia Commons)</img>
### Flip-flops
**Edge-triggered flip-flops** only change state on the edge of a clock. A negative-edge D flip flop below changes only at the **falling edge** of the clock and is greated with two gated D latches in series. A positive-edge D flip flop can be created by inverting both enable inputs.
<img src="https://upload.wikimedia.org/wikipedia/commons/5/52/Negative-edge_triggered_master_slave_D_flip-flop.svg" width=500>(Source: Wikimedia Commons)</img>
The asynchronous operations **clear** and **preset** can be added to force the state of the flip-flop to 0 or 1, respectively. To make them synchronous, the input $D$ can be replaced with $D\text{ and clear}'$. These operations are **active low**.
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8c/D-Type_Flip-flop.svg" width=200>(Source: Wikimedia Commons</img>
A **T flip-flop** holds state if $T=0$ or **toggles** state if $T=1$.
<img src="https://upload.wikimedia.org/wikipedia/commons/a/a9/T-Type_Flip-flop.svg" width=200>(Source: Wikimedia Commons</img>
!!! example
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Dual-edge-triggered-flip-flop-XOR.png" width=500>(Source: Wikimedia Commons)</img>
A **JK flip-flop** acts as a **D flip-flop** if $J\neq K$ and as a **T flip-flop** if $J=K$.
<img src="https://upload.wikimedia.org/wikipedia/commons/3/37/JK_Flip-flop_%28Simple%29_Symbol.svg" width=200>(Source: Wikimedia Commons)</img>
### Timing analysis
Because flip-flop outputs only change on an active clock edge, there are **propagation delays** before the state changes completely.
- The **setup time** $t_{su}$ is the waiting time the input must be held stable **before** the active clock edge
- The **hold time** $t_h$ is the time the input must be held stable **after** the active clock edge
- The **clock-to-output time** $t_{cq}$ is the time required for the output to stabilise after the active clock edge
A **timing violation** occurs if these timing parameters are not met, which limits clock cycle frequency.
### Registers
!!! definition
- An **n-bit register** stores *n* bits.
A flip-flop is a one-bit register.
A **shift register** is a chain of redstone repeaters, consisting of a chain of flip-flops with each output connected to the next input.
<img src="https://upload.wikimedia.org/wikipedia/commons/4/45/4-Bit_SIPO_Shift_Register.svg" width=300>(Source: Wikimedia Commons)</img>
An **up-counter** increments its binary value on input. A **down-counter** decrements its value. It is **synchronous** if all bits update simultaneously.
### Counters
A **Johnson counter** overflows by connecting the complement of the final output to the first input.
A **ring counter** has exactly one output bit equal to one, looping when it reaches the end. It is equivalent to a loop of redstone repeaters, if redstone repeaters required input to switch to the next repeater.
## Synchronous sequential circuits
A **synchronous sequential circuit** or **state machine** is created with a combinational circuit and a flip-flop.
A **state diagram** is a directed graph with nodes and arcs. Each node represents a state while arcs represent changes in input/output to other states. A circuit with $n$ inputs has $2^n$ arcs.
!!! example
A state diagram for a turnstile.
<img src="https://upload.wikimedia.org/wikipedia/commons/9/9e/Turnstile_state_machine_colored.svg" width=300>(Source: Wikimedia Commons)</img>
A **state table** is a simplified state diagram.
!!! example
Where $A,B,C$ are states, and $w$ is the input, a Moore machine can be represented as:
| state | next state | | output |
| --- | --- | --- | --- |
| | $w=0$ | $w=1$ | |
| A | A | B | 0 |
| B | A | C | 0 |
| C | A | C | 1 |
To design a state circuit:
1. Create a state diagram, select starting state
2. Minimise the number of states
3. Decide the number of state variables
4. Choose flip-flop types and derive next state logic expressions to control flip-flops
5. Derive logic expressions
6. Implement the logic expressions
### Moore machine
A Moore machine changes state **only** on the positive edge of the clock. Its output is true only if the previous two inputs were true.
State variables are usually tracked with flip-flops. These can be done with flip-flops treated as binary indexes for each state or with **one hot state** such that one state is tracked with one flip-flop.
### Mealy machine
A Mealy machine changes state **asynchronously**. Its output is true only if the current and past inputs are true.
| state | $w=0$ | $w=1$ | output |
| --- | --- | --- | --- |
| A | A | B | 0 |
| B | A | B | 1 |
### Minimising state
An **equivalent state** is such that each input has the same output and an equivalent next state. Reducing the number of redundant equivalent states minimises the number of states needed.
1. Group states by outputs
2. For each state, if not all states transition to the same group, subgroup them such that they do
3. Repeat as necessary
## Asynchronous sequential circuits
ASCs hae no clocks, relying on feedback from outputs for their memory effect.
!!! warning
ASCs break down if any of these assumptions fail.
- Only one input is allowed to change at a time
- Inputs change only after the circuit stabilises
- There is no propagation delay, although it may be compensated for with a delay element for the output / feedback
### Analysis
1. Determine logic expressions for next state and output in terms of current state and input
2. Create transition and flow tables
3. Circle stable states (will lead to itself)
4. Replace bits with letters
5. Assign bit variables to avoid changing more than one input at a time (as it is undefined)
To create a circuit:
1. Create a state diagram
2. Flow table
3. Minimise state
4. Excitation table
5. Circuit
### Reducing state
1. Partition per [#Minimising state](#minimising-state)
- *don't cares* are no longer equivalent unless both states have them in the same columns
2. States are compatible if and only if, regardless of input:
- their output is the same
- their next state is the same, is stable, or are unspecified
3. Merger diagram, identifying conflicts/compatible pairs
4. Connect diagram, merging a subset (not all) of compatible states
- states can only be in at most one subset
5. Repeat
### Avoiding races
!!! definition
- **Non-critical races** result in the same stable end state.
- **Critical races** cause *problems*.
- A **hazard** is unwanted switching due to unequal propagation delays.
To avoid races: an $n$-dimensional cube with one vertex per state, ensuring that changes only move along one edge. If more states are needed to avoid this, they are automagically *unstable*.
Alternatively, if $n\leq 4$, a state $A$ can be split into equivalent states $A1, A2$.
1. Create a cube with $2n$ vertices
2. Pairs must be adjacent
3. Determine next states by following cube lines only
Alternatively, each state can be assigned exactly one `1` bit, and transitions from one to another have `1`s at the states they transition between.
### Hazards
**Static-1/0 hazards** occur when output should stay constant, but suddenly flickers to the other. These can be fixed by covering minterms adjacent but not connected with another gate as an extra check.
**Dynamic hazards** occur when outputs flip multiple times before stabilising. These can be avoided by switching everything to 2-term POS or SOP and fixing static hazards.
## Multilevel synthesis
!!! definition
- A **literal** is an input character.
- An **implicant** is a collection of inputs that results in a true output.
- A **prime implicant** is such that no literals can be removed while remaining an implicant.
- A **cover** is a set of implicants that cover every possible way $f=1$.
- An **essential prime implicant** is such that there is no other prime implicant that fulfill a necessary condition to make $f$ true.
TO reduce fan-in, multi-input ANDs and ORs can be broken up to multiple versions of their nested form via **factoring**.
$$abcde\to(abc)(de)$$
**Functional decomposition** takes common terms and only calculates them first before feeding that input into the rest of the circuit.
### Tabular method
Cost is minimised when all essential prime implicants are present and the fewest number of prime implicants for the remaining terms.
1. List minterms, group by the number of ones in binary (don't cares can be treated as minterms)
2. Write the implicant for each
3. For each group, if an implicant differs by one bit from an implicant in the group above, merge them (replacing the distinctive term with $x$) and check that minterm / implicant off
4. Repeat, ensuring that $x$ only merges with $x$ in the same columns
Implicants not checked off are prime implicants.
1. List all primes and the minterms they cover as a table, excluding don't cares
- Minterms with only one prime have that as an essential prime
2. Primes that cover the same minterms as another but also more are objectively better (**row dominance**)
3. Make educated guesses to minimise prime implicants
Alternatively, instead of removing **dominated rows**, **dominatING columns** can be removed instead.
### Petrick method
Once reduced to tablular form:
1. For each column, sum all the possible ways a minterm can be covered, then product those sums
2. Expand and simplify, then choose the products with the least number of literals
3. Each product is a solution if you replace the product with a sum of the multiplied literals instead
## VHDL
VHDL is a hardware schematic language.
<img src="https://static.javatpoint.com/tutorial/digital-electronics/images/multiplexer3.png" width=600 />
For example, the basic 2-to-1 multiplexer expressed above can be programmed as:
```vhdl
entity two_one_mux is
port (a0, s, a1 : in bit;
f : out bit);
end two_one_mux
architecture LogicFunc of two_one_mux is
begin
y <= (a0 AND s) OR (NOT s AND a1);
end LogicFunc;
```
In this case, the inputs are `a0, s, a1` that lead to an output `y`. All input/output is of type `bit` (a boolean).
The **architecture** defines how inputs translate to outputs via functions. These all run **concurrently**.