diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,47 @@
 # Changelog for the Clash project
 
+## 1.8.3 *Oct 6th 2025*
+
+Added:
+* `Counter` instances for `Bool`, `Bit`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Word`, `Word8`, `Word16`, `Word32`, `Word64`, `Identity` and `Maybe`. [#2692](https://github.com/clash-lang/clash-compiler/pull/2692)
+* The Vec type now has a [COMPLETE pragma](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/pragmas.html#complete-pragma) to avoid incomplete pattern matches when using the `(:>)` pattern. [#3020](https://github.com/clash-lang/clash-compiler/pull/3020)
+* RamOp now has an AutoReg instance. [#2792](https://github.com/clash-lang/clash-compiler/pull/2792)
+* Added instance `NFDataX (SimOnly a)` [#2900](https://github.com/clash-lang/clash-compiler/pull/2900)
+* Support for GHC 9.10 on Windows (macOS and Linux were already supported) [#2945](https://github.com/clash-lang/clash-compiler/pull/2945)
+* Added a `BitPack` instance for `Char` [#2957](https://github.com/clash-lang/clash-compiler/pull/2957)
+* Support for GHC 9.10.2 [#3003](https://github.com/clash-lang/clash-compiler/pull/3003)
+
+Changed:
+* Functions defined on `Clash.Class.Counter` are now public [#2692](https://github.com/clash-lang/clash-compiler/pull/2692)
+
+Fixed:
+* Clash hanging when rendering `Index n` literals, for large values of `n` [#2813](https://github.com/clash-lang/clash-compiler/issues/2813)
+* Render overflowed Index literals as don't-cares in HDL [#2970](https://github.com/clash-lang/clash-compiler/pull/2970)
+* Clash errors out when `Clash.Sized.Vector.splitAt` is compile-time evaluated in an illegal context [#2831]https://github.com/clash-lang/clash-compiler/issues/2831
+* `Clash.Explicit.DDR`: [#2911](https://github.com/clash-lang/clash-compiler/pull/2911)
+  - `ddrIn`: VHDL: Remove data input from sensitivity list of `ddrIn_neg_latch` register as it is superfluous. This should not affect functionality.
+  - `ddrOut`: VHDL: Fix incorrect usage of `Enable` input when the domain is set to asynchronous resets. Deasserting the `Enable` exhibited wrong behavior before this fix.
+* `Clash.Xilinx.DDR`: [#2911](https://github.com/clash-lang/clash-compiler/pull/2911)
+  - These primitives only support clocks where the rising edge is the active edge. Using them in a domain with falling active edges now causes an error.
+  - `oddr`: Fix VHDL and SystemVerilog erroring out during HDL generation
+  - Symbols in HDL for both `iddr` and `oddr` were renamed to match their function.
+* `Clash.Intel.DDR`: [#2911](https://github.com/clash-lang/clash-compiler/pull/2911)
+  - These primitives only support clocks where the rising edge is the active edge. Using them in a domain with falling active edges now causes an error.
+  - Fix rendering HDL. It variously errored out or generated non-working HDL.
+  - Rendering HDL no longer causes Clash to issue a warning about an argument unused in Haskell but used in the primitive black box.
+* `makeTopEntity` now accounts for `SimOnly` constructs. This can prevent warnings in situtations where the `SimOnly` type would contain types `makeTopEntity` cannot handle. [#2897](https://github.com/clash-lang/clash-compiler/pull/2897)
+* Clash did not build on GHC 9.6.7 (but did on 9.6.6) [#2916](https://github.com/clash-lang/clash-compiler/issues/2916)
+* Ignore `Tick`s in `TermLiteral Integer`, `TermLiteral Char`, `TermLiteral Natural`, and `TermLiteral (SNat n)` [#2925](https://github.com/clash-lang/clash-compiler/pull/2925)
+* Fixed laziness issue in internal black box `imap_go` [#2542](https://github.com/clash-lang/clash-compiler/issues/2542)
+* Clash's evaluator now uses `TemplateHaskell` names to detect renamed symbols in `GHC.*` and `Clash.*`. Fixes errors similar to `No blackbox found for: GHC.Internal.Base.eqString` [#2972](https://github.com/clash-lang/clash-compiler/issues/2972)
+* No blackbox found for: `GHC.Internal.Control.Exception.Base.recSelError` on GHC 9.10 [#2966](https://github.com/clash-lang/clash-compiler/issues/2966)
+* Verilog and System Verilog code gen bug for `map head` [#2809](https://github.com/clash-lang/clash-compiler/issues/2809)
+* Error parsing blackbox: `Clash.Sized.Vector.head` [#2988](https://github.com/clash-lang/clash-compiler/issues/2988)
+* Clash no longer duplicates included datafiles when component is instantiated multiple times [#3008](https://github.com/clash-lang/clash-compiler/issues/3008)
+* Clash will no longer emit "no blackbox found for" `GHC.Real`'s exponentiation function if it is applied to constants [#3010](https://github.com/clash-lang/clash-compiler/pull/3010)
+* Clash will no longer error out when converting `ensureSpine` on Clash number types to HDL [#3021](https://github.com/clash-lang/clash-compiler/issues/3021)
+* Clash will no longer ignore Synthesize annotations when the function is used in an argument position [#3024](https://github.com/clash-lang/clash-compiler/issues/3024)
+
 ## 1.8.2 *Jan 3rd 2025*
 
 Added:
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
 
 [![Pipeline status](https://gitlab.com/clash-lang/clash-compiler/badges/master/pipeline.svg)](https://gitlab.com/clash-lang/clash-compiler/commits/master)
 [![Hackage](https://img.shields.io/hackage/v/clash-prelude.svg)](https://hackage.haskell.org/package/clash-prelude)
-[![Hackage Dependencies](https://img.shields.io/hackage-deps/v/clash-prelude.svg?style=flat)](http://packdeps.haskellers.com/feed?needle=exact%3Aclash-prelude)
 
 Clash is a functional hardware description language that borrows both
 its syntax and semantics from the functional programming language
@@ -25,7 +24,13 @@
 
   * Support for multiple clock domains, with type safe clock domain crossing.
 
-# Support
-For updates and questions join the mailing list
-clash-language+subscribe@googlegroups.com or read the
-[forum](https://groups.google.com/d/forum/clash-language)
+# Open-source community
+Clash benefits from an active community. Whether you need a question answered or
+want to contribute to open-source features, browse the features below to make
+the most of Clash.
+
+- [Discourse: long form discussions and questions](https://clash-lang.discourse.group/)
+- [Discord: short form discussions and community chat room](https://discord.gg/rebGq25FB4)
+- [Slack: short form discussions and questions](https://functionalprogramming.slack.com/archives/CPGMJFF50)
+  (Invite yourself at [fpslack.com](https://fpslack.com))
+- [Github: issue tracker](https://github.com/clash-lang/clash-compiler/issues)
diff --git a/clash-prelude.cabal b/clash-prelude.cabal
--- a/clash-prelude.cabal
+++ b/clash-prelude.cabal
@@ -1,6 +1,6 @@
 Cabal-version:        2.2
 Name:                 clash-prelude
-Version:              1.8.2
+Version:              1.8.3
 Synopsis:             Clash: a functional hardware description language - Prelude library
 Description:
   Clash is a functional hardware description language that borrows both its
@@ -51,7 +51,7 @@
 Copyright:            Copyright © 2013-2016, University of Twente,
                                   2016-2017, Myrtle Software Ltd,
                                   2017-2019, QBayLogic B.V., Google Inc.,
-                                  2021-2023, QBayLogic B.V.
+                                  2021-2025, QBayLogic B.V.
 Category:             Hardware
 Build-type:           Simple
 
@@ -340,10 +340,10 @@
                       constraints               >= 0.9     && < 1.0,
                       containers                >= 0.4.0   && < 0.8,
                       data-binary-ieee754       >= 0.4.4   && < 0.6,
-                      data-default-class        >= 0.1.2   && < 0.2,
+                      data-default-class        >= 0.1.2   && < 0.3,
                       deepseq                   >= 1.4.1.0 && < 1.6,
-                      extra                     >= 1.6.17  && < 1.8,
-                      ghc-prim                  >= 0.5.1.0 && < 0.12,
+                      extra                     >= 1.6.17  && < 1.9,
+                      ghc-prim                  >= 0.5.1.0 && < 0.13,
                       ghc-typelits-extra        >= 0.4     && < 0.5,
                       ghc-typelits-knownnat     >= 0.7.2   && < 0.8,
                       ghc-typelits-natnormalise >= 0.7.2   && < 0.8,
@@ -422,7 +422,7 @@
       base,
       bytestring,
       deepseq,
-      hedgehog      >= 1.0.3    && < 1.5,
+      hedgehog      >= 1.0.3    && < 1.6,
       hint          >= 0.7      && < 0.10,
       quickcheck-classes-base >= 0.6 && < 1.0,
       tasty         >= 1.2      && < 1.6,
diff --git a/src/Clash/Annotations/TH.hs b/src/Clash/Annotations/TH.hs
--- a/src/Clash/Annotations/TH.hs
+++ b/src/Clash/Annotations/TH.hs
@@ -90,6 +90,7 @@
 import           Clash.Annotations.TopEntity    ( PortName(..)
                                                 , TopEntity(..)
                                                 )
+import           Clash.Magic                    (SimOnly)
 import           Clash.NamedTypes               ((:::))
 import           Clash.Signal                   ( HiddenClockResetEnable
                                                 , HiddenClock, HiddenReset, HiddenEnable
@@ -225,6 +226,7 @@
   constructors <- tryReifyDatatype [] datatypeCons name
 
   names <- case constructors of
+    _ | name == ''SimOnly -> return $ Complete []
     []  -> return $ Complete []
     [x] -> portsFromTypes (constructorFields x)
     xs  -> handleNamesInSum xs
@@ -283,6 +285,8 @@
 typeTreeToPorts f@(AppTF (a,a') (b,b')) = do
   -- Gather types applied to a head type
   case unapp (AppT a b) of
+    -- Skip SimOnly constructs - they're always zero bits
+    (ConT x : _) | x == ''SimOnly -> pure (Complete [])
     -- Return the inner type for signals
     (ConT x : _ : _ : []) | x == ''Clash.Signal.Signal -> b'
     (ConT x : _ : _ : _ : []) | x == ''Clash.Signal.Delayed.DSignal -> b'
diff --git a/src/Clash/Class/BitPack/Internal.hs b/src/Clash/Class/BitPack/Internal.hs
--- a/src/Clash/Class/BitPack/Internal.hs
+++ b/src/Clash/Class/BitPack/Internal.hs
@@ -1,7 +1,7 @@
 {-|
 Copyright  :  (C) 2013-2016, University of Twente,
                   2016-2017, Myrtle Software Ltd,
-                  2021-2024  QBayLogic B.V.,
+                  2021-2025, QBayLogic B.V.,
                   2022,      Google Inc.
 License    :  BSD2 (see the file LICENSE)
 Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
@@ -35,6 +35,7 @@
 import Data.Functor.Identity          (Identity)
 import Data.Functor.Product           (Product)
 import Data.Functor.Sum               (Sum)
+import Data.Char                      (chr, ord)
 import Data.Int
 import Data.Ord                       (Down)
 import Data.Word
@@ -342,6 +343,23 @@
   type BitSize () = 0
   pack   _ = minBound
   unpack _ = ()
+
+instance BitPack Char where
+  type BitSize Char = 21
+  pack   = packXWith packChar#
+  unpack = checkUnpackUndef unpackChar#
+
+packChar# :: Char -> BitVector 21
+packChar# = fromIntegral . ord
+-- See: https://github.com/clash-lang/clash-compiler/pull/2511
+{-# CLASH_OPAQUE packChar# #-}
+{-# ANN packChar# hasBlackBox #-}
+
+unpackChar# :: BitVector 21 -> Char
+unpackChar# = chr . fromIntegral
+-- See: https://github.com/clash-lang/clash-compiler/pull/2511
+{-# CLASH_OPAQUE unpackChar# #-}
+{-# ANN unpackChar# hasBlackBox #-}
 
 -- | __NB__: The documentation only shows instances up to /3/-tuples. By
 -- default, instances up to and including /12/-tuples will exist. If the flag
diff --git a/src/Clash/Class/Counter.hs b/src/Clash/Class/Counter.hs
--- a/src/Clash/Class/Counter.hs
+++ b/src/Clash/Class/Counter.hs
@@ -7,7 +7,7 @@
 -}
 
 module Clash.Class.Counter
-  ( Counter
+  ( Counter(countMin, countMax, countSuccOverflow, countPredOverflow)
   , countSucc
   , countPred
   ) where
diff --git a/src/Clash/Class/Counter/Internal.hs b/src/Clash/Class/Counter/Internal.hs
--- a/src/Clash/Class/Counter/Internal.hs
+++ b/src/Clash/Class/Counter/Internal.hs
@@ -1,5 +1,7 @@
-{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralisedNewtypeDeriving #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
 
@@ -8,12 +10,15 @@
 import Clash.CPP (maxTupleSize)
 
 import Clash.Class.Counter.TH (genTupleInstances)
-import Clash.Sized.BitVector (BitVector)
+import Clash.Sized.BitVector (BitVector, Bit)
 import Clash.Sized.Index (Index)
 import Clash.Sized.Signed (Signed)
 import Clash.Sized.Unsigned (Unsigned)
 
 import Data.Bifunctor (bimap)
+import Data.Functor.Identity (Identity(..))
+import Data.Int (Int8, Int16, Int32, Int64)
+import Data.Word (Word8, Word16, Word32, Word64)
 import GHC.TypeLits (KnownNat, type (<=))
 
 -- $setup
@@ -43,11 +48,6 @@
 --
 -- and have 'Clash.Class.Counter.countSucc' work as described.
 --
--- __NB__: This class exposes four functions 'countMin', 'countMax',
--- 'countSuccOverflow', and 'countPredOverflow'. These functions are considered
--- an internal API. Users are encouraged to use 'Clash.Class.Counter.countSucc'
--- and 'Clash.Class.Counter.countPred'.
---
 class Counter a where
   -- | Value counter wraps around to on a 'countSuccOverflow' overflow
   countMin :: a
@@ -79,6 +79,56 @@
 instance KnownNat n => Counter (Unsigned n)
 instance KnownNat n => Counter (Signed n)
 instance KnownNat n => Counter (BitVector n)
+
+-- | @since 1.8.2
+instance Counter Bool
+-- | @since 1.8.2
+instance Counter Bit
+-- | @since 1.8.2
+instance Counter Int
+-- | @since 1.8.2
+instance Counter Int8
+-- | @since 1.8.2
+instance Counter Int16
+-- | @since 1.8.2
+instance Counter Int32
+-- | @since 1.8.2
+instance Counter Int64
+-- | @since 1.8.2
+instance Counter Word
+-- | @since 1.8.2
+instance Counter Word8
+-- | @since 1.8.2
+instance Counter Word16
+-- | @since 1.8.2
+instance Counter Word32
+-- | @since 1.8.2
+instance Counter Word64
+
+-- | @since 1.8.2
+deriving newtype instance Counter a => Counter (Identity a)
+
+-- | 'Nothing' is considered the minimum value, while @'Just' 'countMax'@ is
+-- considered the maximum value.
+--
+-- @since 1.8.2
+instance Counter a => Counter (Maybe a) where
+  countMin = Nothing
+  countMax = Just countMax
+
+  countSuccOverflow = \case
+    Nothing -> (False, Just countMin)
+    Just a0 ->
+      case countSuccOverflow a0 of
+        (True, _) -> (True, Nothing)
+        (False, a1) -> (False, Just a1)
+
+  countPredOverflow = \case
+    Nothing -> (True, Just countMax)
+    Just a0 ->
+      case countPredOverflow a0 of
+        (True, _) -> (False, Nothing)
+        (False, a1) -> (False, Just a1)
 
 -- | Counter instance that flip-flops between 'Left' and 'Right'. Examples:
 --
diff --git a/src/Clash/Class/Exp.hs b/src/Clash/Class/Exp.hs
--- a/src/Clash/Class/Exp.hs
+++ b/src/Clash/Class/Exp.hs
@@ -11,7 +11,16 @@
 
 {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
 
-module Clash.Class.Exp (Exp, ExpResult, (^)) where
+module Clash.Class.Exp
+  ( Exp
+  , ExpResult
+  , (^)
+
+  -- | * Internal
+  , expIndex#
+  , expSigned#
+  , expUnsigned#
+  ) where
 
 import qualified Prelude                       as P
 import           Prelude                       hiding ((^))
diff --git a/src/Clash/Explicit/BlockRam.hs b/src/Clash/Explicit/BlockRam.hs
--- a/src/Clash/Explicit/BlockRam.hs
+++ b/src/Clash/Explicit/BlockRam.hs
@@ -4,6 +4,7 @@
                   2017     , Google Inc.,
                   2021-2023, QBayLogic B.V.,
                   2022     , Google Inc.,
+                  2024     , Alex Mason,
 License    :  BSD2 (see the file LICENSE)
 Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 
@@ -445,13 +446,16 @@
 
 import Clash.Annotations.Primitive
   (Primitive(InlineYamlPrimitive), HDL(..), hasBlackBox)
+import Clash.Class.AutoReg (AutoReg(autoReg))
+import Clash.Class.BitPack (bitToBool, msb)
 import Clash.Class.Num (SaturationMode(SatBound), satSucc)
 import Clash.Explicit.BlockRam.Model (TdpbramModelConfig(..), tdpbramModel)
-import Clash.Explicit.Signal (KnownDomain, Enable, register, fromEnable)
+import Clash.Explicit.Signal (KnownDomain, Enable, register, fromEnable, andEnable)
 import Clash.Promoted.Nat (SNat(..))
 import Clash.Signal.Bundle (unbundle)
 import Clash.Signal.Internal
   (Clock(..), Reset, Signal (..), invertReset, (.&&.), mux)
+import Clash.Sized.BitVector (BitVector)
 import Clash.Sized.Index (Index)
 import Clash.Sized.Unsigned (Unsigned)
 import Clash.Sized.Vector (Vec, replicate, iterateI)
@@ -1167,6 +1171,47 @@
   | RamNoOp
   -- ^ No operation
   deriving (Generic, NFDataX, Show)
+
+instance (AutoReg a, KnownNat n) => AutoReg (RamOp n a) where
+  autoReg clk rst en initVal input =
+    createRamOp <$> tagR <*> valAddr <*> valValue
+    where
+      tag = toTag <$> input
+
+      toTag op = case op of
+        RamNoOp    -> 0b00 :: BitVector 2
+        RamRead{}  -> 0b01
+        RamWrite{} -> 0b10
+
+      tagInit = toTag initVal
+      tagR = register clk rst en tagInit tag
+
+      toAddr op = case op of
+        RamNoOp         -> deepErrorX "autoReg'.ramOpAddr"
+        RamRead addr    -> addr
+        RamWrite addr _ -> addr
+
+      toValue op = case op of
+        RamWrite _ a -> a
+        _ -> deepErrorX "autoReg'.ramOpValue"
+
+
+      opAddr  = toAddr  <$> input
+      opValue = toValue <$> input
+
+      addrInit = toAddr  initVal
+      valInit  = toValue initVal
+
+      valAddr  = autoReg clk rst (andEnable en           ((/=0) <$> tag)) addrInit opAddr
+      valValue = autoReg clk rst (andEnable en (bitToBool . msb <$> tag)) valInit opValue
+
+      createRamOp t addr val = case t of
+        0b00 -> RamNoOp
+        0b01 -> RamRead addr
+        0b10 -> RamWrite addr val
+        _ -> deepErrorX  "autoReg'.createRamOp: impossible"
+
+  {-# INLINE autoReg #-}
 
 ramOpAddr :: RamOp n a -> Index n
 ramOpAddr (RamRead addr)    = addr
diff --git a/src/Clash/Explicit/DDR.hs b/src/Clash/Explicit/DDR.hs
--- a/src/Clash/Explicit/DDR.hs
+++ b/src/Clash/Explicit/DDR.hs
@@ -1,8 +1,9 @@
 {-|
 Copyright  :  (C) 2017, Google Inc
                   2019, Myrtle Software Ltd
+                  2025, QBayLogic B.V.
 License    :  BSD2 (see the file LICENSE)
-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 
 We simulate DDR signal by using 'Signal's which have exactly half the period
 (or double the speed) of our normal 'Signal's.
@@ -42,6 +43,7 @@
 >>> import Clash.Explicit.Prelude
 >>> import Clash.Explicit.DDR
 >>> :{
+type Fast = ("Fast" :: Domain)
 instance KnownDomain "Fast" where
   type KnownConf "Fast" = 'DomainConfiguration "Fast" 5000 'Rising 'Asynchronous 'Defined 'ActiveHigh
   knownDomain = SDomainConfiguration SSymbol SNat SRising SAsynchronous SDefined SActiveHigh
@@ -54,7 +56,20 @@
 -- Consumes a DDR input signal and produces a regular signal containing a pair
 -- of values.
 --
--- >>> printX $ sampleN 5 $ ddrIn systemClockGen systemResetGen enableGen (-1,-2,-3) (fromList [0..10] :: Signal "Fast" Int)
+-- Data is clocked in on both edges of the clock signal. We can discern the
+-- /active edge/ of the clock and the /other edge/. When the domain has the
+-- rising edge as the active edge (which is the most common), this means that
+-- the /rising/ edge is the /active/ edge and the /falling/ edge is the /other/
+-- edge.
+--
+-- Of the output pair @(o0, o1)@, @o0@ is the data clocked in on the /other/
+-- edge and @o1@ is the data clocked in on the /active/ edge, and @o0@ comes
+-- before @o1@ in time. With a domain where the rising edge is the active edge,
+-- this means @o0@ is clocked in on the falling clock edge and @o1@ is clocked
+-- in on the rising clock edge. For a domain with the falling edge as the active
+-- edge, this is the other way around, but @o0@ still comes before @o1@ in time.
+--
+-- >>> sampleN 5 $ ddrIn systemClockGen systemResetGen enableGen (-1,-2,-3) (fromList [0..10] :: Signal Fast Int)
 -- [(-1,-2),(-1,-2),(-3,2),(3,4),(5,6)]
 ddrIn
   :: ( HasCallStack
@@ -62,16 +77,14 @@
      , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
      , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )
   => Clock slow
-  -- ^ clock
   -> Reset slow
-  -- ^ reset
   -> Enable slow
   -> (a, a, a)
-  -- ^ reset values
+  -- ^ Reset values
   -> Signal fast a
   -- ^ DDR input signal
   -> Signal slow (a, a)
-  -- ^ normal speed output pairs
+  -- ^ Normal speed output pair @(o0, o1)@
 ddrIn clk rst en (i0,i1,i2) =
   withFrozenCallStack $ ddrIn# clk rst en i0 i1 i2
 
@@ -143,7 +156,21 @@
 --
 -- Produces a DDR output signal from a normal signal of pairs of input.
 --
--- >>> sampleN 7 (ddrOut systemClockGen systemResetGen enableGen (-1) (fromList [(0,1),(2,3),(4,5)]) :: Signal "Fast" Int)
+-- Data is clocked out on both edges of the clock signal. We can discern the
+-- /active edge/ of the clock and the /other edge/. When the domain has the
+-- rising edge as the active edge (which is the most common), this means that
+-- the /rising/ edge is the /active/ edge and the /falling/ edge is the /other/
+-- edge.
+--
+-- Of the input pair @(i0, i1)@, @i0@ is the data clocked out on the /active/
+-- edge and @i1@ is the data clocked out on the /other/ edge, and @i0@ comes
+-- before @i1@ in time. With a domain where the rising edge is the active edge,
+-- this means @i0@ is clocked out on the rising clock edge and @i1@ is clocked
+-- out on the falling clock edge. For a domain with the falling edge as the
+-- active edge, this is the other way around, but @i0@ still comes before @i1@
+-- in time.
+--
+-- >>> sampleN 7 (ddrOut systemClockGen systemResetGen enableGen (-1) (fromList [(0,1),(2,3),(4,5)]) :: Signal Fast Int)
 -- [-1,-1,-1,2,3,4,5]
 ddrOut
   :: ( HasCallStack
@@ -154,9 +181,9 @@
   -> Reset slow
   -> Enable slow
   -> a
-  -- ^ reset value
+  -- ^ Reset value
   -> Signal slow (a, a)
-  -- ^ Normal speed input pairs
+  -- ^ Normal speed input pair @(i0, i1)@
   -> Signal fast a
   -- ^ DDR output signal
 ddrOut clk rst en i0 =
diff --git a/src/Clash/Intel/DDR.hs b/src/Clash/Intel/DDR.hs
--- a/src/Clash/Intel/DDR.hs
+++ b/src/Clash/Intel/DDR.hs
@@ -1,15 +1,16 @@
 {-|
 Copyright  :  (C) 2017, Google Inc
                   2019, Myrtle Software Ltd
+                  2025, QBayLogic B.V.
 License    :  BSD2 (see the file LICENSE)
-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 
 DDR primitives for Intel FPGAs using ALTDDIO primitives.
 
 For general information about DDR primitives see "Clash.Explicit.DDR".
 
 Note that a reset is only available on certain devices,
-see ALTDDIO userguide for the specifics:
+see the ALTDDIO user guide for the specifics:
 <https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_altddio.pdf>
 -}
 
@@ -32,8 +33,17 @@
 -- | Intel specific variant of 'ddrIn' implemented using the ALTDDIO_IN IP core.
 --
 -- Reset values are @0@
+--
+-- Of the output pair @(o0, o1)@, @o0@ is the data clocked in on the /falling/
+-- edge and @o1@ is the data clocked in on the /rising/ edge, and @o0@ comes
+-- before @o1@ in time.
+--
+-- __NB__: This primitive only supports rising edges as the active edge. Trying
+-- to instantiate this function in a domain where falling edges are the active
+-- edge will lead to a HDL generation or Haskell simulation error.
 altddioIn
-  :: ( HasCallStack
+  :: forall fast fPeriod edge reset init polarity slow m deviceFamily
+   . ( HasCallStack
      , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
      , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
      , KnownNat m )
@@ -44,25 +54,50 @@
   --
   -- > SSymbol @"Cyclone IV GX"
   -> Clock slow
-  -- ^ clock
   -> Reset slow
-  -- ^ reset
   -> Enable slow
-  -- ^ Global enable
   -> Signal fast (BitVector m)
   -- ^ DDR input signal
   -> Signal slow (BitVector m,BitVector m)
-  -- ^ normal speed output pairs
-altddioIn _devFam clk rst en = withFrozenCallStack ddrIn# clk rst en 0 0 0
+  -- ^ Normal speed output pair @(o0, o1)@
+altddioIn =
+  case activeEdge @slow of
+    SRising ->
+      withFrozenCallStack altddioIn#
+    SFalling ->
+      clashCompileError
+        "altddioIn: Primitive only supports rising active edge"
+
+altddioIn#
+  :: ( HasCallStack
+     , KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)
+     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)
+     , KnownNat m )
+  => SSymbol deviceFamily
+  -> Clock slow
+  -> Reset slow
+  -> Enable slow
+  -> Signal fast (BitVector m)
+  -> Signal slow (BitVector m,BitVector m)
+altddioIn# SSymbol clk rst en = withFrozenCallStack ddrIn# clk rst en 0 0 0
 -- See: https://github.com/clash-lang/clash-compiler/pull/2511
-{-# CLASH_OPAQUE altddioIn #-}
-{-# ANN altddioIn hasBlackBox #-}
+{-# CLASH_OPAQUE altddioIn# #-}
+{-# ANN altddioIn# hasBlackBox #-}
 
 -- | Intel specific variant of 'ddrOut' implemented using the ALTDDIO_OUT IP core.
 --
 -- Reset value is @0@
+--
+-- Of the input pair @(i0, i1)@, @i0@ is the data clocked out on the /rising/
+-- edge and @i1@ is the data clocked out on the /falling/ edge, and @i0@ comes
+-- before @i1@ in time.
+--
+-- __NB__: This primitive only supports rising edges as the active edge. Trying
+-- to instantiate this function in a domain where falling edges are the active
+-- edge will lead to a HDL generation or Haskell simulation error.
 altddioOut
-  :: ( HasCallStack
+  :: forall fast fPeriod edge reset init polarity slow m deviceFamily
+   . ( HasCallStack
      , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
      , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
      , KnownNat m )
@@ -73,22 +108,24 @@
   --
   -- > SSymbol @"Cyclone IV E"
   -> Clock slow
-  -- ^ clock
   -> Reset slow
-  -- ^ reset
   -> Enable slow
-  -- ^ Global enable
   -> Signal slow (BitVector m,BitVector m)
-  -- ^ normal speed input pair
+  -- ^ Normal speed input pair @(i0, i1)@
   -> Signal fast (BitVector m)
   -- ^ DDR output signal
 altddioOut devFam clk rst en =
-  uncurry (withFrozenCallStack altddioOut# devFam clk rst en) . unbundle
+  case activeEdge @slow of
+    SRising ->
+      uncurry (withFrozenCallStack altddioOut# devFam clk rst en) . unbundle
+    SFalling ->
+      clashCompileError
+        "altddioOut: Primitive only supports rising active edge"
 
 altddioOut#
   :: ( HasCallStack
-     , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
-     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
+     , KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)
+     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)
      , KnownNat m )
   => SSymbol deviceFamily
   -> Clock slow
@@ -97,7 +134,7 @@
   -> Signal slow (BitVector m)
   -> Signal slow (BitVector m)
   -> Signal fast (BitVector m)
-altddioOut# _ clk rst en = ddrOut# clk rst en 0
+altddioOut# SSymbol clk rst en = ddrOut# clk rst en 0
 -- See: https://github.com/clash-lang/clash-compiler/pull/2511
 {-# CLASH_OPAQUE altddioOut# #-}
 {-# ANN altddioOut# hasBlackBox #-}
diff --git a/src/Clash/Magic.hs b/src/Clash/Magic.hs
--- a/src/Clash/Magic.hs
+++ b/src/Clash/Magic.hs
@@ -17,6 +17,7 @@
 -}
 
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE DeriveAnyClass #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE TemplateHaskellQuotes #-}
 
@@ -43,13 +44,15 @@
   , clashCompileError
   ) where
 
+import Clash.Annotations.Primitive (Primitive(..), hasBlackBox)
+import Clash.NamedTypes            ((:::))
+import Clash.Promoted.Symbol       (SSymbol)
+import Clash.XException            (NFDataX)
 import Data.String.Interpolate     (__i)
+import GHC.Generics                (Generic)
 import GHC.Magic                   (noinline)
 import GHC.Stack                   (HasCallStack, withFrozenCallStack)
-import Clash.NamedTypes            ((:::))
 import GHC.TypeLits                (Nat,Symbol)
-import Clash.Promoted.Symbol       (SSymbol)
-import Clash.Annotations.Primitive (Primitive(..), hasBlackBox)
 
 -- | Prefix instance and register names with the given 'Symbol'
 prefixName
@@ -272,7 +275,7 @@
 --   * Co-simulation state or meta-data
 --   * etc.
 data SimOnly a = SimOnly a
-  deriving (Eq, Ord, Foldable, Traversable)
+  deriving (Generic, Eq, Ord, Foldable, Traversable, NFDataX)
 {-# ANN SimOnly hasBlackBox #-}
 
 instance Functor SimOnly where
diff --git a/src/Clash/Signal/BiSignal.hs b/src/Clash/Signal/BiSignal.hs
--- a/src/Clash/Signal/BiSignal.hs
+++ b/src/Clash/Signal/BiSignal.hs
@@ -203,13 +203,8 @@
 --
 -- as it is not safe to coerce the default behaviour, synthesis domain or width
 -- of the data in the signal.
-#if MIN_VERSION_base(4,15,0) && !MIN_VERSION_base(4,17,0)
 data BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
   = BiSignalOut ![Signal dom (Maybe (BitVector n))]
-#else
-newtype BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
-  = BiSignalOut [Signal dom (Maybe (BitVector n))]
-#endif
 
 type instance HasDomain dom1 (BiSignalOut ds dom2 n) = DomEq dom1 dom2
 type instance TryDomain t (BiSignalOut ds dom n) = 'Found dom
diff --git a/src/Clash/Sized/Internal/BitVector.hs b/src/Clash/Sized/Internal/BitVector.hs
--- a/src/Clash/Sized/Internal/BitVector.hs
+++ b/src/Clash/Sized/Internal/BitVector.hs
@@ -298,6 +298,7 @@
 
 instance NFDataX Bit where
   deepErrorX = errorX
+  ensureSpine = unpack# . xToBV . pack#
   rnfX = rwhnfX
   hasUndefined bv = isLeft (isX bv) || unsafeMask# bv /= 0
 
diff --git a/src/Clash/Sized/Internal/Index.hs b/src/Clash/Sized/Internal/Index.hs
--- a/src/Clash/Sized/Internal/Index.hs
+++ b/src/Clash/Sized/Internal/Index.hs
@@ -158,17 +158,10 @@
 --
 -- as it is not safe to coerce between 'Index'es with different ranges. To
 -- change the size, use the functions in the 'Resize' class.
-#if MIN_VERSION_base(4,15,0) && !MIN_VERSION_base(4,17,0)
 data Index (n :: Nat) =
     -- | The constructor, 'I', and the field, 'unsafeToInteger', are not
     -- synthesizable.
     I { unsafeToInteger :: !Integer }
-#else
-newtype Index (n :: Nat) =
-    -- | The constructor, 'I', and the field, 'unsafeToInteger', are not
-    -- synthesizable.
-    I { unsafeToInteger :: Integer }
-#endif
   deriving (Data, Generic)
 
 {-# ANN I hasBlackBox #-}
@@ -564,6 +557,7 @@
 
 instance NFDataX (Index n) where
   deepErrorX = errorX
+  ensureSpine = id
   rnfX = rwhnfX
 
 -- | None of the 'Read' class' methods are synthesizable.
diff --git a/src/Clash/Sized/Internal/Signed.hs b/src/Clash/Sized/Internal/Signed.hs
--- a/src/Clash/Sized/Internal/Signed.hs
+++ b/src/Clash/Sized/Internal/Signed.hs
@@ -184,23 +184,17 @@
 --
 -- as it is not safe to coerce between different width Signed. To change the
 -- width, use the functions in the 'Clash.Class.Resize.Resize' class.
-#if MIN_VERSION_base(4,15,0) && !MIN_VERSION_base(4,17,0)
 data Signed (n :: Nat) =
     -- | The constructor, 'S', and the field, 'unsafeToInteger', are not
     -- synthesizable.
     S { unsafeToInteger :: !Integer}
-#else
-newtype Signed (n :: Nat) =
-    -- | The constructor, 'S', and the field, 'unsafeToInteger', are not
-    -- synthesizable.
-    S { unsafeToInteger :: Integer}
-#endif
   deriving (Data, Generic)
 
 {-# ANN S hasBlackBox #-}
 
 instance NFDataX (Signed n) where
   deepErrorX = errorX
+  ensureSpine = id
   rnfX = rwhnfX
 
 -- See: https://github.com/clash-lang/clash-compiler/pull/2511
diff --git a/src/Clash/Sized/Internal/Unsigned.hs b/src/Clash/Sized/Internal/Unsigned.hs
--- a/src/Clash/Sized/Internal/Unsigned.hs
+++ b/src/Clash/Sized/Internal/Unsigned.hs
@@ -200,17 +200,10 @@
 --
 -- as it is not safe to coerce between different width Unsigned. To change the
 -- width, use the functions in the 'Clash.Class.Resize.Resize' class.
-#if MIN_VERSION_base(4,15,0) && !MIN_VERSION_base(4,17,0)
 data Unsigned (n :: Nat) =
     -- | The constructor, 'U', and the field, 'unsafeToNatural', are not
     -- synthesizable.
     U { unsafeToNatural :: !Natural }
-#else
-newtype Unsigned (n :: Nat) =
-    -- | The constructor, 'U', and the field, 'unsafeToNatural', are not
-    -- synthesizable.
-    U { unsafeToNatural :: Natural }
-#endif
   deriving (Data, Generic)
 
 {-# ANN U hasBlackBox #-}
@@ -240,6 +233,7 @@
 
 instance NFDataX (Unsigned n) where
   deepErrorX = errorX
+  ensureSpine = id
   rnfX = rwhnfX
 
 -- | None of the 'Read' class' methods are synthesizable.
diff --git a/src/Clash/Sized/RTree.hs b/src/Clash/Sized/RTree.hs
--- a/src/Clash/Sized/RTree.hs
+++ b/src/Clash/Sized/RTree.hs
@@ -54,6 +54,10 @@
   , t2v
     -- * Misc
   , lazyT
+
+  -- * Internal
+  , textract
+  , tsplit
   )
 where
 
diff --git a/src/Clash/Sized/Vector.hs b/src/Clash/Sized/Vector.hs
--- a/src/Clash/Sized/Vector.hs
+++ b/src/Clash/Sized/Vector.hs
@@ -1,7 +1,8 @@
 {-|
 Copyright  :  (C) 2013-2016, University of Twente,
                   2017     , Myrtle Software Ltd
-                  2022-2024, QBayLogic B.V.
+                  2022-2025, QBayLogic B.V.
+                  2024,      Alex Mason
 License    :  BSD2 (see the file LICENSE)
 Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 -}
@@ -180,6 +181,8 @@
   Nil  :: Vec 0 a
   Cons :: a -> Vec n a -> Vec (n + 1) a
 
+{-# COMPLETE Nil, (:>) #-}
+
 -- | In many cases, this Generic instance only allows generic
 -- functions/instances over vectors of at least size 1, due to the
 -- /n-1/ in the /Rep (Vec n a)/ definition.
@@ -806,8 +809,11 @@
 -- >>> reverse (1:>2:>3:>4:>Nil)
 -- 4 :> 3 :> 2 :> 1 :> Nil
 reverse :: Vec n a -> Vec n a
-reverse Nil           = Nil
-reverse (x `Cons` xs) = reverse xs :< x
+reverse xs = go Nil xs
+ where
+  go :: i <= n => Vec (n - i) a -> Vec i a -> Vec n a
+  go a (y `Cons` ys) = go (y `Cons` a) ys
+  go a Nil = a
 -- See: https://github.com/clash-lang/clash-compiler/pull/2511
 {-# CLASH_OPAQUE reverse #-}
 {-# ANN reverse hasBlackBox #-}
@@ -853,15 +859,9 @@
 
 {- | Zip two vectors with a functions that also takes the elements' indices.
 
-#if (__GLASGOW_HASKELL__ >= 900 && __GLASGOW_HASKELL__ < 904) || __GLASGOW_HASKELL__ >= 910
 >>> izipWith (\i a b -> i + a + b) (2 :> 2 :> Nil)  (3 :> 3:> Nil)
 *** Exception: X: Clash.Sized.Index: result 2 is out of bounds: [0..1]
 ...
-#else
->>> izipWith (\i a b -> i + a + b) (2 :> 2 :> Nil)  (3 :> 3:> Nil)
-*** Exception: X: Clash.Sized.Index: result 3 is out of bounds: [0..1]
-...
-#endif
 >>> izipWith (\i a b -> extend (bitCoerce i) + a + b) (2 :> 2 :> Nil) (3 :> 3 :> Nil) :: Vec 2 (Unsigned 8)
 5 :> 6 :> Nil
 
diff --git a/src/Clash/XException.hs b/src/Clash/XException.hs
--- a/src/Clash/XException.hs
+++ b/src/Clash/XException.hs
@@ -2,17 +2,17 @@
 Copyright  :  (C) 2016,      University of Twente,
                   2017,      QBayLogic, Google Inc.
                   2017-2019, Myrtle Software Ltd,
-                  2021-2023, QBayLogic B.V.
+                  2021-2025, QBayLogic B.V.
 License    :  BSD2 (see the file LICENSE)
 Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 
 'XException': An exception for uninitialized values
 
->>> show (errorX "undefined" :: Integer, 4 :: Int)
-"(*** Exception: X: undefined
+>>> show (errorX "No value here" :: Integer, 4 :: Int)
+"(*** Exception: X: No value here
 CallStack (from HasCallStack):
 ...
->>> showX (errorX "undefined" :: Integer, 4 :: Int)
+>>> showX (errorX "No value here" :: Integer, 4 :: Int)
 "(undefined,4)"
 -}
 
@@ -358,11 +358,11 @@
 -- | Like the 'Show' class, but values that normally throw an 'XException' are
 -- converted to @undefined@, instead of error'ing out with an exception.
 --
--- >>> show (errorX "undefined" :: Integer, 4 :: Int)
--- "(*** Exception: X: undefined
+-- >>> show (errorX "No value here" :: Integer, 4 :: Int)
+-- "(*** Exception: X: No value here
 -- CallStack (from HasCallStack):
 -- ...
--- >>> showX (errorX "undefined" :: Integer, 4 :: Int)
+-- >>> showX (errorX "No value here" :: Integer, 4 :: Int)
 -- "(undefined,4)"
 --
 -- Can be derived using 'GHC.Generics':
diff --git a/src/Clash/XException/Internal.hs b/src/Clash/XException/Internal.hs
--- a/src/Clash/XException/Internal.hs
+++ b/src/Clash/XException/Internal.hs
@@ -1,17 +1,18 @@
 {-|
 Copyright  :  (C) 2016,      University of Twente,
-                  2017,      QBayLogic, Google Inc.
-                  2017-2019, Myrtle Software Ltd
+                  2017,      Google Inc.,
+                  2017-2019, Myrtle Software Ltd,
+                  2017-2025, QBayLogic B.V.
 License    :  BSD2 (see the file LICENSE)
-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 
 'XException': An exception for uninitialized values
 
->>> show (errorX "undefined" :: Integer, 4 :: Int)
-"(*** Exception: X: undefined
+>>> show (errorX "No value here" :: Integer, 4 :: Int)
+"(*** Exception: X: No value here
 CallStack (from HasCallStack):
 ...
->>> showX (errorX "undefined" :: Integer, 4 :: Int)
+>>> showX (errorX "No value here" :: Integer, 4 :: Int)
 "(undefined,4)"
 -}
 
diff --git a/src/Clash/Xilinx/DDR.hs b/src/Clash/Xilinx/DDR.hs
--- a/src/Clash/Xilinx/DDR.hs
+++ b/src/Clash/Xilinx/DDR.hs
@@ -1,7 +1,8 @@
 {-|
-Copyright  :  (C) 2017, Google Inc
+Copyright  :  (C) 2017     , Google Inc,
+                  2025     , QBayLogic B.V.,
 License    :  BSD2 (see the file LICENSE)
-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
 
 DDR primitives for Xilinx FPGAs
 
@@ -10,8 +11,8 @@
 For more information about the Xilinx DDR primitives see:
 
 * Vivado Design Suite 7 Series FPGA and Zynq-7000 All Programmable SoC
-  Libraries Guide, UG953 (v2018.3) December 5, 2018, p371-373,p481-483,
-  <https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_3/ug953-vivado-7series-libraries.pdf>
+  Libraries Guide, UG953 (v2022.2) October 19, 2022, p369-371, p477-479,
+  <https://www.xilinx.com/content/dam/xilinx/support/documents/sw_manuals/xilinx2022_2/ug953-vivado-7series-libraries.pdf>
 -}
 
 {-# LANGUAGE CPP #-}
@@ -34,49 +35,85 @@
 -- primitive in @SAME_EDGE@ mode.
 --
 -- Reset values are @0@
+--
+-- Of the output pair @(o0, o1)@, @o0@ is the data clocked in on the /falling/
+-- edge and @o1@ is the data clocked in on the /rising/ edge, and @o0@ comes
+-- before @o1@ in time.
+--
+-- __NB__: This primitive only supports rising edges as the active edge. Trying
+-- to instantiate this function in a domain where falling edges are the active
+-- edge will lead to a HDL generation or Haskell simulation error.
 iddr
-  :: ( HasCallStack
+  :: forall fast fPeriod edge reset init polarity slow m
+   . ( HasCallStack
      , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
      , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
      , KnownNat m )
   => Clock slow
-  -- ^ clock
   -> Reset slow
-  -- ^ reset
   -> Enable slow
-  -- ^ global enable
   -> Signal fast (BitVector m)
   -- ^ DDR input signal
   -> Signal slow ((BitVector m),(BitVector m))
-  -- ^ normal speed output pairs
-iddr clk rst en = withFrozenCallStack ddrIn# clk rst en 0 0 0
+  -- ^ Normal speed output pair @(o0, o1)@
+iddr =
+  case activeEdge @slow of
+    SRising ->
+      withFrozenCallStack iddr#
+    SFalling ->
+      clashCompileError
+        "iddr: Primitive only supports rising active edge"
+
+iddr#
+  :: ( HasCallStack
+     , KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)
+     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)
+     , KnownNat m )
+  => Clock slow
+  -> Reset slow
+  -> Enable slow
+  -> Signal fast (BitVector m)
+  -> Signal slow ((BitVector m),(BitVector m))
+iddr# clk rst en = withFrozenCallStack ddrIn# clk rst en 0 0 0
 -- See: https://github.com/clash-lang/clash-compiler/pull/2511
-{-# CLASH_OPAQUE iddr #-}
-{-# ANN iddr hasBlackBox #-}
+{-# CLASH_OPAQUE iddr# #-}
+{-# ANN iddr# hasBlackBox #-}
 
 -- | Xilinx specific variant of 'ddrOut' implemented using the Xilinx ODDR
 -- primitive in @SAME_EDGE@ mode.
 --
 -- Reset value is @0@
+--
+-- Of the input pair @(i0, i1)@, @i0@ is the data clocked out on the /rising/
+-- edge and @i1@ is the data clocked out on the /falling/ edge, and @i0@ comes
+-- before @i1@ in time.
+--
+-- __NB__: This primitive only supports rising edges as the active edge. Trying
+-- to instantiate this function in a domain where falling edges are the active
+-- edge will lead to a HDL generation or Haskell simulation error.
 oddr
-  :: ( KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
+  :: forall fast fPeriod edge reset init polarity slow m
+   . ( KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
      , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
      , KnownNat m )
   => Clock slow
-  -- ^ clock
   -> Reset slow
-  -- ^ reset
   -> Enable slow
-  -- ^ global enable
   -> Signal slow (BitVector m, BitVector m)
-  -- ^ normal speed input pairs
+  -- ^ Normal speed input pair @(i0, i1)@
   -> Signal fast (BitVector m)
   -- ^ DDR output signal
-oddr clk rst en = uncurry (withFrozenCallStack oddr# clk rst en) . unbundle
+oddr clk rst en =
+  case activeEdge @slow of
+    SRising ->
+       uncurry (withFrozenCallStack oddr# clk rst en) . unbundle
+    SFalling ->
+      clashCompileError
+        "oddr: Primitive only supports rising active edge"
 
 oddr#
-  :: ( KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
-     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
+  :: ( KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)
+     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)
      , KnownNat m )
   => Clock slow
   -> Reset slow
diff --git a/tests/Clash/Tests/Counter.hs b/tests/Clash/Tests/Counter.hs
--- a/tests/Clash/Tests/Counter.hs
+++ b/tests/Clash/Tests/Counter.hs
@@ -6,7 +6,6 @@
 import qualified Prelude as P
 
 import Clash.Class.Counter
-import Clash.Class.Counter.Internal
 import Clash.Prelude
 import Data.Proxy
 import Data.Typeable
diff --git a/tests/Clash/Tests/TopEntityGeneration.hs b/tests/Clash/Tests/TopEntityGeneration.hs
--- a/tests/Clash/Tests/TopEntityGeneration.hs
+++ b/tests/Clash/Tests/TopEntityGeneration.hs
@@ -68,7 +68,13 @@
     , fd2 :: OrderedCF 'True f  ("fd2" ::: Bool)
     }
 
+data RecordWithSimOnlyField = RecordWithSimOnlyField
+  { simOnlyField1 :: "a" ::: SimOnly (Signal System ("foo" ::: Int))
+  , simOnlyField3 :: "b" ::: Signal System (SimOnly ("bar" ::: Int))
+  , someOtherField :: "c" ::: Signal System ("wobble" ::: Int)
+  }
 
+
 topEntity1 :: "in1" ::: Signal System Int
            -> "in2" ::: Signal System Bool
            -> "out" ::: Signal System Int
@@ -226,6 +232,36 @@
     ]
     (PortName "out")
 
+topEntity9 :: (HiddenClockResetEnable System)
+           => "pair" ::: SimOnly (Signal System (Pair Bool))
+           -> "pair" ::: Signal System (SimOnly (Pair Single))
+           -> "out" ::: Signal System Int
+topEntity9 = undefined
+makeTopEntity 'topEntity9
+
+expectedTopEntity9 :: TopEntity
+expectedTopEntity9 =
+ Synthesize "topEntity9"
+    [ PortProduct "" [PortName "clk", PortName "rst", PortName "en"]
+    , PortName "pair"
+    , PortName "pair"
+    ]
+    (PortName "out")
+
+topEntity10 :: (HiddenClockResetEnable System)
+           => "record" ::: Signal System RecordWithSimOnlyField
+           -> "out" ::: Signal System Int
+topEntity10 = undefined
+makeTopEntity 'topEntity10
+
+expectedTopEntity10 :: TopEntity
+expectedTopEntity10 =
+ Synthesize "topEntity10"
+    [ PortProduct "" [PortName "clk", PortName "rst", PortName "en"]
+    , PortProduct "record" [PortName "a",PortName "b",PortName "c_wobble"]
+    ]
+    (PortName "out")
+
 topEntityFailure1
   :: "int"     ::: Signal System Int
   -> "tuple"   ::: ("tup1" ::: Signal System (BitVector 7), "tup2" ::: Signal System (BitVector 9))
@@ -310,6 +346,12 @@
       , testCase "topEntity8" $
           $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntity8)
           @?= Just expectedTopEntity8
+      , testCase "topEntity9" $
+          $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntity9)
+          @?= Just expectedTopEntity9
+      , testCase "topEntity10" $
+          $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntity10)
+          @?= Just expectedTopEntity10
       ]
     , testGroup "Expected failures"
       [ testCase "topEntityFailure1" $
