diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,18 +1,32 @@
 # Changelog for [`clash-prelude` package](http://hackage.haskell.org/package/clash-prelude)
 
+## 0.9 *June 25th 2015*
+* New features:
+  * Add operations on singleton natural numbers: `addSNat`, `subSNat`, `mulSNat`, and `powSNat`.
+  * Add asynchronous RAM functions in `CLaSH.Prelude.RAM`, which have an asynchronous/combinational read port.
+  * Add ROM functions in modules `CLaSH.Prelude.ROM` and `CLaSH.Prelude.ROM.File`, where the latter module contains functions that instantiate a ROM from the content specified in an external data-file.
+  * Add BlockRam functions, in the `CLaSH.Prelude.BlockRam.File` module, whose content can be initialised with the content specified in an external data-file.
+  * `assert` now takes an extra `String` argument so you can distinguish one `assert` from the others.
+  Additionally, `assert'` is added which takes an additional `SClock` argument.
+  This is needed, because `assert` now reports the clock cycle, and clock domain, when an assertion fails.
+  * `defClkAltera` and `defClkXilinx` are replaced by, `altpll` and `alteraPll` for Altera clock sources, and `clockWizard` for Xilinx clock sources.
+  These names correspond to the names of the generator utilities in Quartus and ISE/Vivado.
+  * Add [Safe](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/safe-haskell.html) versions of the prelude modules: `CLaSH.Prelude.Safe` and `CLaSH.Prelude.Explicit.Safe`
+  * Add synchronizers in the `CLaSH.Prelude.Synchronizer` module
+
 ## 0.8 *June 3rd 2015*
 * New features:
   * Make the (Bit)Vector argument the _last_ argument for the following functions: `slice`, `setSlice`, `replaceBit`, `replace`. The signatures for the above functions are now:
-    
+
     ```
     slice      :: BitPack a => SNat m -> SNat n -> a -> BitVector (m + 1 - n)
     setSlice   :: BitPack a => SNat m -> SNat n -> BitVector (m + 1 - n) -> a -> a
     replaceBit :: Integral i => i -> Bit -> a -> a
     replace    :: Integral i => i -> a -> Vec n a -> Vec n a
     ```
-    
+
     This allows for easier chaining, e.g.:
-    
+
     ```
     replaceBit 0 1 $
     repleceBit 4 0 $
@@ -28,16 +42,16 @@
     > unpack 0x0F :: Vec 8 Bit
     <1,1,1,1,0,0,0,0>
     ```
-    
+
     As of version 0.8, we have `head x == msb y`:
-    
+
     ```
     > 0x0F :: BitVector 8
     0000_1111
     > unpack 0x0F :: Vec 8 Bit
     <0,0,0,0,1,1,1,1>
     ```
-    
+
     So converting for `Vec`tors of `Bit`s to `BitVector`s is no longer _index_-preserving, but it is _order_-preserving.
   * Add [QuickCheck](http://hackage.haskell.org/package/QuickCheck) `Arbitary` and `CoArbitary` instances for all data types
   * Add [lens](http://hackage.haskell.org/package/lens) `Ixed` instances for `BitVector`, `Signed`, `Unsigned`, and `Vec`
diff --git a/clash-prelude.cabal b/clash-prelude.cabal
--- a/clash-prelude.cabal
+++ b/clash-prelude.cabal
@@ -1,157 +1,165 @@
-Name:                 clash-prelude
-Version:              0.8.1
-Synopsis:             CAES Language for Synchronous Hardware - Prelude library
-Description:
-  CλaSH (pronounced ‘clash’) is a functional hardware description language that
-  borrows both its syntax and semantics from the functional programming language
-  Haskell. The merits of using a functional language to describe hardware comes
-  from the fact that combinational circuits can be directly modeled as
-  mathematical functions and that functional languages lend themselves very well
-  at describing and (de-)composing mathematical functions.
-  .
-  This package provides:
-  .
-  * Prelude library containing datatypes and functions for circuit design
-  .
-  To use the library:
-  .
-  * Import "CLaSH.Prelude"
-  .
-  * Additionally import "CLaSH.Prelude.Explicit" if you want to design
-    explicitly clocked circuits in a multi-clock setting
-  .
-  A preliminary version of a tutorial can be found in "CLaSH.Tutorial", for a
-  general overview of the library you should however check out "CLaSH.Prelude".
-  Some circuit examples can be found in "CLaSH.Examples".
-Homepage:             http://www.clash-lang.org/
-bug-reports:          http://github.com/clash-lang/clash-prelude/issues
-License:              BSD2
-License-file:         LICENSE
-Author:               Christiaan Baaij
-Maintainer:           Christiaan Baaij <christiaan.baaij@gmail.com>
-Copyright:            Copyright © 2013-2015 University of Twente
-Category:             Hardware
-Build-type:           Simple
-
-Extra-source-files:   README.md
-                      CHANGELOG.md
-                      AUTHORS.md
-
-extra-doc-files:      doc/*.svg
-
-Cabal-version:        >=1.10
-
-source-repository head
-  type: git
-  location: https://github.com/clash-lang/clash-prelude.git
-
-flag doctests
-  description:
-    You can disable testing with doctests using `-f-doctests`.
-  default: True
-  manual: True
-
-flag doclinks
-  description:
-    Create hyperlinks to non-dependent packages using `-fdoclinks`.
-  default: False
-  manual: True
-
-Library
-  HS-Source-Dirs:     src
-
-  default-language:   Haskell2010
-  ghc-options:        -Wall -fexpose-all-unfoldings
-
-  Exposed-modules:    CLaSH.Annotations.TopEntity
-
-                      CLaSH.Class.BitPack
-                      CLaSH.Class.Num
-                      CLaSH.Class.Resize
-
-                      CLaSH.Prelude
-                      CLaSH.Prelude.BitIndex
-                      CLaSH.Prelude.BitReduction
-                      CLaSH.Prelude.BlockRam
-                      CLaSH.Prelude.DataFlow
-                      CLaSH.Prelude.Explicit
-                      CLaSH.Prelude.Mealy
-                      CLaSH.Prelude.Moore
-                      CLaSH.Prelude.Testbench
-
-                      CLaSH.Promoted.Nat
-                      CLaSH.Promoted.Nat.TH
-                      CLaSH.Promoted.Nat.Literals
-                      CLaSH.Promoted.Ord
-                      CLaSH.Promoted.Symbol
-
-                      CLaSH.Signal
-                      CLaSH.Signal.Bundle
-                      CLaSH.Signal.Delayed
-                      CLaSH.Signal.Explicit
-                      CLaSH.Signal.Internal
-
-                      CLaSH.Sized.BitVector
-                      CLaSH.Sized.Fixed
-                      CLaSH.Sized.Index
-                      CLaSH.Sized.Signed
-                      CLaSH.Sized.Unsigned
-                      CLaSH.Sized.Vector
-
-                      CLaSH.Sized.Internal.BitVector
-                      CLaSH.Sized.Internal.Index
-                      CLaSH.Sized.Internal.Signed
-                      CLaSH.Sized.Internal.Unsigned
-
-                      CLaSH.Tutorial
-                      CLaSH.Examples
-
-  other-extensions:   BangPatterns
-                      DataKinds
-                      ConstraintKinds
-                      DefaultSignatures
-                      DeriveDataTypeable
-                      FlexibleContexts
-                      GADTs
-                      GeneralizedNewtypeDeriving
-                      KindSignatures
-                      MagicHash
-                      MultiParamTypeClasses
-                      Rank2Types
-                      ScopedTypeVariables
-                      StandaloneDeriving
-                      TemplateHaskell
-                      TupleSections
-                      TypeFamilies
-                      TypeOperators
-                      UndecidableInstances
-
-  Build-depends:      base                      >= 4.8.0.0 && < 5,
-                      data-default              >= 0.5.3,
-                      integer-gmp               >= 0.5.1.0,
-                      ghc-prim                  >= 0.3.1.0,
-                      ghc-typelits-natnormalise >= 0.3,
-                      lens                      >= 4.9,
-                      QuickCheck                >= 2.7 && <2.9,
-                      singletons                >= 1.0,
-                      template-haskell          >= 2.9.0.0,
-                      th-lift                   >= 0.5.6
-
-  if flag(doclinks)
-    CPP-Options:      -DDOCLINKS
-    build-depends:    transformers              >= 0.4.2.0
-
-test-suite doctests
-  type:             exitcode-stdio-1.0
-  default-language: Haskell2010
-  main-is:          doctests.hs
-  ghc-options:      -Wall
-  hs-source-dirs:   tests
-
-  if !flag(doctests)
-    buildable: False
-  else
-    build-depends:
-      base    >= 4     && < 5,
-      doctest >= 0.9.1 && < 0.11,
-      Glob    >= 0.7   && < 0.8
+Name:                 clash-prelude
+Version:              0.9
+Synopsis:             CAES Language for Synchronous Hardware - Prelude library
+Description:
+  CλaSH (pronounced ‘clash’) is a functional hardware description language that
+  borrows both its syntax and semantics from the functional programming language
+  Haskell. The merits of using a functional language to describe hardware comes
+  from the fact that combinational circuits can be directly modeled as
+  mathematical functions and that functional languages lend themselves very well
+  at describing and (de-)composing mathematical functions.
+  .
+  This package provides:
+  .
+  * Prelude library containing datatypes and functions for circuit design
+  .
+  To use the library:
+  .
+  * Import "CLaSH.Prelude"
+  .
+  * Additionally import "CLaSH.Prelude.Explicit" if you want to design
+    explicitly clocked circuits in a multi-clock setting
+  .
+  A preliminary version of a tutorial can be found in "CLaSH.Tutorial", for a
+  general overview of the library you should however check out "CLaSH.Prelude".
+  Some circuit examples can be found in "CLaSH.Examples".
+Homepage:             http://www.clash-lang.org/
+bug-reports:          http://github.com/clash-lang/clash-prelude/issues
+License:              BSD2
+License-file:         LICENSE
+Author:               Christiaan Baaij
+Maintainer:           Christiaan Baaij <christiaan.baaij@gmail.com>
+Copyright:            Copyright © 2013-2015 University of Twente
+Category:             Hardware
+Build-type:           Simple
+
+Extra-source-files:   README.md
+                      CHANGELOG.md
+                      AUTHORS.md
+
+extra-doc-files:      doc/*.svg
+
+Cabal-version:        >=1.10
+
+source-repository head
+  type: git
+  location: https://github.com/clash-lang/clash-prelude.git
+
+flag doctests
+  description:
+    You can disable testing with doctests using `-f-doctests`.
+  default: True
+  manual: True
+
+flag doclinks
+  description:
+    Create hyperlinks to non-dependent packages using `-fdoclinks`.
+  default: False
+  manual: True
+
+Library
+  HS-Source-Dirs:     src
+
+  default-language:   Haskell2010
+  ghc-options:        -Wall -fexpose-all-unfoldings
+
+  Exposed-modules:    CLaSH.Annotations.TopEntity
+
+                      CLaSH.Class.BitPack
+                      CLaSH.Class.Num
+                      CLaSH.Class.Resize
+
+                      CLaSH.Prelude
+                      CLaSH.Prelude.BitIndex
+                      CLaSH.Prelude.BitReduction
+                      CLaSH.Prelude.BlockRam
+                      CLaSH.Prelude.BlockRam.File
+                      CLaSH.Prelude.DataFlow
+                      CLaSH.Prelude.Explicit
+                      CLaSH.Prelude.Explicit.Safe
+                      CLaSH.Prelude.Mealy
+                      CLaSH.Prelude.Moore
+                      CLaSH.Prelude.RAM
+                      CLaSH.Prelude.ROM
+                      CLaSH.Prelude.ROM.File
+                      CLaSH.Prelude.Safe
+                      CLaSH.Prelude.Synchronizer
+                      CLaSH.Prelude.Testbench
+
+                      CLaSH.Promoted.Nat
+                      CLaSH.Promoted.Nat.TH
+                      CLaSH.Promoted.Nat.Literals
+                      CLaSH.Promoted.Ord
+                      CLaSH.Promoted.Symbol
+
+                      CLaSH.Signal
+                      CLaSH.Signal.Bundle
+                      CLaSH.Signal.Delayed
+                      CLaSH.Signal.Explicit
+                      CLaSH.Signal.Internal
+
+                      CLaSH.Sized.BitVector
+                      CLaSH.Sized.Fixed
+                      CLaSH.Sized.Index
+                      CLaSH.Sized.Signed
+                      CLaSH.Sized.Unsigned
+                      CLaSH.Sized.Vector
+
+                      CLaSH.Sized.Internal.BitVector
+                      CLaSH.Sized.Internal.Index
+                      CLaSH.Sized.Internal.Signed
+                      CLaSH.Sized.Internal.Unsigned
+
+                      CLaSH.Tutorial
+                      CLaSH.Examples
+
+  other-extensions:   BangPatterns
+                      DataKinds
+                      ConstraintKinds
+                      DefaultSignatures
+                      DeriveDataTypeable
+                      FlexibleContexts
+                      GADTs
+                      GeneralizedNewtypeDeriving
+                      KindSignatures
+                      MagicHash
+                      MultiParamTypeClasses
+                      Rank2Types
+                      ScopedTypeVariables
+                      StandaloneDeriving
+                      TemplateHaskell
+                      TupleSections
+                      TypeFamilies
+                      TypeOperators
+                      UndecidableInstances
+
+  Build-depends:      array                     >= 0.5.1.0,
+                      base                      >= 4.8.0.0 && < 5,
+                      data-default              >= 0.5.3,
+                      integer-gmp               >= 0.5.1.0,
+                      ghc-prim                  >= 0.3.1.0,
+                      ghc-typelits-natnormalise >= 0.3,
+                      lens                      >= 4.9,
+                      QuickCheck                >= 2.7 && <2.9,
+                      singletons                >= 1.0,
+                      template-haskell          >= 2.9.0.0,
+                      th-lift                   >= 0.5.6
+
+  if flag(doclinks)
+    CPP-Options:      -DDOCLINKS
+    build-depends:    transformers              >= 0.4.2.0
+
+test-suite doctests
+  type:             exitcode-stdio-1.0
+  default-language: Haskell2010
+  main-is:          doctests.hs
+  ghc-options:      -Wall
+  hs-source-dirs:   tests
+
+  if !flag(doctests)
+    buildable: False
+  else
+    build-depends:
+      base    >= 4     && < 5,
+      doctest >= 0.9.1 && < 0.11,
+      Glob    >= 0.7   && < 0.8
diff --git a/src/CLaSH/Annotations/TopEntity.hs b/src/CLaSH/Annotations/TopEntity.hs
--- a/src/CLaSH/Annotations/TopEntity.hs
+++ b/src/CLaSH/Annotations/TopEntity.hs
@@ -89,7 +89,7 @@
     , t_extraIn  = [ (\"CLOCK_50\", 1)
                    , (\"KEY0\"    , 1)
                    ]
-    , t_clocks   = [ 'defClkAltera' "altpll50" "CLOCK_50(0)" "not KEY0(0)" ]
+    , t_clocks   = [ 'altpll' "altpll50" "CLOCK_50(0)" "not KEY0(0)" ]
     }) \#-\}
 @
 
@@ -173,8 +173,11 @@
   , ClockSource (..)
     -- * Convenience functions
   , defTop
-  , defClkAltera
-  , defClkXilinx
+    -- ** Altera clock sources
+  , altpll
+  , alteraPll
+    -- ** Xilinx clock sources
+  , clockWizard
   )
 where
 
@@ -196,22 +199,18 @@
   --
   -- So given a bit-width @n@, the port has type:
   --
-  -- @std_logic_vector (n-1 downto 0)@ in VHDL
-  --
-  -- and
-  --
-  -- @logic [n-1:0]@ in (System)Verilog.
+  -- * __VHDL__: @std_logic_vector (n-1 downto 0)@
+  -- * __Verilog__: @[n-1:0]@
+  -- * __SystemVerilog__: @logic [n-1:0]@
   , t_extraOut :: [(String,Int)]
   -- ^ Extra output ports, where every tuple holds the name of the input port
   -- and the number of bits are used for that input port.
   --
   -- So given a bit-width @n@, the port has type:
   --
-  -- @std_logic_vector (n-1 downto 0)@ in VHDL
-  --
-  -- and
-  --
-  -- @logic [n-1:0]@ in (System)Verilog.
+  -- * __VHDL__: @std_logic_vector (n-1 downto 0)@
+  -- * __Verilog__: @[n-1:0]@
+  -- * __SystemVerilog__: @logic [n-1:0]@
   , t_clocks   :: [ClockSource]  -- ^ List of clock sources
   }
   deriving (Data,Show)
@@ -275,10 +274,10 @@
   , t_clocks   = []
   }
 
--- | A clock source that corresponds to the Altera PLL component with default
--- settings to provide a stable 'systemClock'.
+-- | A clock source that corresponds to the Altera/Quartus \"ALTPLL\" component
+-- with default settings to provide a stable 'systemClock'.
 --
--- >>> defClkAltera "altpll50" "CLOCK(0)" "not KEY(0)"
+-- >>> altpll "altpll50" "CLOCK(0)" "not KEY(0)"
 -- ClockSource {c_name = "altpll50", c_inp = Just ("inclk0","CLOCK(0)"), c_outp = [("c0","system1000")], c_reset = Just ("areset","not KEY(0)"), c_lock = "locked", c_sync = False}
 --
 -- Will generate the following VHDL:
@@ -292,7 +291,7 @@
 --
 -- If you are however generating (System)Verilog you should write:
 --
--- >>> defClkAltera "altpll50" "CLOCK[0]" "~ KEY[0]"
+-- >>> altpll "altpll50" "CLOCK[0]" "~ KEY[0]"
 -- ClockSource {c_name = "altpll50", c_inp = Just ("inclk0","CLOCK[0]"), c_outp = [("c0","system1000")], c_reset = Just ("areset","~ KEY[0]"), c_lock = "locked", c_sync = False}
 --
 -- so that the following (System)Verilog is created:
@@ -302,11 +301,11 @@
 -- > ,.c0 (system1000)
 -- > ,.areset (~ KEY0[0])
 -- > ,.locked (altpll50_locked));
-defClkAltera :: String -- ^ Name of the component.
-             -> String -- ^ Clock Pin/Expression of the free running clock.
-             -> String -- ^ Reset Pin/Expression controlling the reset of the PLL.
-             -> ClockSource
-defClkAltera pllName clkExpr resExpr = ClockSource
+altpll :: String -- ^ Name of the component.
+       -> String -- ^ Clock Pin/Expression of the free running clock.
+       -> String -- ^ Reset Pin/Expression controlling the reset of the PLL.
+       -> ClockSource
+altpll pllName clkExpr resExpr = ClockSource
   { c_name  = pllName
   , c_inp   = Just ("inclk0",clkExpr)
   , c_outp  = [("c0",show systemClock)]
@@ -315,10 +314,50 @@
   , c_sync  = False
   }
 
--- | A clock source that corresponds to the Xilinx PLL/MMCM component with
--- settings to provide a stable 'systemClock'.
+-- | A clock source that corresponds to the Altera \"Altera PLL\" component
+-- with default settings to provide a stable 'systemClock'.
 --
--- >>> defClkXilinx "clkwiz50" "CLOCK(0)" "not KEY(0)"
+-- >>> alteraPll "alteraPll50" "CLOCK(0)" "not KEY(0)"
+-- ClockSource {c_name = "alteraPll50", c_inp = Just ("refclk","CLOCK(0)"), c_outp = [("outclk_0","system1000")], c_reset = Just ("rst","not KEY(0)"), c_lock = "locked", c_sync = False}
+--
+-- Will generate the following VHDL:
+--
+-- > alteraPll50_inst : entity alteraPll
+-- >   port map
+-- >     (refclk   => CLOCK_50(0)
+-- >     ,outclk_0 => system1000
+-- >     ,rst      => not KEY0(0)
+-- >     ,locked   => alteraPll50_locked);
+--
+-- If you are however generating (System)Verilog you should write:
+--
+-- >>> alteraPll "alteraPll50" "CLOCK[0]" "~ KEY[0]"
+-- ClockSource {c_name = "alteraPll50", c_inp = Just ("refclk","CLOCK[0]"), c_outp = [("outclk_0","system1000")], c_reset = Just ("rst","~ KEY[0]"), c_lock = "locked", c_sync = False}
+--
+-- so that the following (System)Verilog is created:
+--
+-- > alteraPll50 alteraPll50_inst
+-- > (.refclk (CLOCK_50[0])
+-- > ,.outclk_0 (system1000)
+-- > ,.rst (~ KEY0[0])
+-- > ,.locked (alteraPll50_locked));
+alteraPll :: String -- ^ Name of the component.
+          -> String -- ^ Clock Pin/Expression of the free running clock.
+          -> String -- ^ Reset Pin/Expression controlling the reset of the PLL.
+          -> ClockSource
+alteraPll pllName clkExpr resExpr = ClockSource
+  { c_name  = pllName
+  , c_inp   = Just ("refclk",clkExpr)
+  , c_outp  = [("outclk_0",show systemClock)]
+  , c_reset = Just ("rst",resExpr)
+  , c_lock  = "locked"
+  , c_sync  = False
+  }
+
+-- | A clock source that corresponds to the Xilinx PLL/MMCM component created
+-- with the \"Clock Wizard\", with settings to provide a stable 'systemClock'.
+--
+-- >>> clockWizard "clkwiz50" "CLOCK(0)" "not KEY(0)"
 -- ClockSource {c_name = "clkwiz50", c_inp = Just ("CLK_IN1","CLOCK(0)"), c_outp = [("CLK_OUT1","system1000")], c_reset = Just ("RESET","not KEY(0)"), c_lock = "LOCKED", c_sync = False}
 --
 -- Will generate the following VHDL:
@@ -332,7 +371,7 @@
 --
 -- If you are however generating (System)Verilog you should write:
 --
--- >>> defClkXilinx "clkwiz50" "CLOCK[0]" "~ KEY[0]"
+-- >>> clockWizard "clkwiz50" "CLOCK[0]" "~ KEY[0]"
 -- ClockSource {c_name = "clkwiz50", c_inp = Just ("CLK_IN1","CLOCK[0]"), c_outp = [("CLK_OUT1","system1000")], c_reset = Just ("RESET","~ KEY[0]"), c_lock = "LOCKED", c_sync = False}
 --
 -- so that the following (System)Verilog is created:
@@ -342,11 +381,11 @@
 -- > ,.CLK_OUT1 (system1000)
 -- > ,.RESET (~ KEY0[0])
 -- > ,.LOCKED (altpll50_locked));
-defClkXilinx :: String -- ^ Name of the component.
-             -> String -- ^ Clock Pin/Expression of the free running clock.
-             -> String -- ^ Reset Pin/Expression controlling the reset of the PLL.
-             -> ClockSource
-defClkXilinx pllName clkExpr resExpr = ClockSource
+clockWizard :: String -- ^ Name of the component.
+            -> String -- ^ Clock Pin/Expression of the free running clock.
+            -> String -- ^ Reset Pin/Expression controlling the reset of the PLL.
+            -> ClockSource
+clockWizard pllName clkExpr resExpr = ClockSource
   { c_name  = pllName
   , c_inp   = Just ("CLK_IN1",clkExpr)
   , c_outp  = [("CLK_OUT1",show systemClock)]
diff --git a/src/CLaSH/Prelude.hs b/src/CLaSH/Prelude.hs
--- a/src/CLaSH/Prelude.hs
+++ b/src/CLaSH/Prelude.hs
@@ -40,9 +40,25 @@
   , moore
   , mooreB
   , registerB
+    -- * ROMs
+  , asyncRom
+  , asyncRomPow2
+  , rom
+  , romPow2
+    -- ** ROMs initialised with a data file
+  , asyncRomFile
+  , asyncRomFilePow2
+  , romFile
+  , romFilePow2
+    -- * RAM primitives with a combinational read port
+  , asyncRam
+  , asyncRamPow2
     -- * BlockRAM primitives
   , blockRam
   , blockRamPow2
+    -- ** BlockRAM primitives initialised with a data file
+  , blockRamFile
+  , blockRamFilePow2
     -- * Utility functions
   , window
   , windowD
@@ -115,12 +131,12 @@
 import CLaSH.Class.Resize
 import CLaSH.Prelude.BitIndex
 import CLaSH.Prelude.BitReduction
-import CLaSH.Prelude.BlockRam      (blockRam, blockRamPow2)
-import CLaSH.Prelude.Explicit      (registerB', window', windowD', isRising',
-                                    isFalling')
-import CLaSH.Prelude.Mealy         (mealy, mealyB, (<^>))
-import CLaSH.Prelude.Moore         (moore, mooreB)
+import CLaSH.Prelude.BlockRam.File (blockRamFile, blockRamFilePow2)
 import CLaSH.Prelude.DataFlow
+import CLaSH.Prelude.Explicit      (window', windowD')
+import CLaSH.Prelude.ROM.File      (asyncRomFile,asyncRomFilePow2,romFile,
+                                    romFilePow2)
+import CLaSH.Prelude.Safe
 import CLaSH.Prelude.Testbench     (assert, stimuliGenerator, outputVerifier)
 import CLaSH.Promoted.Nat
 import CLaSH.Promoted.Nat.TH
@@ -177,30 +193,3 @@
         => Signal a               -- ^ Signal to create a window over
         -> Vec (n + 1) (Signal a) -- ^ Window of at least size 1
 windowD = windowD' systemClock
-
-{-# INLINE registerB #-}
--- | Create a 'register' function for product-type like signals (e.g. '(Signal a, Signal b)')
---
--- > rP :: (Signal Int,Signal Int) -> (Signal Int, Signal Int)
--- > rP = registerB (8,8)
---
--- >>> simulateB rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
--- [(8,8),(1,1),(2,2),(3,3)...
-registerB :: Bundle a => a -> Unbundled a -> Unbundled a
-registerB = registerB' systemClock
-
-{-# INLINE isRising #-}
--- | Give a pulse when the 'Signal' goes from 'minBound' to 'maxBound'
-isRising :: (Bounded a, Eq a)
-         => a -- ^ Starting value
-         -> Signal a
-         -> Signal Bool
-isRising = isRising' systemClock
-
-{-# INLINE isFalling #-}
--- | Give a pulse when the 'Signal' goes from 'maxBound' to 'minBound'
-isFalling :: (Bounded a, Eq a)
-          => a -- ^ Starting value
-          -> Signal a
-          -> Signal Bool
-isFalling = isFalling' systemClock
diff --git a/src/CLaSH/Prelude/BitIndex.hs b/src/CLaSH/Prelude/BitIndex.hs
--- a/src/CLaSH/Prelude/BitIndex.hs
+++ b/src/CLaSH/Prelude/BitIndex.hs
@@ -39,8 +39,8 @@
 -- 0
 -- >>> (7 :: Unsigned 6) ! 6
 -- *** Exception: (!): 6 is out of range [5..0]
-(!) :: (BitPack a, KnownNat (BitSize a), Integral i) => a -> i -> Bit
-(!) v i = index# (pack v) (fromIntegral i)
+(!) :: (BitPack a, KnownNat (BitSize a), Enum i) => a -> i -> Bit
+(!) v i = index# (pack v) (fromEnum i)
 
 {-# INLINE slice #-}
 -- | Get a slice between bit index @m@ and and bit index @n@.
@@ -93,9 +93,9 @@
 -- 01_1011
 -- >>> replaceBit 6 0 (-5 :: Signed 6)
 -- *** Exception: replaceBit: 6 is out of range [5..0]
-replaceBit :: (BitPack a, KnownNat (BitSize a), Integral i) => i -> Bit -> a
+replaceBit :: (BitPack a, KnownNat (BitSize a), Enum i) => i -> Bit -> a
            -> a
-replaceBit i b v = unpack (replaceBit# (pack v) (fromIntegral i) b)
+replaceBit i b v = unpack (replaceBit# (pack v) (fromEnum i) b)
 
 {-# INLINE setSlice #-}
 -- | Set the bits between bit index @m@ and bit index @n@.
diff --git a/src/CLaSH/Prelude/BlockRam.hs b/src/CLaSH/Prelude/BlockRam.hs
--- a/src/CLaSH/Prelude/BlockRam.hs
+++ b/src/CLaSH/Prelude/BlockRam.hs
@@ -1,25 +1,371 @@
 {-# LANGUAGE DataKinds        #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MagicHash        #-}
 {-# LANGUAGE TypeOperators    #-}
 
 {-# LANGUAGE Safe #-}
 
+{-# OPTIONS_HADDOCK show-extensions #-}
+
 {-|
 Copyright  :  (C) 2013-2015, University of Twente
 License    :  BSD2 (see the file LICENSE)
 Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+BlockRAM primitives
+
+= Using RAMs #usingrams#
+
+We will show a rather elaborate example on how you can, and why you might want
+to use 'blockRam's. We will build a \"small\" CPU+Memory+Program ROM where we
+will slowly evolve to using blockRams. Note that the code is /not/ meant as a
+de-facto standard on how to do CPU design in CλaSH.
+
+We start with the definition of the Instructions, Register names and machine
+codes:
+
+@
+{\-\# LANGUAGE RecordWildCards \#-\}
+module CPU where
+
+import CLaSH.Prelude
+import qualified Data.List as L
+
+type InstrAddr = Unsigned 8
+type MemAddr   = Unsigned 5
+type Value     = Signed 8
+
+data Instruction
+  = Compute Operator Reg Reg Reg
+  | Branch Reg Value
+  | Jump Value
+  | Load MemAddr Reg
+  | Store Reg MemAddr
+  | Nop
+  deriving (Eq,Show)
+
+data Reg
+  = Zero
+  | PC
+  | RegA
+  | RegB
+  | RegC
+  | RegD
+  | RegE
+  deriving (Eq,Show,Enum)
+
+data Operator = Add | Sub | Incr | Imm | CmpGt
+  deriving (Eq,Show)
+
+data MachCode
+  = MachCode
+  { inputX  :: Reg
+  , inputY  :: Reg
+  , result  :: Reg
+  , aluCode :: Operator
+  , ldReg   :: Reg
+  , rdAddr  :: MemAddr
+  , wrAddr  :: MemAddr
+  , wrEn    :: Bool
+  , jmpM    :: Maybe Value
+  }
+
+nullCode = MachCode { inputX = Zero, inputY = Zero, result = Zero, aluCode = Imm
+                    , ldReg = Zero, wrAddr = 0, rdAddr = 0, wrEn = False
+                    , jmpM = Nothing
+                    }
+@
+
+Next we define the CPU and its ALU:
+
+@
+cpu :: Vec 7 Value          -- ^ Register bank
+    -> (Value,Instruction)  -- ^ (Memory output, Current instruction)
+    -> ( Vec 7 Value
+       , (MemAddr,MemAddr,Bool,Value,InstrAddr)
+       )
+cpu regbank (memOut,instr) = ((regbank',(rdAddr,wrAddr,wrEn,aluOut,fromIntegral ipntr))
+  where
+    -- Current instruction pointer
+    ipntr = regbank '!!' PC
+
+    -- Decoder
+    (MachCode {..}) = case instr of
+      Compute op rx ry res -> nullCode {inputX=rx,inputY=ry,result=res,aluCode=op}
+      Branch cr a          -> nullCode {inputX=cr,jmpM=Just a}
+      Jump a               -> nullCode {aluCode=Incr,jmpM=Just a}
+      Load a r             -> nullCode {ldReg=r,rdAddr=a}
+      Store r a            -> nullCode {inputX=r,wrAddr=a,wrEn=True}
+      Nop                  -> nullCode
+
+    -- ALU
+    regX   = regbank '!!' inputX
+    regY   = regbank '!!' inputY
+    aluOut = alu aluCode regX regY
+
+    -- next instruction
+    nextPC = case jmpM of
+               Just a | aluOut /= 0 -> ipntr + a
+               _                    -> ipntr + 1
+
+    -- update registers
+    regbank' = 'replace' Zero   0
+             $ 'replace' PC     nextPC
+             $ 'replace' result aluOut
+             $ 'replace' ldReg  memOut
+             $ regbank
+
+alu Add   x y = x + y
+alu Sub   x y = x - y
+alu Incr  x _ = x + 1
+alu Imm   x _ = x
+alu CmpGt x y = if x > y then 1 else 0
+@
+
+We initially create a memory out of simple registers:
+
+@
+dataMem :: Signal MemAddr -- ^ Read address
+        -> Signal MemAddr -- ^ Write address
+        -> Signal Bool    -- ^ Write enable
+        -> Signal Value   -- ^ data in
+        -> Signal Value   -- ^ data out
+dataMem wr rd en din = 'CLaSH.Prelude.Mealy.mealy' dataMemT ('replicate' d32 0) (bundle (wr,rd,en,din))
+  where
+    dataMemT mem (wr,rd,en,din) = (mem',dout)
+      where
+        dout = mem '!!' rd
+        mem' | en        = 'replace' wr din mem
+             | otherwise = mem
+@
+
+And then connect everything:
+
+@
+system :: KnownNat n => Vec n Instruction -> Signal Value
+system instrs = memOut
+  where
+    memOut = dataMem wrAddr rdAddr wrEn aluOut
+    (rdAddr,wrAddr,wrEn,aluOut,ipntr) = 'CLaSH.Prelude.Mealy.mealyB' cpu (('replicate' d7 0),Zero) (memOut,instr)
+    instr  = 'CLaSH.Prelude.ROM.asyncRom' instrs '<$>' ipntr
+@
+
+Create a simple program that calculates the GCD of 4 and 6:
+
+@
+-- Compute GCD of 4 and 6
+prog = -- 0 := 4
+       Compute Incr Zero RegA RegA :>
+       replicate d3 (Compute Incr RegA Zero RegA) ++
+       Store RegA 0 :>
+       -- 1 := 6
+       Compute Incr Zero RegA RegA :>
+       replicate d5 (Compute Incr RegA Zero RegA) ++
+       Store RegA 1 :>
+       -- A := 4
+       Load 0 RegA :>
+       -- B := 6
+       Load 1 RegB :>
+       -- start
+       Compute CmpGt RegA RegB RegC :>
+       Branch RegC 4 :>
+       Compute CmpGt RegB RegA RegC :>
+       Branch RegC 4 :>
+       Jump 5 :>
+       -- (a > b)
+       Compute Sub RegA RegB RegA :>
+       Jump (-6) :>
+       -- (b > a)
+       Compute Sub RegB RegA RegB :>
+       Jump (-8) :>
+       -- end
+       Store RegA 2 :>
+       Load 2 RegC :>
+       Nil
+@
+
+And test our system:
+
+@
+__>>> L.take 31 $ sample $ system prog__
+[0,0,0,0,0,4,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]
+@
+
+to see that our system indeed calculates that the GCD of 6 and 4 is 2.
+
+=== Improvement 1: using @asyncRam@
+
+As you can see, it's fairly straightforward to build a memory using registers
+and read ('!!') and write ('replace') logic. This might however not result in
+the most efficient hardware structure, especially when building an ASIC.
+
+Instead it is preferable to use the 'CLaSH.Prelude.RAM.asyncRam' function which
+has the potential to be translated to a more efficient structure:
+
+@
+system2 :: KnownNat n => Vec n Instruction -> Signal Value
+system2 instrs = memOut
+  where
+    memOut = 'CLaSH.Prelude.RAM.asyncRam' d32 wrAddr rdAddr wrEn aluOut
+    (rdAddr,wrAddr,wrEn,aluOut,ipntr) = 'mealyB' cpu (('replicate' d7 0),Zero) (memOut,instr)
+    instr  = 'CLaSH.Prelude.ROM.asyncRom' instrs '<$>' ipntr
+@
+
+Again, we can simulate our system and see that it works. This time however,
+we need to drop the first few output samples, because the initial content of an
+'CLaSH.Prelude.RAM.asyncRam' is 'undefined', and consequently, the first few
+output samples are also 'undefined'.
+
+@
+__>>> L.take 26 $ L.drop 5 $ sample $ system2 prog__
+[4,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]
+@
+
+=== Improvement 2: using @blockRam@
+
+Finally we get to using 'blockRam'. On FPGAs, 'CLaSH.Prelude.RAM.asyncRam' will
+be implemented in terms of LUTs, and therefore take up logic resources. FPGAs
+also have large(r) memory structures called /Block RAMs/, which are preferred,
+especially as the memories we need for our application get bigger. The
+'blockRam' function will be translated to such a /Block RAM/.
+
+One important aspect of Block RAMs have a /synchronous/ read port, meaning that,
+unlike the behaviour of 'CLaSH.Prelude.RAM.asyncRam', given a read address @r@
+at time @t@, the value @v@ in the RAM at address @r@ is only available at time
+@t+1@.
+
+For us that means we need to change the design of our CPU. Right now, upon a
+load instruction we generate a read address for the memory, and the value at
+that read address is immediately available to be put in the register bank.
+Because we will be using a BlockRAM, the value is delayed until the next cycle.
+We hence need to also delay the register address to which the memory address
+is loaded:
+
+@
+cpu2 :: (Vec 7 Value,Reg)    -- ^ (Register bank, Load reg addr)
+     -> (Value,Instruction)  -- ^ (Memory output, Current instruction)
+     -> ( (Vec 7 Value,Reg)
+        , (MemAddr,MemAddr,Bool,Value,InstrAddr)
+        )
+cpu2 (regbank,ldRegD) (memOut,instr) = (((regbank',ldRegD'),(rdAddr,wrAddr,wrEn,aluOut,fromIntegral ipntr))
+  where
+    -- Current instruction pointer
+    ipntr = regbank '!!' PC
+
+    -- Decoder
+    (MachCode {..}) = case instr of
+      Compute op rx ry res -> nullCode {inputX=rx,inputY=ry,result=res,aluCode=op}
+      Branch cr a          -> nullCode {inputX=cr,jmpM=Just a}
+      Jump a               -> nullCode {aluCode=Incr,jmpM=Just a}
+      Load a r             -> nullCode {ldReg=r,rdAddr=a}
+      Store r a            -> nullCode {inputX=r,wrAddr=a,wrEn=True}
+      Nop                  -> nullCode
+
+    -- ALU
+    regX   = regbank '!!' inputX
+    regY   = regbank '!!' inputY
+    aluOut = alu aluCode regX regY
+
+    -- next instruction
+    nextPC = case jmpM of
+               Just a | aluOut /= 0 -> ipntr + a
+               _                    -> ipntr + 1
+
+    -- update registers
+    ldRegD'  = ldReg -- Delay the ldReg by 1 cycle
+    regbank' = 'replace' Zero   0
+             $ 'replace' PC     nextPC
+             $ 'replace' result aluOut
+             $ 'replace' ldRegD memOut
+             $ regbank
+@
+
+We can now finally instantiate our system with a 'blockRam':
+
+@
+system3 :: KnownNat n => Vec n Instruction -> Signal Value
+system3 instrs = memOut
+  where
+    memOut = 'blockRam' (replicate d32 0) wrAddr rdAddr wrEn aluOut
+    (rdAddr,wrAddr,wrEn,aluOut,ipntr) = 'mealyB' cpu (('replicate' d7 0),Zero) (memOut,instr)
+    instr  = 'CLaSH.Prelude.ROM.asyncRom' instrs '<$>' ipntr
+@
+
+We are, however, not done. We will also need to update our program. The reason
+being that values that we try to load in our registers won't be loaded into the
+register until the next cycle. This is a problem when the next instruction
+immediately depended on this memory value. In our case, this was only the case
+when the loaded the value @6@, which was stored at address @1@, into @RegB@.
+Our updated program is thus:
+
+@
+prog2 = -- 0 := 4
+       Compute Incr Zero RegA RegA :>
+       replicate d3 (Compute Incr RegA Zero RegA) ++
+       Store RegA 0 :>
+       -- 1 := 6
+       Compute Incr Zero RegA RegA :>
+       replicate d5 (Compute Incr RegA Zero RegA) ++
+       Store RegA 1 :>
+       -- A := 4
+       Load 0 RegA :>
+       -- B := 6
+       Load 1 RegB :>
+       Nop :> -- Extra NOP
+       -- start
+       Compute CmpGt RegA RegB RegC :>
+       Branch RegC 4 :>
+       Compute CmpGt RegB RegA RegC :>
+       Branch RegC 4 :>
+       Jump 5 :>
+       -- (a > b)
+       Compute Sub RegA RegB RegA :>
+       Jump (-6) :>
+       -- (b > a)
+       Compute Sub RegB RegA RegB :>
+       Jump (-8) :>
+       -- end
+       Store RegA 2 :>
+       Load 2 RegC :>
+       Nil
+@
+
+When we simulate our system we see that it works. This time however,
+we need to drop the first few sample, because the initial output of a
+'blockRam' is 'undefined', and consequently, the first output sample is
+also 'undefined'.
+
+@
+__>>> L.take 33 $ L.tail $ sample $ system3 prog2__
+[4,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]
+@
+
+This concludes the short introduction to using 'blockRam'.
+
 -}
-module CLaSH.Prelude.BlockRam where
+module CLaSH.Prelude.BlockRam
+  ( -- * BlockRAM synchronised to the system clock
+    blockRam
+  , blockRamPow2
+    -- * BlockRAM synchronised to an arbitrary clock
+  , blockRam'
+  , blockRamPow2'
+    -- * Internal
+  , blockRam#
+  )
+where
 
+import Control.Monad          (when)
+import Control.Monad.ST.Lazy  (ST,runST)
+import Data.Array.MArray.Safe (newListArray,readArray,writeArray)
+import Data.Array.ST.Safe     (STArray)
 import GHC.TypeLits           (KnownNat, type (^))
-import Prelude                hiding ((!!))
 
-import CLaSH.Prelude.Moore    (moore')
 import CLaSH.Signal           (Signal)
-import CLaSH.Signal.Explicit  (Signal', SClock, systemClock)
+import CLaSH.Signal.Explicit  (Signal', SClock, register', systemClock)
 import CLaSH.Signal.Bundle    (bundle')
 import CLaSH.Sized.Unsigned   (Unsigned)
-import CLaSH.Sized.Vector     (Vec, (!!), replace)
+import CLaSH.Sized.Vector     (Vec, maxIndex, toList)
 
 {-# INLINE blockRam #-}
 -- | Create a blockRAM with space for @n@ elements.
@@ -32,15 +378,20 @@
 --        -> 'Signal' 'CLaSH.Sized.BitVector.Bit' -> Signal 'CLaSH.Sized.BitVector.Bit'
 -- bram40 = 'blockRam' ('CLaSH.Sized.Vector.replicate' d40 1)
 -- @
-blockRam :: (KnownNat n, KnownNat m)
-         => Vec n a             -- ^ Initial content of the BRAM, also
-                                -- determines the size, @n@, of the BRAM.
-                                --
-                                -- __NB__: __MUST__ be a constant.
-         -> Signal (Unsigned m) -- ^ Write address @w@
-         -> Signal (Unsigned m) -- ^ Read address @r@
-         -> Signal Bool         -- ^ Write enable
-         -> Signal a            -- ^ Value to write (at address @w@)
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
+blockRam :: (KnownNat n, Enum addr)
+         => Vec n a     -- ^ Initial content of the BRAM, also
+                        -- determines the size, @n@, of the BRAM.
+                        --
+                        -- __NB__: __MUST__ be a constant.
+         -> Signal addr -- ^ Write address @w@
+         -> Signal addr -- ^ Read address @r@
+         -> Signal Bool -- ^ Write enable
+         -> Signal a    -- ^ Value to write (at address @w@)
          -> Signal a
          -- ^ Value of the @blockRAM@ at address @r@ from the previous clock
          -- cycle
@@ -57,6 +408,11 @@
 --        -> 'Signal' 'CLaSH.Sized.BitVector.Bit' -> 'Signal' 'CLaSH.Sized.BitVector.Bit'
 -- bram32 = 'blockRamPow2' ('CLaSH.Sized.Vector.replicate' d32 1)
 -- @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
 blockRamPow2 :: (KnownNat (2^n), KnownNat n)
              => Vec (2^n) a         -- ^ Initial content of the BRAM, also
                                     -- determines the size, @2^n@, of the BRAM.
@@ -71,7 +427,7 @@
              -- cycle
 blockRamPow2 = blockRam
 
-{-# NOINLINE blockRam' #-}
+{-# INLINE blockRam' #-}
 -- | Create a blockRAM with space for @n@ elements
 --
 -- * __NB__: Read value is delayed by 1 cycle
@@ -87,27 +443,26 @@
 --        -> 'Signal'' ClkA Bool -> 'Signal'' ClkA 'CLaSH.Sized.BitVector.Bit' -> ClkA 'Signal'' 'CLaSH.Sized.BitVector.Bit'
 -- bram40 = 'blockRam'' clkA100 ('CLaSH.Sized.Vector.replicate' d40 1)
 -- @
-blockRam' :: (KnownNat n, KnownNat m)
-          => SClock clk               -- ^ 'Clock' to synchronize to
-          -> Vec n a                  -- ^ Initial content of the BRAM, also
-                                      -- determines the size, @n@, of the BRAM.
-                                      --
-                                      -- __NB__: __MUST__ be a constant.
-          -> Signal' clk (Unsigned m) -- ^ Write address @w@
-          -> Signal' clk (Unsigned m) -- ^ Read address @r@
-          -> Signal' clk Bool         -- ^ Write enable
-          -> Signal' clk a            -- ^ Value to write (at address @w@)
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
+blockRam' :: (KnownNat n, Enum addr)
+          => SClock clk       -- ^ 'Clock' to synchronize to
+          -> Vec n a          -- ^ Initial content of the BRAM, also
+                              -- determines the size, @n@, of the BRAM.
+                              --
+                              -- __NB__: __MUST__ be a constant.
+          -> Signal' clk addr -- ^ Write address @w@
+          -> Signal' clk addr -- ^ Read address @r@
+          -> Signal' clk Bool -- ^ Write enable
+          -> Signal' clk a    -- ^ Value to write (at address @w@)
           -> Signal' clk a
           -- ^ Value of the @blockRAM@ at address @r@ from the previous clock
           -- cycle
-blockRam' clk binit wr rd en din =
-    moore' clk bram' snd (binit,undefined) (bundle' clk (wr,rd,en,din))
-  where
-    bram' (ram,_) (w,r,e,d) = (ram',o')
-      where
-        ram' | e         = replace w d ram
-             | otherwise = ram
-        o'               = ram !! r
+blockRam' clk content wr rd en din = blockRam# clk content (fromEnum <$> wr)
+                                               (fromEnum <$> rd) en din
 
 {-# INLINE blockRamPow2' #-}
 -- | Create a blockRAM with space for 2^@n@ elements
@@ -125,6 +480,11 @@
 --        -> 'Signal'' ClkA Bool -> 'Signal'' ClkA 'CLaSH.Sized.BitVector.Bit' -> Signal' ClkA 'CLaSH.Sized.BitVector.Bit'
 -- bram32 = 'blockRamPow2'' clkA100 ('CLaSH.Sized.Vector.replicate' d32 1)
 -- @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
 blockRamPow2' :: (KnownNat n, KnownNat (2^n))
               => SClock clk               -- ^ 'Clock' to synchronize to
               -> Vec (2^n) a              -- ^ Initial content of the BRAM, also
@@ -140,3 +500,31 @@
               -- ^ Value of the @blockRAM@ at address @r@ from the previous
               -- clock cycle
 blockRamPow2' = blockRam'
+
+{-# NOINLINE blockRam# #-}
+-- | blockRAM primitive
+blockRam# :: KnownNat n
+          => SClock clk       -- ^ 'Clock' to synchronize to
+          -> Vec n a          -- ^ Initial content of the BRAM, also
+                              -- determines the size, @n@, of the BRAM.
+                              --
+                              -- __NB__: __MUST__ be a constant.
+          -> Signal' clk Int  -- ^ Write address @w@
+          -> Signal' clk Int  -- ^ Read address @r@
+          -> Signal' clk Bool -- ^ Write enable
+          -> Signal' clk a    -- ^ Value to write (at address @w@)
+          -> Signal' clk a
+          -- ^ Value of the @blockRAM@ at address @r@ from the previous clock
+          -- cycle
+blockRam# clk content wr rd en din = register' clk undefined dout
+  where
+    szI  = fromInteger $ maxIndex content
+    dout = runST $ do
+      arr <- newListArray (0,szI) (toList content)
+      traverse (ramT arr) (bundle' clk (wr,rd,en,din))
+
+    ramT :: STArray s Int e -> (Int,Int,Bool,e) -> ST s e
+    ramT ram (w,r,e,d) = do
+      d' <- readArray ram r
+      when e (writeArray ram w d)
+      return d'
diff --git a/src/CLaSH/Prelude/BlockRam/File.hs b/src/CLaSH/Prelude/BlockRam/File.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/BlockRam/File.hs
@@ -0,0 +1,300 @@
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE MagicHash           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
+
+{-# LANGUAGE Unsafe #-}
+
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+Copyright  :  (C) 2015, University of Twente
+License    :  BSD2 (see the file LICENSE)
+Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+= Initialising a BlockRAM with a data file #usingramfiles#
+
+BlockRAM primitives that can be initialised with a data file. The BNF grammar
+for this data file is simple:
+
+@
+FILE = LINE+
+LINE = BIT+
+BIT  = '0'
+     | '1'
+@
+
+Consecutive @LINE@s correspond to consecutive memory addresses starting at @0@.
+For example, a data file @memory.bin@ containing the 9-bit unsigned number
+@7@ to @13@ looks like:
+
+@
+000000111
+000001000
+000001001
+000001010
+000001011
+000001100
+000001101
+@
+
+We can instantiate a BlockRAM using the content of the above file like so:
+
+@
+topEntity :: Signal (Unsigned 3) -> Signal (Unsigned 9)
+topEntity rd = 'CLaSH.Class.BitPack.unpack' '<$>' 'blockRamFile' d7 \"memory.bin\" 0 rd (signal False) 0
+@
+
+In the example above, we basically treat the BlockRAM as an synchronous ROM.
+We can see that it works as expected:
+
+@
+__>>> import qualified Data.List as L__
+__>>> L.tail $ sampleN 4 $ topEntity (fromList [3..5])__
+[10,11,12]
+@
+
+However, we can also interpret the same data as a tuple of a 6-bit unsigned
+number, and a 3-bit signed number:
+
+@
+topEntity2 :: Signal (Unsigned 3) -> Signal (Unsigned 6,Signed 3)
+topEntity2 rd = 'CLaSH.Class.BitPack.unpack' '<$>' 'blockRamFile' d7 \"memory.bin\" 0 rd (signal False) 0
+@
+
+And then we would see:
+
+@
+__>>> import qualified Data.List as L__
+__>>> L.tail $ sampleN 4 $ topEntity2 (fromList [3..5])__
+[(1,2),(1,3)(1,-4)]
+@
+
+-}
+module CLaSH.Prelude.BlockRam.File
+  ( -- * BlockRAM synchronised to the system clock
+    blockRamFile
+  , blockRamFilePow2
+    -- * BlockRAM synchronised to an arbitrary clock
+  , blockRamFile'
+  , blockRamFilePow2'
+    -- * Internal
+  , blockRamFile#
+  , initMem
+  )
+where
+
+
+import Control.Monad         (when)
+import Control.Monad.ST.Lazy (ST,runST)
+import Data.Array.MArray     (newListArray,readArray,writeArray)
+import Data.Array.ST         (STArray)
+import Data.Char             (digitToInt)
+import Data.Maybe            (listToMaybe)
+import GHC.TypeLits          (KnownNat, type (^))
+import Numeric               (readInt)
+import System.IO.Unsafe      (unsafePerformIO)
+
+import CLaSH.Promoted.Nat    (SNat,snat,snatToInteger)
+import CLaSH.Sized.BitVector (BitVector)
+import CLaSH.Signal          (Signal)
+import CLaSH.Signal.Explicit (Signal', SClock, register', systemClock)
+import CLaSH.Signal.Bundle   (bundle')
+import CLaSH.Sized.Unsigned  (Unsigned)
+
+{-# INLINE blockRamFile #-}
+-- | Create a blockRAM with space for @n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
+-- * See "CLaSH.Prelude.BlockRam.File#usingramfiles" for more information on how
+-- to instantiate a Block RAM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+blockRamFile :: (KnownNat m, Enum addr)
+             => SNat n               -- ^ Size of the blockRAM
+             -> FilePath             -- ^ File describing the initial content
+                                     -- of the blockRAM
+             -> Signal addr          -- ^ Write address @w@
+             -> Signal addr          -- ^ Read address @r@
+             -> Signal Bool          -- ^ Write enable
+             -> Signal (BitVector m) -- ^ Value to write (at address @w@)
+             -> Signal (BitVector m)
+             -- ^ Value of the @blockRAM@ at address @r@ from the previous clock
+             -- cycle
+blockRamFile = blockRamFile' systemClock
+
+{-# INLINE blockRamFilePow2 #-}
+-- | Create a blockRAM with space for 2^@n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
+-- * See "CLaSH.Prelude.BlockRam.File#usingramfiles" for more information on how
+-- to instantiate a Block RAM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+blockRamFilePow2 :: forall n m . (KnownNat m, KnownNat n, KnownNat (2^n))
+                 => FilePath             -- ^ File describing the initial
+                                         -- content of the blockRAM
+                 -> Signal (Unsigned n)  -- ^ Write address @w@
+                 -> Signal (Unsigned n)  -- ^ Read address @r@
+                 -> Signal Bool          -- ^ Write enable
+                 -> Signal (BitVector m) -- ^ Value to write (at address @w@)
+                 -> Signal (BitVector m)
+                 -- ^ Value of the @blockRAM@ at address @r@ from the previous
+                 -- clock cycle
+blockRamFilePow2 = blockRamFile' systemClock (snat :: SNat (2^n))
+
+{-# INLINE blockRamFilePow2' #-}
+-- | Create a blockRAM with space for 2^@n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
+-- * See "CLaSH.Prelude.BlockRam.File#usingramfiles" for more information on how
+-- to instantiate a Block RAM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+blockRamFilePow2' :: forall clk n m . (KnownNat m, KnownNat n, KnownNat (2^n))
+                  => SClock clk                -- ^ 'Clock' to synchronize to
+                  -> FilePath                  -- ^ File describing the initial
+                                               -- content of the blockRAM
+                  -> Signal' clk (Unsigned n)  -- ^ Write address @w@
+                  -> Signal' clk (Unsigned n)  -- ^ Read address @r@
+                  -> Signal' clk Bool          -- ^ Write enable
+                  -> Signal' clk (BitVector m) -- ^ Value to write (at address @w@)
+                  -> Signal' clk (BitVector m)
+                  -- ^ Value of the @blockRAM@ at address @r@ from the previous
+                  -- clock cycle
+blockRamFilePow2' clk = blockRamFile' clk (snat :: SNat (2^n))
+
+{-# INLINE blockRamFile' #-}
+-- | Create a blockRAM with space for @n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- Block RAM.
+-- * See "CLaSH.Prelude.BlockRam.File#usingramfiles" for more information on how
+-- to instantiate a Block RAM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+blockRamFile' :: (KnownNat m, Enum addr)
+              => SClock clk                -- ^ 'Clock' to synchronize to
+              -> SNat n                    -- ^ Size of the blockRAM
+              -> FilePath                  -- ^ File describing the initial
+                                           -- content of the blockRAM
+              -> Signal' clk addr          -- ^ Write address @w@
+              -> Signal' clk addr          -- ^ Read address @r@
+              -> Signal' clk Bool          -- ^ Write enable
+              -> Signal' clk (BitVector m) -- ^ Value to write (at address @w@)
+              -> Signal' clk (BitVector m)
+              -- ^ Value of the @blockRAM@ at address @r@ from the previous
+              -- clock cycle
+blockRamFile' clk sz file wr rd en din = blockRamFile# clk sz file
+                                                       (fromEnum <$> wr)
+                                                       (fromEnum <$> rd)
+                                                       en din
+
+{-# NOINLINE blockRamFile# #-}
+-- | blockRamFile primitive
+blockRamFile# :: KnownNat m
+              => SClock clk                -- ^ 'Clock' to synchronize to
+              -> SNat n                    -- ^ Size of the blockRAM
+              -> FilePath                  -- ^ File describing the initial
+                                           -- content of the blockRAM
+              -> Signal' clk Int           -- ^ Write address @w@
+              -> Signal' clk Int           -- ^ Read address @r@
+              -> Signal' clk Bool          -- ^ Write enable
+              -> Signal' clk (BitVector m) -- ^ Value to write (at address @w@)
+              -> Signal' clk (BitVector m)
+              -- ^ Value of the @blockRAM@ at address @r@ from the previous
+              -- clock cycle
+blockRamFile# clk sz file wr rd en din = register' clk undefined dout
+  where
+    szI  = fromInteger $ snatToInteger sz
+    dout = runST $ do
+      arr <- newListArray (0,szI-1) (initMem file)
+      traverse (ramT arr) (bundle' clk (wr,rd,en,din))
+
+    ramT :: STArray s Int e -> (Int,Int,Bool,e) -> ST s e
+    ramT ram (w,r,e,d) = do
+      d' <- readArray ram r
+      when e (writeArray ram w d)
+      return d'
+
+{-# NOINLINE initMem #-}
+-- | __NB:__ Not synthesisable
+initMem :: KnownNat n => FilePath -> [BitVector n]
+initMem = unsafePerformIO . fmap (map parseBV . lines) . readFile
+  where
+    parseBV s = case parseBV' s of
+                  Just i  -> fromInteger i
+                  Nothing -> error ("Failed to parse: " ++ s)
+    parseBV' = fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToInt
diff --git a/src/CLaSH/Prelude/Explicit.hs b/src/CLaSH/Prelude/Explicit.hs
--- a/src/CLaSH/Prelude/Explicit.hs
+++ b/src/CLaSH/Prelude/Explicit.hs
@@ -26,15 +26,31 @@
   , moore'
   , mooreB'
   , registerB'
+    -- * Synchronizer circuits for safe clock domain crossings
+  , dualFlipFlopSynchronizer
+  , asyncFIFOSynchronizer
+    -- * ROMs
+  , rom'
+  , romPow2'
+    -- ** ROMs initialised with a data file
+  , romFile'
+  , romFilePow2'
+    -- * RAM primitives with a combinational read port
+  , asyncRam'
+  , asyncRamPow2'
     -- * BlockRAM primitives
   , blockRam'
   , blockRamPow2'
+    -- ** BlockRAM primitives initialised with a data file
+  , blockRamFile'
+  , blockRamFilePow2'
     -- * Utility functions
   , window'
   , windowD'
   , isRising'
   , isFalling'
     -- * Testbench functions
+  , assert'
   , stimuliGenerator'
   , outputVerifier'
     -- * Exported modules
@@ -43,45 +59,24 @@
   )
 where
 
-import Control.Applicative     (liftA2)
-import Data.Default            (Default (..))
-import GHC.TypeLits            (KnownNat, type (+), natVal)
-import Prelude                 hiding (repeat)
+import Data.Default                 (Default (..))
+import GHC.TypeLits                 (KnownNat, type (+), natVal)
+import Prelude                      hiding (repeat)
 
-import CLaSH.Prelude.BlockRam  (blockRam', blockRamPow2')
-import CLaSH.Prelude.Mealy     (mealy', mealyB')
-import CLaSH.Prelude.Moore     (moore', mooreB')
-import CLaSH.Prelude.Testbench (stimuliGenerator', outputVerifier')
+import CLaSH.Prelude.Explicit.Safe
+import CLaSH.Prelude.BlockRam.File (blockRamFile', blockRamFilePow2')
+import CLaSH.Prelude.ROM.File      (romFile', romFilePow2')
+import CLaSH.Prelude.Testbench     (assert', stimuliGenerator', outputVerifier')
 import CLaSH.Signal.Explicit
-import CLaSH.Sized.Vector      (Vec (..), (+>>), asNatProxy, repeat)
+import CLaSH.Sized.Vector          (Vec (..), (+>>), asNatProxy, repeat)
 
 -- $setup
 -- >>> :set -XDataKinds
 -- >>> type ClkA = Clk "A" 100
 -- >>> let clkA = sclock :: SClock ClkA
--- >>> let rP = registerB' clkA (8::Int,8::Int)
 -- >>> let window4 = window' clkA :: Signal' ClkA Int -> Vec 4 (Signal' ClkA Int)
 -- >>> let windowD3 = windowD' clkA :: Signal' ClkA Int -> Vec 3 (Signal' ClkA Int)
 
-{-# INLINE registerB' #-}
--- | Create a 'register' function for product-type like signals (e.g.
--- @('Signal' a, 'Signal' b)@)
---
--- @
--- type ClkA = 'Clk' \"A\" 100
---
--- clkA :: 'SClock' ClkA
--- clkA = 'sclock'
---
--- rP :: ('Signal'' ClkA Int, 'Signal'' ClkA Int) -> ('Signal'' ClkA Int, 'Signal'' ClkA Int)
--- rP = 'registerB'' clkA (8,8)
--- @
---
--- >>> simulateB' clkA clkA rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
--- [(8,8),(1,1),(2,2),(3,3)...
-registerB' :: Bundle a => SClock clk -> a -> Unbundled' clk a -> Unbundled' clk a
-registerB' clk i = unbundle' clk Prelude.. register' clk i Prelude.. bundle' clk
-
 {-# INLINABLE window' #-}
 -- | Give a window over a 'Signal''
 --
@@ -134,27 +129,3 @@
   where
     prev = registerB' clk (repeat def) next
     next = x +>> prev
-
-{-# INLINABLE isRising' #-}
--- | Give a pulse when the 'Signal'' goes from 'minBound' to 'maxBound'
-isRising' :: (Bounded a, Eq a)
-          => SClock clk
-          -> a -- ^ Starting value
-          -> Signal' clk a
-          -> Signal' clk Bool
-isRising' clk is s = liftA2 edgeDetect prev s
-  where
-    prev = register' clk is s
-    edgeDetect old new = old == minBound && new == maxBound
-
-{-# INLINABLE isFalling' #-}
--- | Give a pulse when the 'Signal'' goes from 'maxBound' to 'minBound'
-isFalling' :: (Bounded a, Eq a)
-           => SClock clk
-           -> a -- ^ Starting value
-           -> Signal' clk a
-           -> Signal' clk Bool
-isFalling' clk is s = liftA2 edgeDetect prev s
-  where
-    prev = register' clk is s
-    edgeDetect old new = old == maxBound && new == minBound
diff --git a/src/CLaSH/Prelude/Explicit/Safe.hs b/src/CLaSH/Prelude/Explicit/Safe.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/Explicit/Safe.hs
@@ -0,0 +1,111 @@
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-# LANGUAGE Safe #-}
+
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+Copyright  :  (C) 2013-2015, University of Twente
+License    :  BSD2 (see the file LICENSE)
+Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+__This is the <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/safe-haskell.html Safe> API only of "CLaSH.Prelude.Explicit"__
+
+This module defines the explicitly clocked counterparts of the functions
+defined in "CLaSH.Prelude".
+
+This module uses the explicitly clocked 'Signal'' synchronous signals, as
+opposed to the implicitly clocked 'Signal' used in "CLaSH.Prelude". Take a
+look at "CLaSH.Signal.Explicit" to see how you can make multi-clock designs
+using explicitly clocked signals.
+-}
+module CLaSH.Prelude.Explicit.Safe
+  ( -- * Creating synchronous sequential circuits
+    mealy'
+  , mealyB'
+  , moore'
+  , mooreB'
+  , registerB'
+    -- * Synchronizer circuits for safe clock domain crossing
+  , dualFlipFlopSynchronizer
+  , asyncFIFOSynchronizer
+    -- * ROMs
+  , rom'
+  , romPow2'
+    -- * RAM primitives with a combinational read port
+  , asyncRam'
+  , asyncRamPow2'
+    -- * BlockRAM primitives
+  , blockRam'
+  , blockRamPow2'
+    -- * Utility functions
+  , isRising'
+  , isFalling'
+    -- * Exported modules
+    -- ** Explicitly clocked synchronous signals
+  , module CLaSH.Signal.Explicit
+  )
+where
+
+import Control.Applicative        (liftA2)
+import Prelude                    hiding (repeat)
+
+import CLaSH.Prelude.BlockRam     (blockRam', blockRamPow2')
+import CLaSH.Prelude.Mealy        (mealy', mealyB')
+import CLaSH.Prelude.Moore        (moore', mooreB')
+import CLaSH.Prelude.RAM          (asyncRam',asyncRamPow2')
+import CLaSH.Prelude.ROM          (rom', romPow2')
+import CLaSH.Prelude.Synchronizer (dualFlipFlopSynchronizer,
+                                   asyncFIFOSynchronizer)
+import CLaSH.Signal.Explicit
+
+-- $setup
+-- >>> :set -XDataKinds
+-- >>> type ClkA = Clk "A" 100
+-- >>> let clkA = sclock :: SClock ClkA
+-- >>> let rP = registerB' clkA (8::Int,8::Int)
+
+{-# INLINE registerB' #-}
+-- | Create a 'register' function for product-type like signals (e.g.
+-- @('Signal' a, 'Signal' b)@)
+--
+-- @
+-- type ClkA = 'Clk' \"A\" 100
+--
+-- clkA :: 'SClock' ClkA
+-- clkA = 'sclock'
+--
+-- rP :: ('Signal'' ClkA Int, 'Signal'' ClkA Int) -> ('Signal'' ClkA Int, 'Signal'' ClkA Int)
+-- rP = 'registerB'' clkA (8,8)
+-- @
+--
+-- >>> simulateB' clkA clkA rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
+-- [(8,8),(1,1),(2,2),(3,3)...
+registerB' :: Bundle a => SClock clk -> a -> Unbundled' clk a -> Unbundled' clk a
+registerB' clk i = unbundle' clk Prelude.. register' clk i Prelude.. bundle' clk
+
+{-# INLINABLE isRising' #-}
+-- | Give a pulse when the 'Signal'' goes from 'minBound' to 'maxBound'
+isRising' :: (Bounded a, Eq a)
+          => SClock clk
+          -> a -- ^ Starting value
+          -> Signal' clk a
+          -> Signal' clk Bool
+isRising' clk is s = liftA2 edgeDetect prev s
+  where
+    prev = register' clk is s
+    edgeDetect old new = old == minBound && new == maxBound
+
+{-# INLINABLE isFalling' #-}
+-- | Give a pulse when the 'Signal'' goes from 'maxBound' to 'minBound'
+isFalling' :: (Bounded a, Eq a)
+           => SClock clk
+           -> a -- ^ Starting value
+           -> Signal' clk a
+           -> Signal' clk Bool
+isFalling' clk is s = liftA2 edgeDetect prev s
+  where
+    prev = register' clk is s
+    edgeDetect old new = old == maxBound && new == minBound
diff --git a/src/CLaSH/Prelude/RAM.hs b/src/CLaSH/Prelude/RAM.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/RAM.hs
@@ -0,0 +1,149 @@
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE MagicHash           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies        #-}
+{-# LANGUAGE TypeOperators       #-}
+
+{-# LANGUAGE Safe #-}
+
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+Copyright  :  (C) 2015, University of Twente
+License    :  BSD2 (see the file LICENSE)
+Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+RAM primitives with a combinational read port.
+-}
+module CLaSH.Prelude.RAM
+  ( -- * RAM synchronised to the system clock
+    asyncRam
+  , asyncRamPow2
+    -- * RAM synchronised to an arbitrary clock
+  , asyncRam'
+  , asyncRamPow2'
+    -- * Internal
+  , asyncRam#
+  )
+where
+
+import Control.Monad          (when)
+import Control.Monad.ST.Lazy  (ST,runST)
+import Data.Array.MArray.Safe (newArray_,readArray,writeArray)
+import Data.Array.ST.Safe     (STArray)
+import GHC.TypeLits           (KnownNat, type (^))
+
+import CLaSH.Promoted.Nat     (SNat,snat,snatToInteger)
+import CLaSH.Signal           (Signal)
+import CLaSH.Signal.Bundle    (bundle')
+import CLaSH.Signal.Explicit  (Signal', SClock, systemClock, unsafeSynchronizer)
+import CLaSH.Sized.Unsigned   (Unsigned)
+
+{-# INLINE asyncRam #-}
+-- | Create a RAM with space for @n@ elements.
+--
+-- * __NB__: Initial content of the RAM is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- RAM.
+asyncRam :: (KnownNat n, Enum addr)
+         => SNat n      -- ^ Size @n@ of the RAM
+         -> Signal addr -- ^ Write address @w@
+         -> Signal addr -- ^ Read address @r@
+         -> Signal Bool -- ^ Write enable
+         -> Signal a    -- ^ Value to write (at address @w@)
+         -> Signal a    -- ^ Value of the @RAM@ at address @r@
+asyncRam = asyncRam' systemClock systemClock
+
+{-# INLINE asyncRamPow2 #-}
+-- | Create a RAM with space for 2^@n@ elements
+--
+-- * __NB__: Initial content of the RAM is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- RAM.
+asyncRamPow2 :: forall n a . (KnownNat (2^n), KnownNat n)
+             => Signal (Unsigned n) -- ^ Write address @w@
+             -> Signal (Unsigned n) -- ^ Read address @r@
+             -> Signal Bool         -- ^ Write enable
+             -> Signal a            -- ^ Value to write (at address @w@)
+             -> Signal a            -- ^ Value of the @RAM@ at address @r@
+asyncRamPow2 = asyncRam' systemClock systemClock (snat :: SNat (2^n))
+
+{-# INLINE asyncRamPow2' #-}
+-- | Create a RAM with space for 2^@n@ elements
+--
+-- * __NB__: Initial content of the RAM is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- RAM.
+asyncRamPow2' :: forall wclk rclk n a .
+                 (KnownNat n, KnownNat (2^n))
+              => SClock wclk               -- ^ 'Clock' to which to synchronise
+                                           -- the write port of the RAM
+              -> SClock rclk               -- ^ 'Clock' to which the read
+                                           -- address signal, @r@, is
+                                           -- synchronised
+              -> Signal' wclk (Unsigned n) -- ^ Write address @w@
+              -> Signal' rclk (Unsigned n) -- ^ Read address @r@
+              -> Signal' wclk Bool         -- ^ Write enable
+              -> Signal' wclk a            -- ^ Value to write (at address @w@)
+              -> Signal' rclk a
+              -- ^ Value of the @RAM@ at address @r@
+asyncRamPow2' wclk rclk = asyncRam' wclk rclk (snat :: SNat (2^n))
+
+{-# INLINE asyncRam' #-}
+-- | Create a RAM with space for @n@ elements
+--
+-- * __NB__: Initial content of the RAM is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.BlockRam#usingrams" for more information on how to use a
+-- RAM.
+asyncRam' :: (KnownNat n, Enum addr)
+          => SClock wclk       -- ^ 'Clock' to which to synchronise the write
+                               -- port of the RAM
+          -> SClock rclk       -- ^ 'Clock' to which the read address signal,
+                               -- @r@, is synchronised
+          -> SNat n            -- ^ Size @n@ of the RAM
+          -> Signal' wclk addr -- ^ Write address @w@
+          -> Signal' rclk addr -- ^ Read address @r@
+          -> Signal' wclk Bool -- ^ Write enable
+          -> Signal' wclk a    -- ^ Value to write (at address @w@)
+          -> Signal' rclk a    -- ^ Value of the @RAM@ at address @r@
+asyncRam' wclk rclk sz wr rd en din = asyncRam# wclk rclk sz (fromEnum <$> wr)
+                                                (fromEnum <$> rd) en din
+
+{-# NOINLINE asyncRam# #-}
+-- | RAM primitive
+asyncRam# :: SClock wclk       -- ^ 'Clock' to which to synchronise the write
+                               -- port of the RAM
+          -> SClock rclk       -- ^ 'Clock' to which the read address signal,
+                               -- @r@, is synchronised
+          -> SNat n            -- ^ Size @n@ of the RAM
+          -> Signal' wclk Int  -- ^ Write address @w@
+          -> Signal' rclk Int  -- ^ Read address @r@
+          -> Signal' wclk Bool -- ^ Write enable
+          -> Signal' wclk a    -- ^ Value to write (at address @w@)
+          -> Signal' rclk a    -- ^ Value of the @RAM@ at address @r@
+asyncRam# wclk rclk sz wr rd en din = unsafeSynchronizer wclk rclk dout
+  where
+    szI  = fromInteger $ snatToInteger sz
+    rd'  = unsafeSynchronizer rclk wclk rd
+    dout = runST $ do
+      arr <- newArray_ (0,szI-1)
+      traverse (ramT arr) (bundle' wclk (wr,rd',en,din))
+
+    ramT :: STArray s Int e -> (Int,Int,Bool,e) -> ST s e
+    ramT ram (w,r,e,d) = do
+      d' <- readArray ram r
+      when e (writeArray ram w d)
+      return d'
diff --git a/src/CLaSH/Prelude/ROM.hs b/src/CLaSH/Prelude/ROM.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/ROM.hs
@@ -0,0 +1,173 @@
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MagicHash        #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-# LANGUAGE Safe #-}
+
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+Copyright  :  (C) 2015, University of Twente
+License    :  BSD2 (see the file LICENSE)
+Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+ROMs
+-}
+module CLaSH.Prelude.ROM
+  ( -- * Asynchronous ROM
+    asyncRom
+  , asyncRomPow2
+    -- * Synchronous ROM synchronised to the system clock
+  , rom
+  , romPow2
+    -- * Synchronous ROM synchronised to an arbitrary clock
+  , rom'
+  , romPow2'
+    -- * Internal
+  , asyncRom#
+  , rom#
+  )
+where
+
+import Data.Array             ((!),listArray)
+import GHC.TypeLits           (KnownNat, type (^))
+
+import CLaSH.Signal           (Signal)
+import CLaSH.Signal.Explicit  (Signal', SClock, systemClock)
+import CLaSH.Sized.Unsigned   (Unsigned)
+import CLaSH.Signal.Explicit  (register')
+import CLaSH.Sized.Vector     (Vec, maxIndex, toList)
+
+{-# INLINE asyncRom #-}
+-- | An asynchronous/combinational ROM with space for @n@ elements
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" and "CLaSH.Prelude.BlockRam#usingrams"
+-- for ideas on how to use ROMs and RAMs
+asyncRom :: (KnownNat n, Enum addr)
+         => Vec n a -- ^ ROM content
+                    --
+                    -- __NB:__ must be a constant
+         -> addr    -- ^ Read address @rd@
+         -> a       -- ^ The value of the ROM at address @rd@
+asyncRom content rd = asyncRom# content (fromEnum rd)
+
+{-# INLINE asyncRomPow2 #-}
+-- | An asynchronous/combinational ROM with space for 2^@n@ elements
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" and "CLaSH.Prelude.BlockRam#usingrams"
+-- for ideas on how to use ROMs and RAMs
+asyncRomPow2 :: (KnownNat (2^n), KnownNat n)
+             => Vec (2^n) a -- ^ ROM content
+                            --
+                            -- __NB:__ must be a constant
+             -> Unsigned n  -- ^ Read address @rd@
+             -> a           -- ^ The value of the ROM at address @rd@
+asyncRomPow2 = asyncRom
+
+{-# NOINLINE asyncRom# #-}
+-- | asyncROM primitive
+asyncRom# :: KnownNat n
+          => Vec n a  -- ^ ROM content
+                      --
+                      -- __NB:__ must be a constant
+          -> Int      -- ^ Read address @rd@
+          -> a        -- ^ The value of the ROM at address @rd@
+asyncRom# content rd = arr ! rd
+  where
+    szI = fromInteger (maxIndex content)
+    arr = listArray (0,szI) (toList content)
+
+{-# INLINE rom #-}
+-- | A ROM with a synchronous read port, with space for @n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" and "CLaSH.Prelude.BlockRam#usingrams"
+-- for ideas on how to use ROMs and RAMs
+rom :: (KnownNat n, KnownNat m)
+    => Vec n a               -- ^ ROM content
+                             --
+                             -- __NB:__ must be a constant
+    -> Signal (Unsigned m)   -- ^ Read address @rd@
+    -> Signal a              -- ^ The value of the ROM at address @rd@
+rom = rom' systemClock
+
+{-# INLINE romPow2 #-}
+-- | A ROM with a synchronous read port, with space for 2^@n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" and "CLaSH.Prelude.BlockRam#usingrams"
+-- for ideas on how to use ROMs and RAMs
+romPow2 :: (KnownNat (2^n), KnownNat n)
+        => Vec (2^n) a         -- ^ ROM content
+                               --
+                               -- __NB:__ must be a constant
+        -> Signal (Unsigned n) -- ^ Read address @rd@
+        -> Signal a            -- ^ The value of the ROM at address @rd@
+romPow2 = rom' systemClock
+
+{-# INLINE romPow2' #-}
+-- | A ROM with a synchronous read port, with space for 2^@n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" and "CLaSH.Prelude.BlockRam#usingrams"
+-- for ideas on how to use ROMs and RAMs
+romPow2' :: (KnownNat (2^n), KnownNat n)
+         => SClock clk               -- ^ 'Clock' to synchronize to
+         -> Vec (2^n) a              -- ^ ROM content
+                                     --
+                                     -- __NB:__ must be a constant
+         -> Signal' clk (Unsigned n) -- ^ Read address @rd@
+         -> Signal' clk a            -- ^ The value of the ROM at address @rd@
+romPow2' = rom'
+
+{-# INLINE rom' #-}
+-- | A ROM with a synchronous read port, with space for @n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" and "CLaSH.Prelude.BlockRam#usingrams"
+-- for ideas on how to use ROMs and RAMs
+rom' :: (KnownNat n, Enum addr)
+     => SClock clk       -- ^ 'Clock' to synchronize to
+     -> Vec n a          -- ^ ROM content
+                         --
+                         -- __NB:__ must be a constant
+     -> Signal' clk addr -- ^ Read address @rd@
+     -> Signal' clk a
+     -- ^ The value of the ROM at address @rd@ from the previous clock cycle
+rom' clk content rd = rom# clk content (fromEnum <$> rd)
+
+{-# NOINLINE rom# #-}
+-- | ROM primitive
+rom# :: KnownNat n
+     => SClock clk      -- ^ 'Clock' to synchronize to
+     -> Vec n a         -- ^ ROM content
+                        --
+                        -- __NB:__ must be a constant
+     -> Signal' clk Int -- ^ Read address @rd@
+     -> Signal' clk a
+     -- ^ The value of the ROM at address @rd@ from the previous clock cycle
+rom# clk content rd = register' clk undefined ((arr !) <$> rd)
+  where
+    szI = fromInteger (maxIndex content)
+    arr = listArray (0,szI) (toList content)
diff --git a/src/CLaSH/Prelude/ROM/File.hs b/src/CLaSH/Prelude/ROM/File.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/ROM/File.hs
@@ -0,0 +1,312 @@
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE MagicHash           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
+
+{-# LANGUAGE Unsafe #-}
+
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+Copyright  :  (C) 2015, University of Twente
+License    :  BSD2 (see the file LICENSE)
+Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+= Initialising a ROM with a data file #usingromfiles#
+
+ROMs initialised with a data file. The BNF grammar for this data file is simple:
+
+@
+FILE = LINE+
+LINE = BIT+
+BIT  = '0'
+     | '1'
+@
+
+Consecutive @LINE@s correspond to consecutive memory addresses starting at @0@.
+For example, a data file @memory.bin@ containing the 9-bit unsigned number
+@7@ to @13@ looks like:
+
+@
+000000111
+000001000
+000001001
+000001010
+000001011
+000001100
+000001101
+@
+
+We can instantiate a synchronous ROM using the content of the above file like
+so:
+
+@
+topEntity :: Signal (Unsigned 3) -> Signal (Unsigned 9)
+topEntity rd = 'CLaSH.Class.BitPack.unpack' '<$>' 'romFile' d7 \"memory.bin\" rd
+@
+
+And see that it works as expected:
+
+@
+__>>> import qualified Data.List as L__
+__>>> L.tail $ sampleN 4 $ topEntity (fromList [3..5])__
+[10,11,12]
+@
+
+However, we can also interpret the same data as a tuple of a 6-bit unsigned
+number, and a 3-bit signed number:
+
+@
+topEntity2 :: Signal (Unsigned 3) -> Signal (Unsigned 6,Signed 3)
+topEntity2 rd = 'CLaSH.Class.BitPack.unpack' '<$>' 'romFile' d7 \"memory.bin\" rd
+@
+
+And then we would see:
+
+@
+__>>> import qualified Data.List as L__
+__>>> L.tail $ sampleN 4 $ topEntity2 (fromList [3..5])__
+[(1,2),(1,3)(1,-4)]
+@
+-}
+module CLaSH.Prelude.ROM.File
+  ( -- * Asynchronous ROM
+    asyncRomFile
+  , asyncRomFilePow2
+    -- * Synchronous ROM synchronised to the system clock
+  , romFile
+  , romFilePow2
+    -- * Synchronous ROM synchronised to an arbitrary clock
+  , romFile'
+  , romFilePow2'
+    -- * Internal
+  , asyncRomFile#
+  , romFile#
+  )
+where
+
+import Data.Array                  (listArray,(!))
+import GHC.TypeLits                (KnownNat, type (^))
+
+import CLaSH.Prelude.BlockRam.File (initMem)
+import CLaSH.Promoted.Nat          (SNat,snat,snatToInteger)
+import CLaSH.Sized.BitVector       (BitVector)
+import CLaSH.Signal                (Signal)
+import CLaSH.Signal.Explicit       (Signal', SClock, register', systemClock)
+import CLaSH.Sized.Unsigned        (Unsigned)
+
+{-# INLINE asyncRomFile #-}
+-- | An asynchronous/combinational ROM with space for @n@ elements
+--
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.ROM.File#usingromfiles" for more information on how
+-- to instantiate a ROM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+asyncRomFile :: (KnownNat m, Enum addr)
+             => SNat n      -- ^ Size of the ROM
+             -> FilePath    -- ^ File describing the content of the ROM
+             -> addr        -- ^ Read address @rd@
+             -> BitVector m -- ^ The value of the ROM at address @rd@
+asyncRomFile sz file rd = asyncRomFile# sz file (fromEnum rd)
+
+{-# INLINE asyncRomFilePow2 #-}
+-- | An asynchronous/combinational ROM with space for 2^@n@ elements
+--
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.ROM.File#usingromfiles" for more information on how
+-- to instantiate a ROM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+asyncRomFilePow2 :: forall n m . (KnownNat m, KnownNat n, KnownNat (2^n))
+                 => FilePath    -- ^ File describing the content of the ROM
+                 -> Unsigned n  -- ^ Read address @rd@
+                 -> BitVector m -- ^ The value of the ROM at address @rd@
+asyncRomFilePow2 = asyncRomFile (snat :: SNat (2^n))
+
+{-# NOINLINE asyncRomFile# #-}
+-- | asyncROMFile primitive
+asyncRomFile# :: KnownNat m
+              => SNat n       -- ^ Size of the ROM
+              -> FilePath     -- ^ File describing the content of the ROM
+              -> Int          -- ^ Read address @rd@
+              -> BitVector m  -- ^ The value of the ROM at address @rd@
+asyncRomFile# sz file rd = content ! rd
+  where
+    content = listArray (0,szI-1) (initMem file)
+    szI     = fromInteger (snatToInteger sz)
+
+{-# INLINE romFile #-}
+-- | A ROM with a synchronous read port, with space for @n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.ROM.File#usingromfiles" for more information on how
+-- to instantiate a ROM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+romFile :: (KnownNat m, KnownNat k)
+        => SNat n               -- ^ Size of the ROM
+        -> FilePath             -- ^ File describing the content of the ROM
+        -> Signal (Unsigned k)  -- ^ Read address @rd@
+        -> Signal (BitVector m)
+        -- ^ The value of the ROM at address @rd@ from the previous clock cycle
+romFile = romFile' systemClock
+
+{-# INLINE romFilePow2 #-}
+-- | A ROM with a synchronous read port, with space for 2^@n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.ROM.File#usingromfiles" for more information on how
+-- to instantiate a ROM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+romFilePow2 :: forall n m . (KnownNat m, KnownNat n, KnownNat (2^n))
+            => FilePath             -- ^ File describing the content of the ROM
+            -> Signal (Unsigned n)  -- ^ Read address @rd@
+            -> Signal (BitVector m)
+            -- ^ The value of the ROM at address @rd@ from the previous clock cycle
+romFilePow2 = romFile' systemClock (snat :: SNat (2^n))
+
+{-# INLINE romFilePow2' #-}
+-- | A ROM with a synchronous read port, with space for 2^@n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.ROM.File#usingromfiles" for more information on how
+-- to instantiate a ROM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+romFilePow2' :: forall clk n m . (KnownNat m, KnownNat n, KnownNat (2^n))
+             => SClock clk                -- ^ 'Clock' to synchronize to
+             -> FilePath                  -- ^ File describing the content of
+                                          -- the ROM
+             -> Signal' clk (Unsigned n)  -- ^ Read address @rd@
+             -> Signal' clk (BitVector m)
+             -- ^ The value of the ROM at address @rd@ from the previous clock
+             -- cycle
+romFilePow2' clk = romFile' clk (snat :: SNat (2^n))
+
+{-# INLINE romFile' #-}
+-- | A ROM with a synchronous read port, with space for @n@ elements
+--
+-- * __NB__: Read value is delayed by 1 cycle
+-- * __NB__: Initial output value is 'undefined'
+-- * __NB__: This function might not work for specific combinations of
+-- code-generation backends and hardware targets. Please check the support table
+-- below:
+--
+--     @
+--                    | VHDL     | Verilog                 | SystemVerilog |
+--     ===============+==========+=========================+===============+
+--     Altera/Quartus | Broken   | No Verilog-2005 support | Works         |
+--     Xilinx/ISE     | Works    | Works                   | Works         |
+--     ASIC           | Untested | Untested                | Untested      |
+--     ===============+==========+=========================+===============+
+--     @
+--
+-- Additional helpful information:
+--
+-- * See "CLaSH.Prelude.ROM.File#usingromfiles" for more information on how
+-- to instantiate a ROM with the contents of a data file.
+-- * See "CLaSH.Sized.Fixed#creatingdatafiles" for ideas on how to create your
+-- own data files.
+romFile' :: (KnownNat m, Enum addr)
+         => SClock clk                -- ^ 'Clock' to synchronize to
+         -> SNat n                    -- ^ Size of the ROM
+         -> FilePath                  -- ^ File describing the content of the
+                                      -- ROM
+         -> Signal' clk addr          -- ^ Read address @rd@
+         -> Signal' clk (BitVector m)
+         -- ^ The value of the ROM at address @rd@ from the previous clock cycle
+romFile' clk sz file rd = romFile# clk sz file (fromEnum <$> rd)
+
+{-# NOINLINE romFile# #-}
+-- | romFile primitive
+romFile# :: KnownNat m
+         => SClock clk                -- ^ 'Clock' to synchronize to
+         -> SNat n                    -- ^ Size of the ROM
+         -> FilePath                  -- ^ File describing the content of the
+                                      -- ROM
+         -> Signal' clk Int           -- ^ Read address @rd@
+         -> Signal' clk (BitVector m)
+         -- ^ The value of the ROM at address @rd@ from the previous clock cycle
+romFile# clk sz file rd = register' clk undefined ((content !) <$> rd)
+  where
+    content = listArray (0,szI-1) (initMem file)
+    szI     = fromInteger (snatToInteger sz)
diff --git a/src/CLaSH/Prelude/Safe.hs b/src/CLaSH/Prelude/Safe.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/Safe.hs
@@ -0,0 +1,176 @@
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-# LANGUAGE Safe #-}
+
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+  Copyright   :  (C) 2013-2015, University of Twente
+  License     :  BSD2 (see the file LICENSE)
+  Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+  __This is the <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/safe-haskell.html Safe> API only of "CLaSH.Prelude"__
+
+  CλaSH (pronounced ‘clash’) is a functional hardware description language that
+  borrows both its syntax and semantics from the functional programming language
+  Haskell. The merits of using a functional language to describe hardware comes
+  from the fact that combinational circuits can be directly modeled as
+  mathematical functions and that functional languages lend themselves very well
+  at describing and (de-)composing mathematical functions.
+
+  This package provides:
+
+  * Prelude library containing datatypes and functions for circuit design
+
+  To use the library:
+
+  * Import "CLaSH.Prelude"
+  * Additionally import "CLaSH.Prelude.Explicit" if you want to design
+    explicitly clocked circuits in a multi-clock setting
+
+  For now, "CLaSH.Prelude" is also the best starting point for exploring the
+  library. A preliminary version of a tutorial can be found in "CLaSH.Tutorial".
+  Some circuit examples can be found in "CLaSH.Examples".
+-}
+module CLaSH.Prelude.Safe
+  ( -- * Creating synchronous sequential circuits
+    mealy
+  , mealyB
+  , (<^>)
+  , moore
+  , mooreB
+  , registerB
+    -- * ROMs
+  , asyncRom
+  , asyncRomPow2
+  , rom
+  , romPow2
+    -- * RAM primitives with a combinational read port
+  , asyncRam
+  , asyncRamPow2
+    -- * BlockRAM primitives
+  , blockRam
+  , blockRamPow2
+    -- * Utility functions
+  , isRising
+  , isFalling
+    -- * Exported modules
+    -- ** Synchronous signals
+  , module CLaSH.Signal
+  , module CLaSH.Signal.Delayed
+    -- ** DataFlow interface
+  , module CLaSH.Prelude.DataFlow
+    -- ** Datatypes
+    -- *** Bit vectors
+  , module CLaSH.Sized.BitVector
+  , module CLaSH.Prelude.BitIndex
+  , module CLaSH.Prelude.BitReduction
+    -- *** Arbitrary-width numbers
+  , module CLaSH.Sized.Signed
+  , module CLaSH.Sized.Unsigned
+  , module CLaSH.Sized.Index
+    -- *** Fixed point numbers
+  , module CLaSH.Sized.Fixed
+    -- *** Fixed size vectors
+  , module CLaSH.Sized.Vector
+    -- ** Annotations
+  , module CLaSH.Annotations.TopEntity
+    -- ** Type-level natural numbers
+  , module GHC.TypeLits
+  , module CLaSH.Promoted.Nat
+  , module CLaSH.Promoted.Nat.Literals
+  , module CLaSH.Promoted.Nat.TH
+    -- ** Type-level functions
+  , module CLaSH.Promoted.Ord
+    -- ** Type classes
+    -- *** CLaSH
+  , module CLaSH.Class.BitPack
+  , module CLaSH.Class.Num
+  , module CLaSH.Class.Resize
+    -- *** Other
+  , module Control.Applicative
+  , module Data.Bits
+    -- ** Haskell Prelude
+    -- $hiding
+  , module Prelude
+  )
+where
+
+import Control.Applicative
+import Data.Bits
+import GHC.TypeLits
+import Prelude                     hiding ((++), (!!), concat, drop, foldl,
+                                           foldl1, foldr, foldr1, head, init,
+                                           iterate, last, length, map, repeat,
+                                           replicate, reverse, scanl, scanr,
+                                           splitAt, tail, take, unzip, unzip3,
+                                           zip, zip3, zipWith, zipWith3)
+
+import CLaSH.Annotations.TopEntity
+import CLaSH.Class.BitPack
+import CLaSH.Class.Num
+import CLaSH.Class.Resize
+import CLaSH.Prelude.BitIndex
+import CLaSH.Prelude.BitReduction
+import CLaSH.Prelude.BlockRam      (blockRam, blockRamPow2)
+import CLaSH.Prelude.Explicit.Safe (registerB', isRising', isFalling')
+import CLaSH.Prelude.Mealy         (mealy, mealyB, (<^>))
+import CLaSH.Prelude.Moore         (moore, mooreB)
+import CLaSH.Prelude.RAM           (asyncRam,asyncRamPow2)
+import CLaSH.Prelude.ROM           (asyncRom,asyncRomPow2,rom,romPow2)
+import CLaSH.Prelude.DataFlow
+import CLaSH.Promoted.Nat
+import CLaSH.Promoted.Nat.TH
+import CLaSH.Promoted.Nat.Literals
+import CLaSH.Promoted.Ord
+import CLaSH.Sized.BitVector
+import CLaSH.Sized.Fixed
+import CLaSH.Sized.Index
+import CLaSH.Sized.Signed
+import CLaSH.Sized.Unsigned
+import CLaSH.Sized.Vector
+import CLaSH.Signal
+import CLaSH.Signal.Delayed
+import CLaSH.Signal.Explicit       (systemClock)
+
+-- $setup
+-- >>> let rP = registerB (8,8)
+
+{- $hiding
+"CLaSH.Prelude" re-exports most of the Haskell "Prelude" with the exception of
+the following: (++), (!!), concat, drop, foldl, foldl1, foldr, foldr1, head,
+init, iterate, last, length, map, repeat, replicate, reverse, scanl, scanr,
+splitAt, tail, take, unzip, unzip3, zip, zip3, zipWith, zipWith3.
+
+It instead exports the identically named functions defined in terms of
+'CLaSH.Sized.Vector.Vec' at "CLaSH.Sized.Vector".
+-}
+
+{-# INLINE registerB #-}
+-- | Create a 'register' function for product-type like signals (e.g. '(Signal a, Signal b)')
+--
+-- > rP :: (Signal Int,Signal Int) -> (Signal Int, Signal Int)
+-- > rP = registerB (8,8)
+--
+-- >>> simulateB rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
+-- [(8,8),(1,1),(2,2),(3,3)...
+registerB :: Bundle a => a -> Unbundled a -> Unbundled a
+registerB = registerB' systemClock
+
+{-# INLINE isRising #-}
+-- | Give a pulse when the 'Signal' goes from 'minBound' to 'maxBound'
+isRising :: (Bounded a, Eq a)
+         => a -- ^ Starting value
+         -> Signal a
+         -> Signal Bool
+isRising = isRising' systemClock
+
+{-# INLINE isFalling #-}
+-- | Give a pulse when the 'Signal' goes from 'maxBound' to 'minBound'
+isFalling :: (Bounded a, Eq a)
+          => a -- ^ Starting value
+          -> Signal a
+          -> Signal Bool
+isFalling = isFalling' systemClock
diff --git a/src/CLaSH/Prelude/Synchronizer.hs b/src/CLaSH/Prelude/Synchronizer.hs
new file mode 100644
--- /dev/null
+++ b/src/CLaSH/Prelude/Synchronizer.hs
@@ -0,0 +1,157 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+
+{-# LANGUAGE Safe #-}
+
+{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-|
+Copyright   :  (C) 2015, University of Twente
+License     :  BSD2 (see the file LICENSE)
+Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>
+
+Synchronizer circuits for safe clock domain crossings
+-}
+module CLaSH.Prelude.Synchronizer
+  ( -- * Bit-synchronizers
+    dualFlipFlopSynchronizer
+    -- * Word-synchronizers
+  , asyncFIFOSynchronizer
+  )
+where
+
+import Data.Bits                   (complement, shiftR, xor)
+import GHC.TypeLits                (KnownNat, type (+))
+
+import CLaSH.Class.BitPack         (pack)
+import CLaSH.Class.Resize          (zeroExtend)
+import CLaSH.Prelude.BitIndex      (slice)
+import CLaSH.Prelude.Mealy         (mealyB')
+import CLaSH.Prelude.RAM           (asyncRam')
+import CLaSH.Promoted.Nat          (SNat, powSNat, subSNat)
+import CLaSH.Promoted.Nat.Literals (d0, d1, d2)
+import CLaSH.Signal                ((.&&.), not1)
+import CLaSH.Signal.Explicit       (Signal', SClock, register',
+                                    unsafeSynchronizer)
+import CLaSH.Sized.BitVector       (BitVector, (++#))
+
+-- * Dual flip-flop synchronizer
+
+-- | Synchroniser based on two sequentially connected flip-flops.
+--
+--  * __NB__: This synchroniser can be used for __bit__-synchronization.
+--
+--  * __NB__: Although this synchroniser does reduce metastability, it does
+--  not guarantee the proper synchronisation of a whole __word__. For
+--  example, given that the output is sampled twice as fast as the input is
+--  running, and we have two samples in the input stream that look like:
+--
+--      @[0111,1000]@
+--
+--      But the circuit driving the input stream has a longer propagation delay
+--      on __msb__ compared to the __lsb__s. What can happen is an output stream
+--      that looks like this:
+--
+--      @[0111,0111,0000,1000]@
+--
+--      Where the level-change of the __msb__ was not captured, but the level
+--      change of the __lsb__s were.
+--
+--      If you want to have /safe/ __word__-synchronisation use
+--      'asyncFIFOSynchronizer'.
+dualFlipFlopSynchronizer :: SClock clk1    -- ^ 'Clock' to which the incoming
+                                           -- data is synchronised
+                         -> SClock clk2    -- ^ 'Clock' to which the outgoing
+                                           -- data is synchronised
+                         -> a              -- ^ Initial value of the two
+                                           -- synchronisation registers
+                         -> Signal' clk1 a -- ^ Incoming data
+                         -> Signal' clk2 a -- ^ Outgoing, synchronised, data
+dualFlipFlopSynchronizer clk1 clk2 i = register' clk2 i
+                                     . register' clk2 i
+                                     . unsafeSynchronizer clk1 clk2
+
+-- * Asynchronous FIFO synchronizer
+
+fifoMem :: _
+        => SClock wclk
+        -> SClock rclk
+        -> SNat addrSize
+        -> Signal' wclk (BitVector addrSize)
+        -> Signal' rclk (BitVector addrSize)
+        -> Signal' wclk Bool
+        -> Signal' wclk Bool
+        -> Signal' wclk a
+        -> Signal' rclk a
+fifoMem wclk rclk addrSize waddr raddr winc wfull wdata =
+  asyncRam' wclk rclk
+            (d2 `powSNat` addrSize)
+            waddr raddr
+            (winc .&&. not1 wfull)
+            wdata
+
+boolToBV :: (KnownNat n, KnownNat (n+1)) => Bool -> BitVector (n + 1)
+boolToBV = zeroExtend . pack
+
+ptrCompareT :: _
+            => SNat addrSize
+            -> (BitVector (addrSize + 1) -> BitVector (addrSize + 1) -> Bool)
+            -> (BitVector (addrSize + 1), BitVector (addrSize + 1), Bool)
+            -> (BitVector (addrSize + 1), Bool)
+            -> ((BitVector (addrSize + 1), BitVector (addrSize + 1), Bool)
+               ,(Bool, BitVector addrSize, BitVector (addrSize + 1)))
+ptrCompareT addrSize flagGen (bin,ptr,flag) (s_ptr,inc) = ((bin',ptr',flag')
+                                                          ,(flag,addr,ptr))
+  where
+    -- GRAYSTYLE2 pointer
+    bin' = bin + boolToBV (inc && not flag)
+    ptr' = (bin' `shiftR` 1) `xor` bin'
+    addr = slice (addrSize `subSNat` d1) d0 bin
+
+    flag' = flagGen ptr' s_ptr
+
+
+-- FIFO full: when next pntr == synchonized {~wptr[addrSize:addrSize-1],wptr[addrSize-1:0]}
+isFull :: _
+       => SNat addrSize
+       -> BitVector (addrSize + 1)
+       -> BitVector (addrSize + 1)
+       -> Bool
+isFull addrSize ptr s_ptr =
+  ptr == (complement (slice addrSize (addrSize `subSNat` d1) s_ptr) ++#
+         slice (addrSize `subSNat` d2) d0 s_ptr)
+
+-- | Synchroniser implemented as a FIFO around an asynchronous RAM. Based on the
+-- design described in "CLaSH.Tutorial#multiclock", which is itself based on the
+-- design described in <http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf>.
+--
+-- __NB__: This synchroniser can be used for __word__-synchronization.
+asyncFIFOSynchronizer :: _
+                      => SNat addrSize     -- ^ Size of the internally used
+                                           -- addresses, the FIFO contains
+                                           -- @2^addrSize@ elements.
+                      -> SClock wclk       -- ^ 'Clock' to which the write port
+                                           -- is synchronised
+                      -> SClock rclk       -- ^ 'Clock' to which the read port
+                                           -- is synchronised
+                      -> Signal' wclk a    -- ^ Element to insert
+                      -> Signal' wclk Bool -- ^ Write request
+                      -> Signal' rclk Bool -- ^ Read request
+                      -> (Signal' rclk a, Signal' rclk Bool, Signal' wclk Bool)
+                      -- ^ (Oldest element in the FIFO, @empty@ flag, @full@ flag)
+asyncFIFOSynchronizer addrSize wclk rclk wdata winc rinc = (rdata,rempty,wfull)
+  where
+    s_rptr = dualFlipFlopSynchronizer rclk wclk 0 rptr
+    s_wptr = dualFlipFlopSynchronizer wclk rclk 0 wptr
+
+    rdata = fifoMem wclk rclk addrSize waddr raddr winc wfull wdata
+
+    (rempty,raddr,rptr) = mealyB' rclk (ptrCompareT addrSize (==)) (0,0,True)
+                                  (s_wptr,rinc)
+
+    (wfull,waddr,wptr)  = mealyB' wclk (ptrCompareT addrSize (isFull addrSize))
+                                  (0,0,False) (s_rptr,winc)
diff --git a/src/CLaSH/Prelude/Testbench.hs b/src/CLaSH/Prelude/Testbench.hs
--- a/src/CLaSH/Prelude/Testbench.hs
+++ b/src/CLaSH/Prelude/Testbench.hs
@@ -15,17 +15,17 @@
   , stimuliGenerator
   , outputVerifier
     -- * Testbench functions for circuits synchronised to arbitrary clocks
+  , assert'
   , stimuliGenerator'
   , outputVerifier'
   )
 where
 
-import Control.Applicative   (liftA3)
 import Debug.Trace           (trace)
 import GHC.TypeLits          (KnownNat)
 import Prelude               hiding ((!!))
 
-import CLaSH.Signal          (Signal)
+import CLaSH.Signal          (Signal, fromList)
 import CLaSH.Signal.Explicit (Signal', SClock, register', systemClock)
 import CLaSH.Signal.Bundle   (unbundle')
 import CLaSH.Sized.Index     (Index)
@@ -43,6 +43,22 @@
 -- >>> let testInput' = stimuliGenerator' clkA $(v [(1::Int),3..21])
 -- >>> let expectedOutput' = outputVerifier' clkA $(v ([70,99,2,3,4,5,7,8,9,10]::[Int]))
 
+{-# INLINE assert #-}
+-- | Compares the first two 'Signal's for equality and logs a warning when they
+-- are not equal. The second 'Signal' is considered the expected value. This
+-- function simply returns the third 'Signal' unaltered as its result. This
+-- function is used by 'outputVerifier'.
+--
+--
+-- __NB__: This function is /can/ be used in synthesizable designs.
+assert :: (Eq a,Show a)
+       => String   -- ^ Additional message
+       -> Signal a -- ^ Checked value
+       -> Signal a -- ^ Expected value
+       -> Signal b -- ^ Return valued
+       -> Signal b
+assert = assert' systemClock
+
 {-# INLINE stimuliGenerator #-}
 -- | To be used as a one of the functions to create the \"magical\" 'testInput'
 -- value, which the CλaSH compilers looks for to create the stimulus generator
@@ -77,16 +93,22 @@
 -- >>> import qualified Data.List as List
 -- >>> sampleN 12 (expectedOutput (fromList ([0..10] List.++ [10,10,10])))
 -- [
+-- cycle(system1000): 0, outputVerifier
 -- expected value: 70, not equal to actual value: 0
 -- False,
+-- cycle(system1000): 1, outputVerifier
 -- expected value: 99, not equal to actual value: 1
 -- False,False,False,False,False,
+-- cycle(system1000): 6, outputVerifier
 -- expected value: 7, not equal to actual value: 6
 -- False,
+-- cycle(system1000): 7, outputVerifier
 -- expected value: 8, not equal to actual value: 7
 -- False,
+-- cycle(system1000): 8, outputVerifier
 -- expected value: 9, not equal to actual value: 8
 -- False,
+-- cycle(system1000): 9, outputVerifier
 -- expected value: 10, not equal to actual value: 9
 -- False,True,True]
 outputVerifier :: forall l a . (KnownNat l, Eq a, Show a)
@@ -95,26 +117,34 @@
                -> Signal Bool -- ^ Indicator that all samples are verified
 outputVerifier = outputVerifier' systemClock
 
-{-# NOINLINE assert #-}
--- | Compares the first two arguments for equality and logs a warning when they
--- are not equal. The second argument is considered the expected value. This
--- function simply returns the third argument unaltered as its result. This
--- function is used by 'coutputVerifier'.
+{-# NOINLINE assert' #-}
+-- | Compares the first two 'Signal''s for equality and logs a warning when they
+-- are not equal. The second 'Signal'' is considered the expected value. This
+-- function simply returns the third 'Signal'' unaltered as its result. This
+-- function is used by 'outputVerifier''.
 --
 --
 -- __NB__: This function is /can/ be used in synthesizable designs.
-assert :: (Eq a,Show a)
-       => Signal' t a -- ^ Checked value
-       -> Signal' t a -- ^ Expected value
-       -> Signal' t b -- ^ Return valued
-       -> Signal' t b
-assert = liftA3
-  (\a' b' c' -> if a' == b' then c'
-                            else trace (concat [ "\nexpected value: "
-                                               , show b'
-                                               , ", not equal to actual value: "
-                                               , show a'
-                                               ]) c')
+assert' :: (Eq a,Show a)
+        => SClock t
+        -> String      -- ^ Additional message
+        -> Signal' t a -- ^ Checked value
+        -> Signal' t a -- ^ Expected value
+        -> Signal' t b -- ^ Return valued
+        -> Signal' t b
+assert' clk msg checked expected returned =
+  (\c e cnt r ->
+      if c == e then r
+                else trace (concat [ "\ncycle(" ++ show clk ++ "): "
+                                   , show cnt
+                                   , ", "
+                                   , msg
+                                   , "\nexpected value: "
+                                   , show e
+                                   , ", not equal to actual value: "
+                                   , show c
+                                   ]) r)
+  <$> checked <*> expected <*> fromList [(0::Integer)..] <*> returned
 
 {-# INLINABLE stimuliGenerator' #-}
 -- | To be used as a one of the functions to create the \"magical\" 'testInput'
@@ -173,16 +203,22 @@
 -- >>> import qualified Data.List as List
 -- >>> sampleN 12 (expectedOutput' (fromList ([0..10] List.++ [10,10,10])))
 -- [
+-- cycle(A100): 0, outputVerifier
 -- expected value: 70, not equal to actual value: 0
 -- False,
+-- cycle(A100): 1, outputVerifier
 -- expected value: 99, not equal to actual value: 1
 -- False,False,False,False,False,
+-- cycle(A100): 6, outputVerifier
 -- expected value: 7, not equal to actual value: 6
 -- False,
+-- cycle(A100): 7, outputVerifier
 -- expected value: 8, not equal to actual value: 7
 -- False,
+-- cycle(A100): 8, outputVerifier
 -- expected value: 9, not equal to actual value: 8
 -- False,
+-- cycle(A100): 9, outputVerifier
 -- expected value: 10, not equal to actual value: 9
 -- False,True,True]
 outputVerifier' :: forall l clk a . (KnownNat l, Eq a, Show a)
@@ -194,7 +230,7 @@
 outputVerifier' clk samples i =
     let (s,o) = unbundle' clk (genT <$> register' clk 0 s)
         (e,f) = unbundle' clk o
-    in  assert i e (register' clk False f)
+    in  assert' clk "outputVerifier" i e (register' clk False f)
   where
     genT :: Index l -> (Index l,(a,Bool))
     genT s = (s',(samples !! s,finished))
diff --git a/src/CLaSH/Promoted/Nat.hs b/src/CLaSH/Promoted/Nat.hs
--- a/src/CLaSH/Promoted/Nat.hs
+++ b/src/CLaSH/Promoted/Nat.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE GADTs               #-}
 {-# LANGUAGE KindSignatures      #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -15,7 +16,7 @@
 Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
 -}
 module CLaSH.Promoted.Nat
-  ( SNat (..), snat, withSNat, snatToInteger
+  ( SNat (..), snat, withSNat, snatToInteger, addSNat, subSNat, mulSNat, powSNat
   , UNat (..), toUNat, addUNat, multUNat, powUNat
   )
 where
@@ -66,7 +67,7 @@
     fromI 0 = unsafeCoerce UZero
     fromI n = unsafeCoerce (USucc (fromI (n - 1)))
 
--- | Add two singleton natural numbers
+-- | Add two unary singleton natural numbers
 --
 -- __NB__: Not synthesisable
 addUNat :: UNat n -> UNat m -> UNat (n + m)
@@ -74,7 +75,7 @@
 addUNat x         UZero = x
 addUNat (USucc x) y     = USucc (addUNat x y)
 
--- | Multiply two singleton natural numbers
+-- | Multiply two unary singleton natural numbers
 --
 -- __NB__: Not synthesisable
 multUNat :: UNat n -> UNat m -> UNat (n * m)
@@ -82,9 +83,25 @@
 multUNat _          UZero = UZero
 multUNat (USucc x) y      = addUNat y (multUNat x y)
 
--- | Exponential of two singleton natural numbers
+-- | Power of two unary singleton natural numbers
 --
 -- __NB__: Not synthesisable
 powUNat :: UNat n -> UNat m -> UNat (n ^ m)
 powUNat _ UZero     = USucc UZero
 powUNat x (USucc y) = multUNat x (powUNat x y)
+
+-- | Add two singleton natural numbers
+addSNat :: KnownNat (a + b) => SNat a -> SNat b -> SNat (a+b)
+addSNat _ _ = snat
+
+-- | Subtract two singleton natural numbers
+subSNat :: KnownNat (a - b) => SNat a -> SNat b -> SNat (a-b)
+subSNat _ _ = snat
+
+-- | Multiply two singleton natural numbers
+mulSNat :: KnownNat (a * b) => SNat a -> SNat b -> SNat (a*b)
+mulSNat _ _ = snat
+
+-- | Power of two singleton natural numbers
+powSNat :: KnownNat (a ^ b) => SNat a -> SNat b -> SNat (a^b)
+powSNat _ _ = snat
diff --git a/src/CLaSH/Signal/Delayed.hs b/src/CLaSH/Signal/Delayed.hs
--- a/src/CLaSH/Signal/Delayed.hs
+++ b/src/CLaSH/Signal/Delayed.hs
@@ -40,7 +40,7 @@
 import Data.Coerce                (coerce)
 import Data.Default               (Default(..))
 import Control.Applicative        (liftA2)
-import GHC.TypeLits               (KnownNat, Nat, type (-))
+import GHC.TypeLits               (KnownNat, Nat, type (+))
 import Language.Haskell.TH.Syntax (Lift)
 import Prelude                    hiding (head, length, repeat)
 import Test.QuickCheck            (Arbitrary, CoArbitrary)
@@ -56,7 +56,7 @@
 -- >>> :set -XTypeOperators
 -- >>> import CLaSH.Prelude
 -- >>> let delay3 = delay (0 :> 0 :> 0 :> Nil)
--- >>> let delay2 = delayI :: DSignal (n - 2) Int -> DSignal n Int
+-- >>> let delay2 = delayI :: DSignal n Int -> DSignal (n + 2) Int
 -- >>> :{
 -- let mac :: DSignal 0 Int -> DSignal 0 Int -> DSignal 0 Int
 --     mac x y = feedback (mac' x y)
@@ -98,19 +98,19 @@
 dfromList :: [a] -> DSignal 0 a
 dfromList = coerce . fromList
 
--- | Delay a 'DSignal' for @m@ periods.
+-- | Delay a 'DSignal' for @d@ periods.
 --
 -- @
--- delay3 :: 'DSignal' (n - 3) Int -> 'DSignal' n Int
+-- delay3 :: 'DSignal' n Int -> 'DSignal' (n + 3) Int
 -- delay3 = 'delay' (0 ':>' 0 ':>' 0 ':>' 'Nil')
 -- @
 --
 -- >>> sampleN 6 (delay3 (dfromList [1..]))
 -- [0,0,0,1,2,3]
-delay :: forall a n m . KnownNat m
-      => Vec m a
-      -> DSignal (n - m) a
+delay :: forall a n d . KnownNat d
+      => Vec d a
       -> DSignal n a
+      -> DSignal (n + d) a
 delay m ds = coerce (delay' (coerce ds))
   where
     delay' :: Signal a -> Signal a
@@ -123,15 +123,15 @@
 -- | Delay a 'DSignal' for @m@ periods, where @m@ is derived from the context.
 --
 -- @
--- delay2 :: 'DSignal' (n - 2) Int -> 'DSignal' n Int
+-- delay2 :: 'DSignal' n Int -> 'DSignal' (n + 2) Int
 -- delay2 = 'delayI'
 -- @
 --
 -- >>> sampleN 6 (delay2 (dfromList [1..]))
 -- [0,0,1,2,3,4]
-delayI :: (Default a, KnownNat m)
-       => DSignal (n - m) a
-       -> DSignal n a
+delayI :: (Default a, KnownNat d)
+       => DSignal n a
+       -> DSignal (n + d) a
 delayI = delay (repeat def)
 
 -- | Feed the delayed result of a function back to its input:
@@ -148,8 +148,8 @@
 --
 -- >>> sampleN 6 (mac (dfromList [1..]) (dfromList [1..]))
 -- [0,1,5,14,30,55]
-feedback :: (DSignal (n - m - 1) a -> (DSignal (n - m - 1) a,DSignal n a))
-         -> DSignal (n - m - 1) a
+feedback :: (DSignal n a -> (DSignal n a,DSignal (n + m + 1) a))
+         -> DSignal n a
 feedback f = let (o,r) = f (coerce r) in o
 
 -- | 'Signal's are not delayed
@@ -178,5 +178,5 @@
 --     acc' = (x * y) + 'antiDelay' d1 acc
 --     acc  = 'delay' ('singleton' 0) acc'
 -- @
-antiDelay :: SNat d -> DSignal n a -> DSignal (n - d) a
+antiDelay :: SNat d -> DSignal (n + d) a -> DSignal n a
 antiDelay _ = coerce
diff --git a/src/CLaSH/Signal/Explicit.hs b/src/CLaSH/Signal/Explicit.hs
--- a/src/CLaSH/Signal/Explicit.hs
+++ b/src/CLaSH/Signal/Explicit.hs
@@ -23,6 +23,7 @@
   , withSClock
   , SystemClock
   , systemClock
+  , freqCalc
     -- ** Synchronisation primitive
   , unsafeSynchronizer
     -- * Basic circuit functions
@@ -136,6 +137,44 @@
 -- | The singleton clock for 'SystemClock'
 systemClock :: SClock SystemClock
 systemClock = sclock
+
+-- | Calculate relative periods given a list of frequencies.
+--
+-- So for example, you have one part of your design connected to an ADC running
+-- at 20 MHz, one part of your design connected to a DAC running at 36 MHz, and
+-- the rest of your system is running at 50 MHz. What are the relative
+-- (integer) clock periods in CλaSH, such that their ratios correspond to the
+-- ratios between the actual clock frequencies.
+--
+-- For this we use 'freqCalc':
+--
+-- >>> freqCalc [20,36,50]
+-- [45,25,18]
+--
+-- So that we create the proper clocks:
+--
+-- @
+-- type ADC20 = 'Clk' \"ADC\" 45
+-- type DAC36 = 'Clk' \"DAC\" 25
+-- type Sys50 = 'Clk' \"Sys\" 18
+--
+-- sys50 :: SClock System50
+-- sys50 = 'sclock'
+--
+-- adc20 :: SClock ADC20
+-- adc20 = 'sclock'
+--
+-- dac36 :: SClock DAC36
+-- dac36 = 'sclock'
+-- @
+--
+-- __NB__: This function is /not/ synthesisable
+freqCalc :: [Integer] -> [Integer]
+freqCalc xs = map (`div` g) ys
+  where
+    p  = product xs
+    ys = map (p `div`) xs
+    g  = foldr1 gcd ys
 
 -- ** Synchronisation primitive
 {-# NOINLINE unsafeSynchronizer #-}
diff --git a/src/CLaSH/Signal/Internal.hs b/src/CLaSH/Signal/Internal.hs
--- a/src/CLaSH/Signal/Internal.hs
+++ b/src/CLaSH/Signal/Internal.hs
@@ -70,6 +70,8 @@
   , unsafeShiftR1
   , rotateL1
   , rotateR1
+  -- * EXTREMELY EXPERIMENTAL
+  , joinSignal#
   )
 where
 
@@ -140,6 +142,19 @@
 appSignal# :: Signal' clk (a -> b) -> Signal' clk a -> Signal' clk b
 appSignal# (f :- fs) ~(a :- as) = f a :- appSignal# fs as
 
+{-# NOINLINE joinSignal# #-}
+-- | __WARNING: EXTREMELY EXPERIMENTAL__
+--
+-- The circuit semantics of this operation are unclear and/or non-existent.
+-- There is a good reason there is no 'Monad' instance for 'Signal''.
+--
+-- Is currently treated as 'id' by the CLaSH compiler.
+joinSignal# :: Signal' clk (Signal' clk a) -> Signal' clk a
+joinSignal# ~(xs :- xss) = head# xs :- joinSignal# (mapSignal# tail# xss)
+  where
+    head# (x' :- _ )  = x'
+    tail# (_  :- xs') = xs'
+
 instance Num a => Num (Signal' clk a) where
   (+)         = liftA2 (+)
   (-)         = liftA2 (-)
@@ -219,9 +234,15 @@
     s' = mux b s r
 
 {-# INLINE mux #-}
--- | A multiplexer. Given "@'mux' b t f@", output @t@ when @b@ is 'True', and @f@
+-- | The above type is a generalisation for:
+--
+-- @
+-- __mux__ :: 'CLaSH.Signal.Signal' 'Bool' -> 'CLaSH.Signal.Signal' a -> 'CLaSH.Signal.Signal' a -> 'CLaSH.Signal.Signal' a
+-- @
+--
+-- A multiplexer. Given "@'mux' b t f@", output @t@ when @b@ is 'True', and @f@
 -- when @b@ is 'False'.
-mux :: Signal' clk Bool -> Signal' clk a -> Signal' clk a -> Signal' clk a
+mux :: Applicative f => f Bool -> f a -> f a -> f a
 mux = liftA3 (\b t f -> if b then t else f)
 
 {-# INLINE signal #-}
diff --git a/src/CLaSH/Sized/Fixed.hs b/src/CLaSH/Sized/Fixed.hs
--- a/src/CLaSH/Sized/Fixed.hs
+++ b/src/CLaSH/Sized/Fixed.hs
@@ -47,6 +47,8 @@
   , divide
     -- * Compile-time 'Double' conversion
   , fLit
+    -- * Run-time 'Double' conversion (not synthesisable)
+  , fLitR
     -- * 'Fixed' point wrapper
   , Fixed (..), resizeF, fracShift
     -- * Constraint synonyms
@@ -591,6 +593,170 @@
     truncated = truncate shifted :: Integer
     shifted   = a * (2 ^ (natVal (Proxy :: Proxy frac)))
 
+-- | Convert, at run-time, a 'Double' to a 'Fixed'-point.
+--
+-- __NB__: this functions is /not/ synthesisable
+--
+-- = Creating data-files #creatingdatafiles#
+--
+-- An example usage of this function is for example to convert a data file
+-- containing 'Double's to a data file with ASCI-encoded binary numbers to be
+-- used by a synthesisable function like 'CLaSH.Prelude.ROM.File.asyncRomFile'.
+-- For example, given a file @Data.txt@ containing:
+--
+-- @
+-- 1.2 2.0 3.0 4.0
+-- -1.0 -2.0 -3.5 -4.0
+-- @
+--
+-- which we want to put in a ROM, interpreting them as @8.8@ signed fixed point
+-- numbers. What we do is that we first create a conversion utility,
+-- @createRomFile@, which uses 'fLitR':
+--
+-- @createRomFile.hs@:
+--
+-- @
+-- module Main where
+--
+-- import CLaSH.Prelude
+-- import System.Environment
+-- import qualified Data.List as L
+--
+-- createRomFile :: KnownNat n => (Double -> BitVector n)
+--               -> FilePath -> FilePath -> IO ()
+-- createRomFile convert fileR fileW = do
+--   f <- readFile fileR
+--   let ds :: [Double]
+--       ds = L.concat . (L.map . L.map) read . L.map words $ lines f
+--       bvs = L.map (filter (/= '_') . show . convert) ds
+--   writeFile fileW (unlines bvs)
+--
+-- toSFixed8_8 :: Double -> SFixed 8 8
+-- toSFixed8_8 = 'fLitR'
+--
+-- main :: IO ()
+-- main = do
+--   [fileR,fileW] <- getArgs
+--   createRomFile ('pack' . toSFixed8_8) fileR fileW
+-- @
+--
+-- We then compile this to an executable:
+--
+-- @
+-- $ clash --make createRomFile.hs
+-- @
+--
+-- We can then use this utility to convert our @Data.txt@ file which contains
+-- 'Double's to a @Data.bin@ file which will containing the desired ASCI-encoded
+-- binary data:
+--
+-- @
+-- $ ./createRomFile \"Data.txt\" \"Data.bin\"
+-- @
+--
+-- Which results in a @Data.bin@ file containing:
+--
+-- @
+-- 0000000100110011
+-- 0000001000000000
+-- 0000001100000000
+-- 0000010000000000
+-- 1111111100000000
+-- 1111111000000000
+-- 1111110010000000
+-- 1111110000000000
+-- @
+--
+-- We can then use this @Data.bin@ file in for our ROM:
+--
+-- @
+-- romF :: Unsigned 3 -> Unsigned 3 -> SFixed 8 8
+-- romF rowAddr colAddr = 'unpack'
+--                      $ 'CLaSH.Prelude.ROM.File.asyncRomFile' d8 "Data.bin" ((rowAddr * 4) + colAddr)
+-- @
+--
+-- And see that it works as expected:
+--
+-- @
+-- __>>> romF 1 2__
+-- -3.5
+-- __>>> romF 0 0__
+-- 1.19921875
+-- @
+--
+-- == Using Template Haskell
+--
+-- For those of us who like to live on the edge, another option is to convert
+-- our @Data.txt@ at compile-time using
+-- <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/template-haskell.html Template Haskell>.
+-- For this we first create a module @CreateRomFileTH.hs@:
+--
+-- @
+-- module CreateRomFileTH (romDataFromFile) where
+--
+-- import CLaSH.Prelude
+-- import qualified Data.List        as L
+-- import Language.Haskell.TH        (ExpQ, litE, stringL)
+-- import Language.Haskell.TH.Syntax (qRunIO)
+--
+-- createRomFile :: KnownNat n => (Double -> BitVector n)
+--               -> FilePath -> FilePath -> IO ()
+-- createRomFile convert fileR fileW = do
+--   f <- readFile fileR
+--   let ds :: [Double]
+--       ds = L.concat . (L.map . L.map) read . L.map words $ lines f
+--       bvs = L.map (filter (/= '_') . show . convert) ds
+--   writeFile fileW (unlines bvs)
+--
+-- romDataFromFile :: KnownNat n => (Double -> BitVector n) -> String -> ExpQ
+-- romDataFromFile convert fileR = do
+--   let fileW = fileR L.++ ".bin"
+--   bvF <- qRunIO (createRomFile convert fileR fileW)
+--   litE (stringL fileW)
+-- @
+--
+-- Instead of first converting @Data.txt@ to @Data.bin@, we will now use the
+-- @romDataFromFile@ function to convert @Data.txt@ to a new file in the proper
+-- format at compile-time of our new @romF'@ function:
+--
+-- @
+-- import CLaSH.Prelude
+-- import CreateRomFileTH
+--
+-- toSFixed8_8 :: Double -> SFixed 8 8
+-- toSFixed8_8 = 'fLitR'
+--
+-- romF' :: Unsigned 3 -> Unsigned 3 -> SFixed 8 8
+-- romF' rowAddr colAddr = unpack $
+--   asyncRomFile d8
+--                $(romDataFromFile (pack . toSFixed8_8) "Data.txt") -- Template Haskell splice
+--                ((rowAddr * 4) + colAddr)
+-- @
+--
+-- And see that it works just like the @romF@ function from earlier:
+--
+-- @
+-- __>>> romF' 1 2__
+-- -3.5
+-- __>>> romF' 0 0__
+-- 1.19921875
+-- @
+fLitR :: forall rep int frac size .
+         ( size ~ (int + frac), KnownNat frac, Bounded (rep size)
+         , Integral (rep size))
+      => Double
+      -> Fixed rep int frac
+fLitR a = Fixed (fromInteger sat)
+  where
+    rMax      = toInteger (maxBound :: rep size)
+    rMin      = toInteger (minBound :: rep size)
+    sat       = if truncated > rMax
+                   then rMax
+                   else if truncated < rMin
+                           then rMin
+                           else truncated
+    truncated = truncate shifted :: Integer
+    shifted   = a * (2 ^ (natVal (Proxy :: Proxy frac)))
 
 instance NumFixedC rep int frac => SaturatingNum (Fixed rep int frac) where
   satPlus w (Fixed a) (Fixed b) = Fixed (satPlus w a b)
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
@@ -74,7 +74,6 @@
     -- ** Integral
   , quot#
   , rem#
-  , mod#
   , toInteger#
     -- ** Bits
   , and#
@@ -299,18 +298,16 @@
   quot        = quot#
   rem         = rem#
   div         = quot#
-  mod         = mod#
+  mod         = rem#
   quotRem n d = (n `quot#` d,n `rem#` d)
-  divMod  n d = (n `quot#` d,n `mod#` d)
+  divMod  n d = (n `quot#` d,n `rem#` d)
   toInteger   = toInteger#
 
-quot#,rem#,mod# :: BitVector n -> BitVector n -> BitVector n
+quot#,rem# :: BitVector n -> BitVector n -> BitVector n
 {-# NOINLINE quot# #-}
 quot# (BV i) (BV j) = BV (i `quot` j)
 {-# NOINLINE rem# #-}
 rem# (BV i) (BV j) = BV (i `rem` j)
-{-# NOINLINE mod# #-}
-mod# (BV i) (BV j) = BV (i `mod` j)
 
 {-# NOINLINE toInteger# #-}
 toInteger# :: BitVector n -> Integer
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
@@ -40,7 +40,6 @@
     -- ** Integral
   , quot#
   , rem#
-  , mod#
   , toInteger#
   )
 where
@@ -175,18 +174,16 @@
   quot        = quot#
   rem         = rem#
   div         = quot#
-  mod         = mod#
+  mod         = rem#
   quotRem n d = (n `quot#` d,n `rem#` d)
-  divMod  n d = (n `quot#` d,n `mod#` d)
+  divMod  n d = (n `quot#` d,n `rem#` d)
   toInteger   = toInteger#
 
-quot#,rem#,mod# :: Index n -> Index n -> Index n
+quot#,rem# :: Index n -> Index n -> Index n
 {-# NOINLINE quot# #-}
 (I a) `quot#` (I b) = I (a `div` b)
 {-# NOINLINE rem# #-}
 (I a) `rem#` (I b) = I (a `rem` b)
-{-# NOINLINE mod# #-}
-(I a) `mod#` (I b) = I (a `mod` b)
 
 {-# NOINLINE toInteger# #-}
 toInteger# :: Index n -> Integer
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
@@ -55,7 +55,6 @@
     -- ** Integral
   , quot#
   , rem#
-  , mod#
   , toInteger#
     -- ** Bits
   , and#
@@ -122,9 +121,9 @@
 -- >>> satMin SatSymmetric 2 3 :: Unsigned 3
 -- 0
 newtype Unsigned (n :: Nat) =
-    -- | The constructor, 'U', and the field, 'unsafeToBitVector', are not
+    -- | The constructor, 'U', and the field, 'unsafeToInteger', are not
     -- synthesisable.
-    U { unsafeToBitVector :: Integer }
+    U { unsafeToInteger :: Integer }
 
 {-# NOINLINE size# #-}
 size# :: KnownNat n => Unsigned n -> Int
@@ -272,18 +271,16 @@
   quot        = quot#
   rem         = rem#
   div         = quot#
-  mod         = mod#
+  mod         = rem#
   quotRem n d = (n `quot#` d,n `rem#` d)
-  divMod  n d = (n `quot#` d,n `mod#` d)
+  divMod  n d = (n `quot#` d,n `rem#` d)
   toInteger   = toInteger#
 
-quot#,rem#,mod# :: Unsigned n -> Unsigned n -> Unsigned n
+quot#,rem# :: Unsigned n -> Unsigned n -> Unsigned n
 {-# NOINLINE quot# #-}
 quot# (U i) (U j) = U (i `quot` j)
 {-# NOINLINE rem# #-}
 rem# (U i) (U j) = U (i `rem` j)
-{-# NOINLINE mod# #-}
-mod# (U i) (U j) = U (i `mod` j)
 
 {-# NOINLINE toInteger# #-}
 toInteger# :: Unsigned n -> Integer
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
@@ -790,8 +790,8 @@
 -- 2
 -- >>> (1:>2:>3:>4:>5:>Nil) !! 14
 -- *** Exception: CLaSH.Sized.Vector.(!!): index 14 is larger than maximum index 4
-(!!) :: (KnownNat n, Integral i) => Vec n a -> i -> a
-xs !! i = index_int xs (fromIntegral i)
+(!!) :: (KnownNat n, Enum i) => Vec n a -> i -> a
+xs !! i = index_int xs (fromEnum i)
 
 {-# NOINLINE maxIndex #-}
 -- | Index (subscript) of the last element in a 'Vec'tor
@@ -837,8 +837,8 @@
 -- <7,2,3,4,5>
 -- >>> replace 9 7 (1:>2:>3:>4:>5:>Nil)
 -- <1,2,3,4,*** Exception: CLaSH.Sized.Vector.replace: index 9 is larger than maximum index 4
-replace :: (KnownNat n, Integral i) => i -> a -> Vec n a -> Vec n a
-replace i y xs = replace_int xs (fromIntegral i) y
+replace :: (KnownNat n, Enum i) => i -> a -> Vec n a -> Vec n a
+replace i y xs = replace_int xs (fromEnum i) y
 
 {-# INLINABLE take #-}
 -- | 'take' @n@, applied to a vector @xs@, returns the @n@-length prefix of @xs@
diff --git a/src/CLaSH/Tutorial.hs b/src/CLaSH/Tutorial.hs
--- a/src/CLaSH/Tutorial.hs
+++ b/src/CLaSH/Tutorial.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE NoImplicitPrelude, MagicHash #-}
 {-# OPTIONS_GHC -fno-warn-unused-imports #-}
 
 {-|
@@ -27,7 +27,7 @@
   -- *** Circuit testbench
   -- $mac4
 
-  -- *** Generating SystemVerilog
+  -- *** Generating Verilog and SystemVerilog
   -- $mac5
 
   -- *** Alternative specifications
@@ -42,6 +42,9 @@
   -- * TopEntity annotations: controlling the VHDL\/Verilog\/SystemVerilog generation.
   -- $annotations
 
+  -- * Multiple clock domains
+  -- $multiclock
+
   -- * Advanced: Primitives
   -- $primitives
 
@@ -67,9 +70,11 @@
 
 import CLaSH.Prelude
 import CLaSH.Prelude.Explicit
+import CLaSH.Prelude.BlockRam
 import Data.Char
 import Data.Int
 import GHC.Word
+import Data.Default
 
 -- $setup
 -- >>> :set -XTemplateHaskell
@@ -524,10 +529,13 @@
 
 >>> sampleN 7 $ expectedOutput (topEntity testInput)
 [False,False,False,False,
+cycle(system1000): 4, outputVerifier
 expected value: 14, not equal to actual value: 30
 True,
+cycle(system1000): 5, outputVerifier
 expected value: 14, not equal to actual value: 46
 True,
+cycle(system1000): 6, outputVerifier
 expected value: 14, not equal to actual value: 62
 True]
 
@@ -713,7 +721,7 @@
 which, together with 'bundle' and 'unbundle' defines the isomorphism between a
 product type of 'Signal's and a 'Signal' of a product type. That is, while
 @(Signal a, Signal b)@ and @Signal (a,b)@ are not equal, they are /isomorphic/
-and can be converted from on to the other using 'bundle' and 'unbundle'.
+and can be converted from, or to, the other using 'bundle' and 'unbundle'.
 
 Instances of this 'Bundle' type-class are defined as /isomorphisms/ for:
 
@@ -999,72 +1007,73 @@
 is actually just like a @newtype@ wrapper for 'Integer'.
 
 The second kind of primitive that we will explore is the /declaration/ primitive.
-We will use 'cblockRam' as an example, for which the Haskell/CλaSH code is:
+We will use 'blockRam#' as an example, for which the Haskell/CλaSH code is:
 
 @
-{\-\# NOINLINE blockRam' \#-\}
--- | Create a blockRAM with space for @n@ elements
---
--- * \_\_NB\_\_: Read value is delayed by 1 cycle
--- * \_\_NB\_\_: Initial output value is \'undefined\'
---
--- \@
--- type ClkA = Clk \\\"A\\\" 100
---
--- clkA100 :: SClock ClkA
--- clkA100 = sclock
---
--- bram40 :: Signal' ClkA (Unsigned 6) -> Signal' ClkA (Unsigned 6)
---        -> Signal' ClkA Bool -> Signal' ClkA Bit -> Signal' ClkA Bit
--- bram40 = \'blockRam'' clkA100 (\'CLaSH.Sized.Vector.replicate\' d40 1)
--- \@
-blockRam' :: ('GHC.TypeLits.KnownNat' n, 'GHC.TypeLits.KnownNat' m)
-          => 'SClock' clk               -- ^ \'Clock\' to synchronize to
-          -> 'Vec' n a                  -- ^ Initial content of the BRAM, also
-                                      -- determines the size, \@n\@, of the BRAM.
-                                      --
-                                      -- \_\_NB\_\_: \_\_MUST\_\_ be a constant.
-          -> 'Signal'' clk ('Unsigned' m) -- ^ Write address \@w\@
-          -> 'Signal'' clk ('Unsigned' m) -- ^ Read address \@r\@
-          -> 'Signal'' clk Bool         -- ^ Write enable
-          -> 'Signal'' clk a            -- ^ Value to write (at address \@w\@)
+{\-\# NOINLINE blockRam# \#-\}
+-- | blockRAM primitive
+blockRam' :: 'GHC.TypeLits.KnownNat' n
+          => 'SClock' clk       -- ^ \'Clock\' to synchronize to
+          -> 'Vec' n a          -- ^ Initial content of the BRAM, also
+                              -- determines the size, \@n\@, of the BRAM.
+                              --
+                              -- \_\_NB\_\_: \_\_MUST\_\_ be a constant.
+          -> 'Signal'' clk 'Int'  -- ^ Write address \@w\@
+          -> 'Signal'' clk 'Int'  -- ^ Read address \@r\@
+          -> 'Signal'' clk Bool -- ^ Write enable
+          -> 'Signal'' clk a    -- ^ Value to write (at address \@w\@)
           -> 'Signal'' clk a
           -- ^ Value of the \@blockRAM\@ at address \@r\@ from the previous clock
           -- cycle
-blockRam' clk binit wr rd en din =
-    'mealy'' clk bram' (binit,undefined) ('bundle'' clk (wr,rd,en,din))
+blockRam' clk binit wr rd en din = 'register'' clk undefined dout
   where
-    bram' (ram,o) (w,r,e,d) = ((ram',o'),o)
-      where
-        ram' | e         = 'replace' ram w d
-             | otherwise = ram
-        o'               = ram '!!' r
+    szI  = fromInteger $ 'maxIndex' content
+    dout = runST $ do
+      arr <- newListArray (0,szI) ('toList' content)
+      traverse (ramT arr) ('bundle'' clk (wr,rd,en,din))
+
+    ramT :: STArray s Int e -> (Int,Int,Bool,e) -> ST s e
+    ramT ram (w,r,e,d) = do
+      d' <- readArray ram r
+      when e (writeArray ram w d)
+      return d'
 @
 
 And for which the /definition/ primitive is:
 
 @
 { \"BlackBox\" :
-    { "name"      : "CLaSH.Prelude.BlockRam.blockRam'"
+    { "name"      : "CLaSH.Prelude.BlockRam.blockRam#"
     , "templateD" :
 "blockRam_~COMPNAME_~SYM[0] : block
-  signal ~SYM[1] : ~TYP[3] := ~LIT[3]; -- ram
-  signal ~SYM[2] : ~TYP[7]; -- inp
-  signal ~SYM[3] : ~TYP[7]; -- outp
+  signal RAM  : ~TYP[2] := ~LIT[2];
+  signal dout : ~TYP[6];
+  signal wr   : integer range 0 to ~LIT[0] - 1;
+  signal rd   : integer range 0 to ~LIT[0] - 1;
 begin
-  ~SYM[2] <= ~ARG[7];
+  wr <= ~ARG[3]
+  -- pragma translate_off
+        mod ~LIT[0]
+  -- pragma translate_on
+        ;
 
-  process(~CLK[2])
+  rd <= ~ARG[4]
+  -- pragma translate_off
+        mod ~LIT[0]
+  -- pragma translate_on
+        ;
+
+  blockRam_~SYM[1] : process(~CLK[1])
   begin
-    if rising_edge(~CLK[2]) then
-      if ~ARG[6] then
-        ~SYM[1](to_integer(~ARG[4])) <= ~SYM[2];
+    if rising_edge(~CLK[1]) then
+      if ~ARG[5] then
+        RAM(wr) <= ~ARG[6];
       end if;
-      ~SYM[3] <= ~SYM[1](to_integer(~ARG[5]));
+      dout <= RAM(rd);
     end if;
   end process;
 
-  ~RESULT <= ~SYM[3];
+  ~RESULT <= dout;
 end block;"
     }
   }
@@ -1138,29 +1147,30 @@
 
 @
 { \"BlackBox\" :
-    { "name"      : "CLaSH.Prelude.BlockRam.blockRam'"
+    { "name"      : "CLaSH.Prelude.BlockRam.blockRam#"
     , "templateD" :
-"// blockRam
-reg ~TYPO ~SYM[0] [0:~LIT[0]-1];
-reg ~SIGD[~SYM[1]][7];
+"// blockRam begin
+reg ~TYPO RAM_~SYM[0] [0:~LIT[0]-1];
+reg ~TYPO dout_~SYM[1];
 
-reg ~TYP[3] ~SYM[2];
+reg ~TYP[2] ram_init_~SYM[2];
 integer ~SYM[3];
 initial begin
-  ~SYM[2] = ~ARG[3];
+  ram_init_~SYM[2] = ~ARG[2];
   for (~SYM[3]=0; ~SYM[3] < ~LIT[0]; ~SYM[3] = ~SYM[3] + 1) begin
-    ~SYM[0][~LIT[0]-1-~SYM[3]] = ~SYM[2][~SYM[3]*~SIZE[~TYPO]+:~SIZE[~TYPO]];
+    RAM_~SYM[0][~LIT[0]-1-~SYM[3]] = ram_init_~SYM[2][~SYM[3]*~SIZE[~TYPO]+:~SIZE[~TYPO]];
   end
 end
 
-always @(posedge ~CLK[2]) begin : blockRam_~COMPNAME_~SYM[4]
-  if (~ARG[6]) begin
-    ~SYM[0][~ARG[4]] <= ~ARG[7];
+always @(posedge ~CLK[1]) begin : blockRam_~COMPNAME_~SYM[4]
+  if (~ARG[5]) begin
+    RAM_~SYM[0][~ARG[3]] <= ~ARG[6];
   end
-  ~SYM[1] <= ~SYM[0][~ARG[5]];
+  dout_~SYM[1] <= RAM_~SYM[0][~ARG[4]];
 end
 
-assign ~RESULT = ~SYM[1];"
+assign ~RESULT = dout_~SYM[1];
+// blockRam end"
     }
   }
 @
@@ -1184,23 +1194,304 @@
     { "name"      : "CLaSH.Prelude.BlockRam.blockRam'"
     , "templateD" :
 "// blockRam
-~SIGD[~SYM[0]][3];
-~SIGD[~SYM[1]][7];
+~SIGD[RAM_~SYM[0]][2];
+~SIGD[dout_~SYM[1]][6];
 
 initial begin
   ~SYM[0] = ~LIT[3];
 end
 
-always @(posedge ~CLK[2]) begin
-  if (~ARG[6]) begin
-    ~SYM[0][~ARG[4]] <= ~ARG[7];
+always @(posedge ~CLK[1]) begin : blockRam_~COMPNAME_~SYM[3]
+  if (~ARG[5]) begin
+    RAM_~SYM[0][~ARG[3]] <= ~ARG[6];
   end
-  ~SYM[1] <= ~SYM[0][~ARG[5]];
+  dout_~SYM[1] <= RAM_~SYM[0][~ARG[4]];
 end
 
-assign ~RESULT = ~SYM[1];"
+assign ~RESULT = dout_~SYM[1];"
     }
   }
+@
+
+-}
+
+{- $multiclock #multiclock#
+CλaSH supports multi-clock designs, though perhaps in a slightly limited form.
+What is possible is:
+
+* Explicitly assign clocks to memory primitives.
+* Synchronise between differently-clocked parts of your design in a type-safe
+  way.
+
+What is /not/ possible is:
+
+* Generate a clock signal in module A, and assign this clock signal to a memory
+  primitive in module B.
+
+What this means is that when CλaSH converts your design to VHDL/(System)Verilog,
+you end up with a top-level module/entity with multiple clock and reset ports
+for the different clock domains. If you're targeting an FPGA, you can use e.g. a
+<https://www.altera.com/literature/ug/ug_altpll.pdf PPL> or
+<http://www.xilinx.com/support/documentation/user_guides/ug472_7Series_Clocking.pdf MMCM>
+to provide the clock signals.
+
+== Building a FIFO synchroniser
+
+This part of the tutorial assumes you know what <https://en.wikipedia.org/wiki/Metastability_in_electronics metastability>
+is, and how it can never truly be avoided in any asynchronous circuit. Also
+it assumes that you are familiar with the design of synchronizer circuits, and
+why a dual flip-flop synchroniser only works for bit-synchronisation and not
+word-synchronisation.
+The explicitly clocked versions of all synchronous functions and primitives can
+be found in "CLaSH.Prelude.Explicit", which also re-exports the functions in
+"CLaSH.Signal.Explicit". We will use those functions to create a FIFO where
+the read and write port are synchronised to different clocks. Below you can find
+the code to build the FIFO synchroniser based on the design described in:
+<http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf>
+
+We start with enable a few options that will make wring the type-signatures for
+our components a bit easier. We'll also import the standard "CLaSH.Prelude"
+module, and the "CLaSH.Prelude.Explicit" module for our explicitly clocked
+synchronous functions:
+
+@
+{\-\# LANGUAGE PartialTypeSignatures \#-\}
+{\-\# OPTIONS_GHC -fno-warn-partial-type-signatures \#-\}
+module MultiClockFifo where
+
+import CLaSH.Prelude
+import CLaSH.Prelude.Explicit
+@
+
+Then we'll start with the /hart/ of the FIFO synchroniser, an asynchronous RAM
+in the form of 'asyncRam''. It's called an asynchronous RAM because the read
+port is not synchronised to any clock (though the write port is). Note that in
+CλaSH we don't really have asynchronous logic, there is only combinational and
+synchronous logic. As a consequence, we see in the type signature of 'asyncRam'':
+
+    *
+
+    @
+    __asyncRam'__ :: _ => SClock wclk        -- ^ Clock to which to synchronise the write port of the RAM
+                   -> SClock rclk        -- ^ Clock to which the read address signal __r__ is synchronised
+                   -> SNat n             -- ^ Size __n__ of the RAM
+                   -> Signal' wclk addr  -- ^ Write address __w__
+                   -> Signal' rclk addr  -- ^ Read address __r__
+                   -> Signal' wclk Bool  -- ^ Write enable
+                   -> Signal' wclk a     -- ^ Value to write (at address __w__)
+                   -> Signal' rclk a     -- ^ Value of the RAM at address __r__
+    @
+
+that the signal containing the read address __r__ is synchronised to a different
+clock. That is, there is __no__ such thing as an @AsyncSignal@ in CλaSH.
+
+We continue by instantiating the 'asyncRam'':
+
+@
+fifoMem wclk rclk addrSize waddr raddr winc wfull wdata =
+  'asyncRam'' wclk rclk
+            (d2 ``powSNat`` addrSize)
+            waddr raddr
+            (winc '.&&.' 'not1' wfull)
+            wdata
+@
+
+We see that we give it @2^addrSize@ elements, where @addrSize@ is the bit-size
+of the address. Also, we only write new values to the ram when a new write is
+requested, indicated by @winc@, and the buffer is not full, indicated by
+@wfull@.
+
+The next part of the design calculates the read and write address for the
+asynchronous RAM, and creates the flags indicating whether the FIFO is full
+or empty. We start with a function that converts 'Bool'eans to @n + 1@ bit
+bitvectors:
+
+@
+boolToBV :: (KnownNat n, KnownNat (n+1)) => Bool -> BitVector (n + 1)
+boolToBV = 'zeroExtend' . 'pack'
+@
+
+followed by the actual address and flag generator in 'mealy' machine style:
+
+@
+ptrCompareT addrSize flagGen (bin,ptr,flag) (s_ptr,inc) = ((bin',ptr',flag')
+                                                          ,(flag,addr,ptr))
+  where
+    -- GRAYSTYLE2 pointer
+    bin' = bin + boolToBV (inc && not flag)
+    ptr' = (bin' \`shiftR\` 1) \`xor\` bin'
+    addr = 'slice' (addrSize ``subSNat``  d1) d0 bin
+
+    flag' = flagGen ptr' s_ptr
+@
+
+It is parametrised in both address size, @addrSize@, and status flag generator,
+@flagGen@. It has two inputs, @s_ptr@, the synchronised pointer from the other
+clock domain, and @inc@, which indicates we want to perform a write or read of
+the FIFO. It creates three outputs: @flag@, the full or empty flag, @addr@, the
+read or write address into the RAM, and @ptr@, the Gray-encoded version of the
+read or write address which will be synchronised between the two clock domains.
+
+Next follow the initial states of address generators, and the flag generators
+for the empty and full flags:
+
+@
+-- FIFO empty: when next pntr == synchronized wptr or on reset
+isEmpty       = (==)
+rptrEmptyInit = (0,0,True)
+
+-- FIFO full: when next pntr == synchonized {~wptr[addrSize:addrSize-1],wptr[addrSize-1:0]}
+isFull addrSize ptr s_ptr = ptr == ('complement' ('slice' addrSize (addrSize ``subSNat`` d1) s_ptr) '++#'
+                                   'slice' (addrSize ``subSNat`` d2) d0 s_ptr)
+wptrFullInit        = (0,0,False)
+@
+
+We create a dual flip-flop synchroniser to be used to synchronise the
+Gray-encoded pointers between the two clock domains:
+
+@
+ptrSync clk1 clk2 = 'register'' clk2 0
+                  . 'register'' clk2 0
+                  . 'unsafeSynchronizer' clk1 clk2
+@
+
+It uses the 'unsafeSynchroniser' primitive, which is needed to go from one clock
+domain to the other. All synchronizers are specified in terms of
+'unsafeSynchronizer' (see for example the <src/CLaSH-Prelude-RAM.html#line-103 source of asyncRam#>).
+The 'unsafeSynchronizer' primitive is turned into a (bundle of) wire(s) by the
+CλaSH compiler, so developers must ensure that it is only used as part of a
+proper synchronizer.
+
+Finally we combine all the component in:
+
+@
+fifo :: _
+     => SNat addrSize -> SClock wclk -> SClock rclk
+     -> Signal' wclk a -> Signal' wclk Bool
+     -> Signal' rclk Bool
+     -> (Signal' rclk a, Signal' rclk Bool, Signal' wclk Bool)
+fifo addrSize wclk rclk wdata winc rinc = (rdata,rempty,wfull)
+  where
+    s_rptr = ptrSync wclk rclk rptr
+    s_wptr = ptrSync rclk wclk wptr
+
+    rdata = fifoMem wclk rclk addrSize waddr raddr winc wfull wdata
+
+    (rempty,raddr,rptr) = 'mealyB'' rclk (ptrCompareT addrSize isEmpty) rptrEmptyInit
+                                  (s_wptr,rinc)
+
+    (wfull,waddr,wptr)  = 'mealyB'' wclk (ptrCompareT addrSize (isFull addrSize))
+                                  wptrFullInit (s_rptr,winc)
+@
+
+where we first specify the synchronisation of the read and the write pointers,
+instantiate the asynchronous RAM, and instantiate the read address/pointer/flag
+generator and write address/pointer/flag generator.
+
+Ultimately, the whole file containing our FIFO design will look like this:
+
+@
+{\-\# LANGUAGE PartialTypeSignatures \#-\}
+{\-\# OPTIONS_GHC -fno-warn-partial-type-signatures \#-\}
+module MultiClockFifo where
+
+import CLaSH.Prelude
+import CLaSH.Prelude.Explicit
+
+fifoMem wclk rclk addrSize waddr raddr winc wfull wdata =
+  'asyncRam'' wclk rclk
+            (d2 ``powSNat`` addrSize)
+            waddr raddr
+            (winc '.&&.' 'not1' wfull)
+            wdata
+
+boolToBV :: (KnownNat n, KnownNat (n+1)) => Bool -> BitVector (n + 1)
+boolToBV = 'zeroExtend' . 'pack'
+
+ptrCompareT addrSize flagGen (bin,ptr,flag) (s_ptr,inc) = ((bin',ptr',flag')
+                                                          ,(flag,addr,ptr))
+  where
+    -- GRAYSTYLE2 pointer
+    bin' = bin + boolToBV (inc && not flag)
+    ptr' = (bin' \`shiftR\` 1) \`xor\` bin'
+    addr = 'slice' (addrSize ``subSNat`` d1) d0 bin
+
+    flag' = flagGen ptr' s_ptr
+
+-- FIFO empty: when next pntr == synchronized wptr or on reset
+isEmpty       = (==)
+rptrEmptyInit = (0,0,True)
+
+-- FIFO full: when next pntr == synchonized {~wptr[addrSize:addrSize-1],wptr[addrSize-1:0]}
+isFull addrSize ptr s_ptr = ptr == ('complement' ('slice' addrSize (addrSize ``subSNat`` d1) s_ptr) '++#'
+                                   'slice' (addrSize ``subSNat`` d2) d0 s_ptr)
+wptrFullInit        = (0,0,False)
+
+-- Dual flip-flip synchroniser
+ptrSync clk1 clk2 = 'register'' clk2 0
+                  . 'register'' clk2 0
+                  . 'unsafeSynchronizer' clk1 clk2
+
+-- Async FIFO synchroniser
+fifo :: _
+     => SNat addrSize -> SClock wclk -> SClock rclk
+     -> Signal' wclk a -> Signal' wclk Bool
+     -> Signal' rclk Bool
+     -> (Signal' rclk a, Signal' rclk Bool, Signal' wclk Bool)
+fifo addrSize wclk rclk wdata winc rinc = (rdata,rempty,wfull)
+  where
+    s_rptr = ptrSync rclk wclk rptr
+    s_wptr = ptrSync wclk rclk wptr
+
+    rdata = fifoMem wclk rclk addrSize waddr raddr winc wfull wdata
+
+    (rempty,raddr,rptr) = 'mealyB'' rclk (ptrCompareT addrSize isEmpty) rptrEmptyInit
+                                  (s_wptr,rinc)
+
+    (wfull,waddr,wptr)  = 'mealyB'' wclk (ptrCompareT addrSize (isFull addrSize))
+                                  wptrFullInit (s_rptr,winc)
+@
+
+== Instantiating a FIFO synchroniser
+
+Having finished our FIFO synchroniser it's time to instantiate with concrete
+clock domains. Let us assume we have part of our system connected to an ADC
+which runs at 20 MHz, and we have created an FFT component running at only 9 MHz,
+while the rest of our system runs at 50 MHz. What we want to do connect part
+of our design connected to the ADC, and running at 20 MHz, to part of our design
+connected to the FFT running at 9 MHz.
+
+First, we must calculate the relative clock periods using 'freqCalc':
+
+>>> freqCalc [20,9,50]
+[45,100,18]
+
+We can then create the clocks:
+
+@
+type ClkADC = 'Clk \"ADC\"    45
+type ClkFFT = 'Clk \"FFT\"    100
+type ClkSys = 'Clk \"System\" 18
+
+clkADC :: SClock ClkADC
+clkADC = sclock
+
+clkFFT :: SClock ClkFFT
+clkFFT = sclock
+
+clkSys :: SClock ClkSys
+clkSys = sclock
+@
+
+and subsequently a 256-space FIFO synchroniser that safely bridges the ADC clock
+domain and to the FFT clock domain:
+
+@
+adcToFFT :: Signal' ClkADC (SFixed 8 8)
+         -> Signal' ClkADC Bool
+         -> Signal' ClkFFT Bool
+         -> (Signal' ClkFFT (SFixed 8 8), Signal' ClkFFT Bool, Signal' ClkADC Bool)
+adcToFFT = fifo d8 clkADC clkFFT
 @
 
 -}
