clash-prelude-0.6: src/CLaSH/Prelude/BlockRam.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
module CLaSH.Prelude.BlockRam where
import GHC.TypeLits (KnownNat, type (^))
import Prelude hiding ((!!))
import CLaSH.Prelude.Mealy (cmealy)
import CLaSH.Signal (Signal)
import CLaSH.Signal.Explicit (CSignal, SClock, systemClock)
import CLaSH.Signal.Bundle (bundle)
import CLaSH.Sized.Unsigned (Unsigned)
import CLaSH.Sized.Vector (Vec, (!!), replace)
{-# INLINE blockRam #-}
-- | Create a blockRAM with space for @n@ elements.
--
-- * __NB__: Read value is delayed by 1 cycle
-- * __NB__: Initial output value is 'undefined'
--
-- > bram40 :: Signal (Unsigned 6) -> Signal (Unsigned 6) -> Signal Bool
-- > -> Signal Bit -> Signal Bit
-- > bram40 = blockRam (replicate d40 H)
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@)
-> Signal a
-- ^ Value of the 'blockRAM' at address @r@ from the previous clock
-- cycle
blockRam = cblockRam systemClock
{-# INLINE blockRamPow2 #-}
-- | Create a blockRAM with space for 2^@n@ elements
--
-- * __NB__: Read value is delayed by 1 cycle
-- * __NB__: Initial output value is 'undefined'
--
-- > bram32 :: Signal (Unsigned 5) -> Signal (Unsigned 5) -> Signal Bool
-- > -> Signal Bit -> Signal Bit
-- > bram32 = blockRamPow2 (replicate d32 H)
blockRamPow2 :: (KnownNat (2^n), KnownNat n)
=> Vec (2^n) a -- ^ Initial content of the BRAM, also
-- determines the size, @2^n@, of the BRAM.
--
-- __NB__: __MUST__ be a constant.
-> 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 'blockRAM' at address @r@ from the previous clock
-- cycle
blockRamPow2 = blockRam
{-# NOINLINE cblockRam #-}
-- | 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 :: CSignal ClkA (Unsigned 6) -> CSignal ClkA (Unsigned 6)
-- > -> CSignal ClkA Bool -> CSignal ClkA Bit -> ClkA CSignal Bit
-- > bram40 = cblockRam clkA100 (replicate d40 H)
cblockRam :: (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.
-> CSignal clk (Unsigned m) -- ^ Write address @w@
-> CSignal clk (Unsigned m) -- ^ Read address @r@
-> CSignal clk Bool -- ^ Write enable
-> CSignal clk a -- ^ Value to write (at address @w@)
-> CSignal clk a
-- ^ Value of the 'blockRAM' at address @r@ from the previous clock
-- cycle
cblockRam clk binit wr rd en din =
cmealy clk bram' (binit,undefined) (bundle clk (wr,rd,en,din))
where
bram' (ram,o) (w,r,e,d) = ((ram',o'),o)
where
ram' | e = replace ram w d
| otherwise = ram
o' = ram !! r
{-# INLINE cblockRamPow2 #-}
-- | Create a blockRAM with space for 2^@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
-- >
-- > bramC32 :: CSignal ClkA (Unsigned 5) -> CSignal ClkA (Unsigned 5)
-- > -> CSignal ClkA Bool -> CSignal ClkA Bit -> CSignal ClkA Bit
-- > bramC32 = cblockRamPow2 clkA100 (replicate d32 H)
cblockRamPow2 :: (KnownNat n, KnownNat (2^n))
=> SClock clk -- ^ 'Clock' to synchronize to
-> Vec (2^n) a -- ^ Initial content of the BRAM, also
-- determines the size, @2^n@, of
-- the BRAM.
--
-- __NB__: __MUST__ be a constant.
-> CSignal clk (Unsigned n) -- ^ Write address @w@
-> CSignal clk (Unsigned n) -- ^ Read address @r@
-> CSignal clk Bool -- ^ Write enable
-> CSignal clk a -- ^ Value to write (at address @w@)
-> CSignal clk a
-- ^ Value of the 'blockRAM' at address @r@ from the previous
-- clock cycle
cblockRamPow2 = cblockRam