{-|
Copyright  :  (C) 2017, Google Inc
                  2019, Myrtle Software Ltd
License    :  BSD2 (see the file LICENSE)
Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>

DDR primitives for Intel FPGAs using ALTDDIO primitives.

For general information about DDR primitives see "Clash.Explicit.DDR".

Note that a reset is only available on certain devices,
see the ALTDDIO user guide for the specifics:
<https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_altddio.pdf>
-}

{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}

module Clash.Intel.DDR
  ( altddioIn
  , altddioOut
    -- * Internal
  , altddioIn#
  , altddioOut#
  )
where

import Data.Bifunctor
import GHC.Stack (HasCallStack, withFrozenCallStack)

import Clash.Annotations.Primitive (hasBlackBox)
import Clash.Explicit.Prelude
import Clash.Explicit.DDR

-- | Intel specific variant of 'ddrIn' implemented using the ALTDDIO_IN IP core.
--
-- Reset values are @0@
--
-- Of the output pair @(o0, o1)@, @o0@ is the data clocked in on the /falling/
-- edge and @o1@ is the data clocked in on the /rising/ edge, and @o0@ comes
-- before @o1@ in time.
--
-- __NB__: This primitive only supports rising edges as the active edge.
altddioIn
  :: forall deviceFamily a dom domDDR
   . HasCallStack
  => KnownDomain dom
  => KnownDomain domDDR
  => DomainPeriod dom ~ (2 * DomainPeriod domDDR)
  => DomainActiveEdge dom ~ 'Rising
  => BitPack a
  => SSymbol deviceFamily
  -- ^ The FPGA family
  --
  -- For example this can be instantiated as follows:
  --
  -- > SSymbol @"Cyclone IV GX"
  -> Clock dom
  -> Reset dom
  -> Enable dom
  -> Signal domDDR a
  -- ^ DDR input signal
  -> Signal dom (a, a)
  -- ^ Normal speed output pair @(o0, o1)@
altddioIn :: forall (deviceFamily :: Symbol) a (dom :: Symbol)
       (domDDR :: Symbol).
(HasCallStack, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR),
 DomainActiveEdge dom ~ 'Rising, BitPack a) =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal domDDR a
-> Signal dom (a, a)
altddioIn SSymbol deviceFamily
devFam Clock dom
clk Reset dom
rst Enable dom
en =
  ((BitVector (BitSize a), BitVector (BitSize a)) -> (a, a))
-> Signal dom (BitVector (BitSize a), BitVector (BitSize a))
-> Signal dom (a, a)
forall a b. (a -> b) -> Signal dom a -> Signal dom b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap ((BitVector (BitSize a) -> a)
-> (BitVector (BitSize a) -> a)
-> (BitVector (BitSize a), BitVector (BitSize a))
-> (a, a)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: Type -> Type -> Type) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap BitVector (BitSize a) -> a
forall a. BitPack a => BitVector (BitSize a) -> a
unpack BitVector (BitSize a) -> a
forall a. BitPack a => BitVector (BitSize a) -> a
unpack) (Signal dom (BitVector (BitSize a), BitVector (BitSize a))
 -> Signal dom (a, a))
-> (Signal domDDR a
    -> Signal dom (BitVector (BitSize a), BitVector (BitSize a)))
-> Signal domDDR a
-> Signal dom (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (HasCallStack =>
 Signal domDDR (BitVector (BitSize a))
 -> Signal dom (BitVector (BitSize a), BitVector (BitSize a)))
-> Signal domDDR (BitVector (BitSize a))
-> Signal dom (BitVector (BitSize a), BitVector (BitSize a))
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack (SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal domDDR (BitVector (BitSize a))
-> Signal dom (BitVector (BitSize a), BitVector (BitSize a))
forall (deviceFamily :: Symbol) (n :: Nat) (dom :: Symbol)
       (domDDR :: Symbol).
(HasCallStack, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR),
 DomainActiveEdge dom ~ 'Rising, KnownNat n) =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal domDDR (BitVector n)
-> Signal dom (BitVector n, BitVector n)
altddioIn# SSymbol deviceFamily
devFam Clock dom
clk Reset dom
rst Enable dom
en) (Signal domDDR (BitVector (BitSize a))
 -> Signal dom (BitVector (BitSize a), BitVector (BitSize a)))
-> (Signal domDDR a -> Signal domDDR (BitVector (BitSize a)))
-> Signal domDDR a
-> Signal dom (BitVector (BitSize a), BitVector (BitSize a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> BitVector (BitSize a))
-> Signal domDDR a -> Signal domDDR (BitVector (BitSize a))
forall a b. (a -> b) -> Signal domDDR a -> Signal domDDR b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> BitVector (BitSize a)
forall a. BitPack a => a -> BitVector (BitSize a)
pack

altddioIn#
  :: forall deviceFamily n dom domDDR
   . HasCallStack
  => KnownDomain dom
  => KnownDomain domDDR
  => DomainPeriod dom ~ (2 * DomainPeriod domDDR)
  => DomainActiveEdge dom ~ 'Rising
  => KnownNat n
  => SSymbol deviceFamily
  -> Clock dom
  -> Reset dom
  -> Enable dom
  -> Signal domDDR (BitVector n)
  -> Signal dom (BitVector n, BitVector n)
altddioIn# :: forall (deviceFamily :: Symbol) (n :: Nat) (dom :: Symbol)
       (domDDR :: Symbol).
(HasCallStack, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR),
 DomainActiveEdge dom ~ 'Rising, KnownNat n) =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal domDDR (BitVector n)
-> Signal dom (BitVector n, BitVector n)
altddioIn# SSymbol deviceFamily
SSymbol Clock dom
clk Reset dom
rst Enable dom
en = (HasCallStack =>
 Clock dom
 -> Reset dom
 -> Enable dom
 -> BitVector n
 -> BitVector n
 -> BitVector n
 -> Signal domDDR (BitVector n)
 -> Signal dom (BitVector n, BitVector n))
-> Clock dom
-> Reset dom
-> Enable dom
-> BitVector n
-> BitVector n
-> BitVector n
-> Signal domDDR (BitVector n)
-> Signal dom (BitVector n, BitVector n)
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack HasCallStack =>
Clock dom
-> Reset dom
-> Enable dom
-> BitVector n
-> BitVector n
-> BitVector n
-> Signal domDDR (BitVector n)
-> Signal dom (BitVector n, BitVector n)
Clock dom
-> Reset dom
-> Enable dom
-> BitVector n
-> BitVector n
-> BitVector n
-> Signal domDDR (BitVector n)
-> Signal dom (BitVector n, BitVector n)
forall a (dom :: Symbol) (domDDR :: Symbol).
(HasCallStack, NFDataX a, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR)) =>
Clock dom
-> Reset dom
-> Enable dom
-> a
-> a
-> a
-> Signal domDDR a
-> Signal dom (a, a)
ddrIn# Clock dom
clk Reset dom
rst Enable dom
en BitVector n
0 BitVector n
0 BitVector n
0
-- See: https://github.com/clash-lang/clash-compiler/pull/2511
{-# CLASH_OPAQUE altddioIn# #-}
{-# ANN altddioIn# hasBlackBox #-}

-- | Intel specific variant of 'ddrOut' implemented using the ALTDDIO_OUT IP core.
--
-- Reset value is @0@
--
-- Of the input pair @(i0, i1)@, @i0@ is the data clocked out on the /rising/
-- edge and @i1@ is the data clocked out on the /falling/ edge, and @i0@ comes
-- before @i1@ in time.
--
-- __NB__: This primitive only supports rising edges as the active edge.
altddioOut
  :: forall deviceFamily a dom domDDR
   . HasCallStack
  => KnownDomain dom
  => KnownDomain domDDR
  => DomainPeriod dom ~ (2 * DomainPeriod domDDR)
  => DomainActiveEdge dom ~ 'Rising
  => BitPack a
  => SSymbol deviceFamily
  -- ^ The FPGA family
  --
  -- For example this can be instantiated as follows:
  --
  -- > SSymbol @"Cyclone IV E"
  -> Clock dom
  -> Reset dom
  -> Enable dom
  -> Signal dom (a, a)
  -- ^ Normal speed input pair @(i0, i1)@
  -> Signal domDDR a
  -- ^ DDR output signal
altddioOut :: forall (deviceFamily :: Symbol) a (dom :: Symbol)
       (domDDR :: Symbol).
(HasCallStack, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR),
 DomainActiveEdge dom ~ 'Rising, BitPack a) =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal dom (a, a)
-> Signal domDDR a
altddioOut SSymbol deviceFamily
devFam Clock dom
clk Reset dom
rst Enable dom
en =
  (BitVector (BitSize a) -> a)
-> Signal domDDR (BitVector (BitSize a)) -> Signal domDDR a
forall a b. (a -> b) -> Signal domDDR a -> Signal domDDR b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap BitVector (BitSize a) -> a
forall a. BitPack a => BitVector (BitSize a) -> a
unpack (Signal domDDR (BitVector (BitSize a)) -> Signal domDDR a)
-> (Signal dom (a, a) -> Signal domDDR (BitVector (BitSize a)))
-> Signal dom (a, a)
-> Signal domDDR a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signal dom (BitVector (BitSize a))
 -> Signal dom (BitVector (BitSize a))
 -> Signal domDDR (BitVector (BitSize a)))
-> (Signal dom (BitVector (BitSize a)),
    Signal dom (BitVector (BitSize a)))
-> Signal domDDR (BitVector (BitSize a))
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((HasCallStack =>
 SSymbol deviceFamily
 -> Clock dom
 -> Reset dom
 -> Enable dom
 -> Signal dom (BitVector (BitSize a))
 -> Signal dom (BitVector (BitSize a))
 -> Signal domDDR (BitVector (BitSize a)))
-> SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal dom (BitVector (BitSize a))
-> Signal dom (BitVector (BitSize a))
-> Signal domDDR (BitVector (BitSize a))
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack HasCallStack =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal dom (BitVector (BitSize a))
-> Signal dom (BitVector (BitSize a))
-> Signal domDDR (BitVector (BitSize a))
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal dom (BitVector (BitSize a))
-> Signal dom (BitVector (BitSize a))
-> Signal domDDR (BitVector (BitSize a))
forall (deviceFamily :: Symbol) (n :: Nat) (dom :: Symbol)
       (domDDR :: Symbol).
(HasCallStack, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR),
 DomainActiveEdge dom ~ 'Rising, KnownNat n) =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal dom (BitVector n)
-> Signal dom (BitVector n)
-> Signal domDDR (BitVector n)
altddioOut# SSymbol deviceFamily
devFam Clock dom
clk Reset dom
rst Enable dom
en) ((Signal dom (BitVector (BitSize a)),
  Signal dom (BitVector (BitSize a)))
 -> Signal domDDR (BitVector (BitSize a)))
-> (Signal dom (a, a)
    -> (Signal dom (BitVector (BitSize a)),
        Signal dom (BitVector (BitSize a))))
-> Signal dom (a, a)
-> Signal domDDR (BitVector (BitSize a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Signal dom (BitVector (BitSize a), BitVector (BitSize a))
-> (Signal dom (BitVector (BitSize a)),
    Signal dom (BitVector (BitSize a)))
Signal dom (BitVector (BitSize a), BitVector (BitSize a))
-> Unbundled dom (BitVector (BitSize a), BitVector (BitSize a))
forall a (dom :: Symbol).
Bundle a =>
Signal dom a -> Unbundled dom a
forall (dom :: Symbol).
Signal dom (BitVector (BitSize a), BitVector (BitSize a))
-> Unbundled dom (BitVector (BitSize a), BitVector (BitSize a))
unbundle (Signal dom (BitVector (BitSize a), BitVector (BitSize a))
 -> (Signal dom (BitVector (BitSize a)),
     Signal dom (BitVector (BitSize a))))
-> (Signal dom (a, a)
    -> Signal dom (BitVector (BitSize a), BitVector (BitSize a)))
-> Signal dom (a, a)
-> (Signal dom (BitVector (BitSize a)),
    Signal dom (BitVector (BitSize a)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, a) -> (BitVector (BitSize a), BitVector (BitSize a)))
-> Signal dom (a, a)
-> Signal dom (BitVector (BitSize a), BitVector (BitSize a))
forall a b. (a -> b) -> Signal dom a -> Signal dom b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> BitVector (BitSize a))
-> (a -> BitVector (BitSize a))
-> (a, a)
-> (BitVector (BitSize a), BitVector (BitSize a))
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: Type -> Type -> Type) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap a -> BitVector (BitSize a)
forall a. BitPack a => a -> BitVector (BitSize a)
pack a -> BitVector (BitSize a)
forall a. BitPack a => a -> BitVector (BitSize a)
pack)

altddioOut#
  :: forall deviceFamily n dom domDDR
   . HasCallStack
  => KnownDomain dom
  => KnownDomain domDDR
  => DomainPeriod dom ~ (2 * DomainPeriod domDDR)
  => DomainActiveEdge dom ~ 'Rising
  => KnownNat n
  => SSymbol deviceFamily
  -> Clock dom
  -> Reset dom
  -> Enable dom
  -> Signal dom (BitVector n)
  -> Signal dom (BitVector n)
  -> Signal domDDR (BitVector n)
altddioOut# :: forall (deviceFamily :: Symbol) (n :: Nat) (dom :: Symbol)
       (domDDR :: Symbol).
(HasCallStack, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR),
 DomainActiveEdge dom ~ 'Rising, KnownNat n) =>
SSymbol deviceFamily
-> Clock dom
-> Reset dom
-> Enable dom
-> Signal dom (BitVector n)
-> Signal dom (BitVector n)
-> Signal domDDR (BitVector n)
altddioOut# SSymbol deviceFamily
SSymbol Clock dom
clk Reset dom
rst Enable dom
en = Clock dom
-> Reset dom
-> Enable dom
-> BitVector n
-> Signal dom (BitVector n)
-> Signal dom (BitVector n)
-> Signal domDDR (BitVector n)
forall a (dom :: Symbol) (domDDR :: Symbol).
(HasCallStack, NFDataX a, KnownDomain dom, KnownDomain domDDR,
 DomainPeriod dom ~ (2 * DomainPeriod domDDR)) =>
Clock dom
-> Reset dom
-> Enable dom
-> a
-> Signal dom a
-> Signal dom a
-> Signal domDDR a
ddrOut# Clock dom
clk Reset dom
rst Enable dom
en BitVector n
0
-- See: https://github.com/clash-lang/clash-compiler/pull/2511
{-# CLASH_OPAQUE altddioOut# #-}
{-# ANN altddioOut# hasBlackBox #-}