kansas-lava-0.2.4: Language/KansasLava/Protocols/Enabled.hs
{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, TypeFamilies,
TypeSynonymInstances, FlexibleInstances, GADTs, RankNTypes,
UndecidableInstances #-}
-- | The 'Enabled' module allows the construction of circuits that use
-- additional control logic -- an enable signal -- that externalizes whether a
-- data signal is valid.
module Language.KansasLava.Protocols.Enabled
(Enabled,
packEnabled, unpackEnabled,
enabledVal, isEnabled,
mapEnabled,
enabledS, disabledS,
registerEnabled
) where
import Language.KansasLava.Signal
import Language.KansasLava.Rep
import Language.KansasLava.Utils
import Language.KansasLava.Types
-- | Enabled is a synonym for Maybe.
type Enabled a = Maybe a
-- | This is lifting *Comb* because Comb is stateless, and the 'en' Bool being
-- passed on assumes no history, in the 'a -> b' function.
mapEnabled :: (Rep a, Rep b, sig ~ Signal clk)
=> (forall clk' . Signal clk' a -> Signal clk' b)
-> sig (Enabled a) -> sig (Enabled b)
mapEnabled f en = pack (en_bool,f en_val)
where (en_bool,en_val) = unpack en
-- | Lift a data signal to be an Enabled signal, that's always enabled.
enabledS :: (Rep a, sig ~ Signal clk) => sig a -> sig (Enabled a)
enabledS s = pack (pureS True,s)
-- | Create a signal that's never enabled.
disabledS :: (Rep a, sig ~ Signal clk) => sig (Enabled a)
disabledS = pack (pureS False,undefinedS)
-- | Combine a boolean control signal and an data signal into an enabled signal.
packEnabled :: (Rep a, sig ~ Signal clk) => sig Bool -> sig a -> sig (Enabled a)
packEnabled s1 s2 = pack (s1,s2)
-- | Break the representation of an Enabled signal into a Bool signal (for whether the
-- value is valid) and a signal for the data.
unpackEnabled :: (Rep a, sig ~ Signal clk) => sig (Enabled a) -> (sig Bool, sig a)
unpackEnabled = unpack
-- | Drop the Enabled control from the signal. The output signal will be Rep
-- unknown if the input signal is not enabled.
enabledVal :: (Rep a, sig ~ Signal clk) => sig (Enabled a) -> sig a
enabledVal = snd . unpackEnabled
-- | Determine if the the circuit is enabled.
isEnabled :: (Rep a, sig ~ Signal clk) => sig (Enabled a) -> sig Bool
isEnabled = fst . unpackEnabled
-- | Optionally updatable register, based on the value of the enabled signal.
registerEnabled :: (Rep a, Clock clk, sig ~ Signal clk) => a -> sig (Enabled a) -> sig a
registerEnabled a inp = res
where
res = register a
$ cASE [ (isEnabled inp,enabledVal inp)
] res