{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Boolean logic"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sources\n",
"\n",
"* Hyde, Write Great Code, Volume 1: Understanding the Machine (2004), Chapter 3: Binary Arithmetic and Bit Operations\n",
"* Nisan and Schocken, *The Elements of Computing Systems: Building a Modern Computer from First Principles* (2008), Chapter 1: Boolean Logic\n",
"* Mims, *Workbook I: Basic Electronics, Transistors and Integrated Circuits*, second printing (2013)\n",
"* Mims, *Workbook II: Digital Logic Projects*, second printing (2013)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Boolean algebra"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Boolean expressions\n",
"\n",
"$ f(x, y, z) = (x + y) \\cdot \\overline{z} $\n",
"\n",
"`(x OR y) AND NOT z`\n",
"\n",
"### Canonical representation\n",
"\n",
"$ f(x, y, z) = \\overline{x}y\\overline{z} + x\\overline{y}\\overline{z} + xy\\overline{z} $\n",
"\n",
"`((NOT x) AND y AND (NOT z)) OR (x AND (NOT y) AND (NOT z)) OR (x AND y AND (NOT z))`\n",
"\n",
"### Truth table representation"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def print_truth_table(f, arr):\n",
" for row in arr:\n",
" print(row, f(*row))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Evaluate using bitwise operators:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 0, 0] 0\n",
"[0, 0, 1] 0\n",
"[0, 1, 0] 1\n",
"[0, 1, 1] 0\n",
"[1, 0, 0] 1\n",
"[1, 0, 1] 0\n",
"[1, 1, 0] 1\n",
"[1, 1, 1] 0\n"
]
}
],
"source": [
"def foo(x, y, z):\n",
" return (~x & y & ~z) | (x & ~y & ~z) | (x & y & ~z);\n",
"\n",
"vals = [ [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1],\n",
" [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1] ]\n",
"\n",
"print_truth_table(foo, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Logical operations on bits"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Four main logical operations are performed on bits:\n",
"\n",
"1. AND\n",
"2. OR\n",
"3. XOR (exclusive or)\n",
"4. NOT"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### AND truth table"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"| AND | 0 | 1 |\n",
"|-----|---|---|\n",
"| 0 | 0 | 0 |\n",
"| 1 | 0 | 1 |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### OR truth table"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"| OR | 0 | 1 |\n",
"|----|---|---|\n",
"| 0 | 0 | 1 |\n",
"| 1 | 1 | 1 |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### XOR truth table"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If the first or second value, but *not* both, is 1, the result is 1, otherwise the result is zero."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"| XOR | 0 | 1 |\n",
"|-----|---|---|\n",
"| 0 | 0 | 1 |\n",
"| 1 | 1 | 0 |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### NOT truth table"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"| NOT | 0 | 1 |\n",
"|-----|---|---|\n",
"| | 1 | 0 |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Bitwise (bit-by-bit) operations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Given two values, operate bitwise on bit zero of both operands, then bit one of both operands, and so on."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Bitwise logical AND of two 8-bit numbers:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```\n",
"10110101 // Operand 1\n",
"11101110 // Operand 2\n",
"10100100 // Result\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In Python:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'0b10100100'"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bin(0b10110101 & 0b11101110)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Uses for bitwise logical operations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Check an integer value to see if it is even or odd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If bit position zero of a binary integer value contains one, that integer is odd; if it contains zero, then that integer is even. Testing bit position zero:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def bitwise_is_odd(i):\n",
" return (i & 1) != 0"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bitwise_is_odd(1)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bitwise_is_odd(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## The `nand` gate\n",
"\n",
"$\\overline{x \\cdot y}$\n",
"\n",
"`NOT (x AND y)`\n",
"\n",
"### Truth table representation: direct\n",
"\n",
"`if a = b = 1 then out = 0 else out = 1`"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 0] 1\n",
"[0, 1] 1\n",
"[1, 0] 1\n",
"[1, 1] 0\n"
]
}
],
"source": [
"def _nand(a, b):\n",
" if a == b == 1:\n",
" return 0\n",
" else:\n",
" return 1\n",
"\n",
"vals = [ [0, 0], [0, 1], [1, 0], [1, 1] ]\n",
"print_truth_table(_nand, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic logic gates\n",
"\n",
"(See also https://en.wikipedia.org/wiki/NAND_logic)\n",
"\n",
"### Summary\n",
"\n",
"`Not` built with `Nand` (`_n_` prefix refers to `Nand`):\n",
"```py\n",
"def _n_not(a):\n",
" return _nand(a, a)\n",
"```\n",
"\n",
"`And` built with `Nand` and `Not`:\n",
"```py\n",
"def _n_and(a, b):\n",
" return _n_not(_nand(a, b))\n",
"```\n",
"\n",
"`Or` built with `Nand`, `Not`, and `And`:\n",
"```py\n",
"def _n_or(a, b):\n",
" return _n_not(_n_and(_nand(a, a), _nand(b, b)))\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Basic logic gates: `not`\n",
"\n",
"$\\overline{x}$\n",
"\n",
"`NOT (x)`\n",
"\n",
"Converts its input from 0 to 1 and from 1 to 0.\n",
"\n",
"#### Truth table representation: direct\n",
"\n",
"`if in = 0 then out = 1 else out = 0`"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0] 1\n",
"[1] 0\n"
]
}
],
"source": [
"def _not(a):\n",
" if a == 0:\n",
" return 1\n",
" else:\n",
" return 0\n",
"\n",
"vals = [ [0], [1] ]\n",
"print_truth_table(_not, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Truth table representation: Nand logic\n",
"\n",
"Joining the inputs of a Nand gate leaves only the NOT gate:\n",
"\n",
"`Not(a) = Nand(a, a)`"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0] 1\n",
"[1] 0\n"
]
}
],
"source": [
"def _n_not(a):\n",
" return _nand(a, a)\n",
"\n",
"vals = [ [0], [1] ]\n",
"print_truth_table(_n_not, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### In HDL (using built-in primitive `Nand` chip)\n",
"\n",
"```verilog\n",
"/**\n",
" * Not gate:\n",
" * out = not in\n",
" */\n",
"\n",
"CHIP Not {\n",
" IN in;\n",
" OUT out;\n",
"\n",
" PARTS:\n",
" \n",
" // Using built-in primitive Nand chip:\n",
" // Not(a) = Nand(a, a)\n",
" Nand(a = in, b = in, out = out);\n",
"}\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### Basic logic gates: `and`\n",
"\n",
"$ x \\cdot y $\n",
"\n",
"`x AND y`\n",
"\n",
"Returns 1 when both its inputs are 1, else 0.\n",
"\n",
"#### Truth table representation: direct\n",
"\n",
"`if a = b = 1 then out = 1 else out = 0`"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 0] 0\n",
"[0, 1] 0\n",
"[1, 0] 0\n",
"[1, 1] 1\n"
]
}
],
"source": [
"def _and(a, b):\n",
" if a == b == 1:\n",
" return 1\n",
" else:\n",
" return 0\n",
"\n",
"vals = [ [0, 0], [0, 1], [1, 0], [1, 1] ]\n",
"print_truth_table(_and, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Circuit representation\n",
"\n",
"Two switches connected in series. The LED will only be illuminated if both switches are closed."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%HTML\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Truth table representation: Nand logic\n",
"\n",
"`AND = NOT NAND`\n",
"\n",
"`And(a, b) = Not(Nand(a, b))`"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 0] 0\n",
"[0, 1] 0\n",
"[1, 0] 0\n",
"[1, 1] 1\n"
]
}
],
"source": [
"def _n_and(a, b):\n",
" return _n_not(_nand(a, b))\n",
"\n",
"vals = [ [0, 0], [0, 1], [1, 0], [1, 1] ]\n",
"print_truth_table(_n_and, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### In HDL\n",
"\n",
"```verilog\n",
"/**\n",
" * And gate:\n",
" * out = 1 if (a == 1 and b == 1)\n",
" * 0 otherwise\n",
" */\n",
"\n",
"CHIP And {\n",
" IN a, b;\n",
" OUT out;\n",
"\n",
" PARTS:\n",
"\n",
" // Using built-in primitive Nand chip\n",
" // and previously built Not chip:\n",
" // And(a, b) = Not(Nand(a, b))\n",
" Nand(a = a, b = b, out = c);\n",
" Not(in = c, out = out);\n",
"}\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Basic logic gates: `or`\n",
"\n",
"$ x + y $\n",
"\n",
"`x OR y`\n",
"\n",
"Returns 1 when at least one of its inputs is 1, and 0 otherwise.\n",
"\n",
"#### Truth table representation: direct\n",
"\n",
"`if a = b = 0 then out = 0 else out = 1`"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 0] 0\n",
"[0, 1] 1\n",
"[1, 0] 1\n",
"[1, 1] 1\n"
]
}
],
"source": [
"def _or(a, b):\n",
" if a == b == 0:\n",
" return 0\n",
" else:\n",
" return 1\n",
"\n",
"vals = [ [0, 0], [0, 1], [1, 0], [1, 1] ]\n",
"print_truth_table(_or, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Circuit representation\n",
"\n",
"Two switches connected in parallel. The LED will be illuminated if either switch is open."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%HTML\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Truth table representation: Nand logic\n",
"\n",
"`OR = NOT (NAND AND NAND)`\n",
"\n",
"`Or(a, b) = Not(And(Nand(a, a), Nand(b, b)))`"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 0] 0\n",
"[0, 1] 1\n",
"[1, 0] 1\n",
"[1, 1] 1\n"
]
}
],
"source": [
"def _n_or(a, b):\n",
" return _n_not(_n_and(_nand(a, a), _nand(b, b)))\n",
"\n",
"vals = [ [0, 0], [0, 1], [1, 0], [1, 1] ]\n",
"print_truth_table(_n_or, vals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### In HDL\n",
"\n",
"```verilog\n",
" /**\n",
" * Or gate:\n",
" * out = 1 if (a == 1 or b == 1)\n",
" * 0 otherwise\n",
" */\n",
"\n",
"CHIP Or {\n",
" IN a, b;\n",
" OUT out;\n",
"\n",
" PARTS:\n",
"\n",
" // Using built-in primitive Nand chip\n",
" // and previously built Not and And chips:\n",
" // Or(a, b) = Not(And(Nand(a, a), Nand(b, b)))\n",
" Nand(a = a, b = a, out = c);\n",
" Nand(a = b, b = b, out = d);\n",
" And(a = c, b = d, out = e);\n",
" Not(in = e, out = out);\n",
"}\n",
"\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Basic logic gates: `xor`\n",
"\n",
"WORKINGHERE"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.3"
},
"widgets": {
"state": {},
"version": "1.1.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}