clash-prelude-1.6.0: tests/Clash/Tests/BlockRam.hs
{-# LANGUAGE NoImplicitPrelude #-}
module Clash.Tests.BlockRam (tests) where
import qualified Data.List as List
import Test.Tasty
import Test.Tasty.HUnit
import qualified Clash.Explicit.Prelude as E
import Clash.Explicit.BlockRam (blockRam#)
import Clash.Prelude
readRam
:: (HiddenClockResetEnable dom)
=> Signal dom (Unsigned 4)
-> Signal dom (Unsigned 8)
readRam addr = mux (register False $ addr .<. 8) ram (pure 0xff)
where
ram = blockRam1 NoClearOnReset (SNat @8) 0 addr (pure Nothing)
-- If the block RAM uses the address argument too strictly, then it will
-- attempt to access an out of bounds address when using readRam.
--
addrNotTooStrict :: Assertion
addrNotTooStrict =
let addr = fromList [0..15]
in List.tail (sampleN @System 15 (readRam addr)) @?=
[255,0,0,0,0,0,0,0,255,255,255,255,255,255]
primRam
:: Signal System Int
-> Signal System Bool
-> Signal System Int
-> Signal System Int
-> Signal System (Maybe Int)
primRam rd we wr din =
maybeIsX <$> blockRam# clockGen enableGen (0 :> 1 :> Nil) rd we wr din
type PrimSamples = [(Int, Bool, Int, Int, Maybe Int)]
undefEn :: PrimSamples
-- Undefined enable:
-- The written-to address should read 'undefined', but other addresses
-- should still have their data.
-- rd enable waddr wdata dout
undefEn = [ ( 0, undefined, 0 , 2 , Nothing)
, ( 0, False , 0 , 3 , Just 0 )
, ( 1, False , 0 , 3 , Nothing)
, ( 1, False , 0 , 3 , Just 1 )
]
primRamAssertion
:: PrimSamples
-> Assertion
primRamAssertion samples = actual @?= expectedOutput
where
(rd, we, wr, din, expectedOutput) = List.unzip5 samples
actual = E.sampleN (List.length samples) $ primRam (fromList rd)
(fromList we)
(fromList wr)
(fromList din)
tests :: TestTree
tests = testGroup "BlockRam"
[ testCase "Address strictness" addrNotTooStrict
, testCase "Undefined enable" $ primRamAssertion undefEn
]