clash-prelude-0.99: CAES Language for Synchronous Hardware - Prelude library

Copyright(C) 2013-2016 University of Twente
2016 Myrtle Software
2017 Google Inc.
LicenseBSD2 (see the file LICENSE)
MaintainerChristiaan Baaij <christiaan.baaij@gmail.com>
Safe HaskellTrustworthy
LanguageHaskell2010
Extensions
  • MonoLocalBinds
  • GADTs
  • GADTSyntax
  • DataKinds
  • MagicHash

Clash.Explicit.Signal

Contents

Description

CλaSH has synchronous Signals in the form of:

Signal (domain :: Domain) a

Where a is the type of the value of the Signal, for example Int or Bool, and domain is the clock- (and reset-) domain to which the memory elements manipulating these Signals belong.

The type-parameter, domain, is of the kind Domain which has types of the following shape:

data Domain = Dom { domainName :: Symbol, clkPeriod :: Nat }

Where domainName is a type-level string (Symbol) representing the name of the clock- (and reset-) domain, and clkPeriod is a type-level natural number (Nat) representing the clock period (in ps) of the clock lines in the clock-domain.

  • 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!

Explicit clocks and resets, and meta-stability

When clocks and resets are implicitly routed using the mechanisms provided by the clash-prelude, then clocks and resets are also implicitly unique.

The protection against accidental metastability offered by Clash's domain annotation on Signals is based on the uniqueness of clocks and resets. But with explicit clock and reset lines, there are ways to (accidentally) introduce situations that are prone to metastability.

There are four different clock and reset lines:

Reset domain Synchronous
Reset domain Asynchronous
Clock domain Source
Clock domain Gated

We now go over the combinations over these clock and reset line combinations and explain when they can potentially introduce situations prone to meta-stability:

  • Reset situation 1:

    f :: Reset domain Synchronous -> Reset domain Synchronous -> ..
    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 domain Asynchronous -> Reset domain Asynchronous -> ..
    g x y = ..
    

    This situation can be prone to metastability, because although x and y belong to the same domain according to their type, 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.

    • The Clash compiler will give a warning whenever a function has a type-signature similar to the one above.
    • This is the reason why unsafeFromAsyncReset is prefixed with the word unsafe.
  • Reset situation 3:

    h :: Reset domain Asynchronous -> Reset domain Synchronous -> ..
    h x y = ..
    

    Also this situation is prone to metastability, because again, one component can enter its reset state asynchronously to the other, inducing metastability in the other component.

    • The Clash compiler will give a warning whenever a function has a type-signature similar to the one above.
    • Although in a standalone context, converting between Reset domain Synchronous and Signal domain Bool would be safe from a metastability point of view, it is not when we're in a context where there are also asynchronous resets. That is why unsafeToSyncReset is prefixed with the word unsafe.
  • Clock situations 1, 2, and 3:

    k :: Clock domain Source -> Clock domain source -> ..
    k x y = ..
    
    l :: Clock domain Source -> Clock domain Gated -> ..
    l x y = ..
    
    m :: Clock domain Gated -> Clock domain Gated -> ..
    m x y = ..
    

    All the above situations are potentially prone to metastability, because even though x and y belong to the same domain according to their type, 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.

    • The Clash compiler will give a warning whenever a function has a type-signature similar to one of the above three situations.

Synopsis

Synchronous signal

data Signal (domain :: Domain) a Source #

CλaSH has synchronous Signals in the form of:

Signal (domain :: Domain) a

Where a is the type of the value of the Signal, for example Int or Bool, and domain is the clock- (and reset-) domain to which the memory elements manipulating these Signals belong.

The type-parameter, domain, is of the kind Domain which has types of the following shape:

data Domain = Dom { domainName :: Symbol, clkPeriod :: Nat }

Where domainName is a type-level string (Symbol) representing the name of the clock- (and reset-) domain, and clkPeriod is a type-level natural number (Nat) representing the clock period (in ps) of the clock lines in the clock-domain.

  • 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!

Instances

Functor (Signal domain) Source # 

Methods

fmap :: (a -> b) -> Signal domain a -> Signal domain b #

(<$) :: a -> Signal domain b -> Signal domain a #

Applicative (Signal domain) Source # 

Methods

pure :: a -> Signal domain a #

(<*>) :: Signal domain (a -> b) -> Signal domain a -> Signal domain b #

liftA2 :: (a -> b -> c) -> Signal domain a -> Signal domain b -> Signal domain c #

(*>) :: Signal domain a -> Signal domain b -> Signal domain b #

(<*) :: Signal domain a -> Signal domain b -> Signal domain a #

Foldable (Signal domain) Source #

NB: Not synthesisable

NB: In "foldr f z s":

  • The function f should be lazy in its second argument.
  • The z element will never be used.

Methods

fold :: Monoid m => Signal domain m -> m #

foldMap :: Monoid m => (a -> m) -> Signal domain a -> m #

foldr :: (a -> b -> b) -> b -> Signal domain a -> b #

foldr' :: (a -> b -> b) -> b -> Signal domain a -> b #

foldl :: (b -> a -> b) -> b -> Signal domain a -> b #

foldl' :: (b -> a -> b) -> b -> Signal domain a -> b #

foldr1 :: (a -> a -> a) -> Signal domain a -> a #

foldl1 :: (a -> a -> a) -> Signal domain a -> a #

toList :: Signal domain a -> [a] #

null :: Signal domain a -> Bool #

length :: Signal domain a -> Int #

elem :: Eq a => a -> Signal domain a -> Bool #

maximum :: Ord a => Signal domain a -> a #

minimum :: Ord a => Signal domain a -> a #

sum :: Num a => Signal domain a -> a #

product :: Num a => Signal domain a -> a #

Traversable (Signal domain) Source # 

Methods

traverse :: Applicative f => (a -> f b) -> Signal domain a -> f (Signal domain b) #

sequenceA :: Applicative f => Signal domain (f a) -> f (Signal domain a) #

mapM :: Monad m => (a -> m b) -> Signal domain a -> m (Signal domain b) #

sequence :: Monad m => Signal domain (m a) -> m (Signal domain a) #

Fractional a => Fractional (Signal domain a) Source # 

Methods

(/) :: Signal domain a -> Signal domain a -> Signal domain a #

recip :: Signal domain a -> Signal domain a #

fromRational :: Rational -> Signal domain a #

Num a => Num (Signal domain a) Source # 

Methods

(+) :: Signal domain a -> Signal domain a -> Signal domain a #

(-) :: Signal domain a -> Signal domain a -> Signal domain a #

(*) :: Signal domain a -> Signal domain a -> Signal domain a #

negate :: Signal domain a -> Signal domain a #

abs :: Signal domain a -> Signal domain a #

signum :: Signal domain a -> Signal domain a #

fromInteger :: Integer -> Signal domain a #

Show a => Show (Signal domain a) Source # 

Methods

showsPrec :: Int -> Signal domain a -> ShowS #

show :: Signal domain a -> String #

showList :: [Signal domain a] -> ShowS #

Lift a => Lift (Signal domain a) Source # 

Methods

lift :: Signal domain a -> Q Exp #

Arbitrary a => Arbitrary (Signal domain a) Source # 

Methods

arbitrary :: Gen (Signal domain a) #

shrink :: Signal domain a -> [Signal domain a] #

CoArbitrary a => CoArbitrary (Signal domain a) Source # 

Methods

coarbitrary :: Signal domain a -> Gen b -> Gen b #

Default a => Default (Signal domain a) Source # 

Methods

def :: Signal domain a #

data Domain Source #

A domain with a name (Symbol) and a clock period (Nat) in ps

Constructors

Dom 

type System = Dom "system" 10000 Source #

A clock (and reset) domain with clocks running at 100 MHz

Clock

data Clock (domain :: Domain) (gated :: ClockKind) Source #

A clock signal belonging to a domain

Instances

Show (Clock domain gated) Source # 

Methods

showsPrec :: Int -> Clock domain gated -> ShowS #

show :: Clock domain gated -> String #

showList :: [Clock domain gated] -> ShowS #

data ClockKind Source #

Distinction between gated and ungated clocks

Constructors

Source

A clock signal coming straight from the clock source

Gated

A clock signal that has been gated

Instances

Eq ClockKind Source # 
Ord ClockKind Source # 
Show ClockKind Source # 
Generic ClockKind Source # 

Associated Types

type Rep ClockKind :: * -> * #

NFData ClockKind Source # 

Methods

rnf :: ClockKind -> () #

type Rep ClockKind Source # 
type Rep ClockKind = D1 * (MetaData "ClockKind" "Clash.Signal.Internal" "clash-prelude-0.99-CsW3cvpqI9M691u8MbXWmM" False) ((:+:) * (C1 * (MetaCons "Source" PrefixI False) (U1 *)) (C1 * (MetaCons "Gated" PrefixI False) (U1 *)))

freqCalc :: Double -> Integer 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

>>> freqCalc 240e6
4167

NB: This function is not synthesisable

Synchronisation primitive

unsafeSynchronizer Source #

Arguments

:: Clock domain1 gated1

Clock of the incoming signal

-> Clock domain2 gated2

Clock of the outgoing signal

-> Signal domain1 a 
-> Signal domain2 a 

The unsafeSynchronizer function is a primitive that must be used to connect one clock domain to the other, and will be synthesised to a (bundle of) wire(s) in the eventual circuit. This function should only be used as part of a proper synchronisation component, such as the following dual flip-flop synchronizer:

dualFlipFlop :: Clock domA gatedA -> Clock domB gatedB
             -> Signal domA Bit -> Signal domB Bit
dualFlipFlop clkA clkB = delay clkB . delay clkB
                       . unsafeSynchronizer clkA clkB

The unsafeSynchronizer works in such a way that, given 2 clocks:

type Dom7 = Dom "dom" 7

clk7 :: Clock Dom7 Source
clk7 = clockGen

and

type Dom2 = Dom "dom" 2

clk2 :: Clock Dom2 Source
clk2 = clockGen

Oversampling followed by compression is the identity function plus 2 initial values:

delay clkB $
unsafeSynchronizer clkA clkB $
delay clkA $
unsafeSynchronizer clkB clkA $
delay clkB s

==

X :- X :- s

Something we can easily observe:

oversampling clkA clkB = delay clkB . unsafeSynchronizer clkA clkB
                       . delay clkA
almostId clkA clkB = delay clkB . unsafeSynchronizer clkA clkB
                   . delay clkA . unsafeSynchronizer clkB clkA
                   . delay clkB
>>> printX (sampleN 37 (oversampling clk7 clk2 (fromList [(1::Int)..10])))
[X,X,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]
>>> printX (sampleN 12 (almostId clk2 clk7 (fromList [(1::Int)..10])))
[X,X,1,2,3,4,5,6,7,8,9,10]

Clock gating

clockGate :: Clock domain gated -> Signal domain Bool -> Clock domain Gated Source #

Clock gating primitive

Reset

data Reset (domain :: Domain) (synchronous :: ResetKind) Source #

A reset signal belonging to a domain.

The underlying representation of resets is Bool. Note that all components in the clash-prelude package have an active-high reset port, i.e., the component is reset when the reset port is True.

data ResetKind Source #

The "kind" of reset

Given a situation where a reset is asserted, and then de-asserted at the active flank of the clock, we can observe the difference between a synchronous reset and an asynchronous reset:

Synchronous reset

registerS
  :: Clock domain gated -> Reset domain Synchronous
  -> Signal domain Int -> Signal domain Int
registerS = register
>>> printX (sampleN 4 (registerS (clockGen @System) (syncResetGen @System) 0 (fromList [1,2,3])))
[X,0,2,3]

Asynchronous reset

registerA
  :: Clock domain gated -> Reset domain Asynchronous
  -> Signal domain Int -> Signal domain Int
registerA = register
>>> sampleN 4 (registerA (clockGen @System) (asyncResetGen @System) 0 (fromList [1,2,3]))
[0,1,2,3]

Constructors

Synchronous

Components with a synchronous reset port produce the reset value when:

  • The reset is asserted during the active flank of the clock to which the component is synchronized.
Asynchronous

Components with an asynchronous reset port produce the reset value when:

  • Immediately when the reset is asserted.

Instances

Eq ResetKind Source # 
Ord ResetKind Source # 
Show ResetKind Source # 
Generic ResetKind Source # 

Associated Types

type Rep ResetKind :: * -> * #

NFData ResetKind Source # 

Methods

rnf :: ResetKind -> () #

type Rep ResetKind Source # 
type Rep ResetKind = D1 * (MetaData "ResetKind" "Clash.Signal.Internal" "clash-prelude-0.99-CsW3cvpqI9M691u8MbXWmM" False) ((:+:) * (C1 * (MetaCons "Synchronous" PrefixI False) (U1 *)) (C1 * (MetaCons "Asynchronous" PrefixI False) (U1 *)))

unsafeFromAsyncReset :: Reset domain Asynchronous -> Signal domain Bool Source #

unsafeFromAsyncReset is unsafe because it can introduce:

unsafeToAsyncReset :: Signal domain Bool -> Reset domain Asynchronous Source #

unsafeToAsyncReset is unsafe because it can introduce:

  • combinational loops

Example

resetSynchronizer
  :: Clock domain gated
  -> Reset domain 'Asynchronous
  -> Reset domain 'Asynchronous
resetSynchronizer clk rst  =
  let r1 = register clk rst True (pure False)
      r2 = register clk rst True r1
  in  unsafeToAsyncReset r2

fromSyncReset :: Reset domain Synchronous -> Signal domain Bool Source #

It is safe to treat synchronous resets as Bool signals

unsafeToSyncReset :: Signal domain Bool -> Reset domain Synchronous Source #

unsafeToSyncReset is unsafe because:

  • It can lead to meta-stability issues in the presence of asynchronous resets.

resetSynchronizer :: Clock domain gated -> Reset domain Asynchronous -> Reset domain Asynchronous Source #

Normally, asynchronous resets can be both asynchronously asserted and de-asserted. Asynchronous de-assertion can induce meta-stability in the component which is being reset. To ensure this doesn't happen, resetSynchronizer ensures that de-assertion of a reset happens synchronously. Assertion of the reset remains asynchronous.

Note that asynchronous assertion does not induce meta-stability in the component whose reset is asserted. However, when a component "A" in another clock or reset domain depends on the value of a component "B" being reset, then asynchronous assertion of the reset of component "B" can induce meta-stability in component "A". To prevent this from happening you need to use a proper synchronizer, for example one of the synchronizers in Clash.Explicit.Synchronizer

NB: Assumes the component(s) being reset have an active-high reset port, which all components in clash-prelude have.

Example

topEntity
  :: Clock  System Source
  -> Reset  System Asynchronous
  -> Signal System Bit
  -> Signal System (BitVector 8)
topEntity clk rst key1 =
    let  (pllOut,pllStable) = altpll (SSymbol @ "altpll50") clk rst
         rstSync            = resetSynchronizer pllOut (unsafeToAsyncReset pllStable)
    in   exposeClockReset leds pllOut rstSync
  where
    key1R  = isRising 1 key1
    leds   = mealy blinkerT (1,False,0) key1R

Basic circuit functions

delay Source #

Arguments

:: HasCallStack 
=> Clock domain gated

Clock

-> Signal domain a 
-> Signal domain a 

"delay clk s" delays the values in Signal s for once cycle, the value at time 0 is undefined.

>>> printX (sampleN 3 (delay systemClockGen (fromList [1,2,3,4])))
[X,1,2]

register Source #

Arguments

:: HasCallStack 
=> Clock domain gated

clock

-> Reset domain synchronous

Reset (active-high), register outputs the reset value when the reset value becomes True

-> a

Reset value

-> Signal domain a 
-> Signal domain a 

"register clk rst i s" delays the values in Signal s for one cycle, and sets the value to i the moment the reset becomes False.

>>> sampleN 3 (register systemClockGen systemResetGen 8 (fromList [1,2,3,4]))
[8,1,2]

regMaybe Source #

Arguments

:: HasCallStack 
=> Clock domain gated

Clock

-> Reset domain synchronous

Reset (active-high), regMaybe outputs the reset value when the reset value becomes True

-> a

Reset value

-> Signal domain (Maybe a) 
-> Signal domain a 

Version of register that only updates its content when its fourth argument is a Just value. So given:

sometimes1 clk rst = s where
  s = register clk rst Nothing (switch <$> s)

  switch Nothing = Just 1
  switch _       = Nothing

countSometimes clk rst = s where
  s     = regMaybe clk rst 0 (plusM (pure <$> s) (sometimes1 clk rst))
  plusM = liftA2 (liftA2 (+))

We get:

>>> sampleN 8 (sometimes1 systemClockGen systemResetGen)
[Nothing,Just 1,Nothing,Just 1,Nothing,Just 1,Nothing,Just 1]
>>> sampleN 8 (count systemClockGen systemResetGen)
[0,0,1,1,2,2,3,3]

regEn Source #

Arguments

:: Clock domain clk

Clock

-> Reset domain synchronous

Reset (active-high), regEn outputs the reset value when the reset value becomes True

-> a

Reset value

-> Signal domain Bool

Enable signal

-> Signal domain a 
-> Signal domain a 

Version of register that only updates its content when its fourth argument is asserted. So given:

oscillate clk rst = let s = register clk rst False (not <$> s) in s
count clk rst     = let s = 'regEn clk rst 0 (oscillate clk rst) (s + 1) in s

We get:

>>> sampleN 8 (oscillate systemClockGen systemResetGen)
[False,True,False,True,False,True,False,True]
>>> sampleN 8 (count systemClockGen systemResetGen)
[0,0,1,1,2,2,3,3]

Simulation and testbench functions

clockGen :: (domain ~ Dom nm period, KnownSymbol nm, KnownNat period) => Clock domain Source Source #

Clock generator for simulations. Do not use this clock generator for for the testBench function, use tbClockGen instead.

To be used like:

type DomA = Dom "A" 1000
clkA = clockGen @DomA

tbClockGen :: (domain ~ Dom nm period, KnownSymbol nm, KnownNat period) => Signal domain Bool -> Clock domain Source Source #

Clock generator to be used in the testBench function.

To be used like:

type DomA = Dom "A" 1000
clkA en = clockGen @DomA en

Example

type DomA1 = Dom "A" 1 -- fast, twice as fast as slow
type DomB2 = Dom "B" 2 -- slow

topEntity
  :: Clock DomA1 Source
  -> Reset DomA1 Asynchronous
  -> Clock DomB2 Source
  -> Signal DomA1 (Unsigned 8)
  -> Signal DomB2 (Unsigned 8, Unsigned 8)
topEntity clk1 rst1 clk2 i =
  let h = register clk1 rst1 0 (register clk1 rst1 0 i)
      l = register clk1 rst1 0 i
  in  unsafeSynchronizer clk1 clk2 (bundle (h,l))

testBench
  :: Signal DomB2 Bool
testBench = done
  where
    testInput      = stimuliGenerator clkA1 rstA1 $(listToVecTH [1::Unsigned 8,2,3,4,5,6,7,8])
    expectedOutput = outputVerifier   clkB2 rstB2 $(listToVecTH [(0,0) :: (Unsigned 8, Unsigned 8),(1,2),(3,4),(5,6),(7,8)])
    done           = expectedOutput (topEntity clkA1 rstA1 clkB2 testInput)
    done'          = not <$> done
    clkA1          = tbClockGen @DomA1 (unsafeSynchronizer clkB2 clkA1 done')
    clkB2          = tbClockGen @DomB2 done'
    rstA1          = asyncResetGen @DomA1
    rstB2          = asyncResetGen @DomB2

asyncResetGen :: Reset domain Asynchronous Source #

Asynchronous reset generator, for simulations and the testBench function.

To be used like:

type DomA = Dom "A" 1000
rstA = asyncResetGen @DomA

NB: Can only be used for components with an active-high reset port, which all clash-prelude components are.

Example

type Dom2 = Dom "dom" 2
type Dom7 = Dom "dom" 7
type Dom9 = Dom "dom" 9

topEntity
  :: Clock Dom2 Source
  -> Clock Dom7 Source
  -> Clock Dom9 Source
  -> Signal Dom7 Integer
  -> Signal Dom9 Integer
topEntity clk2 clk7 clk9 i = delay clk9 (unsafeSynchronizer clk2 clk9 (delay clk2 (unsafeSynchronizer clk7 clk2 (delay clk7 i))))
{--}

testBench
  :: Signal Dom9 Bool
testBench = done
  where
    testInput      = stimuliGenerator clk7 rst7 $(listToVecTH [(1::Integer)..10])
    expectedOutput = outputVerifier   clk9 rst9
                        ((undefined :> undefined :> Nil) ++ $(listToVecTH ([2,3,4,5,7,8,9,10]::[Integer])))
    done           = expectedOutput (topEntity clk2 clk7 clk9 testInput)
    done'          = not <$> done
    clk2           = tbClockGen @Dom2 (unsafeSynchronizer clk9 clk2 done')
    clk7           = tbClockGen @Dom7 (unsafeSynchronizer clk9 clk7 done')
    clk9           = tbClockGen @Dom9 done'
    rst7           = asyncResetGen @Dom7
    rst9           = asyncResetGen @Dom9

syncResetGen :: (domain ~ Dom n clkPeriod, KnownNat clkPeriod) => Reset domain Synchronous Source #

Synchronous reset generator, for simulations and the testBench function.

To be used like:

type DomA = Dom "A" 1000
rstA = syncResetGen @DomA

NB: Can only be used for components with an active-high reset port, which all clash-prelude components are.

systemClockGen :: Clock System Source 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

tbSystemClockGen :: Signal System Bool -> Clock System Source Source #

Clock generator for the System clock domain.

NB: can be used in the testBench function

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           = exposeClockReset (expectedOutput (topEntity $ testInput)) clk rst
    clk            = tbSystemClockGen (not <$> done)
    rst            = systemResetGen

systemResetGen :: Reset System Asynchronous Source #

Reset generator for the System clock domain.

NB: should only be used for simulation or the testBench function.

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           = exposeClockReset (expectedOutput (topEntity $ testInput)) clk rst
    clk            = tbSystemClockGen (not <$> done)
    rst            = systemResetGen

Boolean connectives

(.&&.) :: Applicative f => f Bool -> f Bool -> f Bool infixr 3 Source #

The above type is a generalisation for:

(.&&.) :: Signal Bool -> Signal Bool -> Signal Bool

It is a version of (&&) that returns a Signal of Bool

(.||.) :: Applicative f => f Bool -> f Bool -> f Bool infixr 2 Source #

The above type is a generalisation for:

(.||.) :: Signal Bool -> Signal Bool -> Signal Bool

It is a version of (||) that returns a Signal of Bool

Product/Signal isomorphism

class Bundle a where Source #

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
  type Unbundled' clk D = Signal' clk D
  bundle   _ s = s
  unbundle _ s = s

Associated Types

type Unbundled (domain :: Domain) a = res | res -> domain a Source #

Methods

bundle :: Unbundled domain a -> Signal domain a Source #

Example:

bundle :: (Signal domain a, Signal domain b) -> Signal clk (a,b)

However:

bundle :: Signal domain Bit -> Signal domain Bit

bundle :: Signal domain a ~ Unbundled domain a => Unbundled domain a -> Signal domain a Source #

Example:

bundle :: (Signal domain a, Signal domain b) -> Signal clk (a,b)

However:

bundle :: Signal domain Bit -> Signal domain Bit

unbundle :: Signal domain a -> Unbundled domain a Source #

Example:

unbundle :: Signal domain (a,b) -> (Signal domain a, Signal domain b)

However:

unbundle :: Signal domain Bit -> Signal domain Bit

unbundle :: Unbundled domain a ~ Signal domain a => Signal domain a -> Unbundled domain a Source #

Example:

unbundle :: Signal domain (a,b) -> (Signal domain a, Signal domain b)

However:

unbundle :: Signal domain Bit -> Signal domain Bit

Instances

Bundle Bool Source # 

Associated Types

type Unbundled (domain :: Domain) Bool = (res :: *) Source #

Methods

bundle :: Unbundled domain Bool -> Signal domain Bool Source #

unbundle :: Signal domain Bool -> Unbundled domain Bool Source #

Bundle Double Source # 

Associated Types

type Unbundled (domain :: Domain) Double = (res :: *) Source #

Methods

bundle :: Unbundled domain Double -> Signal domain Double Source #

unbundle :: Signal domain Double -> Unbundled domain Double Source #

Bundle Float Source # 

Associated Types

type Unbundled (domain :: Domain) Float = (res :: *) Source #

Methods

bundle :: Unbundled domain Float -> Signal domain Float Source #

unbundle :: Signal domain Float -> Unbundled domain Float Source #

Bundle Int Source # 

Associated Types

type Unbundled (domain :: Domain) Int = (res :: *) Source #

Methods

bundle :: Unbundled domain Int -> Signal domain Int Source #

unbundle :: Signal domain Int -> Unbundled domain Int Source #

Bundle Integer Source # 

Associated Types

type Unbundled (domain :: Domain) Integer = (res :: *) Source #

Methods

bundle :: Unbundled domain Integer -> Signal domain Integer Source #

unbundle :: Signal domain Integer -> Unbundled domain Integer Source #

Bundle () Source #

Note that:

bundle   :: () -> Signal domain ()
unbundle :: Signal domain () -> ()

Associated Types

type Unbundled (domain :: Domain) () = (res :: *) Source #

Methods

bundle :: Unbundled domain () -> Signal domain () Source #

unbundle :: Signal domain () -> Unbundled domain () Source #

Bundle Bit Source # 

Associated Types

type Unbundled (domain :: Domain) Bit = (res :: *) Source #

Methods

bundle :: Unbundled domain Bit -> Signal domain Bit Source #

unbundle :: Signal domain Bit -> Unbundled domain Bit Source #

Bundle (Maybe a) Source # 

Associated Types

type Unbundled (domain :: Domain) (Maybe a) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Maybe a) -> Signal domain (Maybe a) Source #

unbundle :: Signal domain (Maybe a) -> Unbundled domain (Maybe a) Source #

Bundle (BitVector n) Source # 

Associated Types

type Unbundled (domain :: Domain) (BitVector n) = (res :: *) Source #

Methods

bundle :: Unbundled domain (BitVector n) -> Signal domain (BitVector n) Source #

unbundle :: Signal domain (BitVector n) -> Unbundled domain (BitVector n) Source #

Bundle (Index n) Source # 

Associated Types

type Unbundled (domain :: Domain) (Index n) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Index n) -> Signal domain (Index n) Source #

unbundle :: Signal domain (Index n) -> Unbundled domain (Index n) Source #

Bundle (Unsigned n) Source # 

Associated Types

type Unbundled (domain :: Domain) (Unsigned n) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Unsigned n) -> Signal domain (Unsigned n) Source #

unbundle :: Signal domain (Unsigned n) -> Unbundled domain (Unsigned n) Source #

Bundle (Signed n) Source # 

Associated Types

type Unbundled (domain :: Domain) (Signed n) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Signed n) -> Signal domain (Signed n) Source #

unbundle :: Signal domain (Signed n) -> Unbundled domain (Signed n) Source #

Bundle (Either a b) Source # 

Associated Types

type Unbundled (domain :: Domain) (Either a b) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Either a b) -> Signal domain (Either a b) Source #

unbundle :: Signal domain (Either a b) -> Unbundled domain (Either a b) Source #

Bundle (a, b) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b) -> Signal domain (a, b) Source #

unbundle :: Signal domain (a, b) -> Unbundled domain (a, b) Source #

KnownNat n => Bundle (Vec n a) Source # 

Associated Types

type Unbundled (domain :: Domain) (Vec n a) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Vec n a) -> Signal domain (Vec n a) Source #

unbundle :: Signal domain (Vec n a) -> Unbundled domain (Vec n a) Source #

KnownNat d => Bundle (RTree d a) Source # 

Associated Types

type Unbundled (domain :: Domain) (RTree d a) = (res :: *) Source #

Methods

bundle :: Unbundled domain (RTree d a) -> Signal domain (RTree d a) Source #

unbundle :: Signal domain (RTree d a) -> Unbundled domain (RTree d a) Source #

Bundle (a, b, c) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b, c) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b, c) -> Signal domain (a, b, c) Source #

unbundle :: Signal domain (a, b, c) -> Unbundled domain (a, b, c) Source #

Bundle (Fixed rep int frac) Source # 

Associated Types

type Unbundled (domain :: Domain) (Fixed rep int frac) = (res :: *) Source #

Methods

bundle :: Unbundled domain (Fixed rep int frac) -> Signal domain (Fixed rep int frac) Source #

unbundle :: Signal domain (Fixed rep int frac) -> Unbundled domain (Fixed rep int frac) Source #

Bundle (a, b, c, d) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b, c, d) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b, c, d) -> Signal domain (a, b, c, d) Source #

unbundle :: Signal domain (a, b, c, d) -> Unbundled domain (a, b, c, d) Source #

Bundle (a, b, c, d, e) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b, c, d, e) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b, c, d, e) -> Signal domain (a, b, c, d, e) Source #

unbundle :: Signal domain (a, b, c, d, e) -> Unbundled domain (a, b, c, d, e) Source #

Bundle (a, b, c, d, e, f) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b, c, d, e, f) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b, c, d, e, f) -> Signal domain (a, b, c, d, e, f) Source #

unbundle :: Signal domain (a, b, c, d, e, f) -> Unbundled domain (a, b, c, d, e, f) Source #

Bundle (a, b, c, d, e, f, g) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b, c, d, e, f, g) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b, c, d, e, f, g) -> Signal domain (a, b, c, d, e, f, g) Source #

unbundle :: Signal domain (a, b, c, d, e, f, g) -> Unbundled domain (a, b, c, d, e, f, g) Source #

Bundle (a, b, c, d, e, f, g, h) Source # 

Associated Types

type Unbundled (domain :: Domain) (a, b, c, d, e, f, g, h) = (res :: *) Source #

Methods

bundle :: Unbundled domain (a, b, c, d, e, f, g, h) -> Signal domain (a, b, c, d, e, f, g, h) Source #

unbundle :: Signal domain (a, b, c, d, e, f, g, h) -> Unbundled domain (a, b, c, d, e, f, g, h) Source #

Simulation functions (not synthesisable)

simulate :: (NFData a, NFData b) => (Signal domain1 a -> Signal domain2 b) -> [a] -> [b] Source #

Simulate a (Signal a -> Signal b) function given a list of samples of type a

>>> simulate (register systemClockGen systemResetGen 8) [1, 2, 3]
[8,1,2,3...
...

NB: This function is not synthesisable

simulateB Source #

Arguments

:: (Bundle a, Bundle b, NFData a, NFData b) 
=> (Unbundled domain1 a -> Unbundled domain2 b)

The function we want to simulate

-> [a]

Input samples

-> [b] 

Simulate a (Unbundled a -> Unbundled b) function given a list of samples of type a

>>> simulateB (unbundle . register systemClockGen systemResetGen (8,8) . bundle) [(1,1), (2,2), (3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)...
...

NB: This function is not synthesisable

lazy versions

simulate_lazy :: (Signal domain1 a -> Signal domain2 b) -> [a] -> [b] Source #

Simulate a (Signal a -> Signal b) function given a list of samples of type a

>>> simulate (register systemClockGen systemResetGen 8) [1, 2, 3]
[8,1,2,3...
...

NB: This function is not synthesisable

simulateB_lazy Source #

Arguments

:: (Bundle a, Bundle b) 
=> (Unbundled domain1 a -> Unbundled domain2 b)

The function we want to simulate

-> [a]

Input samples

-> [b] 

Lazily simulate a (Unbundled a -> Unbundled b) function given a list of samples of type a

>>> simulateB (unbundle . register systemClockGen systemResetGen (8,8) . bundle) [(1,1), (2,2), (3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)...
...

NB: This function is not synthesisable

List <-> Signal conversion (not synthesisable)

sample :: (Foldable f, NFData a) => f a -> [a] Source #

The above type is a generalisation for:

sample :: Signal a -> [a]

Get an infinite list of samples from a Signal

The elements in the list correspond to the values of the Signal at consecutive clock cycles

sample s == [s0, s1, s2, s3, ...

NB: This function is not synthesisable

sampleN :: (Foldable f, NFData a) => Int -> f a -> [a] Source #

The above type is a generalisation for:

sampleN :: Int -> Signal a -> [a]

Get a list of n samples from a Signal

The elements in the list correspond to the values of the Signal at consecutive clock cycles

sampleN 3 s == [s0, s1, s2]

NB: This function is not synthesisable

fromList :: NFData a => [a] -> Signal domain 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 synthesisable

lazy versions

sample_lazy :: Foldable f => f a -> [a] Source #

The above type is a generalisation for:

sample :: Signal a -> [a]

Get an infinite list of samples from a Signal

The elements in the list correspond to the values of the Signal at consecutive clock cycles

sample s == [s0, s1, s2, s3, ...

NB: This function is not synthesisable

sampleN_lazy :: Foldable f => Int -> f a -> [a] Source #

The above type is a generalisation for:

sampleN :: Int -> Signal a -> [a]

Get a list of n samples from a Signal

The elements in the list correspond to the values of the Signal at consecutive clock cycles

sampleN 3 s == [s0, s1, s2]

NB: This function is not synthesisable

fromList_lazy :: [a] -> Signal domain 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 synthesisable

QuickCheck combinators

testFor :: Foldable f => Int -> f Bool -> Property Source #

The above type is a generalisation for:

testFor :: Int -> Signal Bool -> Property

testFor n s tests the signal s for n cycles.

Type classes

Eq-like

(.==.) :: (Eq a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.==.) :: Eq a => Signal a -> Signal a -> Signal Bool

It is a version of (==) that returns a Signal of Bool

(./=.) :: (Eq a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(./=.) :: Eq a => Signal a -> Signal a -> Signal Bool

It is a version of (/=) that returns a Signal of Bool

Ord-like

(.<.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.<.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (<) that returns a Signal of Bool

(.<=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.<=.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (<=) that returns a Signal of Bool

(.>=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.>=.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (>=) that returns a Signal of Bool

(.>.) :: (Ord a, Applicative f) => f a -> f a -> f Bool infix 4 Source #

The above type is a generalisation for:

(.>.) :: Ord a => Signal a -> Signal a -> Signal Bool

It is a version of (>) that returns a Signal of Bool