diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,19 @@
 # Changelog for the Clash project
+## 1.4.7 *Jan 30th 2022*
+Fixed:
+  * Clash now shows days in time strings for compile runs which take longer than a day [#1989](https://github.com/clash-lang/clash-compiler/compare/issue-1989).
+  * Types defined in the package head are no longer qualified in the package body when rendering VHDL [#1996](https://github.com/clash-lang/clash-compiler/issues/1996).
+  * `asyncRam` with different read and write clocks no longer produce the wrong results in Haskell simulation. [#2031](https://github.com/clash-lang/clash-compiler/pull/2031)
+  * `Clash.Explicit.RAM.asyncRam#` Haskell simulation incorrectly treated an _undefined_ write enable as asserted. It now causes an _undefined_ value to be written instead. This problem did not propagate to the other `asyncRam` functions, where the same condition would simultaneously lead to an undefined write address, which would be handled correctly. This problem also only affects Haskell simulation, not the generated HDL. [#2031](https://github.com/clash-lang/clash-compiler/pull/2031)
+  * `Clash.Explicit.BlockRam.blockRam#` and `Clash.Explicit.BlockRam.File.blockRamFile#` Haskell simulation incorrectly treated an _undefined_ write enable as asserted. It now causes an _undefined_ value to be written instead. This problem did not propagate to the other `blockRam` functions, where the same condition would simultaneously lead to an undefined write address, which would be handled correctly. This problem also only affects Haskell simulation, not the generated HDL.([#2054](https://github.com/clash-lang/clash-compiler/pull/2054))
+
+Internal changes:
+  * Removed instances of `Hashable Term` and `Hashable Type` [#1986](https://github.com/clash-lang/clash-compiler/pull/1986)
+  * Added structural equality on `Term` (`Clash.Core.Subst.eqTerm`) and `Type` (`Clash.Core.Subst.eqType`)
+
+Internal fixes:
+  * Enable used to be a `Bool` in the Blackbox DSL, so we could use `boolToBit`. However it now has its own type in the DSL (`Enable domainName`), so we've added a new conversion function in order to convert it to a Bool.
+
 
 ## 1.4.6 *Oct 26th 2021*
 
diff --git a/clash-ghc.cabal b/clash-ghc.cabal
--- a/clash-ghc.cabal
+++ b/clash-ghc.cabal
@@ -1,6 +1,6 @@
 Cabal-version:        2.2
 Name:                 clash-ghc
-Version:              1.4.6
+Version:              1.4.7
 Synopsis:             Clash: a functional hardware description language - GHC frontend
 Description:
   Clash is a functional hardware description language that borrows both its
@@ -154,23 +154,23 @@
                       filepath                  >= 1.3      && < 1.5,
                       ghc                       >= 8.4.0    && < 9.1,
                       process                   >= 1.2      && < 1.7,
-                      hashable                  >= 1.1.2.3  && < 1.4,
+                      hashable                  >= 1.1.2.3  && < 1.5,
                       haskeline                 >= 0.7.0.3  && < 0.9,
                       lens                      >= 4.10     && < 5.1.0,
                       mtl                       >= 2.1.1    && < 2.3,
                       split                     >= 0.2.3    && < 0.3,
-                      text                      >= 1.2.2    && < 1.3,
+                      text                      >= 1.2.2    && < 2.1,
                       transformers              >= 0.5.2.0  && < 0.7,
                       unordered-containers      >= 0.2.1.0  && < 0.3,
 
-                      clash-lib                 == 1.4.6,
-                      clash-prelude             == 1.4.6,
+                      clash-lib                 == 1.4.7,
+                      clash-prelude             == 1.4.7,
                       concurrent-supply         >= 0.1.7    && < 0.2,
                       ghc-typelits-extra        >= 0.3.2    && < 0.5,
                       ghc-typelits-knownnat     >= 0.6      && < 0.8,
                       ghc-typelits-natnormalise >= 0.6      && < 0.8,
                       deepseq                   >= 1.3.0.2  && < 1.5,
-                      time                      >= 1.4.0.1  && < 1.13,
+                      time                      >= 1.4.0.1  && < 1.14,
                       ghc-boot                  >= 8.4.0    && < 9.1,
                       ghc-prim                  >= 0.3.1.0  && < 0.8,
                       ghci                      >= 8.4.0    && < 9.1,
@@ -184,7 +184,7 @@
     Build-Depends:    exceptions                >= 0.10.4   && < 0.11,
 
   if impl(ghc >= 9.0.0)
-    Build-Depends:    ghc-bignum                >= 1.0      && < 1.1
+    Build-Depends:    ghc-bignum                >= 1.0      && < 1.3
   else
     Build-Depends:    integer-gmp               >= 1.0.1.0  && < 2.0
 
diff --git a/src-ghc/Clash/GHC/GenerateBindings.hs b/src-ghc/Clash/GHC/GenerateBindings.hs
--- a/src-ghc/Clash/GHC/GenerateBindings.hs
+++ b/src-ghc/Clash/GHC/GenerateBindings.hs
@@ -234,11 +234,14 @@
                   ) bs
       case tms of
         [Binding v sp inl pr tm] -> return [(v, Binding v sp inl pr tm)]
+
+        -- Rewrite the bindings to avoid triggering the recursion check.
+        -- See NOTE [bindings in recursive groups]
         _ -> let vsL   = map (setIdScope LocalId . bindingId) tms
                  vsV   = map Var vsL
                  subst = extendGblSubstList (mkSubst emptyInScopeSet) (zip vsL vsV)
                  lbs   = zipWith (\b vL -> (vL,substTm "mkBindings" subst (bindingTerm b))) tms vsL
-                 tms1  = zipWith (\b (_, e) -> (bindingId b, b { bindingTerm = Letrec lbs e })) tms lbs
+                 tms1  = zipWith (\b (i, _) -> (bindingId b, b { bindingTerm = Letrec lbs (Var i) })) tms lbs
              in  return tms1
     ) bindings
   clsOpList    <- mapM (\(v,i) -> do
@@ -247,6 +250,33 @@
                        ) clsOps
 
   return (mkVarEnv (concat bindingsList), mkVarEnv clsOpList)
+
+{-
+NOTE [bindings in recursive groups]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+After normalization, Clash currently checks that all normalized entities are
+not recursive and errors if any are. However, this check only applies to
+recursion on global identifiers. Since GHC may present recursive groups of
+global binders, these are rewritten to only be locally recursive, i.e.
+
+  f[GlobalId] = g[GlobalId] ...
+  g[GlobalId] = f[GlobalId] ...
+
+will be rewritten (and inserted into the map of global bindings) as
+
+  f[GlobalId] = let f[LocalId] = g[LocalId] ...
+                    g[LocalId] = f[LocalId] ...
+                 in f[LocalId]
+
+  g[GlobalId] = let f[LocalId] = g[LocalId] ...
+                    g[LocalId] = f[LocalId] ...
+                 in g[LocalId]
+
+Recursive groups with only a single binding (i.e. global self-recursive
+definitions do not need this rewriting. This is because normalization can
+trivially spot these self-recursive bindings and where necessary lift them to
+global bindings when they appear in a term.
+-}
 
 -- | If this CoreBndr is a primitive, check it's Haskell definition
 --   for potential problems.
diff --git a/src-ghc/Clash/GHC/LoadModules.hs b/src-ghc/Clash/GHC/LoadModules.hs
--- a/src-ghc/Clash/GHC/LoadModules.hs
+++ b/src-ghc/Clash/GHC/LoadModules.hs
@@ -522,7 +522,7 @@
                   No top-level function called 'topEntity' or 'testBench' found,
                   nor any function annotated with a 'Synthesize' or 'TestBench'
                   annotation. If you want to synthesize a specific binder in
-                  #{show modName}, use '-main-is=myTopEntity'.
+                  #{show modName}, use '-main-is myTopEntity'.
                 |]
               _ ->
                 allImplicit
