1

How do I correctly use readNew?

A minimal example with two modules which just reads and writes an asyncRam:

TopLevel.hs

module TopLevel where

import Clash.Prelude
import LowerLevel

topEntity 
  :: Clock System Source
  -> Reset System Asynchronous
  -> Signal System (Unsigned 5)
  -> Signal System (Maybe (Unsigned 5, BitVector 5))
  -> Signal System (BitVector 5)
topEntity = exposeClockReset topLevel

topLevel :: HiddenClockReset dom gated sync
         => Signal dom (Unsigned 5)
         -> Signal dom (Maybe (Unsigned 5, BitVector 5))
         -> Signal dom (BitVector 5)
topLevel rdAddr wrM = lowerLevel rdAddr wrM

LowerLevel.hs

module LowerLevel where

import Clash.Prelude

lowerLevel :: HiddenClockReset dom gated sync
           => Signal dom (Unsigned 5)
           -> Signal dom (Maybe (Unsigned 5, BitVector 5))
           -> Signal dom (BitVector 5)
lowerLevel rdAddr wrM = readNew (asyncRam d32) rdAddr wrM

Currently, when I compile this code I receive metastability warnings (though it is successful):

Compiling: TopLevel.topEntity LowerLevel.$sreadNew20998 (::
GHC.Classes.IP   rst   (Clash.Signal.Internal.Reset
     (Clash.Signal.Internal.Dom system 10000)
     Clash.Signal.Internal.Asynchronous)
-> GHC.Classes.IP
     clk
     (Clash.Signal.Internal.Clock
        (Clash.Signal.Internal.Dom system 10000)
        Clash.Signal.Internal.Source)
-> Clash.Signal.Internal.Clock
     (Clash.Signal.Internal.Dom system 10000)
     Clash.Signal.Internal.Source
-> Clash.Signal.Internal.Signal
     (Clash.Signal.Internal.Dom system 10000)
     (Clash.Sized.Internal.Unsigned.Unsigned 5)
-> Clash.Signal.Internal.Signal
     (Clash.Signal.Internal.Dom system 10000)
     (GHC.Base.Maybe
        (GHC.Tuple.(,)
           (Clash.Sized.Internal.Unsigned.Unsigned 5)
           (Clash.Sized.Internal.BitVector.BitVector 5)))
-> Clash.Sized.Internal.BitVector.BitVector 5) has potentially dangerous meta-stability issues:

The following clocks:
* GHC.Classes.IP   clk   (Clash.Signal.Internal.Clock
     (Clash.Signal.Internal.Dom system 10000)
     Clash.Signal.Internal.Source)
* Clash.Signal.Internal.Clock   (Clash.Signal.Internal.Dom system 10000)   Clash.Signal.Internal.Source belong to the same clock domain
and should be connected to the same clock source in order to prevent
meta-stability issues.

I've done some research and found this google group answer. I'm pretty sure this is what I should do, but I am not sure how to implement.

How would I inline asyncRam clk d32 as mentioned in the post? How do I get the "free clk"? I was experimenting with the readNew from Clash.Explicit.Prelude (unsuccessfully), but I don't understand why I can't just use the Prelude version. I figure there might be some need to exposeClockReset but from what I've read it seems like there's two clocks from the same domain being used to circumvent the metastability warnings? Please clarify, thanks!

Update: This is a known issue. I am told it is fine to ignore the compiler warnings for now.

dopamane
  • 1,315
  • 2
  • 14
  • 27

0 Answers0