Copyright | (C) 2013-2016 University of Twente |
---|---|
License | BSD2 (see the file LICENSE) |
Maintainer | Christiaan Baaij <christiaan.baaij@gmail.com> |
Safe Haskell | Unsafe |
Language | Haskell2010 |
Extensions |
|
This module defines the explicitly clocked counterparts of the functions defined in CLaSH.Prelude.
This module uses the explicitly clocked Signal'
synchronous signals, as
opposed to the implicitly clocked Signal
used in CLaSH.Prelude. Take a
look at CLaSH.Signal.Explicit to see how you can make multi-clock designs
using explicitly clocked signals.
- mealy' :: SClock clk -> (s -> i -> (s, o)) -> s -> Signal' clk i -> Signal' clk o
- mealyB' :: (Bundle i, Bundle o) => SClock clk -> (s -> i -> (s, o)) -> s -> Unbundled' clk i -> Unbundled' clk o
- moore' :: SClock clk -> (s -> i -> s) -> (s -> o) -> s -> Signal' clk i -> Signal' clk o
- mooreB' :: (Bundle i, Bundle o) => SClock clk -> (s -> i -> s) -> (s -> o) -> s -> Unbundled' clk i -> Unbundled' clk o
- registerB' :: Bundle a => SClock clk -> a -> Unbundled' clk a -> Unbundled' clk a
- dualFlipFlopSynchronizer :: SClock clk1 -> SClock clk2 -> a -> Signal' clk1 a -> Signal' clk2 a
- asyncFIFOSynchronizer :: 2 <= addrSize => SNat addrSize -> SClock wclk -> SClock rclk -> Signal' rclk Bool -> Signal' wclk (Maybe a) -> (Signal' rclk a, Signal' rclk Bool, Signal' wclk Bool)
- rom' :: (KnownNat n, Enum addr) => SClock clk -> Vec n a -> Signal' clk addr -> Signal' clk a
- romPow2' :: KnownNat n => SClock clk -> Vec (2 ^ n) a -> Signal' clk (Unsigned n) -> Signal' clk a
- romFile' :: (KnownNat m, Enum addr) => SClock clk -> SNat n -> FilePath -> Signal' clk addr -> Signal' clk (BitVector m)
- romFilePow2' :: forall clk n m. (KnownNat m, KnownNat n) => SClock clk -> FilePath -> Signal' clk (Unsigned n) -> Signal' clk (BitVector m)
- asyncRam' :: Enum addr => SClock wclk -> SClock rclk -> SNat n -> Signal' rclk addr -> Signal' wclk (Maybe (addr, a)) -> Signal' rclk a
- asyncRamPow2' :: forall wclk rclk n a. KnownNat n => SClock wclk -> SClock rclk -> Signal' rclk (Unsigned n) -> Signal' wclk (Maybe (Unsigned n, a)) -> Signal' rclk a
- blockRam' :: Enum addr => SClock clk -> Vec n a -> Signal' clk addr -> Signal' clk (Maybe (addr, a)) -> Signal' clk a
- blockRamPow2' :: KnownNat n => SClock clk -> Vec (2 ^ n) a -> Signal' clk (Unsigned n) -> Signal' clk (Maybe (Unsigned n, a)) -> Signal' clk a
- blockRamFile' :: (KnownNat m, Enum addr) => SClock clk -> SNat n -> FilePath -> Signal' clk addr -> Signal' clk (Maybe (addr, BitVector m)) -> Signal' clk (BitVector m)
- blockRamFilePow2' :: forall clk n m. (KnownNat m, KnownNat n) => SClock clk -> FilePath -> Signal' clk (Unsigned n) -> Signal' clk (Maybe (Unsigned n, BitVector m)) -> Signal' clk (BitVector m)
- window' :: (KnownNat n, Default a) => SClock clk -> Signal' clk a -> Vec (n + 1) (Signal' clk a)
- windowD' :: (KnownNat n, Default a) => SClock clk -> Signal' clk a -> Vec (n + 1) (Signal' clk a)
- isRising' :: (Bounded a, Eq a) => SClock clk -> a -> Signal' clk a -> Signal' clk Bool
- isFalling' :: (Bounded a, Eq a) => SClock clk -> a -> Signal' clk a -> Signal' clk Bool
- assert' :: (Eq a, Show a) => SClock t -> String -> Signal' t a -> Signal' t a -> Signal' t b -> Signal' t b
- stimuliGenerator' :: forall l clk a. KnownNat l => SClock clk -> Vec l a -> Signal' clk a
- outputVerifier' :: forall l clk a. (KnownNat l, Eq a, Show a) => SClock clk -> Vec l a -> Signal' clk a -> Signal' clk Bool
- module CLaSH.Signal.Explicit
Creating synchronous sequential circuits
:: SClock clk |
|
-> (s -> i -> (s, o)) | Transfer function in mealy machine form:
|
-> s | Initial state |
-> Signal' clk i -> Signal' clk 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 type ClkA =Clk
"A" 100 clkA ::SClock
ClkA clkA =sclock
topEntity ::Signal'
ClkA (Int, Int) ->Signal'
ClkA Int topEntity =mealy'
clkA 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'
clkA100 Int,Signal'
clkA100 Int) -> (Signal'
clkA100 Int,Signal'
clkA100 Int) ->Signal'
clkA100 Int dualMac (a,b) (x,y) = s1 + s2 where s1 =mealy'
clkA100 mac 0 (bundle'
clkA100 (a,x)) s2 =mealy'
clkA100 mac 0 (bundle'
clkA100 (b,y))
:: (Bundle i, Bundle o) | |
=> SClock clk | |
-> (s -> i -> (s, o)) | Transfer function in mealy machine form:
|
-> s | Initial state |
-> Unbundled' clk i -> Unbundled' clk 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 clk a b c = (b1,b2,i2) where (i1,b1) =unbundle'
clk (mealy' clk f 0 (bundle'
clk (a,b))) (i2,b2) =unbundle'
clk (mealy' clk f 3 (bundle'
clk (i1,c)))
Using mealyB'
however we can write:
g clk a b c = (b1,b2,i2) where (i1,b1) =mealyB'
clk f 0 (a,b) (i2,b2) =mealyB'
clk f 3 (i1,c)
:: SClock clk |
|
-> (s -> i -> s) | Transfer function in moore machine form:
|
-> (s -> o) | Output function in moore machine form:
|
-> s | Initial state |
-> Signal' clk i -> Signal' clk 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,Int) -- Updated state mac s (x,y) = x * y + s type ClkA =Clk
"A" 100 clkA ::SClock
ClkA clkA =sclock
topEntity ::Signal'
ClkA (Int, Int) ->Signal'
ClkA Int topEntity =moore'
clkA 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'
clkA Int,Signal'
clkA Int) -> (Signal'
clkA Int,Signal'
clkA Int) ->Signal'
clkA Int dualMac (a,b) (x,y) = s1 + s2 where s1 =moore'
clkA mac id 0 (bundle'
clkA (a,x)) s2 =moore'
clkA mac id 0 (bundle'
clkA (b,y))
:: (Bundle i, Bundle o) | |
=> SClock clk | |
-> (s -> i -> s) | Transfer function in moore machine form:
|
-> (s -> o) | Output function in moore machine form:
|
-> s | Initial state |
-> Unbundled' clk i -> Unbundled' clk 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 clk a b c = (b1,b2,i2) where (i1,b1) =unbundle'
clk (moore' clk t o 0 (bundle'
clk (a,b))) (i2,b2) =unbundle'
clk (moore' clk t o 3 (bundle'
clk (i1,c)))
Using mooreB'
however we can write:
g clk a b c = (b1,b2,i2) where (i1,b1) =mooreB'
clk t o 0 (a,b) (i2,b2) =mooreB'
clk to 3 (i1,c)
registerB' :: Bundle a => SClock clk -> a -> Unbundled' clk a -> Unbundled' clk a Source #
Create a register
function for product-type like signals (e.g.
(
)Signal
a, Signal
b)
type ClkA =Clk
"A" 100 clkA ::SClock
ClkA clkA =sclock
rP :: (Signal'
ClkA Int,Signal'
ClkA Int) -> (Signal'
ClkA Int,Signal'
ClkA Int) rP =registerB'
clkA (8,8)
>>>
simulateB rP [(1,1),(2,2),(3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)... ...
Synchronizer circuits for safe clock domain crossings
dualFlipFlopSynchronizer Source #
:: SClock clk1 |
|
-> SClock clk2 |
|
-> a | Initial value of the two synchronisation registers |
-> Signal' clk1 a | Incoming data |
-> Signal' clk2 a | Outgoing, synchronised, data |
Synchroniser based on two sequentially connected flip-flops.
- NB: This synchroniser can be used for bit-synchronization.
NB: Although this synchroniser does reduce metastability, it does not guarantee the proper synchronisation of a whole word. For example, given that the output is sampled twice as fast as the input is running, and we have two samples in the input stream that look like:
[0111,1000]
But the circuit driving the input stream has a longer propagation delay on msb compared to the lsbs. What can happen is an output stream that looks like this:
[0111,0111,0000,1000]
Where the level-change of the msb was not captured, but the level change of the lsbs were.
If you want to have safe word-synchronisation use
asyncFIFOSynchronizer
.
asyncFIFOSynchronizer Source #
:: 2 <= addrSize | |
=> SNat addrSize | Size of the internally used addresses, the
FIFO contains |
-> SClock wclk |
|
-> SClock rclk |
|
-> Signal' rclk Bool | Read request |
-> Signal' wclk (Maybe a) | Element to insert |
-> (Signal' rclk a, Signal' rclk Bool, Signal' wclk Bool) | (Oldest element in the FIFO, |
Synchroniser implemented as a FIFO around an asynchronous RAM. Based on the design described in CLaSH.Tutorial, which is itself based on the design described in http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf.
NB: This synchroniser can be used for word-synchronization.
ROMs
:: (KnownNat n, Enum addr) | |
=> SClock clk |
|
-> Vec n a | ROM content NB: must be a constant |
-> Signal' clk addr | Read address |
-> Signal' clk 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 | |
=> SClock clk |
|
-> Vec (2 ^ n) a | ROM content NB: must be a constant |
-> Signal' clk (Unsigned n) | Read address |
-> Signal' clk 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 initialised with a data file
:: (KnownNat m, Enum addr) | |
=> SClock clk |
|
-> SNat n | Size of the ROM |
-> FilePath | File describing the content of the ROM |
-> Signal' clk addr | Read address |
-> Signal' clk (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) | |
=> SClock clk |
|
-> FilePath | File describing the content of the ROM |
-> Signal' clk (Unsigned n) | Read address |
-> Signal' clk (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 | |
=> SClock wclk |
|
-> SClock rclk |
|
-> SNat n | Size |
-> Signal' rclk addr | Read address |
-> Signal' wclk (Maybe (addr, a)) | (write address |
-> Signal' rclk 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 | |
=> SClock wclk |
|
-> SClock rclk |
|
-> Signal' rclk (Unsigned n) | Read address |
-> Signal' wclk (Maybe (Unsigned n, a)) | (write address |
-> Signal' rclk 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
:: Enum addr | |
=> SClock clk |
|
-> Vec n a | Initial content of the BRAM, also
determines the size, NB: MUST be a constant. |
-> Signal' clk addr | Read address |
-> Signal' clk (Maybe (addr, a)) | (write address |
-> Signal' clk 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
type ClkA = Clk "A" 100 clkA100 :: SClock ClkA clkA100 =sclock
bram40 ::Signal'
ClkA (Unsigned
6) ->Signal'
ClkA (Maybe (Unsigned
6,Bit
)) ->Signal'
ClkABit
bram40 =blockRam'
clkA100 (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' clk (blockRam' clk inits) rd wrM
.
:: KnownNat n | |
=> SClock clk |
|
-> Vec (2 ^ n) a | Initial content of the BRAM, also
determines the size, NB: MUST be a constant. |
-> Signal' clk (Unsigned n) | Read address |
-> Signal' clk (Maybe (Unsigned n, a)) | (Write address |
-> Signal' clk 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
type ClkA = Clk "A" 100 clkA100 :: SClock ClkA clkA100 =sclock
bram32 ::Signal'
ClkA (Unsigned
5) ->Signal'
ClkA (Maybe (Unsigned
5,Bit
)) ->Signal'
ClkABit
bram32 =blockRamPow2'
clkA100 (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' clk (blockRamPow2' clk inits) rd wrM
.
BlockRAM primitives initialised with a data file
:: (KnownNat m, Enum addr) | |
=> SClock clk |
|
-> SNat n | Size of the blockRAM |
-> FilePath | File describing the initial content of the blockRAM |
-> Signal' clk addr | Read address |
-> Signal' clk (Maybe (addr, BitVector m)) | (write address |
-> Signal' clk (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) | |
=> SClock clk |
|
-> FilePath | File describing the initial content of the blockRAM |
-> Signal' clk (Unsigned n) | Read address |
-> Signal' clk (Maybe (Unsigned n, BitVector m)) | (write address |
-> Signal' clk (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.
Utility functions
Testbench functions
:: (Eq a, Show a) | |
=> SClock t | |
-> String | Additional message |
-> Signal' t a | Checked value |
-> Signal' t a | Expected value |
-> Signal' t b | Return value |
-> Signal' t 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.
:: KnownNat l | |
=> SClock clk | Clock to which to synchronize the output signal |
-> Vec l a | Samples to generate |
-> Signal' clk 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:
type ClkA =Clk
"A" 100 clkA ::SClock
ClkA clkA =sclock
testInput' ::Signal'
clkA Int testInput' =stimuliGenerator'
clkA $(listToVecTH
[(1::Int),3..21])
>>>
sampleN 13 testInput'
[1,3,5,7,9,11,13,15,17,19,21,21,21]
:: (KnownNat l, Eq a, Show a) | |
=> SClock clk | Clock to which the input signal is synchronized to |
-> Vec l a | Samples to compare with |
-> Signal' clk a | Signal to verify |
-> Signal' clk 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:
type ClkA =Clk
"A" 100 clkA ::SClock
ClkA clkA =sclock
expectedOutput' ::Signal'
ClkA Int ->Signal'
ClkA Bool expectedOutput' =outputVerifier'
clkA $(listToVecTH
([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(A100): 0, outputVerifier expected value: 70, not equal to actual value: 0 [False cycle(A100): 1, outputVerifier expected value: 99, not equal to actual value: 1 ,False,False,False,False,False cycle(A100): 6, outputVerifier expected value: 7, not equal to actual value: 6 ,False cycle(A100): 7, outputVerifier expected value: 8, not equal to actual value: 7 ,False cycle(A100): 8, outputVerifier expected value: 9, not equal to actual value: 8 ,False cycle(A100): 9, outputVerifier expected value: 10, not equal to actual value: 9 ,False,True,True]
Exported modules
Explicitly clocked synchronous signals
module CLaSH.Signal.Explicit