diff --git a/klee-examples/Cargo.toml b/klee-examples/Cargo.toml
index 35110b04423ac6fb5038b1b331a06f65c2333ded..a9a1b2fea16b70125294315fd2d177100ca3be18 100644
--- a/klee-examples/Cargo.toml
+++ b/klee-examples/Cargo.toml
@@ -44,6 +44,10 @@ path = "src/register.rs"
 name = "peripheral"
 path = "src/peripheral.rs"
 
+[[bin]]
+name = "clk"
+path = "src/clk.rs"
+
 [profile.dev]
 incremental = false
 # lto = true
@@ -51,6 +55,7 @@ incremental = false
 [profile.release]
 debug = true
 panic = "abort"
+incremental = false
 lto = true
 
 [features]
diff --git a/klee-examples/src/clk.rs b/klee-examples/src/clk.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e17bff078433943cbe31d0a1bd659b04fdaf4dfe
--- /dev/null
+++ b/klee-examples/src/clk.rs
@@ -0,0 +1,103 @@
+#![no_std]
+#![no_main]
+
+#[macro_use]
+extern crate klee;
+extern crate panic_abort;
+
+use klee::{kassert, kassume, ksymbol};
+
+#[derive(Clone, Copy, Debug)]
+pub struct CFGR {
+    hse: Option<u32>,
+    hclk: Option<u32>,
+    pclk1: Option<u32>,
+    pclk2: Option<u32>,
+    sysclk: Option<u32>,
+    usbclk: bool,
+}
+
+pub struct Requirements {
+    pllsrcclk: u32,
+    sysclk: u32,
+    usbclk: bool,
+}
+
+pub struct Unknowns {
+    pllp: u32,
+    pllm: u32,
+    plln: u32,
+    pllq: u32,
+}
+
+fn pll_derive() -> Unknowns {
+    // pll input default to HSI
+
+    let pllsrcclk = 8_000_000;
+
+    // desired system clock, default to pll input
+    let sysclk = 96_000_000;
+
+    // Sysclk output divisor must be one of 2, 4, 6 or 8
+    // (&!1 implies even numbers)
+    let pllp = core::cmp::min(8, (432_000_000 / sysclk) & !1);
+
+    // Input divisor from PLL source clock, must result to frequency in
+    // the range from 1 to 2 MHz
+    let mut pllm: u32 = 0;
+    ksymbol!(&mut pllm, "pllm");
+    kassume(pllm > 0);
+
+    // require multiples of 1 MHz
+    kassume(1_000_000 <= pllsrcclk / pllm && pllsrcclk / pllm <= 2_000_000);
+    // only 4Mz..=26Mz allowed
+    kassume(4 <= pllm && pllm <= 26);
+
+    // Main scaler,
+    let plln = sysclk * pllp / (pllsrcclk / pllm);
+    assert!(50 <= plln && plln <= 432); // constraint according to data sheet
+
+    let osc = (pllsrcclk / pllm) * plln;
+    // 100MHz <= OSC <= 432MHz
+    kassume(100_000_000 <= osc && osc <= 432_000_000);
+
+    // 192MHz  <= OSC <= 432MHz // for F401
+    // kassume(192_000_000 <= osc && osc <= 432_000_000);
+
+    // compute USB clock
+    // 1-2MHz * plln / pllq = 48Mhz
+    let pllq = (pllsrcclk / pllm) * plln / 48_000_000;
+
+    // Calculate real system clock
+    let sysclk_real = (pllsrcclk / pllm) * plln / pllp;
+
+    kassume(sysclk_real == sysclk);
+
+    Unknowns {
+        pllp,
+        pllm,
+        plln,
+        pllq,
+    }
+}
+
+#[no_mangle]
+fn main() {
+    let mut pllp: u32 = 0;
+    // let mut pll_in: u32 = 0;
+    let mut pllm: u32 = 0;
+    let mut plln: u32 = 0;
+    let mut pllq: u32 = 0;
+    ksymbol!(&mut pllp, "pllp");
+    // ksymbol!(&mut pll_in, "pll_in");
+    ksymbol!(&mut pllm, "pllm");
+    ksymbol!(&mut plln, "plln");
+    ksymbol!(&mut pllq, "pllq");
+
+    let u = pll_derive();
+    kassume(pllp == u.pllp);
+    // kassume(pll_in == u.pll_in);
+    kassume(pllm == u.pllm);
+    kassume(plln == u.plln);
+    kassume(pllq == u.pllq);
+}