clash-prelude-1.8.4: Clash: a functional hardware description language - Prelude library

Copyright | (C) 2015-2016 University of Twente 2017 Google Inc. 2019 Myrtle Software Ltd. 2021-2022 QBayLogic B.V.
License | BSD2 (see the file LICENSE)
Maintainer | QBayLogic B.V. <devops@qbaylogic.com>
Safe Haskell | Unsafe
Language | Haskell2010

Extensions

- Cpp
- ScopedTypeVariables
- BangPatterns
- ViewPatterns
- DataKinds
- InstanceSigs
- StandaloneDeriving
- DeriveDataTypeable
- DeriveFunctor
- DeriveTraversable
- DeriveFoldable
- DeriveGeneric
- DefaultSignatures
- DeriveLift
- DerivingStrategies
- FlexibleContexts
- MagicHash
- KindSignatures
- PostfixOperators
- TupleSections
- TypeOperators
- ExplicitNamespaces
- ExplicitForAll
- BinaryLiterals
- TypeApplications

Clash.Explicit.ROM.File

Contents

- Synchronous ROM synchronized to an arbitrary clock
- Producing files
- Internal

Description

# Initializing a ROM with a data file

ROMs initialized with a data file. The BNF grammar for this data file is simple:

    FILE = LINE+
    LINE = BIT+
    BIT  = '0'
         | '1'

Consecutive `LINE`s correspond to consecutive memory addresses starting at `0`. For example, a data file `memory.bin` containing the 9-bit unsigned numbers `7` to `13` looks like:

    000000111
    000001000
    000001001
    000001010
    000001011
    000001100
    000001101

Such a file can be produced with `memFile`:

    writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13])

We can instantiate a synchronous ROM using the contents of the file above like so:

    f :: KnownDomain dom
      => Clock  dom
      -> Enable dom
      -> Signal dom (Unsigned 3)
      -> Signal dom (Unsigned 9)
    f clk en rd = unpack <$> romFile clk en d7 "memory.bin" rd

And see that it works as expected:

    >>> import qualified Data.List as L
    >>> L.tail $ sampleN 4 $ f systemClockGen (fromList [3..5])
    [10,11,12]

However, we can also interpret the same data as a tuple of a 6-bit unsigned number, and a 3-bit signed number:

    g :: KnownDomain dom
      => Clock  dom
      -> Signal dom (Unsigned 3)
      -> Signal dom (Unsigned 6,Signed 3)
    g clk en rd = unpack <$> romFile clk en d7 "memory.bin" rd

And then we would see:

    >>> import qualified Data.List as L
    >>> L.tail $ sampleN 4 $ g systemClockGen (fromList [3..5])
    [(1,2),(1,3)(1,-4)]

Synopsis

- romFile :: forall (m :: Nat) addr (dom :: Domain) (n :: Nat). (KnownNat m, Enum addr, KnownDomain dom) => Clock dom -> Enable dom -> SNat n -> FilePath -> Signal dom addr -> Signal dom (BitVector m)
- romFilePow2 :: forall (dom :: Domain) (n :: Nat) (m :: Nat). (KnownNat m, KnownNat n, KnownDomain dom) => Clock dom -> Enable dom -> FilePath -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
- memFile :: (BitPack a, Foldable f, HasCallStack) => Maybe Bit -> f a -> String
- romFile# :: forall (m :: Nat) (dom :: Domain) (n :: Nat). (KnownNat m, KnownDomain dom) => Clock dom -> Enable dom -> SNat n -> FilePath -> Signal dom Int -> Signal dom (BitVector m)

# Synchronous ROM synchronized to an arbitrary clock

romFile Source #

Arguments

:: forall (m :: Nat) addr (dom :: Domain) (n :: Nat). (KnownNat m, Enum addr, KnownDomain dom) |
=> Clock dom | `Clock` to synchronize to
-> Enable dom | `Enable` line
-> SNat n | Size of the ROM
-> FilePath | File describing the content of the ROM
-> Signal dom addr | Read address `r`
-> Signal dom (BitVector m) | The value of the ROM at address `r` 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, reading it will throw an `XException`
- 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 also:

- See Clash.Explicit.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
- See `memFile` for creating a data file with Clash.
- See Clash.Sized.Fixed for ideas on how to create your own data files.

romFilePow2 Source #

Arguments

:: forall (dom :: Domain) (n :: Nat) (m :: Nat). (KnownNat m, KnownNat n, KnownDomain dom) |
=> Clock dom | `Clock` to synchronize to
-> Enable dom | `Enable` line
-> FilePath | File describing the content of the ROM
-> Signal dom (Unsigned n) | Read address `r`
-> Signal dom (BitVector m) | The value of the ROM at address `r` 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, reading it will throw an `XException`
- 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 also:

- See Clash.Explicit.ROM.File for more information on how to instantiate a ROM with the contents of a data file.
- See `memFile` for creating a data file with Clash.
- See Clash.Sized.Fixed for more ideas on how to create your own data files.

# Producing files

memFile Source #

Arguments

:: (BitPack a, Foldable f, HasCallStack) |
=> Maybe Bit | Value to map don't care bits to. `Nothing` means throwing an error on don't care bits.
-> f a | Values to convert
-> String | Contents of the memory file

Convert data to the `String` contents of a memory file.

- NB: Not synthesizable

- The following document the several ways to instantiate components with files:

  - Clash.Prelude.BlockRam.File
  - Clash.Prelude.ROM.File
  - Clash.Explicit.BlockRam.File
  - Clash.Explicit.ROM.File
- See Clash.Sized.Fixed for more ideas on how to create your own data files.

# Example

The `Maybe` datatype has don't care bits, where the actual value does not matter. But the bits need a defined value in the memory. Either 0 or 1 can be used, and both are valid representations of the data.

    >>> let es = [ Nothing, Just (7 :: Unsigned 8), Just 8]
    >>> mapM_ (putStrLn . show . pack) es
    0b0_...._....
    0b1_0000_0111
    0b1_0000_1000
    >>> putStr (memFile (Just 0) es)
    000000000
    100000111
    100001000
    >>> putStr (memFile (Just 1) es)
    011111111
    100000111
    100001000

# Internal

romFile# Source #

Arguments

:: forall (m :: Nat) (dom :: Domain) (n :: Nat). (KnownNat m, KnownDomain dom) |
=> Clock dom | `Clock` to synchronize to
-> Enable dom | `Enable` line
-> SNat n | Size of the ROM
-> FilePath | File describing the content of the ROM
-> Signal dom Int | Read address `r`
-> Signal dom (BitVector m) | The value of the ROM at address `r` from the previous clock cycle

romFile primitive