clash-prelude-1.8.4: Clash: a functional hardware description language - Prelude library

Copyright | (C) 2017 Google Inc. 2019 Myrtle Software Ltd 2022-2024 QBayLogic B.V.
License | BSD2 (see the file LICENSE)
Maintainer | QBayLogic B.V. <devops@qbaylogic.com>
Safe Haskell | None
Language | Haskell2010

Clash.Signal.BiSignal

Description

Wires are fundamentally bidirectional, and in traditional HDLs we can exploit this aspect by explicitly marking the endpoint, or port, of such a wire as inout, thereby making this port function as both a source and a drain for the signals flowing over the wire.

Clash has support for `inout` ports through the implementation of BiSignals. To cleanly map to functions (and thus support software simulation using Haskell), a BiSignal comes in two parts; the in part:

    BiSignalIn (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)

and the out part:

    BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)

Where:

- The internal representation is a `BitVector`
- n indicates the number of bits in the `BitVector`
- dom is the clock- (and reset-) domain to which the memory elements manipulating these BiSignals belong.
- Lastly, ds indicates the default behavior for the BiSignal if nothing is being written (pull-down, pull-up, or undefined).

`BiSignalIn` is used by Clash to generate the `inout` ports on a HDL level, while `BiSignalOut` is only used for simulation purposes and generally discarded by the compiler.

# Example

The following describes a system where two circuits, in alternating fashion, read the current value from the bus, increment it, and write it on the next cycle.

    import Clash.Explicit.Prelude
    import Clash.Signal.BiSignal

    -- | Alternatingly read / increment+write
    counter
      :: (Bool, Int)
      -- ^ Internal flip + previous read
      -> Int
      -- ^ Int from inout
      -> ((Bool, Int), Maybe Int)
    counter (write, prevread) i = ((write', prevread'), output)
      where
        output    = if write then Just (succ prevread) else Nothing
        prevread' = if write then prevread else i
        write' = not write

    -- | Write on odd cyles
    f :: Clock System
      -> Reset System
      -> Enable System
      -> BiSignalIn  'Floating System (BitSize Int)
      -> BiSignalOut 'Floating System (BitSize Int)
    f clk rst en s = writeToBiSignal s (mealy clk rst en counter (False, 0) (readFromBiSignal s))

    -- | Write on even cyles
    g :: Clock System
      -> Reset System
      -> Enable System
      -> BiSignalIn  'Floating System (BitSize Int)
      -> BiSignalOut 'Floating System (BitSize Int)
    g clk rst en s = writeToBiSignal s (mealy clk rst en counter (True, 0) (readFromBiSignal s))

    -- | Connect the /f/ and /g/ circuits to the same bus
    topEntity
      :: Clock System
      -> Reset System
      -> Enable System
      -> Signal System Int
    topEntity clk rst en = readFromBiSignal bus'
      where
        bus  = mergeBiSignalOuts $ f clk rst en bus' :> g clk rst en bus' :> Nil
        bus' = veryUnsafeToBiSignalIn bus

Synopsis

- data BiSignalIn (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
- data BiSignalOut (ds :: BiSignalDefault) (dom :: Domain) (n :: Nat)
- data BiSignalDefault
  - = PullUp
  - | PullDown
  - | Floating
- data SBiSignalDefault (a :: BiSignalDefault) where
  - SPullUp :: SBiSignalDefault 'PullUp
  - SPullDown :: SBiSignalDefault 'PullDown
  - SFloating :: SBiSignalDefault 'Floating
- class HasBiSignalDefault (ds :: BiSignalDefault) where
  - pullUpMode :: forall (dom :: Domain) (n :: Nat). BiSignalIn ds dom n -> SBiSignalDefault ds
- mergeBiSignalOuts :: forall (n :: Nat) (defaultState :: BiSignalDefault) (dom :: Domain) (m :: Nat). (HasCallStack, KnownNat n) => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m
- readFromBiSignal :: forall a (ds :: BiSignalDefault) (d :: Domain). (HasCallStack, BitPack a) => BiSignalIn ds d (BitSize a) -> Signal d a
- writeToBiSignal :: forall a (ds :: BiSignalDefault) (d :: Domain). (HasCallStack, BitPack a, NFDataX a) => BiSignalIn ds d (BitSize a) -> Signal d (Maybe a) -> BiSignalOut ds d (BitSize a)
- veryUnsafeToBiSignalIn :: forall (n :: Nat) (ds :: BiSignalDefault) (d :: Domain). (HasCallStack, KnownNat n, Given (SBiSignalDefault ds)) => BiSignalOut ds d n -> BiSignalIn ds d n

# Documentation

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

Instances details

Monoid (BiSignalOut defaultState dom n) Source # | Monoid instance to support concatenating NB: Not synthesizable
Instance details Defined in Clash.Signal.BiSignal Methods 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 #
Semigroup (BiSignalOut defaultState dom n) Source # | NB: Not synthesizable
Instance details Defined in Clash.Signal.BiSignal Methods (<>) :: 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 #
type TryDomain t (BiSignalOut ds dom n) Source # |
Instance details Defined in Clash.Signal.BiSignal type TryDomain t (BiSignalOut ds dom n) = 'Found dom
type HasDomain dom1 (BiSignalOut ds dom2 n) Source # |
Instance details Defined in Clash.Signal.BiSignal type HasDomain dom1 (BiSignalOut ds dom2 n) = DomEq dom1 dom2

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.

Constructors

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

Instances details

Show BiSignalDefault Source # |
Instance details Defined in Clash.Signal.BiSignal Methods showsPrec :: Int -> BiSignalDefault -> ShowS Source # show :: BiSignalDefault -> String Source # showList :: [BiSignalDefault] -> ShowS Source #

data SBiSignalDefault (a :: BiSignalDefault) where Source #

Singleton versions of `BiSignalDefault`

Constructors

SPullUp :: SBiSignalDefault 'PullUp |
SPullDown :: SBiSignalDefault 'PullDown |
SFloating :: SBiSignalDefault 'Floating |

#### Instances

Instances details

Given (SBiSignalDefault 'Floating) Source # |
Instance details Defined in Clash.Signal.BiSignal Methods given :: SBiSignalDefault 'Floating Source #
Given (SBiSignalDefault 'PullDown) Source # |
Instance details Defined in Clash.Signal.BiSignal Methods given :: SBiSignalDefault 'PullDown Source #
Given (SBiSignalDefault 'PullUp) Source # |
Instance details Defined in Clash.Signal.BiSignal Methods given :: SBiSignalDefault 'PullUp Source #

class HasBiSignalDefault (ds :: BiSignalDefault) where Source #

Type class for `BiSignalDefault`: can be used as a constraint and for obtaining the pull-up mode

Methods

pullUpMode :: forall (dom :: Domain) (n :: Nat). BiSignalIn ds dom n -> SBiSignalDefault ds Source #

#### Instances

Instances details

HasBiSignalDefault 'Floating Source # |
Instance details Defined in Clash.Signal.BiSignal Methods pullUpMode :: forall (dom :: Domain) (n :: Nat). BiSignalIn 'Floating dom n -> SBiSignalDefault 'Floating Source #
HasBiSignalDefault 'PullDown Source # |
Instance details Defined in Clash.Signal.BiSignal Methods pullUpMode :: forall (dom :: Domain) (n :: Nat). BiSignalIn 'PullDown dom n -> SBiSignalDefault 'PullDown Source #
HasBiSignalDefault 'PullUp Source # |
Instance details Defined in Clash.Signal.BiSignal Methods pullUpMode :: forall (dom :: Domain) (n :: Nat). BiSignalIn 'PullUp dom n -> SBiSignalDefault 'PullUp Source #

mergeBiSignalOuts :: forall (n :: Nat) (defaultState :: BiSignalDefault) (dom :: Domain) (m :: Nat). (HasCallStack, KnownNat n) => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m Source #

Combine several inout signals into one.

readFromBiSignal Source #

Arguments

:: forall a (ds :: BiSignalDefault) (d :: Domain). (HasCallStack, BitPack a) |
=> BiSignalIn ds d (BitSize a) | A `BiSignalIn` with a number of bits needed to represent a
-> Signal d a |

Read the value from an inout port

writeToBiSignal Source #

Arguments

:: forall a (ds :: BiSignalDefault) (d :: Domain). (HasCallStack, BitPack a, NFDataX a) |
=> BiSignalIn ds d (BitSize a) |

-> Signal d (Maybe a)

Value to write

- Just a writes an a value
- Nothing puts the port in a high-impedance state

-> BiSignalOut ds d (BitSize a) |

Write to an inout port

veryUnsafeToBiSignalIn :: forall (n :: Nat) (ds :: BiSignalDefault) (d :: Domain). (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.