Clash


General

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 NFData with support for undefined values.

Simulating a Mealy machine

(cf: from here)

            +---------------+
Input  --->-|               |------> Output
            | Combinational |
            |    logic      |
        +---|               |---+
        |   +---------------+   |
Current ^                       V   Next
 state  |   +---------------+   |  state
        |   |               |   |
        +-<-|     Memory    |-<-+
            |    elements   |
            +---------------+

-- | Function to run a mealy machine
run _ _ []                    = []   -- no input means no output
run func state (input:inputs) = output: outputs
 where
  (output, state′) = func input state
  outputs = run func state′ inputs

-- | Transition function for a mealy machine
func :: InputSignals  State a  (OutputSignals, State a)
func input state = (output, 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

Types

From base itself:

From clash-prelude:

Assign names to signals

à la ports in VHDL, I guess.

Use :::. An example: https://github.com/clash-lang/clash-compiler/pull/2584/files

Control name of ports in generated HDL

Using an annotation

Example:

{-# ANN topEntity
  (Synthesize
    { t_name   = "topEntity"
    , t_inputs = [ PortName "clk"
                 , PortName "rst"
                 , PortName "en"
                 , PortName "inp" ]
    , t_output = PortName "res"
    }) #-}

Testbenches

https://hackage.haskell.org/package/clash-prelude-1.8.1/docs/Clash-Tutorial.html

Misc

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]

Bitvectors

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

7 segment with clash

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
a = [('0', True  :> True :> True  :> True  :> True  :> True  :> True  :> Nil),
     ('1', False :> True :> True  :> False :> False :> False :> False :> Nil),
     ('?', True  :> True :> False :> False :> True  :> False :> True  :> Nil)]
b = Data.Map.fromList a

Constructing Signal manually

Not 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 ...............

Unknown