clash-prelude-0.10.14: 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 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

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))
```

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 `Bundle`ing

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)
```

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`

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))
```

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 `Bundle`ing

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

Arguments

 :: (KnownNat n, Enum addr) => Vec n a ROM contentNB: 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

Arguments

 :: (KnownNat (2 ^ n), KnownNat n) => Vec (2 ^ n) a ROM contentNB: 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

Arguments

 :: (KnownNat n, KnownNat m) => Vec n a ROM contentNB: 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`

Arguments

 :: (KnownNat (2 ^ n), KnownNat n) => Vec (2 ^ n) a ROM contentNB: 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`

## ROMs initialised with a data file

Arguments

 :: (KnownNat m, Enum addr) => SNat n Size of the ROM -> FilePath File describing the content of the ROM -> addr Read address `rd` -> BitVector m The value of the ROM at address `rd`

An asynchronous/combinational ROM with space for `n` elements

• NB: This function might not work for specific combinations of code-generation backends and hardware targets. Please check the support table below:

```               | VHDL     | Verilog  | SystemVerilog |
===============+==========+==========+===============+
Altera/Quartus | Broken   | Works    | Works         |
Xilinx/ISE     | Works    | Works    | Works         |
ASIC           | Untested | Untested | Untested      |
===============+==========+==========+===============+
```

• See CLaSH.Prelude.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
• See CLaSH.Sized.Fixed for ideas on how to create your own data files.
• When you notice that `asyncRomFile` is significantly slowing down your simulation, give it a monomorphic type signature. So instead of leaving the type to be inferred:

```myRomData = asyncRomFile d512 "memory.bin"
```

or giving it a polymorphic type signature:

```myRomData :: Enum addr => addr -> BitVector 16
myRomData = asyncRomFile d512 "memory.bin"
```

you should give it a monomorphic type signature:

```myRomData :: Unsigned 9 -> BitVector 16
myRomData = asyncRomFile d512 "memory.bin"
```

Arguments

 :: (KnownNat m, KnownNat n, KnownNat (2 ^ n)) => FilePath File describing the content of the ROM -> Unsigned n Read address `rd` -> BitVector m The value of the ROM at address `rd`

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

• NB: This function might not work for specific combinations of code-generation backends and hardware targets. Please check the support table below:

```               | VHDL     | Verilog  | SystemVerilog |
===============+==========+==========+===============+
Altera/Quartus | Broken   | Works    | Works         |
Xilinx/ISE     | Works    | Works    | Works         |
ASIC           | Untested | Untested | Untested      |
===============+==========+==========+===============+
```

• See CLaSH.Prelude.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
• See CLaSH.Sized.Fixed for ideas on how to create your own data files.
• When you notice that `asyncRomFilePow2` is significantly slowing down your simulation, give it a monomorphic type signature. So instead of leaving the type to be inferred:

```myRomData = asyncRomFilePow2 "memory.bin"
```

you should give it a monomorphic type signature:

```myRomData :: Unsigned 9 -> BitVector 16
myRomData = asyncRomFilePow2 "memory.bin"
```

Arguments

 :: (KnownNat m, KnownNat k) => SNat n Size of the ROM -> FilePath File describing the content of the ROM -> Signal (Unsigned k) Read address `rd` -> Signal (BitVector m) The value of the ROM at address `rd` from the previous clock cycle

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`
• NB: This function might not work for specific combinations of code-generation backends and hardware targets. Please check the support table below:

```               | VHDL     | Verilog  | SystemVerilog |
===============+==========+==========+===============+
Altera/Quartus | Broken   | Works    | Works         |
Xilinx/ISE     | Works    | Works    | Works         |
ASIC           | Untested | Untested | Untested      |
===============+==========+==========+===============+
```

Arguments

 :: (KnownNat m, KnownNat n, KnownNat (2 ^ n)) => FilePath File describing the content of the ROM -> Signal (Unsigned n) Read address `rd` -> Signal (BitVector m) The value of the ROM at address `rd` from the previous clock cycle

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`
• NB: This function might not work for specific combinations of code-generation backends and hardware targets. Please check the support table below:

```               | VHDL     | Verilog  | SystemVerilog |
===============+==========+==========+===============+
Altera/Quartus | Broken   | Works    | Works         |
Xilinx/ISE     | Works    | Works    | Works         |
ASIC           | Untested | Untested | Untested      |
===============+==========+==========+===============+
```

# RAM primitives with a combinational read port

Arguments

 :: Enum addr => SNat n Size `n` of the RAM -> Signal addr Write address `w` -> Signal addr Read address `r` -> Signal Bool Write enable -> Signal a Value to write (at address `w`) -> Signal a Value of the `RAM` at address `r`

Create a RAM with space for `n` elements.

• NB: Initial content of the RAM is `undefined`

Arguments

 :: (KnownNat (2 ^ n), KnownNat n) => 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 `RAM` at address `r`

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

• NB: Initial content of the RAM is `undefined`

# BlockRAM primitives

Arguments

 :: (KnownNat n, 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 Write address `w` -> Signal addr 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
• NB: Initial output value is `undefined`
```bram40 :: `Signal` (`Unsigned` 6) -> Signal (`Unsigned` 6) -> `Signal` Bool
-> `Signal` `Bit` -> Signal `Bit`
bram40 = `blockRam` (`replicate` d40 1)
```

• 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) wr rd en dt`.

Arguments

 :: (KnownNat (2 ^ n), 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) 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
• NB: Initial output value is `undefined`
```bram32 :: `Signal` (`Unsigned` 5) -> Signal (`Unsigned` 5) -> `Signal` Bool
-> `Signal` `Bit` -> `Signal` `Bit`
bram32 = `blockRamPow2` (`replicate` d32 1)
```

• 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) wr rd en dt`.

## BlockRAM primitives initialised with a data file

Arguments

 :: (KnownNat m, Enum addr) => SNat n Size of the blockRAM -> FilePath File describing the initial content of the blockRAM -> Signal addr Write address `w` -> Signal addr Read address `r` -> Signal Bool Write enable -> Signal (BitVector m) Value to write (at address `w`) -> Signal (BitVector m) 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`
• NB: This function might not work for specific combinations of code-generation backends and hardware targets. Please check the support table below:

```               | VHDL     | Verilog  | SystemVerilog |
===============+==========+==========+===============+
Altera/Quartus | Broken   | Works    | Works         |
Xilinx/ISE     | Works    | Works    | Works         |
ASIC           | Untested | Untested | Untested      |
===============+==========+==========+===============+
```

• 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 (blockRamFile size file) wr rd en dt`.
• See CLaSH.Prelude.BlockRam.File for more information on how to instantiate a Block RAM with the contents of a data file.
• See CLaSH.Sized.Fixed for ideas on how to create your own data files.

Arguments

 :: (KnownNat m, KnownNat n, KnownNat (2 ^ n)) => FilePath File describing the initial content of the blockRAM -> Signal (Unsigned n) Write address `w` -> Signal (Unsigned n) Read address `r` -> Signal Bool Write enable -> Signal (BitVector m) Value to write (at address `w`) -> Signal (BitVector m) 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`
• NB: This function might not work for specific combinations of code-generation backends and hardware targets. Please check the support table below:

```               | VHDL     | Verilog  | SystemVerilog |
===============+==========+==========+===============+
Altera/Quartus | Broken   | Works    | Works         |
Xilinx/ISE     | Works    | Works    | Works         |
ASIC           | Untested | Untested | Untested      |
===============+==========+==========+===============+
```

• 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 (blockRamFilePow2 file) wr rd en dt`.
• See CLaSH.Prelude.BlockRam.File for more information on how to instantiate a Block RAM with the contents of a data file.
• See CLaSH.Sized.Fixed for ideas on how to create your own data files.

readNew :: Eq addr => (Signal addr -> Signal addr -> Signal Bool -> Signal a -> Signal a) -> Signal addr -> Signal addr -> Signal Bool -> Signal a -> Signal a Source

````>>> ````import CLaSH.Prelude
````>>> ````:t readNew (blockRam (0 :> 1 :> Nil))
```readNew (blockRam (0 :> 1 :> Nil))
Signal addr -> Signal addr -> Signal Bool -> Signal a -> Signal a
```

readNew' :: Eq addr => SClock clk -> (Signal' clk addr -> Signal' clk addr -> Signal' clk Bool -> Signal' clk a -> Signal' clk a) -> Signal' clk addr -> Signal' clk addr -> Signal' clk Bool -> Signal' clk a -> Signal' clk a Source

# Utility functions

Arguments

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

Give a window over a `Signal`

```window4 :: Signal Int -> Vec 4 (Signal Int)
window4 = window```
````>>> ````simulateB window4 [1::Int,2,3,4,5] :: [Vec 4 Int]
```[<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```
````>>> ````simulateB windowD3 [1::Int,2,3,4] :: [Vec 3 Int]
```[<0,0,0>,<1,0,0>,<2,1,0>,<3,2,1>,<4,3,2>...
```

Arguments

 :: (Bounded a, Eq a) => a Starting value -> Signal a -> Signal Bool

Give a pulse when the `Signal` goes from `minBound` to `maxBound`

Arguments

 :: (Bounded a, Eq a) => a Starting value -> Signal a -> Signal Bool

Give a pulse when the `Signal` goes from `maxBound` to `minBound`

# Testbench functions

Arguments

 :: (Eq a, Show a) => String Additional message -> Signal a Checked value -> Signal a Expected value -> Signal b Return value -> Signal b

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

NB: This function can be used in synthesizable designs.

Arguments

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

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

Example:

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

Arguments

 :: (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 one of the functions to generate the "magical" `expectedOutput` function, which the CλaSH compiler 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]))
```
````>>> ````import qualified Data.List as List
````>>> ````sampleN 12 (expectedOutput (fromList ([0..10] List.++ [10,10,10])))
```[
cycle(system1000): 0, outputVerifier
expected value: 70, not equal to actual value: 0
False,
cycle(system1000): 1, outputVerifier
expected value: 99, not equal to actual value: 1
False,False,False,False,False,
cycle(system1000): 6, outputVerifier
expected value: 7, not equal to actual value: 6
False,
cycle(system1000): 7, outputVerifier
expected value: 8, not equal to actual value: 7
False,
cycle(system1000): 8, outputVerifier
expected value: 9, not equal to actual value: 8
False,
cycle(system1000): 9, outputVerifier
expected value: 10, not equal to actual value: 9
False,True,True]
```

# Exported modules

## Type-level functions

class Lift t where

Methods

lift :: t -> Q Exp

Instances

 Lift () Lift a => Lift [a] Integral a => Lift (Ratio a) Lift a => Lift (Maybe a) KnownNat n => Lift (Index n) KnownNat n => Lift (BitVector n) 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 (Signal' clk a) Lift a => Lift (Vec n a) (Lift a, Lift b, Lift c) => Lift (a, b, c) (Lift (rep ((+) int frac)), KnownNat frac, KnownNat int, Typeable (Nat -> *) rep) => Lift (Fixed rep int frac) Lift a => Lift (DSignal' clk delay a) (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.

## Type classes

### Other

module Data.Bits

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