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

CLaSH.Prelude

Description

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 tutorial module will be added within due time.

Synopsis

# Creating synchronous sequential circuits

Arguments

 :: (Pack i, Pack o) => (s -> i -> (s, o)) Transfer function in mealy machine form: `state -> input -> (newstate,output)` -> s Initial state -> SignalP i -> SignalP 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, Signal Int) -> Signal Int
topEntity = mac <^> 0```
````>>> ````simulateP topEntity [(1,1),(2,2),(3,3),(4,4),...
```[0,1,5,14,30,...
```

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 = (mac <^> 0) (a,b)
s2 = (mac <^> 0) (x,y)```

registerP :: Pack a => a -> SignalP a -> SignalP a 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 = registerP (8,8)```
````>>> ````simulateP rP [(1,1),(2,2),(3,3),...
```[(8,8),(1,1),(2,2),(3,3),...
```

# `Arrow` interface for synchronous sequential circuits

newtype Comp a b Source

Deprecated: Will be removed in version 0.6. Use `Applicative` interface and (`<^>`) instead

`Comp`onent: an `Arrow` interface to synchronous sequential functions

Constructors

 C FieldsasFunction :: Signal a -> Signal b

Instances

 Arrow Comp ArrowLoop Comp Category * Comp

Arguments

 :: (s -> i -> (s, o)) Transfer function in mealy machine form: `state -> input -> (newstate,output)` -> s Initial state -> Comp i o Synchronous sequential `Comp`onent with input and output matching that of the mealy machine

Deprecated: Will be removed in version 0.6. Use `Applicative` interface and (`<^>`) instead

Create a synchronous `Comp`onent 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 :: Comp (Int,Int) Int
topEntity = mac ^^^ 0```
````>>> ````simulateC topEntity [(1,1),(2,2),(3,3),(4,4),...
```[0,1,5,14,30,...
```

Synchronous sequential must be composed using the `Arrow` syntax

```dualMac :: Comp (Int,Int,Int,Int) Int
dualMac = proc (a,b,x,y) -> do
rec s1 <- mac ^^^ 0 -< (a,b)
s2 <- mac ^^^ 0 -< (x,y)
returnA -< (s1 + s2)```

registerC :: a -> Comp a a Source

Deprecated: `Comp` is deprecated and will be removed in version 0.6, use `register` instead

Create a `register` `Comp`onent

```rC :: Comp (Int,Int) (Int,Int)
rC = registerC (8,8)```
````>>> ````simulateC rP [(1,1),(2,2),(3,3),...
```[(8,8),(1,1),(2,2),(3,3),...
```

simulateC :: Comp a b -> [a] -> [b] Source

Deprecated: `Comp` is deprecated and will be removed in version 0.6, use `simulate` instead

Simulate a `Comp`onent given a list of samples

````>>> ````simulateC (registerC 8) [1, 2, 3, ...
```[8, 1, 2, 3, ...
```

# BlockRAM primitives

Arguments

 :: forall n m a . (KnownNat n, KnownNat m, Pack a, Default a) => SNat n Size `n` of the blockram -> Signal (Unsigned m) Write address `w` -> Signal (Unsigned m) Read address `r` -> Signal Bool Write enable -> Signal a Value to write (at address `w`) -> 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

```bram40 :: Signal (Unsigned 6) -> Signal (Unsigned 6) -> Signal Bool -> Signal a -> Signal a
bram40 = blockRam d40```

Arguments

 :: (KnownNat n, KnownNat (2 ^ n), Pack a, Default a) => SNat (2 ^ n) Size `2^n` of the blockram -> Signal (Unsigned n) Write address `w` -> Signal (Unsigned n) Read address `r` -> Signal Bool Write enable -> Signal a Value to write (at address `w`) -> 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

```bram32 :: Signal (Unsigned 5) -> Signal (Unsigned 5) -> Signal Bool -> Signal a -> Signal a
bram32 = blockRamPow2 d32```

Arguments

 :: (KnownNat n, KnownNat m, Pack a, Default a) => SNat n Size `n` of the blockram -> Comp (Unsigned m, Unsigned m, Bool, a) a

Deprecated: `Comp` is deprecated and will be removed in version 0.6, use `blockRam` instead

Create a blockRAM with space for `n` elements

NB: Read value is delayed by 1 cycle

```bramC40 :: Comp (Unsigned 6, Unsigned 6, Bool, a) a
bramC40 = blockRamC d40```

Arguments

 :: (KnownNat n, KnownNat (2 ^ n), Pack a, Default a) => SNat (2 ^ n) Size `2^n` of the blockram -> Comp (Unsigned n, Unsigned n, Bool, a) a

Deprecated: `Comp` is deprecated and will be removed in version 0.6, use `blockRamPow2` instead

Create a blockRAM with space for 2^`n` elements

NB: Read value is delayed by 1 cycle

```bramC32 :: Comp (Unsigned 5, Unsigned 5, Bool, a) a
bramC32 = blockRamPow2C d32```

# Utility functions

Arguments

 :: (KnownNat (n + 1), Default a) => Signal a Signal to create a window over -> Vec ((n + 1) + 1) (Signal a) Window of at least size 2

Give a window over a `Signal`

```window4 :: Signal Int -> Vec 4 (Signal Int)
window4 = window```
````>>> ````simulateP window4 [1,2,3,4,5,...
```[<1,0,0,0>, <2,1,0,0>, <3,2,1,0>, <4,3,2,1>, <5,4,3,2>,...
```

Arguments

 :: (KnownNat (n + 1), Default a) => Signal a Signal to create a window over -> Vec (n + 1) (Signal a) Window of at least size 1

Give a delayed window over a `Signal`

```windowD3 :: Signal Int -> Vec 3 (Signal Int)
windowD3 = windowD```
````>>> ````simulateP windowD3 [1,2,3,4,...
```[<0,0,0>, <1,0,0>, <2,1,0>, <3,2,1>, <4,3,2>,...
```

# Testbench functions

Arguments

 :: (Eq a, Show a) => Signal a Checked value -> Signal a Expected value -> Signal b Returned value -> Signal b

Compares the first two arguments for equality and logs a warning when they are not equal. The second argument is considered the expected value. This function simply returns the third argument unaltered as its result. This function is used by `outputVerifier`.

This function is translated to the following VHDL:

```sassert_block : block
begin
-- pragma translate_off
process(clk_1000,reset_1000,arg0,arg1) is
begin
if (rising_edge(clk_1000) or rising_edge(reset_1000)) then
assert (arg0 = arg1) report ("expected: " & to_string (arg1) & \", actual: \" & to_string (arg0)) severity error;
end if;
end process;
-- pragma translate_on
result <= arg2;
end block;```

And can, due to the pragmas, be used in synthesizable designs

Arguments

 :: forall l a . KnownNat l => Vec l a Samples to generate -> Signal a Signal of given samples

To be used as a one of the functions to create the "magical" `testInput` value, which the CλaSH compilers looks for to create the stimulus generator for the generated VHDL testbench.

Example:

```testInput :: Signal Int
testInput = stimuliGenerator \$(v [(1::Int),3..21])```
````>>> ````sample testInput
```[1,3,5,7,9,11,13,15,17,19,21,21,21,...
```

Arguments

 :: forall l a . (KnownNat l, Eq a, Show a) => Vec l a Samples to compare with -> Signal a Signal to verify -> Signal Bool Indicator that all samples are verified

To be used as a functions to generate the "magical" `expectedOutput` function, which the CλaSH compilers looks for to create the signal verifier for the generated VHDL testbench.

Example:

```expectedOutput :: Signal Int -> Signal Bool
expectedOutput = outputVerifier \$(v ([70,99,2,3,4,5,7,8,9,10]::[Int]))```
````>>> ````sample (expectedOutput (fromList ([0..10] ++ [10,10,10])))
```[
expected value: 70, not equal to actual value: 0
False,
expected value: 99, not equal to actual value: 1
False,False,False,False,False,
expected value: 7, not equal to actual value: 6
False,
expected value: 8, not equal to actual value: 7
False,
expected value: 9, not equal to actual value: 8
False,
expected value: 10, not equal to actual value: 9
False,True,True,...
```

# Exported modules

module CLaSH.Bit

## Type-level functions

class Lift t where

Methods

lift :: t -> Q Exp

Instances

 Lift Bool Lift Char Lift Int Lift Integer Lift Rational Lift Name Lift () Lift ModName Lift PkgName Lift OccName Lift NameFlavour Lift NameSpace Lift Bit Lift a => Lift [a] Lift a => Lift (Maybe a) Lift a => Lift (Signal a) KnownNat n => Lift (Signed n) KnownNat n => Lift (Unsigned n) (Lift a, Lift b) => Lift (Either a b) (Lift a, Lift b) => Lift (a, b) Lift a => Lift (CSignal clk a) (Lift a, Lift b, Lift c) => Lift (a, b, c) (Lift (rep size), KnownNat frac, KnownNat size, Typeable (Nat -> *) rep) => Lift (Fixed frac rep size) (Lift a, Lift b, Lift c, Lift d) => Lift (a, b, c, d) (Lift a, Lift b, Lift c, Lift d, Lift e) => Lift (a, b, c, d, e) (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift (a, b, c, d, e, f) (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift (a, b, c, d, e, f, g)

deriveLift :: Name -> Q [Dec]

Derive Lift instances for the given datatype.

module Data.Bits