Copyright | (C) 2013-2016 University of Twente 2017-2019 Myrtle Software Ltd 2017 Google Inc. |
---|---|
License | BSD2 (see the file LICENSE) |
Maintainer | Christiaan Baaij <christiaan.baaij@gmail.com> |
Safe Haskell | Unsafe |
Language | Haskell2010 |
Extensions |
|
- Creating synchronous sequential circuits
- ROMs
- RAM primitives with a combinational read port
- BlockRAM primitives
- Utility functions
- Tracing
- Exported modules
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; by default clock and reset lines are implicitly routed for all the components found in Clash.Prelude. You can read more about implicit clock and reset lines in Clash.Signal
- Alternatively, if you want to explicitly route clock and reset ports, for more straightforward multi-clock designs, you can import the Clash.Explicit.Prelude module. Note that you should not import Clash.Prelude and Clash.Explicit.Prelude at the same time as they have overlapping definitions.
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
- mealy :: (HiddenClockResetEnable dom, NFDataX s) => (s -> i -> (s, o)) -> s -> Signal dom i -> Signal dom o
- mealyB :: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) => (s -> i -> (s, o)) -> s -> Unbundled dom i -> Unbundled dom o
- (<^>) :: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) => (s -> i -> (s, o)) -> s -> Unbundled dom i -> Unbundled dom o
- moore :: (HiddenClockResetEnable dom, NFDataX s) => (s -> i -> s) -> (s -> o) -> s -> Signal dom i -> Signal dom o
- mooreB :: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) => (s -> i -> s) -> (s -> o) -> s -> Unbundled dom i -> Unbundled dom o
- registerB :: (HiddenClockResetEnable dom, NFDataX a, Bundle a) => a -> Unbundled dom a -> Unbundled dom a
- asyncRom :: (KnownNat n, Enum addr) => Vec n a -> addr -> a
- asyncRomPow2 :: KnownNat n => Vec (2 ^ n) a -> Unsigned n -> a
- rom :: forall dom n m a. (NFDataX a, KnownNat n, KnownNat m, HiddenClock dom, HiddenEnable dom) => Vec n a -> Signal dom (Unsigned m) -> Signal dom a
- romPow2 :: forall dom n a. (KnownNat n, NFDataX a, HiddenClock dom, HiddenEnable dom) => Vec (2 ^ n) a -> Signal dom (Unsigned n) -> Signal dom a
- asyncRomFile :: (KnownNat m, Enum addr) => SNat n -> FilePath -> addr -> BitVector m
- asyncRomFilePow2 :: forall n m. (KnownNat m, KnownNat n) => FilePath -> Unsigned n -> BitVector m
- romFile :: (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom) => SNat n -> FilePath -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
- romFilePow2 :: forall n m dom. (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom) => FilePath -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
- asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- blockRam :: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, Enum addr) => Vec n a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- blockRamPow2 :: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, KnownNat n) => Vec (2 ^ n) a -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- blockRamU :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) => ResetStrategy r -> SNat n -> (Index n -> a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- blockRam1 :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) => ResetStrategy r -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- data ResetStrategy (r :: Bool) where
- blockRamFile :: (KnownNat m, Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) => SNat n -> FilePath -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
- blockRamFilePow2 :: forall dom n m. (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) => FilePath -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
- readNew :: (HiddenClockResetEnable dom, NFDataX a, Eq addr) => (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- window :: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) => Signal dom a -> Vec (n + 1) (Signal dom a)
- windowD :: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) => Signal dom a -> Vec (n + 1) (Signal dom a)
- isRising :: (HiddenClockResetEnable dom, NFDataX a, Bounded a, Eq a) => a -> Signal dom a -> Signal dom Bool
- isFalling :: (HiddenClockResetEnable dom, NFDataX a, Bounded a, Eq a) => a -> Signal dom a -> Signal dom Bool
- riseEvery :: HiddenClockResetEnable dom => SNat n -> Signal dom Bool
- oscillate :: HiddenClockResetEnable dom => Bool -> SNat n -> Signal dom Bool
- traceSignal1 :: (BitPack a, NFDataX a, Typeable a) => String -> Signal dom a -> Signal dom a
- traceVecSignal1 :: (KnownNat n, BitPack a, NFDataX a, Typeable a) => String -> Signal dom (Vec (n + 1) a) -> Signal dom (Vec (n + 1) a)
- traceSignal :: forall dom a. (KnownDomain dom, BitPack a, NFDataX a, Typeable a) => String -> Signal dom a -> Signal dom a
- traceVecSignal :: forall dom a n. (KnownDomain dom, KnownNat n, BitPack a, NFDataX a, Typeable a) => String -> Signal dom (Vec (n + 1) a) -> Signal dom (Vec (n + 1) a)
- dumpVCD :: NFDataX a => (Int, Int) -> Signal dom a -> [String] -> IO (Either String Text)
- module Clash.Signal
- module Clash.Signal.Delayed
- module Clash.Prelude.DataFlow
- module Clash.Sized.BitVector
- module Clash.Prelude.BitIndex
- module Clash.Prelude.BitReduction
- module Clash.Sized.Signed
- module Clash.Sized.Unsigned
- module Clash.Sized.Index
- module Clash.Sized.Fixed
- module Clash.Sized.Vector
- module Clash.Sized.RTree
- module Clash.Annotations.TopEntity
- class Generic a
- class Generic1 (f :: k -> Type)
- module GHC.TypeLits
- module GHC.TypeLits.Extra
- module Clash.Promoted.Nat
- module Clash.Promoted.Nat.Literals
- module Clash.Promoted.Nat.TH
- module Clash.Promoted.Symbol
- class Lift t where
- autoReg :: (HasCallStack, HiddenClockResetEnable dom, AutoReg a) => a -> Signal dom a -> Signal dom a
- deriveAutoReg :: Name -> DecsQ
- module Clash.Class.BitPack
- module Clash.Class.Exp
- module Clash.Class.Num
- module Clash.Class.Parity
- module Clash.Class.Resize
- module Control.Applicative
- module Data.Bits
- module Data.Default.Class
- module Clash.XException
- module Clash.NamedTypes
- module Clash.Hidden
- module Clash.Magic
- module Clash.HaskellPrelude
Creating synchronous sequential circuits
:: (HiddenClockResetEnable dom, NFDataX s) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Signal dom i -> Signal dom 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
macT :: Int -- Current state -> (Int,Int) -- Input -> (Int,Int) -- (Updated state, output) macT s (x,y) = (s',s) where s' = x * y + s mac :: HiddenClockResetEnable dom =>Signal
dom (Int, Int) ->Signal
dom Int mac =mealy
macT 0
>>>
simulate @System mac [(0,0),(1,1),(2,2),(3,3),(4,4)]
[0,0,1,5,14... ...
Synchronous sequential functions can be composed just like their combinational counterpart:
dualMac :: HiddenClockResetEnable dom => (Signal
dom Int,Signal
dom Int) -> (Signal
dom Int,Signal
dom Int) ->Signal
dom Int dualMac (a,b) (x,y) = s1 + s2 where s1 =mealy
mac 0 (bundle
(a,x)) s2 =mealy
mac 0 (bundle
(b,y))
:: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Unbundled dom i -> Unbundled dom 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
(c,i1)))
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 (c,i1)
:: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) | |
=> (s -> i -> (s, o)) | Transfer function in mealy machine form: |
-> s | Initial state |
-> Unbundled dom i -> Unbundled dom o | Synchronous sequential function with input and output matching that of the mealy machine |
Infix version of mealyB
:: (HiddenClockResetEnable dom, NFDataX s) | |
=> (s -> i -> s) | Transfer function in moore machine form: |
-> (s -> o) | Output function in moore machine form: |
-> s | Initial state |
-> Signal dom i -> Signal dom 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
macT :: Int -- Current state -> (Int,Int) -- Input -> Int -- Updated state macT s (x,y) = x * y + s mac :: HiddenClockResetEnable dom =>Signal
dom (Int, Int) ->Signal
dom Int mac =moore
mac id 0
>>>
simulate @System mac [(0,0),(1,1),(2,2),(3,3),(4,4)]
[0,0,1,5,14,30,... ...
Synchronous sequential functions can be composed just like their combinational counterpart:
dualMac :: HiddenClockResetEnable dom => (Signal
dom Int,Signal
dom Int) -> (Signal
dom Int,Signal
dom Int) ->Signal
dom 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))
:: (HiddenClockResetEnable dom, NFDataX s, Bundle i, Bundle o) | |
=> (s -> i -> s) | Transfer function in moore machine form: |
-> (s -> o) | Output function in moore machine form: |
-> s | Initial state |
-> Unbundled dom i -> Unbundled dom 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
(c,i1)))
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 (c,i1)
registerB :: (HiddenClockResetEnable dom, NFDataX a, Bundle a) => a -> Unbundled dom a -> Unbundled dom a infixr 3 Source #
Create a register
function for product-type like signals (e.g. '(Signal a, Signal b)')
rP :: HiddenClockResetEnable dom => (Signal dom Int, Signal dom Int) -> (Signal dom Int, Signal dom Int) rP = registerB (8,8)
>>>
simulateB @System rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)... ...
ROMs
:: (KnownNat n, Enum addr) | |
=> Vec n a | ROM content NB: must be a constant |
-> addr | Read address |
-> a | The value of the ROM at address |
An asynchronous/combinational ROM with space for n
elements
Additional helpful information:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam for ideas on how to use ROMs and RAMs
:: KnownNat n | |
=> Vec (2 ^ n) a | ROM content NB: must be a constant |
-> Unsigned n | Read address |
-> a | The value of the ROM at address |
An asynchronous/combinational ROM with space for 2^n
elements
Additional helpful information:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam for ideas on how to use ROMs and RAMs
:: (NFDataX a, KnownNat n, KnownNat m, HiddenClock dom, HiddenEnable dom) | |
=> Vec n a | ROM content NB: must be a constant |
-> Signal dom (Unsigned m) | Read address |
-> Signal dom a | The value of the ROM at address |
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:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam for ideas on how to use ROMs and RAMs
:: (KnownNat n, NFDataX a, HiddenClock dom, HiddenEnable dom) | |
=> Vec (2 ^ n) a | ROM content NB: must be a constant |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom a | The value of the ROM at address |
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:
- See Clash.Sized.Fixed and Clash.Prelude.BlockRam for ideas on how to use ROMs and RAMs
ROMs initialized with a data file
:: (KnownNat m, Enum addr) | |
=> SNat n | Size of the ROM |
-> FilePath | File describing the content of the ROM |
-> addr | Read address |
-> BitVector m | The value of the ROM at address |
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 | ===============+==========+==========+===============+
Additional helpful information:
- 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"
:: (KnownNat m, KnownNat n) | |
=> FilePath | File describing the content of the ROM |
-> Unsigned n | Read address |
-> BitVector m | The value of the ROM at address |
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 | ===============+==========+==========+===============+
Additional helpful information:
- 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"
:: (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom) | |
=> SNat n | Size of the ROM |
-> FilePath | File describing the content of the ROM |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (BitVector m) | The value of the ROM at address |
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 | ===============+==========+==========+===============+
Additional helpful information:
- 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.
:: (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom) | |
=> FilePath | File describing the content of the ROM |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (BitVector m) | The value of the ROM at address |
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 | ===============+==========+==========+===============+
Additional helpful information:
- 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.
RAM primitives with a combinational read port
:: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) | |
=> SNat n | Size |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the |
Create a RAM with space for n
elements.
- NB: Initial content of the RAM is
undefined
Additional helpful information:
- See Clash.Prelude.BlockRam for more information on how to use a RAM.
:: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) | |
=> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, a)) | (write address |
-> Signal dom a | Value of the |
Create a RAM with space for 2^n
elements
- NB: Initial content of the RAM is
undefined
Additional helpful information:
- See Clash.Prelude.BlockRam for more information on how to use a RAM.
BlockRAM primitives
:: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, Enum addr) | |
=> Vec n a | Initial content of the BRAM, also determines the size, NB: MUST be a constant. |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the |
Create a blockRAM with space for n
elements.
- NB: Read value is delayed by 1 cycle
- NB: Initial output value is
undefined
bram40 ::HiddenClock
dom =>Signal
dom (Unsigned
6) ->Signal
dom (Maybe (Unsigned
6,Bit
)) ->Signal
domBit
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
.
:: (HasCallStack, HiddenClock dom, HiddenEnable dom, NFDataX a, KnownNat n) | |
=> Vec (2 ^ n) a | Initial content of the BRAM, also determines the size, NB: MUST be a constant. |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, a)) | (write address |
-> Signal dom a | Value of the |
Create a blockRAM with space for 2^n
elements
- NB: Read value is delayed by 1 cycle
- NB: Initial output value is
undefined
bram32 ::HiddenClock
dom =>Signal
dom (Unsigned
5) ->Signal
dom (Maybe (Unsigned
5,Bit
)) ->Signal
domBit
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
.
:: (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) | |
=> ResetStrategy r | Whether to clear BRAM on asserted reset ( |
-> SNat n | Number of elements in BRAM |
-> (Index n -> a) | If applicable (see first argument), reset BRAM using this function. |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the |
Version of blockram that has no default values set. May be cleared to a arbitrary state using a reset function.
:: (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, 1 <= n) | |
=> ResetStrategy r | Whether to clear BRAM on asserted reset ( |
-> SNat n | Number of elements in BRAM |
-> a | Initial content of the BRAM (replicated n times) |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (write address |
-> Signal dom a | Value of the |
Version of blockram that is initialized with the same value on all memory positions.
data ResetStrategy (r :: Bool) where Source #
BlockRAM primitives initialized with a data file
:: (KnownNat m, Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) | |
=> SNat n | Size of the blockRAM |
-> FilePath | File describing the initial content of the blockRAM |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, BitVector m)) | (write address |
-> Signal dom (BitVector m) | Value of the |
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 | ===============+==========+==========+===============+
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
clk (blockRamFile
clk size file) rd wrM - 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.
:: (KnownNat m, KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) | |
=> FilePath | File describing the initial content of the blockRAM |
-> Signal dom (Unsigned n) | Read address |
-> Signal dom (Maybe (Unsigned n, BitVector m)) | (write address |
-> Signal dom (BitVector m) | Value of the |
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 | ===============+==========+==========+===============+
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
clk (blockRamFilePow2
clk file) rd wrM - 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.
BlockRAM read/write conflict resolution
:: (HiddenClockResetEnable dom, NFDataX a, Eq addr) | |
=> (Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a) | The |
-> Signal dom addr | Read address |
-> Signal dom (Maybe (addr, a)) | (Write address |
-> Signal dom a | Value of the |
Create read-after-write blockRAM from a read-before-write one (synchronized to system clock)
>>>
import Clash.Prelude
>>>
:t readNew (blockRam (0 :> 1 :> Nil))
readNew (blockRam (0 :> 1 :> Nil)) :: ... ... ... ... ... => Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
Utility functions
:: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) | |
=> Signal dom a | Signal to create a window over |
-> Vec (n + 1) (Signal dom a) | Window of at least size 1 |
Give a window over a Signal
window4 :: HiddenClockResetEnable dom => Signal dom Int -> Vec 4 (Signal dom Int) window4 = window
>>>
simulateB @System 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>... ...
:: (HiddenClockResetEnable dom, KnownNat n, Default a, NFDataX a) | |
=> Signal dom a | Signal to create a window over |
-> Vec (n + 1) (Signal dom a) | Window of at least size 1 |
Give a delayed window over a Signal
windowD3 :: HiddenClockResetEnable dom => Signal dom Int -> Vec 3 (Signal dom Int) windowD3 = windowD
>>>
simulateB @System windowD3 [1::Int,2,3,4] :: [Vec 3 Int]
[<0,0,0>,<1,0,0>,<2,1,0>,<3,2,1>,<4,3,2>... ...
riseEvery :: HiddenClockResetEnable dom => SNat n -> Signal dom Bool Source #
Give a pulse every n
clock cycles. This is a useful helper function when
combined with functions like
or regEn
,
in order to delay a register by a known amount.mux
To be precise: the given signal will be
for the next False
n-1
cycles,
followed by a single
value:True
>>>
Prelude.last (sampleN @System 1025 (riseEvery d1024)) == True
True>>>
Prelude.or (sampleN @System 1024 (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 :: HiddenClockResetEnable dom => Bool -> SNat n -> Signal dom Bool Source #
Oscillate a
for a given number of cycles. This is a convenient
function when combined with something like Bool
, as it allows you to
easily hold a register value for a given number of cycles. The input regEn
determines what the initial value is.Bool
To oscillate on an interval of 5 cycles:
>>>
sampleN @System 11 (oscillate False d5)
[False,False,False,False,False,False,True,True,True,True,True]
To oscillate between
and True
:False
>>>
sampleN @System 11 (oscillate False d1)
[False,False,True,False,True,False,True,False,True,False,True]
An alternative definition for the above could be:
>>>
let osc' = register False (not <$> osc')
>>>
sampleN @System 200 (oscillate False d1) == sampleN @System 200 osc'
True
Tracing
Simple
:: (BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in the VCD output |
-> Signal dom a | Signal to trace |
-> Signal dom a |
Trace a single signal. Will emit an error if a signal with the same name was previously registered.
NB associates the traced signal with a clock period of 1, which
results in incorrect VCD files when working with circuits that have
multiple clocks. Use traceSignal
when working with circuits that have
multiple clocks.
:: (KnownNat n, BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in debugging output. Will be appended by _0, _1, ..., _n. |
-> Signal dom (Vec (n + 1) a) | Signal to trace |
-> Signal dom (Vec (n + 1) a) |
Trace a single vector signal: each element in the vector will show up as a different trace. If the trace name already exists, this function will emit an error.
NB associates the traced signal with a clock period of 1, which
results in incorrect VCD files when working with circuits that have
multiple clocks. Use traceSignal
when working with circuits that have
multiple clocks.
Tracing in a multi-clock environment
:: (KnownDomain dom, BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in the VCD output |
-> Signal dom a | Signal to trace |
-> Signal dom a |
Trace a single signal. Will emit an error if a signal with the same name was previously registered.
NB Works correctly when creating VCD files from traced signal in
multi-clock circuits. However traceSignal1
might be more convenient to
use when the domain of your circuit is polymorphic.
:: (KnownDomain dom, KnownNat n, BitPack a, NFDataX a, Typeable a) | |
=> String | Name of signal in debugging output. Will be appended by _0, _1, ..., _n. |
-> Signal dom (Vec (n + 1) a) | Signal to trace |
-> Signal dom (Vec (n + 1) a) |
Trace a single vector signal: each element in the vector will show up as a different trace. If the trace name already exists, this function will emit an error.
NB Works correctly when creating VCD files from traced signal in
multi-clock circuits. However traceSignal1
might be more convinient to
use when the domain of your circuit is polymorphic.
VCD dump functions
:: NFDataX a | |
=> (Int, Int) | (offset, number of samples) |
-> Signal dom a | (One of) the outputs of the circuit containing the traces |
-> [String] | The names of the traces you definitely want to be dumped in the VCD file |
-> IO (Either String Text) |
Produce a four-state VCD (Value Change Dump) according to IEEE 1364-{1995,2001}. This function fails if a trace name contains either non-printable or non-VCD characters.
Due to lazy evaluation, the created VCD files might not contain all the traces you were expecting. You therefore have to provide a list of names you definately want to be dumped in the VCD file.
For example:
vcd <- dumpVCD (0, 100) cntrOut ["main", "sub"]
Evaluates cntrOut long enough in order for to guarantee that the main
,
and sub
traces end up in the generated VCD file.
Exported modules
Synchronous signals
module Clash.Signal
module Clash.Signal.Delayed
DataFlow interface
module Clash.Prelude.DataFlow
Datatypes
Bit vectors
module Clash.Sized.BitVector
module Clash.Prelude.BitIndex
module Clash.Prelude.BitReduction
Arbitrary-width numbers
module Clash.Sized.Signed
module Clash.Sized.Unsigned
module Clash.Sized.Index
Fixed point numbers
module Clash.Sized.Fixed
Fixed size vectors
module Clash.Sized.Vector
Perfect depth trees
module Clash.Sized.RTree
Annotations
module Clash.Annotations.TopEntity
Generics type-classes
Representable types of kind *
.
This class is derivable in GHC with the DeriveGeneric
flag on.
A Generic
instance must satisfy the following laws:
from
.to
≡id
to
.from
≡id
Instances
class Generic1 (f :: k -> Type) #
Representable types of kind * -> *
(or kind k -> *
, when PolyKinds
is enabled).
This class is derivable in GHC with the DeriveGeneric
flag on.
A Generic1
instance must satisfy the following laws:
from1
.to1
≡id
to1
.from1
≡id
Instances
Type-level natural numbers
module GHC.TypeLits
module GHC.TypeLits.Extra
module Clash.Promoted.Nat
module Clash.Promoted.Nat.Literals
module Clash.Promoted.Nat.TH
Type-level strings
module Clash.Promoted.Symbol
Template Haskell
A Lift
instance can have any of its values turned into a Template
Haskell expression. This is needed when a value used within a Template
Haskell quotation is bound outside the Oxford brackets ([| ... |]
) but not
at the top level. As an example:
add1 :: Int -> Q Exp add1 x = [| x + 1 |]
Template Haskell has no way of knowing what value x
will take on at
splice-time, so it requires the type of x
to be an instance of Lift
.
A Lift
instance must satisfy $(lift x) ≡ x
for all x
, where $(...)
is a Template Haskell splice.
Lift
instances can be derived automatically by use of the -XDeriveLift
GHC language extension:
{-# LANGUAGE DeriveLift #-} module Foo where import Language.Haskell.TH.Syntax data Bar a = Bar1 a (Bar a) | Bar2 String deriving Lift
Nothing
Instances
Type classes
Clash
autoReg :: (HasCallStack, HiddenClockResetEnable dom, AutoReg a) => a -> Signal dom a -> Signal dom a Source #
Implicit version of autoReg
deriveAutoReg :: Name -> DecsQ Source #
Automatically derives an AutoReg
instance for a product type
Usage:
data Pair a b = MkPair { getA :: a, getB :: b } deriving (Generic, NFDataX) data Tup3 a b c = MkTup3 { getAB :: Pair a b, getC :: c } deriving (Generic, NFDataX) deriveAutoReg ''Pair deriveAutoReg ''Tup3
NB: Because of the way template haskell works the order here matters,
if you try to deriveAutoReg ''Tup3
before Pair
it will complain
about missing an instance AutoReg (Pair a b)
.
module Clash.Class.BitPack
module Clash.Class.Exp
module Clash.Class.Num
module Clash.Class.Parity
module Clash.Class.Resize
Other
module Control.Applicative
module Data.Bits
module Data.Default.Class
Exceptions
module Clash.XException
Named types
module Clash.NamedTypes
Hidden arguments
module Clash.Hidden
Magic
module Clash.Magic
Haskell Prelude
Clash.Prelude re-exports most of the Haskell Prelude with the exception of the following: (++), (!!), concat, drop, even, foldl, foldl1, foldr, foldr1, head, init, iterate, last, length, map, odd, 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. For the odd
end even
function a type class called Parity is available at Parity
.
module Clash.HaskellPrelude