Functional hardware description in Lava
Functional hardware description in Lava
Functional hardware description in Lava
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
<strong>Functional</strong> <strong>hardware</strong> <strong>description</strong> <strong>in</strong> <strong>Lava</strong><br />
Alexander Sulfrian (2009)<br />
E<strong>in</strong>leitung:<br />
Dieses Dokument befasst sich mit der Möglichkeit logische Schaltkreise <strong>in</strong> Haskell zu<br />
beschreiben. Es existieren verschiedene andere Varianten um Hardware am PC zu<br />
beschreiben. Die verbreitetsten s<strong>in</strong>d VHDL <strong>in</strong> Europa und Verilog <strong>in</strong> den USA. Diese<br />
formalen Sprachen dienen dazu über e<strong>in</strong>e gewisses Abstraktionsebene Schaltkreise zu<br />
beschreiben. Dabei s<strong>in</strong>d diese Sprache aber sehr kompliziert und mit erst mit viel<br />
E<strong>in</strong>arbeitung zu verstehen. Dazu kommt, dass für e<strong>in</strong>e e<strong>in</strong>fache Schaltung schon diese<br />
Sprache schon sehr umfangreich werden können.<br />
Wir verwenden zur Beschreibung von Hardware das Modul <strong>Lava</strong>2000. Dieses kann im<br />
Gegensatz zu den anderen Sprachen mit e<strong>in</strong>fachen Haskellfunktionen aus<br />
grundlegenden logischen Gattern ganze Schaltungen beschreiben und simulieren.<br />
Dabei dient es bei der Verifikation oder auch bei der realen Fertigung nur als Frontend<br />
für andere Anwendung und kann die Schaltungen dann auch <strong>in</strong> VHDL (das vorwiegend<br />
zur Konfiguration von programmierbaren <strong>in</strong>tegrierten Schaltkreisen dient) exportieren.<br />
Zu Beg<strong>in</strong>n werde ich kurz auf die Installation von <strong>Lava</strong>200 und den benötigten<br />
Anwendungen e<strong>in</strong>gehen. Danach werde ich versuchen an Hand von anschaulichen<br />
Beispielen die Idee h<strong>in</strong>ter <strong>Lava</strong> zu zeigen. Dabei werde ich von Grundlagen, über<br />
e<strong>in</strong>fache logische Gatter, bis h<strong>in</strong> zu komplexen logischen Schaltnetzen und<br />
Schaltwerken die Methoden von <strong>Lava</strong> erläutern.<br />
Installation<br />
<strong>Lava</strong>2000 ist e<strong>in</strong> Haskellmodul. Es sollte klar se<strong>in</strong>, dass für den Betrieb von diesem<br />
e<strong>in</strong>e Haskellcompiler (zum Beispiel der ghc) vorhanden se<strong>in</strong> muss. Da allerd<strong>in</strong>gs viele<br />
gezeigten Anwendungen <strong>in</strong>teraktiv se<strong>in</strong> können, wäre es vorteilhaft wenn auch der<br />
zugehörige Interpreter (ghci) <strong>in</strong>stalliert wäre. Damit <strong>Lava</strong> <strong>in</strong>stalliert werden kann s<strong>in</strong>d<br />
darüber h<strong>in</strong>aus noch darcs (das Versionsverwaltungssystem von den meisten<br />
Haskellprojekten) sowie cabal (das Haskellpaketverwaltungssystem) von Vorteil.<br />
Zur Zeit existieren m<strong>in</strong>destens 2 Versionen von <strong>Lava</strong>. <strong>Lava</strong>2000 (auch Chalmers-<strong>Lava</strong>)<br />
soll vor allem als Interface für formale Verifikationstools dienen. Parallel dazu wurde<br />
von Xil<strong>in</strong>x Inc. e<strong>in</strong>e weitere Version von <strong>Lava</strong> entwickelt, die im Gegensatz dazu vor<br />
allem zum Erstellen von Konfigurationen für die FPGAs von Xil<strong>in</strong>x geeignet ist. Im<br />
folgenden liegt der Schwerpunkt hier auf dem Chalmers-<strong>Lava</strong> Modul. 1<br />
Zur Installation von <strong>Lava</strong>2000 ist die zunächst e<strong>in</strong>fach wie folgt herunterzuladen:<br />
darcs get http://www.cs.chalmers.se/~emax/darcs/chalmers-lava2000/<br />
Danach ist e<strong>in</strong>e Besonderheit von <strong>Lava</strong> zu beachten: Für verschiedene Aufgaben<br />
werden externe Tools benutzt. Daher benötigt <strong>Lava</strong> den Pfad der Installation um<br />
benutzerdef<strong>in</strong>ierte Scripte zu laden. Dieser Pfad muss <strong>in</strong> der Datei<br />
<strong>Lava</strong>2000/<strong>Lava</strong>Dir.hs im heruntergeladenem Sourcecode anzupassen. Danach kann<br />
<strong>Lava</strong> genau wie jedes andere cabal-Projekt mit den folgenden 3 Schritten <strong>in</strong>stalliert<br />
werden: (hier am Beispiel für den ghc)<br />
runghc Setup configure<br />
runghc Setup build<br />
runghc Setup <strong>in</strong>stall<br />
1: http://www.cs.chalmers.se/~koen/<strong>Lava</strong>/<br />
Seite 1/7
Um Schaltungen zu Verifizieren benötigt man nun noch e<strong>in</strong>e externe Anwendung. Hier<br />
wird die nötige Konfiguration am Beispiel von NuSMV 2 erläutert: Nach der Installation<br />
von NuSMV muss man noch e<strong>in</strong>e passende Scriptdatei für die Anb<strong>in</strong>dung an <strong>Lava</strong><br />
erstellen. Die smv.wrapper die bei <strong>Lava</strong> dabei ist, ist leider für e<strong>in</strong>e ältere Version und<br />
nicht mit NuSMV kompatibel. Daher habe ich diese modifiziert. Die veränderte Version<br />
kann jetzt unter http://download.animux.de/smv.wrapper heruntergeladen werden.<br />
Diese Datei muss an den Pfad der <strong>in</strong> <strong>Lava</strong>2000/<strong>Lava</strong>Dir.hs angegeben wurde <strong>in</strong> Scripts/<br />
abgelegt werden.<br />
Wenn dies geschafft ist, ist <strong>Lava</strong> endlich e<strong>in</strong>satzbereit und man kann anfangen<br />
Schaltungen damit zu beschreiben, zu simulieren und zu verifizieren.<br />
Schaltnetze<br />
Schaltnetze s<strong>in</strong>d e<strong>in</strong>e der grundlegende Strukturen von logischen Schaltungen. Dies<br />
s<strong>in</strong>d logische Formeln aus der Mathematik <strong>in</strong> Hardware als e<strong>in</strong> Netz aus logischen<br />
Gattern. Dabei f<strong>in</strong>det man <strong>in</strong> Schaltnetzen ke<strong>in</strong>e Gatter die ihren Zustand speichern<br />
und deshalb haben Schaltnetze ke<strong>in</strong>en <strong>in</strong>neren Zustand. Bei e<strong>in</strong>er Belegung der<br />
E<strong>in</strong>gänge kann man unabhängig von der vorherigen Belegung immer die selben Werte<br />
an den Ausgängen messen.<br />
• Die e<strong>in</strong>fachste Struktur ist e<strong>in</strong> Halbaddierer:<br />
Dieses Schaltnetz realisiert die Addition der beiden E<strong>in</strong>gänge. Dabei liefert es<br />
zum e<strong>in</strong>en die Summe und an e<strong>in</strong>em anderen Ausgang den Übertrag, der bei<br />
der Addition von 2 Bit entstehen kann. Die Umsetzung von dieser Struktur <strong>in</strong><br />
<strong>Lava</strong> sieht wie folgt aus:<br />
import <strong>Lava</strong>2000<br />
halfAdd :: (Signal Bool, Signal Bool) -> (Signal Bool, Signal Bool)<br />
halfAdd(a,b) = (sum,carry)<br />
where<br />
sum = xor2(a,b)<br />
carry = and2(a,b)<br />
Wie man erkennen kann, kann der Schaltplan direkt 1-zu-1 nach <strong>Lava</strong><br />
übersetzt werden und mit den logischen Gattern die <strong>Lava</strong> bereit stellt<br />
nachgebaut werden.<br />
• Allerd<strong>in</strong>gs reicht meißt e<strong>in</strong> Halbaddierer nicht aus. Mit diesem kann man wie der<br />
Name schon sagt Bits nur zur Hälfte addieren. Um mehrere Bits addieren zu<br />
können benötigt man e<strong>in</strong>en Volladdierer:<br />
2: NuSMV - a new symbolic model checker: http://nusmv.irst.itc.it/<br />
Seite 2/7
Der Volladdierer erhält als E<strong>in</strong>gang ähnlich wie der Halbaddierer auch zwei<br />
Werte die er addiert. Er hat allerd<strong>in</strong>gs zusätzlich e<strong>in</strong>en E<strong>in</strong>gang um e<strong>in</strong>en<br />
Überlauf von e<strong>in</strong>er vorherigen Addition aufzunehmen. Das Ergebnis dieser 3<br />
Bit gibt er genauso wie der Halbaddierer als Summe und Überlauf aus.<br />
Wie man erkennen kann ist der Volladdierer aus 2 Halbaddierern aufgebaut.<br />
Da <strong>Lava</strong> die Schaltungen als Funktionen darstellt, ist die Wiederverwendung<br />
besonders e<strong>in</strong>fach:<br />
fullAdd :: (Signal Bool, (Signal Bool, Signal Bool)) -><br />
(Signal Bool, Signal Bool)<br />
fullAdd(carryIn, (a,b)) = (sum,carryOut)<br />
where<br />
(sum1, carryOut1) = halfAdd(a,b)<br />
(sum, carryOut2) = halfAdd(carryIn,sum1)<br />
carryOut = xor2(carryOut1,carryOut2)<br />
Auch hier wird wieder die 1-zu-1 Übersetzung des Schaltbildes <strong>in</strong> <strong>Lava</strong><br />
sichbar.<br />
• Nachdem wir nun die Voraussetzung für die Addition von mehreren Bits mit dem<br />
Volladdierer geschaffen haben, können wir nun e<strong>in</strong>e Schaltung beschreiben, die<br />
e<strong>in</strong> Bit zu e<strong>in</strong>er ganzen Liste von Bits addiert und die resultierende Liste und<br />
e<strong>in</strong>en eventuellen Überlauf zurückgibt. Die Liste könnte hierbei als B<strong>in</strong>ärzahl<br />
gesehen werden, wobei anders als bei der üblichen Schreibweise das<br />
niederwertigste Bit am Anfang steht:<br />
bitAdder :: (Signal Bool, [Signal Bool]) -><br />
([Signal Bool], Signal Bool)<br />
bitAdder(carryIn, []) = ([], carryIn)<br />
bitAdder(carryIn, a:as) = (sum : sums, carryOut)<br />
where<br />
(sum, carry) = halfAdd(carryIn, a)<br />
(sums, carryOut) = bitAdder(carry, as)<br />
Das besondere bei dieser <strong>Lava</strong>funktion ist, dass dies ke<strong>in</strong>e Beschreibung für<br />
e<strong>in</strong>e Schaltung ist, sondern e<strong>in</strong>e Beschreibung für e<strong>in</strong>e ganze Gruppe<br />
Schaltungen. Durch die Rekursion <strong>in</strong> der Funktion über die Liste vom E<strong>in</strong>gang<br />
wird erst durch die Belegung des Parameters entschieden wie groß die<br />
Schaltung se<strong>in</strong> wird. Dabei wird die Rekursion verwendet um e<strong>in</strong> Muster zu<br />
beschreiben. Dadurch entsteht e<strong>in</strong>e Rekursion über Raum bzw. über die<br />
Struktur der Schaltung.<br />
• Mit diesem Vorwissen können wir jetzt relativ e<strong>in</strong>fach e<strong>in</strong>en kompletten<br />
Addierer erstellen. Dieser erhält als E<strong>in</strong>gabe 2 gleichlange Listen mit b<strong>in</strong>är<br />
Zahlen (wie oben erwähnt <strong>in</strong> umgekehrter Reihenfolge) und e<strong>in</strong>en evtl. Überlauf<br />
von e<strong>in</strong>er früheren Addition. Die beiden Zahlen werden mit Hilfe des ripple-carry<br />
Schemas addiert. Dadruch entsteht zwar der Nachteil, dass die Zahlen<br />
gleichlang se<strong>in</strong> müssen. Dies ist aber öftmals beim Hardwaredesign gegeben<br />
(zum Beispiel bei e<strong>in</strong>em PC s<strong>in</strong>d die Zahlen meißt 32bit oder 64bit lang) oder<br />
die folgende Implementierung ließe sich relativ e<strong>in</strong>fach erweitern:<br />
adder :: (Signal Bool, ([Signal Bool],[Signal Bool])) -><br />
([Signal Bool], Signal Bool)<br />
adder(carryIn, ([], [])) = ([], carryIn)<br />
adder(carryIn, (a:as, b:bs)) = (sum : sums, carryOut)<br />
where<br />
Seite 3/7
(sum, carry) = fullAdd(carryIn, (a, b))<br />
(sums, carryOut) = adder(carry, (as, bs))<br />
Ähnlich wie dieser Addierer könnte mit diesem Rekursionsschema auch e<strong>in</strong>e<br />
Struktur zur Subtraktion oder Multiplikation erstellt werden.<br />
Gerade <strong>in</strong> den letzten beiden Beispielen wurde deutlich, dass viele Schaltungen<br />
ähnliche Strukturen verwenden. Um diese zusammen zufassen liefert <strong>Lava</strong><br />
polymorphe (also für alle Typen def<strong>in</strong>ierte) Verb<strong>in</strong>dungsfunktionen. Die e<strong>in</strong>fachsten<br />
Verb<strong>in</strong>dungen s<strong>in</strong>d parallele und serielle Schaltungen. Diese könnte man zwar auch<br />
ohne die Funktionen die <strong>Lava</strong> bietet realisieren, allerd<strong>in</strong>gs ist es möglich, dass<br />
Hardwarehersteller (wie Xil<strong>in</strong>x Inc.) diese Funktionen so auf ihre Produkte anpassen,<br />
dass präferenzen über die Platzierung von den Schaltungsteilen e<strong>in</strong>gehalten werden.<br />
Damit kann beispielsweise die Effizienz von den Schlatungen verbessert werden.<br />
Bei der seriellen Verb<strong>in</strong>dung werden 2 e<strong>in</strong>zelne Schaltungen so verbunden, dass der<br />
Ausgang der ersten an den E<strong>in</strong>gang der zweiten Schaltung geleitet werden. Dies<br />
funktioniert mit dieser Funktion für alle Schaltungen die <strong>in</strong> dieser Form<br />
zusammenpassen (also der Ausgang der ersten das gleiche Format wie der E<strong>in</strong>gang<br />
der zweiten hat):<br />
(->-) :: (a -> b) -> (b -> c) -> (a -> c)<br />
(f ->- g) a = c<br />
where<br />
b = f a<br />
c = g b<br />
Die parallele Verb<strong>in</strong>dung verknüpft die Schaltungen so, dass aus 2 Schaltungen e<strong>in</strong>e<br />
Schaltung wird, die gleichzeitig die E<strong>in</strong>gäng der ersten und der zweiten aufnimmt und<br />
die Ausgänge beider Schaltungen zusammen zurückgibt.<br />
(-|-) :: (a -> c) -> (b -> d) -> ((a, b) -> (c, d))<br />
(f -|- g) (a, b) = (c, d)<br />
where<br />
c = f a<br />
d = g b<br />
Weiterführend zu diesen e<strong>in</strong>fachen Verb<strong>in</strong>dungen kann man e<strong>in</strong>e Verb<strong>in</strong>dung<br />
def<strong>in</strong>ieren, die e<strong>in</strong>e Schaltung mehrfach h<strong>in</strong>tere<strong>in</strong>ander hängt, die E<strong>in</strong>gänge und die<br />
Ausgängen zusammenfasst und e<strong>in</strong>en speziellen Ausgang immer an e<strong>in</strong>en speziellen<br />
E<strong>in</strong>gang von der nächsten Schaltung weiterreicht. Diese "Zeile" (analog wäre auch<br />
e<strong>in</strong>e Spalte möglich) könnte wiefolgt aussehen:<br />
row :: ((c, a) -> (b, c)) -> (c, [a]) -> ([b], c)<br />
row f (carryIn, []) = ([], carryIn)<br />
row f (carryIn, a:as) = (b:bs, carryOut)<br />
where<br />
(b, carry) = f (carryIn, a)<br />
(bs, carryOut) = row f (carry, as)<br />
Diese Struktur ermöglicht es jetzt die Def<strong>in</strong>ition von BitAddierer oder Addierer stark zu<br />
vere<strong>in</strong>fachen 3 :<br />
bitAdder = row halfAdd<br />
adder' = row fullAdd<br />
3: Die Signatur von adder' ist nicht exakt identisch mit der von adder: Es wird ke<strong>in</strong><br />
Tupel von 2 Listen übergeben sondern e<strong>in</strong>en Liste mit Tupeln von je 2 Werten.<br />
Seite 4/7
Schaltwerke<br />
Schaltwerke s<strong>in</strong>d ähnlich wie Schaltnetze boolsche Formeln. Allerd<strong>in</strong>gs enthalten sie<br />
elektronische Bauelemente die ihren Zustand speichern können. Diese Verzögerungen<br />
(oder auch Register) sorgen dafür, dass der Zustand an den Ausgängen nicht mehr nur<br />
von den E<strong>in</strong>gängen abhängt sondern auch noch von dem Verlauf der E<strong>in</strong>gänge.<br />
Diese Verzögerung heißt <strong>in</strong> <strong>Lava</strong> delay und gibt beim ersten Aufruf den Wert des<br />
ersten Parameters zurück und <strong>in</strong> allen folgenden immer den Wert den der zweite<br />
Parameter beim vorherigen Aufruf hatte.<br />
E<strong>in</strong>e e<strong>in</strong>fache Anwendung e<strong>in</strong>er solchen Verzögerung ist e<strong>in</strong> Wechseler. Sobald der<br />
e<strong>in</strong>e E<strong>in</strong>gang e<strong>in</strong> High-Signal erhält, wechselt wer den Zustand von se<strong>in</strong>em Ausgang:<br />
toggle :: Signal Bool -> Signal Bool<br />
toggle change = out<br />
where<br />
out' = delay low out<br />
out = xor2(change, out')<br />
Das besondere an dieser Def<strong>in</strong>ition ist, dass beide Werte <strong>in</strong> dem where-Statement<br />
vone<strong>in</strong>ander abhängen. Dies ist normalerweise <strong>in</strong> e<strong>in</strong>er <strong>Lava</strong>-Schaltung nicht möglich.<br />
Allerd<strong>in</strong>gs ist dies bei der Verwendung von delay essentiell und wird dafür mittels<br />
observable shar<strong>in</strong>g realisiert.<br />
Die delay Funktion, die von <strong>Lava</strong> bereit gestellt wird, ist universell überladen und kann<br />
Bits, Tupel von Bits, Listen von Bits und andere Komb<strong>in</strong>ationen speichern. Deshalb ist<br />
es damit auch möglich e<strong>in</strong>en Zähler zu realisieren:<br />
counter :: Int -> () -> [Signal Bool]<br />
counter n () = number<br />
where<br />
number' = delay (zeroList n) number<br />
(number, _) = bitAdder (high, number')<br />
Dieser Zählerbauste<strong>in</strong> (ohne E<strong>in</strong>gang) addiert bei jedem Aufruf auf e<strong>in</strong>en <strong>in</strong>ternen<br />
Zähler e<strong>in</strong>s und gibt dann den Wert zurück. Der Parameter n gibt dabei nur an wie<br />
viele Bits für den Zähler verwendet werden sollen.<br />
Simulation<br />
<strong>Lava</strong>schaltungen können ganz e<strong>in</strong>fach simuliert werden. Dazu kann man e<strong>in</strong>fach<br />
simulate verwenden. Diesem übergibt man e<strong>in</strong>fach die <strong>Lava</strong>-Schaltung und die<br />
entsprechenden Werte für die E<strong>in</strong>gänge:<br />
> simulate halfAdd (high, high)<br />
(low,high)<br />
Möchte man mehrer E<strong>in</strong>gangsbelegungen gleichzeitig überprüfen (ist für Schaltwerke<br />
zw<strong>in</strong>gend erforderlich) verwendet man e<strong>in</strong>fach simulateSeq dem man e<strong>in</strong>e <strong>Lava</strong>-<br />
Schaltung und e<strong>in</strong>e Liste von entsprechenden Werten für die E<strong>in</strong>gänge übergibt:<br />
> simulateSeq toggle [low, high, low, low, high, high, low]<br />
[low,high,high,high,low,high,high]<br />
Seite 5/7
Verifikation<br />
Da man nun aber nicht für jede Schaltung alle E<strong>in</strong>gangsbelegungen (bei Schaltwerken<br />
sogar alle Folgen von Belegungen) durchprobieren möchte um zu überprüfen ob e<strong>in</strong>e<br />
Aussage wahr oder falsch ist, bietet <strong>Lava</strong> an die Schaltung an e<strong>in</strong> externes<br />
Verifikationstool zu übergeben. Dazu muss man zuerst e<strong>in</strong>e Funktion schreiben, die die<br />
Eigenschaft der Schaltung beschreibt, die man überprüfen möchte:<br />
prop_HalfAddOutputNeverBothHigh :: (Signal Bool, Signal Bool) -> Signal Bool<br />
prop_HalfAddOutputNeverBothHigh (a,b) = ok<br />
where<br />
(sum, carryOut) = halfAdd(a,b)<br />
ok<br />
= nand2(sum, carryOut)<br />
Diese Beschreibung sieht selbst aus wie e<strong>in</strong>e Schaltung und gibt High zurück wenn die<br />
zu überprüfende Eigenschaft zutrifft. (Hier wird beispielsweise überprüft ob bei e<strong>in</strong>em<br />
Halbaddierer die beiden Ausgänge niemals zusammen High se<strong>in</strong> können.)<br />
Wenn man jetzt dem Aufruf des Verifikationstools diese Eigenschaftsdef<strong>in</strong>ition<br />
übergibt kann dieses überprüfen ob diese Eigenschaft immer erfüllt ist:<br />
> smv prop_HalfAddOutputNeverBothHigh<br />
Smv:...Valid.<br />
Dabei ist wichtig, dass die Verifikation nicht daraus besteht alle Varianten durch zu<br />
probieren. Sondern die Schaltung wird <strong>in</strong> e<strong>in</strong>en mathematischen Ausdruck<br />
umgewandelt und dann von dem externen Tool überprüft. So kann sowohl die<br />
Wahrheit als auch der Gegenbeweis relativ schnell festgestellt werden. Versucht man<br />
den oberen Beweis, statt mit dem Halbaddierer mit dem Volladdierer durchzuführen,<br />
ergibt dies folgendes:<br />
> smv prop_FullAddOutputNeverBothHigh<br />
Smv:...Falsifiable.<br />
E<strong>in</strong>en Spezialfall bei der Verifikation stellen die <strong>Lava</strong>def<strong>in</strong>itionen dar, die als Parameter<br />
e<strong>in</strong>e Liste erwarten. Bei diesen Def<strong>in</strong>itionen wird erst durch die konkrete Belegung der<br />
E<strong>in</strong>gänge entscheiden was für e<strong>in</strong>e Schaltung entsteht. Daher ist e<strong>in</strong>e e<strong>in</strong>fach<br />
Def<strong>in</strong>ition der Eigenschaft wie folgt nicht ausreichend:<br />
prop_AdderCommutative :: ([Signal Bool], [Signal Bool]) -><br />
Signal Bool<br />
prop_AdderCommutative (a,b) = ok<br />
where<br />
out1 = adder(a,b)<br />
out2 = adder(b,a)<br />
ok = out1 out2<br />
Bei dieser Def<strong>in</strong>ition ist noch völlig offen wie groß die E<strong>in</strong>gabewerte s<strong>in</strong>d und welche<br />
Schaltung entsteht. Damit man diese Schaltung aber zum<strong>in</strong>dest für e<strong>in</strong>e bestimmte<br />
Größe testen kann, kann man e<strong>in</strong>e Hilfsfunktion def<strong>in</strong>ieren:<br />
prop_AdderCommutative_ForSize :: Int -> Property<br />
prop_AdderCommutative_ForSize n =<br />
forAll (list n) $ \as -><br />
forAll (list n) $ \bs -><br />
prop_AdderCommutative (as, bs)<br />
Seite 6/7
Mit dieser Funktion ist es möglich für e<strong>in</strong>e E<strong>in</strong>gabelänge n die oben def<strong>in</strong>ierte<br />
Eigenschaft zu überprüfen:<br />
> smv (prop_AdderCommutative_ForSize 32)<br />
Smv:...Valid.<br />
Fazit<br />
Mit <strong>Lava</strong> ist es e<strong>in</strong>fach und schnell möglich Hardware zu designen. Durch die e<strong>in</strong>fach<br />
Möglichkeit die Schaltungen danach zu Simulieren und zu verifizieren bietet sich <strong>Lava</strong><br />
als das optimale Tool zur Entwicklung von Schaltungen an. Leider ist es <strong>in</strong> letzter Zeit<br />
um die Entwicklung von <strong>Lava</strong> relativ ruhig gewurden. Das mag daran liegen, dass die<br />
Installation von Haskell und den erforderlichen Tools für die meißten<br />
Hardwaredesigner nicht ohne weiteres erschlossen werden kann und diese lieber zu<br />
komerziellen Lösungen <strong>in</strong> VHDL und Verilog greifen.<br />
Ich f<strong>in</strong>de <strong>Lava</strong> bietet e<strong>in</strong>e gute Möglichkeit mit relativ wenig Erfahrung e<strong>in</strong>fach<br />
Schaltungen Schritt für Schritt aufzubauen und würde es begrüßen wenn die<br />
Entwicklung von <strong>Lava</strong> nicht ganz untergeht damit man auch <strong>in</strong> Zukunft <strong>Lava</strong> noch für<br />
das Design von Hardware e<strong>in</strong>setzen kann.<br />
Seite 7/7