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

DDR primitives for Xilinx FPGAs

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

For more information about the Xilinx DDR primitives see:

* Vivado Design Suite 7 Series FPGA and Zynq-7000 All Programmable SoC
  Libraries Guide, UG953 (v2018.3) December 5, 2018, p371-373,p481-483,
  <https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_3/ug953-vivado-7series-libraries.pdf>
-}

{-# LANGUAGE CPP              #-}
{-# LANGUAGE DataKinds        #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MagicHash        #-}
{-# LANGUAGE TypeFamilies     #-}
{-# LANGUAGE TypeOperators    #-}
#if __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif

module Clash.Xilinx.DDR
  ( iddr
  , oddr
  )
where

import GHC.Stack (HasCallStack, withFrozenCallStack)

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

-- | Xilinx specific variant of 'ddrIn' implemented using the Xilinx IDDR
-- primitive in @SAME_EDGE@ mode.
--
-- Reset values are @0@
iddr
  :: ( HasCallStack
     , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
     , KnownNat m )
  => Clock slow
  -- ^ clock
  -> Reset slow
  -- ^ reset
  -> Enable slow
  -- ^ global enable
  -> Signal fast (BitVector m)
  -- ^ DDR input signal
  -> Signal slow ((BitVector m),(BitVector m))
  -- ^ normal speed output pairs
iddr :: Clock slow
-> Reset slow
-> Enable slow
-> Signal fast (BitVector m)
-> Signal slow (BitVector m, BitVector m)
iddr clk :: Clock slow
clk rst :: Reset slow
rst en :: Enable slow
en = (HasCallStack =>
 Clock slow
 -> Reset slow
 -> Enable slow
 -> BitVector m
 -> BitVector m
 -> BitVector m
 -> Signal fast (BitVector m)
 -> Signal slow (BitVector m, BitVector m))
-> Clock slow
-> Reset slow
-> Enable slow
-> BitVector m
-> BitVector m
-> BitVector m
-> Signal fast (BitVector m)
-> Signal slow (BitVector m, BitVector m)
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack HasCallStack =>
Clock slow
-> Reset slow
-> Enable slow
-> BitVector m
-> BitVector m
-> BitVector m
-> Signal fast (BitVector m)
-> Signal slow (BitVector m, BitVector m)
forall a (slow :: Domain) (fast :: Domain) (fPeriod :: Nat)
       (polarity :: ResetPolarity) (edge :: ActiveEdge)
       (reset :: ResetKind) (init :: InitBehavior).
(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 slow
clk Reset slow
rst Enable slow
en 0 0 0
{-# NOINLINE iddr #-}
{-# ANN iddr hasBlackBox #-}

-- | Xilinx specific variant of 'ddrOut' implemented using the Xilinx ODDR
-- primitive in @SAME_EDGE@ mode.
--
-- Reset value is @0@
oddr
  :: ( KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
     , KnownNat m )
  => Clock slow
  -- ^ clock
  -> Reset slow
  -- ^ reset
  -> Enable slow
  -- ^ global enable
  -> Signal slow (BitVector m, BitVector m)
  -- ^ normal speed input pairs
  -> Signal fast (BitVector m)
  -- ^ DDR output signal
oddr :: Clock slow
-> Reset slow
-> Enable slow
-> Signal slow (BitVector m, BitVector m)
-> Signal fast (BitVector m)
oddr clk :: Clock slow
clk rst :: Reset slow
rst en :: Enable slow
en = (Signal slow (BitVector m)
 -> Signal slow (BitVector m) -> Signal fast (BitVector m))
-> (Signal slow (BitVector m), Signal slow (BitVector m))
-> Signal fast (BitVector m)
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((HasCallStack =>
 Clock slow
 -> Reset slow
 -> Enable slow
 -> Signal slow (BitVector m)
 -> Signal slow (BitVector m)
 -> Signal fast (BitVector m))
-> Clock slow
-> Reset slow
-> Enable slow
-> Signal slow (BitVector m)
-> Signal slow (BitVector m)
-> Signal fast (BitVector m)
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack HasCallStack =>
Clock slow
-> Reset slow
-> Enable slow
-> Signal slow (BitVector m)
-> Signal slow (BitVector m)
-> Signal fast (BitVector m)
forall (fast :: Domain) (fPeriod :: Nat) (edge :: ActiveEdge)
       (reset :: ResetKind) (init :: InitBehavior)
       (polarity :: ResetPolarity) (slow :: Domain) (m :: Nat).
(KnownConfiguration
   fast ('DomainConfiguration fast fPeriod edge reset init polarity),
 KnownConfiguration
   slow
   ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity),
 KnownNat m) =>
Clock slow
-> Reset slow
-> Enable slow
-> Signal slow (BitVector m)
-> Signal slow (BitVector m)
-> Signal fast (BitVector m)
oddr# Clock slow
clk Reset slow
rst Enable slow
en) ((Signal slow (BitVector m), Signal slow (BitVector m))
 -> Signal fast (BitVector m))
-> (Signal slow (BitVector m, BitVector m)
    -> (Signal slow (BitVector m), Signal slow (BitVector m)))
-> Signal slow (BitVector m, BitVector m)
-> Signal fast (BitVector m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signal slow (BitVector m, BitVector m)
-> (Signal slow (BitVector m), Signal slow (BitVector m))
forall a (dom :: Domain).
Bundle a =>
Signal dom a -> Unbundled dom a
unbundle

oddr#
  :: ( KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)
     , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)
     , KnownNat m )
  => Clock slow
  -> Reset slow
  -> Enable slow
  -> Signal slow (BitVector m)
  -> Signal slow (BitVector m)
  -> Signal fast (BitVector m)
oddr# :: Clock slow
-> Reset slow
-> Enable slow
-> Signal slow (BitVector m)
-> Signal slow (BitVector m)
-> Signal fast (BitVector m)
oddr# clk :: Clock slow
clk rst :: Reset slow
rst en :: Enable slow
en = Clock slow
-> Reset slow
-> Enable slow
-> BitVector m
-> Signal slow (BitVector m)
-> Signal slow (BitVector m)
-> Signal fast (BitVector m)
forall a (fast :: Domain) (fPeriod :: Nat) (edge :: ActiveEdge)
       (reset :: ResetKind) (init :: InitBehavior)
       (polarity :: ResetPolarity) (slow :: Domain).
(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# Clock slow
clk Reset slow
rst Enable slow
en 0
{-# NOINLINE oddr# #-}
{-# ANN oddr# hasBlackBox #-}