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

Copyright(C) 2013-2016 University of Twente
LicenseBSD2 (see the file LICENSE)
MaintainerChristiaan Baaij <christiaan.baaij@gmail.com>
Safe HaskellSafe
LanguageHaskell2010
Extensions
  • DataKinds
  • FlexibleContexts
  • TypeOperators
  • ExplicitNamespaces

CLaSH.Prelude.Safe

Contents

Description

This is the Safe API only of CLaSH.Prelude

CλaSH (pronounced ‘clash’) is a functional hardware description language that borrows both its syntax and semantics from the functional programming language Haskell. The merits of using a functional language to describe hardware comes from the fact that combinational circuits can be directly modeled as mathematical functions and that functional languages lend themselves very well at describing and (de-)composing mathematical functions.

This package provides:

  • Prelude library containing datatypes and functions for circuit design

To use the library:

For now, CLaSH.Prelude is also the best starting point for exploring the library. A preliminary version of a tutorial can be found in CLaSH.Tutorial. Some circuit examples can be found in CLaSH.Examples.

Synopsis

Creating synchronous sequential circuits

mealy Source #

Arguments

:: (s -> i -> (s, o))

Transfer function in mealy machine form: state -> input -> (newstate,output)

-> s

Initial state

-> Signal i -> Signal o

Synchronous sequential function with input and output matching that of the mealy machine

Create a synchronous function from a combinational function describing a mealy machine

mac :: Int        -- Current state
    -> (Int,Int)  -- Input
    -> (Int,Int)  -- (Updated state, output)
mac s (x,y) = (s',s)
  where
    s' = x * y + s

topEntity :: Signal (Int, Int) -> Signal Int
topEntity = mealy mac 0
>>> simulate topEntity [(1,1),(2,2),(3,3),(4,4)]
[0,1,5,14...
...

Synchronous sequential functions can be composed just like their combinational counterpart:

dualMac :: (Signal Int, Signal Int)
        -> (Signal Int, Signal Int)
        -> Signal Int
dualMac (a,b) (x,y) = s1 + s2
  where
    s1 = mealy mac 0 (bundle (a,x))
    s2 = mealy mac 0 (bundle (b,y))

mealyB Source #

Arguments

:: (Bundle i, Bundle o) 
=> (s -> i -> (s, o))

Transfer function in mealy machine form: state -> input -> (newstate,output)

-> s

Initial state

-> Unbundled i -> Unbundled o

Synchronous sequential function with input and output matching that of the mealy machine

A version of mealy that does automatic Bundleing

Given a function f of type:

f :: Int -> (Bool, Int) -> (Int, (Int, Bool))

When we want to make compositions of f in g using mealy, we have to write:

g a b c = (b1,b2,i2)
  where
    (i1,b1) = unbundle (mealy f 0 (bundle (a,b)))
    (i2,b2) = unbundle (mealy f 3 (bundle (i1,c)))

Using mealyB however we can write:

g a b c = (b1,b2,i2)
  where
    (i1,b1) = mealyB f 0 (a,b)
    (i2,b2) = mealyB f 3 (i1,c)

(<^>) Source #

Arguments

:: (Bundle i, Bundle o) 
=> (s -> i -> (s, o))

Transfer function in mealy machine form: state -> input -> (newstate,output)

-> s

Initial state

-> Unbundled i -> Unbundled o

Synchronous sequential function with input and output matching that of the mealy machine

Infix version of mealyB

moore Source #

Arguments

:: (s -> i -> s)

Transfer function in moore machine form: state -> input -> newstate

-> (s -> o)

Output function in moore machine form: state -> output

-> s

Initial state

-> Signal i -> Signal o

Synchronous sequential function with input and output matching that of the moore machine

Create a synchronous function from a combinational function describing a moore machine

mac :: Int        -- Current state
    -> (Int,Int)  -- Input
    -> Int        -- Updated state
mac s (x,y) = x * y + s

topEntity :: Signal (Int, Int) -> Signal Int
topEntity = moore mac id 0
>>> simulate topEntity [(1,1),(2,2),(3,3),(4,4)]
[0,1,5,14...
...

Synchronous sequential functions can be composed just like their combinational counterpart:

dualMac :: (Signal Int, Signal Int)
        -> (Signal Int, Signal Int)
        -> Signal Int
dualMac (a,b) (x,y) = s1 + s2
  where
    s1 = moore mac id 0 (bundle (a,x))
    s2 = moore mac id 0 (bundle (b,y))

mooreB Source #

Arguments

:: (Bundle i, Bundle o) 
=> (s -> i -> s)

Transfer function in moore machine form: state -> input -> newstate

-> (s -> o)

Output function in moore machine form: state -> output

-> s

Initial state

-> Unbundled i -> Unbundled o

Synchronous sequential function with input and output matching that of the moore machine

A version of moore that does automatic Bundleing

Given a functions t and o of types:

t :: Int -> (Bool, Int) -> Int
o :: Int -> (Int, Bool)

When we want to make compositions of t and o in g using moore, we have to write:

g a b c = (b1,b2,i2)
  where
    (i1,b1) = unbundle (moore t o 0 (bundle (a,b)))
    (i2,b2) = unbundle (moore t o 3 (bundle (i1,c)))

Using mooreB however we can write:

g a b c = (b1,b2,i2)
  where
    (i1,b1) = mooreB t o 0 (a,b)
    (i2,b2) = mooreB t o 3 (i1,c)

registerB :: Bundle a => a -> Unbundled a -> Unbundled a infixr 3 Source #

Create a register function for product-type like signals (e.g. '(Signal a, Signal b)')

rP :: (Signal Int,Signal Int) -> (Signal Int, Signal Int)
rP = registerB (8,8)
>>> simulateB rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)...
...

ROMs

asyncRom Source #

Arguments

:: (KnownNat n, Enum addr) 
=> Vec n a

ROM content

NB: must be a constant

-> addr

Read address rd

-> a

The value of the ROM at address rd

An asynchronous/combinational ROM with space for n elements

Additional helpful information:

asyncRomPow2 Source #

Arguments

:: KnownNat n 
=> Vec (2 ^ n) a

ROM content

NB: must be a constant

-> Unsigned n

Read address rd

-> a

The value of the ROM at address rd

An asynchronous/combinational ROM with space for 2^n elements

Additional helpful information:

rom Source #

Arguments

:: (KnownNat n, KnownNat m) 
=> Vec n a

ROM content

NB: must be a constant

-> Signal (Unsigned m)

Read address rd

-> Signal a

The value of the ROM at address rd

A ROM with a synchronous read port, with space for n elements

  • NB: Read value is delayed by 1 cycle
  • NB: Initial output value is undefined

Additional helpful information:

romPow2 Source #

Arguments

:: KnownNat n 
=> Vec (2 ^ n) a

ROM content

NB: must be a constant

-> Signal (Unsigned n)

Read address rd

-> Signal a

The value of the ROM at address rd

A ROM with a synchronous read port, with space for 2^n elements

  • NB: Read value is delayed by 1 cycle
  • NB: Initial output value is undefined

Additional helpful information:

RAM primitives with a combinational read port

asyncRam Source #

Arguments

:: Enum addr 
=> SNat n

Size n of the RAM

-> Signal addr

Read address r

-> Signal (Maybe (addr, a))

(write address w, value to write)

-> Signal a

Value of the RAM at address r

Create a RAM with space for n elements.

Additional helpful information:

asyncRamPow2 Source #

Arguments

:: KnownNat n 
=> Signal (Unsigned n)

Read address r

-> Signal (Maybe (Unsigned n, a))

(write address w, value to write)

-> Signal a

Value of the RAM at address r

Create a RAM with space for 2^n elements

Additional helpful information:

BlockRAM primitives

blockRam Source #

Arguments

:: Enum addr 
=> Vec n a

Initial content of the BRAM, also determines the size, n, of the BRAM.

NB: MUST be a constant.

-> Signal addr

Read address r

-> Signal (Maybe (addr, a))

(write address w, value to write)

-> Signal a

Value of the blockRAM at address r from the previous clock cycle

Create a blockRAM with space for n elements.

  • NB: Read value is delayed by 1 cycle
  • NB: Initial output value is undefined
bram40 :: Signal (Unsigned 6)
       -> Signal (Maybe (Unsigned 6, Bit))
       -> Signal Bit
bram40 = blockRam (replicate d40 1)

Additional helpful information:

  • See CLaSH.Prelude.BlockRam for more information on how to use a Block RAM.
  • Use the adapter readNew for obtaining write-before-read semantics like this: readNew (blockRam inits) rd wrM.

blockRamPow2 Source #

Arguments

:: KnownNat n 
=> Vec (2 ^ n) a

Initial content of the BRAM, also determines the size, 2^n, of the BRAM.

NB: MUST be a constant.

-> Signal (Unsigned n)

Read address r

-> Signal (Maybe (Unsigned n, a))

(write address w, value to write)

-> Signal a

Value of the blockRAM at address r from the previous clock cycle

Create a blockRAM with space for 2^n elements

  • NB: Read value is delayed by 1 cycle
  • NB: Initial output value is undefined
bram32 :: Signal (Unsigned 5)
       -> Signal (Maybe (Unsigned 5, Bit))
       -> Signal Bit
bram32 = blockRamPow2 (replicate d32 1)

Additional helpful information:

  • See CLaSH.Prelude.BlockRam for more information on how to use a Block RAM.
  • Use the adapter readNew for obtaining write-before-read semantics like this: readNew (blockRamPow2 inits) rd wrM.

BlockRAM read/write conflict resolution

readNew Source #

Arguments

:: Eq addr 
=> (Signal addr -> Signal (Maybe (addr, a)) -> Signal a)

The ram component

-> Signal addr

Read address r

-> Signal (Maybe (addr, a))

(Write address w, value to write)

-> Signal a

Value of the ram at address r from the previous clock cycle

Create read-after-write blockRAM from a read-before-write one (synchronised to system clock)

>>> import CLaSH.Prelude
>>> :t readNew (blockRam (0 :> 1 :> Nil))
readNew (blockRam (0 :> 1 :> Nil))
  :: ... =>
     Signal addr -> Signal (Maybe (addr, a)) -> Signal a

readNew' Source #

Arguments

:: Eq addr 
=> SClock clk 
-> (Signal' clk addr -> Signal' clk (Maybe (addr, a)) -> Signal' clk a)

The ram component

-> Signal' clk addr

Read address r

-> Signal' clk (Maybe (addr, a))

(Write address w, value to write)

-> Signal' clk a

Value of the ram at address r from the previous clock cycle

Create read-after-write blockRAM from a read-before-write one (synchronised to specified clock)

Utility functions

isRising Source #

Arguments

:: (Bounded a, Eq a) 
=> a

Starting value

-> Signal a 
-> Signal Bool 

Give a pulse when the Signal goes from minBound to maxBound

isFalling Source #

Arguments

:: (Bounded a, Eq a) 
=> a

Starting value

-> Signal a 
-> Signal Bool 

Give a pulse when the Signal goes from maxBound to minBound

riseEvery :: KnownNat n => SNat n -> Signal Bool Source #

Give a pulse every n clock cycles. This is a useful helper function when combined with functions like regEn or mux, in order to delay a register by a known amount.

To be precise: the given signal will be False for the next n-1 cycles, followed by a single True value:

>>> Prelude.last (sampleN 1024 (riseEvery d1024)) == True
True
>>> Prelude.or (sampleN 1023 (riseEvery d1024)) == False
True

For example, to update a counter once every 10 million cycles:

counter = regEn 0 (riseEvery (SNat :: SNat 10000000)) (counter + 1)

oscillate :: KnownNat n => Bool -> SNat n -> Signal Bool Source #

Oscillate a Bool for a given number of cycles. This is a convenient function when combined with something like regEn, as it allows you to easily hold a register value for a given number of cycles. The input Bool determines what the initial value is.

To oscillate on an interval of 5 cycles:

>>> sampleN 10 (oscillate False d5)
[False,False,False,False,False,True,True,True,True,True]

To oscillate between True and False:

>>> sampleN 10 (oscillate False d1)
[False,True,False,True,False,True,False,True,False,True]

An alternative definition for the above could be:

>>> let osc' = register False (not <$> osc')
>>> let sample' = sampleN 200
>>> sample' (oscillate False d1) == sample' osc'
True

Exported modules

Synchronous signals

DataFlow interface

Datatypes

Bit vectors

Arbitrary-width numbers

Fixed point numbers

Fixed size vectors

Perfect depth trees

Annotations

Type-level natural numbers

Type classes

CLaSH

Other

module Data.Bits

Exceptions

Named types

Haskell Prelude

CLaSH.Prelude re-exports most of the Haskell Prelude with the exception of the following: (++), (!!), concat, drop, foldl, foldl1, foldr, foldr1, head, init, iterate, last, length, map, repeat, replicate, reverse, scanl, scanr, splitAt, tail, take, unzip, unzip3, zip, zip3, zipWith, zipWith3.

It instead exports the identically named functions defined in terms of Vec at CLaSH.Sized.Vector.

module Prelude