{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module Clash.Explicit.DDR
( ddrIn
, ddrOut
, ddrIn#
, ddrOut#
)
where
import GHC.Stack (HasCallStack, withFrozenCallStack)
import Clash.Annotations.Primitive (hasBlackBox)
import Clash.Explicit.Prelude
import Clash.Signal.Internal
ddrIn
:: ( HasCallStack
, NFDataX a
, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
, KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )
=> Clock slow
-> Reset slow
-> Enable slow
-> (a, a, a)
-> Signal fast a
-> Signal slow (a, a)
ddrIn clk rst en (i0,i1,i2) =
withFrozenCallStack $ ddrIn# clk rst en i0 i1 i2
ddrIn#
:: forall a slow fast fPeriod polarity edge reset init
. ( HasCallStack
, NFDataX a
, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
, KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )
=> Clock slow
-> Reset slow
-> Enable slow
-> a
-> a
-> a
-> Signal fast a
-> Signal slow (a,a)
ddrIn# (Clock _) (unsafeToHighPolarity -> hRst) (fromEnable -> ena) i0 i1 i2 =
case resetKind @fast of
SAsynchronous ->
goAsync
( deepErrorX "ddrIn: initial value 0 undefined"
, deepErrorX "ddrIn: initial value 1 undefined"
, deepErrorX "ddrIn: initial value 2 undefined" )
hRst
ena
SSynchronous ->
goSync
( deepErrorX "ddrIn: initial value 0 undefined"
, deepErrorX "ddrIn: initial value 1 undefined"
, deepErrorX "ddrIn: initial value 2 undefined" )
hRst
ena
where
goSync
:: (a, a, a)
-> Signal slow Bool
-> Signal slow Bool
-> Signal fast a
-> Signal slow (a,a)
goSync (o0,o1,o2) rt@(~(r :- rs)) ~(e :- es) as@(~(x0 :- x1 :- xs)) =
let (o0',o1',o2') = if r then (i0,i1,i2) else (o2,x0,x1)
in o0 `seqX` o1 `seqX` (o0,o1)
:- (rt `seq` as `seq` if e then goSync (o0',o1',o2') rs es xs
else goSync (o0 ,o1 ,o2) rs es xs)
goAsync
:: (a, a, a)
-> Signal slow Bool
-> Signal slow Bool
-> Signal fast a
-> Signal slow (a, a)
goAsync (o0,o1,o2) ~(r :- rs) ~(e :- es) as@(~(x0 :- x1 :- xs)) =
let (o0',o1',o2',o3',o4') = if r then (i0,i1,i0,i1,i2) else (o0,o1,o2,x0,x1)
in o0' `seqX` o1' `seqX` (o0',o1')
:- (as `seq` if e then goAsync (o2',o3',o4') rs es xs
else goAsync (o0',o1',o2') rs es xs)
{-# NOINLINE ddrIn# #-}
{-# ANN ddrIn# hasBlackBox #-}
ddrOut
:: ( HasCallStack
, NFDataX a
, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
, KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )
=> Clock slow
-> Reset slow
-> Enable slow
-> a
-> Signal slow (a, a)
-> Signal fast a
ddrOut clk rst en i0 =
uncurry (withFrozenCallStack $ ddrOut# clk rst en i0) . unbundle
ddrOut#
:: ( HasCallStack
, NFDataX a
, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
, KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )
=> Clock slow
-> Reset slow
-> Enable slow
-> a
-> Signal slow a
-> Signal slow a
-> Signal fast a
ddrOut# clk rst en i0 xs ys =
let (_ :- out) = zipSig xs' ys' in out
where
xs' = register# clk rst en (error "ddrOut: unreachable error") i0 xs
ys' = register# clk rst en (deepErrorX "ddrOut: initial value undefined") i0 ys
zipSig (a :- as) (b :- bs) = a :- b :- zipSig as bs
{-# NOINLINE ddrOut# #-}
{-# ANN ddrOut# hasBlackBox #-}