Kansas Lava is a Haskell library that provides abstractions and powerful combinations to describe and simulate hardware circuits. Hardware descriptions are strongly typed and provide a means to describe hardware in a clear manner and express values that flow between components. You can describe both sequential and combinatorial circuits using Kansas Lava. To install the same on Fedora 20 (x86_64), follow the steps described below:

Download petersen/cabal-install repo from https://copr.fedoraproject.org/coprs/petersen/cabal-install/. If you do not have wget installed on your system, install it first using the following command:

 

# yum install wget

You can then run the following from /etc/yum.repos.d directory:

 

$ wget https://copr.fedoraproject.org/
coprs/petersen/cabal-install/repo/
fedora-20-i386/petersen-cabal-install-
fedora-20-i386.repo

Install cabal-install and Git.

 

# yum install cabal-install git

Download petersen/ghc-7.8 repo from https://copr.fedoraproject.org/coprs/petersen/ghc-7.8/ to /etc/yum.repos.d using:

 

# wget https://copr.fedoraproject.org/
coprs/petersen/ghc-7.8/repo/fedora-
rawhide-i386/petersen-ghc-7.8-fedora-
rawhide-i386.repo

Install Glasgow Haskell compiler (GHC) using:

 

# yum install ghc

Update the cabal local package list and install sized types using:

 

$ cabal update
$ cabal install sized-types

Obtain the latest Kansas Lava code from GitHub using:

 

$ git clone https://github.com/ku-fpg/
kansas-lava.git

Enter the following into the checked out Kansas Lava directory, compile and install the same as follows:

 

$ cabal install –only-dependencies
$ cabal build
$ cabal install

The tool can help verify the behaviour of a circuit in simulation, generate VHDL for synthesis and also validate whether the generated VHDL is the same as the simulated circuit.

A simple code for the half adder combinatorial circuit is given below:

 

import Language.KansasLava

halfAdd :: Signal i Bool -> Signal i
Bool -> (Signal i Bool, Signal i Bool)
halfAdd a b = (carry, sum)
where carry = a `and2` b
sum = a `xor2` b

Execute the above example using Glasgow Haskell compiler (GHCi):

 

$ ghci halfAdd.hs
ghci> halfAdd low high
(low,high)
ghci> halfAdd high high
(high,low)

Kansas Lava implements the idea of an undefined Signal, where binary functions like and2, or2 and xor2 are short circuited. With unknown values, these function as hardware gates.

 

ghci> :m + Language.KansasLava

ghci> undefinedS `or2` low
?
ghci> undefinedS `or2` high
high
ghci> undefinedS `and2` low
low
ghci> undefinedS `and2` high
?
ghci> undefinedS `xor2` low
?
ghci> undefinedS `xor2` high
?

mux is a function that can be used to select an input. With low input, it picks the first argument in the tuple, and with high input, it picks the second argument in the tuple.

 

ghci> :m + Language.KansasLava

ghci> mux low (0,1) :: Signal c Int
0
ghci> mux high (0,1) :: Signal c Int
1

Kansas Lava provides a number of instance declarations and overloadings for the signal module.

 

instance (Num a, Rep a) => Num (Signal
i a)

instance (Bounded a, Rep a) => Bounded
(Signal i a)

instance (Show a, Bits a, Rep a) => Bits
(Signal i a)

The overloading enables you to use Haskell expressions with Signal c and can be helpful in describing hardware signals.

 

ghci> :m + Language.KansasLava

ghci> 2 :: Signal c Int
2
ghci> 2 * 4 :: Signal c Int
8

ghci> :m + Data.Bits
ghci> 8 `shiftR` 2 :: Signal c Int
2

The clock class can change a signal with time and is used for sequential values. It provides two important functions: register and delay. The register function accepts an initial value and an input sequence as arguments, while delay function is similar to register function with the initial value undefined. Register function behaves like D edge-triggered flip-flop with an internal clock. toS function converts a set of values into a signal. For example,

 

ghci> :m + Language.KansasLava

ghci> let xs = toS [1..5] :: Seq Int
ghci> xs
1 | 2 | 3 | 4 | 5 | ? .
ghci> delay xs
? | 1 | 2 | 3 | 4 | 5 | ? .
ghci> register 10 xs
10 | 1 | 2 | 3 | 4 | 5 | ? .

Kansas Lava has support for both fixed-width signed and unsigned numbers. An unsigned X4 is a 4-bit unsigned number.

 

ghci> :m + Data.Sized.Matrix
ghci> :m + Data.Sized.Unsigned

ghci> 100 :: U4
4

ghci> :m + Data.Sized.Signed

ghci> 100 :: S8
100
ghci> 100 + 100 :: S8
-56
ghci> [minBound..maxBound] :: [U4]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

It also provides support for fixed-width matrices. A matrix with four elements of boolean type is represented by Matrix U2 bool. These are useful when specifying irregular-sized values in hardware.

 

ghci> :m + Data.Sized.Matrix

ghci> let m = matrix [1,2,3,4] ::
Matrix U2 Int

ghci> :m + Data.Array.IArray

ghci> m ! 1
2
ghci> m ! 0
1

The pack utility provides a means to combine multiple signals into a single signal, and the unpack combinator does the reverse. These allow flexible-type representation of data in the program. For example,

 

ghci> :m + Language.KansasLava

ghci> let p = toS (cycle [False, True])
:: Seq Bool
ghci> let q = toS [1..] :: Seq Int
ghci> let pq = pack (p, q) :: Seq (Bool,
Int)
ghci> takeS 2 pq
(low,1) | (high,2) | (?,?) .

Apart from signal types, circuits can also be built from Haskell functions.

Consider a ROM that stores the cube of a value. funMapXXX function when used directly is similar to an asynchronous ROM.

 

ghci> :m + Language.KansasLava
ghci> :set -XScopedTypeVariables

ghci> let cubeROM = funMapXXX(\(x::Int)
-> return(x*x*x))

ghci> takeS 5 $ cubeROM $ toS [1..] ::
Seq Int
1 | 8 | 27 | 64 | 125 | ? .

Kansas Lava also provides various coerce functions that can be used between two signal types, as long as both types have the same bit-width. For example,

 

ghci> :m + Language.KansasLava

ghci> let a = toS (cycle [False, True])
:: Seq Bool
ghci> takeS 5 a
low | high | low | high | low | ? .

ghci> takeS 5 $ (unsigned) a :: Seq Int
0 | 1 | 0 | 1 | 0 | ? .

Circuits can be debugged using probes, which present a way to observe intermediate values in shallow embedded circuits without modifying the circuit interface. These are inserted in the function using probeS function.

 

ghci> :m + Language.KansasLava

ghci> setProbesAsTrace (appendFile
“DEBUG”)
ghci> let xs = toS (cycle [False, True])
:: Seq Bool
ghci> let ys = probeS “ys” (takeS 5 $
(unsigned) xs :: Seq Int)
ghci> takeS 5 ys
0 | 1 | 0 | 1 | 0 | ? .
ghci> :!cat DEBUG
ys(0)0
ys(1)1
ys(2)0
ys(3)1
ys(4)0

An important purpose of Kansas Lava is to produce useful VHDL. Hardware descriptions are converted into efficient VHDL. Kansas Lava programs are extracted into a Kansas Lava entity graph (KLEG), which is an abstract representation of the netlist. This can be optimised and written into VHDL. The generic netlist rendering tool can also target Verilog. Kansas Lava can also generate and execute a VHDL test bench. mkTestbench function can be used to generate a test bench.

LEAVE A REPLY

Please enter your comment!
Please enter your name here