{-| Copyright : (C) 2015-2016, University of Twente, 2017 , Google Inc. 2019 , Myrtle Software Ltd License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> ROMs -} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE Safe #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_HADDOCK show-extensions #-} module Clash.Prelude.ROM ( -- * Asynchronous ROM asyncRom , asyncRomPow2 -- * Synchronous ROM synchronized to an arbitrary clock , rom , romPow2 -- * Internal , asyncRom# ) where import Data.Array ((!),listArray) import GHC.TypeLits (KnownNat, type (^)) import Prelude hiding (length) import qualified Clash.Explicit.ROM as E import Clash.Signal import Clash.Sized.Unsigned (Unsigned) import Clash.Sized.Vector (Vec, length, toList) import Clash.XException (NFDataX) -- | 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 asyncRom #-} -- | 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 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 {-# INLINE asyncRomPow2 #-} -- | 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 = length content arr = listArray (0,szI-1) (toList content) {-# NOINLINE asyncRom# #-} -- | 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 :: forall dom n m a . ( NFDataX a , KnownNat n , KnownNat m , HiddenClock dom , HiddenEnable dom ) => Vec n a -- ^ ROM content -- -- __NB:__ must be a constant -> Signal dom (Unsigned m) -- ^ Read address @rd@ -> Signal dom a -- ^ The value of the ROM at address @rd@ rom = hideEnable (hideClock E.rom) {-# INLINE rom #-} -- | 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 :: forall dom n a . ( KnownNat n , NFDataX a , HiddenClock dom , HiddenEnable dom ) => Vec (2^n) a -- ^ ROM content -- -- __NB:__ must be a constant -> Signal dom (Unsigned n) -- ^ Read address @rd@ -> Signal dom a -- ^ The value of the ROM at address @rd@ romPow2 = hideEnable (hideClock E.romPow2) {-# INLINE romPow2 #-}