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

Copyright(C) 2013-2016 University of Twente
2017 Myrtle Software Ltd Google Inc.
LicenseBSD2 (see the file LICENSE)
MaintainerChristiaan Baaij <christiaan.baaij@gmail.com>
Safe HaskellSafe
LanguageHaskell2010
Extensions
  • ScopedTypeVariables
  • DataKinds
  • FlexibleContexts
  • TypeOperators
  • ExplicitNamespaces
  • ExplicitForAll

Clash.Explicit.Prelude.Safe

Contents

Description

This is the Safe API only of Clash.Explicit.Prelude

This module defines the explicitly clocked counterparts of the functions defined in Clash.Prelude. Take a look at Clash.Signal.Explicit to see how you can make multi-clock designs.

Synopsis

Creating synchronous sequential circuits

mealy Source #

Arguments

:: Clock dom gated

Clock to synchronize to

-> Reset dom synchronous 
-> (s -> i -> (s, o))

Transfer function in mealy machine form: state -> input -> (newstate,output)

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

import qualified Data.List as L

macT
  :: Int        -- Current state
  -> (Int,Int)  -- Input
  -> (Int,Int)  -- (Updated state, output)
macT s (x,y) = (s',s)
  where
    s' = x * y + s

mac
  :: Clock domain Source
  -> Reset domain Asynchronous
  -> Signal domain (Int, Int)
  -> Signal domain Int
mac clk rst = mealy clk rst macT 0
>>> simulate (mac systemClockGen systemResetGen) [(1,1),(2,2),(3,3),(4,4)]
[0,1,5,14...
...

Synchronous sequential functions can be composed just like their combinational counterpart:

dualMac
  :: Clock domain gated -> Reset domain synchronous
  -> (Signal domain Int, Signal domain Int)
  -> (Signal domain Int, Signal domain Int)
  -> Signal domain Int
dualMac clk rst (a,b) (x,y) = s1 + s2
  where
    s1 = mealy clk rst mac 0 (bundle (a,x))
    s2 = mealy clk rst mac 0 (bundle (b,y))

mealyB Source #

Arguments

:: (Bundle i, Bundle o) 
=> Clock dom gated 
-> Reset dom synchronous 
-> (s -> i -> (s, o))

Transfer function in mealy machine form: state -> input -> (newstate,output)

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

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 rst a b c = (b1,b2,i2)
  where
    (i1,b1) = unbundle (mealy clk rst f 0 (bundle (a,b)))
    (i2,b2) = unbundle (mealy clk rst f 3 (bundle (i1,c)))

Using mealyB' however we can write:

g clk rst a b c = (b1,b2,i2)
  where
    (i1,b1) = mealyB clk rst f 0 (a,b)
    (i2,b2) = mealyB clk rst f 3 (i1,c)

moore Source #

Arguments

:: Clock domain gated

Clock to synchronize to

-> Reset domain synchronous 
-> (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 domain i -> Signal domain 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,Int)  -- Updated state
macT s (x,y) = x * y + s

mac
  :: Clock mac Source
  -> Reset mac Asynchronous
  -> Signal mac (Int, Int)
  -> Signal mac Int
mac clk rst = moore clk rst macT id 0
>>> simulate (mac systemClockGen systemResetGen) [(1,1),(2,2),(3,3),(4,4)]
[0,1,5,14...
...

Synchronous sequential functions can be composed just like their combinational counterpart:

dualMac
  :: Clock domain gated
  -> Reset domain synchronous
  -> (Signal domain Int, Signal domain Int)
  -> (Signal domain Int, Signal domain Int)
  -> Signal domain Int
dualMac clk rst (a,b) (x,y) = s1 + s2
  where
    s1 = moore clk rst mac id 0 (bundle (a,x))
    s2 = moore clk rst mac id 0 (bundle (b,y))

mooreB Source #

Arguments

:: (Bundle i, Bundle o) 
=> Clock domain gated 
-> Reset domain synchronous 
-> (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 domain i -> Unbundled domain o

Synchronous sequential function with input and output matching that of the moore machine

A version of moore that does automatic Bundleing

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 rst a b c = (b1,b2,i2)
  where
    (i1,b1) = unbundle (moore clk rst t o 0 (bundle (a,b)))
    (i2,b2) = unbundle (moore clk rst t o 3 (bundle (i1,c)))

Using mooreB' however we can write:

g clk rst a b c = (b1,b2,i2)
  where
    (i1,b1) = mooreB clk rst t o 0 (a,b)
    (i2,b2) = mooreB clk rst t o 3 (i1,c)

registerB :: Bundle a => Clock domain gated -> Reset domain synchronous -> a -> Unbundled domain a -> Unbundled domain a Source #

Create a register function for product-type like signals (e.g. (Signal a, Signal b))

rP :: Clock domain gated -> Reset domain synchronous
   -> (Signal domain Int, Signal domain Int)
   -> (Signal domain Int, Signal domain Int)
rP clk rst = registerB clk rst (8,8)
>>> simulateB (rP systemClockGen systemResetGen) [(1,1),(2,2),(3,3)] :: [(Int,Int)]
[(8,8),(1,1),(2,2),(3,3)...
...

Synchronizer circuits for safe clock domain crossing

dualFlipFlopSynchronizer Source #

Arguments

:: Clock domain1 gated1

Clock to which the incoming data is synchronised

-> Clock domain2 gated2

Clock to which the outgoing data is synchronised

-> Reset domain2 synchronous

Reset for registers on the outgoing domain

-> a

Initial value of the two synchronisation registers

-> Signal domain1 a

Incoming data

-> Signal domain2 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 #

Arguments

:: 2 <= addrSize 
=> SNat addrSize

Size of the internally used addresses, the FIFO contains 2^addrSize elements.

-> Clock wdomain wgated

Clock to which the write port is synchronised

-> Clock rdomain rgated

Clock to which the read port is synchronised

-> Reset wdomain synchronous 
-> Reset rdomain synchronous 
-> Signal rdomain Bool

Read request

-> Signal wdomain (Maybe a)

Element to insert

-> (Signal rdomain a, Signal rdomain Bool, Signal wdomain Bool)

(Oldest element in the FIFO, empty flag, full flag)

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

asyncRom Source #

Arguments

:: (KnownNat n, Enum addr) 
=> Vec n a

ROM content

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

Additional helpful information:

asyncRomPow2 Source #

Arguments

:: KnownNat n 
=> Vec (2 ^ n) a

ROM content

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

Additional helpful information:

rom Source #

Arguments

:: (KnownNat n, Enum addr) 
=> Clock domain gated

Clock to synchronize to

-> Vec n a

ROM content

NB: must be a constant

-> Signal domain addr

Read address rd

-> Signal domain a

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

Additional helpful information:

romPow2 Source #

Arguments

:: KnownNat n 
=> Clock domain gated

Clock to synchronize to

-> Vec (2 ^ n) a

ROM content

NB: must be a constant

-> Signal domain (Unsigned n)

Read address rd

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

Additional helpful information:

RAM primitives with a combinational read port

asyncRam Source #

Arguments

:: (Enum addr, HasCallStack) 
=> Clock wdom wgated

Clock to which to synchronise the write port of the RAM

-> Clock rdom rgated

Clock to which the read address signal, r, is synchronised

-> SNat n

Size n of the RAM

-> Signal rdom addr

Read address r

-> Signal wdom (Maybe (addr, a))

(write address w, value to write)

-> Signal rdom a

Value of the RAM at address r

Create a RAM with space for n elements

Additional helpful information:

asyncRamPow2 Source #

Arguments

:: (KnownNat n, HasCallStack) 
=> Clock wdom wgated

Clock to which to synchronise the write port of the RAM

-> Clock rdom rgated

Clock to which the read address signal, r, is synchronised

-> Signal rdom (Unsigned n)

Read address r

-> Signal wdom (Maybe (Unsigned n, a))

(write address w, value to write)

-> Signal rdom a

Value of the RAM at address r

Create a RAM with space for 2^n elements

Additional helpful information:

BlockRAM primitives

blockRam Source #

Arguments

:: HasCallStack 
=> Enum addr 
=> Clock dom gated

Clock to synchronize to

-> Vec n a

Initial content of the BRAM, also determines the size, n, of the BRAM.

NB: MUST be a constant.

-> Signal dom addr

Read address r

-> Signal dom (Maybe (addr, a))

(write address w, value to write)

-> Signal dom 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 :: Clock  domain gated
       -> Signal domain (Unsigned 6)
       -> Signal domain (Maybe (Unsigned 6, Bit))
       -> Signal domain Bit
bram40 clk = blockRam clk (replicate d40 1)

Additional helpful information:

blockRamPow2 Source #

Arguments

:: (KnownNat n, HasCallStack) 
=> Clock dom gated

Clock to synchronize to

-> Vec (2 ^ n) a

Initial content of the BRAM, also determines the size, 2^n, of the BRAM.

NB: MUST be a constant.

-> Signal dom (Unsigned n)

Read address r

-> Signal dom (Maybe (Unsigned n, a))

(Write address w, value to write)

-> Signal dom 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 domain (Unsigned 5)
       -> Signal domain (Maybe (Unsigned 5, Bit))
       -> Signal domain Bit
bram32 clk = blockRamPow2 clk (replicate d32 1)

Additional helpful information:

BlockRAM read/write conflict resolution

readNew Source #

Arguments

:: Eq addr 
=> Reset domain synchronous 
-> Clock domain gated 
-> (Signal domain addr -> Signal domain (Maybe (addr, a)) -> Signal domain a)

The ram component

-> Signal domain addr

Read address r

-> Signal domain (Maybe (addr, a))

(Write address w, value to write)

-> Signal domain a

Value of the ram at address r from the previous clock cycle

Create read-after-write blockRAM from a read-before-write one

Utility functions

isRising Source #

Arguments

:: (Bounded a, Eq a) 
=> Clock domain gated 
-> Reset domain synchronous 
-> a

Starting value

-> Signal domain a 
-> Signal domain Bool 

Give a pulse when the Signal goes from minBound to maxBound

isFalling Source #

Arguments

:: (Bounded a, Eq a) 
=> Clock domain gated 
-> Reset domain synchronous 
-> a

Starting value

-> Signal domain a 
-> Signal domain Bool 

Give a pulse when the Signal goes from maxBound to minBound

riseEvery :: forall domain gated synchronous n. Clock domain gated -> Reset domain synchronous -> SNat n -> Signal domain Bool Source #

Give a pulse every n clock cycles. This is a useful helper function when combined with functions like regEn or mux, in order to delay a register by a known amount.

oscillate :: forall domain gated synchronous n. Clock domain gated -> Reset domain synchronous -> Bool -> SNat n -> Signal domain Bool Source #

Oscillate a Bool for a given number of cycles, given the starting state.

Exported modules

Synchronous signals

DataFlow interface

Datatypes

Bit vectors

Arbitrary-width numbers

Fixed point numbers

Fixed size vectors

Perfect depth trees

Annotations

Type-level natural numbers

Type classes

Clash

Other

module Data.Bits

Exceptions

Named types

Haskell Prelude

module Prelude