{-| 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 FlexibleContexts #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Safe #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_HADDOCK show-extensions #-} module Clash.Prelude.ROM ( -- * Asynchronous ROM asyncRom , asyncRomPow2 -- * Synchronous ROM synchronised 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) -- | 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 :: (KnownNat n, KnownNat m, HiddenClock domain gated) => Vec n a -- ^ ROM content -- -- __NB:__ must be a constant -> Signal domain (Unsigned m) -- ^ Read address @rd@ -> Signal domain a -- ^ The value of the ROM at address @rd@ rom = 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 :: (KnownNat n, HiddenClock domain gated) => 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 = hideClock E.romPow2 {-# INLINE romPow2 #-}