diff --git a/dev_tools/qualtran_dev_tools/notebook_specs.py b/dev_tools/qualtran_dev_tools/notebook_specs.py
index e5260b455..292f56869 100644
--- a/dev_tools/qualtran_dev_tools/notebook_specs.py
+++ b/dev_tools/qualtran_dev_tools/notebook_specs.py
@@ -120,6 +120,8 @@
 import qualtran.bloqs.rotations.phasing_via_cost_function
 import qualtran.bloqs.rotations.programmable_rotation_gate_array
 import qualtran.bloqs.rotations.quantum_variable_rotation
+import qualtran.bloqs.rotations.rz_via_phase_gradient
+import qualtran.bloqs.rotations.zpow_via_phase_gradient
 import qualtran.bloqs.state_preparation.black_box_prepare
 import qualtran.bloqs.state_preparation.prepare_base
 import qualtran.bloqs.state_preparation.prepare_uniform_superposition
@@ -636,6 +638,18 @@
             qualtran.bloqs.rotations.hamming_weight_phasing._HAMMING_WEIGHT_PHASING_VIA_PHASE_GRADIENT_DOC,
         ],
     ),
+    NotebookSpecV2(
+        title='ZPow Rotation via Phase Gradient',
+        module=qualtran.bloqs.rotations.zpow_via_phase_gradient,
+        bloq_specs=[
+            qualtran.bloqs.rotations.zpow_via_phase_gradient._ZPOW_CONST_VIA_PHASE_GRADIENT_DOC
+        ],
+    ),
+    NotebookSpecV2(
+        title='Rz Rotation via Phase Gradient',
+        module=qualtran.bloqs.rotations.rz_via_phase_gradient,
+        bloq_specs=[qualtran.bloqs.rotations.rz_via_phase_gradient._RZ_VIA_PHASE_GRADIENT_DOC],
+    ),
     NotebookSpecV2(
         title='Programmable Rotation Gate Array',
         module=qualtran.bloqs.rotations.programmable_rotation_gate_array,
diff --git a/docs/bloqs/index.rst b/docs/bloqs/index.rst
index d827dfaad..3ed5dfe35 100644
--- a/docs/bloqs/index.rst
+++ b/docs/bloqs/index.rst
@@ -108,6 +108,8 @@ Bloqs Library
     rotations/phasing_via_cost_function.ipynb
     rotations/phase_gradient.ipynb
     rotations/hamming_weight_phasing.ipynb
+    rotations/zpow_via_phase_gradient.ipynb
+    rotations/rz_via_phase_gradient.ipynb
     rotations/programmable_rotation_gate_array.ipynb
     qft/two_bit_ffft.ipynb
     qft/approximate_qft.ipynb
diff --git a/qualtran/bloqs/rotations/__init__.py b/qualtran/bloqs/rotations/__init__.py
index 48c79d877..e6c63bdf4 100644
--- a/qualtran/bloqs/rotations/__init__.py
+++ b/qualtran/bloqs/rotations/__init__.py
@@ -24,3 +24,5 @@
 from qualtran.bloqs.rotations.phasing_via_cost_function import PhasingViaCostFunction
 from qualtran.bloqs.rotations.programmable_rotation_gate_array import ProgrammableRotationGateArray
 from qualtran.bloqs.rotations.quantum_variable_rotation import QvrPhaseGradient, QvrZPow
+from qualtran.bloqs.rotations.rz_via_phase_gradient import RzViaPhaseGradient
+from qualtran.bloqs.rotations.zpow_via_phase_gradient import ZPowConstViaPhaseGradient
diff --git a/qualtran/bloqs/rotations/rz_via_phase_gradient.ipynb b/qualtran/bloqs/rotations/rz_via_phase_gradient.ipynb
new file mode 100644
index 000000000..75e37a757
--- /dev/null
+++ b/qualtran/bloqs/rotations/rz_via_phase_gradient.ipynb
@@ -0,0 +1,168 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "bbc3afcf",
+   "metadata": {
+    "cq.autogen": "title_cell"
+   },
+   "source": [
+    "# Rz Rotation via Phase Gradient"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e6ca3000",
+   "metadata": {
+    "cq.autogen": "top_imports"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register\n",
+    "from qualtran import QBit, QInt, QUInt, QAny\n",
+    "from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n",
+    "from typing import *\n",
+    "import numpy as np\n",
+    "import sympy\n",
+    "import cirq"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4d0db53e",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.bloq_doc.md"
+   },
+   "source": [
+    "## `RzViaPhaseGradient`\n",
+    "Apply a controlled-Rz using a phase gradient state.\n",
+    "\n",
+    "Implements the following unitary action:\n",
+    "\n",
+    "$$\n",
+    "    |\\psi\\rangle \\otimes |x\\rangle \\mapsto \\text{Rz}(4 \\pi x) |\\psi\\rangle \\otimes |x\\rangle\n",
+    "$$\n",
+    "\n",
+    "for every state $|\\psi\\rangle$ and every $x$, or equivalently\n",
+    "\n",
+    "$$\n",
+    "    |b\\rangle|x\\rangle \\mapsto |b\\rangle e^{- (-1)^b i x/2} |x\\rangle\n",
+    "$$\n",
+    "\n",
+    "for every $b \\in \\{0, 1\\}$ and every $x$.\n",
+    "\n",
+    "To apply an $\\text{Rz}(\\theta) = e^{-i Z \\theta/2}$, the angle register $x$ should store $\\theta/(4\\pi)$.\n",
+    "\n",
+    "#### Parameters\n",
+    " - `angle_dtype`: Data type for the `angle_data` register.\n",
+    " - `phasegrad_dtype`: Data type for the phase gradient register. \n",
+    "\n",
+    "#### Registers\n",
+    " - `q`: The qubit to apply Rz on.\n",
+    " - `angle`: The rotation angle in radians.\n",
+    " - `phase_grad`: The phase gradient register of sufficient width. \n",
+    "\n",
+    "#### References\n",
+    " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). Section II-C: Oracles for phasing by cost function. Appendix A: Addition for controlled rotations.\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "88ae8ba0",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.bloq_doc.py"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran.bloqs.rotations import RzViaPhaseGradient"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f3d5ab59",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.example_instances.md"
+   },
+   "source": [
+    "### Example Instances"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "16a874c9",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.rz_via_phase_gradient"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran import QFxp\n",
+    "\n",
+    "rz_via_phase_gradient = RzViaPhaseGradient(angle_dtype=QFxp(4, 4), phasegrad_dtype=QFxp(4, 4))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ca4ac4bc",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.graphical_signature.md"
+   },
+   "source": [
+    "#### Graphical Signature"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "92d7b03c",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.graphical_signature.py"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran.drawing import show_bloqs\n",
+    "show_bloqs([rz_via_phase_gradient],\n",
+    "           ['`rz_via_phase_gradient`'])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "03999011",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.call_graph.md"
+   },
+   "source": [
+    "### Call Graph"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d0cc79d3",
+   "metadata": {
+    "cq.autogen": "RzViaPhaseGradient.call_graph.py"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran.resource_counting.generalizers import ignore_split_join\n",
+    "rz_via_phase_gradient_g, rz_via_phase_gradient_sigma = rz_via_phase_gradient.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
+    "show_call_graph(rz_via_phase_gradient_g)\n",
+    "show_counts_sigma(rz_via_phase_gradient_sigma)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "name": "python"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/qualtran/bloqs/rotations/rz_via_phase_gradient.py b/qualtran/bloqs/rotations/rz_via_phase_gradient.py
index 00e71e2ee..d3ec380d2 100644
--- a/qualtran/bloqs/rotations/rz_via_phase_gradient.py
+++ b/qualtran/bloqs/rotations/rz_via_phase_gradient.py
@@ -17,6 +17,7 @@
     Bloq,
     bloq_example,
     BloqBuilder,
+    BloqDocSpec,
     QBit,
     QDType,
     QUInt,
@@ -109,3 +110,8 @@ def _rz_via_phase_gradient() -> RzViaPhaseGradient:
 
     rz_via_phase_gradient = RzViaPhaseGradient(angle_dtype=QFxp(4, 4), phasegrad_dtype=QFxp(4, 4))
     return rz_via_phase_gradient
+
+
+_RZ_VIA_PHASE_GRADIENT_DOC = BloqDocSpec(
+    bloq_cls=RzViaPhaseGradient, examples=[_rz_via_phase_gradient]
+)
diff --git a/qualtran/bloqs/rotations/rz_via_phase_gradient_test.py b/qualtran/bloqs/rotations/rz_via_phase_gradient_test.py
index 110583b25..4fb5e7987 100644
--- a/qualtran/bloqs/rotations/rz_via_phase_gradient_test.py
+++ b/qualtran/bloqs/rotations/rz_via_phase_gradient_test.py
@@ -16,6 +16,7 @@
 import sympy
 from attrs import frozen
 
+import qualtran.testing as qlt_testing
 from qualtran import Bloq, BloqBuilder, QBit, QFxp, QUInt, Signature, Soquet, SoquetT
 from qualtran.bloqs.basic_gates import IntState, Rz
 from qualtran.bloqs.rotations.phase_gradient import PhaseGradientState
@@ -87,3 +88,8 @@ def test_tensor(bitsize: int):
         expected = Rz(theta).tensor_contract()
 
         np.testing.assert_allclose(actual, expected, atol=1 / 2**bitsize)
+
+
+@pytest.mark.notebook
+def test_notebook():
+    qlt_testing.execute_notebook('rz_via_phase_gradient')
diff --git a/qualtran/bloqs/rotations/zpow_via_phase_gradient.ipynb b/qualtran/bloqs/rotations/zpow_via_phase_gradient.ipynb
new file mode 100644
index 000000000..fda19c320
--- /dev/null
+++ b/qualtran/bloqs/rotations/zpow_via_phase_gradient.ipynb
@@ -0,0 +1,188 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "7e96cff5",
+   "metadata": {
+    "cq.autogen": "title_cell"
+   },
+   "source": [
+    "# ZPow Rotation via Phase Gradient"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "197bfd0b",
+   "metadata": {
+    "cq.autogen": "top_imports"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register\n",
+    "from qualtran import QBit, QInt, QUInt, QAny\n",
+    "from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n",
+    "from typing import *\n",
+    "import numpy as np\n",
+    "import sympy\n",
+    "import cirq"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a1b0782f",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.bloq_doc.md"
+   },
+   "source": [
+    "## `ZPowConstViaPhaseGradient`\n",
+    "Apply an $Z**t$ on a qubit using a phase gradient state.\n",
+    "\n",
+    "This bloq implements a `Z**t` by conditionally loading `t/2` into a quantum\n",
+    "register, conditioned on the qubit `q` (rotation target), and then adding\n",
+    "this value to the phase gradient to get a phase kickback, and uncomputes the load.\n",
+    "This controlled-load trick is taken from Ref. [2], Fig 2a.\n",
+    "\n",
+    "See :class:`PhaseGradientState` for details on phase gradients.\n",
+    "\n",
+    "It loads an approximation of `t/2` to `phase_grad_bitsize` bits,\n",
+    "which is loaded using `phase_grad_bitsize` clean ancilla.\n",
+    "\n",
+    "The total Tofolli cost is `phase_grad_bitsize - 2`.\n",
+    "\n",
+    "\n",
+    "#### Parameters\n",
+    " - `exponent`: value of `t` to apply `Z**t`\n",
+    " - `phase_grad_bitsize`: number of qubits of the phase gradient state. \n",
+    "\n",
+    "#### Registers\n",
+    " - `q`: qubit to apply rotation on.\n",
+    " - `phase_grad`: phase gradient state of type `QFxp` with `phase_grad_bitsize` fractional bits. \n",
+    "\n",
+    "#### References\n",
+    " - [Improved quantum circuits for elliptic curve discrete logarithms](https://arxiv.org/abs/2001.09580). Haner et al. 2020. Section 3: Components. \"Integer addition\" and Fig 2a.\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d9111c04",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.bloq_doc.py"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran.bloqs.rotations import ZPowConstViaPhaseGradient"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b09c61b5",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.example_instances.md"
+   },
+   "source": [
+    "### Example Instances"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ab048833",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.zpow_const_via_phase_grad"
+   },
+   "outputs": [],
+   "source": [
+    "zpow_const_via_phase_grad = ZPowConstViaPhaseGradient.from_precision(3 / 8, eps=1e-11)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "f61b0a60",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.zpow_const_via_phase_grad_symb_prec"
+   },
+   "outputs": [],
+   "source": [
+    "eps = sympy.symbols(\"eps\")\n",
+    "zpow_const_via_phase_grad_symb_prec = ZPowConstViaPhaseGradient.from_precision(3 / 8, eps=eps)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "66d60de6",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.zpow_const_via_phase_grad_symb_angle"
+   },
+   "outputs": [],
+   "source": [
+    "t = sympy.symbols(\"t\")\n",
+    "zpow_const_via_phase_grad_symb_angle = ZPowConstViaPhaseGradient.from_precision(t, eps=1e-11)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9b31feb6",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.graphical_signature.md"
+   },
+   "source": [
+    "#### Graphical Signature"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "faa5dba0",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.graphical_signature.py"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran.drawing import show_bloqs\n",
+    "show_bloqs([zpow_const_via_phase_grad, zpow_const_via_phase_grad_symb_prec, zpow_const_via_phase_grad_symb_angle],\n",
+    "           ['`zpow_const_via_phase_grad`', '`zpow_const_via_phase_grad_symb_prec`', '`zpow_const_via_phase_grad_symb_angle`'])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "91234700",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.call_graph.md"
+   },
+   "source": [
+    "### Call Graph"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "93ec7137",
+   "metadata": {
+    "cq.autogen": "ZPowConstViaPhaseGradient.call_graph.py"
+   },
+   "outputs": [],
+   "source": [
+    "from qualtran.resource_counting.generalizers import ignore_split_join\n",
+    "zpow_const_via_phase_grad_g, zpow_const_via_phase_grad_sigma = zpow_const_via_phase_grad.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
+    "show_call_graph(zpow_const_via_phase_grad_g)\n",
+    "show_counts_sigma(zpow_const_via_phase_grad_sigma)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "name": "python"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/qualtran/bloqs/rotations/zpow_via_phase_gradient.py b/qualtran/bloqs/rotations/zpow_via_phase_gradient.py
index c1b5ff1d2..b7d7d605d 100644
--- a/qualtran/bloqs/rotations/zpow_via_phase_gradient.py
+++ b/qualtran/bloqs/rotations/zpow_via_phase_gradient.py
@@ -21,6 +21,7 @@
     Bloq,
     bloq_example,
     BloqBuilder,
+    BloqDocSpec,
     DecomposeTypeError,
     QBit,
     QFxp,
@@ -142,13 +143,23 @@ def _zpow_const_via_phase_grad() -> ZPowConstViaPhaseGradient:
 
 @bloq_example(generalizer=ignore_alloc_free)
 def _zpow_const_via_phase_grad_symb_prec() -> ZPowConstViaPhaseGradient:
-    eps = sympy.symbols(r"\epsilon")
+    eps = sympy.symbols("eps")
     zpow_const_via_phase_grad_symb_prec = ZPowConstViaPhaseGradient.from_precision(3 / 8, eps=eps)
     return zpow_const_via_phase_grad_symb_prec
 
 
 @bloq_example(generalizer=ignore_alloc_free)
 def _zpow_const_via_phase_grad_symb_angle() -> ZPowConstViaPhaseGradient:
-    t = sympy.symbols(r"t")
+    t = sympy.symbols("t")
     zpow_const_via_phase_grad_symb_angle = ZPowConstViaPhaseGradient.from_precision(t, eps=1e-11)
     return zpow_const_via_phase_grad_symb_angle
+
+
+_ZPOW_CONST_VIA_PHASE_GRADIENT_DOC = BloqDocSpec(
+    bloq_cls=ZPowConstViaPhaseGradient,
+    examples=[
+        _zpow_const_via_phase_grad,
+        _zpow_const_via_phase_grad_symb_prec,
+        _zpow_const_via_phase_grad_symb_angle,
+    ],
+)
diff --git a/qualtran/bloqs/rotations/zpow_via_phase_gradient_test.py b/qualtran/bloqs/rotations/zpow_via_phase_gradient_test.py
index 10d5cec75..17fa1e59b 100644
--- a/qualtran/bloqs/rotations/zpow_via_phase_gradient_test.py
+++ b/qualtran/bloqs/rotations/zpow_via_phase_gradient_test.py
@@ -14,6 +14,7 @@
 import pytest
 from attrs import frozen
 
+import qualtran.testing as qlt_testing
 from qualtran import Bloq, BloqBuilder, Signature, Soquet, SoquetT
 from qualtran.bloqs.basic_gates import ZPowGate
 from qualtran.bloqs.rotations.phase_gradient import PhaseGradientState
@@ -36,9 +37,6 @@
     ],
 )
 def test_examples(bloq_autotester, bloq):
-    if bloq_autotester.check_name == 'serialize':
-        pytest.skip()
-
     bloq_autotester(bloq)
 
 
@@ -95,3 +93,8 @@ def test_unitary(exponent: float, phase_grad_bitsize: int):
     actual = bloq.tensor_contract()
     expected = ZPowGate(exponent).tensor_contract()
     assert_unitaries_equivalent_upto_global_phase(actual, expected, atol=2**-phase_grad_bitsize)
+
+
+@pytest.mark.notebook
+def test_notebook():
+    qlt_testing.execute_notebook('zpow_via_phase_gradient')
diff --git a/qualtran/serialization/resolver_dict.py b/qualtran/serialization/resolver_dict.py
index cd01026fb..d81f9030a 100644
--- a/qualtran/serialization/resolver_dict.py
+++ b/qualtran/serialization/resolver_dict.py
@@ -147,6 +147,7 @@
 import qualtran.bloqs.rotations.programmable_rotation_gate_array
 import qualtran.bloqs.rotations.quantum_variable_rotation
 import qualtran.bloqs.rotations.rz_via_phase_gradient
+import qualtran.bloqs.rotations.zpow_via_phase_gradient
 import qualtran.bloqs.state_preparation.black_box_prepare
 import qualtran.bloqs.state_preparation.prepare_base
 import qualtran.bloqs.state_preparation.prepare_uniform_superposition
@@ -427,6 +428,7 @@
     "qualtran.bloqs.rotations.quantum_variable_rotation.QvrPhaseGradient": qualtran.bloqs.rotations.quantum_variable_rotation.QvrPhaseGradient,
     "qualtran.bloqs.rotations.quantum_variable_rotation.QvrZPow": qualtran.bloqs.rotations.quantum_variable_rotation.QvrZPow,
     "qualtran.bloqs.rotations.rz_via_phase_gradient.RzViaPhaseGradient": qualtran.bloqs.rotations.rz_via_phase_gradient.RzViaPhaseGradient,
+    "qualtran.bloqs.rotations.zpow_via_phase_gradient.ZPowConstViaPhaseGradient": qualtran.bloqs.rotations.zpow_via_phase_gradient.ZPowConstViaPhaseGradient,
     "qualtran.bloqs.state_preparation.prepare_uniform_superposition.PrepareUniformSuperposition": qualtran.bloqs.state_preparation.prepare_uniform_superposition.PrepareUniformSuperposition,
     "qualtran.bloqs.state_preparation.black_box_prepare.BlackBoxPrepare": qualtran.bloqs.state_preparation.black_box_prepare.BlackBoxPrepare,
     "qualtran.bloqs.state_preparation.prepare_base.PrepareOracle": qualtran.bloqs.state_preparation.prepare_base.PrepareOracle,