Copyright | (C) 2013-2016 University of Twente 2016-2019 Myrtle Software 2017-2022 Google Inc. 2020 Ben Gamari 2021-2024 QBayLogic B.V. |
---|---|
License | BSD2 (see the file LICENSE) |
Maintainer | QBayLogic B.V. <devops@qbaylogic.com> |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
Extensions |
|
Clash has synchronous Signal
s in the form of:
Signal
(dom ::Symbol
) a
Where a is the type of the value of the Signal
, for example Int or Bool,
and dom is the clock- (and reset-) domain to which the memory elements
manipulating these Signal
s belong.
The type-parameter, dom, is of the kind Domain
- a simple string. That
string refers to a single synthesis domain. A synthesis domain describes the
behavior of certain aspects of memory elements in it. More specifically, a
domain looks like:
DomainConfiguration
{ _name::Symbol
-- ^ Domain name , _period ::Nat
-- ^ Clock period in /ps/ , _edge ::ActiveEdge
-- ^ Active edge of the clock , _reset ::ResetKind
-- ^ Whether resets are synchronous (edge-sensitive) or asynchronous (level-sensitive) , _init ::InitBehavior
-- ^ Whether the initial (or "power up") value of memory elements is -- unknown/undefined, or configurable to a specific value , _polarity ::ResetPolarity
-- ^ Whether resets are active high or active low }
Check the documentation of each of the types to see the various options Clash
provides. In order to specify a domain, an instance of KnownDomain
should be
made. Clash provides a standard implementation, called System
, that is
configured as follows:
instance KnownDomainSystem
where type KnownConfSystem
= 'DomainConfigurationSystem
10000 'Rising 'Asynchronous 'Defined 'ActiveHigh knownDomain =SDomainConfiguration
SSymbol SNatSRising
SAsynchronous
SDefined
SActiveHigh
In words, "System" is a synthesis domain with a clock running with a period of 10000 ps (100 MHz). Memory elements update their state on the rising edge of the clock, can be reset asynchronously with regards to the clock, and have defined power up values if applicable.
In order to create a new domain, you don't have to instantiate it explicitly.
Instead, you can have createDomain
create a domain for you. You can also use
the same function to subclass existing domains.
- NB: "Bad things"™ happen when you actually use a clock period of
0
, so do not do that! - NB: You should be judicious using a clock with period of
1
as you can never create a clock that goes any faster! - NB: For the best compatibility make sure your period is divisible by 2, because some VHDL simulators don't support fractions of picoseconds.
- NB: Whether
System
has good defaults depends on your target platform. Check outIntelSystem
andXilinxSystem
too!
Explicit clocks and resets, and meta-stability
When using multiple clocks and/or reset lines there are ways to accidentally introduce situations that are prone to metastability. These bugs are incredibly hard to debug as they often cannot be simulated, so it's best to prevent them in the first place. This section outlines the situations in which metastability arises and how to prevent it.
Two types of resets exist: synchronous and asynchronous resets. These reset types are encoded in a synthesis domain. For the following examples we assume the following exist:
DomainConfiguration
"SyncExample" _period _edgeSynchronous
_initDomainConfiguration
"AsyncExample" _period _edgeAsynchronous
_init
See the previous section on how to use domains.
We now go over the clock and reset line combinations and explain when they can potentially introduce situations prone to meta-stability:
Reset situation 1:
f ::
Reset
"SyncExample" ->Reset
"SyncExample" -> .. f x y = ..There are no problems here, because although x and y can have different values, components to these reset lines are reset synchronously, and there is no metastability situation.
Reset situation 2:
g ::
Reset
"AsyncExample" ->Reset
"AsyncExample" -> .. g x y = ..This situation can be prone to metastability, because although x and y belong to the same domain according to their domain, there is no guarantee that they actually originate from the same source. This means that one component can enter its reset state asynchronously to another component, inducing metastability in the other component.
Clock situation:
k ::
Clock
dom ->Clock
dom -> .. k x y = ..The situation above is potentially prone to metastability, because even though x and y belong to the same domain according to their domain, there is no guarantee that they actually originate from the same source. They could hence be connected to completely unrelated clock sources, and components can then induce metastable states in others.
Synopsis
- data Signal (dom :: Domain) a
- data BiSignalIn (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
- data BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
- data BiSignalDefault
- type Domain = Symbol
- class (KnownSymbol dom, KnownNat (DomainPeriod dom)) => KnownDomain (dom :: Domain) where
- type KnownConf dom :: DomainConfiguration
- knownDomain :: SDomainConfiguration dom (KnownConf dom)
- type KnownConfiguration dom conf = (KnownDomain dom, KnownConf dom ~ conf)
- data ActiveEdge
- data SActiveEdge (edge :: ActiveEdge) where
- data InitBehavior
- data SInitBehavior (init :: InitBehavior) where
- data ResetKind
- data SResetKind (resetKind :: ResetKind) where
- data ResetPolarity
- data SResetPolarity (polarity :: ResetPolarity) where
- data DomainConfiguration = DomainConfiguration {}
- data SDomainConfiguration (dom :: Domain) (conf :: DomainConfiguration) where
- SDomainConfiguration :: 1 <= period => {..} -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
- type DomainPeriod (dom :: Domain) = DomainConfigurationPeriod (KnownConf dom)
- type DomainActiveEdge (dom :: Domain) = DomainConfigurationActiveEdge (KnownConf dom)
- type DomainResetKind (dom :: Domain) = DomainConfigurationResetKind (KnownConf dom)
- type DomainInitBehavior (dom :: Domain) = DomainConfigurationInitBehavior (KnownConf dom)
- type DomainResetPolarity (dom :: Domain) = DomainConfigurationResetPolarity (KnownConf dom)
- type HasSynchronousReset (dom :: Domain) = (KnownDomain dom, DomainResetKind dom ~ 'Synchronous)
- type HasAsynchronousReset (dom :: Domain) = (KnownDomain dom, DomainResetKind dom ~ 'Asynchronous)
- type HasDefinedInitialValues (dom :: Domain) = (KnownDomain dom, DomainInitBehavior dom ~ 'Defined)
- type Seconds (s :: Nat) = Milliseconds (1000 * s)
- type Milliseconds (ms :: Nat) = Microseconds (1000 * ms)
- type Microseconds (us :: Nat) = Nanoseconds (1000 * us)
- type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns)
- type Picoseconds (ps :: Nat) = ps
- type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom)
- type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz
- type PeriodToHz (period :: Nat) = Seconds 1 `Div` period
- type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom
- type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period
- type System = "System" :: Domain
- type XilinxSystem = "XilinxSystem" :: Domain
- type IntelSystem = "IntelSystem" :: Domain
- vSystem :: VDomainConfiguration
- vIntelSystem :: VDomainConfiguration
- vXilinxSystem :: VDomainConfiguration
- data VDomainConfiguration = VDomainConfiguration {}
- vDomain :: SDomainConfiguration dom conf -> VDomainConfiguration
- createDomain :: VDomainConfiguration -> Q [Dec]
- knownVDomain :: forall dom. KnownDomain dom => VDomainConfiguration
- clockPeriod :: forall dom period. (KnownDomain dom, DomainPeriod dom ~ period) => SNat period
- activeEdge :: forall dom edge. (KnownDomain dom, DomainActiveEdge dom ~ edge) => SActiveEdge edge
- resetKind :: forall dom sync. (KnownDomain dom, DomainResetKind dom ~ sync) => SResetKind sync
- initBehavior :: forall dom init. (KnownDomain dom, DomainInitBehavior dom ~ init) => SInitBehavior init
- resetPolarity :: forall dom polarity. (KnownDomain dom, DomainResetPolarity dom ~ polarity) => SResetPolarity polarity
- data Enable dom
- toEnable :: Signal dom Bool -> Enable dom
- fromEnable :: Enable dom -> Signal dom Bool
- enableGen :: Enable dom
- data Clock (dom :: Domain)
- data DiffClock (dom :: Domain)
- periodToHz :: (HasCallStack, Fractional a) => Natural -> a
- hzToPeriod :: (HasCallStack, Integral a) => Ratio Natural -> a
- unsafeSynchronizer :: forall dom1 dom2 a. (KnownDomain dom1, KnownDomain dom2) => Clock dom1 -> Clock dom2 -> Signal dom1 a -> Signal dom2 a
- veryUnsafeSynchronizer :: Either Int (Signal dom1 Int) -> Either Int (Signal dom2 Int) -> Signal dom1 a -> Signal dom2 a
- data Reset (dom :: Domain)
- unsafeToReset :: KnownDomain dom => Signal dom Bool -> Reset dom
- unsafeFromReset :: Reset dom -> Signal dom Bool
- unsafeToActiveHigh :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool
- unsafeToActiveLow :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool
- unsafeFromActiveHigh :: forall dom. KnownDomain dom => Signal dom Bool -> Reset dom
- unsafeFromActiveLow :: forall dom. KnownDomain dom => Signal dom Bool -> Reset dom
- andEnable :: Enable dom -> Signal dom Bool -> Enable dom
- dflipflop :: (KnownDomain dom, NFDataX a) => Clock dom -> Signal dom a -> Signal dom a
- delay :: (KnownDomain dom, NFDataX a) => Clock dom -> Enable dom -> a -> Signal dom a -> Signal dom a
- delayMaybe :: (KnownDomain dom, NFDataX a) => Clock dom -> Enable dom -> a -> Signal dom (Maybe a) -> Signal dom a
- delayEn :: (KnownDomain dom, NFDataX a) => Clock dom -> Enable dom -> a -> Signal dom Bool -> Signal dom a -> Signal dom a
- register :: (KnownDomain dom, NFDataX a) => Clock dom -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
- regMaybe :: (KnownDomain dom, NFDataX a) => Clock dom -> Reset dom -> Enable dom -> a -> Signal dom (Maybe a) -> Signal dom a
- regEn :: (KnownDomain dom, NFDataX a) => Clock dom -> Reset dom -> Enable dom -> a -> Signal dom Bool -> Signal dom a -> Signal dom a
- mux :: Applicative f => f Bool -> f a -> f a -> f a
- clockGen :: KnownDomain dom => Clock dom
- resetGen :: forall dom. KnownDomain dom => Reset dom
- resetGenN :: forall dom n. (KnownDomain dom, 1 <= n) => SNat n -> Reset dom
- systemClockGen :: Clock System
- systemResetGen :: Reset System
- (.&&.) :: Applicative f => f Bool -> f Bool -> f Bool
- (.||.) :: Applicative f => f Bool -> f Bool -> f Bool
- class Bundle a where
- data EmptyTuple = EmptyTuple
- data TaggedEmptyTuple (dom :: Domain) = TaggedEmptyTuple
- simulate :: (NFDataX a, NFDataX b) => (Signal dom1 a -> Signal dom2 b) -> [a] -> [b]
- simulateB :: (Bundle a, Bundle b, NFDataX a, NFDataX b) => (Unbundled dom1 a -> Unbundled dom2 b) -> [a] -> [b]
- simulateWithReset :: forall dom a b m. (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) => SNat m -> a -> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a -> Signal dom b) -> [a] -> [b]
- simulateWithResetN :: (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) => SNat m -> a -> Int -> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a -> Signal dom b) -> [a] -> [b]
- runUntil :: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) => (a -> Bool) -> Signal dom a -> IO ()
- simulate_lazy :: (Signal dom1 a -> Signal dom2 b) -> [a] -> [b]
- simulateB_lazy :: (Bundle a, Bundle b) => (Unbundled dom1 a -> Unbundled dom2 b) -> [a] -> [b]
- signalAutomaton :: forall dom a b. (Signal dom a -> Signal dom b) -> Automaton (->) a b
- sample :: (Foldable f, NFDataX a) => f a -> [a]
- sampleN :: (Foldable f, NFDataX a) => Int -> f a -> [a]
- sampleWithReset :: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) => SNat m -> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a) -> [a]
- sampleWithResetN :: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) => SNat m -> Int -> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a) -> [a]
- fromList :: NFDataX a => [a] -> Signal dom a
- fromListWithReset :: forall dom a. (KnownDomain dom, NFDataX a) => Reset dom -> a -> [a] -> Signal dom a
- sample_lazy :: Foldable f => f a -> [a]
- sampleN_lazy :: Foldable f => Int -> f a -> [a]
- fromList_lazy :: [a] -> Signal dom a
- testFor :: Foldable f => Int -> f Bool -> Property
- (.==.) :: (Eq a, Applicative f) => f a -> f a -> f Bool
- (./=.) :: (Eq a, Applicative f) => f a -> f a -> f Bool
- (.<.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- (.<=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- (.>=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- (.>.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
- veryUnsafeToBiSignalIn :: (HasCallStack, KnownNat n, Given (SBiSignalDefault ds)) => BiSignalOut ds d n -> BiSignalIn ds d n
- readFromBiSignal :: (HasCallStack, BitPack a) => BiSignalIn ds d (BitSize a) -> Signal d a
- writeToBiSignal :: (HasCallStack, BitPack a, NFDataX a) => BiSignalIn ds d (BitSize a) -> Signal d (Maybe a) -> BiSignalOut ds d (BitSize a)
- mergeBiSignalOuts :: (HasCallStack, KnownNat n) => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m
- unsafeFromHighPolarity :: forall dom. KnownDomain dom => Signal dom Bool -> Reset dom
- unsafeFromLowPolarity :: forall dom. KnownDomain dom => Signal dom Bool -> Reset dom
- unsafeToHighPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool
- unsafeToLowPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool
Synchronous signal
data Signal (dom :: Domain) a Source #
Clash has synchronous Signal
s in the form of:
Signal
(dom ::Domain
) a
Where a is the type of the value of the Signal
, for example Int or Bool,
and dom is the clock- (and reset-) domain to which the memory elements
manipulating these Signal
s belong.
The type-parameter, dom, is of the kind Domain
- a simple string. That
string refers to a single synthesis domain. A synthesis domain describes the
behavior of certain aspects of memory elements in it.
- NB: "Bad things"™ happen when you actually use a clock period of
0
, so do not do that! - NB: You should be judicious using a clock with period of
1
as you can never create a clock that goes any faster! - NB: For the best compatibility make sure your period is divisible by 2, because some VHDL simulators don't support fractions of picoseconds.
- NB: Whether
System
has good defaults depends on your target platform. Check outIntelSystem
andXilinxSystem
too!
Signals have the type role
>>>
:i Signal
type role Signal nominal representational ...
as it is safe to coerce the underlying value of a signal, but not safe to coerce a signal between different synthesis domains.
See the module documentation of Clash.Signal for more information about domains.
Instances
data BiSignalIn (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat) Source #
The in part of an inout port. BiSignalIn has the type role
>>>
:i BiSignalIn
type role BiSignalIn nominal nominal nominal ...
as it is not safe to coerce the default behaviour, synthesis domain or width of the data in the signal.
data BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat) Source #
The out part of an inout port
Wraps (multiple) writing signals. The semantics are such that only one of the signals may write at a single time step.
BiSignalOut has the type role
>>>
:i BiSignalOut
type role BiSignalOut nominal nominal nominal ...
as it is not safe to coerce the default behaviour, synthesis domain or width of the data in the signal.
Instances
Semigroup (BiSignalOut defaultState dom n) Source # | NB: Not synthesizable |
Defined in Clash.Signal.BiSignal (<>) :: BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n Source # sconcat :: NonEmpty (BiSignalOut defaultState dom n) -> BiSignalOut defaultState dom n Source # stimes :: Integral b => b -> BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n Source # | |
Monoid (BiSignalOut defaultState dom n) Source # | Monoid instance to support concatenating NB: Not synthesizable |
Defined in Clash.Signal.BiSignal mempty :: BiSignalOut defaultState dom n Source # mappend :: BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n -> BiSignalOut defaultState dom n Source # mconcat :: [BiSignalOut defaultState dom n] -> BiSignalOut defaultState dom n Source # | |
type HasDomain dom1 (BiSignalOut ds dom2 n) Source # | |
Defined in Clash.Signal.BiSignal | |
type TryDomain t (BiSignalOut ds dom n) Source # | |
Defined in Clash.Signal.BiSignal |
data BiSignalDefault Source #
Used to specify the default behavior of a "BiSignal" in Haskell simulation, i.e. what value is read when no value is being written to it.
PullUp | inout port behaves as if connected to a pull-up resistor |
PullDown | inout port behaves as if connected to a pull-down resistor |
Floating | inout port behaves as if is floating. Reading a floating "BiSignal" value in simulation will yield an errorX (undefined value). |
Instances
Show BiSignalDefault Source # | |
Defined in Clash.Signal.BiSignal |
Domain
class (KnownSymbol dom, KnownNat (DomainPeriod dom)) => KnownDomain (dom :: Domain) where Source #
A KnownDomain
constraint indicates that a circuit's behavior depends on
some properties of a domain. See DomainConfiguration
for more information.
type KnownConf dom :: DomainConfiguration Source #
knownDomain :: SDomainConfiguration dom (KnownConf dom) Source #
Returns SDomainConfiguration
corresponding to an instance's DomainConfiguration
.
Example usage:
>>>
knownDomain @System
SDomainConfiguration {sName = SSymbol @"System", sPeriod = SNat @10000, sActiveEdge = SRising, sResetKind = SAsynchronous, sInitBehavior = SDefined, sResetPolarity = SActiveHigh}
Instances
KnownDomain XilinxSystem Source # | System instance with defaults set for Xilinx FPGAs |
Defined in Clash.Signal.Internal type KnownConf XilinxSystem :: DomainConfiguration Source # | |
KnownDomain IntelSystem Source # | System instance with defaults set for Intel FPGAs |
Defined in Clash.Signal.Internal type KnownConf IntelSystem :: DomainConfiguration Source # | |
KnownDomain System Source # | A clock (and reset) dom with clocks running at 100 MHz |
Defined in Clash.Signal.Internal type KnownConf System :: DomainConfiguration Source # |
type KnownConfiguration dom conf = (KnownDomain dom, KnownConf dom ~ conf) Source #
data ActiveEdge Source #
Determines clock edge memory elements are sensitive to. Not yet implemented.
Rising | Elements are sensitive to the rising edge (low-to-high) of the clock. |
Falling | Elements are sensitive to the falling edge (high-to-low) of the clock. |
Instances
data SActiveEdge (edge :: ActiveEdge) where Source #
Singleton version of ActiveEdge
SRising :: SActiveEdge 'Rising | |
SFalling :: SActiveEdge 'Falling |
Instances
Show (SActiveEdge edge) Source # | |
Defined in Clash.Signal.Internal |
data InitBehavior Source #
Unknown | Power up value of memory elements is unknown. |
Defined | If applicable, power up value of a memory element is defined. Applies to
|
Instances
data SInitBehavior (init :: InitBehavior) where Source #
Instances
Show (SInitBehavior init) Source # | |
Defined in Clash.Signal.Internal |
Asynchronous | Elements respond asynchronously to changes in their reset input. This means that they do not wait for the next active clock edge, but respond immediately instead. Common on Intel FPGA platforms. |
Synchronous | Elements respond synchronously to changes in their reset input. This means that changes in their reset input won't take effect until the next active clock edge. Common on Xilinx FPGA platforms. |
Instances
Eq ResetKind Source # | |
Data ResetKind Source # | |
Defined in Clash.Signal.Internal gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ResetKind -> c ResetKind Source # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ResetKind Source # toConstr :: ResetKind -> Constr Source # dataTypeOf :: ResetKind -> DataType Source # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ResetKind) Source # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ResetKind) Source # gmapT :: (forall b. Data b => b -> b) -> ResetKind -> ResetKind Source # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ResetKind -> r Source # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ResetKind -> r Source # gmapQ :: (forall d. Data d => d -> u) -> ResetKind -> [u] Source # gmapQi :: Int -> (forall d. Data d => d -> u) -> ResetKind -> u Source # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ResetKind -> m ResetKind Source # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ResetKind -> m ResetKind Source # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ResetKind -> m ResetKind Source # | |
Ord ResetKind Source # | |
Defined in Clash.Signal.Internal | |
Read ResetKind Source # | |
Show ResetKind Source # | |
Generic ResetKind Source # | |
Binary ResetKind Source # | |
NFData ResetKind Source # | |
Defined in Clash.Signal.Internal | |
Hashable ResetKind Source # | |
type Rep ResetKind Source # | |
data SResetKind (resetKind :: ResetKind) where Source #
Singleton version of ResetKind
Instances
Show (SResetKind reset) Source # | |
Defined in Clash.Signal.Internal |
data ResetPolarity Source #
Determines the value for which a reset line is considered "active"
ActiveHigh | Reset is considered active if underlying signal is |
ActiveLow | Reset is considered active if underlying signal is |
Instances
data SResetPolarity (polarity :: ResetPolarity) where Source #
Singleton version of ResetPolarity
Instances
Show (SResetPolarity polarity) Source # | |
Defined in Clash.Signal.Internal |
data DomainConfiguration Source #
A domain with a name (Domain
). Configures the behavior of various aspects
of a circuits. See the documentation of this record's field types for more
information on the options.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
DomainConfiguration | |
|
data SDomainConfiguration (dom :: Domain) (conf :: DomainConfiguration) where Source #
Singleton version of DomainConfiguration
SDomainConfiguration | |
|
Instances
Show (SDomainConfiguration dom conf) Source # | |
Defined in Clash.Signal.Internal |
Configuration type families
type DomainPeriod (dom :: Domain) = DomainConfigurationPeriod (KnownConf dom) Source #
Convenience type to help to extract a period from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainPeriod dom ~ 6000) => ...
type DomainActiveEdge (dom :: Domain) = DomainConfigurationActiveEdge (KnownConf dom) Source #
Convenience type to help to extract the active edge from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainActiveEdge dom ~ 'Rising) => ...
type DomainResetKind (dom :: Domain) = DomainConfigurationResetKind (KnownConf dom) Source #
Convenience type to help to extract the reset synchronicity from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainResetKind dom ~ 'Synchronous) => ...
type DomainInitBehavior (dom :: Domain) = DomainConfigurationInitBehavior (KnownConf dom) Source #
Convenience type to help to extract the initial value behavior from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainInitBehavior dom ~ 'Defined) => ...
type DomainResetPolarity (dom :: Domain) = DomainConfigurationResetPolarity (KnownConf dom) Source #
Convenience type to help to extract the reset polarity from a domain. Example usage:
myFunc :: (KnownDomain dom, DomainResetPolarity dom ~ 'ActiveHigh) => ...
Convenience types
Simplifying
If you want to write part of your Clash design as domain-polymorphic functions, it can be practical to define a design-wide constraint synonym that captures the characteristics of the clock domains of the design. Such a constraint synonym can be used as a constraint on all domain-polymorphic functions in the design, regardless of whether they actually need the constraints from this section.
type DesignDomain dom = (HasSynchronousReset
dom ,HasDefinedInitialValues
dom ) type DesignDomainHidden dom = ( DesignDomain dom ,HiddenClockResetEnable
dom ) myFunc :: DesignDomainHidden dom =>Signal
dom [...]
This way, you don't have to think about which constraints the function you're writing has exactly, and the constraint is succinct.
type HasSynchronousReset (dom :: Domain) = (KnownDomain dom, DomainResetKind dom ~ 'Synchronous) Source #
Convenience type to constrain a domain to have synchronous resets. Example usage:
myFunc :: HasSynchronousReset dom => ...
Using this type implies KnownDomain
.
type HasAsynchronousReset (dom :: Domain) = (KnownDomain dom, DomainResetKind dom ~ 'Asynchronous) Source #
Convenience type to constrain a domain to have asynchronous resets. Example usage:
myFunc :: HasAsynchronousReset dom => ...
Using this type implies KnownDomain
.
type HasDefinedInitialValues (dom :: Domain) = (KnownDomain dom, DomainInitBehavior dom ~ 'Defined) Source #
Convenience type to constrain a domain to have initial values. Example usage:
myFunc :: HasDefinedInitialValues dom => ...
Using this type implies KnownDomain
.
Note that there is no UnknownInitialValues dom
as a component that works
without initial values will also work if it does have them.
Time representations
type Seconds (s :: Nat) = Milliseconds (1000 * s) Source #
Gets time in Picoseconds
from time in Seconds
type Milliseconds (ms :: Nat) = Microseconds (1000 * ms) Source #
Gets time in Picoseconds
from time in Milliseconds
type Microseconds (us :: Nat) = Nanoseconds (1000 * us) Source #
Gets time in Picoseconds
from time in Microseconds
type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns) Source #
Gets time in Picoseconds
from time in Nanoseconds
type Picoseconds (ps :: Nat) = ps Source #
Gets time in Picoseconds
from time in picoseconds, essentially id
Time conversions
type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom) Source #
The domain's clock frequency in hertz, calculated based on the period stored in picoseconds. This might lead to rounding errors.
type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz Source #
Converts a frequency in hertz to a period in picoseconds. This might lead to rounding errors.
type PeriodToHz (period :: Nat) = Seconds 1 `Div` period Source #
Converts a period in picoseconds to a frequency in hertz. This might lead to rounding errors.
type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom Source #
Number of clock cycles required at the clock frequency of dom
before a minimum
period
has passed
type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period Source #
Number of clock cycles required at the clock frequency of dom
before a minimum
period
has passed. The same as PeriodToCycles
.
Default domains
type System = "System" :: Domain Source #
A clock (and reset) dom with clocks running at 100 MHz. Memory elements respond to the rising edge of the clock, and asynchronously to changes in reset signals. It has defined initial values, and active-high resets.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
type XilinxSystem = "XilinxSystem" :: Domain Source #
A clock (and reset) dom with clocks running at 100 MHz. Memory elements respond to the rising edge of the clock, and synchronously to changes in reset signals. It has defined initial values, and active-high resets.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
type IntelSystem = "IntelSystem" :: Domain Source #
A clock (and reset) dom with clocks running at 100 MHz. Memory elements respond to the rising edge of the clock, and asynchronously to changes in reset signals. It has defined initial values, and active-high resets.
See module documentation of Clash.Explicit.Signal for more information on how to create custom synthesis domains.
vSystem :: VDomainConfiguration Source #
Convenience value to allow easy "subclassing" of System domain. Should
be used in combination with createDomain
. For example, if you just want to
change the period but leave all other settings intact use:
createDomain vSystem{vName="System10", vPeriod=10}
vIntelSystem :: VDomainConfiguration Source #
Convenience value to allow easy "subclassing" of IntelSystem domain. Should
be used in combination with createDomain
. For example, if you just want to
change the period but leave all other settings intact use:
createDomain vIntelSystem{vName="Intel10", vPeriod=10}
vXilinxSystem :: VDomainConfiguration Source #
Convenience value to allow easy "subclassing" of XilinxSystem domain. Should
be used in combination with createDomain
. For example, if you just want to
change the period but leave all other settings intact use:
createDomain vXilinxSystem{vName="Xilinx10", vPeriod=10}
Domain utilities
data VDomainConfiguration Source #
Same as SDomainConfiguration but allows for easy updates through record update syntax.
Should be used in combination with vDomain
and createDomain
. Example:
createDomain (knownVDomain @System){vName="System10", vPeriod=10}
This duplicates the settings in the System
domain, replaces the name and
period, and creates an instance for it. As most users often want to update
the system domain, a shortcut is available in the form:
createDomain vSystem{vName="System10", vPeriod=10}
VDomainConfiguration | |
|
Instances
vDomain :: SDomainConfiguration dom conf -> VDomainConfiguration Source #
Convert SDomainConfiguration
to VDomainConfiguration
. Should be used in combination with
createDomain
only.
createDomain :: VDomainConfiguration -> Q [Dec] Source #
Convenience method to express new domains in terms of others.
createDomain (knownVDomain @System){vName="System10", vPeriod=10}
This duplicates the settings in the System domain, replaces the name and period, and creates an instance for it. As most users often want to update the system domain, a shortcut is available in the form:
createDomain vSystem{vName="System10", vPeriod=10}
The function will create two extra identifiers. The first:
type System10 = ..
You can use that as the dom to Clocks/Resets/Enables/Signals. For example:
Signal System10 Int
. Additionally, it will create a VDomainConfiguration
that you can
use in later calls to createDomain
:
vSystem10 = knownVDomain @System10
It will also make System10
an instance of KnownDomain
.
If either identifier is already in scope it will not be generated a second time. Note: This can be useful for example when documenting a new domain:
-- | Here is some documentation for CustomDomain type CustomDomain = ("CustomDomain" :: Domain) -- | Here is some documentation for vCustomDomain createDomain vSystem{vName="CustomDomain"}
knownVDomain :: forall dom. KnownDomain dom => VDomainConfiguration Source #
Like 'knownDomain but yields a VDomainConfiguration
. Should only be used
in combination with createDomain
.
clockPeriod :: forall dom period. (KnownDomain dom, DomainPeriod dom ~ period) => SNat period Source #
Get the clock period from a KnownDomain context
activeEdge :: forall dom edge. (KnownDomain dom, DomainActiveEdge dom ~ edge) => SActiveEdge edge Source #
Get ActiveEdge
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case activeEdge @dom of SRising -> foo SFalling -> bar
resetKind :: forall dom sync. (KnownDomain dom, DomainResetKind dom ~ sync) => SResetKind sync Source #
Get ResetKind
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case resetKind @dom of SAsynchronous -> foo SSynchronous -> bar
initBehavior :: forall dom init. (KnownDomain dom, DomainInitBehavior dom ~ init) => SInitBehavior init Source #
Get InitBehavior
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case initBehavior @dom of SDefined -> foo SUnknown -> bar
resetPolarity :: forall dom polarity. (KnownDomain dom, DomainResetPolarity dom ~ polarity) => SResetPolarity polarity Source #
Get ResetPolarity
from a KnownDomain context. Example usage:
f :: forall dom . KnownDomain dom => .... f a b c = case resetPolarity @dom of SActiveHigh -> foo SActiveLow -> bar
Enabling
A signal of booleans, indicating whether a component is enabled. No special meaning is implied, it's up to the component itself to decide how to respond to its enable line. It is used throughout Clash as a global enable signal.
fromEnable :: Enable dom -> Signal dom Bool Source #
Convert Enable
construct to its underlying representation: a signal of
bools.
Clock
data Clock (dom :: Domain) Source #
A clock signal belonging to a domain named dom.
Instances
data DiffClock (dom :: Domain) Source #
A differential clock signal belonging to a domain named dom. The clock
input of a design with such an input has two ports which are in antiphase.
The first input is the positive phase, the second the negative phase. When
using makeTopEntity
, the names of the inputs will end
in _p
and _n
respectively.
To create a differential clock in a test bench, you can use
clockToDiffClock
.
periodToHz :: (HasCallStack, Fractional a) => Natural -> a Source #
Calculate the frequency in Hz, given the period in ps
I.e., to calculate the clock frequency of a clock with a period of 5000 ps:
>>>
periodToHz 5000
2.0e8
Note that if p
in periodToHz (
is negative,
fromIntegral
p)fromIntegral
will give an
without a call stack, making debugging
cumbersome.Underflow
::
ArithException
Before Clash 1.8, this function always returned a Ratio
Natural
. To get the old behavior of this function, use a type application:
>>>
periodToHz @(Ratio Natural) 5000
200000000 % 1
NB: This function is not synthesizable
hzToPeriod :: (HasCallStack, Integral a) => Ratio Natural -> a Source #
Calculate the period in ps, given a frequency in Hz
I.e., to calculate the clock period for a circuit to run at 240 MHz we get
>>>
hzToPeriod 240e6
4166
If the value hzToPeriod
is applied to is not of the type Ratio
Natural
, you can use hzToPeriod (
. Note that if realToFrac
f)f
is
negative, realToFrac
will give an
without a call stack, making debugging
cumbersome.Underflow
::
ArithException
Before Clash 1.8, this function always returned a Natural
. To get the old
behavior of this function, use a type application:
>>>
hzToPeriod @Natural 240e6
4166
- NB: This function is not synthesizable
- NB: This function is lossy. I.e.,
periodToHz . hzToPeriod /= id
.
Synchronization primitive
:: forall dom1 dom2 a. (KnownDomain dom1, KnownDomain dom2) | |
=> Clock dom1 |
|
-> Clock dom2 |
|
-> Signal dom1 a | |
-> Signal dom2 a |
The unsafeSynchronizer
function is a primitive that must be used to
connect one clock domain to the other, and will be synthesized to a (bundle
of) wire(s) in the eventual circuit. This function should only be used as
part of a proper synchronization component, such as the following dual
flip-flop synchronizer:
dualFlipFlop :: Clock domA -> Clock domB -> Enable domA -> Enable domB -> Bit -> Signal domA Bit -> Signal domB Bit dualFlipFlop clkA clkB enA enB dflt =delay
clkB enB dflt .delay
clkB enB dflt .unsafeSynchronizer
clkA clkB
The unsafeSynchronizer
works in such a way that, given 2 clocks:
createDomain vSystem{vName="Dom7", vPeriod=7} clk7 ::Clock
Dom7 clk7 =clockGen
en7 ::Enable
Dom7 en7 =enableGen
and
createDomain vSystem{vName="Dom2", vPeriod=2} clk2 ::Clock
Dom2 clk2 =clockGen
en2 ::Enable
Dom2 en2 =enableGen
Oversampling followed by compression is the identity function plus 2 initial values:
delay
clkB enB dflt $unsafeSynchronizer
clkA clkB $delay
clkA enA dflt $unsafeSynchronizer
clkB clkA $delay
clkB enB s == dflt :- dflt :- s
Something we can easily observe:
oversampling clkA clkB enA enB dflt =delay
clkB enB dflt .unsafeSynchronizer
clkA clkB .delay
clkA enA dflt almostId clkA clkB enA enB dflt =delay
clkB enB dflt .unsafeSynchronizer
clkA clkB .delay
clkA enA dflt .unsafeSynchronizer
clkB clkA .delay
clkB enB dflt
>>>
sampleN 37 (oversampling clk7 clk2 en7 en2 0 (fromList [(1::Int)..10]))
[0,0,1,1,1,2,2,2,2,3,3,3,4,4,4,4,5,5,5,6,6,6,6,7,7,7,8,8,8,8,9,9,9,10,10,10,10]>>>
sampleN 12 (almostId clk2 clk7 en2 en7 0 (fromList [(1::Int)..10]))
[0,0,1,2,3,4,5,6,7,8,9,10]
veryUnsafeSynchronizer Source #
:: Either Int (Signal dom1 Int) | Period of clock belonging to |
-> Either Int (Signal dom2 Int) | Period of clock belonging to |
-> Signal dom1 a | |
-> Signal dom2 a |
Same as unsafeSynchronizer
, but with manually supplied clock periods.
Note: this unsafeSynchronizer is defined to be consistent with the vhdl and verilog implementations however as only synchronous signals are represented in Clash this cannot be done precisely and can lead to odd behavior. For example,
sample $ unsafeSynchronizer @Dom2 @Dom7 . unsafeSynchronizer @Dom7 @Dom2 $ fromList [0..10] > [0,4,4,4,7,7,7,7,11,11,11..
is quite different from the identity,
sample $ fromList [0..10] > [0,1,2,3,4,5,6,7,8,9,10..
with values appearing from the "future".
Reset
data Reset (dom :: Domain) Source #
A reset signal belonging to a domain called dom.
The underlying representation of resets is Bool
.
Instances
unsafeToReset :: KnownDomain dom => Signal dom Bool -> Reset dom Source #
unsafeToReset
is unsafe. For asynchronous resets it is unsafe
because it can introduce combinatorial loops. In case of synchronous resets
it can lead to meta-stability
issues in the presence of asynchronous resets.
NB: You probably want to use unsafeFromActiveLow
or
unsafeFromActiveHigh
.
unsafeFromReset :: Reset dom -> Signal dom Bool Source #
unsafeFromReset
is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
NB: You probably want to use unsafeToActiveLow
or
unsafeToActiveHigh
.
unsafeToActiveHigh :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool Source #
Convert a reset to an active high reset. Has no effect if reset is already an active high reset. Is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeToActiveLow :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool Source #
Convert a reset to an active low reset. Has no effect if reset is already an active low reset. It is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
:: forall dom. KnownDomain dom | |
=> Signal dom Bool | Reset signal that's |
-> Reset dom |
Interpret a signal of bools as an active high reset and convert it to a reset signal corresponding to the domain's setting.
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
:: forall dom. KnownDomain dom | |
=> Signal dom Bool | Reset signal that's |
-> Reset dom |
Interpret a signal of bools as an active low reset and convert it to a reset signal corresponding to the domain's setting.
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
Basic circuit functions
andEnable :: Enable dom -> Signal dom Bool -> Enable dom Source #
Merge enable signal with signal of bools by applying the boolean AND operation.
dflipflop :: (KnownDomain dom, NFDataX a) => Clock dom -> Signal dom a -> Signal dom a Source #
Special version of delay
that doesn't take enable signals of any kind.
Initial value will be undefined.
:: (KnownDomain dom, NFDataX a) | |
=> Clock dom | Clock |
-> Enable dom | Global enable |
-> a | Initial value |
-> Signal dom Bool | Enable |
-> Signal dom a | |
-> Signal dom a |
Version of delay
that only updates when its third argument is asserted.
>>>
let input = fromList [1,2,3,4,5,6,7::Int]
>>>
let enable = fromList [True,True,False,False,True,True,True]
>>>
sampleN 7 (delayEn systemClockGen enableGen 0 enable input)
[0,1,2,2,2,5,6]
:: (KnownDomain dom, NFDataX a) | |
=> Clock dom | Clock |
-> Reset dom | Reset, |
-> Enable dom | Global enable |
-> a | Reset value. If the domain has initial values enabled, the reset value will also be the initial value. |
-> Signal dom (Maybe a) | |
-> Signal dom a |
Version of register
that only updates its content when its fourth
argument is a Just
value. So given:
sometimes1 clk rst en = s where s =register
clk rst en Nothing (switch<$>
s) switch Nothing = Just 1 switch _ = Nothing countSometimes clk rst en = s where s =regMaybe
clk rst en 0 (plusM (pure
<$>
s) (sometimes1 clk rst en)) plusM = liftA2 (liftA2 (+))
We get:
>>>
sampleN 9 (sometimes1 systemClockGen resetGen enableGen)
[Nothing,Nothing,Just 1,Nothing,Just 1,Nothing,Just 1,Nothing,Just 1]>>>
sampleN 9 (count systemClockGen resetGen enableGen)
[0,0,0,1,1,2,2,3,3]
:: (KnownDomain dom, NFDataX a) | |
=> Clock dom | Clock |
-> Reset dom | Reset, |
-> Enable dom | Global enable |
-> a | Reset value. If the domain has initial values enabled, the reset value will also be the initial value. |
-> Signal dom Bool | Enable signal |
-> Signal dom a | |
-> Signal dom a |
Version of register
that only updates its content when its fourth
argument is asserted. So given:
oscillate clk rst en = let s = register
clk rst en False (not <$> s) in s
count clk rst en = let s = 'regEn clk rst en 0 (oscillate clk rst en) (s + 1) in s
We get:
>>>
sampleN 9 (oscillate systemClockGen resetGen enableGen)
[False,False,True,False,True,False,True,False,True]>>>
sampleN 9 (count systemClockGen resetGen enableGen)
[0,0,0,1,1,2,2,3,3]
mux :: Applicative f => f Bool -> f a -> f a -> f a Source #
Simulation and testbench functions
clockGen :: KnownDomain dom => Clock dom Source #
Clock generator for simulations. Do not use this clock generator for
the testBench function, use tbClockGen
instead.
To be used like:
clkSystem = clockGen @System
See DomainConfiguration
for more information on how to use synthesis domains.
resetGen :: forall dom. KnownDomain dom => Reset dom Source #
Reset generator for simulation purposes. Asserts the reset for a single cycle.
To be used like:
rstSystem = resetGen @System
See tbClockGen
for example usage.
NB: While this can be used in the testBench
function, it cannot be
synthesized to hardware.
:: forall dom n. (KnownDomain dom, 1 <= n) | |
=> SNat n | Number of initial cycles to hold reset high |
-> Reset dom |
Reset generator for simulation purposes. Asserts the reset for the first n cycles.
To be used like:
rstSystem5 = resetGen @System d5
Example usage:
>>>
sampleN 7 (unsafeToActiveHigh (resetGenN @System d3))
[True,True,True,False,False,False,False]
NB: While this can be used in the testBench
function, it cannot be
synthesized to hardware.
systemClockGen :: Clock System Source #
Clock generator for the System
clock domain.
NB: Should only be used for simulation, and not for the testBench
function. For the testBench function, used tbSystemClockGen
systemResetGen :: Reset System Source #
Reset generator for use in simulation, for the System
clock domain.
Asserts the reset for a single cycle.
NB: While this can be used in the testBench
function, it cannot be
synthesized to hardware.
Example
topEntity :: Vec 2 (Vec 3 (Unsigned 8)) -> Vec 6 (Unsigned 8)
topEntity = concat
testBench :: Signal System Bool
testBench = done
where
testInput = pure ((1 :> 2 :> 3 :> Nil) :> (4 :> 5 :> 6 :> Nil) :> Nil)
expectedOutput = outputVerifier' ((1:>2:>3:>4:>5:>6:>Nil):>Nil)
done = exposeClockResetEnable (expectedOutput (topEntity <$> testInput)) clk rst
clk = tbSystemClockGen (not <$> done)
rst = systemResetGen
Boolean connectives
Product/Signal isomorphism
Isomorphism between a Signal
of a product type (e.g. a tuple) and a
product type of Signal
s.
Instances of Bundle
must satisfy the following laws:
bundle
.unbundle
=id
unbundle
.bundle
=id
By default, bundle
and unbundle
, are defined as the identity, that is,
writing:
data D = A | B instance Bundle D
is the same as:
data D = A | B instance Bundle D where typeUnbundled
clk D =Signal
clk Dbundle
s = sunbundle
s = s
For custom product types you'll have to write the instance manually:
data Pair a b = MkPair { getA :: a, getB :: b } instance Bundle (Pair a b) where type Unbundled dom (Pair a b) = Pair (Signal dom a) (Signal dom b) -- bundle :: Pair (Signal dom a) (Signal dom b) -> Signal dom (Pair a b) bundle (MkPair as bs) = MkPair<$>
as<*>
bs -- unbundle :: Signal dom (Pair a b) -> Pair (Signal dom a) (Signal dom b) unbundle pairs = MkPair (getA<$>
pairs) (getB<$>
pairs)
Nothing
bundle :: Unbundled dom a -> Signal dom a Source #
Example:
bundle :: (Signal
dom a,Signal
dom b) ->Signal
dom (a,b)
However:
bundle ::Signal
domBit
->Signal
domBit
Instances
Bundle Bool Source # | |
Bundle Double Source # | |
Bundle Float Source # | |
Bundle Int Source # | |
Bundle Integer Source # | |
Bundle () Source # | |
Bundle Bit Source # | |
Bundle EmptyTuple Source # | See commit 94b0bff5
and documentation for |
Defined in Clash.Signal.Bundle type Unbundled dom EmptyTuple = (res :: Type) Source # bundle :: forall (dom :: Domain). Unbundled dom EmptyTuple -> Signal dom EmptyTuple Source # unbundle :: forall (dom :: Domain). Signal dom EmptyTuple -> Unbundled dom EmptyTuple Source # | |
Bundle (Maybe a) Source # | |
Bundle (BitVector n) Source # | |
Bundle (Index n) Source # | |
Bundle (Unsigned n) Source # | |
Bundle (Signed n) Source # | |
Bundle (Either a b) Source # | |
Bundle (a1, a2) Source # | |
KnownNat n => Bundle (Vec n a) Source # | |
KnownNat d => Bundle (RTree d a) Source # | |
Bundle (a1, a2, a3) Source # | NB: The documentation only shows instances up to 3-tuples. By
default, instances up to and including 12-tuples will exist. If the flag
|
Bundle (Fixed rep int frac) Source # | |
Defined in Clash.Signal.Bundle | |
Bundle ((f :*: g) a) Source # | |
data EmptyTuple Source #
See TaggedEmptyTuple
Instances
Bundle EmptyTuple Source # | See commit 94b0bff5
and documentation for |
Defined in Clash.Signal.Bundle type Unbundled dom EmptyTuple = (res :: Type) Source # bundle :: forall (dom :: Domain). Unbundled dom EmptyTuple -> Signal dom EmptyTuple Source # unbundle :: forall (dom :: Domain). Signal dom EmptyTuple -> Unbundled dom EmptyTuple Source # | |
Bundle EmptyTuple Source # | See commit 94b0bff5
and documentation for |
Defined in Clash.Signal.Delayed.Bundle type Unbundled dom d EmptyTuple = (res :: Type) Source # bundle :: forall (dom :: Domain) (d :: Nat). Unbundled dom d EmptyTuple -> DSignal dom d EmptyTuple Source # unbundle :: forall (dom :: Domain) (d :: Nat). DSignal dom d EmptyTuple -> Unbundled dom d EmptyTuple Source # | |
type Unbundled dom EmptyTuple Source # | |
Defined in Clash.Signal.Bundle | |
type Unbundled dom d EmptyTuple Source # | |
Defined in Clash.Signal.Delayed.Bundle |
data TaggedEmptyTuple (dom :: Domain) Source #
Helper type to emulate the "old" behavior of Bundle's unit instance. I.e.,
the instance for Bundle ()
used to be defined as:
class Bundle () where bundle :: () -> Signal dom () unbundle :: Signal dom () -> ()
In order to have sensible type inference, the Bundle
class specifies that
the argument type of bundle
should uniquely identify the result type, and
vice versa for unbundle
. The type signatures in the snippet above don't
though, as ()
doesn't uniquely map to a specific domain. In other words,
domain
should occur in both the argument and result of both functions.
TaggedEmptyTuple
tackles this by carrying the domain in its type. The
bundle
and unbundle
instance now looks like:
class Bundle EmptyTuple where bundle :: TaggedEmptyTuple dom -> Signal dom EmptyTuple unbundle :: Signal dom EmptyTuple -> TaggedEmptyTuple dom
dom
is now mentioned both the argument and result for both bundle
and
unbundle
.
Simulation functions (not synthesizable)
:: forall dom a b m. (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> a | Reset value |
-> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a -> Signal dom b) | Circuit to simulate |
-> [a] | |
-> [b] |
Same as simulate
, but with the reset line asserted for n cycles. Similar
to simulate
, simulateWithReset
will drop the output values produced while
the reset is asserted. While the reset is asserted, the first value from
[a]
is fed to the circuit.
:: (KnownDomain dom, NFDataX a, NFDataX b, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> a | Reset value |
-> Int | Number of cycles to simulate (excluding cycle spent in reset) |
-> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a -> Signal dom b) | Circuit to simulate |
-> [a] | |
-> [b] |
Same as simulateWithReset
, but only sample the first Int output values.
:: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) | |
=> (a -> Bool) | Condition checking function, should return |
-> Signal dom a |
|
-> IO () |
Simulate a component until it matches a condition
It prints a message of the form
Signal sampled for N cycles until value X
NB: This function is not synthesizable
Example with test bench
A common usage is with a test bench using
outputVerifier
.
NB: Since this uses assert
, when using
clashi
, read the note at Clash.Explicit.Testbench.
import Clash.Prelude import Clash.Explicit.Testbench topEntity ::Signal
System
Int ->Signal
System
Int topEntity = id testBench ::Signal
System
Bool testBench = done where testInput =stimuliGenerator
clk rst $(listToVecTH
[1 :: Int .. 10]) expectedOutput =outputVerifier'
clk rst $(listToVecTH
$ [1 :: Int .. 9]<>
[42]) done = expectedOutput $ topEntity testInput clk =tbSystemClockGen
(not <$> done) rst =systemResetGen
> runUntil id testBench cycle(<Clock: System>): 10, outputVerifier expected value: 42, not equal to actual value: 10 Signal sampled for 11 cycles until value True
When you need to verify multiple test benches, the following invocations come in handy:
> mapM_
(runUntil id) [ testBenchA, testBenchB ]
or when the test benches are in different clock domains:
testBenchA :: Signal DomA Bool testBenchB :: Signal DomB Bool
> sequence_
[ runUntil id testBenchA, runUntil id testBenchB ]
lazy versions
simulate_lazy :: (Signal dom1 a -> Signal dom2 b) -> [a] -> [b] Source #
Automaton
List <-> Signal conversion (not synthesizable)
:: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a) |
|
-> [a] |
Get a list of samples from a Signal
, while asserting the reset line
for n clock cycles. sampleWithReset
does not return the first n cycles,
i.e., when the reset is asserted.
NB: This function is not synthesizable
:: forall dom a m. (KnownDomain dom, NFDataX a, 1 <= m) | |
=> SNat m | Number of cycles to assert the reset |
-> Int | Number of samples to produce |
-> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Signal dom a) |
|
-> [a] |
Get a fine list of m samples from a Signal
, while asserting the reset line
for n clock cycles. sampleWithReset
does not return the first n cycles,
i.e., while the reset is asserted.
NB: This function is not synthesizable
fromList :: NFDataX a => [a] -> Signal dom a Source #
Create a Signal
from a list
Every element in the list will correspond to a value of the signal for one clock cycle.
>>>
sampleN 2 (fromList [1,2,3,4,5])
[1,2]
NB: This function is not synthesizable
fromListWithReset :: forall dom a. (KnownDomain dom, NFDataX a) => Reset dom -> a -> [a] -> Signal dom a Source #
Like fromList
, but resets on reset and has a defined reset value.
>>>
let rst = unsafeFromActiveHigh (fromList [True, True, False, False, True, False])
>>>
let res = fromListWithReset @System rst Nothing [Just 'a', Just 'b', Just 'c']
>>>
sampleN 6 res
[Nothing,Nothing,Just 'a',Just 'b',Nothing,Just 'a']
NB: This function is not synthesizable
lazy versions
sample_lazy :: Foldable f => f a -> [a] Source #
sampleN_lazy :: Foldable f => Int -> f a -> [a] Source #
fromList_lazy :: [a] -> Signal dom a Source #
Create a Signal
from a list
Every element in the list will correspond to a value of the signal for one clock cycle.
>>>
sampleN 2 (fromList [1,2,3,4,5] :: Signal System Int)
[1,2]
NB: This function is not synthesizable
QuickCheck combinators
Type classes
Eq
-like
Ord
-like
Bisignal functions
veryUnsafeToBiSignalIn :: (HasCallStack, KnownNat n, Given (SBiSignalDefault ds)) => BiSignalOut ds d n -> BiSignalIn ds d n Source #
Converts the out
part of a BiSignal to an in
part. In simulation it
checks whether multiple components are writing and will error accordingly.
Make sure this is only called ONCE for every BiSignal.
:: (HasCallStack, BitPack a) | |
=> BiSignalIn ds d (BitSize a) | A |
-> Signal d a |
Read the value from an inout port
:: (HasCallStack, BitPack a, NFDataX a) | |
=> BiSignalIn ds d (BitSize a) | |
-> Signal d (Maybe a) | Value to write
|
-> BiSignalOut ds d (BitSize a) |
Write to an inout port
mergeBiSignalOuts :: (HasCallStack, KnownNat n) => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m Source #
Combine several inout signals into one.
Deprecated
unsafeFromHighPolarity Source #
:: forall dom. KnownDomain dom | |
=> Signal dom Bool | Reset signal that's |
-> Reset dom |
Deprecated: Use unsafeFromActiveHigh
instead. This function will be removed in Clash 1.12.
Interpret a signal of bools as an active high reset and convert it to a reset signal corresponding to the domain's setting.
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeFromLowPolarity Source #
:: forall dom. KnownDomain dom | |
=> Signal dom Bool | Reset signal that's |
-> Reset dom |
Deprecated: Use unsafeFromActiveLow
instead. This function will be removed in Clash 1.12.
Interpret a signal of bools as an active low reset and convert it to a reset signal corresponding to the domain's setting.
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeToHighPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool Source #
Deprecated: Use unsafeToActiveHigh
instead. This function will be removed in Clash 1.12.
Convert a reset to an active high reset. Has no effect if reset is already an active high reset. Is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.
unsafeToLowPolarity :: forall dom. KnownDomain dom => Reset dom -> Signal dom Bool Source #
Deprecated: Use unsafeToActiveLow
instead. This function will be removed in Clash 1.12.
Convert a reset to an active low reset. Has no effect if reset is already an active low reset. It is unsafe because it can introduce:
For asynchronous resets it is unsafe because it can cause combinatorial loops. In case of synchronous resets it can lead to meta-stability in the presence of asynchronous resets.