diff --git a/notebooks/FCLayer_graph.onnx b/notebooks/FCLayer_graph.onnx
index efefcd681bfda4d72fd9be9d15f5069c05184a37..641ef704256c0c7af863cafc79b3f6af57d0abd5 100644
Binary files a/notebooks/FCLayer_graph.onnx and b/notebooks/FCLayer_graph.onnx differ
diff --git a/notebooks/FINN-CodeGenerationAndCompilation.ipynb b/notebooks/FINN-CodeGenerationAndCompilation.ipynb
index 0183ce9a6d9aac7882fde6d53873712026f55720..f33d4baf724753edb2418a02b47f8bb9aac44af9 100644
--- a/notebooks/FINN-CodeGenerationAndCompilation.ipynb
+++ b/notebooks/FINN-CodeGenerationAndCompilation.ipynb
@@ -6,7 +6,21 @@
    "source": [
     "# FINN - Code Generation and Compilation\n",
     "-----------------------------------------------------------------\n",
-    "<font size=\"3\">This notebook is about code generation and compilation to enable execution of FINN custom operation nodes. </font>"
+    "<font size=\"3\">This notebook is about code generation and compilation to enable execution of FINN custom operation nodes. \n",
+    "\n",
+    "Following showSrc function is used to print the source code of function calls in the Jupyter notebook:</font>"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import inspect\n",
+    "\n",
+    "def showSrc(what):\n",
+    "    print(\"\".join(inspect.getsourcelines(what)[0]))"
    ]
   },
   {
@@ -15,7 +29,8 @@
    "source": [
     "## Outline\n",
     "-------------\n",
-    "* <font size=\"3\">Example model</font>\n"
+    "* <font size=\"3\">Example model</font>\n",
+    "* <font size=\"3\">Code generation</font>"
    ]
   },
   {
@@ -30,7 +45,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -49,7 +64,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": 14,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -72,7 +87,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -95,7 +110,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 16,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -129,7 +144,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -147,7 +162,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 18,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -170,7 +185,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 19,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -179,7 +194,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 20,
    "metadata": {},
    "outputs": [
     {
@@ -199,7 +214,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 21,
    "metadata": {},
    "outputs": [
     {
@@ -220,6 +235,104 @@
     "<iframe src=\"http://0.0.0.0:8081/\" style=\"position: relative; width: 100%;\" height=\"400\"></iframe>"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Code Generation\n",
+    "<font size=\"3\">Code generation is a transformation that can be applied to the model. For more information about transformation passes, see Jupyter Notebook *FINN-HowToTransformPass*.\n",
+    "\n",
+    "The code generation transformation is shown below.</font>"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "class CodeGen(Transformation):\n",
+      "    \"\"\"Code generation for all nodes in model\"\"\"\n",
+      "\n",
+      "    def apply(self, model):\n",
+      "        for node in model.graph.node:\n",
+      "            if node.domain == \"finn\":\n",
+      "                backend_attribute = get_by_name(node.attribute, \"backend\")\n",
+      "                backend_value = backend_attribute.s.decode(\"UTF-8\")\n",
+      "                if backend_value == \"fpgadataflow\":\n",
+      "                    _codegen_single_node(node, model)\n",
+      "        return (model, False)\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "from finn.transformation.fpgadataflow.codegen import CodeGen\n",
+    "showSrc(CodeGen)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "<font size=\"3\">The transformation passes iterates over all nodes in the model and if `domain=\"finn\"` and `backend=\"fpgadataflow\"` the function `_codegen_single_node()` is executed which is also part of the transformation pass and is shown below. </font>"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "def _codegen_single_node(node, model):\n",
+      "    \"\"\"Call custom implementation to generate code for single custom node\n",
+      "    and create folder that contains all the generated files\"\"\"\n",
+      "    op_type = node.op_type\n",
+      "    try:\n",
+      "        # lookup op_type in registry of CustomOps\n",
+      "        inst = registry.custom_op[op_type](node)\n",
+      "        # get the path of the code generation directory\n",
+      "        code_gen_dir = inst.get_nodeattr(\"code_gen_dir\")\n",
+      "        # ensure that there is a directory\n",
+      "        if code_gen_dir == \"\" or not os.path.isdir(code_gen_dir):\n",
+      "            code_gen_dir = tmp.mkdtemp(prefix=\"code_gen_\" + str(node.op_type) + \"_\")\n",
+      "            inst.set_nodeattr(\"code_gen_dir\", code_gen_dir)\n",
+      "        # ensure that there is generated code inside the dir\n",
+      "        inst.code_generation(model)\n",
+      "    except KeyError:\n",
+      "        # exception if op_type is not supported\n",
+      "        raise Exception(\"Custom op_type %s is currently not supported.\" % op_type)\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "from finn.transformation.fpgadataflow.codegen import _codegen_single_node\n",
+    "showSrc(_codegen_single_node)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "<font size=\"3\">An instance of the node is created and checked for the attribute `code_gen_dir`. If the attribute is not set, a temporary directory is created and the attribute is set accordingly. \n",
+    "\n",
+    "Then the `code_generation()` function of the instance is called. If an error occurs during this process, this is probably due to the fact that the selected CustomOp is not yet supported.</font>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "<font size=\"3\">The following description of the code generation within the CustomOp instance may lead to overlaps with the Jupyter notebook *FINN-CustomOps*. </font>"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": null,