{-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> ROMs -} {-# LANGUAGE DataKinds #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Safe #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_HADDOCK show-extensions #-} module Clash.Explicit.ROM ( -- * Synchronous ROM synchronised to an arbitrary clock rom , romPow2 -- * Internal , rom# ) where import Data.Array ((!),listArray) import GHC.TypeLits (KnownNat, type (^)) import Prelude hiding (length) -- import Clash.Signal (Signal) -- import Clash.Signal.Explicit (Signal', SClock, systemClockGen) import Clash.Explicit.Signal (Clock, Signal, delay) import Clash.Sized.Unsigned (Unsigned) -- import Clash.Signal.Explicit (register') import Clash.Sized.Vector (Vec, length, toList) -- import Clash.XException (errorX) -- | 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.Explicit.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs romPow2 :: KnownNat n => Clock domain gated -- ^ 'Clock' to synchronize to -> Vec (2^n) a -- ^ ROM content -- -- __NB:__ must be a constant -> Signal domain (Unsigned n) -- ^ Read address @rd@ -> Signal domain a -- ^ The value of the ROM at address @rd@ romPow2 = rom {-# INLINE romPow2 #-} -- | 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.Explicit.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs rom :: (KnownNat n, Enum addr) => Clock domain gated -- ^ 'Clock' to synchronize to -> Vec n a -- ^ ROM content -- -- __NB:__ must be a constant -> Signal domain addr -- ^ Read address @rd@ -> Signal domain a -- ^ The value of the ROM at address @rd@ from the previous clock cycle rom = \clk content rd -> rom# clk content (fromEnum <$> rd) {-# INLINE rom #-} -- | ROM primitive rom# :: KnownNat n => Clock domain gated -- ^ 'Clock' to synchronize to -> Vec n a -- ^ ROM content -- -- __NB:__ must be a constant -> Signal domain Int -- ^ Read address @rd@ -> Signal domain a -- ^ The value of the ROM at address @rd@ from the previous clock cycle rom# clk content rd = delay clk ((arr !) <$> rd) where szI = length content arr = listArray (0,szI-1) (toList content) {-# NOINLINE rom# #-}