clash-protocols-0.1: src/Protocols/PacketStream/AsyncFifo.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_HADDOCK hide #-}
{- |
Copyright : (C) 2024, QBayLogic B.V.
License : BSD2 (see the file LICENSE)
Maintainer : QBayLogic B.V. <devops@qbaylogic.com>
Provides `asyncFifoC` for crossing clock domains in the packet stream protocol.
-}
module Protocols.PacketStream.AsyncFifo (asyncFifoC) where
import Data.Maybe.Extra (toMaybe)
import Clash.Explicit.Prelude (asyncFIFOSynchronizer)
import Clash.Prelude
import Protocols
import Protocols.PacketStream.Base
{- | Asynchronous FIFO circuit that can be used to safely cross clock domains.
Uses `Clash.Explicit.Prelude.asyncFIFOSynchronizer` internally.
-}
asyncFifoC ::
forall
(wDom :: Domain)
(rDom :: Domain)
(depth :: Nat)
(dataWidth :: Nat)
(meta :: Type).
(KnownDomain wDom) =>
(KnownDomain rDom) =>
(KnownNat depth) =>
(KnownNat dataWidth) =>
(2 <= depth) =>
(1 <= dataWidth) =>
(NFDataX meta) =>
-- | 2^depth is the number of elements this component can store
SNat depth ->
-- | Clock signal in the write domain
Clock wDom ->
-- | Reset signal in the write domain
Reset wDom ->
-- | Enable signal in the write domain
Enable wDom ->
-- | Clock signal in the read domain
Clock rDom ->
-- | Reset signal in the read domain
Reset rDom ->
-- | Enable signal in the read domain
Enable rDom ->
Circuit (PacketStream wDom dataWidth meta) (PacketStream rDom dataWidth meta)
asyncFifoC depth wClk wRst wEn rClk rRst rEn =
exposeClockResetEnable forceResetSanity wClk wRst wEn |> fromSignals ckt
where
ckt (fwdIn, bwdIn) = (bwdOut, fwdOut)
where
(element, isEmpty, isFull) = asyncFIFOSynchronizer depth wClk rClk wRst rRst wEn rEn readReq fwdIn
notEmpty = not <$> isEmpty
-- If the FIFO is empty, we output Nothing. Else, we output the oldest element.
fwdOut = toMaybe <$> notEmpty <*> element
-- Assert backpressure when the FIFO is full.
bwdOut = PacketStreamS2M . not <$> isFull
-- Next component is ready to read if the fifo is not empty and it does not assert backpressure.
readReq = notEmpty .&&. _ready <$> bwdIn