zahl-Integer-Arithmetik-Bibliothek in VHDL

Werbung
Universität Rostock
Fachbereich Elektrotechnik und Informationstechnik
Institut für Angewandte
Mikroelektronik und Datentechnik
Großer Beleg
Entwicklung und Implementierung einer Langzahl-Integer-Arithmetik-Bibliothek in VHDL
Bearbeiter:
cand. ing. Mathias Schmalisch
Betreuer:
Dipl.-Ing. Hagen Ploog
Institut für Angewandte Mikroelektronik und Datentechnik
Richard-Wagner-Str. 31
18119 Warnemünde
U N I V E R S I T Ä T RO S T O C K
FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK
Institut für Angewandte Mikroelektronik und Datentechnik
Studienarbeit
für cand. ing. Mathias Schmalisch
Entwicklung und Implementierung einer Langzahl-Integer-Arithmetik-Bibliothek in VHDL
Zur funktionalen Verifikation unterschiedlicher Implementierungen von Architekturen werden diese in
einer VHDL-Testumgebung mit Stimuli beaufschlagt. Üblicherweise werden diese Stimuli direkt in
der Testumgebung erzeugt. Probleme treten dann auf, wenn das Erzeugen der Stimuli aus gegebenen
Gründen nicht mit den Mitteln der Testumgebung erfolgen kann.
Einen solchen Grund stellt die Verwendung von Langzahl-Integer-Arithmetik dar, da VHDL nur
Wortbreiten bis 32 Bit unterstützt.
Ziel der Studienarbeit ist es, eine Bibliothek in VHDL zu entwickeln, die Funktionen zum Bearbeiten
von langen Zahlen bereitstellt. Neben der üblichen Arithmetik sind Funktionen zur Erzeugung von
Schlüsselpaaren, wie sie beim RSA-Verfahren eingesetzt werden, zu realisieren.
Die nach außen sichtbaren Funktionen der Bibliothek sollen für Zahlen im reinem Binärformat als
auch für im Zweier-Komplement vorliegende Zahlen realisiert werden.
Die Bibliothek ist auf Ausführungsgeschwindigkeit zu optimieren.
Folgende Aufgaben sind dabei zu lösen:
•
•
•
•
Einarbeitung in die Theorie der langen Zahlen
Realisierungsvorschläge und Bewertung
Nachweis der Funktionalität durch C-Cross-Simulation
Simulation der VHDL-Quellen
Betreuer: Dipl.-Ing. H. Ploog
Tag der Ausgabe:
Tag der Abgabe:
19.10.1998
29. 1.1999
Prof. Dr. D. Timmermann
Betreuender Hochschullehrer
Inst. für Angewandte Mikroelektronik
und Datentechnik
Seite 2
KURZREFERAT
Aufgabe dieses Beleges ist die Entwicklung einer simulationsfähigen Langzahl-Integer-Arithmetik-Bibliothek in VHDL. Um der Komplexität dieser Aufgabe Rechnung
zu tragen, reichen die aufgeführten Themen von der Einführung in die Zahlentheorie bis zum
Aufzeigen möglicher Implementierungen einzelner Funktionen.
Einen wichtigen Aspekt stellen dabei die kryptographischen Funktionen dar, die ebenfalls in der VHDL-Bibliothek zu realisieren sind. Da es mit ihnen dann möglich ist, in Hardware realisierte Funktionalitäten mit dieser Bibliothek zu simulieren. Dabei wird vor allem
Wert darauf gelegt, Funktionen zur Erzeugung von Schlüsselpaare für den RSA-Algorithmus
zu entwickeln.
Vervollständigt wird die Arbeit durch die Beschreibung und Benutzung des
C-Interfaces des Synopsys-Simulators, wodurch die Simulationszeit meßbar wird, und so die
schnellste Implementierung ausgewählt werden kann.
Zum Schluß soll noch gezeigt werden, wie die Bitbreite der Ziffern in der Zahlendarstellung mit der benötigten Rechenzeit für einige Funktionen zusammenhängt.
Alle Quellen sowie die Dokumentationen zu den einzelnen Funktionen sind im Anhang enthalten.
Seite 3
INHALTSVERZEICHNIS
Abkürzungsverzeichnis ........................................................................................... 7
Abbildungsverzeichnis ............................................................................................ 8
Tabellenverzeichnis ................................................................................................. 9
Motivation................................................................................................................ 10
1
Theorie der Langzahlarithmetik................................................................. 11
1.1
1.2
1.2.1
1.2.2
1.2.3
Zahlendarstellung.................................................................................................................... 11
Darstellung vorzeichenbehafteter Zahlen ............................................................................... 12
Betrags-/Vorzeichendarstellung.................................................................................................... 12
Komplementdarstellung ................................................................................................................ 13
Wahl einer geeigneten Darstellung............................................................................................... 13
1.3
1.4
1.5
Einstellung des Basiswertes für die Ziffern............................................................................. 14
Darstellung von Zahlen in der VHDL-Bibliothek ..................................................................... 14
Hierarchischer Aufbau der Bibliothek...................................................................................... 14
2
Logische Funktionen.................................................................................. 15
3
Mathematische Grundfunktionen.............................................................. 16
3.1
3.2
3.3
3.4
Addition ................................................................................................................................... 16
Subtraktion .............................................................................................................................. 16
Multiplikation ........................................................................................................................... 17
Division.................................................................................................................................... 17
4
Vergleichsfunktionen ................................................................................. 19
4.1
4.2
4.3
4.4
4.5
4.6
Die "kleiner als" Funktion ........................................................................................................ 19
Die "kleiner gleich" Funktion ................................................................................................... 19
Die "größer als" Funktion ........................................................................................................ 20
Die "größer gleich" Funktion ................................................................................................... 20
Die "gleich" Funktion ............................................................................................................... 20
Die "ungleich" Funktion ........................................................................................................... 20
5
Zusätzliche Funktionen.............................................................................. 21
5.1
5.1.1
5.1.2
Schiebeoperationen ................................................................................................................ 21
Links Schieben............................................................................................................................... 21
Rechts Schieben............................................................................................................................. 21
5.2
Konvertierungsfunktionen ....................................................................................................... 21
6
Kryptographische Funktionen................................................................... 23
6.1
6.2
6.3
6.4
6.4.1
Potenzierung ........................................................................................................................... 23
Remainder............................................................................................................................... 24
Modulo .................................................................................................................................... 24
Erzeugung von Zufallszahlen.................................................................................................. 24
Eigenschaften eines guten Zufallszahlengenerators...................................................................... 25
Seite 4
6.4.2
6.4.3
6.4.4
6.4.5
Lineare-Kongruenz Generatoren .................................................................................................. 26
Tausworthe Generatoren............................................................................................................... 27
Erweiterte Fibonacci Generatoren ............................................................................................... 29
Kombinierte Generatoren ............................................................................................................. 30
6.5
6.6
6.6.1
6.6.2
6.6.3
Euler-Phi Funktion................................................................................................................... 31
Primzahltests........................................................................................................................... 31
Fermat Test ................................................................................................................................... 32
Solovay-Strassen Test.................................................................................................................... 32
Miller-Rabin Test .......................................................................................................................... 33
6.7
6.8
6.9
6.9.1
6.9.2
6.9.3
6.9.4
Größter gemeinsamer Teiler................................................................................................... 34
Erweiterter euklidischer Algorithmus....................................................................................... 34
Der RSA-Algorithmus.............................................................................................................. 35
Erzeugen von RSA-Schlüsselpaaren.............................................................................................. 35
RSA-Verschlüsselung .................................................................................................................... 36
RSA-Entschlüsslung ...................................................................................................................... 36
RSA Beispiel .................................................................................................................................. 37
7
Geschwindigkeitsmessung mit dem C-Interface ..................................... 38
7.1
7.1.1
7.1.2
7.1.3
7.1.4
Benutzung des C-Interfaces ................................................................................................... 38
Die Verbindung zum C-Code ........................................................................................................ 38
Der C-Code ................................................................................................................................... 39
Die Komponente............................................................................................................................ 41
Compilieren und Linken ................................................................................................................ 42
7.2
Beschreibung der Meßfunktion ............................................................................................... 42
8
Überprüfung der Bibliothek ....................................................................... 44
9
Testergebnisse ........................................................................................... 45
9.1
9.2
9.3
Testergebnisse bei konstanter Vektorbreite ........................................................................... 45
Testergebnisse bei konstanter Ziffernbreite ........................................................................... 47
Optimierung nach Ermittlung von Meßergebnissen................................................................ 48
10
Zusammenfassung ..................................................................................... 50
Literaturverzeichnis ............................................................................................... 51
Anhang .................................................................................................................... 52
A
A1
A1.1
A1.2
A1.3
A1.4
A2
A1.1
A1.2
A1.3
A1.4
Die VHDL-Bibliothek ............................................................................................................... 52
Enthaltene Funktionen ...................................................................................................................... 52
Logische Funktionen ..................................................................................................................... 52
Mathematische und Vergleichsfunktionen .................................................................................... 52
Krytographische Funktionen ......................................................................................................... 55
Zusätzliche Funktionen ................................................................................................................. 55
VHDL-Quellen .................................................................................................................................. 57
Datei: mp_logic.vhd ...................................................................................................................... 57
Datei: mp_arith.vhd....................................................................................................................... 64
Datei: mp_std_logic.vhd ............................................................................................................... 79
Datei: mp_crypt.vhd...................................................................................................................... 82
Seite 5
B
B1
B1.1
B1.2
B1.3
B1.4
B2
B2.1
B2.2
B2.3
B2.4
Die Quellen für das C-Interfaces............................................................................................. 90
Das Addiererbeispiel......................................................................................................................... 90
Datei: adder.vhd ............................................................................................................................ 90
Datei: adder_comp.vhd ................................................................................................................. 90
Datei: adder.h ................................................................................................................................ 90
Datei: adder.c ................................................................................................................................ 90
Die Meßfunktion................................................................................................................................ 92
Datei: benchmark.vhd ................................................................................................................... 92
Datei: benchmark_comp.vhd......................................................................................................... 92
Datei: Benchmark.h....................................................................................................................... 92
Datei: Benchmark.c....................................................................................................................... 92
Seite 6
ABKÜRZUNGSVERZEICHNIS
CLI
C-Language Interface
DES
Data Encryption Standard
GCD
Greatest Common Divisor
IEEE
Institute of Electrical and Electronics Engineers
MPA
Multiple-Precision Arithmetic
RSA
Rivest Shamir Adleman
VHDL
VHSIC Hardware Description Language
VHSIC
Very High Speed Integrated Circuit
Seite 7
ABBILDUNGSVERZEICHNIS
Abbildung 1.1: Fließkommadarstellung................................................................................... 11
Abbildung 1.2: Hierarchischer Aufbau am Beispiel einer Addiererfunktion .......................... 14
Abbildung 6.1: Die Periode eines Zufallszahlengenerators ..................................................... 26
Abbildung 6.2: Implementation eines Zufallszahlengenerators mit Schieberegistern............. 28
Abbildung 6.3: Schieberegisterimplementation eines Zufallszahlengenerators ...................... 29
Abbildung 6.4: Der RSA-Algorithmus .................................................................................... 35
Abbildung 9.1: Durchschnittszeiten für die Addition, Subtraktion und Multiplikation .......... 47
Abbildung 9.2: Rechenzeiten bei konstanter Ziffernbreite ...................................................... 48
Seite 8
TABELLENVERZEICHNIS
Tabelle 1.1: Parameter für die Basisformate ............................................................................ 11
Tabelle 1.2: Bezeichnungen für einige Basiswerte .................................................................. 12
Tabelle 1.3: Vergleich zwischen Vorzeichen- und Zweierkomplementdarstellung ................ 13
Tabelle 5.1: Konvertierungsfunktionen.................................................................................... 22
Tabelle 5.2: Konvertierungsfunktionen mit Längenänderung ................................................. 22
Tabelle 6.1: Vergleich zwischen Remainder und Modulo....................................................... 24
Tabelle 7.1: Parameter für das Eingangssignal-Attribut .......................................................... 39
Tabelle 8.1: Programmparameter für "mpa" ............................................................................ 44
Tabelle 9.1: Testergebnisse bei konstanter Vektorbreite ......................................................... 46
Tabelle 9.2: Testergebnisse bei konstanter Ziffernbreite ......................................................... 47
Tabelle 9.3: Vergleich zweier verschiedener Addiererimplementationen ............................... 49
Seite 9
MOTIVATION
Um Architekturen, die in VHDL entwickelt wurden, zu verifizieren, werden diese in dem
VHDL-Simulator von Synopsys mit Stimuli beaufschlagt. Normalerweise werden diese Stimuli direkt im VHDL-Simulator mit Hilfe einer Testbench erzeugt. Es gibt allerdings Probleme, wenn die Stimuli mit Hilfe der standardmäßigen VHDL-Bibliotheken nicht erzeugt
werden kann, weil diese Bibliotheken nicht ausreichend Funktionalitäten bereitstellen. So
fehlt zum Beispiel in den IEEE-Bibliotheken eine Funktion zur Division von Bitvektoren.
Daher ist es notwendig gewesen, eine Bibliothek in VHDL zu entwickeln, die alle nötigen Funktionalitäten aufweist und auch mit sehr großen Zahlen rechnen kann. Neben der üblichen Arithmetik sollten auch noch Funktionen zur Erzeugung von Schlüsselpaaren für den
RSA-Algorithmus entwickelt werden.
Besonderer Wert wurde dabei auf die Optimierung der Funktionen auf Ausführungsgeschwindigkeit gelegt. Daher war es notwendig das C-Interface des Synopsys
VHDL-Simultors zur Messung der Rechenzeit zu benutzen, da in VHDL die Rechenzeit sonst
nicht meßbar ist.
Seite 10
1 THEORIE DER LANGZAHLARITHMETIK
Die gebräuchlichste Form, zur Darstellung von großen Zahlen auf dem Computer und auch in
Taschenrechnern, ist die der Fließkommadarstellung. Für die Darstellung von Fließkommazahlen gibt es verschiedene Formen [1]. Die heute üblichste, entspricht dem 1985 verabschiedeten IEEE-Standard (Institute of Electrical and Electronics Engineers).
Charakteristik C
Mantisse M
Vorzeichen v der Fließkommazahl
Abbildung 1.1: Fließkommadarstellung
Wie in Abbildung 1.1 zu sehen ist, besteht die Fließkommazahl aus der Charakteristik C, der
Mantisse M und dem Vorzeichen v. Dabei wird die Charakteristik C aus dem Exponenten E
durch Addition einer geeigneten Konstante K gebildet, so daß für die Charakteristik nur positive Werte auftreten. So kann dann eine Zahl A mit der Basis B dargestellt werden.
A = (− 1) ⋅ M ⋅ B E
v
mit E = C - K
(1.1)
Der IEEE-Standard gibt zwei Basisformate vor, läßt aber auch weitere zu. Die Tabelle 1.1
enthält die Parameter für das einfach- und doppeltgenaue Basisformat.
Parameter
einfachgenau
doppeltgenau
Wortlänge in Bits
32
64
maximaler Exponent Emax
+127
+1023
minimaler Exponent Emin
-127
-1022
Konstante K
+127
+1023
Anzahl Bits des Exponenten
8
11
Anzahl Bits der Mantisse
24
53
Tabelle 1.1: Parameter für die Basisformate
In einigen Fällen, wie z.B. in der Kryptographie, ist es allerdings notwendig mit sehr großen
Zahlen zu rechnen, die bis auf die letzte Stelle vor dem Komma genau sein müssen. Dafür ist
die Fließkommaarithmetik nicht mehr zu gebrauchen, da die Genauigkeit auf die Anzahl Stellen der Mantisse begrenzt ist. Deshalb wird eine anderer Art der Arithmetik benötigt, die sogenannte Langzahlarithmetik. Bei dieser werden alle Stellen vor dem Komma gespeichert, um
so die nötige Genauigkeit zu gewährleisten.
1.1 Zahlendarstellung
Eine beliebige positive natürliche Zahl A mit der Basis r, die aus n Ziffern besteht, kann folgendermaßen dargestellt werden:
Seite 11
A = a n −1 a n −2 ⋅ ⋅ ⋅ a1 a 0
(1.2)
Wobei ai eine Ziffer mit 0 ≤ ai < r ist. In Tabelle 1.2 werden einmal einige Bezeichnungen für
häufig verwendete Basiswerte aufgezeigt.
Basis r =
Bezeichnung
2
binär
3
ternär
8
octal
10
dezimal
16
hexadezimal
Tabelle 1.2: Bezeichnungen für einige Basiswerte
Beim Stellenwertverfahren ergibt sich der Zahlenwert V(A) aus der Summe der Produkte des
Ziffernwerts und des Stellenwerts:
n −1
V ( A) = ∑ ai r i
(1.3)
i =0
So kann eine beliebige Zahl im Bereich von 0 ≤ V(A) < rn dargestellt werden.
1.2 Darstellung vorzeichenbehafteter Zahlen
Negative Zahlen können auf verschiedene Weise dargestellt werden. Zwei der am häufigsten
verwendeten Methoden sind:
• Betrags-/Vorzeichendarstellung (sign magnitude)
• Komplementdarstellung
Diese werden im folgenden Abschnitt etwas genauer behandelt.
1.2.1 Betrags-/Vorzeichendarstellung
Bei der Betrags-/Vorzeichendarstellung (sign magnitude) wird eine zusätzliche Ziffer eingefügt, die sogenannte Vorzeichenziffer, diese dient als Zeiger für positive bzw. negative Zahlen. Das Vorzeichen wird dabei folgendermaßen dargestellt:
• 0 = positive
• (r-1) = negativ
Somit wird eine n-stellige positive bzw. negative Zahl wie folgt dargestellt:
ASM = 0 a n − 2 a n −3 ⋅ ⋅ ⋅ a1 a 0
− ASM = (r − 1) an−2 an−3 ⋅ ⋅ ⋅ a1 a0
(für eine n-stellige positive Zahl)
(1.4)
(für eine n-stellige negative Zahl)
(1.5)
Mit dieser Darstellungsform können Zahlen im Bereich -rn-1 < V(A) < rn-1 dargestellt werden.
Wobei sich der Zahlenwert folgendermaßen berechnen läßt:
n −2
V ( ASM ) = (− 1) n −1 ⋅ ∑ ai r i
a
(1.6)
i =0
Seite 12
Der Wertebereich ist bei der Betrags-/Vorzeichendarstellung vollkommen symmetrisch und
somit die Null existiert doppelt, einmal positiv und einmal negativ. Der große Nachteil dieser
Darstellung liegt darin, daß man positive und negative Zahlen gesondert behandeln muß. Die
Tabelle 1.3 zeigt die binäre Betrags-/Vorzeichendarstellung von Zahlen im Bereich [-7,7].
1.2.2 Komplementdarstellung
Bei der Komplementdarstellung gibt es zwei unterschiedliche Arten, die Einer- bzw. Zweierkomplementdarstellung. Die Einerkomplementdarstellung (allg. (r-1)-Komplement) hat die
gleichen Vor- und Nachteile wie die Betrags-/Vorzeichendarstellung, daher soll diese Methode hier nicht weiter behandelt werden. Bei der Zweierkomplementdarstellung (allg.
r-Komplement) sieht das schon anders aus, sie hat den großen Vorteil, daß positive und negative Zahlen bei der Addition und Subtraktion nicht gesondert behandelt werden müssen. Die
Darstellung positiver bzw. negativer Zahlen im Zweierkomplement sieht folgendermaßen aus:
AZK = 0 an−2 an−3 ⋅ ⋅ ⋅ a1 a0
− AZK = ( ( r − 1) a n −2 a n −3 ⋅ ⋅ ⋅ a1 a 0 ) + 1
(für eine n-stellige positive Zahl)
(1.7)
(für eine n-stellige negative Zahl)
(1.8)
Wobei mit ai = r − 1 − ai gemeint ist. So können Zahlen im Bereich -rn-1 ≤ V(A) < rn-1
dargestellt werden, wobei sich der Zahlenwert wie folgt berechnet:
n −2
V ( AZK ) = − a n −1 ⋅ r n −1 + ∑ ai r i
(1.9)
i =0
Ein weiterer Vorteil dieser Form der Zahlendarstellung ist der, daß die Null nur einmal existiert, da dies keine symmetrische Darstellung ist. Die Tabelle 1.3 zeigt die binäre Zweierkomplementdarstellung von Zahlen im Bereich [-8,7].
Sequenz Vorzeichendar- ZweierkomSequenz Vorzeichendar- Zweierkomstellung
plement
stellung
plement
0111
7
7
1111
-7
-1
0110
6
6
1110
-6
-2
0101
5
5
1101
-5
-3
0100
4
4
1100
-4
-4
0011
3
3
1011
-3
-5
0010
2
2
1010
-2
-6
0001
1
1
1001
-1
-7
0000
0
0
1000
-0
-8
Tabelle 1.3: Vergleich zwischen Vorzeichen- und Zweierkomplementdarstellung
1.2.3 Wahl einer geeigneten Darstellung
Nachdem nun die einzelnen Darstellungsmethoden für negative Zahlen, sowie ihre Vor- und
Nachteile vorgestellt wurden, ist die Wahl einer geeigneten Darstellungsform leicht zu begründen. Da die VHDL-Bibliothek auf die Ausführungsgeschwindigkeit optimiert werden
soll, fällt die Wahl auf die Zweierkomplementdarstellung. Denn damit kann die Addition oder
Seite 13
Subtraktion positiver und negativer Zahlen mit ein- und derselben Funktion berechnet werden.
1.3 Einstellung des Basiswertes für die Ziffern
Um die VHDL-Bibliothek möglichst variabel zu gestalten, ist es möglich, die Anzahl Bits für
jede Ziffer mit Hilfe der Konstanten "digit_size" in er Bibliothek einzustellen. Allerdings ist
diese Einstellung vor der Compilierung der Bibliothek vorzunehmen. Somit ergibt sich dann
eine Basis von r = 2digit_size, die für die ganze Bibliothek gilt.
1.4 Darstellung von Zahlen in der VHDL-Bibliothek
Um in VHDL mit Zahlen in Langzahlarithmetik Format arbeiten zu können, war es notwendig neue Zahlentypen zu erstellen. Dies sind die Typen:
• udigit_vector
• digit_vector
Dabei ist der Typ "udigit_vector" für Berechnungen ausschließlich mit positiven Zahlen gedacht, daher auch das "u" am Anfang, welches hier für unsign (positiv) steht. Der Typ
"digit_vector" ist für Berechnungen im positiven und negativen Bereich gedacht, wobei die
negative Zahlen im Zweierkomplement dargestellt werden.
1.5 Hierarchischer Aufbau der Bibliothek
Um den Aufbau der Bibliothek möglichst einfach zu gestalten, wurde eine Hierarchie, wie sie
in Abbildung 1.2 am Beispiel einer Addiererfunktion zu sehen ist, eingeführt. Durch dieses
Konzept, kann ein und die selbe Addiererfunktion mit verschiedenen Zahlentypen genutzt
werden. Denn durch die vorgeschalteten Konvertierungsfunktionen werden aus zwei unterschiedlichen Zahlentypen zwei "digit_vector"-Zahlen gemacht. Da die Addition zwei Zahlen
der selben Länge benötigt, wird durch die Konvertierungsfunktion gleichzeitig noch die Länge der beiden Zahlen angepaßt.
Falls eine Verbesserung für die Addiererfunktion gefunden wurde, braucht nur eine
Funktion ausgetauscht zu werden, da diese durch die vorhergehenden Konvertierungsfunktionen von den unterschiedlichen Zahlentypen entkoppelt ist. Damit ist eine leichte Wartung der
VHDL-Bibliothek gewährleistet. Andere arithmetische Funktionen können nach dem selben
Prinzip aufgebaut werden, dabei können dann auch die selben Konvertierungsfunktionen eingesetzt werden. Wenn dann bei einer Funktion noch eine neuer Zahlentyp benötigt werden
sollte, ist nur eine neue Konvertierungsfunktion zu entwickeln.
a
b
conv_digit_vector
conv_digit_vector
addition
Ergebnis
Abbildung 1.2: Hierarchischer Aufbau am Beispiel einer Addiererfunktion
Seite 14
2 LOGISCHE FUNKTIONEN
Da VHDL aus dem Bereich der Hardwareentwicklung kommt, wo häufig logische Verknüpfungen von zwei Werten vorgenommen werden, dürfen die logischen Funktionen in einer
vollständigen VHDL-Bibliothek nicht fehlen. Diese Funktionen können allerdings nur angewendet werden, wenn die Zahlen binär darstellbar sind, deshalb muß die Basis r einen Potenz
von 2 sein (r = 2x). Als Beispiel für die logischen Funktionen wird in Algorithmus 2.1 einmal
die AND-Verknüpfung für Zahlen in Langzahlarithmetik vorgestellt. Dazu werden zwei Zahlen gleicher Länge ziffernweise AND-verknüpft.
Algorithmus 2.1: AND
EINGABE: Zwei natürliche Zahle x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die logische AND-Verknüpfung von x und y.
1. Für i in n bis 0 mache folgendes:
1.1. result = xi AND yi.
2. Gebe (result) zurück.
Dieser Algorithmus kann auch für viele andere logische Verknüpfungen genutzt werden, dazu
zählen die NAND-, OR-, NOR-, XOR- und XNOR-Verknüpfung. Es muß jeweils nur der
Schritt 1.1. an die entsprechende logische Funktion angepaßt werden. Für die
XNOR-Verknüpfung gibt es in den VHDL-Standardbibliotheken keine Funktion, daher wird
ein abgewandelter Algorithmus verwendet, welcher in Algorithmus 2.2 dargestellt ist, um
eine XNOR-Funktion auch in der Langzahlarithmetikbibliothek zu realisieren.
Algorithmus 2.2: XNOR
EINGABE: Zwei natürliche Zahle x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die logische AND-Verknüpfung von x und y.
1. Für i in n bis 0 mache folgendes:
1.1. result = NOT (xi XOR yi).
2. Gebe (result) zurück.
Eine weiterr Besonderheit stellt die NOT-Verknüpfung oder auch Invertierung dar, da diese
nur auf eine Zahl angewendet wird. Deshalb wird diese auch in Algorithmus 2.3 vorgestellt.
Algorithmus 2.3: NOT
EINGABE: Eine natürliche Zahle x, mit n+1 Ziffern der Basis r.
AUSGABE: Die Invertierung von x.
1. Für i in n bis 0 mache folgendes:
1.1. result = NOT xi.
2. Gebe (result) zurück.
Seite 15
3 MATHEMATISCHE GRUNDFUNKTIONEN
In diesem Kapitel werden mögliche Implementierungen für die vier Grundrechenarten Addition, Subtraktion, Multiplikation und Division vorgestellt.
3.1 Addition
Die Addition wird auf zwei natürliche Zahlen mit der selben Anzahl Ziffern der Basis r ausgeführt. Um zwei natürliche Zahlen mit verschiedener Länge zu addieren, muß die kürzere zuerst mit Nullen auf der linken Seite aufgefüllt werden.
Algorithmus 3.1: Addition
EINGABE: Zwei positive natürliche Zahlen x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die Summe x + y = (wn+1wn ⋅⋅⋅ w1w0)r.
1. c ← 0 (c ist die Überlaufziffer (carry digit)).
2. Für i von 0 bis n mache folgendes:
2.1. wi ← (xi + yi + c) mod r.
2.2. Wenn (xi + yi + c) < r dann c ← 0, ansonsten c ← 1.
3. wn+1 ← c.
4. Gebe (wnwn-1 ⋅⋅⋅ w1w0) zurück.
Wenn man die Basis r günstig wählt, kann (xi + yi + c) mod r schneller berechnet werden. Die
Wahl für die Basis wurde schon in Kapitel 1.3 beschreiben, dadurch lassen sich die Schritte
2.1. und 2.2. durch folgende ersetzen:
2.1. t ← (xi + yi + c).
2.2. wi ← t((digit_size -1) downto 0) und c ← t(digit_size).
Dabei ist die Variable t (digit_size + 1) Bits lang, die unteren Bits werden dann der aktuellen
Summenziffer wi zugewiesen und das oberste Bit wird an die Überlaufziffer c weitergegeben.
Durch diese Konstruktion fällt die Modulo- und Vergleichsoperation weg, und das Ergebnis
kann so in VHDL schneller berechnet werden.
Mit diesem Algorithmus ist es auch möglich negative Zahlen zu addieren. Allerdings
müssen diese, wenn sie kürzer als die zweite Zahl sind, mit (r-1) auf der linken Seite aufgefüllt werden.
3.2 Subtraktion
Auch die Subtraktion wird auf zwei Zahlen gleicher Länge ausgeführt. Wenn die Zahlen unterschiedlich lang sind, müssen sie wie schon bei der Addition beschrieben, auf der linken
Seite verlängert werden.
Algorithmus 3.2: Subtraktion
EINGABE: Zwei Zahlen x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die Differenz x - y = (wn+1wn ⋅⋅⋅ w1w0)r.
1. c ← 1.
.
2. yv ← y
3. Für i von 0 bis n mache folgendes:
3.1. wi ← (xi + yvi + c) mod r.
Seite 16
3.2. Wenn (xvi + yvi + c) < b dann c ← 0, ansonsten c ← 1.
4. wn+1 ← c.
5. Gebe (wn+1wn ⋅⋅⋅ w1w0) zurück.
Auch hier können die Schritte 3.1. und 3.2., wie schon bei der Addition beschrieben ersetzt
werden, wenn die Basis r eine Potenz von 2 ist. Dieser Algorithmus ist der Addition sehr ähnlich, allerdings wird hier durch die Schritte 1. und 2. die Zahl y negiert. Der Schritt 2. kann in
VHDL durch einen einfache Invertierung ersetzt werden. Somit benötigt die Subtraktion nur
einen minimalen Rechenaufwand mehr als die Addition.
3.3 Multiplikation
Die Multiplikation kann auf zwei natürliche Zahlen x und y unterschiedlicher Länge mit der
Basis r angewendet werden, mit x = (xnxn-1 ⋅⋅⋅ x1x0)r und y = (ytyt-1 ⋅⋅⋅ y1y0)r. Das Produkt von
x ⋅ y hat dann (n + t + 2) Ziffern der Basis r.
Algorithmus 3.3: Multiplikation
EINGABE: Zwei positive Zahlen x und y, mit n + 1 und t + 1 Ziffern der Basis r.
AUSGABE: Das Produkt x ⋅ y = (wn+t+1 ⋅⋅⋅ w1w0)r.
1. Für i von 0 bis (n + t + 1) mache: wi ← 0.
2. Für i von 0 bis t mache folgendes:
2.1. c ← 0.
2.2. Für j von 0 bis n mache folgendes:
Berechne (uv)r = wi+j + xj ⋅ yi + c, und setze wi+j ← v, c ← u.
2.3. wi+n+1 ← u.
3. Gebe (wn+t+1 ⋅⋅⋅ w1w0) zurück.
Der Algorithmus 3.3 ist eine abgewandelte Form der Papier und Bleistiftmethode (paper and
pencil method), wie sie in der Schule gelehrt wird.
Allerdings kann dieser Algorithmus nicht für negative Zahlen angewendet werden, dazu sind einige Veränderungen nötig. Zum Anfang sind die Absolutwerte von x und y zu ermitteln, dann kann der Algorithmus 3.3 angewendet werden. Und zu Schluß muß noch überprüft werden, ob einen Zahl positiv und die andere negativ war, denn dann ist das Ergebnis
noch zu negieren, bevor es zurückgegeben werden kann.
3.4 Division
Die Division ist die am schwierigsten zu realisierende Operation unter den vier Grundrechenarten. Algorithmus 3.4 berechnet den Quotienten q und den Rest z in der Basis r, wenn x
durch y geteilt wird.
Algorithmus 3.4: Division für Langzahlarithmetik
EINGABE: Positive Zahlen x = (xn ⋅⋅⋅ x1x0)r und y = (yt ⋅⋅⋅ y1y0)r, mit n ≥ t ≥ 1, yt ≠ 0.
AUSGABE: Der Quotient q = (qn-t ⋅⋅⋅ q1q0)r und der Rest z = (zt ⋅⋅⋅ z1z0)r, so daß
x = qy + z, 0 ≤ z < y.
1. Für j von 0 bis (n - t) mache: qj ← 0.
2. Solange (x ≥ yrn-t) mache folgendes: qn-t ← qn-t + 1, x ← x - yrn-t.
3. Für i von n bis (t + 1) mache folgendes:
Seite 17
3.1. Wenn xi = yt dann setze qi-t-1 ← r – 1, ansonsten qi-t-1 ← (xir + xi-1) / yt.
3.2. Solange (qi-t-1(ytr + yt-1) > xir2 + xi-1r + xi-2) mache: qi-t-1 ← qi-t-1 – 1.
3.3. x ← x – qi-t-1yri-t-1.
3.4. Wenn x < 0 dann setze x ← x + yr i-t-1 und qi-t-1 ← qi-t-1 – 1.
4. z ← x.
5. Gebe (q, z) zurück.
Wie auf den ersten Blick zu sehen ist, benötigt dieser Algorithmus viele Rechenoperationen.
Des weiteren wird im Schritt 3.1. eine Division für die Ziffern benötigt, welche in den
VHDL-Standardbibliotheken nicht vorhanden ist. Daher wurde für die VHDL-Bibliothek eine
andere Implementierung gewählt, welche in Algorithmus 3.5 beschreiben ist. Dabei ist noch
zu erwähnen, daß x und y vorher in Bitvektoren umzuwandeln sind, bevor der folgende Algorithmus angewendet werden kann.
Algorithmus 3.5: Division in VHDL
EINGABE: Positive Zahlen x = (xn ⋅⋅⋅ x1x0) und y = (yt ⋅⋅⋅ y1y0) in Binärdarstellung,
mit n ≥ t, y ≠ 0.
AUSGABE: Der Quotient q = (qn ⋅⋅⋅ q1q0) und der Rest z = (zt ⋅⋅⋅ z1z0), so daß
x = qy + z, 0 ≤ z < y.
1. q ← 0, qw ← n + 1, z ← x.
2. Für i in 1 bis qw mache folgendes:
2.1. Wenn (z((qw – 1) downto (qw – i)) ≥ b) dann mache folgendes:
2.1.1. q(qw - i) ← 1.
2.1.2. Wenn (i ≤ t) berechne folgendes:
z((qw - 1) downto (qw - i))
= z((qw - 1) downto (qw - i)) – b((i - 1) downto 0),
ansonsten mache folgendes:
z((qw – i + t) downto (qw - i))
= z((qw – i + t) downto (qw - i)) – b((t - 1) downto 0).
3. Gebe (q, z) zurück.
Nachdem der Quotient q als Bitvektor vorliegt, ist dieser dann wieder in eine Basis r Darstellung zurück zu wandeln, bevor er für weitere Berechnungen verwendet werden kann. Der
Rest z der bei diesem Algorithmus ebenfalls anfällt, kann für andere Berechnungen genutzt
werden, so zum Beispiel für Modulo- oder Remainderalgorithmen.
Um diesen Algorithmus auch auf negative Zahlen anwenden zu können, müssen die
selben Modifikationen wie sie schon bei der Multiplikation beschrieben wurden vorgenommen werden.
Seite 18
4 VERGLEICHSFUNKTIONEN
Um die VHDL-Bibliothek für Langzahlarithmetik wie jede andere Bibliothek weiter verwenden zu können ist es nötig auch Vergleichsoperationen zu implementieren. Daher werden in
diesem Kapitel mögliche Implementierungen für die Vergleichsfunktionen vorgestellt.
4.1 Die "kleiner als" Funktion
Diese Funktion wird auf zwei positive natürliche Zahlen angewendet, die die selbe Anzahl
Ziffern mit der Basis r haben. Wenn die beiden Zahlen unterschiedlich lang sind, dann ist die
kürzere auf der linken Seite mit Nullen aufzufüllen.
Algorithmus 4.1: kleiner als ("<")
EINGABE: Zwei positive natürliche Zahlen x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die Antwort wahr oder falsch auf die Frage: Ist x kleiner als y ?
1. result ← falsch.
2. Für i von n bis 0 mache folgendes:
2.1. Wenn (xi ≠ yi) dann mache folgendes:
2.1.1. Wenn (xi < yi) dann setze result ← wahr, ansonsten result ← falsch.
2.1.2. Gebe (result) zurück.
3. Gebe (result) zurück.
Der Algorithmus 4.1 kann nicht ohne weiters auf positive und negative Zahlen angewendet
werden. Zuerst einmal ist ein kürzere negative Zahl auf der linken Seite mit (r - 1) aufzufüllen, damit die beiden Zahlen die selbe Länge haben. Dann ist das Vorzeichen zu überprüfen.
Wenn es unterschiedlich ist, kann dann schon festgelegt werden, welche Zahl die kleinere ist.
Bei gleichem Vorzeichen wird der Algorithmus 4.1 verwendet, um die kleinere Zahl zu ermitteln.
4.2 Die "kleiner gleich" Funktion
Dieser Algorithmus wird ebenfalls auf zwei natürliche Zahlen gleicher Länge angewendet.
Algorithmus 4.2: kleiner gleich ("≤")
EINGABE: Zwei positive natürliche Zahlen x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die Antwort wahr oder falsch auf die Frage: Ist x kleiner gleich y ?
1. result ← wahr.
2. Für i von n bis 0 mache folgendes:
2.1. Wenn (xi ≠ yi) dann mache folgendes:
2.1.1. Wenn (xi < yi) dann setze result ← wahr, ansonsten result ← falsch.
2.1.2. Gebe (result) zurück.
3. Gebe (result) zurück.
Der Algorithmus 4.2 unterschiedet sich zum Algorithmus 4.1 nur in Schritt 1., dort wird die
boolsche Variable result mit "wahr" vorgeladen. Wenn die Schleife in Schritt 2. dann ohne
einen vorzeitigen Abbruch durchlaufen wird, steht fest, daß x gleich y ist und so der Vergleich
"wahr" ist.
Auch bei diesem Algorithmus müssen die Modifikationen, wie sie im Abschnitt 4.1
beschrieben wurden, vorgenommen werden um negative Zahlen darauf anwenden zu können.
Seite 19
4.3 Die "größer als" Funktion
Für diese Funktion wird kein neuer Algorithmus benötigt, es kann der Algorithmus 4.1 angewendet werden. Allerdings sind vorher die beiden Zahlen x und y zu vertauschen.
4.4 Die "größer gleich" Funktion
Auch hier ist es nicht nötig einen neuen Algorithmus zu erstellen. Wenn die Zahlen x und y
vertauscht an den Algorithmus 4.2 übergeben werden, erhält man das richtige Ergebnis.
4.5 Die "gleich" Funktion
Diese Funktion wird auf zwei natürliche Zahlen gleicher Länge der Basis r angewendet.
Algorithmus 4.3: gleich ("=")
EINGABE: Zwei positive natürliche Zahlen x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die Antwort wahr oder falsch auf die Frage: Ist x gleich y ?
1. Für i von n bis 0 mache folgendes:
1.1. Wenn (xi ≠ yi) dann gebe (falsch) zurück.
2. Gebe (wahr) zurück.
Der Algorithmus 4.3 kann ohne weitere Veränderungen auf negative Zahlen angewendet werden, da durch die Schleife in Schritt 1. auch die Vorzeichenziffer abgetestet wird.
4.6 Die "ungleich" Funktion
Der Algorithmus 4.4 wird wieder auf zwei Zahlen gleicher Länge angewendet. Dabei ist es
egal ob die Zahlen positiv oder negativ sind.
Algorithmus 4.4: ungleich ("≠")
EINGABE: Zwei positive natürliche Zahlen x und y, jede mit n+1 Ziffern der Basis r.
AUSGABE: Die Antwort wahr oder falsch auf die Frage: Ist x ungleich y ?
1. Für i von n bis 0 mache folgendes:
1.1. Wenn (xi ≠ yi) dann gebe (wahr) zurück.
2. Gebe (falsch) zurück.
Wie zu sehen ist, sieht der Algorithmus 4.4 dem Algorithmus 4.3 sehr ähnlich. Es wurden nur
die Ergebnisse, welche zurückgegeben werden, vertauscht.
Seite 20
5 ZUSÄTZLICHE FUNKTIONEN
Um der Langzahlarithmetik-Bibliothek die volle Funktionalität einer Standart-Bibliothek, wie
zum Beispiel der IEEE-Bibliothek, zu geben, sind noch einige zusätzliche Funktionen nötig.
Diese sollen in diesem Kapitel behandelt werden.
5.1 Schiebeoperationen
5.1.1 Links Schieben
Hierbei wird eine Zahl a mit n + 1 Ziffern um b Ziffern nach links geschoben, wobei b eine
positive Zahl sein muß. Der Algorithmus dazu ist im folgenden dargestellt:
Algorithmus 5.1: Links schieben
EINGABE: a mit n + 1 Ziffern und b mit er Anzahl zu schiebender Ziffern.
AUSGABE: a um b Ziffern nach links geschoben.
1. Wenn (b ≤ n) dann mache folgendes:
1.1. x(n downto b) = a((n – b) downto 0).
1.2. x((b – 1) downto 0) = 0.
2. ansonsten mache folgendes:
2.1. x = 0
3. Gebe (x) zurück.
Wie in Algorithmus 5.1 zu sehen ist, wird als Ergebnis eine Null zurückgegeben, wenn b größer als n ist, da in diesem Fall alle Ziffern über das linke Ende hinausgeschoben wurden.
5.1.2 Rechts Schieben
Die Zahl a mit n + 1 Ziffern wird um b Ziffern nach rechts verschoben, wobei b eine positive
Zahl sein muß. Der Algorithmus dazu sieht folgendermaßen aus:
Algorithmus 5.2: Rechts schieben
EINGABE: a mit n + 1 Ziffern und b mit er Anzahl zu schiebender Ziffern.
AUSGABE: a um b Ziffern nach rechts geschoben.
1. Wenn (b ≤ n) dann mache folgendes:
1.1. x((n – b) downto 0) = a(n downto b).
1.2. x(n downto (n – b + 1)) = 0
2. ansonsten mache folgendes:
2.1. x = 0
3. Gebe (x) zurück.
Auch hier wird eine Null zurückgegeben, wenn alle Ziffern über das rechte Ende hinausgeschoben wurde.
5.2 Konvertierungsfunktionen
In VHDL gibt es verschiedene Darstellungsmöglichkeiten für Zahlen, daher werden Konvertierungsfunktionen benötigt, um auch diese Zahlenformate in der Langzahlarithmetik-Bibliothek verwenden zu können. Es gibt dabei zwei verschiedenen Arten von Konvertierungsfunktionen. Eine davon dient zum Umwandeln eines beliebigen Zahlenformates in "udiSeite 21
git_vector" oder "digit_vector", und wieder zurück in "std_logic_vector". Diese Konvertierungsfunktionen sind in Tabelle 5.1 dargestellt.
Kovertiertungsfunktion
To_DigitVector
To_UdigitVector
Konvertierung
von
in
std_logic_vector
digit_vector
std_ulogic_vector
udigit_vector
string
std_logic_vector
udigit_vector
std_ulogic_vector
digit_vector
string
Tabelle 5.1: Konvertierungsfunktionen
Dabei ist zu beachten, daß die Länge von "std_logic_vector" und "std_ulogic_vector" ein vielfaches der Konstanten "digit_size" sind, da sonst die obersten Bits in der höchstwertigsten
Zahl nicht definiert sind, und somit eine korrekte Arbeitsweise der darauffolgenden Funktionen nicht gewährleistet werden kann.
Eine Besonderheit sind dabei die Funktionen zum konvertieren eines Strings. Dabei
wird ein Zahl die hexadezimal in einem String dargestellt ist in einen "udigit_vector" oder
"digit_vector" umgewandelt.
Bei der zweiten Art von Konvertierungsfunktionen wird zusätzlich zur eigentlichen
Konvertierung noch die Anzahl Ziffern verändert. Diese Art wird benötigt, um zwei Zahlen
auf die selbe Länge zu bringen, bevor sie zum Beispiel mit der Addition verwendet werden
können.
Konvertierung
von
in
digit_vector
digit_vector
udigit_vector
integer
CONV_UDIGIT_VECTOR
udigit_vector
udigit_vector
digit_vector
integer
Tabelle 5.2: Konvertierungsfunktionen mit Längenänderung
Kovertiertungsfunktion
CONV_DIGIT_VECTOR
Die Besonderheit bei den in Tabelle 5.2 dargestellten Konvertierungsfunktionen ist, daß es
auch Funktionen zur Konvertierung von "digit_vector" in "digit_vector" und "udigit_vector"
in "udigit_vector" gibt, diese dienen eigentlich nur zur Änderung der Anzahl Ziffern einer
Zahl.
Seite 22
6 KRYPTOGRAPHISCHE FUNKTIONEN
Die zu entwickelnde VHDL-Bibliothek soll vor allem zur Simulation von kryptographischen
Routinen eingesetzt werden. Daher ist es notwendig einige Funktionen in die Bibliothek mit
aufzunehmen, die speziell für dieses Einsatzgebiet gedacht sind. In dem folgenden Kapitel
werden die Funktionen und ihre Realisierungsvorschläge vorgestellt und bewertet.
6.1 Potenzierung
Eine der wichtigsten Funktionen für die asymmetrische Kryptographie ist die Potenzierung,
daher ist sie auch die erste, die in diesem Abschnitt behandelt wird. Als Beispiel für die asymmetrische Kryptographie soll hier der RSA-Algorithmus dienen. Dieser wird in Abschnitt
6.9 genauer behandelt und wie dort zu sehen ist, wird die Potenzierung zur Ver- und Entschlüsselung benötigt. Der naivste Weg um ge zu berechnen währe e – 1 Multiplikationen mit
der Zahl g auszuführen. In der Kryptographie kann dieser Weg allerdings nicht angewendet
werden, da dort mit Zahlen bis zu 1024 Bit Länge gearbeitet wird, was 21024 – 2 Multiplikationen im ungünstigsten Fall bedeuten würde. Selbst wenn e nicht immer so groß ausfällt, so ist
es aber meist immer noch groß genug um diese Methode ineffizient zu machen. Daher ist es
notwendig die Anzahl Multiplikationen deutlich zu reduzieren. Die beiden folgenden Algorithmen sind für Zahlen in Binärdarstellung gedacht.
Algorithmus 6.1: Binäre Potenzierung von rechts nach links
EINGABE: Zwei Zahlen in Binärdarstellung g und e, mit e ≥ 0.
AUSGABE: Das Ergebnis von ge.
1. A ← 1, S ← g.
2. Solange (e ≠ 0) mache folgendes:
2.1. Wenn e ungerade ist dann A ← A ⋅ S.
2.2. e ← e / 2.
2.3. Wenn e ≠ 0 dann S ← S ⋅ S.
3. Gebe (A) zurück.
Wie in Algorithmus 6.1 zu sehen ist, werden im schlechtesten Fall pro Schleifendurchlauf
zwei Multiplikationen und ein Division, die allerdings durch die Binärdarstellung durch eine
Schiebeoperation ersetzt werden kann, benötigt. Wenn e eine Bitlänge von t + 1 hat, und wt(e)
die Anzahlen Einsen in der Binärdarstellung ist, dann werden bei diesem Algorithmus insgesamt t + wt(e) – 1 Multiplikationen gebraucht, um die Potenzierung auszuführen.
Algorithmus 6.2: Binäre Potenzierung von links nach rechts
EINGABE: Zwei Zahlen in Binärdarstellung g und e = (etet-1⋅⋅⋅e1e0)2, mit e ≥ 0.
AUSGABE: Das Ergebnis von ge.
1. A ← 1.
2. Für i von t bis 0 mache folgendes:
2.1. A ← A ⋅ A.
2.2.Wenn ei = 1, dann setze A ← A ⋅ g.
3. Gebe (A) zurück.
Auch in Algorithmus 6.2 werden in schlechtesten Fall zwei Multiplikationen pro Schleifendurchlauf benötigt. Für diesen Algorithmus werden insgesamt t + wt(e) Multiplikationen geSeite 23
braucht, das ist eine mehr als bei Algorithmus 6.1 allerdings fällt die Division bzw. Schiebeoperation weg. Daher ist dieser Algorithmus die bessere Wahl.
Bei die Potenzierung zweier relativ kleiner Zahlen kann eine Ergebnis entstehen, welches sehr groß ist, das kann in manchen Fällen zu Problem führen. Da die Exponential-Funktion in der asymmetrischen Kryptographie häufig in Verbindung mit der Modulo-Funktion eingesetzt wird, währe an dieser Stelle ein Einsatz der modularen Expansion von
Vorteil, da das Ergebnis dann nicht so groß ausfällt.
6.2 Remainder
Da in der Langzahlarithmetik nur mit ganzen Zahlen gerechnet wird, entsteht bei der Division
von einer Zahl a durch eine Zahl b außer dem Quotienten q auch noch ein Rest r, so daß:
a = qb + r
mit 0 ≤ r < b
(6.1)
Mit der Remainder-Funktion kann dieser Rest ermittelt werden. Er fällt als Nebenprodukt bei
der Division, wie sie in Kapitel 3.4 beschrieben ist, ab. Daher kann der gleiche Algorithmus
verwendet werden um den Rest zu ermitteln.
a rem b = r
(6.2)
Das Vorzeichen des Restes ist das gleiche wie das von a, somit hat b keinen Einfluß darauf.
6.3 Modulo
Die Modulo-Funktion arbeitet genau wie die Remainder-Funktion, solange a und b positiv
sind.
a mod b = r
(6.3)
Das Vorzeichen wird hier allerdings nicht von a, sondern von b bestimmt. Außerdem wird der
Quotient nicht durch Abschneiden der Nachkommastellen ermittelt, wie es bei Remainder der
Fall ist, sondern durch Abrunden zur nächsten ganzen Zahl, so daß bei negativem a oder b
andere Werte für r entstehen, damit die Gleichung (6.1) erfüllt wird. In Tabelle 6.1 erfolgt
einmal ein Vergleich zwischen Remainder und Modulo an einem Beispiel.
a
Rem 5
Mod 5
Rem -5
Mod -5
-9
-4
1
-4
-4
-8
-3
2
-3
-3
-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5
-2 -1 0 -4 -3 -2 -1 0 1 2 3 4 0
3 4 0 1 2 3 4 0 1 2 3 4 0
-2 -1 0 -4 -3 -2 -1 0 1 2 3 4 0
-2 -1 0 -4 -3 -2 -1 0 -4 -3 -2 -1 0
Tabelle 6.1: Vergleich zwischen Remainder und Modulo
6 7 8 9
1 2 3 4
1 2 3 4
1 2 3 4
-4 -3 -2 -1
6.4 Erzeugung von Zufallszahlen
Eine der Schlüsselfunktionen für die Simulation ist eine Routine zur Erzeugung von zufälligen Werten für Variablen mit einer spezifischen zufälligen Verteilung, z.B. exponentiell und
normal. Dies kann in zwei Schritten vollzogen werden. Zuerst wird eine Sequenz von zufälliSeite 24
gen Zahlen, gleichmäßig verteilt zwischen 0 und 1, benötigt. Dann wird diese Sequenz transformiert, um die zufälligen Werte mit der benötigten Verteilung zu erzeugen.
6.4.1 Eigenschaften eines guten Zufallszahlengenerators
Um zu verstehen, warum ein Zufallszahlengenerator besser ist als ein anderer, ist es erst einmal wichtig zu verstehen, wie ein solcher Generator funktioniert. Bei den gebräuchlichsten
Methoden wird eine rekursive Beziehung verwendet, in welcher die nächste Zahl der Sequenz
eine Funktion der letzten oder der letzten zwei Zahlen ist.
xn = f ( xn −1 , xn −2 , ...)
(6.4)
Eine solche Funktion ist:
x n = 5 x n −1 + 1 mod 16
(6.5)
Wenn mit x0 = 5 gestartet wird, erhält man x1 wie folgt:
x1 = 5(5) + 1 mod 16 = 26 mod 16 = 10
(6.6)
Die ersten 32 Zahlen die man mit dieser Prozedur erhält, sind 10, 3, 0, 1, 6, 15, 12, 13, 2, 11,
8, 9, 14, 7, 4, 5, 10, 3, 0, 1, 6, 15, 12, 13, 2, 11, 8, 9, 14, 7, 4, 5.
Wie zu sehen ist, sind dies natürliche Zahlen zwischen 0 und 15. Wenn diese dann
durch 16 dividiert werden, bekommt man eine Sequenz von zufälligen Zahlen zwischen 0 und
1. Für dieses Beispiel sind das die Zahlen 0,6250; 0,1875; 0,0000; 0,0625; 0,3750; 0,9375;
0,7500; 0,8125; 0,1250; 0,6875; 0,5000; 0,5625; 0,8750; 0,4375; 0,2500; 0,3125; 0,6250;
0,1875; 0,0000; 0,0625; 0,3750; 0,9375; 0,7500; 0,8125; 0,1250; 0,6875; 0,5000; 0,5625;
0,8750; 0,4375; 0,2500; 0,3125.
Es ist offensichtlich, daß wenn die Funktion ƒ bekannt ist, die Sequenz jeder Zeit regeneriert werden kann, vorausgesetzt der Startwert x0 ist gegeben. Dieser Wert, der benutzt
wird um die Sequenz zu beginnen, wird auch Saat genannt.
Eine wichtige Beobachtung bei diesem Beispiel ist, daß die Funktion ƒ deterministisch
ist. Denn mit einer vorgegebenen Saat kann mit einer Wahrscheinlichkeit von 1 gesagt werden, welche Zahlen in der Sequenz sind. Aber die Zahlen sind zufällig in dem Sinn, daß sie
einem statistischen Test auf Zufälligkeit bestehen würden. Diese Zahlen sind deshalb nur
teilweise zufällig, und werden daher auch pseudozufällig genannt. Solche Zahlen werden
aber für Simulationen eher bevorzugt, als völlig zufällige Zahlen, denn es ist oftmals notwendig ein Simulationsexperiment mit genau denselben Werten zu wiederholen. Wenn natürlich
verschiedene Ergebnisse benötigt werde, kann ja die Saat verändert werden, bevor die Simulation gestartet wird. So hat man zusätzlich Kontrolle über die Reproduzierbarkeit von Ergebnissen.
Wie man sieht sind in dem durchgeführten Beispiel nur die ersten 16 Zahlen einzigartig. Die 17. Zahl ist die gleiche, wie die erste und die folgende Sequenz ist einfach eine zyklische Wiederholung der ersten 16 Zahlen. In anderen Worten, der Zufallszahlengenerator hat
eine Zykluslänge von 16. Einige Generatoren wiederholen einen anfänglichen Teil der Sequenz nicht. Dieser Teil wird Schwanz genannt. In diesem Fall, besteht die Periode des Generators aus der Summe der Schwanzlänge und der Zykluslänge, wie es in Abbildung 6.1 gezeigt wird.
Seite 25
Saat
Schwanz
Zykluslänge
Periode
Abbildung 6.1: Die Periode eines Zufallszahlengenerators
Die nötigen Eigenschaften einer guten Generatorfunktion sind folgende:
1. Die Funktion sollte gut berechenbar sein. Für typische Simulationen werden einige tausend Zufallszahlen benötigt. Daher sollte die Prozessorzeit, die vergeht während diese
Zahlen erzeugt werden, kurz sein.
2. Die Periode sollte lang sein. Eine kurze Periode würde bedeuten, daß sich die Zufallszahlen schnell wiederholen. Damit würde die nutzbare Länge für eine Simulation begrenzt
sein.
3. Die aufeinanderfolgenden Werte sollten unabhängig voneinander und gleichmäßig verteilt sein. Die Korrelation zwischen aufeinanderfolgenden Zahlen sollte klein sein. Denn
eine signifikante Korrelation gibt Hinweise auf Abhängigkeiten.
Während die ersten beiden Eigenschaften leicht zu überprüfen sind, benötigt man für die Dritte entsprechende Tests. Im Folgenden sind einige Typen von Zufallszahlengeneratoren aufgezählt, welche in diesem Abschnitt behandelt werden:
•
•
•
Lineare-Kongruenz Generatoren
• Tausworthe Generatoren
Erweiterte Fibonacci Generatoren
Kombinierte Generatoren
Eine Beschreibung jedes Typen folgt.
6.4.2 Lineare-Kongruenz Generatoren
1951 entdeckte D. H. Lehmer, daß der Rest aufeinanderfolgender Potenzen einer Zahl gute
zufällige Eigenschaften hat. Er bekam die n-te Zahl in einer Sequenz mittels dividieren der
n-ten Potenz einer ganzen Zahl a durch eine andere ganze Zahl m und verwenden des Restes.
x n = a n mod m
(6.7)
Um xn nach xn-1 zu berechnen, gibt es einen äquivalenten Ausdruck:
x n = a x n −1 mod m
(6.8)
Seite 26
Die Parameter a und m werden jeweils Multiplikator und Modulus genannt. Lehmer wählte
für diese Parameter a = 23 und m = 108 + 1. Damit wurde die Implementierung auf ENIAC,
einer achtstelligen dezimalen Maschine, sehr einfach.
Viele der heute gebräuchlichen Zufallszahlengeneratoren sind Verallgemeinerungen
der Vorschläge von Lehmer und haben folgende Form:
x n = a x n −1 + b mod m
(6.9)
Dabei ist xn eine ganze Zahl zwischen 0 und m – 1, und die Konstanten a und b sind positiv.
Im allgemeinen hat die Wahl von a, b und m Einfluß auf die Periode und Autokorrelation der Sequenz. Viele Wissenschaftler haben diese Generatoren studiert und die Ergebnisse
ihrer Untersuchungen können folgendermaßen zusammengefaßt werden:
1. Der Modulus m sollte groß sein. Denn alle Werte von x liegen zwischen 0 und m – 1,
die Periode kann niemals größer als m sein.
2. Um die (mod m) Berechnung schnell ausführen zu können, sollte m eine Potenz von 2
sein (m = 2k). In diesem Fall erhält man das Ergebnis, indem man die niederen k Bits
verwendet und die höherwertigen Bits abschneidet.
3. Wenn b nicht Null ist, dann erhält man die maximale Periode nur wenn:
a) die natürlichen Zahlen m und b relativ prim zueinander sind. Das heißt, sie haben
keine gemeinsamen Faktoren außer 1.
b) jede Primzahl die ein Faktor von m ist, auch ein Faktor von a – 1 ist.
c) a – 1 ein Vielfaches von 4 ist, dann ist m ebenfalls ein Vielfaches von 4.
All diese Bedingungen werden erfüllt, wenn m = 2k, a = 4c + 1 und b ungerade ist. Wobei c, b
und k natürliche Zahlen sind.
Ein Generator, der die maximal mögliche Periode hat, wird auch Vollperiode Generator genannt. Alle Vollperiode Generatoren sind aber nicht gleich gut. Generatoren mit niedriger Autokorrelation zwischen aufeinanderfolgenden Zahlen sind vorzuziehen. Zum Beispiel
haben die beiden folgenden Generatoren die gleiche volle Periode, aber der erste hat eine Korrelation von 0,25 zwischen xn-1 und xn, wobei der zweite eine viel geringere Korrelation von
2-18 hat:
xn = (2 34 + 1) xn −1 + 1 mod 2 35
(6.10)
x n = (218 + 1) x n −1 + 1 mod 2 35
(6.11)
6.4.3 Tausworthe Generatoren
Das Interesse an Zufallszahlengeneratoren entstand vor kurzem infolge des Aufkommens der
Kryptographie, denn dort werden Zufallszahlen mit großer Länge benötigt. Zum Beispiel wird
eine 64-Byte (512-Βit) lange Zahl benötigt, um eine Nachricht zu Verschlüsseln. Solche langen Zahlen werden produziert unter Benutzung von zufälligen Sequenzen binärer Zahlen
(0 oder 1), die in die benötigte Länge unterteilt werden. Solche Generatoren wurden zum ersten mal von Tausworthe (1965) vorgeschlagen und tragen deshalb seinen Namen.
Im allgemeinen hat ein Tausworthe Generator folgenden Form:
Seite 27
bn = c q −1bn −1 ⊗ c q −2 bn −2 ⊗ c q −3bn −3 ⊗ ⋅ ⋅ ⋅ ⊗ c0 bn −q
(6.12)
wobei ci und bi binäre Variablen mit Werten von 0 oder 1 sind und ⊗ ist die XOR Operation.
Der Generator verwendet die letzten q Bits der Sequenz. Deshalb wird diese auch autoregresisve Sequenze der Ordnung q genannt oder auch AR(q). Ein AR(q) Generator kann eine maximale Periode von 2q – 1 haben.
Wenn man mit D einen Verzögerungsoperator andeutete, so daß Db(n) = b(n + 1) ist,
dann kann die Gleichung (6.12) folgendermaßen geschrieben werden:
D q b(i − q ) = cq −1 D q −1b(i − q ) + cq − 2 D q − 2 b(i − q ) + ⋅ ⋅ ⋅ + c0 b(i − q ) mod 2
(6.13)
D q − c q −1 D q −1 − c q −2 D q −2 − ⋅ ⋅ ⋅ − c0 = mod 2
(6.14)
oder
In der binären Architektur ist die Subtraktion äquivalent zur Addition, damit ist die vorhergehende Gleichung äquivalent zu:
D q + c q −1 D q −1 + c q − 2 D q − 2 + ⋅ ⋅ ⋅ + c0 = mod 2
(6.15)
Das Polynom auf der linken Seite dieser Gleichung wird auch charakteristisches Polynom
genannt und wird normalerweise folgendermaßen geschrieben, wobei das D durch ein x ersetzt wird:
x q + c q −1 x q −1 + c q − 2 x q −2 + ⋅ ⋅ ⋅ + c0
(6.16)
Die Periode eines Tausworthe Generators ist von charakteristischen Polynom abhängig. In der
Praxis ist die Periode, die kleinste positive natürliche Zahl n, für welche xn – 1 durch das charakteristische Polynom teilbar ist. Die maximal mögliche Periode mit einem Polynom der
Ordnung q ist 2q – 1. Das Polynom, welches diese Periode ergibt wird auch einfaches Polynom genannt.
bn
bn-1
bn-2
bn-3
bn-4
bn-5
Ausgabe
Abbildung 6.2: Implementation eines Zufallszahlengenerators mit Schieberegistern
Eine Tausworthe Sequenz kann in Hardware einfach realisiert werden, im dem man Schieberegister verwendet. Als Beispiel wurde das Polynom:
x5 + x3 + 1
(6.17)
in Abbildung 6.2 realisiert. Wenn der D Operator für das x eingesetzt wir, erhält man folgende Formel zur Erzeugung einer Bitsequenz:
Seite 28
D 5b(n ) + D 3b(n ) + b( n ) = 0 mod 2
(6.18)
bn +5 + bn +3 + bn = 0 mod 2
(6.19)
oder
Wird der XOR Operator als Modulo 2 Addition verwendet, erhält man folgende Gleichung:
bn +5 ⊗ bn + 3 ⊗ bn = 0
(6.20)
bn +5 = bn +3 ⊗ bn
(6.21)
oder
Jetzt wird n mit n – 5 Substituiert:
bn = bn −2 ⊗ bn −5
(6.22)
So erhält man aus dem Polynom in Gleichung (6.17) die Funktion, welche in Abbildung 6.2
realisiert wurde. Dort sind sechs Register, welche jeweils ein Bit enthalten. Bei jedem Takt
werden die Register um eins weiter geschoben.
In Abbildung 6.3 ist der Kreislauf eines allgemeinen Tausworthe Generators dargestellt, wie er in Gleichung (6.12) beschrieben wurde.
...
cn-1
&
cn-2
cn-q+1
&
&
AND
bn
bn-1
bn-2
...
bn-q+1
bn-q
Ausgabe
Abbildung 6.3: Schieberegisterimplementation eines Zufallszahlengenerators
In der Praxis kann die AND Funktion weggelassen werden, wenn ci konstant ist. Wenn ci = 1
ist, dann fällt die AND Funktion weg. Bei ci = 0 fällt zusätzlich auch noch die entsprechende
XOR Funktion weg.
6.4.4 Erweiterte Fibonacci Generatoren
Eine Fibonacci Sequenz {xn} wird durch folgende Beziehung generiert:
x n = x n −1 + x n − 2
(6.23)
Ein Zufallszahlengenerator kann durch folgende Modifikationen der Fibonacci Sequenz erzeugt werden:
Seite 29
x n = x n −1 + x n −2 mod m
(6.24)
Jedoch hat diese Sequenz keine guten zufälligen Eigenschaften. In der Praxis hat sie eine große serielle Korrelation. Eine Erweiterung dieser Methode währe zum Beispiel eine Kombination des fünften und siebzehnten Vorgängers:
x n = x n −5 + x n −17 mod 2 k
(6.25)
Marsaglia (1983) zeigte, daß dieser Generator die meisten statistischen Test besteht und empfahl eine Implementierung wie folgt mit 17 Speicherstellen L[1], ... , L[17]. Während der Initialisierung werden diese Speicherstellen mit 17 natürlichen Zahlen gefüllt, wobei nicht alle
gerade sein dürfen. Dann werden die beiden Zeiger i und j jeweils auf 5 und 17 gesetzt. Bei
jedem Aufruf wird der folgende Algorithmus ausgeführt, welcher die nächste Zufallszahl zurückgibt und die Zeiger neu berechnet:
Algorithmus 6.3: Erweiterter Fibonacci Generator
AUSGABE: Die Zufallszahl x.
1. x = L[i] + L[j] mod 2k.
2. L[i] = x.
3. i = i – 1, wenn i = 0 dann setze i ← 17.
4. j = j – 1, wenn j = 0 dann setze j ← 17.
5. Gebe (x) zurück.
Bei der Addition in der erste Zeile dieses Generators kann die Modulooperation weggelassen
werden, wenn der Algorithmus in einer k-Bit begrenzten Zweierkomplement Berechnung
eingesetzt wird. Die Periode dieses Generators ist 2k(217 – 1). Für k = 8, 16 und 32 ist diese
Periode jeweils 1,6 ⋅ 107; 4,3 ⋅ 109 und 2,8 ⋅ 1014. Diese ist bedeutend länger, als die eines Linearen-Kongruenz Generators.
6.4.5 Kombinierte Generatoren
Es ist möglich zwei oder mehr Zufallszahlengeneratoren zu kombinieren um einen besseren
Generator zu erhalten. Dafür gibt es drei Techniken die im folgenden beschrieben werden:
1. Addition von Zufallszahlen, die aus zwei oder mehr Generatoren erhalten wurden. Wenn
xn und yn zwei Zufallszahlsequenzen im Bereich von 0 bis m – 1 sind, dann können sie
kombiniert werden, um wn = (xn + yn) mod m zu erhalten. Wenn die beiden Sequenzen unterschiedliche Perioden haben und auf verschiedenen Algorithmen beruhen, dann wird die
Periode und die Zufälligkeit erheblich erhöht. Als Beispiel empfahl L'Ecuyer (1988) die
Kombination der folgenden zwei Generatoren:
x n = 40014 x n −1 mod 2 ⋅147 ⋅ 483⋅563
(6.26)
y n = 40692 y n −1 mod 2 ⋅147⋅ 483⋅399
(6.27)
Damit entsteht folgender Generator:
Seite 30
wn = ( x n − y n ) mod 2 ⋅147 ⋅ 483⋅562
(6.28)
Dieser Generator hat eine Periode von 2,3 ⋅ 1012.
2. XOR Verknüpfung von Zufallszahlen, die aus zwei oder mehr Generatoren erhalten wurden. Diese Technik ist mit der vorherigen ähnlich, hierbei wird die Addition durch eine
bitweise XOR Verknüpfung ersetzt. Santha und Vazirani (1984) zeigten, daß die XOR
Verknüpfung von einigen einfachen Zufallszahlengeneratoren, wobei jeder eine n-Bit
Zahl erzeugt, benutzt werden kann, um eine zufälligere Sequenz zu produzieren.
3. Mischen. Bei dieser Technik wird eine Sequenz als Index benutzt, um zu entscheiden,
welche Zahl einer zweiten Sequenz zurückgeben wird. Viele verschiedene Mischalgorithmen sind in der Literatur zu finden. Eine populäre Technik, welche man Marsaglia und
Bray (1964) anrechnen muß, ist auch als Algorithmus M bekannt. Wobei eine Feld der
Größe 100 zum Beispiel mit Zufallszahlen einer Sequenz xn gefüllt wird. Um Zufallszahlen zu erzeugen, wird eine neue Sequenz yn (zwischen 0 und m – 1) generiert und skaliert
um einen Index i = 1 + 100yn / m zu erhalten. Der Wert im i-ten Element des Feldes wird
als nächste Zufallszahl zurückgegeben. Dann wird ein neuer Wert xn generiert und an die
i-te Stelle im Feld gespeichert.
6.5 Euler-Phi Funktion
Die Euler-Phi Funktion ϕ(n) gibt die Anzahl der natürlichen Zahlen im Intervall von 1 bis n
an, welche zu n relative prim sind. Wenn die Zahl n eine Primzahl ist, dann ist:
ϕ ( n) = n − 1
(6.29)
Die Euler-Phi Funktion ist multiplikativ. Wenn zwei Zahlen m und n relativ prim zueinander
sind, daß heißt der größte gemeinsame Teiler ist 1, dann ist:
ϕ ( mn ) = ϕ ( m ) ⋅ ϕ ( n )
(6.30)
Um die Euler-Phi Funktion einer natürlichen Zahl n zu bestimmen, wobei n keine Primzahl
ist, ist vorher eine Primfaktorzerlegung von n vorzunehmen.
n = p1e1 p 2e2 ⋅ ⋅ ⋅ pkek

ϕ ( n ) = n 1 −

Primfaktoren von n
1 
1  
1 
 1 −  ⋅ ⋅ ⋅ 1 − 
p1  
p2  
pk 
(6.31)
(6.32)
6.6 Primzahltests
Für einige kryptographische Algorithmen werden große Primzahlen benötigt, z.B. für das
RSA-Verfahren. Die Bedeutung von Primzahlen für die Kryptographie liegt in der Tatsache
begründet, daß es schwierig und zeitaufwendig ist, Zahlen, die aus großen Primzahlen bestehen, zu faktorisieren. Daher werden in diesem Abschnitt die bekanntesten Primzahlentests
vorgestellt.
Seite 31
6.6.1 Fermat Test
Dieser Algorithmus beruht auf dem kleinen Fermatschen Satz (nach Pierre Fermat,
1601-1655) und ist auch in [4] und [5] nachzulesen. Der Satz besagt, daß für jede Primzahl n
und jede natürliche Zahl a mit 1 ≤ a ≤ n-1 gilt:
a n −1 ≡ 1 ( mod n )
(6.33)
Somit erhält man dann folgenden Primzahltest für n:
Algorithmus 6.4: Der Fermat Primzahltest
FERMAT(n, t)
EINGABE: Eine ungerade natürliche Zahl n ≥ 3 und einen Sicherheitsparameter t ≥ 1.
AUSGABE: Die Antwort "prim" oder "zusammengesetzt" auf die Frage: "Ist n prim?"
1. Für i von 1 bis t mache folgendes:
1.1. Wähle eine zufällige Zahl a, mit 1 ≤ a ≤ n – 1.
1.2. Berechne r = an-1 mod n.
1.3. Wenn r ≠ 1, dann gebe ("zusammengesetzt") zurück.
2. Gebe ("prim") zurück.
Allerdings kann man nach diesem Test nicht sicher sein, daß n eine Primzahl ist, denn es gibt
zusammengesetzte Zahlen n, die die Gleichung (6.33) für alle zu n teilerfremden ganzen Zahlen a erfüllen. Diese heißen Carmichael-Zahlen. Diese Zahlen können mit Hilfe probabilistischer Tests, wie etwa des Solovay-Strassen oder Miller-Rabin Tests mit beliebiger Wahrscheinlichkeit ausgeschlossen werden.
6.6.2 Solovay-Strassen Test
Dieser probabilistische Test geht auf die Entwickler Robert Solovay und Volker Strassen zurück, nachzulesen in [2]. Dieser Test war der erste Primzahltest, der mit dem Aufkommen der
asymmetrischen Kryptographie bekannt wurde. Allerdings wird dieser Test normalerweise
nicht mehr verwendet, denn es gibt inzwischen eine bessere Alternative, den Miller-Rabin
Test. Trotzdem sollte dieser Primzahltest nicht unerwähnt bleiben, denn er fand einige Zeit
lang Verwendung.
Der Solovay-Strassen Test basiert auf dem Eulerschen Kriterium, das folgendes besagt. Wenn n eine Primzahl ist, dann gilt:
a
a (n −1) / 2 ≡   ( mod n )
n
(6.34)
für alle natürlichen Zahlen a mit 1 ≤ a ≤ n-1 und mit dem größten gemeinsamen Teiler von 1
für a und n. Dabei ist mit  an  das Jacobisymbol gemeint, das wie folgt berechnet wird:
Algorithmus 6.5: Berechnung des Jacobisymbols
JACOBI(a, n)
EINGABE: Eine ungerade natürliche Zahl n ≥ 3,
und eine natürliche Zahl a, mit 0 ≤ a < n.
a
AUSGABE: Das Jacobisymbol  n  .
1. Wenn a = 0 dann gebe (0) zurück.
Seite 32
2. Wenn a = 1 dann gebe (1) zurück.
3. Berechne a1 und e so, daß a = 2ea1, wobei a1 ungerade ist.
4. Wenn e gerade ist, dann setze s ← 1. Andernfalls setze s ← 1,
wenn n ≡ 1 oder 7 (mod 8), oder setze s ← –1, wenn n ≡ 3 oder 5 (mod 8).
5. Wenn n ≡ 3 (mod 4) und a1 ≡ 3 (mod 4), dann setze s ← -s.
6. Setze n1 ← n mod a1.
7. Gebe (s ⋅ JACOBI(n1, a1)) zurück.
Mit dem Jacobisymbol ist dann der Solovay-Strassen Test durchführbar:
Algorithmus 6.6: Der Solovay-Strassen Primzahltest
SOLOVAY-STRASSEN(n, t)
EINGABE: eine ungerade natürliche Zahl n ≥ 3 und einen Sicherheitsparameter t ≥ 1.
AUSGABE: Die Antwort "prim" oder "zusammengesetzt" auf die Frage: "Ist n prim?"
1. Für i von 1 bis t mache folgendes:
1.1. Wähle eine zufällige Zahl a, mit 2 ≤ a ≤ n – 2.
1.2. Berechne r = a(n-1)/2 mod n.
1.3. Wenn r ≠ 1 und r ≠ n – 1, dann gebe ("zusammengesetzt") zurück.
1.4. Berechne das Jacobisymbol s = JACOBI(a, n) mit dem Algorithmus 6.5.
1.5.Wenn r ≡/ s (mod n) ist, dann gebe ("zusammengesetzt") zurück.
2. Gebe ("prim") zurück.
Nach einem Schleifendurchlauf beträgt die Wahrscheinlichkeit, daß n keine Primzahl ist 50%.
Dies potenziert sich aber mit jedem weiterem Durchlauf. Somit beträgt die Wahrscheinlichkeit nach t Durchläufen nur noch (½)t.
6.6.3 Miller-Rabin Test
Dieser Test ist der heute gebräuchlichste Primzahltest. Er wurde von Gary Miller und Michael
Rabin entwickelt, weshalb er auch ihre Namen trägt. Der Test basiert auf folgendem Kriterium, das besagt wenn n eine Primzahl ist und s und r die Gleichung n – 1 = 2sr erfüllen, wobei
r ungerade ist, dann gilt:
a r ≡ 1 ( mod n )
(6.35)
oder
a2
j
r
≡ − 1 ( mod n )
(6.36)
für alle natürlichen Zahlen a, die den größten gemeinsamen Teiler von 1 für a und n haben,
wobei j im Bereich von 0 ≤ j ≤ s – 1 liegt. So erhält man dann folgenden Primzahltest:
Algorithmus 6.7: Der Miller-Rabin Primzahltest
MILLER-RABIN(n, t)
EINGABE: Eine ungerade natürliche Zahl n ≥ 3 und einen Sicherheitsparameter t ≥ 1.
AUSGABE: Die Antwort "prim" oder "zusammengesetzt" auf die Frage: "Ist n prim?"
1. Berechne s und r, so daß r ungerade ist und die Gleichung n – 1 = 2sr erfüllt ist.
2. Für i von 1 bis t mache folgendes:
Seite 33
2.1. Wähle eine zufällige Zahl a, mit 2 ≤ a ≤ n – 2.
2.2. Berechne y = ar mod n.
2.3. Wenn y ≠ 1 und y ≠ n – 1 dann mache folgendes:
2.3.1. j ← 1.
2.3.2. Solange j ≤ s – 1 und y ≠ n – 1 mache folgendes:
2.3.2.1. Berechne y = y2 mod n.
2.3.2.2. Wenn y = 1 dann gebe ("zusammengesetzt") zurück.
2.3.2.3. j ← j + 1.
2.3.3. Wenn y ≠ n – 1 dann gebe ("zusammengesetzt") zurück.
3. Gebe ("prim") zurück.
Die Wahrscheinlichkeit, daß eine Zahl, die keine Primzahl ist, diesen Test trotzdem besteht,
beträgt 25%. Des weiteren nimmt diese Wahrscheinlichkeit aber schneller ab als bei den beiden vorhergehenden Tests. So beträgt diese nur noch (¼)t nach t Schleifendurchläufe.
6.7 Größter gemeinsamer Teiler
Der größte gemeinsame Teiler, kurz gcd (greatest common divisor), zweier natürlicher Zahlen läßt sich mit Hilfe des euklidischen Algorithmus wie folgt berechnen:
Algorithmus 6.8: Berechnung des größten gemeinsamen Teilers (gcd)
GCD(a, b)
EINGABE: zwei positive natürliche Zahle a und b mit a ≥ b.
AUSGABE: der größte gemeinsame Teiler von a und b.
1. Solange b ≠ 0 ist, mache folgendes:
1.1. Setze r ← a mod b, a ← b, b ← r.
2. Gebe (a) zurück.
6.8 Erweiterter euklidischer Algorithmus
Der euklidische Algorithmus kann so erweitert werden, daß damit nicht nur den größte gemeinsame Teiler berechenbar ist, sondern auch folgende Gleichung gelöst werden kann:
e ⋅ d = k ⋅ϕ + 1
(6.37)
Dabei sind e und ϕ bekannt und d ist zu berechnen. Die Auflösung dieser Gleichung ist zur
Erzeugung von Schlüsselpaaren für den RSA-Algorithmus nötigt, welcher im Abschnitt 6.9
beschrieben wird. Der erweiterte euklidische Algorithmus ist folgendermaßen zu berechnen:
Algorithmus 6.9: Der erweiterte euklidische Algorithmus
EUCLID(e, ϕ)
EINGABE: zwei positive natürliche Zahlen e und ϕ mit e ≤ ϕ.
AUSGABE: d für die Lösung der Gleichung (6.37).
1. Setze a ← ϕ, b ← e, x ← 0 und y ← 1.
2. Berechne q = a/b und r = a – q ⋅ b.
3. Solange r > 0 ist, mache folgendes:
3.1. Berechne s = x – q ⋅ y.
3.2. Wenn s ≥ 0, dann setze s ← s mod ϕ, sonst setze s ← ϕ – (–s mod ϕ).
Seite 34
3.3. Setze x ← y, y ← s, a ← b und b ← r.
3.4. Berechne q = a/b und r = a – q ⋅ b.
4. Wenn b ≠ 1, dann setze r ← 0, sonst setze r ← y mod ϕ.
5. Gebe (r) zurück.
6.9 Der RSA-Algorithmus
Der RSA-Algorithmus ist einer der bekanntesten Vertreter aus der Familie der asymmetrischen Verschlüsselungsverfahren. Dabei steht RSA für die drei Erfinder Rivest, Shamir und
Adleman. Der Algorithmus wurden 1978 entwickelt, als sie beweisen wollten, daß Public-Key Kryptographie unmöglich ist. Die Sicherheit des RSA-Verfahren beruht vor allem in
dem Rechenaufwand, der zur Primfaktorzerlegung sehr großer Zahlen benötigt wird.
Bevor auf Einzelheiten eingegangen wird, soll erst einmal ein allgemeiner Überblick
über die Funktionsweise das RSA-Algorithmus aufgezeigt werden. Wie schon erwähnt, ist
dies ein asymmetrisches Verfahre. Das bedeutet, daß es dabei nicht nur einen Schlüssel gibt,
wie es bei symmetrische Algorithmen, z.B. dem DES-Algorithmus, der Fall ist, sonder hier
wird ein privater und ein öffentlicher Schlüssel verwendet. Dabei wird der öffentliche Schlüssel des Empfängers zur Verschlüsselung einer Nachricht verwendet und dieser kann dann die
Nachricht mit seinen privatem Schlüssel wieder entschlüsseln. Dieser Vorgang ist einmal in
Abbildung 6.4 dargestellt.
Entschlüsselung
Verschlüsselung
Klartext
(message)
E(m)
=c
= me mod n
D(c)
=m
= cd mod n
Chiffretext
öffentlicher Schlüssel: e, n
Klartext
(message)
privater Schlüssel: d
Abbildung 6.4: Der RSA-Algorithmus
6.9.1 Erzeugen von RSA-Schlüsselpaaren
Bevor der RSA-Algorithmus angewendet werde kann, muß für jeden Kommunikationsteilnehmer ein Schlüsselpaar, welches aus privaten und öffentlichen Schlüssel besteht, erzeugt
werden. Dazu werden zwei große Primzahlen p und q sowie das Produkt beider n = p ⋅ q benötigt. Dann ist die Euler-Phi Funktion von n zu berechnen:
ϕ (n ) = ϕ ( p ⋅ q ) = ϕ ( p ) ⋅ ϕ (q ) = ( p − 1) ⋅ (q − 1)
(6.38)
Anschließend wird eine natürliche Zahl e gewählt, die relative prim zu ϕ(n) ist, und deren
größter gemeinsamer Teiler 1 ist. Dann ist d zu berechnen, so daß
Seite 35
e ⋅ d mod ϕ (n ) = 1
(6.39)
erfüllt ist. Die Gleichung (6.39) kann so umgerechnet werden, daß man die Gleichung (6.37)
erhält. Somit ist es möglich den erweiterten euklidischen Algorithmus zu benutzen um d zu
berechnen. Dann ist noch zu überprüfen, ob der größte gemeinsame Teiler von d und ϕ(n)
auch 1 ist. Wenn diese Berechnungen abgeschlossen sind wird e und n als öffentlicher Schlüssel an alle anderen Kommunikationsteilnehmer weitergegeben, während d, p und q als privater Schlüssel geheim gehalten werden muß.
6.9.2 RSA-Verschlüsselung
Um eine Nachricht m zu verschlüsseln ist folgenden Gleichung zu berechnen:
c = m e mod n
(6.40)
Dabei ist zu beachten, daß m < n sein muß. Wenn die Nachricht m größer als n ist, dann ist sie
in mehrere Teile aufzuteilen, so daß die Teilnachricht mi kleiner als n ist.
Algorithmus 6.10: RSA Verschlüsselung
RSAEncrypt(m, e, n)
EINGABE: Die Nachricht m und der öffentliche Schlüssel e und n.
AUSGABE: Den Chiffretext c.
1. Berechne c = me mod n.
2. Gebe (c) zurück.
6.9.3 RSA-Entschlüsslung
Um eine Verschlüsselte Nachricht wieder lesbar zu mache, ist folgende Formel zu berechnen:
m = c d mod n
(6.41)
Wenn die Nachricht aus mehreren Teile bestand, so können diese nach dem Entschlüsseln
wieder zusammengesetzt werden. Im folgenden ist die Gleichung (6.41) als Algorithmus dargestellt:
Algorithmus 6.11: RSA Entschlüsselung
RSADecrypt(c, d, n)
EINGABE: Der Chiffretext c und der private Schlüssel d und n.
AUSGABE: Die Nachricht m.
1. Berechne m = cd mod n.
2. Gebe (m) zurück.
Der Algorithmus 6.11 ist genau derselbe wie Algorithmus 6.10, es werden nur andere Werte
übergeben, daher können diese Berechnungen auch in eine Algorithmus vorgenommen werden.
Seite 36
6.9.4 RSA Beispiel
An dieser Stelle soll einmal ein kleines Beispiel zum RSA-Algorithmus vorgestellt werden.
1. Auswahl zweier Primzahlen p und q:
p = 47
q = 59
2. Berechnung des Produktes n:
n=p⋅q
n = 2773
3. Berechnung von ϕ(n):
ϕ(n) = (p – 1) ⋅ (q – 1)
ϕ(n) = (47 – 1) ⋅ (59 – 1) = 2668
4. Auswahl einer Zahl e, die relative prim zu ϕ(n) ist:
e = 17
Test:
gcd(e, ϕ(n)) = 1
5. Berechnung von d mit dem erweiterten Euklidischen Algorithmus:
e ⋅ d mod ϕ(n) = 1
umrechnen in
e ⋅ d = k ⋅ ϕ(n) + 1
d = euclid(e, ϕ(n))
d = 157
Test:
gcd(d, ϕ(n)) = 1
gcd(e, d) = 1
öffentlicher Schlüssel (e, n): e = 17, n = 2773
privater Schlüssel (d, p, q): d = 157, p = 47, q = 59
6. Verschlüsselung der Nachricht "Test": E(m) = me mod n
T
e
s
t
7. Entschlüsseln der Nachricht:
→
→
→
→
84
101
115
116
→ 8417
→ 10117
→ 11517
→ 11617
mod
mod
mod
mod
2773
2773
2773
2773
= 2063
= 758
= 1751
= 2504
D(c) = cd mod n
2063157
758157
1751157
2504157
Seite 37
mod
mod
mod
mod
2773
2773
2773
2773
= 84 → T
= 101 → e
= 115 → s
= 116 → t
7 GESCHWINDIGKEITSMESSUNG MIT DEM C-INTERFACE
Um die Funktionen der VHDL-Bibliothek hinsichtlich ihrer Ausführungsgeschwindigkeit zu
optimieren, ist es notwendig die Zeit, die für die Simulation benötigt wird, zu messen. So
kann dann entschieden werden, welche Implementierung einer Funktion die schnellere ist. Die
Simulationszeit ist allerdings in VHDL nicht meßbar, aber es gibt noch eine andere Möglichkeit, denn der Simulator von Synopsys verfügt über ein C-Language Interface (CLI). Mit
einem drüber eingebundenen C-Programm ist es dann möglich Zeitmessungen vorzunehmen.
7.1 Benutzung des C-Interfaces
Für die Benutzung von C-Code mit dem Simulator sind drei Dateien notwendig. In der ersten
wird in VHDL beschrieben, wie die Verbindung zum C-Code aussieht. Als Zweites wird dann
der eigentliche C-Code benötigt. Die dritte Datei enthält die Komponentenbeschreibung, um
den C-Code in andere VHDL-Quellen einbinden zu können. Um dies alles zu verdeutlichen
wird anschließend die Benutzung des CLI am Beispiel eines Integer-Addierers beschrieben.
7.1.1 Die Verbindung zum C-Code
Im folgenden VHDL-Code wird die Verbindung zum C-Code beschrieben.
Datei: adder.vhd
LIBRARY synopsys;
USE synopsys.attributes.all;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY adder IS
GENERIC (
delay
);
PORT (
a : IN
b : IN
c : OUT
);
END adder;
: time := 5 ns
-- Ausgangsverzögerung
integer;
integer;
integer
ARCHITECTURE CLI OF adder IS
ATTRIBUTE FOREIGN OF CLI : ARCHITECTURE IS "SYNOPSYS:CLI";
ATTRIBUTE
ATTRIBUTE
ATTRIBUTE
ATTRIBUTE
CLI_ELABORATE
CLI_EVALUATE
CLI_CLOSE
CLI_ERROR
OF
OF
OF
OF
CLI
CLI
CLI
CLI
:
:
:
:
ARCHITECTURE
ARCHITECTURE
ARCHITECTURE
ARCHITECTURE
IS
IS
IS
IS
"adder_open";
"adder_eval";
"adder_close";
"adder_error";
ATTRIBUTE CLI_PIN OF a : SIGNAL IS CLI_EVENT;
ATTRIBUTE CLI_PIN OF b : SIGNAL IS CLI_EVENT;
BEGIN
END CLI;
Die ENTITY enthält alle Eingangs- und Ausgangssignale die zur Kommunikation mit dem
C-Code notwendig sind. In der darauffolgenden ARCHITECTURE sind einige Attribute zu
setzen, um das Interface genauer zu spezifizieren. Mit dem FOREIGN-Attribut wird festgelegt, um welches Interface es sich in diesem Fall handelt, denn der Synopsys-Simulator unterstützt auch noch andere außer dem CLI. In den vier folgenden Attributen sind die
C-Funktionen, die bei den entsprechenden Ereignissen aufgerufen werden, einzutragen. Allerdings sind nur die CLI_ELABORATE und CLI_EVALUATE Attribute nötig, die beiden
Seite 38
anderen können weggelassen werde. Es ist aber empfehlenswert alle vier zu verwenden. Zum
Schluß ist noch ein Attribut für jedes Eingangssignal zu setzen. Damit wird dem Simulator
mitgeteilt, wann die CLI-Komponente auszuwerten ist. Es gibt dafür 3 möglich Werte, die
dem Attribut zugewiesen werden können, siehe dazu Tabelle 7.1.
Parameter
CLI_EVENT
CLI_ACTIVE
CLI_PASSIVE
Zeitpunkt der Auswertung
Sobald sich das Signal verändert, wird die Komponente ausgewertet.
Wenn der Simulator diese Signal aktualisiert, erfolgt eine Auswertung.
Diese Signal hat keine Effekt auf die Komponentenauswertung.
Tabelle 7.1: Parameter für das Eingangssignal-Attribut
7.1.2 Der C-Code
Der C-Code enthält die eigentliche Funktionalität der Komponente. Hier sind die vier
C-Funktionen zu realisieren, welche vorher im VHDL-Code den Ereignis-Attributen zugewiesen wurden.
Um Probleme beim Arbeiten mit dem C-Interface feststellen zu können wird eine
Funktion zur Fehlerabfrage benötigt, diese kann auch als DEFINE realisiert werden, wie es in
der folgenden Header-Datei zu sehen ist.
Datei: adder.h
#define CHECK_ERRNO
if(cli_errno) { (void) printf("file %s, line %d\n",__FILE__,__LINE__);
cliPrintError((char *)0); exit(1) ;}
Zum Anfang der C-Codes sind erst einmal die Header-Dateien einzubinden. Eine Besonderheit spielt dabei die "cli.h", in dieser Datei sind sämtliche Funktionen und Definitionen die für
das C-Interface benötigt werden enthalten. Als nächstes folgt eine Struktur, in welcher die
ID's für die Signale zwischen C und VHDL, und einige zusätzliche Variablen enthalten sind.
Datei: adder.c
#include <stdio.h>
#include "adder.h"
#include "cli.h"
typedef struct
{
cliPID pidA;
cliPID pidB;
cliPID pidC;
cliGID gidDelay;
cliAFTER gvCDelay;
} ADDER_INSTANCE_DATA;
/* CLI-Headerdatei enthält alle Typen für VHDL */
/*
/*
/*
/*
/*
Pin ID für "a" */
Pin ID für "b" */
Pin ID für "c" */
ID für "delay" */
Ausgangsverzögerung für C */
Die folgenden Funktion wird beim Start des C-Interfaces aufgerufen. Dabei wird Speicher für
die obige Struktur reserviert und die ID's für die Signal ermittelt. Wie zu sehen ist, wird nach
jedem Aufruf einer Funktion des C-Interfaces das DEFINE aus der Header-Datei "adder.h"
ausgeführt, um eventuelle Fehler beim Aufruf zu ermitteln. Nachdem alle Variablen der
Struktur mit ihren Startwerten beschrieben wurden, wird die Struktur gespeichert.
void adder_open(did, iid)
cliDID did;
cliIID iid;
Seite 39
{
ADDER_INSTANCE_DATA *adder_idata;
cliVALUE gvDelay;
/* Speicher für die Datenstruktur reservieren */
adder_idata = (ADDER_INSTANCE_DATA *) cliAllocMem(sizeof(ADDER_INSTANCE_DATA));
/* Pins und Generics auf die Datenstruktur abbilden */
adder_idata->pidA = cliPortName2PID(did, "A");
CHECK_ERRNO;
adder_idata->pidB = cliPortName2PID(did, "B");
CHECK_ERRNO;
adder_idata->pidC = cliPortName2PID(did, "C");
CHECK_ERRNO;
adder_idata->gidDelay = cliGenericName2GID(did, "DELAY");
CHECK_ERRNO;
/* Ausgansverzögerung setzen */
cliGetGenericValue(did, iid, adder_idata->gidDelay, &gvDelay);
CHECK_ERRNO
adder_idata->gvCDelay.delaytype = INERTIAL;
adder_idata->gvCDelay.delay.low = gvDelay.value.time.low;
adder_idata->gvCDelay.delay.high = 0;
adder_idata->gvCDelay.delay.timebase = gvDelay.value.time.timebase;
/* die Datenstruktur sichern */
cliSaveInstanceData(did, iid, (void *) adder_idata);
CHECK_ERRNO;
}
Bei Beendigung des VHDL-Simulators ist auch der reservierte Speicher des C-Interfaces wieder freizugeben, dies erfolgt in der folgenden Funktion.
void adder_close(did, iid)
cliDID did;
cliIID iid;
{
ADDER_INSTANCE_DATA *adder_idata;
/* Datenstruktur wiederherstellen */
adder_idata = (ADDER_INSTANCE_DATA *) cliRestoreInstanceData(did,iid);
/* reservierten Speicher für die Datenstruktur freigeben */
if(adder_idata != (ADDER_INSTANCE_DATA *)0)
{
cliFreeMem((void *) adder_idata);
}
}
Wenn sich im VHDL-Simulator ein Signal der C-Komponente ändert und der Simulator eine
Auswertung dieses Signals vornimmt wird die folgende C-Funktion aufgerufen. Dies Funktion enthält die Funktionalität der C-Komponente. Zuerst einmal wird die Struktur wiederhergestellt, um überhaupt auf sie zugreifen zu können. Dann werden die aktuellen Werte von den
Signalen des C-Interfaces eingelesen. Danach wird die Struktur für die Ergebnisvariable aufgebaut und das Ergebnis berechnet. Zum Schluß wird diese Ergebnis über ein Signal des
C-Interfaces zurückgegeben. Die möglichen Signale und ihr Aufbau sind in der Dokumentation für den Simulator nachzulesen.
void adder_eval(did, iid, ppid, np)
cliDID did;
cliIID iid;
cliPID *ppid; /* Zeiger auf die Pin-IDs (Pinliste) */
int np;
/* Anzahl Pins in der Pinliste */
{
ADDER_INSTANCE_DATA *adder_idata;
cliVALUE svA;
cliVALUE svB;
cliVALUE svC;
Seite 40
/* Datenstruktur wiederherstellen */
adder_idata = (ADDER_INSTANCE_DATA *) cliRestoreInstanceData(did,iid);
cliGetPortValue(did, iid, adder_idata->pidA, &svA);
CHECK_ERRNO;
cliGetPortValue(did, iid, adder_idata->pidB, &svB);
CHECK_ERRNO;
svC.typemark = CLI_TYPE_INTEGER;
svC.length = 0;
svC.value.integer = svA.value.integer + svB.value.integer;
cliScheduleOutput(did, iid, adder_idata->pidC, &svC, &adder_idata->gvCDelay);
CHECK_ERRNO;
}
Die letze Funktion wird benötigt, um Fehler, die der VHDL-Simulator feststellt, anzuzeigen.
void adder_error(did, iid, level)
cliDID did;
cliIID iid;
int level;
{
char *s;
if(level == 0)
s = "WARNUNG";
else
s = "FEHLER";
(void) printf("%s gefunden mit (%d,%d)\n",s,did,iid);
cliPrintError("ADDER FEHLER");
}
Damit ist der C-Teil des Interfaces abgeschlossen. Wie sehr gut ersichtlich wird, ist es nicht
allzu schwierig das C-Interface des Synopsys VHDL-Simulators zu benutzen. Allerdings kann
solch ein Interface bei anderen Simulatoren völlig anders aussehen, daher ist die beschriebene
Komponente nur mit dem Synopsys-Simulator lauffähig.
7.1.3 Die Komponente
Um den C-Code auch in anderen VHDL-Quellen einzusetzen, wird eine Komponentenbeschreibung benötigt. Diese kann wie im folgenden beschrieben, als Bibliothek realisiert werden. So daß dann nur noch diese Bibliothek eingebunden werden muß, um die C-Komponente
in anderen VHDL-Beschreibungen benutzen zu können.
Datei: adder_comp.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.all;
PACKAGE adder_comp IS
COMPONENT adder
GENERIC (
delay : time := 5 ns
);
PORT (
a : IN integer;
b : IN integer;
c : OUT integer
);
END COMPONENT;
END;
Seite 41
7.1.4 Compilieren und Linken
Bevor die C-Komponente verwendet werden kann, sind die C-Datei zu compilieren und zu
linken. Dabei sollte wie folgt vorgegangen werden:
1. Analysieren der VHDL-Dateien:
vhdlan -nc adder_comp.vhd adder.vhd
Dabei werden als Parameter die beiden VHDL-Datei übergeben. Der "-nc"-Parameter
kann weggelassen werden, er unterdrückt nur die Startausgabe des VHDL-Analysers.
2. Compilieren der C-Dateien:
cli -nc -add -cv adder adder
Hierbei gibt der erste "adder"-Parameter den Namen der C-Datei an, und der zweite den
ENTITY-Namen der Komponente. Beim ausführen dieser Kommandozeile wird eine Objektdatei erzeugt, die "adder.o" heißt.
3. Erzeugen einer C-Bibliothek:
ar crl adder.a adder.o
Mit diesem Programmaufruf wird aus der Objektdatei eine C-Bibliothek mit dem Namen
"adder.a" erzeugt.
4. Linken der C-Bibliothek
cli -nc -s -build -libs adder.a
Hiermit wird die C-Bibliothek statisch mit dem VHDL-Simulator gelinkt. Dabei wird ein
neues VHDL-Simulatorprogramm im aktuellen Verzeichnis erzeugt, dieses muß dann
auch von dort aufgerufen werden, um die C-Komponente benutzen zu können.
Es ist auch möglich die C-Bibliothek dynamisch zu linken, allerdings ist dies nur unter
einigen wenigen Betriebssystemen (Sparc oder SparcOS5) möglich. Wenn diese Möglichkeit genutzt werden soll, dann hat der Kommandozeilenaufruf folgendermaßen auszusehen:
cli -nc -build -libs adder.a
7.2 Beschreibung der Meßfunktion
Um die Zeit zu messen, die vergeht während eine Berechnung statt findet, kann die folgende
C-Funktion genutzt werden. Dabei wird der Funktion die Variable s übergeben, diese kann die
Werte 0 und 1 annehmen. Wenn s = 1 ist, dann wird die Zeitmessung gestartet und mit s = 0
beendet. Bei Beendigung der Zeitmessung wird das Ergebnis ausgegeben und auch als Rückgabeparameter an die aufrufende Funktion zurückgegeben. Dort kann das Ergebnis dann auch
über ein Signal an das C-Interface übergeben werden.
double Time_F(s)
int s;
{
static struct timeb tstart, tend;
long i;
double ret;
switch(s)
{
case 0:
printf("\n--------------------- ENDE -------------------------------\n\n");
ftime(&tend);
i = (long)tend.millitm - (long)tstart.millitm;
ret = ((double)(tend.time - tstart.time)) + ((double)i) / 1000.0;
printf("Rechenzeit: %21.3f Sekunden\n", ret);
printf("\n--------------------- ENDE -------------------------------\n\n");
Seite 42
break;
case 1:
printf("\n--------------------- START ------------------------------\n\n");
ret = (double)0;
ftime(&tstart);
break;
default:
break;
}
return (ret);
}
Diese Funktion wird in der EVALUATE-Teil des C-Codes aufgerufen.
Seite 43
8 ÜBERPRÜFUNG DER BIBLIOTHEK
Um die richtige Funktionsweise der VHDL-Bibliothek zu überprüfen, war es notwendig ein
C-Programm zu entwickelt, welches Testvektoren für den VHDL-Simulator berechnete. Dazu
wurde der C-Code von Arjen K. Lenstra verwendet, mit dem es möglich ist Langzahlarithmetikfunktionen auszuführen. Um diesen C-Code zur Generierung von Testvektoren einsetzen
zu können, war es nötig einige Anpassungen und Erweiterungen vorzunehmen. So wurde eine
Funktion entwickelt, mit der es möglich ist große Zufallszahlen zu erzeugen. Des weiteren
wurde noch eine Funktion benötigt, um die langen Zahlen in hexadezimaler Form in eine Datei auszugeben.
Das Programm hat folgende Kommandozeilenparameter, wobei "mpa" der Name der Programmes ist:
mpa Funktion Vektoranzahl Vektorbreite Ausgabedatei [Saat]
Dabei haben die Parameter folgende Bedeutung:
Paramter
Funktion
Vektoranzahl
Vektorbreite
Ausgabedatei
Saat
Bedeutung
1 Addition
2 Subtraktion
3 Multiplikation
4 Division
5 Modulo
Anzahl der zu erzeugenden Testvektoren
Breite der Testvektoren in Bits
Name der Datei, in der die Testvektoren gespeichert werden
Die Saat für den Zufallszahlengenerator. Wenn dieser Parameter
weggelassen wird, werden jedesmal andere Testvektoren erzeugt.
Tabelle 8.1: Programmparameter für "mpa"
Die Testvektoren, die so erzeugt wurden, können nun mit Hilfe des VHDL-Simulators eingelesen werden, und so zum Überprüfen der VHDL-Funktionen genutzt werden.
Seite 44
9 TESTERGEBNISSE
9.1 Testergebnisse bei konstanter Vektorbreite
In Tabelle 9.1 sind die Meßergebnisse, welche mit dem C-Interface des VHDL-Simulators
und der Meßfunktion aus Kapitel 7.2 ermittelt wurden, abgebildet. Dabei ist zu beachten, daß
diese Meßfunktion nur die Zeit mißt, die auf dem Computer vergeht während die Berechnung
stattfindet. Da der Simulator auf einem UNIX Betriebssystem mit Multitaskingfunktion läuft,
war es notwendig eine Rechner zu benutzen, auf dem keine weiteren Programme liefen, weil
es sonst zu Verfälschungen der Meßergebnisse gekommen währe.
Vektorbreite Ziffernbreite Durchläufe Addition
1024
4
10000
109,853
10000
109,886
10000
110,293
10000
109,660
10000
108,453
10000
108,492
109,440
∅
8
10000
60,540
10000
60,684
10000
60,698
10000
60,524
10000
60,909
10000
60,860
60,703
∅
16
10000
36,600
10000
37,845
10000
37,740
10000
36,698
10000
38,913
10000
36,623
37,403
∅
32
10000
24,748
10000
25,666
10000
24,604
10000
24,731
10000
24,733
10000
24,598
24,847
∅
64
10000
19,107
10000
19,631
10000
18,486
10000
18,679
10000
18,732
10000
18,688
18,887
∅
Seite 45
in Sekunden
Subtraktion Multiplikation
110,606
155,268
110,660
154,954
110,781
155,235
110,128
154,654
109,257
148,490
109,189
148,548
110,104
152,858
61,133
85,894
61,179
86,266
61,017
86,441
61,186
85,999
61,346
87,072
61,522
86,408
61,231
86,347
37,227
54,820
38,421
56,202
38,446
56,276
37,299
54,863
39,511
57,681
37,239
54,657
38,024
55,750
25,593
39,160
25,880
40,090
25,615
39,135
25,571
39,172
25,256
39,274
25,459
39,150
25,562
39,330
19,946
32,220
20,386
32,806
19,384
31,718
19,279
31,674
19,428
31,920
19,401
31,867
19,637
32,034
Division
2620,101
2619,379
2618,980
2620,231
3066,831
3059,711
2767,539
3001,722
3001,815
3001,861
3001,733
3027,597
3025,981
3010,118
2974,308
2980,363
2980,012
2974,872
3017,391
2974,030
2983,496
2955,730
2960,383
2956,750
2955,159
2955,379
2957,580
2956,830
2974,895
2973,338
2946,335
2947,299
2947,745
2948,637
2956,375
128
10000
15,673
16,616
29,711
10000
16,193
17,123
30,755
10000
17,251
17,988
31,617
10000
15,676
16,481
29,691
10000
15,663
16,532
29,704
10000
15,802
16,386
29,666
16,043
16,854
30,191
∅
256
10000
14,657
15,214
26,191
10000
14,527
15,416
25,937
10000
14,489
15,221
26,192
10000
14,621
15,314
26,100
10000
14,518
15,384
26,028
10000
14,490
15,248
26,236
14,550
15,300
26,114
∅
512
10000
13,679
14,562
25,945
10000
13,819
14,430
26,153
10000
13,653
14,422
26,364
10000
13,665
14,561
26,121
10000
13,641
14,428
26,025
10000
13,837
14,785
26,333
13,716
14,531
26,157
∅
1024
10000
13,448
14,362
21,369
10000
14,036
15,163
21,890
10000
14,148
14,699
22,086
10000
14,170
14,375
21,609
10000
14,319
14,553
21,828
10000
14,139
15,592
21,710
14,043
14,791
21,749
∅
Tabelle 9.1: Testergebnisse bei konstanter Vektorbreite
2948,219
2948,303
2948,653
2946,506
2949,505
2946,708
2947,982
3011,864
3012,169
3012,264
3014,144
3012,465
3012,248
3012,526
2685,863
2602,149
2602,602
2601,580
2601,381
2602,023
2615,933
3209,273
3216,082
3219,504
3270,300
3372,407
3319,777
3267,891
Die Durchschnittszeiten der Addition, Subtraktion und Multiplikation, welche in Tabelle 9.1
ermittelt wurden, sind in Abbildung 9.1 als Diagramm dargestellt. Die Division wurde dabei
weggelassen, da die Meßzeiten hier so groß sind, daß die Kurven der Addition, Subtraktion
und Multiplikation sonst nicht mehr sichtbar währen. Die Kurve der Addition wird von der
Subtraktion fast verdeckt, da die Meßwerte so dicht zusammen liegen, daß der Unterschied
nur minimal ist.
Wie in Abbildung 9.1 sehr gut zu sehen ist, nimmt die Rechenzeit um so mehr zu, je
kleiner die Anzahl Bits pro Ziffer sind. Allerdings strebt die Rechenzeit nicht gegen Null,
sonder pegelt sich bei einem bestimmten Wert ein.
Seite 46
160,000
Rechenzeit [s]
140,000
120,000
100,000
Addition
Subtraktion
Mutliplikation
80,000
60,000
40,000
20,000
0,000
4
8
16
32
64
128
256
512 1024
Ziffernbreite [bit]
Abbildung 9.1: Durchschnittszeiten für die Addition, Subtraktion und Multiplikation
9.2 Testergebnisse bei konstanter Ziffernbreite
Als zweites wurden noch einige Meßergebnisse aufgenommen, wobei die Ziffernbreite konstant blieb und die Vektorbreite variiert wurden. Dabei war zu erwarten, daß die Rechenzeit
linear ansteigt und sich bei doppelter Vektorbreite auch verdoppelt. Bei der Messung wurden
folgende Werte ermittelt:
Addition in Sekunden bei einer Vektorbreite von
Ziffernbreite Durchläufe
256
512
1024
2048
4096
16
10000
11,120
19,049
38,773
76,260
165,706
10000
10,990
19,220
38,804
75,989
165,796
10000
10,975
19,202
38,802
75,981
166,089
10000
11,270
19,774
38,705
75,417
167,420
10000
10,937
19,308
38,921
76,087
166,154
10000
11,043
19,189
38,798
75,978
165,815
11,056
19,290
38,801
75,952
166,163
∅
32
10000
7,945
12,937
26,667
49,801
104,140
10000
7,555
13,075
25,509
49,683
104,678
10000
7,738
12,966
26,581
50,067
104,417
10000
7,762
12,996
26,874
50,063
104,715
10000
7,574
13,136
26,810
50,041
104,413
10000
7,830
12,986
25,815
50,058
104,559
7,734
13,016
26,376
49,952
104,487
∅
Tabelle 9.2: Testergebnisse bei konstanter Ziffernbreite
Die Tabelle 9.2 zeigt, daß sich die Erwartungen in etwa erfüllt haben. Noch besser wird dies
gezeigt, wenn die Durchschnittswerte grafisch dargestellt werden, wie es in Abbildung 9.2
Seite 47
geschehen ist. Dabei ist ein linearer Anstieg der Rechenzeit unverkennbar. Um dies noch zu
verdeutlichen, wurden die Meßergebnisse für zwei verschiedene Ziffernbreiten ermittelt. So
ist sehr gut zu erkennen, daß sich die Geraden immer weiter voneinander entfernen, je größer
die Vektorbreite wird.
180,000
160,000
Rechenzeit [s]
140,000
120,000
100,000
Ziffernbreite 16
80,000
Ziffernbreite 32
60,000
40,000
20,000
0,000
0
1024
2048
3072
4096
Vektorlänge [bit]
Abbildung 9.2: Rechenzeiten bei konstanter Ziffernbreite
9.3 Optimierung nach Ermittlung von Meßergebnissen
Außer der MPA-Adition (multiple-precision arithmetic) wie sie in Algorithmus 3.1 vorgestellt wurde, ist in VHDL auch noch eine andere Implementation möglich. Dabei werden die
beiden Zahlen x und y zum Anfang von einer "digit_vector"-Darstellung in eine
"std_logic_vector"-Darstellung umgewandelt. Auf diese "std_logic_vector"-Zahlen kann dann
die Addition aus der IEEE-Bibliothek angewendet werden. Um das Ergebnis wieder weiter
verwende zu können, ist diese dann in eine "digit_vector"-Zahl zurück zu wandeln. Ein solcher Algorithmus kann wie folgt realisiert werden:
Algorithmus 9.1: Addition in VHDL
EINGABE: Zwei positive natürliche Zahlen x und y, in "digit_vector"-Darstellung.
AUSGABE: Die Summe x + y = w.
1. Umwandeln in "std_logic_vector": xv ← x, yv ← y.
2. Adition mit der IEEE-Funktion: wv = xv + yv.
3. Zurückwandeln in "digit_vector": w ← wv.
4. Gebe (w) zurück.
Allerdings stellt sich jetzt die Frage welche Implementation ist die schnellere. Dazu kann
dann wieder das C-Interface genutzt werden. Die damit ermittelten Meßwerte sind in Tabelle
9.3 dargestellt. Wie deutlich zu sehen ist, stellt sich die in Algorithmus 9.1 vorgestellte Lösung als die bessere Variante dar. Auf die gleiche Weise lassen sich die Algorithmen für die
Subtraktion und Multiplikation auch noch verbessern.
Seite 48
in Sekunden
Vektorbreite
Ziffernbreite
Durchläufe
MPA Addition VHDL Addition
1024
4
10000
142,135
109,853
10000
142,664
109,886
10000
141,792
110,293
10000
142,218
109,660
10000
141,748
108,453
10000
143,932
108,492
142,415
109,440
∅
32
10000
27,413
24,748
10000
28,037
25,666
10000
27,057
24,604
10000
28,203
24,731
10000
27,589
24,733
10000
27,414
24,598
27,619
24,847
∅
Tabelle 9.3: Vergleich zweier verschiedener Addiererimplementationen
Seite 49
10 ZUSAMMENFASSUNG
Durch die Fertigstellung der Langzahl-Integer-Arithmetik-Bibliothek in VHDL sind Berechnungen für VHDL-Simulationen möglich geworden, die mit den Standard-Bibliotheken nur
unter großen Umständen zu realisieren gewesen wären.
Es wurden auch Funktionen zur Generierung von Schlüsselpaaren für den
RSA-Algorithmus in der VHDL-Bibliothek realisiert, allerdings kann die Berechnung eines
Schlüsselpaares mehrere Stunden oder sogar Tage in Anspruch nehmen. Daher währe hierfür
eine Berechnung in einem C-Programm vorteilhafter, da diese wesentlich schneller fertig ist.
Wie bei der Zeitmessung der einzelnen Funktionen zu sehen ist, war die Divisionsfunktion wesentlich langsamer als alle anderen mathematischen Grundfunktionen. Deswegen
sollte an dieser Funktion nach Möglichkeit noch Optimierungen vorgenommen werden. Allerdings ist dies schwierig zu realisieren, da es keine Division für eine
"std_logic_vector"-Typen in den Standard-Bibliotheken gibt.
Seite 50
LITERATURVERZEICHNIS
[1]
Bronstein, Semendjajew, Musiol, Mühlig, Taschenbuch der Mathematik, Verlag Harri
Deutsch, Frankfurt am Main, 1993
[2]
Alfred J. Menezes, Paul C. van Oorschot, Scott A. Vanstone, Handbook of Applied
Cryptography, CRC Press, Boca Raton, 1997
[3]
Peter J. Ashenden, The Designer's Guide to VHDL, Morgan Kaufmann Publishers,
Inc., San Francisco, 1996
[4]
Beutelspacher, Schwenk, Wolfenstetter, Moderne Verfahren der Kryptographie,
Vieweg Verlag, Braunschweig, 1995
[5]
Neal Koblitz, A Course in Number Theory and Cryptography, Springer-Verlag,
New York, 1994
Seite 51
ANHANG
A Die VHDL-Bibliothek
A1 Enthaltene Funktionen
A1.1 LOGISCHE FUNKTIONEN
Die logischen Funktionen sind in der Datei "mp_logic.vhd" enthalten. Dort sind die folgende
Funktionen realisiert:
FUNCTION "and"
FUNCTION "and"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "nand" ( l, r : udigit_vector ) RETURN udigit_vector;
FUNCTION "nand" ( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "or"
FUNCTION "or"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "nor"
FUNCTION "nor"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "xor"
FUNCTION "xor"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION xnor
FUNCTION xnor
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "not"
FUNCTION "not"
( l : udigit_vector
( l : digit_vector
) RETURN udigit_vector;
) RETURN digit_vector;
Zusätzlich sind noch einige Konvertierungsfunktionen enthalten, um andere Datentype in einen "digit_vector" oder "udigit_vector" umzuwandel:
FUNCTION To_StdLogicVector ( d : digit_vector ) RETURN std_logic_vector;
FUNCTION To_StdLogicVector ( u : udigit_vector ) RETURN std_logic_vector;
FUNCTION To_StdLogicVector ( u : digit ) RETURN std_logic_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
To_DigitVector
To_DigitVector
To_DigitVector
To_DigitVector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
To_UDigitVector
To_UDigitVector
To_UDigitVector
To_UDigitVector
(
(
(
(
s
s
u
s
(
(
(
(
:
:
:
:
s
s
d
s
std_logic_vector
std_ulogic_vector
udigit_vector
string
:
:
:
:
std_logic_vector
std_ulogic_vector
digit_vector
string
)
)
)
)
RETURN
RETURN
RETURN
RETURN
)
)
)
)
RETURN
RETURN
RETURN
RETURN
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
udigit_vector;
udigit_vector;
Mit den folgenden beiden Funktionen können die "digit_vector" und "udigit_vector" in
Strings umgewandelt werden, um sie zum Beispiele in eine Datei auszugeben:
FUNCTION To_String ( u : udigit_vector ) RETURN string;
FUNCTION To_String ( d : digit_vector ) RETURN string;
A1.2 MATHEMATISCHE UND VERGLEICHSFUNKTIONEN
In der Datei "mp_arith.vhd" sind die folgenden mathematischen Grundfunktionen enthalten:
FUNCTION "+" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector;
FUNCTION "+" ( l : digit; r : udigit_vector ) RETURN udigit_vector;
FUNCTION "+" ( l : udigit_vector; r : digit ) RETURN udigit_vector;
FUNCTION "+" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector;
FUNCTION "+" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector;
FUNCTION "+" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector;
Seite 52
FUNCTION "+" ( l : digit_vector;
r : digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"+"
"+"
"+"
"+"
"+"
"+"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"-"
"-"
"-"
"-"
"-"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"-"
"-"
"-"
"-"
"-"
"-"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"+" (
"+" (
"-" (
"-" (
"-" (
"ABS"
l
l
l
l
l
(
:
:
:
:
:
l
udigit_vector ) RETURN udigit_vector;
digit_vector ) RETURN digit_vector;
udigit_vector ) RETURN udigit_vector;
udigit_vector ) RETURN digit_vector;
digit_vector ) RETURN digit_vector;
: digit_vector ) RETURN digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"*"
"*"
"*"
"*"
"*"
"*"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
udigit_vector; r
digit; r : digit
udigit_vector; r
udigit_vector; r
digit_vector; r
digit_vector; r
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"*"
"*"
"*"
"*"
"*"
"*"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/"
"/"
"/"
"/"
"/"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/"
"/"
"/"
"/"
"/"
"/"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
r
r
r
r
r
:
:
:
:
:
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
:
)
:
:
:
:
r
r
r
r
r
)
)
)
)
)
)
) RETURN digit_vector;
)
)
)
)
)
)
)
)
)
)
)
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector ) RETURN
RETURN udigit_vector;
udigit_vector ) RETURN
digit_vector ) RETURN
udigit_vector ) RETURN
digit_vector ) RETURN
:
:
:
:
:
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
)
)
)
)
)
)
)
)
)
)
)
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
Des weiteren sind in dieser Datei auch die folgenden Vergleichsfunktionen realisiert:
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"<"
"<"
"<"
"<"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"<"
"<"
"<"
"<"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"<="
"<="
"<="
"<="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
r
r
r
r
udigit_vector
digit_vector
udigit_vector
digit_vector
:
:
:
:
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
digit_vector
udigit_vector
digit_vector
)
)
)
)
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
FUNCTION "<=" ( l : udigit_vector; r : integer ) RETURN boolean;
FUNCTION "<=" ( l : integer; r : udigit_vector ) RETURN boolean;
FUNCTION "<=" ( l : digit_vector; r : integer ) RETURN boolean;
Seite 53
FUNCTION "<=" ( l : integer; r : digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
">"
">"
">"
">"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
FUNCTION
FUNCTION
FUNCTION
FUNCTION
">"
">"
">"
">"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
">="
">="
">="
">="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
">="
">="
">="
">="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"="
"="
"="
"="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"="
"="
"="
"="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/="
"/="
"/="
"/="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/="
"/="
"/="
"/="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
r
r
r
r
r
r
r
r
udigit_vector
digit_vector
udigit_vector
digit_vector
:
:
:
:
:
:
:
:
r
r
r
r
) RETURN boolean;
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
digit_vector
udigit_vector
digit_vector
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
digit_vector
udigit_vector
digit_vector
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
RETURN
RETURN
RETURN
RETURN
udigit_vector
digit_vector
udigit_vector
digit_vector
:
:
:
:
)
)
)
)
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
Zusätzlich sind auch noch die folgende Schiebefunktionen enthalte:
FUNCTION
FUNCTION
FUNCTION
FUNCTION
SHL
SHL
SHL
SHL
(
(
(
(
ARG
ARG
ARG
ARG
:
:
:
:
udigit_vector; COUNT : udigit_vector
digit_vector; COUNT : udigit_vector
udigit_vector; COUNT : integer
digit_vector; COUNT : integer
)
)
)
)
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
udigit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
SHR
SHR
SHR
SHR
(
(
(
(
ARG
ARG
ARG
ARG
:
:
:
:
udigit_vector; COUNT : udigit_vector
digit_vector; COUNT : udigit_vector
udigit_vector; COUNT : integer
digit_vector; COUNT : integer
)
)
)
)
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
udigit_vector;
digit_vector;
Um die Hierarchie in den Funktionen zu realisieren, sind noch folgende Konvertierungsfunktionen nötig:
FUNCTION CONV_INTEGER ( ARG : udigit_vector ) RETURN integer;
FUNCTION CONV_INTEGER ( ARG : digit_vector ) RETURN integer;
FUNCTION CONV_DIGIT_VECTOR
FUNCTION CONV_DIGIT_VECTOR
FUNCTION CONV_DIGIT_VECTOR
( ARG : udigit_vector; SIZE : integer ) RETURN digit_vector;
( ARG : digit_vector; SIZE : integer ) RETURN digit_vector;
( ARG : integer; SIZE : integer
) RETURN digit_vector;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : udigit_vector; SIZE : integer ) RETURN udigit_vector;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : digit_vector; SIZE : integer ) RETURN udigit_vector;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : integer; SIZE : integer
) RETURN udigit_vector;
Seite 54
A1.3 KRYTOGRAPHISCHE FUNKTIONEN
In der Datei "mp_crypt.vhd" sind die erweiterten mathematischen und kryptographischen
Funktionen enthalten:
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"mod"
"mod"
"mod"
"mod"
"mod"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
r
:
:
:
:
:
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"mod"
"mod"
"mod"
"mod"
"mod"
"mod"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"rem"
"rem"
"rem"
"rem"
"rem"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"rem"
"rem"
"rem"
"rem"
"rem"
"rem"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"**"
"**"
"**"
"**"
"**"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"**"
"**"
"**"
"**"
"**"
"**"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
r
r
r
r
r
r
r
r
r
r
:
:
:
:
:
:
:
:
:
:
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
FUNCTION modexp ( b, e, m : udigit_vector ) RETURN udigit_vector;
FUNCTION modexp ( b, e, m : digit_vector ) RETURN digit_vector;
Die folgenden Funktionen werden zur Erzeugung von RSA-Schlüsslepaaren benötigt:
FUNCTION gcd ( a, b : udigit_vector ) RETURN udigit_vector;
FUNCTION euclid ( e, phi : udigit_vector ) RETURN udigit_vector;
PROCEDURE rnd ( CONSTANT length : IN integer; VARIABLE seed : INOUT udigit_vector;
VARIABLE number : OUT udigit_vector );
FUNCTION prim ( p : udigit_vector; t : integer ) RETURN boolean;
PROCEDURE RSA ( CONSTANT length : IN integer; VARIABLE seed : INOUT udigit_vector;
VARIABLE p, q, e, d, n : OUT udigit_vector );
A1.4 ZUSÄTZLICHE FUNKTIONEN
In der Datei "mp_std_logic.vhd" sind einige zusätzliche Funktionen enthalten, die die Funktionalität der IEEE-Bibliotheken erweitern:
FUNCTION "/" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "/" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "/" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "mod" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "mod" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "mod" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "rem" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "rem" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
Seite 55
FUNCTION "rem" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "**" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "**" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "**" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION modexp ( b, e, m : std_logic_vector ) RETURN std_logic_vector;
Seite 56
A2 VHDL-Quellen
A1.1 DATEI: MP_LOGIC.VHD
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
PACKAGE mp_logic IS
-- pragma synthesis_off
----------------------------------------------------------------------------------- constants
----------------------------------------------------------------------------------- size of digits in bits
CONSTANT digit_size : positive := 4;
----------------------------------------------------------------------------------- subtypes and types
----------------------------------------------------------------------------------- digit
SUBTYPE digit IS std_logic_vector((digit_size - 1) DOWNTO 0);
-- unsigned digit vector
TYPE udigit_vector IS ARRAY ( NATURAL RANGE <> ) OF digit;
-- two's coplement digit vector
TYPE digit_vector IS ARRAY ( NATURAL RANGE <> ) OF digit;
----------------------------------------------------------------------------------- constants
---------------------------------------------------------------------------------CONSTANT zero_digit : digit := (OTHERS => '0');
CONSTANT max_digit : digit := (OTHERS => '1');
CONSTANT one_digit : digit := (0 => '1', OTHERS => '0');
----------------------------------------------------------------------------------- overloaded logical operators
-----------------------------------------------------------------------------------------
FUNCTION "and" ( l : digit;
FUNCTION "nand" ( l : digit;
FUNCTION "or"
( l : digit;
FUNCTION "nor" ( l : digit;
FUNCTION "xor" ( l : digit;
FUNCTION xnor
( l : digit;
FUNCTION "not" ( l : digit
r
r
r
r
r
r
:
:
:
:
:
:
digit ) RETURN digit;
digit ) RETURN digit;
digit ) RETURN digit;
digit ) RETURN digit;
digit ) RETURN digit;
digit ) RETURN digit;
) RETURN digit;
----------------------------------------------------------------------------------- vectorized overloaded logical operators
---------------------------------------------------------------------------------FUNCTION "and"
FUNCTION "and"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "nand" ( l, r : udigit_vector ) RETURN udigit_vector;
FUNCTION "nand" ( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "or"
FUNCTION "or"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "nor"
FUNCTION "nor"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "xor"
FUNCTION "xor"
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION xnor
FUNCTION xnor
( l, r : udigit_vector ) RETURN udigit_vector;
( l, r : digit_vector ) RETURN digit_vector;
FUNCTION "not"
FUNCTION "not"
( l : udigit_vector
( l : digit_vector
) RETURN udigit_vector;
) RETURN digit_vector;
----------------------------------------------------------------------------------- conversion functions
---------------------------------------------------------------------------------FUNCTION To_StdLogicVector ( d : digit_vector ) RETURN std_logic_vector;
FUNCTION To_StdLogicVector ( u : udigit_vector ) RETURN std_logic_vector;
FUNCTION To_StdLogicVector ( u : digit ) RETURN std_logic_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
To_DigitVector
To_DigitVector
To_DigitVector
To_DigitVector
(
(
(
(
FUNCTION
FUNCTION
FUNCTION
FUNCTION
To_UDigitVector
To_UDigitVector
To_UDigitVector
To_UDigitVector
s
s
u
s
(
(
(
(
:
:
:
:
s
s
d
s
std_logic_vector
std_ulogic_vector
udigit_vector
string
:
:
:
:
)
)
)
)
std_logic_vector
std_ulogic_vector
digit_vector
string
RETURN
RETURN
RETURN
RETURN
)
)
)
)
digit_vector;
digit_vector;
digit_vector;
digit_vector;
RETURN
RETURN
RETURN
RETURN
udigit_vector;
udigit_vector;
udigit_vector;
udigit_vector;
FUNCTION To_String ( u : udigit_vector ) RETURN string;
FUNCTION To_String ( d : digit_vector ) RETURN string;
-- pragma synthesis_on
END mp_logic;
-----------------------------------------------------------------------------------
Seite 57
PACKAGE BODY mp_logic IS
-- pragma synthesis_off
----------------------------------------------------------------------------------- overloaded logical operators
--------------------------------------------------------------------------------------
FUNCTION "and" ( l : digit; r : digit ) RETURN digit IS
BEGIN
RETURN digit( std_logic_vector(l) and std_logic_vector(r) );
END;
-----
FUNCTION "nand" ( l : digit; r : digit ) RETURN digit IS
BEGIN
RETURN digit( std_logic_vector(l) nand std_logic_vector(r) );
END;
-----
FUNCTION "or"
( l : digit; r : digit ) RETURN digit IS
BEGIN
RETURN digit( std_logic_vector(l) or std_logic_vector(r) );
END;
-----
FUNCTION "nor" ( l : digit; r : digit ) RETURN digit IS
BEGIN
RETURN digit( std_logic_vector(l) nor std_logic_vector(r) );
END;
-----
FUNCTION "xor" ( l : digit; r : digit ) RETURN digit IS
BEGIN
RETURN digit( std_logic_vector(l) xor std_logic_vector(r) );
END;
-----
FUNCTION xnor
( l : digit; r : digit ) RETURN digit IS
BEGIN
RETURN digit( not(std_logic_vector(l) xor std_logic_vector(r)) );
END;
-----
FUNCTION "not" ( l : digit
) RETURN digit IS
BEGIN
RETURN digit( not std_logic_vector(l) );
END;
----------------------------------------------------------------------------------- vectorized overloaded logical operators
-------------------------------------------------------------------------------------------------------------------------------------------------------------------- and
---------------------------------------------------------------------------------FUNCTION "and" ( l, r : udigit_vector ) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : udigit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'and' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) and rv(i) );
END LOOP;
END IF;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION "and" ( l, r : digit_vector ) RETURN digit_vector IS
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : digit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'and' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) and rv(i) );
END LOOP;
END IF;
RETURN result;
END;
----------------------------------------------------------------------------------- nand
---------------------------------------------------------------------------------FUNCTION "nand" ( l, r : udigit_vector ) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : udigit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nand' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) nand rv(i) );
END LOOP;
END IF;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION "nand" ( l, r : digit_vector ) RETURN digit_vector IS
Seite 58
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : digit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nand' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) nand rv(i) );
END LOOP;
END IF;
RETURN result;
END;
----------------------------------------------------------------------------------- or
---------------------------------------------------------------------------------FUNCTION "or"
( l, r : udigit_vector ) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : udigit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'or' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) or rv(i) );
END LOOP;
END IF;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION "or"
( l, r : digit_vector ) RETURN digit_vector IS
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : digit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'or' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) or rv(i) );
END LOOP;
END IF;
RETURN result;
END;
----------------------------------------------------------------------------------- nor
---------------------------------------------------------------------------------FUNCTION "nor" ( l, r : udigit_vector ) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : udigit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) nor rv(i) );
END LOOP;
END IF;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION "nor" ( l, r : digit_vector ) RETURN digit_vector IS
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : digit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) nor rv(i) );
END LOOP;
END IF;
RETURN result;
END;
----------------------------------------------------------------------------------- xor
---------------------------------------------------------------------------------FUNCTION "xor" ( l, r : udigit_vector ) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : udigit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) xor rv(i) );
Seite 59
END LOOP;
END IF;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION "xor" ( l, r : digit_vector ) RETURN digit_vector IS
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : digit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( lv(i) xor rv(i) );
END LOOP;
END IF;
RETURN result;
END;
----------------------------------------------------------------------------------- xnor
---------------------------------------------------------------------------------FUNCTION xnor
( l, r : udigit_vector ) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : udigit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xnor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( not( lv(i) xor rv(i) ) );
END LOOP;
END IF;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION xnor
( l, r : digit_vector ) RETURN digit_vector IS
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
ALIAS rv : digit_vector ( (r'LENGTH - 1) DOWNTO 0 ) IS r;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xnor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := ( not( lv(i) xor rv(i) ) );
END LOOP;
END IF;
RETURN result;
END;
----------------------------------------------------------------------------------- not
---------------------------------------------------------------------------------FUNCTION "not" ( l : udigit_vector
) RETURN udigit_vector IS
ALIAS lv : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
VARIABLE result : udigit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
FOR i IN (l'LENGTH - 1) DOWNTO 0 LOOP
result(i) := ( NOT lv(i) );
END LOOP;
RETURN result;
END;
---------------------------------------------------------------------------------FUNCTION "not" ( l : digit_vector
) RETURN digit_vector IS
ALIAS lv : digit_vector ( (l'LENGTH - 1) DOWNTO 0 ) IS l;
VARIABLE result : digit_vector ( (l'LENGTH - 1) DOWNTO 0 );
BEGIN
FOR i IN (l'LENGTH - 1) DOWNTO 0 LOOP
result(i) := ( NOT lv(i) );
END LOOP;
RETURN result;
END;
----------------------------------------------------------------------------------- conversion functions
---------------------------------------------------------------------------------FUNCTION To_StdLogicVector ( d : digit_vector ) RETURN std_logic_vector IS
ALIAS dv
: digit_vector((d'LENGTH - 1) DOWNTO 0) IS d;
VARIABLE result : std_logic_vector(((d'LENGTH * digit_size) - 1) DOWNTO 0);
VARIABLE prod
: integer;
BEGIN
FOR i IN dv'RANGE LOOP
prod := i * digit_size;
result((prod + (digit_size - 1)) DOWNTO prod) := dv(i);
END LOOP;
RETURN result;
END;
FUNCTION To_StdLogicVector ( u : udigit_vector ) RETURN std_logic_vector IS
ALIAS uv
: udigit_vector((u'LENGTH - 1) DOWNTO 0) IS u;
VARIABLE result : std_logic_vector(((u'LENGTH * digit_size) - 1) DOWNTO 0);
VARIABLE prod
: integer;
BEGIN
FOR i IN uv'RANGE LOOP
Seite 60
prod := i * digit_size;
result((prod + (digit_size - 1)) DOWNTO prod) := uv(i);
END LOOP;
RETURN result;
END;
FUNCTION To_StdLogicVector ( u : digit) RETURN std_logic_vector IS
VARIABLE result : std_logic_vector((digit_size-1) DOWNTO 0);
BEGIN
result((digit_size-1) DOWNTO 0) := u;
RETURN result;
END;
FUNCTION To_DigitVector ( s : std_logic_vector ) RETURN digit_vector IS
ALIAS sv
: std_logic_vector((s'LENGTH - 1) DOWNTO 0) IS s;
VARIABLE result : digit_vector(((s'LENGTH - 1) / digit_size) DOWNTO 0);
VARIABLE prod
: integer;
BEGIN
FOR i IN result'RANGE LOOP
prod := i * digit_size;
result(i) := sv((prod +(digit_size - 1)) DOWNTO prod);
END LOOP;
RETURN result;
END;
FUNCTION To_DigitVector ( s : std_ulogic_vector ) RETURN digit_vector IS
VARIABLE sv
: std_logic_vector((s'LENGTH - 1) DOWNTO 0) := To_StdLogicVector(s);
VARIABLE result : digit_vector(((s'LENGTH - 1) / digit_size) DOWNTO 0);
VARIABLE prod
: integer;
BEGIN
FOR i IN result'RANGE LOOP
prod := i * digit_size;
result(i) := sv((prod + (digit_size - 1)) DOWNTO prod);
END LOOP;
RETURN result;
END;
FUNCTION To_DigitVector ( u : udigit_vector
) RETURN digit_vector IS
ALIAS uv
: udigit_vector((u'LENGTH - 1) DOWNTO 0) IS u;
VARIABLE result : digit_vector((u'LENGTH - 1) DOWNTO 0);
BEGIN
FOR i IN result'RANGE LOOP
result(i) := uv(i);
END LOOP;
RETURN result;
END;
FUNCTION To_DigitVector ( s : string
) RETURN digit_vector IS
CONSTANT msb : integer := (s'LENGTH * 4);
ALIAS sv : string(s'LENGTH DOWNTO 1) IS s;
VARIABLE result : std_logic_vector((msb - 1) DOWNTO 0);
BEGIN
FOR i IN 0 TO (s'LENGTH - 1) LOOP
CASE sv(i + 1) IS
WHEN '0' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0000";
WHEN '1' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0001";
WHEN '2' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0010";
WHEN '3' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0011";
WHEN '4' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0100";
WHEN '5' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0101";
WHEN '6' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0110";
WHEN '7' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0111";
WHEN '8' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1000";
WHEN '9' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1001";
WHEN 'a' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1010";
WHEN 'b' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1011";
WHEN 'c' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1100";
WHEN 'd' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1101";
WHEN 'e' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1110";
WHEN 'f' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1111";
WHEN 'A' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1010";
WHEN 'B' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1011";
WHEN 'C' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1100";
WHEN 'D' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1101";
WHEN 'E' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1110";
WHEN 'F' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1111";
WHEN OTHERS =>
ASSERT FALSE
REPORT "failure in 'to_digitvector' function, S is not a hex string"
SEVERITY FAILURE;
END CASE;
END LOOP;
RETURN To_DigitVector(result);
END;
FUNCTION To_UDigitVector ( s : std_logic_vector ) RETURN udigit_vector IS
ALIAS sv
: std_logic_vector((s'LENGTH - 1) DOWNTO 0) IS s;
VARIABLE result : udigit_vector(((s'LENGTH - 1) / digit_size) DOWNTO 0);
VARIABLE prod
: integer;
BEGIN
FOR i IN result'RANGE LOOP
prod := i * digit_size;
result(i) := sv((prod + (digit_size - 1)) DOWNTO prod);
END LOOP;
RETURN result;
END;
FUNCTION To_UDigitVector ( s : std_ulogic_vector ) RETURN udigit_vector IS
VARIABLE sv
: std_logic_vector((s'LENGTH - 1) DOWNTO 0) := To_StdLogicVector(s);
VARIABLE result : udigit_vector(((s'LENGTH - 1) / digit_size) DOWNTO 0);
VARIABLE prod
: integer;
BEGIN
FOR i IN result'RANGE LOOP
prod := i * digit_size;
result(i) := sv((prod + (digit_size - 1)) DOWNTO prod);
Seite 61
END LOOP;
RETURN result;
END;
FUNCTION To_UDigitVector ( d : digit_vector
) RETURN udigit_vector IS
ALIAS dv
: digit_vector((d'LENGTH - 1) DOWNTO 0) IS d;
VARIABLE result : udigit_vector((d'LENGTH - 1) DOWNTO 0);
BEGIN
FOR i IN result'RANGE LOOP
result(i) := dv(i);
END LOOP;
RETURN result;
END;
FUNCTION To_UDigitVector ( s : string
) RETURN udigit_vector IS
CONSTANT msb : integer := (s'LENGTH * 4);
ALIAS sv : string((s'LENGTH) DOWNTO 1) IS s;
VARIABLE result : std_logic_vector((msb - 1) DOWNTO 0);
BEGIN
FOR i IN 0 TO (s'LENGTH - 1) LOOP
CASE sv(i + 1) IS
WHEN '0' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0000";
WHEN '1' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0001";
WHEN '2' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0010";
WHEN '3' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0011";
WHEN '4' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0100";
WHEN '5' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0101";
WHEN '6' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0110";
WHEN '7' => result(((i * 4) + 3) DOWNTO (i * 4)) := "0111";
WHEN '8' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1000";
WHEN '9' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1001";
WHEN 'a' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1010";
WHEN 'b' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1011";
WHEN 'c' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1100";
WHEN 'd' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1101";
WHEN 'e' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1110";
WHEN 'f' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1111";
WHEN 'A' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1010";
WHEN 'B' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1011";
WHEN 'C' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1100";
WHEN 'D' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1101";
WHEN 'E' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1110";
WHEN 'F' => result(((i * 4) + 3) DOWNTO (i * 4)) := "1111";
WHEN OTHERS =>
ASSERT FALSE
REPORT "failure in 'to_udigitvector' function, S is not a hex string"
SEVERITY FAILURE;
END CASE;
END LOOP;
RETURN To_UDigitVector(result);
END;
FUNCTION To_String ( u : udigit_vector ) RETURN string IS
CONSTANT string_length : integer := (u'LENGTH * digit_size)/4;
CONSTANT std_length
: integer := u'LENGTH * digit_size;
ALIAS uv : udigit_vector((u'LENGTH - 1) DOWNTO 0) IS u;
VARIABLE temp : std_logic_vector((std_length - 1) DOWNTO 0);
VARIABLE temp2 : std_logic_vector(3 DOWNTO 0);
VARIABLE result : string (string_length DOWNTO 1);
BEGIN
temp := To_StdLogicVector(uv);
FOR i IN 0 TO (string_length - 1) LOOP
temp2 := temp(((i * 4) + 3) DOWNTO (i * 4));
CASE temp2 IS
WHEN "0000" => result(i + 1) := '0';
WHEN "0001" => result(i + 1) := '1';
WHEN "0010" => result(i + 1) := '2';
WHEN "0011" => result(i + 1) := '3';
WHEN "0100" => result(i + 1) := '4';
WHEN "0101" => result(i + 1) := '5';
WHEN "0110" => result(i + 1) := '6';
WHEN "0111" => result(i + 1) := '7';
WHEN "1000" => result(i + 1) := '8';
WHEN "1001" => result(i + 1) := '9';
WHEN "1010" => result(i + 1) := 'A';
WHEN "1011" => result(i + 1) := 'B';
WHEN "1100" => result(i + 1) := 'C';
WHEN "1101" => result(i + 1) := 'D';
WHEN "1110" => result(i + 1) := 'E';
WHEN "1111" => result(i + 1) := 'F';
WHEN OTHERS => result(i + 1) := 'X';
END CASE;
END LOOP;
RETURN result;
END;
FUNCTION To_String ( d : digit_vector ) RETURN string IS
CONSTANT string_length : integer := (d'LENGTH * digit_size)/4;
CONSTANT std_length
: integer := d'LENGTH * digit_size;
ALIAS dv : digit_vector((d'LENGTH - 1) DOWNTO 0) IS d;
VARIABLE temp : std_logic_vector((std_length - 1) DOWNTO 0);
VARIABLE temp2 : std_logic_vector(3 DOWNTO 0);
VARIABLE result : string (string_length DOWNTO 1);
BEGIN
temp := To_StdLogicVector(dv);
FOR i IN 0 TO (string_length - 1) LOOP
temp2 := temp(((i * 4) + 3) DOWNTO (i * 4));
CASE temp2 IS
WHEN "0000" => result(i + 1) := '0';
WHEN "0001" => result(i + 1) := '1';
WHEN "0010" => result(i + 1) := '2';
WHEN "0011" => result(i + 1) := '3';
WHEN "0100" => result(i + 1) := '4';
WHEN "0101" => result(i + 1) := '5';
WHEN "0110" => result(i + 1) := '6';
Seite 62
WHEN "0111"
WHEN "1000"
WHEN "1001"
WHEN "1010"
WHEN "1011"
WHEN "1100"
WHEN "1101"
WHEN "1110"
WHEN "1111"
WHEN OTHERS
END CASE;
END LOOP;
RETURN result;
END ;
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
result(i
result(i
result(i
result(i
result(i
result(i
result(i
result(i
result(i
result(i
+
+
+
+
+
+
+
+
+
+
1)
1)
1)
1)
1)
1)
1)
1)
1)
1)
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
'7';
'8';
'9';
'A';
'B';
'C';
'D';
'E';
'F';
'X';
-- pragma synthesis_on
END mp_logic;
Seite 63
A1.2 DATEI: MP_ARITH.VHD
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
LIBRARY WORK;
USE WORK.mp_logic.all;
PACKAGE mp_arith IS
-- pragma synthesis_off
------------------------------------------------------------------------------ overloaded "+" functions with two arguments
----------------------------------------------------------------------------FUNCTION "+" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector;
FUNCTION "+" ( l : digit; r : udigit_vector ) RETURN udigit_vector;
FUNCTION "+" ( l : udigit_vector; r : digit ) RETURN udigit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"+"
"+"
"+"
"+"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"+"
"+"
"+"
"+"
"+"
"+"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ overloaded "-" functions with two arguments
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"-"
"-"
"-"
"-"
"-"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
r
:
:
:
:
:
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"-"
"-"
"-"
"-"
"-"
"-"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ overloaded functions with one argument
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"+" (
"+" (
"-" (
"-" (
"-" (
"ABS"
l
l
l
l
l
(
:
:
:
:
:
l
udigit_vector ) RETURN udigit_vector;
digit_vector ) RETURN digit_vector;
udigit_vector ) RETURN udigit_vector;
udigit_vector ) RETURN digit_vector;
digit_vector ) RETURN digit_vector;
: digit_vector ) RETURN digit_vector;
------------------------------------------------------------------------------ overloaded "*" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"*"
"*"
"*"
"*"
"*"
"*"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
udigit_vector; r
digit; r : digit
udigit_vector; r
udigit_vector; r
digit_vector; r
digit_vector; r
:
)
:
:
:
:
udigit_vector ) RETURN
RETURN udigit_vector;
udigit_vector ) RETURN
digit_vector ) RETURN
udigit_vector ) RETURN
digit_vector ) RETURN
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"*"
"*"
"*"
"*"
"*"
"*"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ overloaded "/" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/"
"/"
"/"
"/"
"/"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
r
:
:
:
:
:
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/"
"/"
"/"
"/"
"/"
"/"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ overloaded "<" functions
----------------------------------------------------------------------------FUNCTION "<" ( l : udigit_vector; r : udigit_vector ) RETURN boolean;
FUNCTION "<" ( l : udigit_vector; r : digit_vector ) RETURN boolean;
FUNCTION "<" ( l : digit_vector; r : udigit_vector ) RETURN boolean;
Seite 64
FUNCTION "<" ( l : digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"<"
"<"
"<"
"<"
(
(
(
(
l
l
l
l
:
:
:
:
r : digit_vector
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
)
)
)
)
) RETURN boolean;
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
------------------------------------------------------------------------------ overloaded "<=" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
"<="
"<="
"<="
"<="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"<="
"<="
"<="
"<="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
------------------------------------------------------------------------------ overloaded ">" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
">"
">"
">"
">"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
">"
">"
">"
">"
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
------------------------------------------------------------------------------ overloaded ">=" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
">="
">="
">="
">="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
">="
">="
">="
">="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
------------------------------------------------------------------------------ overloaded "=" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
"="
"="
"="
"="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"="
"="
"="
"="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
------------------------------------------------------------------------------ overloaded "/=" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/="
"/="
"/="
"/="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
:
:
:
:
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"/="
"/="
"/="
"/="
(
(
(
(
l
l
l
l
:
:
:
:
udigit_vector; r : integer
integer; r : udigit_vector
digit_vector; r : integer
integer; r : digit_vector
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
boolean;
------------------------------------------------------------------------------ overloaded shift functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
SHL
SHL
SHL
SHL
(
(
(
(
ARG
ARG
ARG
ARG
:
:
:
:
udigit_vector; COUNT : udigit_vector
digit_vector; COUNT : udigit_vector
udigit_vector; COUNT : integer
digit_vector; COUNT : integer
)
)
)
)
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
udigit_vector;
digit_vector;
FUNCTION
FUNCTION
FUNCTION
FUNCTION
SHR
SHR
SHR
SHR
(
(
(
(
ARG
ARG
ARG
ARG
:
:
:
:
udigit_vector; COUNT : udigit_vector
digit_vector; COUNT : udigit_vector
udigit_vector; COUNT : integer
digit_vector; COUNT : integer
)
)
)
)
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
udigit_vector;
digit_vector;
------------------------------------------------------------------------------ conversion functions
----------------------------------------------------------------------------FUNCTION CONV_INTEGER ( ARG : udigit_vector ) RETURN integer;
FUNCTION CONV_INTEGER ( ARG : digit_vector ) RETURN integer;
FUNCTION CONV_DIGIT_VECTOR
FUNCTION CONV_DIGIT_VECTOR
FUNCTION CONV_DIGIT_VECTOR
( ARG : udigit_vector; SIZE : integer ) RETURN digit_vector;
( ARG : digit_vector; SIZE : integer ) RETURN digit_vector;
( ARG : integer; SIZE : integer
) RETURN digit_vector;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : udigit_vector; SIZE : integer ) RETURN udigit_vector;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : digit_vector; SIZE : integer ) RETURN udigit_vector;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : integer; SIZE : integer
) RETURN udigit_vector;
Seite 65
-- pragma synthesis_on
END mp_arith;
----------------------------------------------------------------------------------PACKAGE BODY mp_arith IS
-- pragma synthesis_off
FUNCTION max ( L, R : integer ) RETURN integer IS
BEGIN
IF L > R THEN
RETURN L;
ELSE
RETURN R;
END IF;
END;
FUNCTION min ( L, R : integer ) RETURN integer IS
BEGIN
IF L < R THEN
RETURN L;
ELSE
RETURN R;
END IF;
END;
FUNCTION mult ( a, b : digit_vector ) RETURN digit_vector IS
VARIABLE av
: UNSIGNED(((a'LENGTH * digit_size) - 1) DOWNTO 0) ;
VARIABLE bv
: UNSIGNED(((b'LENGTH * digit_size) - 1) DOWNTO 0);
VARIABLE result : UNSIGNED( (((a'LENGTH + b'LENGTH) * digit_size) - 1) DOWNTO 0);
VARIABLE neg
: std_logic;
BEGIN
neg := a(a'LEFT)(digit_size - 1) XOR b(b'LEFT)(digit_size - 1);
av := UNSIGNED(To_StdLogicVector(ABS(a)));
bv := UNSIGNED(To_StdLogicVector(ABS(b)));
result := av * bv;
IF (neg = '1') THEN
RETURN -To_DigitVector(std_logic_vector(result));
ELSE
RETURN To_DigitVector(std_logic_vector(result));
END IF;
END;
FUNCTION division ( a, b : digit_vector ) RETURN digit_vector IS
CONSTANT q_width : positive := a'LENGTH * digit_size;
VARIABLE bv : UNSIGNED(((b'LENGTH * digit_size) - 1) DOWNTO 0);
VARIABLE quotient, z : UNSIGNED((q_width - 1) DOWNTO 0);
VARIABLE neg : std_logic;
BEGIN
IF (b = 0) THEN
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
neg := a(a'LEFT)(digit_size - 1) XOR b(b'LEFT)(digit_size - 1);
bv := UNSIGNED(To_StdLogicVector(ABS(b)));
z := UNSIGNED(To_StdLogicVector(ABS(a)));
quotient := (OTHERS => '0');
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
quotient(q_width-i) := '1';
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
IF (neg = '1') THEN
RETURN -To_DigitVector(std_logic_vector(quotient));
ELSE
RETURN To_DigitVector(std_logic_vector(quotient));
END IF;
END;
FUNCTION minus ( a, b : digit_vector ) RETURN digit_vector IS
VARIABLE av, bv, sum : unsigned((a'LENGTH * digit_size - 1) DOWNTO 0);
BEGIN
av := unsigned(To_StdLogicVector(a));
bv := unsigned(To_StdLogicVector(b));
sum := av - bv;
RETURN To_DigitVector(std_logic_vector(sum));
END;
FUNCTION plus ( a, b : digit_vector ) RETURN digit_vector IS
VARIABLE av, bv, sum : unsigned((a'LENGTH * digit_size - 1) DOWNTO 0);
BEGIN
av := unsigned(To_StdLogicVector(a));
bv := unsigned(To_StdLogicVector(b));
sum := av + bv;
RETURN To_DigitVector(std_logic_vector(sum));
END;
Seite 66
FUNCTION is_less ( a, b : digit_vector ) RETURN boolean IS
CONSTANT sign : integer := a'LEFT;
VARIABLE result : boolean;
BEGIN
IF (a(sign)(digit_size - 1) /= b(sign)(digit_size - 1)) THEN
result := a(sign)(digit_size - 1) = '1';
ELSE
result := FALSE;
FOR i IN sign DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (a(i)(j) /= b(i)(j)) THEN
result := a(i)(j) = '0';
RETURN result;
END IF;
END LOOP;
END LOOP;
END IF;
RETURN result;
END;
FUNCTION is_less_or_equal ( a, b : digit_vector ) RETURN boolean IS
CONSTANT sign : integer := a'LEFT;
VARIABLE result : boolean;
BEGIN
IF (a(sign)(digit_size - 1) /= b(sign)(digit_size - 1)) THEN
result := a(sign)(digit_size - 1) = '1';
ELSE
result := TRUE;
FOR i IN sign DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (a(i)(j) /= b(i)(j)) THEN
result := a(i)(j) = '0';
RETURN result;
END IF;
END LOOP;
END LOOP;
END IF;
RETURN result;
END;
FUNCTION equal ( l, r : digit_vector ) RETURN boolean IS
BEGIN
FOR i IN l'RANGE LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (l(i)(j) /= r(i)(j)) THEN
RETURN FALSE;
END IF;
END LOOP;
END LOOP;
RETURN TRUE;
END;
FUNCTION not_equal ( l, r : digit_vector ) RETURN boolean IS
BEGIN
FOR i IN l'RANGE LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (l(i)(j) /= r(i)(j)) THEN
RETURN TRUE;
END IF;
END LOOP;
END LOOP;
RETURN FALSE;
END;
FUNCTION shift_left ( arg : digit_vector; count : integer ) RETURN digit_vector IS
CONSTANT msb
: integer := arg'LENGTH - 1;
VARIABLE result : digit_vector( msb DOWNTO 0 );
VARIABLE count2 : integer;
BEGIN
IF (count < 0) THEN
ASSERT FALSE
REPORT "failure in 'shift_left' function, COUNT have to be a positive integer"
SEVERITY FAILURE;
ELSE
IF (count <= msb) THEN
result(msb DOWNTO count) := arg((msb - count) DOWNTO 0);
IF (count /= 0) THEN
result((count - 1) DOWNTO 0) := (OTHERS => zero_digit);
END IF;
ELSE
result := (OTHERS => zero_digit);
END IF;
END IF;
RETURN result;
END;
FUNCTION shift_right ( arg : digit_vector; count : integer ) RETURN digit_vector IS
CONSTANT msb
: integer := ARG'LENGTH - 1;
VARIABLE result : digit_vector( msb DOWNTO 0 );
VARIABLE count2 : integer;
BEGIN
IF (count < 0) THEN
ASSERT FALSE
REPORT "failure in 'shift_right' function, COUNT have to be a positive integer"
SEVERITY FAILURE;
ELSE
IF (count <= msb) THEN
result((msb - count) DOWNTO 0) := arg(msb DOWNTO count);
IF (count /= 0) THEN
result(msb DOWNTO (msb - count + 1)) := (OTHERS => zero_digit);
END IF;
ELSE
result := (OTHERS => zero_digit);
END IF;
END IF;
Seite 67
RETURN result;
END;
FUNCTION unsigned_mult ( a, b : udigit_vector ) RETURN udigit_vector IS
VARIABLE av
: UNSIGNED(((a'LENGTH * digit_size) - 1) DOWNTO 0) ;
VARIABLE bv
: UNSIGNED(((b'LENGTH * digit_size) - 1) DOWNTO 0);
VARIABLE result : UNSIGNED( (((a'LENGTH + b'LENGTH) * digit_size) - 1) DOWNTO 0);
BEGIN
av := UNSIGNED(To_StdLogicVector(a));
bv := UNSIGNED(To_StdLogicVector(b));
result := av * bv;
RETURN To_UDigitVector(std_logic_vector(result));
END;
FUNCTION unsigned_division ( a, b : udigit_vector ) RETURN udigit_vector IS
CONSTANT q_width : positive := a'LENGTH * digit_size;
VARIABLE bv : UNSIGNED(((b'LENGTH * digit_size) - 1) DOWNTO 0);
VARIABLE quotient, z : UNSIGNED((q_width - 1) DOWNTO 0);
BEGIN
IF (b = 0) THEN
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
bv := UNSIGNED(To_StdLogicVector(b));
z := UNSIGNED(To_StdLogicVector(a));
quotient := (OTHERS => '0');
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
quotient(q_width-i) := '1';
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
RETURN To_UDigitVector(std_logic_vector(quotient));
END;
FUNCTION unsigned_minus ( a, b : udigit_vector ) RETURN udigit_vector IS
VARIABLE av, bv, sum : unsigned((a'LENGTH * digit_size - 1) DOWNTO 0);
BEGIN
av := unsigned(To_StdLogicVector(a));
bv := unsigned(To_StdLogicVector(b));
sum := av - bv;
RETURN To_UDigitVector(std_logic_vector(sum));
END;
FUNCTION unsigned_plus ( a, b : udigit_vector ) RETURN udigit_vector IS
VARIABLE av, bv, sum : unsigned((a'LENGTH * digit_size - 1) DOWNTO 0);
BEGIN
av := unsigned(To_StdLogicVector(a));
bv := unsigned(To_StdLogicVector(b));
sum := av + bv;
RETURN To_UDigitVector(std_logic_vector(sum));
END;
FUNCTION unsigned_is_less ( a, b : udigit_vector ) RETURN boolean IS
CONSTANT sign : integer := a'LEFT;
VARIABLE result : boolean;
BEGIN
result := FALSE;
FOR i IN sign DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (a(i)(j) /= b(i)(j)) THEN
result := a(i)(j) = '0';
RETURN result;
END IF;
END LOOP;
END LOOP;
RETURN result;
END;
FUNCTION unsigned_is_less_or_equal ( a, b : udigit_vector ) RETURN boolean IS
CONSTANT sign : integer := a'LEFT;
VARIABLE result : boolean;
BEGIN
result := TRUE;
FOR i IN sign DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (a(i)(j) /= b(i)(j)) THEN
result := a(i)(j) = '0';
RETURN result;
END IF;
END LOOP;
END LOOP;
RETURN result;
END;
FUNCTION unsigned_equal ( l, r : udigit_vector ) RETURN boolean IS
BEGIN
Seite 68
FOR i IN l'RANGE LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (l(i)(j) /= r(i)(j)) THEN
RETURN FALSE;
END IF;
END LOOP;
END LOOP;
RETURN TRUE;
END;
FUNCTION unsigned_not_equal ( l, r : udigit_vector ) RETURN boolean IS
BEGIN
FOR i IN l'RANGE LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF (l(i)(j) /= r(i)(j)) THEN
RETURN TRUE;
END IF;
END LOOP;
END LOOP;
RETURN FALSE;
END;
FUNCTION unsigned_shift_left ( arg : udigit_vector; count : integer ) RETURN udigit_vector IS
CONSTANT msb
: integer := arg'LENGTH - 1;
VARIABLE result : udigit_vector( msb DOWNTO 0 );
VARIABLE count2 : integer;
BEGIN
IF (count < 0) THEN
ASSERT FALSE
REPORT "failure in 'shift_left' function, COUNT have to be a positive integer"
SEVERITY FAILURE;
ELSE
IF (count <= msb) THEN
result(msb DOWNTO count) := arg((msb - count) DOWNTO 0);
IF (count /= 0) THEN
result((count - 1) DOWNTO 0) := (OTHERS => zero_digit);
END IF;
ELSE
result := (OTHERS => zero_digit);
END IF;
END IF;
RETURN result;
END;
FUNCTION unsigned_shift_right ( arg : udigit_vector; count : integer ) RETURN udigit_vector IS
CONSTANT msb
: integer := ARG'LENGTH - 1;
VARIABLE result : udigit_vector( msb DOWNTO 0 );
VARIABLE count2 : integer;
BEGIN
IF (count < 0) THEN
ASSERT FALSE
REPORT "failure in 'shift_right' function, COUNT have to be a positive integer"
SEVERITY FAILURE;
ELSE
IF (count <= msb) THEN
result((msb - count) DOWNTO 0) := arg(msb DOWNTO count);
IF (count /= 0) THEN
result(msb DOWNTO (msb - count + 1)) := (OTHERS => zero_digit);
END IF;
ELSE
result := (OTHERS => zero_digit);
END IF;
END IF;
RETURN result;
END;
------------------------------------------------------------------------------ overloaded "+" functions with two arguments
----------------------------------------------------------------------------FUNCTION "+" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_plus( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : digit; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := r'LENGTH;
VARIABLE lv : UDIGIT_VECTOR(0 DOWNTO 0);
BEGIN
lv(0) := l;
RETURN unsigned_plus( CONV_UDIGIT_VECTOR(lv, length), CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : udigit_vector; r : digit ) RETURN udigit_vector IS
CONSTANT length : integer := l'LENGTH;
VARIABLE rv : UDIGIT_VECTOR(0 DOWNTO 0);
BEGIN
rv(0) := r;
RETURN unsigned_plus( CONV_UDIGIT_VECTOR(l, length), CONV_UDIGIT_VECTOR(rv, length) );
END;
FUNCTION "+" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH + 1);
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
Seite 69
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN unsigned_plus( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN unsigned_plus( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : integer; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "+" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN plus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "-" functions with two arguments
----------------------------------------------------------------------------FUNCTION "-" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_minus( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH + 1);
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN unsigned_minus( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
Seite 70
FUNCTION "-" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN unsigned_minus( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : integer; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "-" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN minus( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded functions with one argument
----------------------------------------------------------------------------FUNCTION "+" ( l : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN l;
END;
FUNCTION "+" ( l : digit_vector
BEGIN
RETURN l;
END;
) RETURN digit_vector IS
FUNCTION "-" ( l : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN 0 - l;
END;
FUNCTION "-" ( l : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN 0 - l;
END;
FUNCTION "-" ( l : digit_vector
BEGIN
RETURN 0 - l;
END;
) RETURN digit_vector IS
FUNCTION "ABS" ( l : digit_vector ) RETURN digit_vector IS
BEGIN
IF (l(l'LEFT)(digit_size - 1) = '0') THEN
RETURN l;
ELSE
RETURN 0 - l;
END IF;
END;
------------------------------------------------------------------------------ overloaded "*" functions
----------------------------------------------------------------------------FUNCTION "*" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_mult( CONV_UDIGIT_VECTOR(l, l'LENGTH),
CONV_UDIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "*" ( l : digit; r : digit ) RETURN udigit_vector IS
VARIABLE lv : UDIGIT_VECTOR(0 DOWNTO 0);
VARIABLE rv : UDIGIT_VECTOR(0 DOWNTO 0);
BEGIN
lv(0) := l;
rv(0) := r;
RETURN unsigned_mult( CONV_UDIGIT_VECTOR(lv, 1), CONV_UDIGIT_VECTOR(rv, 1) );
END;
FUNCTION "*" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "*" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
Seite 71
END;
CONV_DIGIT_VECTOR(r, r'LENGTH) );
FUNCTION "*" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "*" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "*" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN unsigned_mult( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "*" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN unsigned_mult( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "*" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "*" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "*" ( l : integer; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "*" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN mult( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "/" functions
----------------------------------------------------------------------------FUNCTION "/" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_division( CONV_UDIGIT_VECTOR(l, l'LENGTH),
CONV_UDIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "/" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "/" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "/" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "/" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "/" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := r'LENGTH ;
BEGIN
RETURN unsigned_division( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "/" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN unsigned_division( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
Seite 72
FUNCTION "/" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/" ( l : integer; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN division( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "<" functions
----------------------------------------------------------------------------FUNCTION "<" ( l : udigit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_is_less( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : udigit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : digit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH+ 1);
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : digit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : udigit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : integer; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : digit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<" ( l : integer; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "<=" functions
----------------------------------------------------------------------------FUNCTION "<=" ( l : udigit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_is_less_or_equal( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "<=" ( l : udigit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
Seite 73
FUNCTION "<=" ( l : digit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<=" ( l : digit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<=" ( l : udigit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<=" ( l : integer; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<=" ( l : digit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "<=" ( l : integer; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded ">" functions
----------------------------------------------------------------------------FUNCTION ">" ( l : udigit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_is_less( CONV_UDIGIT_VECTOR(r, length),
CONV_UDIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : udigit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : digit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : digit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : udigit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : integer; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : digit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">" ( l : integer; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN is_less( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
------------------------------------------------------------------------------ overloaded ">=" functions
-----------------------------------------------------------------------------
Seite 74
FUNCTION ">=" ( l : udigit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_is_less_or_equal( CONV_UDIGIT_VECTOR(r, length),
CONV_UDIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : udigit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : digit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : digit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : udigit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : integer; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : digit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
FUNCTION ">=" ( l : integer; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN is_less_or_equal( CONV_DIGIT_VECTOR(r, length),
CONV_DIGIT_VECTOR(l, length) );
END;
------------------------------------------------------------------------------ overloaded "=" functions
----------------------------------------------------------------------------FUNCTION "=" ( l : udigit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_equal( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : udigit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : digit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : digit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : udigit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : integer; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : digit_vector; r : integer
CONSTANT length : integer := l'LENGTH;
) RETURN boolean IS
Seite 75
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "=" ( l : integer; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "/=" functions
----------------------------------------------------------------------------FUNCTION "/=" ( l : udigit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN unsigned_not_equal( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : udigit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH + 1, r'LENGTH);
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : digit_vector; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH + 1);
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : digit_vector; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : udigit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : integer; r : udigit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : digit_vector; r : integer ) RETURN boolean IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "/=" ( l : integer; r : digit_vector ) RETURN boolean IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN not_equal( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded shift functions
----------------------------------------------------------------------------FUNCTION SHL ( ARG : udigit_vector; COUNT : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_shift_left( CONV_UDIGIT_VECTOR(ARG, ARG'LENGTH),
CONV_INTEGER(COUNT) );
END;
FUNCTION SHL ( ARG : digit_vector; COUNT : udigit_vector
BEGIN
RETURN shift_left( CONV_DIGIT_VECTOR(ARG, ARG'LENGTH),
CONV_INTEGER(COUNT) );
END;
) RETURN digit_vector IS
FUNCTION SHL ( ARG : udigit_vector; COUNT : integer
) RETURN udigit_vector IS
BEGIN
RETURN unsigned_shift_left( CONV_UDIGIT_VECTOR(ARG, ARG'LENGTH),
COUNT );
END;
FUNCTION SHL ( ARG : digit_vector; COUNT : integer
BEGIN
RETURN shift_left( CONV_DIGIT_VECTOR(ARG, ARG'LENGTH),
COUNT );
END;
) RETURN digit_vector IS
FUNCTION SHR ( ARG : udigit_vector; COUNT : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_shift_right( CONV_UDIGIT_VECTOR(ARG, ARG'LENGTH),
CONV_INTEGER(COUNT) );
END;
Seite 76
FUNCTION SHR ( ARG : digit_vector; COUNT : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN shift_right( CONV_DIGIT_VECTOR(ARG, ARG'LENGTH),
CONV_INTEGER(COUNT) );
END;
FUNCTION SHR ( ARG : udigit_vector; COUNT : integer
) RETURN udigit_vector IS
BEGIN
RETURN unsigned_shift_right( CONV_UDIGIT_VECTOR(ARG, ARG'LENGTH),
COUNT );
END;
FUNCTION SHR ( ARG : digit_vector; COUNT : integer
) RETURN digit_vector IS
BEGIN
RETURN shift_right( CONV_DIGIT_VECTOR(ARG, ARG'LENGTH),
COUNT );
END;
------------------------------------------------------------------------------ conversion functions
----------------------------------------------------------------------------FUNCTION CONV_INTEGER ( ARG : udigit_vector ) RETURN integer IS
VARIABLE msb : integer := ARG'LENGTH - 1;
ALIAS argv : udigit_vector(msb DOWNTO 0) IS ARG;
VARIABLE result : integer := 0;
VARIABLE position : integer;
BEGIN
FOR i IN 0 TO msb LOOP
FOR j IN 0 TO (digit_size - 1) LOOP
IF (argv(i)(j) = '1') THEN
position := (i * digit_size) + j;
IF (position > 30) THEN
ASSERT FALSE
REPORT "ARG value is too large in 'conv_integer', it can not convert in a integer"
SEVERITY FAILURE;
ELSE
result := result + (2**position);
END IF;
END IF;
END LOOP;
END LOOP;
RETURN result;
END;
FUNCTION CONV_INTEGER ( ARG : digit_vector ) RETURN integer IS
VARIABLE msb : integer := ARG'LENGTH - 1;
VARIABLE argv : udigit_vector(msb DOWNTO 0) := To_UDigitVector(ABS(ARG));
VARIABLE result : integer := 0;
VARIABLE position : integer;
BEGIN
FOR i IN 0 TO msb LOOP
FOR j IN 0 TO (digit_size - 1) LOOP
IF (argv(i)(j) = '1') THEN
position := (i * digit_size) + j;
IF (position > 30) THEN
ASSERT FALSE
REPORT "ARG value is too large in 'conv_integer', it can not convert in a integer"
SEVERITY FAILURE;
ELSE
result := result + (2**position);
END IF;
END IF;
END LOOP;
END LOOP;
IF (ARG(ARG'LEFT)(digit_size - 1) = '1') THEN
RETURN -result;
ELSE
RETURN result;
END IF;
END;
FUNCTION CONV_DIGIT_VECTOR ( ARG : udigit_vector; SIZE : integer ) RETURN digit_vector IS
CONSTANT msb
: integer := min(ARG'LENGTH, SIZE) - 1;
VARIABLE argv
: digit_vector(msb DOWNTO 0) := To_DigitVector(ARG);
VARIABLE result : digit_vector((SIZE - 1) DOWNTO 0);
BEGIN
IF ((argv(msb)(digit_size - 1) = '1') AND (msb = (SIZE - 1))) THEN
ASSERT FALSE
REPORT "failure in 'conv_digit_vector' function, use a larger SIZE"
SEVERITY FAILURE;
ELSE
result := (OTHERS => zero_digit);
result(msb DOWNTO 0) := argv;
END IF;
RETURN result;
END;
FUNCTION CONV_DIGIT_VECTOR ( ARG : digit_vector; SIZE : integer ) RETURN digit_vector IS
CONSTANT msb
: integer := min(ARG'LENGTH, SIZE) - 1;
ALIAS argv
: digit_vector(msb DOWNTO 0) IS ARG;
VARIABLE result : digit_vector((SIZE - 1) DOWNTO 0);
BEGIN
IF (argv(msb)(digit_size - 1) = '1') THEN
result := (OTHERS => max_digit);
ELSE
result := (OTHERS => zero_digit);
END IF;
result(msb DOWNTO 0) := argv;
RETURN result;
END;
FUNCTION CONV_DIGIT_VECTOR ( ARG : integer; SIZE : integer
VARIABLE result : digit_vector((SIZE - 1) DOWNTO 0);
) RETURN digit_vector IS
Seite 77
VARIABLE temp
: integer := ARG;
BEGIN
FOR i IN 0 TO (SIZE - 1) LOOP
FOR j IN 0 TO (digit_size - 1) LOOP
IF ((temp mod 2) = 1) THEN
result(i)(j) := '1';
ELSE
result(i)(j) := '0';
END IF;
IF (temp > 0) THEN
temp := temp / 2;
ELSE
IF (temp > integer'low) THEN
temp := (temp - 1) / 2;
ELSE
temp := temp / 2;
END IF;
END IF;
END LOOP;
END LOOP;
RETURN result;
END;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : udigit_vector; SIZE : integer ) RETURN udigit_vector IS
CONSTANT msb
: integer := min(ARG'LENGTH, SIZE) - 1;
ALIAS argv
: udigit_vector(msb DOWNTO 0) IS ARG;
VARIABLE result : udigit_vector((SIZE - 1) DOWNTO 0);
BEGIN
result := (OTHERS => zero_digit);
result(msb DOWNTO 0) := argv;
RETURN result;
END;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : digit_vector; SIZE : integer ) RETURN udigit_vector IS
CONSTANT msb
: integer := min(ARG'LENGTH, SIZE) - 1;
VARIABLE argv
: udigit_vector(msb DOWNTO 0) := To_UDigitVector(ARG);
VARIABLE result : udigit_vector((SIZE - 1) DOWNTO 0);
BEGIN
IF (argv(msb)(digit_size - 1) = '1') THEN
ASSERT FALSE
REPORT "failure in 'conv_udigit_vector' function, it is not possible to convert a negative digit_vector in a udigit_vector"
SEVERITY FAILURE;
ELSE
result := (OTHERS => zero_digit);
result(msb DOWNTO 0) := argv;
END IF;
RETURN result;
END;
FUNCTION CONV_UDIGIT_VECTOR ( ARG : integer; SIZE : integer
) RETURN udigit_vector IS
VARIABLE result : udigit_vector((SIZE - 1) DOWNTO 0);
VARIABLE temp
: integer := ARG;
BEGIN
IF (ARG < 0) THEN
ASSERT FALSE
REPORT "failure in 'conv_udigit_vector' function, it is not possible to convert a negative integer in a udigit_vector"
SEVERITY FAILURE;
ELSE
FOR i IN 0 TO (SIZE - 1) LOOP
FOR j IN 0 TO (digit_size - 1) LOOP
IF ((temp mod 2) = 1) THEN
result(i)(j) := '1';
ELSE
result(i)(j) := '0';
END IF;
IF (temp > 0) THEN
temp := temp / 2;
ELSE
IF (temp > integer'low) THEN
temp := (temp - 1) / 2;
ELSE
temp := temp / 2;
END IF;
END IF;
END LOOP;
END LOOP;
END IF;
RETURN result;
END;
-- pragma synthesis_on
END mp_arith;
Seite 78
A1.3 DATEI: MP_STD_LOGIC.VHD
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
PACKAGE mp_std_logic IS
-- pragma synthesis_off
------------------------------------------------------------------------------ overloaded "/" functions
----------------------------------------------------------------------------FUNCTION "/" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "/" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "/" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
------------------------------------------------------------------------------ overloaded "mod" functions
----------------------------------------------------------------------------FUNCTION "mod" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "mod" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "mod" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
------------------------------------------------------------------------------ overloaded "rem" functions
----------------------------------------------------------------------------FUNCTION "rem" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "rem" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "rem" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
------------------------------------------------------------------------------ overloaded "**" functions
----------------------------------------------------------------------------FUNCTION "**" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "**" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector;
FUNCTION "**" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector;
------------------------------------------------------------------------------ modular exponentation
----------------------------------------------------------------------------FUNCTION modexp ( b, e, m : std_logic_vector ) RETURN std_logic_vector;
-- pragma synthesis_on
END mp_std_logic;
----------------------------------------------------------------------------------PACKAGE BODY mp_std_logic IS
-- pragma synthesis_off
FUNCTION max ( L, R : integer ) RETURN integer IS
BEGIN
IF L > R THEN
RETURN L;
ELSE
RETURN R;
END IF;
END;
FUNCTION division ( a, b : std_logic_vector ) RETURN std_logic_vector IS
CONSTANT q_width : positive := a'LENGTH;
VARIABLE quotient, z, bv : UNSIGNED((q_width - 1) DOWNTO 0);
BEGIN
IF (b = 0) THEN
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
bv := UNSIGNED(b);
z := UNSIGNED(a);
quotient := (OTHERS => '0');
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
quotient(q_width-i) := '1';
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
RETURN std_logic_vector(quotient);
END;
FUNCTION modulo ( a, b : std_logic_vector ) RETURN std_logic_vector IS
CONSTANT q_width : positive := a'LENGTH;
CONSTANT r_width : positive := b'LENGTH;
VARIABLE z : UNSIGNED((q_width - 1) DOWNTO 0);
VARIABLE result, bv : UNSIGNED((r_width - 1) DOWNTO 0);
BEGIN
IF (b = 0) THEN
Seite 79
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
bv := UNSIGNED(b);
z := UNSIGNED(a);
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
result := z((r_width - 1) DOWNTO 0);
RETURN std_logic_vector(result);
END;
FUNCTION power ( a, b : std_logic_vector ) RETURN std_logic_vector IS
VARIABLE av : unsigned((a'LENGTH - 1) DOWNTO 0);
VARIABLE bv : unsigned((b'LENGTH - 1) DOWNTO 0);
VARIABLE result : unsigned(((a'LENGTH * b'LENGTH) - 1) DOWNTO 0);
BEGIN
av := unsigned(a);
bv := unsigned(b);
result := (OTHERS => '0');
result(0) := '1';
FOR i IN (bv'LENGTH - 1) DOWNTO 0 LOOP
result := result * result;
IF (av(i) = '1') THEN
result := result * av;
END IF;
END LOOP;
RETURN std_logic_vector(result);
END;
------------------------------------------------------------------------------ overloaded "/" functions
----------------------------------------------------------------------------FUNCTION "/" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector IS
CONSTANT length : integer := max(l'LENGTH, r'LENGTH);
BEGIN
RETURN division( CONV_STD_LOGIC_VECTOR(unsigned(l), length),
CONV_STD_LOGIC_VECTOR(unsigned(r), length) );
END;
FUNCTION "/" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN division( CONV_STD_LOGIC_VECTOR(unsigned(l), length),
CONV_STD_LOGIC_VECTOR(r, length) );
END;
FUNCTION "/" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN division( CONV_STD_LOGIC_VECTOR(l, length),
CONV_STD_LOGIC_VECTOR(unsigned(r), length) );
END;
------------------------------------------------------------------------------ overloaded "mod" functions
----------------------------------------------------------------------------FUNCTION "mod" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector IS
BEGIN
RETURN modulo( CONV_STD_LOGIC_VECTOR(unsigned(l), l'LENGTH),
CONV_STD_LOGIC_VECTOR(unsigned(r), r'LENGTH) );
END;
FUNCTION "mod" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector IS
BEGIN
RETURN modulo( CONV_STD_LOGIC_VECTOR(unsigned(l), l'LENGTH),
CONV_STD_LOGIC_VECTOR(r, l'LENGTH) );
END;
FUNCTION "mod" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN modulo( CONV_STD_LOGIC_VECTOR(l, r'LENGTH),
CONV_STD_LOGIC_VECTOR(unsigned(r), r'LENGTH) );
END;
------------------------------------------------------------------------------ overloaded "rem" functions
----------------------------------------------------------------------------FUNCTION "rem" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector IS
BEGIN
RETURN modulo( CONV_STD_LOGIC_VECTOR(unsigned(l), l'LENGTH),
CONV_STD_LOGIC_VECTOR(unsigned(r), r'LENGTH) );
END;
FUNCTION "rem" ( l : std_logic_vector; r : integer
CONSTANT length : integer := l'LENGTH;
BEGIN
) RETURN std_logic_vector IS
Seite 80
RETURN modulo( CONV_STD_LOGIC_VECTOR(unsigned(l), l'LENGTH),
CONV_STD_LOGIC_VECTOR(r, l'LENGTH) );
END;
FUNCTION "rem" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN modulo( CONV_STD_LOGIC_VECTOR(l, r'LENGTH),
CONV_STD_LOGIC_VECTOR(unsigned(r), r'LENGTH) );
END;
------------------------------------------------------------------------------ overloaded "**" functions
----------------------------------------------------------------------------FUNCTION "**" ( l : std_logic_vector; r : std_logic_vector ) RETURN std_logic_vector IS
BEGIN
RETURN power( CONV_STD_LOGIC_VECTOR(unsigned(l), l'LENGTH),
CONV_STD_LOGIC_VECTOR(unsigned(r), r'LENGTH) );
END;
FUNCTION "**" ( l : std_logic_vector; r : integer
) RETURN std_logic_vector IS
BEGIN
RETURN power( CONV_STD_LOGIC_VECTOR(unsigned(l), l'LENGTH),
CONV_STD_LOGIC_VECTOR(r, l'LENGTH) );
END;
FUNCTION "**" ( l : integer;
r : std_logic_vector ) RETURN std_logic_vector IS
BEGIN
RETURN power( CONV_STD_LOGIC_VECTOR(l, r'LENGTH),
CONV_STD_LOGIC_VECTOR(unsigned(r), r'LENGTH) );
END;
------------------------------------------------------------------------------ modular exponentation
----------------------------------------------------------------------------FUNCTION modexp ( b, e, m : std_logic_vector ) RETURN std_logic_vector IS
ALIAS bv : std_logic_vector((b'LENGTH - 1) DOWNTO 0) IS b;
ALIAS ev : std_logic_vector((e'LENGTH - 1) DOWNTO 0) IS e;
ALIAS mv : std_logic_vector((m'LENGTH - 1) DOWNTO 0) IS m;
VARIABLE result : std_logic_vector((m'LENGTH - 1) DOWNTO 0);
BEGIN
result := (OTHERS => '0');
result(0) := '1';
FOR i IN (e'LENGTH - 1) DOWNTO 0 LOOP
result := (result * result) mod mv;
IF (ev(i) = '1') THEN
result := (bv * result) mod mv;
END IF;
END LOOP;
RETURN result;
END;
-- pragma synthesis_on
END mp_std_logic;
Seite 81
A1.4 DATEI: MP_CRYPT.VHD
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
LIBRARY work;
USE work.mp_logic.all;
USE work.mp_arith.all;
USE work.mp_std_logic.all;
PACKAGE mp_crypt IS
-- pragma synthesis_off
------------------------------------------------------------------------------ overloaded "mod" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"mod"
"mod"
"mod"
"mod"
"mod"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
r
:
:
:
:
:
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"mod"
"mod"
"mod"
"mod"
"mod"
"mod"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ overloaded "rem" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"rem"
"rem"
"rem"
"rem"
"rem"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
r
:
:
:
:
:
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"rem"
"rem"
"rem"
"rem"
"rem"
"rem"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ overloaded "**" functions
----------------------------------------------------------------------------FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"**"
"**"
"**"
"**"
"**"
(
(
(
(
(
l
l
l
l
l
:
:
:
:
:
udigit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
r
r
r
r
r
:
:
:
:
:
udigit_vector
udigit_vector
digit_vector
udigit_vector
digit_vector
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
FUNCTION
"**"
"**"
"**"
"**"
"**"
"**"
(
(
(
(
(
(
l
l
l
l
l
l
:
:
:
:
:
:
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : udigit_vector
udigit_vector; r : integer
integer; r : digit_vector
digit_vector; r : integer
)
)
)
)
)
)
)
)
)
)
)
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
RETURN
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
udigit_vector;
udigit_vector;
digit_vector;
digit_vector;
digit_vector;
digit_vector;
------------------------------------------------------------------------------ modular exponentation
----------------------------------------------------------------------------FUNCTION modexp ( b, e, m : udigit_vector ) RETURN udigit_vector;
FUNCTION modexp ( b, e, m : digit_vector ) RETURN digit_vector;
------------------------------------------------------------------------------ extended functions
----------------------------------------------------------------------------FUNCTION gcd ( a, b : udigit_vector ) RETURN udigit_vector;
FUNCTION euclid ( e, phi : udigit_vector ) RETURN udigit_vector;
PROCEDURE rnd ( CONSTANT length : IN integer; VARIABLE seed : INOUT udigit_vector; VARIABLE number : OUT udigit_vector );
FUNCTION prim ( p : udigit_vector; t : integer ) RETURN boolean;
PROCEDURE RSA ( CONSTANT length : IN integer; VARIABLE seed : INOUT udigit_vector; VARIABLE p, q, e, d, n : OUT udigit_vector );
-- pragma synthesis_on
END mp_crypt;
----------------------------------------------------------------------------------PACKAGE BODY mp_crypt IS
-- pragma synthesis_off
FUNCTION max ( L, R : integer ) RETURN integer IS
BEGIN
IF L > R THEN
RETURN L;
ELSE
RETURN R;
END IF;
END;
FUNCTION remainder ( a, b : digit_vector ) RETURN digit_vector IS
CONSTANT q_width : positive := a'LENGTH * digit_size;
Seite 82
CONSTANT r_width : positive := b'LENGTH * digit_size;
VARIABLE bv : UNSIGNED((r_width - 1) DOWNTO 0);
VARIABLE z : UNSIGNED((q_width - 1) DOWNTO 0);
VARIABLE result : UNSIGNED((r_width - 1) DOWNTO 0);
BEGIN
IF (b = 0) THEN
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
bv := UNSIGNED(To_StdLogicVector(ABS(b)));
z := UNSIGNED(To_StdLogicVector(ABS(a)));
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
result := z((r_width - 1) DOWNTO 0);
IF (a(a'LEFT)(digit_size - 1) = '1') THEN
RETURN -To_DigitVector(std_logic_vector(result));
ELSE
RETURN To_DigitVector(std_logic_vector(result));
END IF;
END;
FUNCTION modulo ( a, b : digit_vector ) RETURN digit_vector IS
CONSTANT q_width : positive := a'LENGTH * digit_size;
CONSTANT r_width : positive := b'LENGTH * digit_size;
VARIABLE bv : UNSIGNED((r_width - 1) DOWNTO 0);
VARIABLE z : UNSIGNED((q_width - 1) DOWNTO 0);
VARIABLE abs_result, result : digit_vector((b'LENGTH - 1) DOWNTO 0);
BEGIN
IF (b = 0) THEN
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
bv := UNSIGNED(To_StdLogicVector(ABS(b)));
z := UNSIGNED(To_StdLogicVector(ABS(a)));
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
abs_result := To_DigitVector(std_logic_vector(z((r_width - 1) DOWNTO 0)));
IF ( (b(b'LEFT)(digit_size - 1) = '1') OR (a(a'LEFT)(digit_size - 1) = '1') ) THEN
IF (abs_result = 0) THEN
result := abs_result;
ELSE
IF ( (b(b'LEFT)(digit_size - 1) = '0') AND (a(a'LEFT)(digit_size - 1) = '1') ) THEN
result := b - abs_result;
ELSE
IF ( (b(b'LEFT)(digit_size - 1) = '1') AND (a(a'LEFT)(digit_size - 1) = '1') ) THEN
result := 0 - abs_result;
ELSE
result := b + abs_result;
END IF;
END IF;
END IF;
ELSE
result := abs_result;
END IF;
RETURN result;
END;
FUNCTION power ( a, b : digit_vector ) RETURN digit_vector IS
VARIABLE result : digit_vector(((a'LENGTH * b'LENGTH) - 1) DOWNTO 0);
VARIABLE av : digit_vector(a'LEFT DOWNTO 0);
VARIABLE tdigit, tbit : integer := 0;
BEGIN
IF (b < 0) THEN
ASSERT FALSE
REPORT "exponent have to be a positive digit_vector"
SEVERITY FAILURE;
ELSE
result := (OTHERS => zero_digit);
result := result + 1;
IF (b > 0) THEN
av := ABS(a);
FOR i IN b'LEFT DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF ((b(i)(j) = '1') AND (tdigit = 0) AND (tbit = 0)) THEN
tdigit := i;
tbit
:= j;
END IF;
END LOOP;
END LOOP;
Seite 83
IF (tbit /= 0) THEN
FOR i IN tbit DOWNTO 0 LOOP
result := result * result;
IF (b(tdigit)(i) = '1') THEN
result := result * av;
END IF;
END LOOP;
tdigit := tdigit - 1;
END IF;
IF (tdigit >= 0) THEN
FOR i IN tdigit DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
result := result * result;
IF (b(i)(j) = '1') THEN
result := result * av;
END IF;
END LOOP;
END LOOP;
END IF;
END IF;
END IF;
IF ((a(0)(0) = '1') AND (a(a'LEFT)(digit_size - 1) = '1')) THEN
RETURN -result;
ELSE
RETURN result;
END IF;
END;
FUNCTION unsigned_modulo ( a, b : udigit_vector ) RETURN udigit_vector IS
CONSTANT q_width : positive := a'LENGTH * digit_size;
CONSTANT r_width : positive := b'LENGTH * digit_size;
VARIABLE bv : UNSIGNED((r_width - 1) DOWNTO 0);
VARIABLE z : UNSIGNED((q_width - 1) DOWNTO 0);
VARIABLE result : UNSIGNED((r_width - 1) DOWNTO 0);
BEGIN
IF (b = 0) THEN
ASSERT FALSE
REPORT "division by zero"
SEVERITY FAILURE;
ELSE
bv := UNSIGNED(To_StdLogicVector(b));
z := UNSIGNED(To_StdLogicVector(a));
FOR i IN 1 TO q_width LOOP
IF (z(q_width-1 DOWNTO q_width-i) >= bv) THEN
IF (i <= bv'LENGTH) THEN
z(q_width-1 DOWNTO q_width-i)
:= z(q_width-1 DOWNTO q_width-i) - bv(i-1 DOWNTO 0);
ELSE
z(q_width-i+bv'LENGTH DOWNTO q_width-i)
:= z(q_width-i+bv'LENGTH DOWNTO q_width-i) - bv(bv'LENGTH-1 DOWNTO 0);
END IF;
END IF;
END LOOP;
END IF;
result := z((r_width - 1) DOWNTO 0);
RETURN To_UDigitVector(std_logic_vector(result));
END;
FUNCTION unsigned_power ( a, b : udigit_vector ) RETURN udigit_vector IS
VARIABLE result : udigit_vector(((a'LENGTH * b'LENGTH) - 1) DOWNTO 0);
VARIABLE tdigit, tbit : integer := 0;
BEGIN
result := (OTHERS => zero_digit);
result := result + 1;
IF (b > 0) THEN
FOR i IN b'LEFT DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
IF ((b(i)(j) = '1') AND (tdigit = 0) AND (tbit = 0)) THEN
tdigit := i;
tbit
:= j;
END IF;
END LOOP;
END LOOP;
IF (tbit /= 0) THEN
FOR i IN tbit DOWNTO 0 LOOP
result := result * result;
IF (b(tdigit)(i) = '1') THEN
result := result * a;
END IF;
END LOOP;
tdigit := tdigit - 1;
END IF;
IF (tdigit >= 0) THEN
FOR i IN tdigit DOWNTO 0 LOOP
FOR j IN (digit_size - 1) DOWNTO 0 LOOP
result := result * result;
IF (b(i)(j) = '1') THEN
result := result * a;
END IF;
END LOOP;
END LOOP;
END IF;
END IF;
RETURN result;
END;
------------------------------------------------------------------------------ overloaded "mod" functions
----------------------------------------------------------------------------FUNCTION "mod" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_modulo( CONV_UDIGIT_VECTOR(l, l'LENGTH),
Seite 84
END;
CONV_UDIGIT_VECTOR(r, r'LENGTH) );
FUNCTION "mod" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "mod" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "mod" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, (r'LENGTH) + 1) );
END;
FUNCTION "mod" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "mod" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN unsigned_modulo( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(l, length) );
END;
FUNCTION "mod" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN unsigned_modulo( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "mod" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH + 1;
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "mod" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH + 1;
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "mod" ( l : integer; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : integer := r'LENGTH;
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "mod" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : integer := l'LENGTH;
BEGIN
RETURN modulo( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "rem" functions
----------------------------------------------------------------------------FUNCTION "rem" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_modulo( CONV_UDIGIT_VECTOR(l ,l'LENGTH),
CONV_UDIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "rem" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "rem" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l, (l'LENGTH + 1)),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "rem" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, (r'LENGTH + 1)) );
END;
FUNCTION "rem" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "rem" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : positive := r'LENGTH;
Seite 85
BEGIN
RETURN unsigned_modulo( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "rem" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : positive := l'LENGTH;
BEGIN
RETURN unsigned_modulo( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "rem" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : positive := r'LENGTH + 1;
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l ,length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "rem" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : positive := l'LENGTH + 1;
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l ,length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "rem" ( l : integer; r : digit_vector ) RETURN digit_vector IS
CONSTANT length : positive := r'LENGTH;
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l ,length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "rem" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : positive := l'LENGTH;
BEGIN
RETURN remainder( CONV_DIGIT_VECTOR(l ,length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ overloaded "**" functions
----------------------------------------------------------------------------FUNCTION "**" ( l : udigit_vector; r : udigit_vector ) RETURN udigit_vector IS
BEGIN
RETURN unsigned_power( CONV_UDIGIT_VECTOR(l, l'LENGTH),
CONV_UDIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "**" ( l : udigit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, l'LENGTH + 1),
CONV_DIGIT_VECTOR(r, r'LENGTH + 1) );
END;
FUNCTION "**" ( l : udigit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, l'LENGTH + 1),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "**" ( l : digit_vector; r : udigit_vector ) RETURN digit_vector IS
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, r'LENGTH + 1) );
END;
FUNCTION "**" ( l : digit_vector; r : digit_vector ) RETURN digit_vector IS
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, l'LENGTH),
CONV_DIGIT_VECTOR(r, r'LENGTH) );
END;
FUNCTION "**" ( l : integer; r : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : positive := r'LENGTH;
BEGIN
RETURN unsigned_power( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "**" ( l : udigit_vector; r : integer ) RETURN udigit_vector IS
CONSTANT length : positive := l'LENGTH;
BEGIN
RETURN unsigned_power( CONV_UDIGIT_VECTOR(l, length),
CONV_UDIGIT_VECTOR(r, length) );
END;
FUNCTION "**" ( l : integer; r : udigit_vector ) RETURN digit_vector IS
CONSTANT length : positive := r'LENGTH + 1;
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "**" ( l : udigit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : positive := l'LENGTH + 1;
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "**" ( l : integer; r : digit_vector
CONSTANT length : positive := r'LENGTH;
BEGIN
) RETURN digit_vector IS
Seite 86
RETURN power( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
FUNCTION "**" ( l : digit_vector; r : integer ) RETURN digit_vector IS
CONSTANT length : positive := l'LENGTH;
BEGIN
RETURN power( CONV_DIGIT_VECTOR(l, length),
CONV_DIGIT_VECTOR(r, length) );
END;
------------------------------------------------------------------------------ modular exponentation
----------------------------------------------------------------------------FUNCTION modexp ( b, e, m : udigit_vector ) RETURN udigit_vector IS
VARIABLE result : std_logic_vector((m'LENGTH * digit_size - 1) DOWNTO 0);
BEGIN
result := modexp( To_StdLogicVector(b), To_StdLogicVector(e), To_StdLogicVector(m) );
RETURN To_UDigitVector(result);
END;
FUNCTION modexp ( b, e, m : digit_vector ) RETURN digit_vector IS
VARIABLE result : std_logic_vector((m'LENGTH * digit_size - 1) DOWNTO 0);
BEGIN
result := modexp( To_StdLogicVector(b), To_StdLogicVector(e), To_StdLogicVector(m) );
RETURN To_DigitVector(result);
END;
------------------------------------------------------------------------------ gcd function
----------------------------------------------------------------------------FUNCTION gcd ( a, b : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := max(a'LENGTH, b'LENGTH);
VARIABLE av, bv, r : udigit_vector((length - 1) DOWNTO 0);
BEGIN
av := (OTHERS => zero_digit);
bv := (OTHERS => zero_digit);
IF (a >= b) THEN
av((a'LENGTH - 1) DOWNTO 0) := a;
bv((b'LENGTH - 1) DOWNTO 0) := b;
ELSE
av((b'LENGTH - 1) DOWNTO 0) := b;
bv((a'LENGTH - 1) DOWNTO 0) := a;
END IF;
WHILE (bv /= 0) LOOP
r := av mod bv;
av := bv;
bv := r;
END LOOP;
RETURN av;
END;
------------------------------------------------------------------------------ extended euclidean function
----------------------------------------------------------------------------FUNCTION euclid ( e, phi : udigit_vector ) RETURN udigit_vector IS
CONSTANT length : integer := max(e'LENGTH, phi'LENGTH);
VARIABLE a, b, r, q, result : udigit_vector((length - 1) DOWNTO 0) := (OTHERS => zero_digit);
VARIABLE x, y, s : digit_vector(length DOWNTO 0);
VARIABLE st : digit_vector((2 * (length + 1) - 1) DOWNTO 0);
BEGIN
a((phi'LENGTH - 1) DOWNTO 0) := phi;
b((e'LENGTH - 1) DOWNTO 0)
:= e;
x := (OTHERS => zero_digit);
y := (OTHERS => zero_digit);
y(0) := one_digit;
q := a / b;
r := a mod b;
WHILE (r > 0) LOOP
st := x - (q * y);
IF (st >= 0) THEN
s := st mod phi;
ELSE
s := phi - (-st mod phi);
END IF;
x := y;
y := s;
a := b;
b := r;
q := a / b;
r := a mod b;
END LOOP;
IF (b /=
result
ELSE
s := y
result
END IF;
1) THEN
:= (OTHERS => zero_digit);
mod phi;
:= To_UDigitVector(s(length - 1 DOWNTO 0));
RETURN result;
END;
------------------------------------------------------------------------------ random nuber generation
----------------------------------------------------------------------------PROCEDURE rnd ( CONSTANT length : IN integer; VARIABLE seed : INOUT udigit_vector; VARIABLE number : OUT udigit_vector ) IS
VARIABLE m : udigit_vector(length DOWNTO 0) := (OTHERS => zero_digit);
VARIABLE a : udigit_vector((length) DOWNTO 0) := (OTHERS => zero_digit);
Seite 87
VARIABLE temp : udigit_vector((length + seed'LENGTH) DOWNTO 0);
VARIABLE result : udigit_vector((length) DOWNTO 0);
BEGIN
-- linear-congruence generator
m(length)(0) := '1';
a(length/2)(0) := '1';
a(0)(0) := '1';
temp := (a * seed) + 1;
-result := ((a * seed) + 1) mod m;
result := (OTHERS => zero_digit);
result((length - 1) DOWNTO 0) := temp((length - 1) DOWNTO 0);
number(number'length-1 downto length) := (OTHERS => zero_digit);
seed(seed'length-1 downto length)
:= (OTHERS => zero_digit);
number((length - 1) DOWNTO 0) := (result((length - 1) DOWNTO 0));
seed((length - 1) DOWNTO 0)
:= result((length - 1) DOWNTO 0);
END;
------------------------------------------------------------------------------ primaly test
----------------------------------------------------------------------------FUNCTION prim ( p : udigit_vector; t : integer ) RETURN boolean IS
-- "n is prim !" (true or false)
VARIABLE a, m, z, j, p1, p2 : udigit_vector((p'LENGTH - 1) DOWNTO 0);
VARIABLE b : integer;
VARIABLE seed : udigit_vector((p'LENGTH - 1) DOWNTO 0);
VARIABLE plength, i : integer;
BEGIN
-- Miller-Rabin test
-- error probability is (1/4)**t
plength := p'LENGTH;
WHILE ((p(plength - 1) = 0) AND (p /= 0)) LOOP
plength := plength - 1;
END LOOP;
seed := p;
IF (p(0)(0) = '0') THEN
RETURN FALSE;
END IF;
p1 := p - 1;
p2 := p - 2;
b := 0;
FOR i IN 0 TO (p'LENGTH - 1) LOOP
FOR j IN 0 TO (digit_size - 1) LOOP
IF ((p1(i)(j) = '1') AND (b = 0)) THEN
b := ((i*digit_size) + j);
END IF;
END LOOP;
END LOOP;
m := p1 / (2**b);
FOR i IN 1 TO t LOOP
rnd(plength, seed, a);
WHILE ((a > p2) OR (a < 2)) LOOP
rnd(plength, seed, a);
END LOOP;
z := modexp(a, m, p); --(a**m) mod p;
IF ((z /= 1) AND (z /= p1)) THEN
j := (OTHERS => zero_digit);
j := j + 1;
WHILE ((j < b) AND (z /= p1)) LOOP
z := modexp(z, CONV_UDIGIT_VECTOR(2, z'LENGTH), p); --(z**2) mod p;
IF (z = 1) THEN
RETURN FALSE;
END IF;
j := j + 1;
END LOOP;
IF (z /= p1) THEN
RETURN FALSE;
END IF;
END IF;
END LOOP;
RETURN TRUE;
END;
------------------------------------------------------------------------------ RSA-key generation
----------------------------------------------------------------------------PROCEDURE RSA ( CONSTANT length : IN integer; VARIABLE seed : INOUT udigit_vector; VARIABLE p, q, e, d, n : OUT udigit_vector ) IS
VARIABLE pv, qv, ev, dv, nv : udigit_vector((length - 1) DOWNTO 0) := (OTHERS => zero_digit);
VARIABLE phi : udigit_vector((length - 1) DOWNTO 0);
VARIABLE pqlength : integer := (length /2);
VARIABLE test, test2 : boolean;
CONSTANT security : integer := 4;
VARIABLE nv_temp, phi_temp : udigit_vector(((2 * length) - 1) DOWNTO 0);
VARIABLE pv1, qv1 : udigit_vector((length - 1) DOWNTO 0);
BEGIN
-- p generation and prim test
test := TRUE;
WHILE (test) LOOP
pv := (OTHERS => zero_digit);
rnd(pqlength + 2, seed, pv);
pv(0)(0) := '1';
pv(pqlength + 1)(digit_size - 1) := '1';
IF (prim(pv, security)) THEN
test := FALSE;
END IF;
END LOOP;
Seite 88
-- q generation and prim test
test := TRUE;
WHILE (test) LOOP
rnd(pqlength - 2, seed, qv);
qv(0)(0) := '1';
qv(pqlength - 3)(digit_size - 1) := '1';
IF (prim(qv, security) AND (qv /= pv)) THEN
test := FALSE;
END IF;
END LOOP;
nv_temp := pv * qv;
nv
:= nv_temp((nv'LENGTH - 1) DOWNTO 0);
pv1 := pv - 1;
qv1 := qv - 1;
phi_temp := pv1 * qv1;
phi := phi_temp((phi'LENGTH - 1) DOWNTO 0);
test := TRUE;
WHILE (test) LOOP
-- e generation
test2 := TRUE;
WHILE (test2) LOOP
rnd(length/4, seed, ev);
IF ((gcd(ev, phi) = 1) AND (ev < nv)) THEN
test2 := FALSE;
END IF;
END LOOP;
-- d generation with euclidean algorithm
dv := euclid(ev, phi);
IF ((gcd(dv, phi) = 1) AND (gcd(dv, ev) = 1) AND (dv < nv)) THEN
test := FALSE;
END IF;
END LOOP;
-- return
p := pv;
q := qv;
e := ev;
d := dv;
n := nv;
END;
-- pragma synthesis_on
END mp_crypt;
Seite 89
B Die Quellen für das C-Interfaces
B1 Das Addiererbeispiel
B1.1 DATEI: ADDER.VHD
LIBRARY synopsys;
USE synopsys.attributes.all;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY adder IS
GENERIC (
delay : time := 5 ns
);
PORT (
a : IN integer;
b : IN integer;
c : OUT integer
);
END adder;
-- Ausgangsverzögerung
ARCHITECTURE CLI OF adder IS
ATTRIBUTE FOREIGN OF CLI : ARCHITECTURE IS "SYNOPSYS:CLI";
ATTRIBUTE
ATTRIBUTE
ATTRIBUTE
ATTRIBUTE
CLI_ELABORATE
CLI_EVALUATE
CLI_CLOSE
CLI_ERROR
OF
OF
OF
OF
CLI
CLI
CLI
CLI
:
:
:
:
ARCHITECTURE
ARCHITECTURE
ARCHITECTURE
ARCHITECTURE
IS
IS
IS
IS
"adder_open";
"adder_eval";
"adder_close";
"adder_error";
ATTRIBUTE CLI_PIN OF a : SIGNAL IS CLI_EVENT;
ATTRIBUTE CLI_PIN OF b : SIGNAL IS CLI_EVENT;
BEGIN
END CLI;
B1.2 DATEI: ADDER_COMP.VHD
LIBRARY ieee;
USE ieee.std_logic_1164.all;
PACKAGE adder_comp IS
COMPONENT adder
GENERIC (
delay : time := 5 ns
);
PORT (
a : IN integer;
b : IN integer;
c : OUT integer
);
END COMPONENT;
END;
B1.3 DATEI: ADDER.H
#define CHECK_ERRNO
exit(1) ;}
if(cli_errno) { (void) printf("file %s, line %d\n",__FILE__,__LINE__); cliPrintError((char *)0);
B1.4 DATEI: ADDER.C
#include <stdio.h>
#include "adder.h"
#include "cli.h"
typedef struct
{
cliPID pidA;
cliPID pidB;
cliPID pidC;
cliGID gidDelay;
cliAFTER gvCDelay;
} ADDER_INSTANCE_DATA;
/*
/*
/*
/*
/*
Pin ID für "a" */
Pin ID für "b" */
Pin ID für "c" */
ID für "delay" */
Ausgangsverzögerung für C */
void adder_open(did, iid)
cliDID did;
cliIID iid;
{
ADDER_INSTANCE_DATA *adder_idata;
cliVALUE gvDelay;
/* Speicher für die Datenstruktur reservieren */
adder_idata = (ADDER_INSTANCE_DATA *) cliAllocMem(sizeof(ADDER_INSTANCE_DATA));
Seite 90
/* Pins und Generics auf die Datenstruktur abbilden */
adder_idata->pidA = cliPortName2PID(did, "A");
CHECK_ERRNO;
adder_idata->pidB = cliPortName2PID(did, "B");
CHECK_ERRNO;
adder_idata->pidC = cliPortName2PID(did, "C");
CHECK_ERRNO;
adder_idata->gidDelay = cliGenericName2GID(did, "DELAY");
CHECK_ERRNO;
/* Ausgansverzögerung setzen */
cliGetGenericValue(did, iid, adder_idata->gidDelay, &gvDelay);
CHECK_ERRNO
adder_idata->gvCDelay.delaytype = INERTIAL;
adder_idata->gvCDelay.delay.low = gvDelay.value.time.low;
adder_idata->gvCDelay.delay.high = 0;
adder_idata->gvCDelay.delay.timebase = gvDelay.value.time.timebase;
/* die Datenstruktur sichern */
cliSaveInstanceData(did, iid, (void *) adder_idata);
CHECK_ERRNO;
}
void adder_close(did, iid)
cliDID did;
cliIID iid;
{
ADDER_INSTANCE_DATA *adder_idata;
/* Datenstruktur wiederherstellen */
adder_idata = (ADDER_INSTANCE_DATA *) cliRestoreInstanceData(did,iid);
}
/* reservierten Speicher für die Datenstruktur freigeben */
if(adder_idata != (ADDER_INSTANCE_DATA *)0)
{
cliFreeMem((void *) adder_idata);
}
void adder_eval(did, iid, ppid, np)
cliDID did;
cliIID iid;
cliPID *ppid; /* Zeiger auf die Pin-IDs (Pinliste) */
int np;
/* Anzahl Pins in der Pinliste */
{
ADDER_INSTANCE_DATA *adder_idata;
cliVALUE svA;
cliVALUE svB;
cliVALUE svC;
/* Datenstruktur wiederherstellen */
adder_idata = (ADDER_INSTANCE_DATA *) cliRestoreInstanceData(did,iid);
cliGetPortValue(did, iid, adder_idata->pidA, &svA);
CHECK_ERRNO;
cliGetPortValue(did, iid, adder_idata->pidB, &svB);
CHECK_ERRNO;
svC.typemark = CLI_TYPE_INTEGER;
svC.length = 0;
svC.value.integer = svA.value.integer + svB.value.integer;
}
cliScheduleOutput(did, iid, adder_idata->pidC, &svC, &adder_idata->gvCDelay);
CHECK_ERRNO;
void adder_error(did, iid, level)
cliDID did;
cliIID iid;
int level;
{
char *s;
if(level == 0)
s = "WARNUNG";
else
s = "FEHLER";
}
(void) printf("%s gefunden mit (%d,%d)\n",s,did,iid);
cliPrintError("ADDER FEHLER");
Seite 91
B2 Die Meßfunktion
B2.1 DATEI: BENCHMARK.VHD
LIBRARY synopsys;
USE synopsys.attributes.all;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE work.benchmark_comp.all;
ENTITY benchmark IS
PORT (
ready : IN std_logic;
prtime : OUT string(1 TO 30)
);
END;
ARCHITECTURE CLI OF benchmark IS
ATTRIBUTE FOREIGN OF CLI : ARCHITECTURE IS "Synopsys:CLI";
ATTRIBUTE
ATTRIBUTE
ATTRIBUTE
ATTRIBUTE
CLI_ELABORATE
CLI_EVALUATE
CLI_ERROR
CLI_CLOSE
OF
OF
OF
OF
CLI
CLI
CLI
CLI
:
:
:
:
ARCHITECTURE
ARCHITECTURE
ARCHITECTURE
ARCHITECTURE
IS
IS
IS
IS
"benchmark_open";
"benchmark_eval";
"benchmark_error";
"benchmark_close";
ATTRIBUTE CLI_PIN OF ready : SIGNAL IS CLI_ACTIVE;
BEGIN
END;
CONFIGURATION cfg_benchmark OF benchmark IS
FOR CLI
END FOR;
END cfg_benchmark;
B2.2 DATEI: BENCHMARK_COMP.VHD
LIBRARY ieee;
USE ieee.std_logic_1164.all;
PACKAGE benchmark_comp IS
COMPONENT benchmark
PORT (
ready : IN std_logic;
prtime : OUT string(1 TO 30)
);
END COMPONENT;
END;
B2.3 DATEI: BENCHMARK.H
#define CHECK_ERRNO
exit(1); }
if(cli_errno) { (void) printf("file %s, line %d\n",__FILE__,__LINE__); cliPrintError((char *)0);
B2.4 DATEI: BENCHMARK.C
#include
#include
#include
#include
#include
<stdio.h>
<sys/types.h>
<sys/timeb.h>
"benchmark.h"
"cli.h"
typedef struct
{
cliPID pidReady;
cliPID pidPrTime;
cliAFTER afterPROP;
} BENCHMARK_INSTANCE_DATA;
double Time_F(s)
int s;
{
static struct timeb tstart, tend;
long i;
double ret;
switch(s)
{
case 2:
printf("\n--------------------- ENDE -------------------------------\n\n");
ftime(&tend);
i = (long)tend.millitm - (long)tstart.millitm;
ret = ((double)(tend.time - tstart.time)) + ((double)i) / 1000.0;
printf("Rechenzeit: %21.3f Sekunden\n\n--------------------- ENDE -------------------------------\n\n", ret);
break;
Seite 92
case 3:
printf("\n--------------------- START ------------------------------\n\n");
ret = (double)0;
ftime(&tstart);
break;
}
default:
break;
return (ret);
}
void benchmark_open(did, iid)
cliDID did;
cliIID iid;
{
BENCHMARK_INSTANCE_DATA *benchmark_idata;
benchmark_idata = (BENCHMARK_INSTANCE_DATA *) cliAllocMem(sizeof(BENCHMARK_INSTANCE_DATA));
benchmark_idata->pidReady = cliPortName2PID(did,"READY");
CHECK_ERRNO;
benchmark_idata->pidPrTime = cliPortName2PID(did,"PRTIME");
CHECK_ERRNO;
cliSaveInstanceData(did,iid,(void *) benchmark_idata);
CHECK_ERRNO;
}
void benchmark_close(did, iid)
cliDID did;
cliIID iid;
{
BENCHMARK_INSTANCE_DATA *benchmark_idata;
benchmark_idata = (BENCHMARK_INSTANCE_DATA *) cliRestoreInstanceData(did,iid);
if(benchmark_idata != (BENCHMARK_INSTANCE_DATA *)0)
{
cliFreeMem((void *) benchmark_idata);
}
}
void benchmark_eval(did, iid, ppid, np)
cliDID did;
/* definition ID */
cliIID iid;
/* instance ID */
cliPID *ppid;
/* pointer to pin IDs (pin list) */
int np;
/* number of pins in pin list */
{
int ready_value = 0;
int i;
double prtime;
unsigned char temp_string[31];
unsigned char temp;
cliVALUE svReady;
cliVALUE svPrTime;
BENCHMARK_INSTANCE_DATA *benchmark_idata;
benchmark_idata = (BENCHMARK_INSTANCE_DATA *) cliRestoreInstanceData(did,iid);
cliAssert(np == 1);
cliAssert(ppid[0] == benchmark_idata->pidReady);
cliGetPortValue(did, iid, benchmark_idata->pidReady, &svReady);
CHECK_ERRNO;
cliAssert(svReady.typemark == CLI_TYPE_STD_LOGIC);
ready_value = svReady.value.std_logic;
prtime = Time_F(ready_value);
sprintf(temp_string, "%21.3f Sekunden", prtime);
/* string umdrehen für vhdl */
for(i = 0; i < 15; i++)
{
temp = temp_string[i];
temp_string[i] = temp_string[29-i];
temp_string[29-i] = temp;
}
/* neu */
svPrTime.typemark = CLI_TYPE_STRING;
svPrTime.length
= 30;
svPrTime.direction = TO;
svPrTime.value.string = temp_string;
cliScheduleOutput(did, iid, benchmark_idata->pidPrTime, &svPrTime, &benchmark_idata->afterPROP);
CHECK_ERRNO;
}
void benchmark_error(did, iid, level)
cliDID did;
cliIID iid;
Seite 93
{
int level;
char *s;
if(level == 0)
s = "warning";
else
s = "fatal error";
(void) printf("%s encountered with (%d,%d)\n",s,did,iid);
cliPrintError("benchmark_error");
}
Seite 94
Herunterladen