topEntity
Domain
: synthesis domain
System
: Useful for simulationclash --vhdl MAC.hs
Signal
values represent synchronous values. ie, values that change with respect to a clock.
HiddenClockResetEnable
.
exposeClockResetEnable
.NFDataX
To be synthesizable, data type needs to be an instance of NFDataX
, a typeclass defined in clash-prelude.
It's like NFData
. NFData
says that the type has a normal form (ie, is fully evaluatable and doesn't diverge). (I guess NF stands for 'normal form').
This makes the evaluation eager?
NFDataX
is like NFData
from deepseq package, but with support for undefined values.
(cf: from here)
+---------------+
Input --->-| |------> Output
| Combinational |
| logic |
+---| |---+
| +---------------+ |
Current ^ V Next
state | +---------------+ | state
| | | |
+-<-| Memory |-<-+
| elements |
+---------------+
–
-- | Function to run a mealy machine
= [] -- no input means no output
run _ _ [] :inputs) = output: outputs
run func state (inputwhere
= func input state
(output, state′) = run func state′ inputs
outputs
-- | Transition function for a mealy machine
func :: InputSignals → State a → (OutputSignals, State a)
= (output, state′)
func input state where
...
...
–
Type:
mealy
:: (KnownDomain dom,
GHC.Classes.IP (Clash.Signal.HiddenClockName dom) (Clock dom),
GHC.Classes.IP (Clash.Signal.HiddenEnableName dom) (Enable dom),
GHC.Classes.IP (Clash.Signal.HiddenResetName dom) (Reset dom),
NFDataX s) =>
(s -> i -> (s, o)) -> s -> Signal dom i -> Signal dom o
Transition function of the mealy machine:
(s -- ^ current state
-> i -- ^ next input
-> (s, o)) -- ^ next state, next output (produced /during/ the transition)
s -- ^ initial state of mealy machine
-> Signal dom i -- ^ input signal
-> Signal dom o -- ^ output signal
From base
itself:
From clash-prelude
:
à la ports in VHDL, I guess.
Use :::
. An example: https://github.com/clash-lang/clash-compiler/pull/2584/files
Example:
{-# ANN topEntity
(Synthesize
{ t_name = "topEntity"
, t_inputs = [ PortName "clk"
, PortName "rst"
, PortName "en"
, PortName "inp" ]
, t_output = PortName "res"
}) #-}
Becomes:
testBench
testBench
has to be in root modulehttps://hackage.haskell.org/package/clash-prelude-1.8.1/docs/Clash-Tutorial.html
outputVerifier
True
when all test cases have been testedFalse
simulate
: give a Signal a -> Signal b
and get a [a] -> [b]
simulate_lazy
: lazy version of simulate
sample
: Convert a Signal
into an infinite list
L.take 5 $ sample 10 top
sampleN
: get n samples of a Signal
as a list
sampleN @System 5 $ register 8 $ fromList [1,2,3,4]
fromList
: convert a list to a Signal
https://hackage.haskell.org/package/clash-prelude-1.6.3/docs/Clash-Signal-Bundle.html
bundle
takes a tuple of signals and makes a signal of tuples. Something like: (Signal dom a, Signal dom b)
becoming Signal dom (a, b)
.
Similarly unbundle
does it in the other direction. Signal of tuples becomes tuple of signals. Something like: Signal dom (a, b)
becoming (Signal dom a, Signal dom b)
.
bundle :: Unbundled dom a -> Signal dom a
-- Example:
bundle :: (Signal dom a, Signal dom b) -> Signal dom (a,b)
unbundle :: Signal dom a -> Unbundled dom a
-- Example:
unbundle :: Signal dom (a,b) -> (Signal dom a, Signal dom b)
BitVector
!
bar :: BitVector 8 -> (BitVector 2, BitVector 3, BitVector 3)
bar bv = let (zyx, cba, qp) = unpack bv in (qp, cba, zyx)
-- Another option: Using `slice`
koo :: BitVector 8 -> (BitVector 2, BitVector 3, BitVector 3)
koo bv = (slice d1 d0 bv, slice d4 d2 bv, slice d7 d5 bv)
-- Convoluted
foo :: BitVector 8 -> (BitVector 2, BitVector 3, BitVector 3)
foo bv = case bv of
$(bitPattern "zyxc_baqp") -> (pack (q ++# p), pack (c ++# b ++# a), pack (z ++# y ++# x))
Packing/unpacking:
λ> pack (Left () :: Either () Bool)
0b0.
λ> pack (Right False :: Either () Bool)
0b10
λ> pack (Right True :: Either () Bool)
0b11
-- The . is a don't care
λ> pack (((), True) :: ((), Bool))
0b1
λ> pack (((), False) :: ((), Bool))
0b0
Signal
type.register
register
:: (HiddenClockResetEnable dom, NFDataX a)
=> a -> Signal dom a -> Signal dom a
Clash.Prelude> sampleN @System 5 $ register 8 $ fromList [1,2,3,4]
[8,8,2,3,4]
Conversion between Bitvector and Int:
Clash.Prelude> pack (59 :: Unsigned 8)
0b0011_1011
Clash.Prelude> :t pack (59 :: Unsigned 8)
pack (59 :: Unsigned 8) :: BitVector 8
Clash.Prelude> :t pack (59 :: Unsigned 9)
pack (59 :: Unsigned 9) :: BitVector 9
Clash.Prelude> unpack 0b101 ::Signed 3
-3
Clash.Prelude> unpack 0b101 ::Unsigned 3
5
—
Some operations:
-- Bitwise OR
Clash.Prelude Prelude> (Clash.Prelude..|.) 0b1001 0b1010
11
—
bLit:
Clash.Prelude> import qualified Data.List as List
Clash.Prelude List> $(bLit (List.replicate 4 '0'))
0b1111
a | b | c | d | g | e | f | g | |
---|---|---|---|---|---|---|---|---|
0 | T | T | T | T | T | T | T | |
1 | T | T | ||||||
2 | T | T | T | T | T | |||
3 | T | T | T | T |
import Data.Char
import qualified Data.Map
a :: [(Char, Vec 7 Bool)]
-- a b c d e f g
= [('0', True :> True :> True :> True :> True :> True :> True :> Nil),
a '1', False :> True :> True :> False :> False :> False :> False :> Nil),
('?', True :> True :> False :> False :> True :> False :> True :> Nil)]
(= Data.Map.fromList a b
Signal
manuallyNot synthesizable. Shouldn't be used in production code!!
> import Clash.Signal.Internal
λ> :t (1 :- 2)
λ1 :- 2) :: Num a => Signal dom a
(
> 1 :: Signal System Int
λ1 1 1 1 1 ...............