Safe Haskell | None |
---|---|
Language | Haskell2010 |
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:
- Import CLaSH.Prelude
- Additionally import CLaSH.Prelude.Explicit if you want to design explicitly clocked circuits in a multi-clock setting
For now, CLaSH.Prelude is also the best starting point for exploring the library. A tutorial module will be added within due time.
- (<^>) :: (Pack i, Pack o) => (s -> i -> (s, o)) -> s -> SignalP i -> SignalP o
- registerP :: Pack a => a -> SignalP a -> SignalP a
- newtype Comp a b = C {
- asFunction :: Signal a -> Signal b
- (^^^) :: (s -> i -> (s, o)) -> s -> Comp i o
- registerC :: a -> Comp a a
- simulateC :: Comp a b -> [a] -> [b]
- blockRam :: forall n m a. (KnownNat n, KnownNat m, Pack a, Default a) => SNat n -> Signal (Unsigned m) -> Signal (Unsigned m) -> Signal Bool -> Signal a -> Signal a
- blockRamPow2 :: (KnownNat n, KnownNat (2 ^ n), Pack a, Default a) => SNat (2 ^ n) -> Signal (Unsigned n) -> Signal (Unsigned n) -> Signal Bool -> Signal a -> Signal a
- blockRamC :: (KnownNat n, KnownNat m, Pack a, Default a) => SNat n -> Comp (Unsigned m, Unsigned m, Bool, a) a
- blockRamPow2C :: (KnownNat n, KnownNat (2 ^ n), Pack a, Default a) => SNat (2 ^ n) -> Comp (Unsigned n, Unsigned n, Bool, a) a
- window :: (KnownNat (n + 1), Default a) => Signal a -> Vec ((n + 1) + 1) (Signal a)
- windowD :: (KnownNat (n + 1), Default a) => Signal a -> Vec (n + 1) (Signal a)
- sassert :: (Eq a, Show a) => Signal a -> Signal a -> Signal b -> Signal b
- stimuliGenerator :: forall l a. KnownNat l => Vec l a -> Signal a
- outputVerifier :: forall l a. (KnownNat l, Eq a, Show a) => Vec l a -> Signal a -> Signal Bool
- module CLaSH.Signal.Implicit
- module CLaSH.Bit
- module CLaSH.Sized.Signed
- module CLaSH.Sized.Unsigned
- module CLaSH.Sized.Fixed
- module CLaSH.Sized.Vector
- module GHC.TypeLits
- module CLaSH.Promoted.Nat
- module CLaSH.Promoted.Nat.Literals
- module CLaSH.Promoted.Nat.TH
- module CLaSH.Promoted.Ord
- class Lift t where
- deriveLift :: Name -> Q [Dec]
- module CLaSH.Class.BitVector
- module CLaSH.Class.Num
- module Control.Arrow
- module Control.Applicative
- module Data.Bits
- module Data.Default
Creating synchronous sequential circuits
:: (Pack i, Pack o) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> 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
Deprecated: Will be removed in version 0.6. Use Applicative
interface and (<^>
) instead
Comp
onent: an Arrow
interface to synchronous sequential functions
C | |
|
:: (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Comp i o | Synchronous sequential |
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)
BlockRAM primitives
:: forall n m a . (KnownNat n, KnownNat m, Pack a, Default a) | |
=> SNat n | Size |
-> Signal (Unsigned m) | Write address |
-> Signal (Unsigned m) | Read address |
-> Signal Bool | Write enable |
-> Signal a | Value to write (at address |
-> Signal a | Value of the |
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
:: (KnownNat n, KnownNat (2 ^ n), Pack a, Default a) | |
=> SNat (2 ^ n) | Size |
-> Signal (Unsigned n) | Write address |
-> Signal (Unsigned n) | Read address |
-> Signal Bool | Write enable |
-> Signal a | Value to write (at address |
-> Signal a | Value of the |
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
:: (KnownNat n, KnownNat (2 ^ n), Pack a, Default a) | |
=> SNat (2 ^ n) | Size |
-> 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
:: (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>,...
:: (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
:: (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
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,...
:: 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
Implicitly clocked synchronous signals
module CLaSH.Signal.Implicit
Datatypes
module CLaSH.Bit
Arbitrary-width numbers
module CLaSH.Sized.Signed
module CLaSH.Sized.Unsigned
Fixed point numbers
module CLaSH.Sized.Fixed
Fixed size vectors
module CLaSH.Sized.Vector
Type-level natural numbers
module GHC.TypeLits
module CLaSH.Promoted.Nat
module CLaSH.Promoted.Nat.Literals
module CLaSH.Promoted.Nat.TH
Type-level functions
module CLaSH.Promoted.Ord
Template Haskell
class Lift t where
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.
Type classes
CLaSH
module CLaSH.Class.BitVector
module CLaSH.Class.Num
Other
module Control.Arrow
module Control.Applicative
module Data.Bits
module Data.Default