Page 1
ΠΑΝΕΠΙΣΤΉΜΙΟ ΠΑΤΡΏΝ
ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ Η/Υ ΚΑΙ ΠΛΗΡΟΦΟΡΙΚΗΣ
Ανάπτυξη Soft Processor σε ολοκληρωμένο προγραμματιζόμενηςλογικής και σύγκριση των επιδόσεων του έναντι λύσεων υλικού
και λογισμικού
ΔΙΠΛΩΜΑΤΙΚΗ ΕΡΓΑΣΙΑ
του
ΚΕΝΆΤΣΟ ΧΡΉΣΤΟΥ(ΑΜ:5545)
Επιβλέπων : Χαρίδημος Βέργος
Πάτρα, 2019
Page 4
- 4 -
Περίληψη
Οι απαιτήσεις των εφαρμογών αυξάνονται ραγδαία με την πάροδο του χρόνου. Έτσι ο χρήστης θα
πρέπει να αλλάξει τα στοιχεία που χρησιμοποιεί ή να αλλάξει των τρέχον σχεδιασμό του ώστε να
ανταποκρίνεται στις απαιτήσεις που προέκυψαν. Αυτό είναι χρονοβόρο και δαπανηρό, οπότε οι χρήστες
ψάχνουν λύσεις που να παρέχουν ευελιξία ως προς τον σχεδιασμό τους.
Μια λύση είναι οι soft processor,όπως ο Microblaze της Xilinx τον οποίο θα χρησιμοποιήσουμε σε
αυτή την διπλωματική. Ο Microblaze μπορεί να υλοποιηθεί σε πολλές εναλλακτικές μορφές και μπορεί
να χρησιμοποιηθεί ως microcontroller ή ως ενσωματωμένος επεξεργαστής πάνω στα FPGAς. Σε αυτή την
διπλωματική θα δούμε τα πλεονεκτήματα και τα μειονεκτήματα του Microblaze σε σχέση με λύσεις
υλικού και λογισμικού. Θα αντιμετωπίσουμε τα ίδια προβλήμματα με τρεις τρόπους (α) με την γλώσσα
περιγραφής υλικού Verilog, (β) με την γλώσσα προγραμματισμού C και (γ) με τον soft processor
Microblaze,και θα συγκρίνουμε τους χρόνους εκτέλεσης κάθε υλοποίησης. Με αυτό τον τρόπο θα
μπορέσουμε να μάθουμε σε ποιόν τύπο προβλημμάτων συμφέρει τον χρήστης να χρησιμοποιήσει έναν
soft processor σαν τον Microblaze κα σε ποιά όχι.
Page 5
- 5 -
Περιεχόμενα
Κεφαλαιο 1:FPGA………………….... . . . . . . . . . . . . . . . . . . . . .……….... . . . . . . . . . . . .…………………..7
1.1 Τι είναι FPGA………………………………………..... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .………7
1.2 Περιγραφή του FPGA που χρησιμοποιήθηκε...............................................................……………….13
Κεφαλαιο 2:Περιγράφη Microblaze... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17
2.1 Περιγραφη του Soft procesor................................................................................................................17
Κεφαλαιο 3:Περιγραφή προβλημματων... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28
3.1 Πρόβλημμα 1ο: Διάνυσμα επί διάνυσμα................................................................................................28
3.2 Πρόβλημμα 2ο:Κόσκινο του Ερατοσθένη..............................................................................................30
3.3 Πρόβλημμα 3ο:RNS Assisted Image Filtering and Edge Detection .....................................................32
3.4 Πρόβλημμα 4ο:Υπολογισμός απόστασης ανάµεσασε δύο διανύσµατα................................................33
3.5 Πρόβλημμα 5ο: Τέλειοι αριθμοί.............................................................................................................34
3.6 Πρόβλημμα 6ο: Ακολουθία Fibonacci...................................................................................................35
3.7 Πρόβλημμα 7ο:Κωδικοποίηση Δέλτα....................................................................................................36
3.8 Πρόβλημμα 8ο:Bubble sort....................................................................................................................37
3.9 Πρόβλημμα 9ο: Ακολουθία Hailstone....................................................................................................37
Κεφαλαιο 4:Αποτελέσματα και Συμπεράσματα.....................................................................................38
Βιβλιογραφία..............................................................................................................................................46
Page 6
- 6 -
Λεξικό
FPGA - Field Programmable Gate Array - Συστοιχία Επιτόπιων Προγραμματιζόμενων Πυλών
PLL - Phase-locked loop - Βρόχος Κλειδώματος Φάσης
DSP - Digital Signal Processing - Ψηφιακή Επεξεργασία Σημάτων
HDL - Hardware Description Language - Γλώσσα Περιγραφής Υλικού
PLD - Programmable Logic Devices - Προγραμματιζόμενες λογικές συσκευές
ASIC - Aplication Specific Intergrated System - Ολοκληρωμένο κύκλωμα για συγκεκριμένη εφαρμογή
CLB - Configurable Logic Block - Λογικό μπλόκ
LUT - Look -Up table - Πίνακας αναζήτησης
SOC - System-on-chip
FFT - Fast Fourier Transform - Γρήγορος μετασχηματισμός Φουριέ
SRAM - Static Random-Access Memory - Στατική μνήμη τυχαίας προσπέλασης
PROM - Programmable Read-Only Memory - Προγραμματιζόμενη μνήμη μόνο για ανάγνωση
EPROM - Erasable Programmable Read-Only Memory - Διαγράψιμη προγραμματιζόμενη μνήμη μόνο
για ανάγνωση
EEPROM - Electrically Erasable Programmable Read-Only Memory - Ηλεκτρικά διαγράψιμη
προγραμματιζόμενη μνήμη μόνο για ανάγνωση
DRAM - Dynamic Random-Access Memory - Δυναμική μνήμη τυχαίας προσπέλασης
RISC - Reduced Instruction Set Computer - Υπολογιστής περιορισμένου συνόλου εντολών
Page 7
- 7 -
ΚΕΦΑΛΑΙΟ 1
1.1 Τι είναι FPGA
Το FPGAs (Field Programmable Gate Arrays) ή συστοιχία επιτόπιων προγραμματιζόμενων
πυλών είναι τύπος προγραμματιζόμενων ολοκληρωμένων κυκλωμάτων γενικής χρήσης τα οποία
διαθέτουν πολύ μεγάλο αριθμό τυποποιημένων προγραμματιζόμενων μπλοκ και μια ιεραρχία από
διαμορφώσιμες διασυνδέσεις που επιτρέπουν στα blocks αυτά να συνδέονται μεταξύ τους. Πολλά FPGAς
περιλαμβάνουν και διάφορες άλλες ψηφιακές λειτουργίες όπως απαριθμητές, καταχωρητές μνήμης,
γεννήτριες PLL, DSP slices κα. Σε ορισμένα από αυτά ενσωματώνονται και αναλογικές λειτουργίες.
Κατά τον προγραμματισμό του FPGA ενεργοποιούνται οι επιθυμητές λειτουργίες έτσι ώστε το FPGA να
συμπεριφέρεται ως ολοκληρωμένο κύκλωμα με συγκεκριμένη λειτουργία. Το αρχείο προγραμματισμού
συνήθως προκύπτει απο την σύνθεση ενός κυκλώματος που περιγράφεται σε κάποια HDL.
Η ύπαρξη των FPGAs οφείλεται στο κενό που παρατηρήθηκε ότι υπάρχει στο “φάσμα” των
ψηφιακών ολοκληρωμένων κυκλωμάτων στις αρχές της δεκαετίας του '90. Από την μία πλευρά υπήρχαν
τα PLDs (Programmable Logic Devices), τα οποία ήταν σε πολύ μεγάλο βαθμό προγραμματιζόμενα και
απαιτούσαν πολύ μικρούς χρόνους σχεδίασης αλλά αδυνατούσαν να υλοποιήσουν πολύ μεγάλες ή και
πολύπλοκες λογικές συναρτήσεις. Από την άλλη πλευρά ήταν τα ASICs (Application-Specific Integrated
Circuits), τα οποία μπορούσαν να υλοποιήσουν πολύ μεγάλες και πολύπλοκες λογικές συναρτήσεις αλλά
ο χρόνος και το κόστος σχεδίασής τους ήταν εξαιρετικά μεγάλα. Επίσης στα ASICs η τελική σχεδίαση
κατασκευάζεται άπαξ για μια συγκεκριμένη εφαρμογή και δεν υπάρχει στο εξής δυνατότητα αλλαγής της
λειτουργικότητάς τους. Ένα FPGA μπορεί να προγραμματιστεί απεριόριστες φορές και συνεπώς να
αλλάζει λειτουργικότητα ανάλογα με τις εκάστοτε απαιτήσεις του χρήστη.
Ένα σημαντικό μειονέκτημά τους είναι ότι τα FPGAs δεν είναι πλήρως εξατομικευμένα στοιχεία
σχεδιασμού και για αυτό δεν είναι τόσο βέλτιστα όσο θα ήταν ένα πλήρως εξατομικευμένο
ολοκληρωμένο που σχεδιάζεται για μια συγκεκριμένη εφαρμογή. Τα FPGAs επιτυγχάνουν συνήθως
μικρότερες ταχύτητες υπολογισμού και καταναλώνουν μεγαλύτερη ενέργεια σε σχέση με την αντίστοιχη
εξατομικευμένη λογική. Επίσης είναι σχετικά πιο ακριβά σε σχέση με τα ολοκληρωμένα κυκλώματα
εξατομικευμένου σχεδιασμού.
Εν τούτοις, παρουσιάζουν σημαντικά πλεονεκτήματα κυρίως εξαιτίας του γεγονότος ότι αποτελούν
τυποποιημένα κυκλώματα.Μερικά απο αυτά είναι τα παρακάτω
Δεν υπάρχει ανάγκη για μακρά αναμονή από τη στιγμή του σχεδιασμού του κυκλώματος μέχρι την
υλοποίησή του. Το κύκλωμα μπορεί να προγραμματιστεί στο FPGA και να ελεγχθεί η
λειτουργικότητά του άμεσα.
Page 8
- 8 -
Τα FPGAs είναι τέλειο όχημα για τη πρωτοτυποποίηση. Εάν χρησιμοποιηθεί στο τελικό σχεδιασμό η
μετάβαση από το πρωτότυπο σχέδιο στο τελικό προϊόν είναι βραχύχρονη και εύκολη διαδικασία.
Το ίδιο FPGA μπορεί να χρησιμοποιηθεί στο σχεδιασμό πολλών κυκλωμάτων μειώνοντας αρκετά το
κόστος.
Όπως αναφέραμε τα FPGA αποτελούνται από έναν ολοένα και αυξανόμενο αριθμό λογικών μπλοκ
και από ένα πλήθος διασυνδέσεων μεταξύ των μπλοκ. Τόσο τα λογικά μπλοκς όσο και οι διασυνδέσεις
είναι προγραμματιζόμενα. Έτσι, κάθε λογικό μπλοκ μπορεί να προγραμματιστεί ώστε να εκτελεί μια
συγκεκριμένη λειτουργία και πολλά λογικά μπλοκ μπορούν να διασυνδεθούν μεταξύ τους για να
διαμορφωθεί το τελικό κύκλωμα. Όταν ο χρήστης προγραμματίζει, το FPGA, καθορίζει τη λογική
συμπεριφορά των μπλοκ αυτών και τις συνδέσεις που υφίστανται μεταξύ τους. Οι πυκνότητες των
λογικών πυλών στα FPGA κυμαίνονται από μερικές χιλιάδες έως μερικά εκατομμύρια λογικές πύλες.
Μια τυπική αρχιτεκτονική των FPGAς ( εικόνα από Xilinx Inc ) φαίνεται στην Εικόνα 1.1.
Εικόνα 1.1.1 : τυπική δομή PFGA
Όπως παρατηρούμε ότι η πλειοψηφία των μπλοκς στο συγκεκριμένο FPGA της Xilinx είναι το CLB
(Configurable Logic Block) και μπορεί να υλοποιήσει ασύγχρονες ή σύγχρονες λογικές συναρτήσεις
πολλών εισόδων, μνήμες RAM ή ROM, αθροιστές, shift registers. Το κάθε CLB αποτελείται από ενα
σύνολο λογικών κελιών τα οποία βρίσκονται κοντά μεταξύ τους να έχουν γρήγορο δίαυλο επικοινωνίας,
μειώνοντας έτσι την καθυστέρηση διάδοσης. O αριθμός αυτός εξαρτάται από το εκάστοτε μοντέλο FPGA
που παράγει ο εκάστοτε κάτασκευαστής.
Page 9
- 9 -
Το κάθε λογικό κελί αποτελείται απο τα ακόλουθα:
Look-up Table (LUT): Το στοιχείο αυτό πραγματοποιεί λογικές πράξεις.
D Flip-Flops : Είναι καταχωρητές που αποθηκεύουν τα αποτελέσματα των LUTs
Πολυπλέκτης
Εικόνα 1.1.2 : Αρχιτεκτονική λογικού κελιού
Για παράδειγμα στην Εικόνα 1.2 εμφανίζεται η πιο απλή αρχιτεκτονική που μπορεί να έχει ενα CLB. Το
κάθε LUT υλοποιεί μια λογική συνάρτηση (π.χ. AND, OR, XOR). Μπορεί να θεωρηθεί ως μια πολύ
μικρή RAM. To D flip-flop συγχρονίζει την έξοδο σε κάθε κύκλο ρολογιού, δηλαδή σε κάθε κύκλο
ρολογιού το D flip-flop κρατάει την τιμή έξοδου σταθερή ως τον επόμενο κύκλο ρολογιού. Ο
πολυπλέκτης μας δίνει την δυνατότητα να παρακάμψουμε το D flip-flop όποτε χρειάζεται. Εκτός από τα
CLB υπάρχουν και άλλα λογικά μπλοκς τα οποία εκτελούν εξειδικευμένες λειτουργίες, όπως μνήμες
RAM, γρήγορους πολλαπλασιαστές, γεννήτριες σημάτων χρονισμού και πλήρεις μικροεπεξεργαστές
ανάλογα με το FPGA που θα επιλέξει ο χρήστης. Το πλέγμα των διασυνδέσεων περιέχει διασυνδέσεις
γενικής χρήσης, οι οποίες ενώνουν οποιαδήποτε λογικά μπλοκς μεταξύ τους, όπως επίσης και
διασυνδέσεις εξειδικευμένης λειτουργικότητας. Η επικοινωνία του FPGA με τον εξωτερικό κόσμο
γίνεται συνήθως μέσω ειδικών μπλοκ Εισόδου-Εξόδου (Input Output Blocks - IOB).Τα σύγχρονα FPGA
διαθέτουν εκατοντάδες θύρες I/O και υποστηρίζουν πολλά διαφορετικά πρότυπα επικοινωνίας.
Η εμφώλευση ενός σχεδιασμού για τα FPGA ξεκινά συνήθως με την περιγραφή του σε ειδικές
γλώσσες προγραμματισμού ,που ονομάζονται Hardware Description Languages (HDL). Οι πιο γνωστές
γλώσσες είναι οι VHDL και Verilog. Σε αυτή την διπλωματική εργασία προγραμματίσαμε το FPGA
χρησιμοποιώντας την γλώσσα Verilog.
Οι εφαρμογές των FPGAs περιλαμβάνουν ψηφιακή επεξεργασία σήματος, διαστημικές εφαρμογές
και συστήματα άμυνας, αναγνώριση φωνής, κρυπτογραφία, βίο-πληροφορική, και ένα σύνολο άλλων
αναπτυσσόμενων εφαρμογών.Καθώς το μέγεθος τους, η δυνατότητες και η ταχύτητα τους αυξάνονται,
άρχισαν να υλοποιούν όλο και μεγαλύτερες συναρτήσεις στο επίπεδο που κάποιες να έχουν εξελιχτεί σε
Page 10
- 10 -
πλήρη συστήματα on chip (SOC). Τα FPGAς βρίσκουν επίσης εφαρμογές σε περιοχές που
χρησιμοποιούν μαζικό παραλληλισμό, πράγμα που προσφέρεται από την αρχιτεκτονική τους. Μια τέτοια
περιοχή είναι η κρυπτανάλυση, και συγκεκριμένα η μέθοδος επίθεσης με υπολογιστική ισχύ (brute force
attack) σε κρυπτογραφημένα μηνύματα. Τα FPGA έχουν αρχίσει να χρησιμοποιούνται κατά κόρον σε
εφαρμογές υψηλής επίδοσης υπολογισμών, όπως Ταχύ Μετασχηματισμό Fourier (FFT) ή συνελίξεις που
πραγματοποιούνται από παράλληλους πυρήνες υλοποιημένους στα FPGAς αντί ενός και μόνο
μικροεπεξεργαστή. Η ευελιξία των FPGA δίνει την δυνατότητα για ακόμη μεγαλύτερη απόδοση,
αλλάζοντας την ακρίβεια και το εύρος για έναν αυξανόμενο αριθμό παράλληλων αριθμητικών μονάδων.
Αυτό έχει οδηγήσει σε έναν νέο τύπο επεξεργασίας, που ονομάζεται αναδιαμορφουμένος υπολογισμός
(reconfigurable computing). Μια νέα τάση είναι ο συνδυασμός των λογικών μπλοκ και των
διασυνδέσεων των παραδοσιακών FPGAs με ένθετους μικροεπεξεργαστές και περιφερειακά, για την
διαμόρφωση ενός πλήρους "συστήματος σε προγραμματιζόμενο chip" (SOC).
Κατά την διάρκεια της ανάπτυξης εφαρογών σε ενα FPGA ο χρήστης πρέπει να έχει στα υπόψη
μερικές ιδιότητες που θα πρέπει να ακολουθούν οι εφαρμογές αυτές:
Απόδοση (Performance). Η λογική του κυκλώματος πρέπει να εκτελείται σε συγκεκριμένο χρόνο.
Η απόδοση μετριέται με διαφορετικούς τρόπους: με το ρυθμό ολοκλήρωσης υπολογισμών
(throughput) ή με τον χρόνο εκτέλεσεις (latency). Επίσης η περίοδος ρολογιού συχνά
χρησιμοποιείται σα μέτρο της απόδοσης.
Ισχύς/ενέργεια(Power/energy). Το ολοκληρωμένο κύκλωμα πρέπει να λειτουργεί σε συγκεκριμένα
επίπεδα ενέργειας ή ισχύος. Η κατανάλωση ενέργειας είναι κρίσιμος παράγοντας σε συστήματα με
μπαταρία. Ακόμα και εάν στο σύστημα έχει προβλεφθεί η απαγωγή ενέργειας, οι απώλειες λόγω
θερμότητας κοστίζουν σε χρήμα και πρέπει να λαμβάνονται υπόψιν.
Χρόνος σχεδιασμού. Επειδή τα FPGA είναι τυποποιημένα τμήματα υλικού, παρουσιάζουν μερικά
πλεονεκτήματα όσον αφορά το χρόνο σχεδιασμού. Μπορούν να χρησιμοποιηθούν σα πρότυπα
συστήματα, μπορούν να προγραμματιστούν γρήγορα και μπορούν να χρησιμοποιηθούν ως
υποσύστημα στο τελικό σχέδιο.
Κόστος σχεδιασμού. Ο χρόνος σχεδιασμού είναι σημαντική συνιστώσα του κόστους σχεδιασμού,
μα άλλοι παράγοντες, όπως τα απαιτούμενα εργαλεία σχεδιασμού είναι επίσης σημαντικοί. Τα
εργαλεία σχεδίασης για FPGAς είναι συνήθως πιο φθηνά απ’ ότι τα αντίστοιχα που
χρησιμοποιούνται για το σχεδιασμό ASICS.
Page 11
- 11 -
Οι επικρατέστερες τεχνολογίες προγραμματισμού των διασυνδέσεων των FPGAς είναι οι
παρακάτω:
Μέσω κελιών SRAM: Ο προγραμματισμός κάθε σύνδεσης γίνεται αποθηκεύοντας ένα bit σε ένα
κελί SRAM. Το bit αυτό οδηγεί ένα τρανζίστορ διασύνδεσης σε κατάσταση αγωγιμότητας ή
αποκοπής, ενεργοποιώντας ή απενεργοποιώντας αντίστοιχα τη σύνδεση. Ο προγραμματισμός
χάνεται μετά από κάθε απώλεια ισχύος, συνεπώς η τεχνική αυτή απαιτεί τη χρήση εξωτερικής
μνήμης για την αποθήκευση του bitstream προγραμματισμού.
Fuse-antifuse:χρησιμοποιεί προγραμματιζόμενες συνδέσεις, των οποίων η αντίσταση μεταβάλλεται με
την εφαρμογή υψηλής τάσης. Στη μη-προγραμματισμένη κατάσταση η αντίσταση των συνδέσεων είναι
της τάξης των μερικών GΩ, επομένως μπορεί να θεωρηθεί ως ανοιχτοκύκλωμα. Με την εφαρμογή μιας
σχετικά μεγάλης τιμής τάσης, συμβαίνει ένα φυσικό φαινόμενο που ονομάζεται τήξη. Το αποτέλεσμα
αυτού είναι η δημιουργία μιας αντίστασης της τάξης των μερικών Ohm (Ω) κατά μήκος της συσκευής,
υλοποιώντας με τον τρόπο αυτό μια σύνδεση.
PROM–EPROM–EEPROM–Flash: Αυτή η μέθοδος χρησιμοποιεί τις ίδιες τεχνικές
προγραμματισμού με τις τεχνολογίες των μνημών PROM – EPROM – EEPROM – Flash και μπορεί
να θεωρηθεί ότι βρίσκεται στο μέσο των δύο προηγούμενων τεχνικών. Παρέχει τόσο την ευστάθεια
της fuse-antifuse όσο και την ικανότητα επανεγγραφής της SRAM. Από την άλλη, η αντίσταση των
διακοπτών δρομολόγησης είναι μεγαλύτερη από αυτήν της fuse-antifuse, ενώ ο προγραμματισμός
είναι πιο πολύπλοκος και χρονοβόρος από ότι αυτός της τεχνικής SRAM.
Οι νέες συσκευές των FPGAs περιλαμβάνουν κάτι περισσότερο από ένα FPGA αυτό καθεαυτό. Είναι
ουσιαστικά ολοκληρωμένες πλατφόρμες με FPGAs που περιλαμβάνουν αρκετά περιφερειακά έτσι ώστε
οποιοδήποτε μεγάλο σύστημα να μπορεί να υλοποιηθεί αποδοτικά. Τυπικά χαρακτηριστικά μιας
πλατφόρμας FPGA είναι μια CPU έτσι ώστε να είναι δυνατός ο συνσχεδιασμός
υλικού-λογισμικού.Επίσης μπορεί να περιλαμβάνει λογικές διαύλου έτσι, ώστε για παράδειγμα ένας PCI
δίαυλος να μπορεί να συμπεριληφθεί στο σχεδιασμό του υλοποιούμενου συστήματος.
Τα τελευταία χρονια υπάρχουν πέντε μεγάλες εταιρίες παγκοσμιως που κατασκευάζουν FPAGs.Οι
δυο κυριότερες που επικρατούν στην αγορά είναι η Xilinx και η Altera.
Xilinx: Η φιλοσοφία της Xilinx είναι η παραγωγή όλων των πιθανών τύπων ασχέτως του βαθμού
πολυπλοκότητας
Page 12
- 12 -
Altera(Intel): Η φιλοσοφία της Altera είναι η παραγωγή των τύπων συκευών με την μεγαλύτερη
ζήτηση,αλλά και με ευκολιά στη χρήση. Τώρα ανήκει στην Intel.
Lattice: εξιδικεύεται σε προγραμματιαζόμενα τα οποία απαιτούν χαμηλή κατανάλωση ενέργειας.
Microsemi: προσφέρει στον χρήστη προγραμματιζόμενα που ειναι κατάλληλα για εφαρμογές που
απαιτούν επεξεργασία αναλογικών σημάτων αλλά και προστασία από τυχόν εξεωτερικές
παραβιάσεις.
Μερικές πρόσφατες οικογένειες προγραματιζόμενων που προσφέρει η Xilinx είναι το Spartan-6,
Spartan-7, Artix-7 και το Zynq-7000. Στον πίνακα 1.1 βρίσκονται μερικά χαρακτηριστικά τους. Στον
πίνακα 1.2 παρουσιάζονται μερικές οικογένειες προγραματιζόμενων απο την Intel. Ο χρήστης ανάλογα
με τις απαιτήσεις τις εκάστοτε εφαρμογής πρέπει να επιλέξει την κατάλληλη οικογένεια καθώς
διαφέρουν πολύ μεταξύ τους. Σύμφωνα με το σάιτ της Xilinx το Spartan-6 και Spartan-7 ειναι κατάλληλα
για εφαρμογές που απαιτούν βέλτιστοι επικοινωνία με τις θύρες εισόδου/εξόδου, αλλά το Spartan-7 έχει
καλύτερη κατανάλωση ενέργειας από το Spartan-6.Το Artix-7 παρέχει την μεγαλύτερη απόδοσηανά watt,
οπότε είναι κατάλληλο για εφαρμογές που απαιτούν χαμηλη καταλάνωση ενέργειας.Το Zynq-7000 εχει
ενσωματωμένο επεξεργαστεί, δηλαδη είναι ενα SoC.
Πίνακας 1.1
Agilex Stratix Arria Cyclone
Logic elements(LEs) (K) 392 378 160 85
DSP Blocks 1150 648 -- 84
Max I/O Pins 360 374 288 192
Πίνακας 1.
Spartan-7 Spartan-6 Artix-7 Zynq-7000
Max logic cells(K) 102 147 215 444
Max Memory(Mb) 4.2 4.8 13 26.5
Max DSP Slices 160 180 740 2020
Max Tranceiver speed -- 3.2 6.6 12.5
Max I/O Pins 400 576 500 250
Page 13
- 13 -
1.2 Περιγραφή του FPGA που χρησιμοποιήθηκε
Για τις ανάγκες αυτής της διπλωματική χρησιμοποιήσαμε το NEXYS 3 που είναι βασισμένο στο
FPGA Spartan-6 LX16 της Xilinx. Το NEXYS 3 εκτός απο το FPGA Spartan-6 LX16 προσφέρει και
πολλά περιφεριακά στοιχεία όπως μια μνήμη 32Mbytes, ένα 10/100 Ethernet PHY, μια 16Mbytes of
Cellular RAM, ένα USB-UART port,μια USB host port για ποντίκι και πληκτρολόγιο.
Εικόνα 1.2.1 : Nexys 3
Τα αρχεία προγραμματισμού αποθηκεύονται στην SRAM μνήμη του FPGA. Τα δεδομένα αυτά
καθορίζουν την λογική λειτουργία και τις συνδέσεις των κυκλωμάτων.Παραμένουν έγκυρα μέχρι να
σβήσουμε το FPGA, μεχρι να πατήσουμε το κουμπί Reset, είτε μέχρι να στείλουμε άλλα αρχεία
προγραμματισμού χρησιμοποιώντας την θύρα JTAG. Τα αρχεία προγραμματισμού που μετεφέρονται
μέσω της JTAG θύρας πρέπει να έχουν κατάληξη .bin ή .svf , όσα μεταφέρονται μέσω USB-stick πρέπει
να έχουν κατάληξη .bit και όσα μετεφέρονται μέσω της BPI-UP θύρας πρέπει να έχουν
κατάληξη .bit, .bin, ή .mcs.Το πρόγραμμα ISE Design Suite (14.7) που χρησιμοποιήσαμε μπορεί να
διμηουργήσει όλα τα απαραίτητα αρχεία για το προγραμματισμό του FPGA.
Page 14
- 14 -
Το FPGA μπορει να ρυθμιστεί με τέσσερις τρόπους:
χρησιμοποιόντας την θύρα Adept "USB Prog"
Αποθηκεύοντας στην non-volatile parallel PCM device τα αρχεία προγραμματισμού μέσω της θύρας
BPI-UP
Αποθηκεύοντας στην non-volatile serial (SPI) PCM device τα αρχεία προγραμματισμού μέσω της
θύρας SPI
Χρησιμοποιώντας την θύρα USB HID για να μεταφέρουμε τα αρχεία προγραμματισμού από ένα
USB memory stick
Εικόνα 1.2.2 : Θύρες προγραμματισμού του Nexys 3
Τα βασικά χαρακτηριστικά του Spartan-6 LX16 είναι:
2,278 slices το οποίο καθένα περιέχει τέσσερα 6-input LUTs and οχτώ flip-flops
576Kbits of fast block RAM
Δύο clock tiles (τέσσερα DCMs & δύο PLLs)
32 DSP slices
συχνότητα ρολογιού μέχρι 500MHz
Page 15
- 15 -
Εικόνα 1.2.3 : Θύρες εισόδου/εξόδου Spartan 6
Τώρα όσων αφορά τις μνήμες το Nexys 3 περιέχει 3 εξωτερικές μνήμες : μια 128Mbit Cellular
RAM (pseudo-static DRAM),μια 128Mbit parallel non-volatile PCM (phase-change memory) και μια
128Mbit serial PCM device. Όλες από την εταιρεία Micron.Η Cellular RAM και η parallel PCM device
έχουν κοινή αρτηρία.
Η 16Mbyte Cellular RAM (Micron part number M45W8MW16) έχει αρτηρία 16-bit.Μπορεί να
χρησιμποιηθεί είτε σαν ασύγχρονη μνήμη SRAM με κύκλο εγγραφής και ανάγνωσης στα 70 ns είτε σαν
σύγχρονη μνήμη με αρτηρία συγχρονισμένη στα 80MHz. Η parallel PCM device (Micron part number
NP8P128A13T1760E) είναι οργανωμένη ως 8Mwords με 16-bits ανά θέση.Έχει κύκλο ανάγνωσης στα
115ns και εσωτερικό buffer 64-bit με κύκλο εγγραφής 50ns.
Η Cellular RAM και η parallel PCM έχουν κοινή αρτηρία δεδομένων 16-bit και κοινή αρτηρία
διευθύνσεων 24-bit. Η 16Mbyte serial PCM device (Micron part number NP5Q128A13ESFC0E)
υποστηρίζει πρωτόκολλο legacy SPI όπως και τα καινούρια Quad I/O and Dual I/O πρωτόκολλα και
ταχύτητα αρτηρίας στα 50MHz.
Τα αρχεία προγραμματισμού του Spartan-6 LX16 απαιτούν περίπου 512Kbytes μνήμης,Αυτό
συνεπάγεται οτι το 97% της μνήμης είναι διαθέσιμη στον χρήστη.Τα αρχεία αυτά μπορούν να γραφτούν
και στις δύο PCM μνήμες.
Page 16
- 16 -
Εικόνα 1.2.4 :Mνήμες του Spartan 6
Το ρολόι του Nexys 3 είναι ένα 100MHz CMOS oscillator που είναι συνδεδεμένος στο pin V10 του
FPGA.Τα βασικά στοιχεία εισόδου/εξόδου του Nexys 3 είναι οχτώ (8) slide switches,πέντε (5) push
buttons, οχτώ (8) Leds και 4 seven-segment displays. Επιπλέον περιέχει μια θύρα USB HID host για να
συνδέσει ο χρήστης ποντίκι ή πληκτρολόγιο,μια θύρα VGA και μια USB-UART Bridge ( Serial Port ) με
την οποια γίνεται ή σύνδεση του FPGA με τον υπολογιστή.
Εικόνα 1.2.5 : Pins εξόδου του Spartan 6
Page 17
- 17 -
ΚΕΦΑΛΑΙΟ 2
2.1 Περιγραφη του Soft processor
Ο Microblaze είναι ένας 32-bit RISC (reduced instruction set computer) soft core processor της
Xilinx ο οποίος είναι ειδικά σχεδιασμένος για τα FPGAs της εταιρίας. Χρησιμοποιώντας τα εργαλεία της
εταιρίας, ISE Design Suite και Xilinx SDK, ο χρήστης μπορει να δημιουργήσει ένα System On a Chip
(SoC) σύστημα με αρκετά υψηλή απόδοση. Ένα διάγραμα του Microblaze φαίνεται στην Εικόνα 2.1.
Εικόνα 2.1 : Microblaze
Page 18
- 18 -
Το σταθερό σύνολο στοιχείων του επεξεργαστή ειναι τα παρακάτω:
32 καταχωρητές των 32-bit ή των 64-bit
Εντολές 32-bit με 3 τελούμενα και 2 addressing modes
Αρτηρία διευθύνσεων 32-bit με δυνατοτητα επέκτασης στα 64 bits
Single issue pipeline
Παρακάτω θα αναφέρουμε μερικά βασικά χαρακτηριστικά του επεξεργαστή όσων αφορά την
αρχιτεκτονική του και τον τρόπο λειτουργίας του. Χρησιμοποιεί Big-Endian και Little-Endian για την
αποθήκευση των δεδομένων στην μνήμη ανάλογα την επιλογή του χρήστη. Η επολογή καθορίζεται με
την τιμή της παραμέτρου C_ENDIANNESS η οποια είναι προκαθορισμένη στο 1 (Little-Endian).Οι
τύποι δεδομένων που υποστηρίζει το hardware είναι μια λεξη, μισή λεξη και ένα byte. Η λέξη
αποτελείται από 32 bit,επομένως η μισή λέξη αποτελείται από 16 bit και όπως γνωρίζουμε το byte
αποτελείται από 8 bit. Όσον αφορά τις εντολές του Microblaze είναι των 32-bit και μπορεί να έχουν δύο
μορφές, Type A και Type Β. Στην πρώτη μορφή, Type A, έχουμε έως δύο καταχωρητές για τα δεδομένα
εισόδου και ένα καταχωρητή για την αποθήκευση των αποτελεσμάτων.
Type A:
Εικονα 2.2 : Εντολές τύπου Α
Ενώ στον Type Β έχουμε ένα καταχωρητή για τα δεδομένα εισόδου,έναν καταχωρητή για την
αποθήκευση των αποτελεσμάτων και 16-bit για έμμεση διεθυνσιοδότηση
Type B:
Εικονα 2.3 : Εντολές τύπου Β
Page 19
- 19 -
Το σύνολο των εντολών του μπορεί να ανήκουν στις επόμενες κατηγορίες: αριθμητικές, λογικές,
διακλάδωσης, load/store και ειδικές. Υποστηρίζει interrupt, user exception, break, and hardware
exceptions.
Η σειρά προτεραιότητας είναι:
1. Reset
2. Hardware Exception
3. Non-maskable Break
4. Break
5. Interrupt
6. User Vector (Exception)
Έχει 32 καταχωρητές γενικού σκοπού των 32-bit ή 64-bit και έως 16 ειδικού σκοπού καταχωρητές των
32-bit ανάλογα τις ρυθμίσεις του χρήστη.
R0:έχει πάντα την τιμή 0.
R1-R13:καταχωρητές γενικού σκοπού.
R14:καταχωρητής που χρησιμοποιείται για την αποθήκευση της διεύθυνσης επιστροφής για τα
interupt.
R15:καταχωρητής γενικού σκοπού,που συνιστάται για την αποθήκευση της διεύθυνσης από τα
interrupt.
R16:καταχωρητής που χρησιμοποιείται για την αποθήκευση της διεύθυνσης επιστροφής για τις
εντολές break.
R17:αν ο επεξεργαστής έχει ρυθμιστει ωστε να δέχεται hardware exceptions στον καταχωρητή αυτόν
αποθηκεύεται η διεύθυνση της εντολής που προκάλεσε το exception.
R18-R31:καταχωρητές γενικού σκοπού
Μερικοί καταχωρητές ειδικού σκοπού που αξίζει να αναφέρουμε είναι :
Program Counter (PC): στον οποίο αποθηκεύεται η προς εκτέληση εντολή.
Machine Status Register (MSR): ο οποίος περιέχει bits γαι την κατάσταση του επεξεργαστή και
σήματα ελένγχου.
Page 20
- 20 -
Exception Address Register (EAR) :στον οποιο αποθηκεύουμε ολη την εντολή load /store η οποία
προκάλεσε το exception.
Exception Status Register (ESR) :που περιέχει status bit για τον επεξεργαστή.
Floating Point Status Register (FSR): που περιέχει πληροφορία για την μονάδα κινητής
υποδιαστολής.
Οι εντολές στον Microblaze εκτελούνται με χρήση του pipeline. Για τις περισσότερες εντολές καθε
στάδιο χρειάζεται ενα κύκλο ρολογιού να εκτελεστεί.Όταν το optimization είναι ενεργοποιημένο το
pipeline χωρίζεται σε τρία στάδια για να μειωθεί το κόστος του hardware. Τα οποία είναι Fetch, Decode
και Execute.
Εικονα 2.4 : Στάδια pipeline οταν έχουμε 3 στάδια
Ενώ οταν το optimization είναι απενεργοποιημένο το pipeline χωρίζεται σε πέντε στάδια για
μεγαλύτερη απόδοση. Τα οποία είναι Fetch (IF), Decode (OF), Execute (EX), Access Memory (MEM),
and Writeback (WB).
Εικονα 2.5 : Στάδια pipeline οταν έχουμε 5 στάδια
Είναι σχεδιασμένος με Harvard αρχιτεκτονική για τις μνήμες. Οι εντολές και τα δεδομένα αποθηκεύονται
σε διαφορετικό χώρο διευθύνσεων κα είναι των 32-bit. Ο επεξεργαστής έχει τρείς διεπαφές για
επικοινωνία με τις μνήμες:
Page 21
- 21 -
Local Memory Bus (LMB):Χρησιμοποιείται κυρίως για την επικοινωνία με τις on-chip RAMs και
έχει λίγα σήματα ελέγχου και απλό πρωτόκολλο επικοινωνίας προκειμένου η πρόσβαση στις RAMs
να γίνεται σε ένα κυκλο ρολογιού.
Advanced eXtensible Interface (AXI4): για προσπέλαση περιφεριακών συσκευών
Advanced eXtensible Interface (AXI4) or AXI Coherency Extension (ACE): για προσπέλαση
κρυφής μνήμης
Επίσης δίνει στον χρήστη την δυνατότητα παραμετροποιημένης κρυφής μνήμης εντολών αλλά και
δεδομένων. Όταν ο χρήστης ενεργοποιήσει την κρυφή μνήμη εντολών ο χώρος εντολών χωρίζεται σε δύο
κομμάτια,την κρυφή και την κανονική. Το εύρος της κρυφής μνήμης ορίζεται απο δυο
παραμέτρους,C_ICACHE_BASEADDR και C_ICACHE_HIGHADDR και πρέπει να είναι αναγκαστικά
δύναμη του 2. Η διεύθυνση της κρυφής μνήμης εντολών χωρίζεται σε δύο μέρη : ετικέτα και δεδομένα.
Στον Microblaze η κρυφή μνήμη εντολών μπορεί να έχει μέγεθος 64 bytes έως 64 kB, οπότε τα δεδομένα
είναι μεταξύ 6 και 16 bits. Για κάθε εντολή που καλείται η κρυφη μνήμη ελέγχει αν η διεύθυνση ανήκει
στο τμήμα της κρυφή μνήμης. Αν ανηκεί, γίνεται έλεγχος στην μνημη tag RAM για να δουμέ αν η
ζητούμενη διεύθυνση είναι προσωρινα αποθηκευμένη στην κρυφή μνημή. Υπάρχει επιτυχία αν η έξοδος
της μνήμης tag RAM είναι ίδιο με το tag address της διεύθυνσης και το σήμα valid είναι ενεργοποιημένο.
Μια πιο σαφή εικονα της οργάνωσης της κρυφής μνήμης φαίνεται στην εικόνα 2.6.
Εικονα 2.6 : Οργάνωση κρυφής μνήμης εντολών
Το ίδιο ισχύει και για την κρυφή μνήμη δεδομένων απλά αλλάζουν οι παράμετροι. Σε αυτήν την
περίστωση ειναι οι C_DCACHE_BASEADDR and C_DCACHE_HIGHADDR. Η παράμετρος
C_DCACHE_USE_WRITEBACK καθορίζει αν η κρηφή μνήμη θα υλοποιηθεί με το πρωτόκολλο
write-back ή write-through. Όταν είναι ενεργοποιημένη, εφαρμόζεται το πρωτόκολλο write-back. Στο
Page 22
- 22 -
πρωτόκολλο write-through τα δεδομένα γράφονται πάντα στη μνήμη και στην κρυφή μνήμη ενώ στο
write-back τα δεδομένα γράφονται πάντα στην κρυφή μνήμη και αντιγράφεται στη μνήμη όταν
καθαριστεί από άλλη θέση μήμης.
Εικονα 2.7 : Οργάνωση κρυφής μνήμης δεδομένων
Η μονάδα κινητής υποδιαστολής ειναι μονής ακρίβειας (single precision) όταν ο Microblaze είναι
ρυθμισμένος στα 32-bit ενω στα 64-bit είναι διπλής ακρίβειας.Όταν έχουμε μονή ακρίβεια ένα bit
χρησιμοποιείται για το πρόσημο, 8 bit για τον εκθέτη και 23 για το κλασματικό μέρος. Στην διπλής
ακρίβειας έχουμε ένα bit για το πρόσημο, 11 bit για τον εκθέτη και 52 για το κλασματικό μέρος.
Δίνεται η δυνατότητα στον χρήστη να υλοποιήσει στο ίδιο υλικό δυο ή παραπάνω Microblaze soft
processors οι οποίοι εκτελώντας το ίδιο πρόγραμμα μπορεί να ανιχνεύσει προσπάθειες παραβίασης
υλικού, παροδικά σφάλματα ή μόνιμα σφάλματα υλικού συγκρίνοντας τις εξόδους. Ένα παραδειγμα που
είναι χρήσιμη αυτή η δυνατότητα είναι σε μια εφαρμογή κρυπτογράφησης αλλά και σε εφαρμογές που
απαιτείται μικρό ποσοστό σφαλμάτων. Η υλοποιήση των processor είναι λίγο διαφορετική όταν θέλουμε
να κάνουμε ανίχνευση λαθών και οταν θέλουμε να ελέγξουμε για τυχόν εξωτερικές παραβίασεις. Και
στις δυο περιπτώσεις η παράμετρος C_LOCKSTEP_SLAVE ειναι ενεργοποιημένη ( δηλαδή πρεπει να
τεθεί στο “1” ) σε όλους τους slave Microblaze επεξεργαστές εκτός απο τον master. Ο master Microblaze
επεξεργαστής οδηγεί όλα τα σήματα εξόδου και είναι υπεύθυνος για το αποσφαλμάτωση ( debugging )
του συστήματος.
Και στις δυο περιπτώσεις κάθε επεξεργαστής είναι πανομοιότυπος με τον άλλον και δεν
επικοινωνούν μεταξύ τους. Στην περίπτωση ανίχνευσης λαθών οι εξοδοι όλων των processors μέσω της
θύρας lockstep_out συγκρίνωνται μεταξύ τους μέσω μόνο ενός συγκριτή. Μόλις ανακαλυφθεί λάθος όλοι
οι επεξεργαστές σταμάτανε την λειτουργία τους ( δηλαδή μπαίνουν σε λειτουργία halt ) για να
εμποδίσουν τύχον διάδοση του σφάλματος. Στην περίπτωση που θέλουμε να ελέγξουμε για εξωτερικές
παραβίασεις κάθε επεξεργαστής έχει την δική του μνήμη οπως φαινεται και στην εικόνα 2.9 σε αντίθεση
με την περίπτωση ανίχνευσης λαθών που έχουν κοινή μνήμη. Δέχονται τα ίδια σήματα εισόδου και οι
Page 23
- 23 -
εξοδοί τους μέσω της θύρας lockstep_out συγκρίνονται με την χρήση δυο συγκριτών, οι οποίοι
βρισκονται σε προστατευμένη περιοχή πάνω στο FPGA.
Εικονα 2.8 : Aνίχνευση λαθών
Εικονα 2.9 : Ασφάλεια εφαρμογών
Τώρα θα αναθερφούμε στον προγραμματισμό του Μicroblaze στο Xilinx SDK. Προγραμματίζεται
γράφοντας κώδικα σε γλώσσα προγραμματισμού C. Στις Εικόνες 2.10 έως 2.15 είναι μερικές βασικές
εντολες για να οδηγήσουμε τις εισόδους και εξόδους του Μicroblaze. Για την υλοποιηση των
προβλημμάτων χρησιμοποιήσαμε κυρίως τις εντολές XIOModule_Initialize, XIOModule_Start,
XIOModule_DiscreteWrite. Η εντολή XIOModule_Initialize καλείται μονο μια φορά και αρχικοποιεί τις θύρες
εισόδου/εξόδου. Η εντολή XIOModule_Start ενεργοποιεί τις θυρες εισόδου/εξόδου, δηλαδή είναι έτοιμες να
δεχτούν δεδομένα. Με την εντολή XIOModule_DiscreteWrite μπορούμε να γράψουμε στις θύρες εξόδου.
Page 24
- 24 -
Εικονα 2.10 : Εντολες 1
Εικονα 2.11 :Εντολες 2
Εικονα 2.12 : Εντολες 3
Page 25
- 25 -
Εικονα 2.13 :Εντολες 4
Εικονα 2.14 : Εντολες 5
Page 26
- 26 -
Εικονα 2.15 :Εντολές 6
Μερικοί αλλοι soft processor που είναι διαθέσιμοι στον χρήστη ειναι ο LatticeMico32 της εταιρίας
Lattice και o Nios II της εταιρίας Intel. Ο LatticeMico32 είναι και αυτός ένας RISC soft processor των
32-bit.Είναι σχεδιασμένος με harvard αρχιτεκτονικής, έχει 32 καταχωρητές γενικού σκοπού,με αρτηρία
δεδομένων και εντολών των 32-bit. Έχει την δυνατότητα παραμετροποιημένης κρηφής μνήμης εντολών
και δεδομένων. Μπορεί να χειριστεί έως 32 εξωτερικά interupts, Έχει 6 στάδια pipeline σε αντίθεση με
τον Micrοblaze που εχει 5 στάδια. Στον πίνακα 2.1 βλέπουμε τις δυνατότητες του LatticeMico32 σε
μερικές οικογένειες FPGAs της Lattice. Στην τελευταία γραμμή του πίνακα βλέπουμε τις αντιστοιχες
τιμές του Microblaze στην οικογένεια FPGA Vartix E. Οπως παρατηρούμε ο microblaze απαιτεί λιγότερα
LUTs και πορει να πετύχει πολύ μεγαλύτερη συχνότητα λιτουργείας.
Οικογένεια FPGAs LUTs Fmax(MHz)
LatticeECP3 2.370 115
LatticeXP2 2.406 85
LatticeECP2/M 2.497 110
Vartix E (Microblaze) 1.900 220
Πίνακας 2.1
O Nios II έχει και αυτός 32 καταχωρητές γενικού σκοπού των 32-bit, εντολές των 32 bit . Μπορει να
ρυθμιστεί σε 3 εναλλακτικές μορφές fast, economy και standard. Ο Nios II/fast έχει κρυφή μνήμη
δεδομένων και εντολών, ο Nios II/standard έχει μόνο κρυφή μνήμη εντολών και ο Nios II/economy δεν
έχει ούτε κρυφή μνήμη δεδομένων ούτε κρυφή μνήμη εντολών. Μια επιπλέον διαφορά του Nios II/fast σε
σχέση με τον Nios II/standard είναι ότι ο Nios II/fast έχει 6 στάδια pipeline για να πετυχαίνει καλύτερα
επίπεδα DMIPS ενώ ο Nios II/standard έχει 5 στάδια. Αυτό φαινεται και στον πίνακα 2.2.
Page 27
- 27 -
Οικογένεια FPGA Nios II/economy (DMIPS/MHz) Nios II/fast (DMIPSMHz)
Cyclone V GX 33 at 220 192 at 170
Arria 10 GX 52.5 at 350 305 at 270
Stratix V 54 at 420 385 at 350
Πίνακας 2.2
Nios II/fast Nios II/standard Nios II/economy
Stratix 1.800 1.170 530
Cyclone 1.680 1.140 520
Πίνακας 2.3
Page 28
- 28 -
ΚΕΦΑΛΑΙΟ 3
3 Εισαγωγή
Για να συγκρίνουμε τον soft processor Microblaze βρήκαμε μερικά προβλήματα με υψηλή χρονική
πολυπλοκότητα. Κυρίως θα συγκρίνουμε τον χρόνο εκτελέσεις των προβλημάτων όταν τα εκτελούμε
χρησιμοποιώντας τον Microblaze, όταν χρησιμοποιούμε καθαρά hardware υλοποιήση (χρήση γλώσσας
προγραμματσιμού Verilog) και όταν χρησιμοποιούμε την γλωσσα προγραμματισμού C. Παρακάτω θα
αναλύσουμε και θα περιγράψουμε τα προβλήμματα και τον τρόπο που υλοποιήθηκαν.
3.1 Πρόβλημμα 1ο: Διάνυσμα επί διάνυσμα
Σε αυτό το πρόβλημα υπολογίζουμε το εσωτερικό γινόμενο δύο διανυσμάτων X και Y μήκους 128.
Πολλαπλασιάζουμε κάθε στοιχείο του ενός διανύσματος με το αντίστοιχο του άλλου και κάθε φορά
προσθέτουμε το αποτέλεσμα σε ένα συσσωρευτή. Υπολογίζουμε την έκφραση:
)*(128
11
i
ii yxR
Ύστερα για καλύτερα αποτελέσματα παραλληλοποιούμε τον σχεδιασμό. Αυτή την φορά κανοντας
τέσσερις πολλαπλασιασμούς και τρείς προσθέσεις σε κάθε βήμα. Δηλαδή, λύνουμε την εξίσωση.
128
4,13322112 )*()()*()*(
iiiiiiiiiii yxyxyxyxR
Παραληλλοποιούμε και άλλο τον σχεδιασμό κάνοντας δεκαέξι πολλαπλασιασμούς και δεκαπέντε
προσθέσεις.
Page 29
- 29 -
128
16,1
1515141413131212
111110109988
77665544
332211
3
))*()()*()*()*()()*()*(
)*()()*()*()*()()*()*((
iii
iiiiiiii
iiiiiiii
iiiiiiii
iiiiiiii
yxyxyxyxyxyxyxyxyxyxyxyx
yxyxyxyx
R
Το κύκλωμα για την hardaware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού), reset (σήμα
αρχικοποποίησης) και παράγει στην έξοδό του το σήμα result στο οποίο αποθηκεύουμε το αποτέλεσμα.
Τα δεδομένα είναι αποθηκευμένα σε δύο RAM ασύγχρονης ανάγνωσης 128 θέσεων. Για τα δεδομένα
εισόδου στις RAMs:
Χ=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
Υ=[2,2,14,2, 4,10,12,0,10,2,14,2,4,10,12,15,2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15,
2,2,14,2, 4,10,12,0,10,2,14,2,4,10,12,15,2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15,
2,2,14,2, 4,10,12,0,10,2,14,2,4,10,12,15,2,2,14,2, 4,10,12,0,10,2,14,2,4,10,12,15,
2,2,14,2, 4,10,12,0,10,2,14,2,4,10,12,15,2,2,14,2, 4,10,12,0,10,2,14,2,4,10,12,15]
Στην έξοδο result εμφανιζεται ο αριθμός 8040. Για τον Microblaze έχουμε πάλι μια έξοδο στην οποία
εμφανίζουμε το τελικό αποτέλεσμα.
Page 30
- 30 -
3.2 Πρόβλημμα 2ο:Κόσκινο του Ερατοσθένη
Είναι ένας αλγόριθμος για την εύρεση όλων των πρώτων αριθμών μέχρι έναν συγκεκριμένο ακέραιο,
έστω n. Σαν αλγόριθμος είναι γρήγορος για μικρούς πρώτους (κάτω από 10 εκατομμύρια).
Δημιουργήθηκε από τον Ερατοσθένη, μαθηματικό της Αρχαίας Ελλάδας. Ένας πρώτος αριθμός είναι
ένας φυσικός αριθμός που έχει ακριβώς δύο διαφορετικούς διαιρέτες: το 1 και τον εαυτό του.
Η εύρεση όλων των πρώτων αριθμών που είναι μικρότεροι ή ίσοι από έναν ακέραιο n, σύμφωνα με
τη μέθοδο του Ερατοσθένη, γίνεται ως εξής:
1. Δημιουργούμε μια λίστα από διαδοχικούς ακέραιους από το 2 μέχρι το n: (2, 3, 4, ..., n).
2. Αρχικά, έστω ότι το p είναι ίσο με 2, τον 1ο πρώτο αριθμό.
3. Διαγράφουμε από τη λίστα όλα τα πολλαπλάσια του p που είναι μικρότερα ή ίσα με n. (2p, 3p, 4p,
κτλ)
4. Βρίσκουμε τον 1ο αριθμό που απομένει στη λίστα μετά τον p (αυτός ο αριθμός είναι ο επόμενος
πρώτος αριθμός) και αντικαθιστούμε το p με αυτόν τον αριθμό.
5. Επαναλαμβάνουμε τα βήματα 3 και 4 μέχρι το p2 να είναι μεγαλύτερο από n.
6. Όλοι οι αριθμοί που απομένουν στη λίστα είναι πρώτοι αριθμοί.
Η πολυπλοκότητα του αλγορίθμου είναι O(n(logn)(log(logn))) λειτουργίες bit με απαιτήσεις μνήμης
O(n).
Page 31
- 31 -
Ο ψευδοκώδικας που χρησιμοποιήθηκε στην hardware υλοποίηση φαίνεται στην Εικόνα 3.1
Εικόνα 3.1 : Ψευδοκώδικας για κοσκινο του Ερατοσθένη
Το κύκλωμα για την hardaware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού), reset
(σήμα αρχικοποίησης) και παράγει στην έξοδό του τον καταχωρητή counter στο οποίο αποθηκεύουμε το
σύνολο των πρώτων αριθμών έως τον αριθμό n. Αρχικοποιούμε μια μνήμη RAM ασύγχρονης ανάγνωσης
των 127 θέσεων στο 0 (για όλες τις θέσεις της). Αν ο αριθμός είναι πρώτος τότε στην μνήμη γράφουμε
“0” και αν δεν είναι “1”. Για τον Microblaze και για την software υλοποίηση ένας τρόπος σχεδίασης
φαίνεται στην Εικόνα 3.2. Ο prime είναι ένας boolean πίνακας με n θέσεις αρχικοποιημένος στο false.
Εικόνα 3.2 : Software κώδικας
Page 32
- 32 -
3.3 Πρόβλημμα Τρίτο :RNS Assisted Image Filtering and Edge Detection
Σε αυτό το πρόβλημα υλοποιούμε ένα αλγόριθμο φιλτραρίσματος εικόνας. Kάθε pixel της εικόνας
έχει εύρος 8-bit,δηλαδή μπορεί να πάρει τιμές στο διάστημα [0.255]. Σε κάθε βήμα παίρνουμε ένα 3x3
block της εικόνας σειριακά.Για κάθε block δημιουργούμε τρείς πίνακες Ι1,Ι2,Ι3 μεγεθους 3x3.Ο πίνακας Ι1
περιέχει τα υπόλοιπα της διαίρεσης των στοιχείων του 3x3 block με τον αριθμό 31,ο Ι2 περιέχει τα
υπόλοιπα της διαίρεσης των στοιχείων του 3x3 block με τον αριθμό 32 και ο Ι3 περιέχει τα υπόλοιπα της
διαίρεσης των στοιχείων του 3x3 block με τον αριθμό 33. Μετά εφαρμόζουμε στους πίνακες αυτούς
φίλτρο Gauss. Πολλαπλασιάζουμε γραμμικά τους πίνακες Ι1,Ι2,Ι3 με τον G.
121222121
141G
Προκύπτουν τρείς αριθμοί g1,g2,g3 που είναι το αποτέλεσματα του φίλτρου Gauss στους πίνακες
Ι1,Ι2,Ι3.Ύστερα υπολογίζουμε τον αριθμό 1023g3)*496-g1*528+g2*32- (*32+g2=f και
αναθέτουμε σε όλα τα στοιχεία του αρχικού 3x3 block αυτόν τον αριθμό.Αυτή την διαδικασία την
κάνουμε σε όλα τα υπόλοιπα block της εικόνας. Μετα το πέρας του υπολογισμού έχουμε μια
φιλτραρισμένη ειοκόνα.Το κύκλωμα για την hardaware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα
χρονισμού), reset (σήμα αρχικοποίησης) και παράγει στην έξοδό του, την σημαία done η οποία γίνεται 1
μετά το πέρας του υπολογισμού. Η εικόνα είναι αποθηκευμένη σε ένα μπλοκ μνήμης 15x15 και καθε
στοιχείο έχει εύρος 8-bit.
Page 33
- 33 -
3,4 Πρόβλημμα 4o:Υπολογισμός απόστασης ανάµεσα σε δύο διανύσµατα
Σε αυτό το πρόβλημα έχουμε δυό διανύσματα X και Y μήκους 128 και υπολογίζουμε την απόσταση
ανάμεσα εφαρμόζοντας τον τύπο:
N
iii yx
1
2||
Αρχικά υπολογίζουμε το άθροισμα και ύστερα υπολογίζουμε την τετραγωνική ρίζα. Το άθροισμα
υπολογίζεται με την ίδια λογική με τον πρώτο πρόβλημμα. Για τον υπολογισμό της τετραγωνικής ρίζας
στην hardaware υλοποίηση χρησιμοποιήθηκε ο ψευδοκώδικας που φαινεται στην Εικόνα 3.3
Εικόνα 3.3 :Υπολογισμός τετραγωνικής ρίζας
Παραλληλοποιούμε την σχεδίαση όπως κάναμε και στο πρώτο πρόβλημμα κάνοντας 4 και 16 πράξεις
ανα βήμα. Το κύκλωμα για την hardaware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού),
reset (σήμα αρχικοποίησης) και παράγει στην έξοδό του το σήμα result στο οποίο αποθηκεύουμε το
αποτέλεσμα της εξίσωσης. Τα δεδομένα είναι αποθηκευμένα σε δύο RAM ασύγχρονης ανάγνωσης 128
θέσεων.Χρησιμοποιήσαμε τα ίδια δεδομένα εισόδου γαι τις RAMς με το πρώτο πρόβλημμα. Οπότε στην
έξοδο θα πρεπεί μα πάρουμε την τιμή 62.
Page 34
- 34 -
3.5 Πρόβλημμα 5o:Τέλειοι αριθμοί
Τέλειος είναι ένας φυσικός αριθμός όταν το άθροισμα των διαιρετών του, εκτός του αριθμού, είναι
ίσο τον αριθμό. Ο μικρότερος τέλειος αριθμός είναι ο 6. Για παράδειγμα οι διαιρέτες του 6 είναι οι 1, 2, 3
και το άθροισμα αυτών είναι ίσο με 6 (1+2+3=6). Άλλοι τέλειοι αριθμοί είναι οι 28 = 1 + 2 + 4 + 7 + 14,
496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248 και ο 8128.
Το κύκλωμα για την hardware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού), reset
(σήμα αρχικοποίησης) και το διάνυσμα value (αντιστοιχεί στο n), εύρους 16 bit . Παράγει στην έξοδό του,
την σημαία perfect η οποία γίνεται 1 μόνο στην περίπτωση που υπολογιστεί ότι ο din είναι τέλειος. Ο
ψευδοκώδικας που χρησιμοποιήθηκε για την υλοποίηση φαίνεται στην Εικόνα 3.4.
Εικόνα 3.4
Page 35
- 35 -
3.6 Πρόβλημμα 6o :Ακολουθία Fibonacci
Βρίσκουμε τον n-οστό όρο της ακολουθίας Fibonacci. Η ακολουθία Fibonacci πρώτης τάξης
ορίζεται σύμφωνα με την παρακάτω σχέση:
Ο ψευδοκώδικας που χρησιμοποιήθηκε ειναί για την υλοποίηση είναι ο παρακάτω:
Εικόνα 3.6
Το κύκλωμα για την hardaware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού) και reset
(σήμα αρχικοποίησης) και το διάνυσμα din (αντιστοιχεί στο n),εύρους 16 bit. Παράγει στην έξοδό τον
n-οστό όρο της ακολοθίας. Για είσοδο τον αριθμό 20 πρέπει στην έξοδο να έχουμε στην έξοδο το 6765.
Page 36
- 36 -
3.7 Πρόβλημμα 7Ο:Κωδικοποίηση Δέλτα
Η κωδικοποίηση Δέλτα αποτελεί έναν απλό τρόπο για τη συμπίεση δεδομένων, και λειτουργεί
αποθηκεύοντας τις τιμές διαφοράς μεταξύ διαδοχικών δεδομένων. Για παράδειγμα για την ακολουθία
τιμών: 1, 5, 7, 11, 12, οι αντίστοιχες τιμές Δέλτα είναι 1, 4, 2, 4, 1. Το κύκλωμα για την hardware
υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού) και reset (σήμα αρχικοποιήσης). Τα αρχικά
δεδομένα υπάρχουν προαποθηκευμένα σε μνήμη RAM ασύγχρονης ανάγνωσης 128 θέσεων. Έξοδος του
κυκλώματος είναι το σήμα done το οποίο γίνεται 1 με το πέρας της διαδικασίας κωδικοποίησης. Μετά το
πέρας της διαδικασίας στην μνήμη RAM βρισκονται τα δεδομένα συμπιεσμένα.
Ο ψευδοκώδικας που χρησιμοποιήθηκε για την υλοποίηση φαίνεται στην Εικόνα 3.7:
Εικόνα 3.7
Page 37
- 37 -
3.8 Πρόβλημμα Όγδοο :Bubble sort
Ο αλγόριθμος ταξινόμησης Bubble Sort χαρακτηρίζεται από υψηλή χρονική πολυπλοκότητα
(O(n^2)).Σε κάθε βήμα κάνουμε συγκρίσεις διαδοχικών στοιχείων τα οποία αντιμετατιθέτουμαι σε
περίπτωση που δεν βρίσκονται ήδη ταξινομημένα. Στο τέλος έχουμε μια ταξινομημένη λίστα.
Το κύκλωμα για την hardaware υλοποίηση δέχεται ως είσοδο το σήμα clk (σήμα χρονισμού) και
reset (σήμα αρχικοποίησης) οπως και στα άλλα προβλήμματα. Η εξοδός του είναι η σημαία valid η
οποία γίνεται “1” μετα το πέρας του υπολογισμού. Τα δεδομένα της λίστας βρίσκονται αποθηκευμένα σε
μνήμη RAM ασύγχρονης ανάγνωσης 128 θέσεων. Κάθε φορά που διατρέχουμε την RAM το μεγαλύτερο
στοιχείο τοποθετήται στο τέλος μιας όλο και συρρικνούμενης λίστας. Οπότε μετά απο n^2 προσπελάσεις
η λίστα θα έχει ταξινομηθεί.
3.9 Πρόβλημμα 9o :Ακολουθία Hailstone
Η ακολουθία Hailstone ορίζεται για ένα δοθέντα θετικό ακέραιο n ως εξής:
•Αν n = 1 τότε η ακολουθία τερματίζεται.
•Αν ο n είναι άρτιος (δηλ. το τελευταίο του δυαδικό ψηφίο είναι 0) τότε η επόμενη τιμή στην
ακολουθία είναι ο n/2.
•Αν ο n είναι περιττός (δηλ. το τελευταίο του δυαδικό ψηφίο είναι 1) τότε η επόμενη τιμή στην
ακολουθία είναι ο 3*n + 1.
Η ακολουθία hailstone σχετίζεται με την εικασία του Collatz (Collatz conjecture) σύμφωνα με την
οποία η ακολουθία hailstone για οποιονδήποτε αρχικό αριθμό, τερματίζεται. Η ακολουθία hailstone
δίνεται συνεπώς από την παρακάτω σχέση:
Το κύκλωμα για την hardware υλοποίηση δέχεται ως είσοδο το σήμα clk(σήμα χρονισμού), reset
( σήμα αρχικοποίησης ) και το διάνυσμα din (αντιστοιχεί στο n),εύρους 16 bit. Παράγει στην έξοδό του,
τον τρέχοντα όρο της ακολουθίας dout,εύρους 16 bit, και τον counter ο οποίος μετράει τους όρους της
ακολουθίας. Η σημαίας done είναι 1, όταν τερματίζεται η ακολουθία hailstone, δηλαδή όταν ο όρος της
γίνει ίσος με “1”. Στην υλοποίηση μας το din είναι ίσο με 27 και παράγεται η ακολουθία:
27, 82, 41, 124,......, 8, 4, 2, 1 η οποία έχει συνολικά 112 όρους.
Page 38
- 38 -
ΚΕΦΑΛΑΙΟ 4
4. Αποτελέσματα και Συμπεράσματα
Για καθένα απο τα προβλήματα που παρουσιάστηκαν στο Κεφάλαιο 3, κάναμε τουλάχιστον 3 (στις
περιπτώσεις που μπορούσε το πρόβλημα να παραλληλοποιηθεί περαιτέρω εξετάστηκαν και άλλη πιο
παράλληλες υλοποίησεις ) διαφορετικές υλοποιήσεις.
(α) Σε προγραμματιζόμενο υλικό (FPGA)
(β) Σε πρόγραμμα που εκτελείται στον soft επεξεργαστή Microblaze
(γ) Σε υλοποίηση με λογισμικό
Για να υπολογίσουμε τον χρόνο εκτέλεσεις βρήκαμε πόσους κύκλους ρολογιού απαιτούνται στον
εκάστοτε σχεδιασμό για να ολοκληρωθεί και την μέγιστη καθυστέρηση ανα κύκλο ρολογιού του
σχεδιασμού. Κάνοντας πολλαπλασιασμό μεταξύ των κύκλων ρολογιού με την μέγιστη καθυστέρηση
βρίσκουμε τον χρόνο εκτέλεσης του εκάστοτε σχεδιασμού.Τα αποτελέσματα παρουσιάζονται στους
παρακάτω πίνακες. Έπειτα βρήκαμε τον χρόνο εκτέλεσεις των προγραμμάτων σε γλώσσα
προγραμματισμού C.
Παρατηρήστε οτι η συχνότητα ρολογιού της υλοποίησης του Microblaze είναι διαφορετική σε καθε
περίπτωση ( οφείλεται στον αλγόριθμο του εργαλείου σύνθεσης και των λειτουργικών μονάδων που
συντίθεται ). Επίσης ο χρόνος της υλοποιήσης με Microblaze αναφέρεται για 2 διαφορετικές περιπτώσεις:
λαμβάνοντας ή μη τους απαιτούμενους κύκλους αρχικοποίησης
Πρόβλημμα 1ο:Διάνυσμα επί διάνυσμα
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
Σειριακή 129 11.682 1506,978
Παραλληλοποίηση 1 33 13.285 438,405
Παραλληλοποίηση 2 9 12.862 115,758
Microblaze 14954 8.864 132552,26
Χωρίς initial time 8.864 123457,792
Software 150659,50
Page 39
- 39 -
Πρόβλημμα 2ο:Κόσκινο του Ερατοσθένη
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 363 9.387 3407,481
Microblaze 11246 7.921 89079,566
Χωρίς initial time 7.921 80952,62
Software 56135,90
Πρόβλημμα 3ο:RNS Assisted Image Filtering and Edge Detection
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 96 12.548 1204,608
Microblaze 183805 8.167 1501135,44
Χωρίς initial time 8.167 1492756,09
Software 74145,34
Πρόβλημμα 4ο:Υπολογισμός απόστασης ανάμεσα σε δύο διανύσματα
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 147 9.084 1335,348
Παραλληλοποίηση 1 50 9.604 480,2
Παραλληλοποίηση 2 26 10.536 273,963
Microblaze 31476 8.175 257316,3
Χωρίς initial time 8.175 248928,75
Software 149707,6
Πρόβλημμα 5ο:Τέλειοι αριθμοί
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 4065 6.878 27959,07
Microblaze 117357 8.167 958454,619
Χωρίς initial time 950075,277
Software 70964,47
Page 40
- 40 -
Πρόβλημμα 6ο:Aκολουθία Fibonacci
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 32 8.307 265,824
Microblaze 1610 8.167 13148,87
Χωρίς initial time 4769,528
Software 44567,13
Πρόβλημμα 7ο:Κωδικοποίιηση Δέλτα
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 139 8.375 1164,125
Παραλληλοποίηση 1 100 8.549 854,9
Microblaze 17397 8.167 142081,299
Χωρίς initial time 133701,956
Software 144871,8
Πρόβλημμα 8ο:Bubble sort
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 20895 8.109 169437,56
Microblaze 506402 8.167 4135785,13
Χωρίς initial time 4127405,79
Software 207158,94
Πρόβλημμα 9ο:Ακολουθία Hailstone
Κύκλοι ρολογιού Μέγιστη καθυστέρηση(ns) Χρόνος εκτέλεσης(ns)
σειριακή 168 8.241 1384,488
Microblaze 15485 7.651 118475,735
Χωρίς initial time 110625,809
Software 132274,13
Page 45
- 45 -
Στους πίνακες 4.1 έως 4.9 βλέπουμε πόσο λογικα στοιχεία καταλαμβάνει κάθε σχεδιάσμος στο FPGA
που επιλέξαμε ( Spartan 6 ). Παρατηρούμε οτι ο αριθμός των λογικών στοιχείων που απαιτεί ο
Microblaze είναι σχεδόν σταθερός σε κάθε σχεδιασμό. Έτσι σε σχεδιασμούς που απαιτούν περισσότερα
λογικά στοιχεία σε σχέση με τον Microblaze η χρήση του soft processor απελευθερώνει αρκετό χώρο στο
FPGA που είναι πλέον διαθέσιμος στον χρήστη. Οι μικρές διαφορές στα λογικά στοιχεία που
καταλαμβάνει ο Microblaze προκυπτούν απο τον αλγόριθμο σύνθεσης, καθώς αυτος επιλέγει που θα
τοποθετηθεί πάνω στο FPGA. Αυτό αλλάζει σε καθε σύνθεση του εκάστοτε σχεδιασμού.
Πίνακας 4.1
Εσωτερικό γινόμενο Slices που καταλαμβάνει
Σειριακή 36 στα 2.278 (1%)
Παραλληλοποίηση 1 55 στα 2.278 (2%)
Παραλληλοποίηση 2 116 στα 2.278 (5%)
Microblaze 376 στα 2.278 (16%)
Page 46
- 46 -
Πίνακας 4.2
Πίνακας 4.3
Πίνακας 4.4
Πίνακας 4.5
Πίνακας 4.6
Κόσκινο του Ερατοσθένη Slices που καταλαμβάνει
σειριακή 194 στα 2.278 (8%)
Microblaze 365 στα 2.278 (16%)
RNS Assisted Image Filtering Slices που καταλαμβάνει
σειριακή 2104 στα 2.278 (92%)
Microblaze 420 στα 2.278 (18%)
Υπολογισμός απόστασης
ανάμεσα σε δύο διανύσματα
Slices που καταλαμβάνει
σειριακή 66 στα 2.278 (2%)
Παραλληλοποίηση 1 115 στα 2.278 (5%)
Παραλληλοποίηση 2 118 στα 2.278 (8%)
Microblaze 405 στα 2.278 (17%)
Τέλειοι αριθμοί Slices που καταλαμβάνει
σειριακή 175 στα 2.278 (7%)
Microblaze 420 στα 2.278 (18%)
Aκολουθία Fibonacci Slices που καταλαμβάνει
σειριακή 51 στα 2.278 (2%)
Microblaze 420 στα 2.278 (18%)
Page 47
- 47 -
Πίνακας 4.7
Πίνακας 4.8
Πίνακας 4.9
Κωδικοποίιηση Δέλτα Slices που καταλαμβάνει
σειριακή 23 στα 2.278 (1%)
Παραλληλοποίηση 1 23 στα 2.278 (1%)
Microblaze 420 στα 2.278 (18%)
Bubble sort Slices που καταλαμβάνει
σειριακή 727 στα 2.278 (31%)
Microblaze 420 στα 2.278 (18%)
Ακολουθία Hailstone Slices που καταλαμβάνει
σειριακή 21 στα 2.278 (1%)
Microblaze 379 στα 2.278 (16%)
Page 48
- 48 -
ΒΙΒΛΙΟΓΡΑΦΙΑ
[1] https://www.xilinx.com/products/intellectual-property/microblazecore.html
[2] https://www.xilinx.com/support/documentation/quick_start/microblaze-quick-start-g
uide.pdf
[3] https://www.xilinx.com/publications/product-briefs/microblaze-product-brief.pdf
[4] https://www.xilinx.com/support/documentation/sw_manuals/mb_ref_guide.pdf
[5] http://ibelimb.com/2014/03/30/generating-a-microblaze-soft-processor-with-ise-web
pack-14-dot-7/
[6] https://el.wikipedia.org/wiki/FPGA
[7] https://www.xilinx.com/products/silicon-devices/fpga.html
[8] https://www.geeksforgeeks.org/sieve-of-eratosthenes/
[9] https://www.fpga4fun.com/FPGAinfo2.html
[10] https://www.intel.com/content/www/us/en/products/programmable/fpga.html
[11] https://www.fpgarelated.com/showarticle/17.php
[12] http://www.embeddedinsights.com/epd/lattice/lattice-latticemico8.php
[13] http://www.latticesemi.com/en/Products/DesignSoftwareAndIP/IntellectualPropert
y/IPCore/IPCores02/LatticeMico32.aspx
[14] https://www.latticesemi.com/view_document?document_id=52077
[15] https://en.wikipedia.org/wiki/Nios_II
[16] https://www.intel.ca/content/www/ca/en/products/programmable/processor/nios-ii.
html
[17] https://people.ece.cornell.edu/land/courses/ece5760/DE2/tut_nios2_introduction.
pdf
[18] https://www.microsemi.com/company/about-us
[19] https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/sg/pr
oduct-catalog.pdf
Page 49
- 49 -
ΠΑΡΑΡΤΗΜΑΚώδικας verilog για την hardware υλοποίηση του 1ου προβλήμματος :(σειριακή)
1. `timescale 1ns / 1ps
2. module eso_gin(clk,reset,result);
3. input clk;
4. input reset;
5. output reg signed [31:0] result; //καταχωρητής εξόδου για το αποτέλεμα
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,j,temp_0,temp_1;
10. reg [7:0] mem0 [0:N];//[wide] R[rows][cols]
11. reg [7:0] mem1 [0:N];//[wide] R[rows][cols]
12.
13. initial begin //αρχικοποίηση δεδομένων
14. //πρώτο διάνυσμα
15. mem0[0]=0; mem0[1]=1; mem0[2]=2; mem0[3]=3; mem0[4]=4; mem0[5]=5; mem0[6]=6; mem0[7]=7;
16. mem0[8]=8; mem0[9]=9; mem0[10]=10; mem0[11]=11; mem0[12]=12; mem0[13]=13; mem0[14]=14;
17. mem0[15]=15; mem0[16]=0;.......
18. //δεύτερο διάνυσμα
19. mem1[0]=2; mem1[1]=2; mem1[2]=14; mem1[3]=2; mem1[4]=4; mem1[5]=10; mem1[6]=12; mem1[7]=0;
20. mem1[8]=10; mem1[9]=2; mem1[10]=14; mem1[11]=2; mem1[12]=4; mem1[13]=10; mem1[14]=12;
21. mem1[15]=15; mem1[16]=2;......
22. end
23. always @ (clk)
24. if (reset)
25. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
26. else
27. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
28. always @(state)
29. begin
30. case(state)
31. s1:begin
32. i=0; temp_1=0; //αρχικοποίηση προσωρινών μεταβλητών
Page 50
- 50 -
33. nextstate=s2; //ορισμός επόμενης κατάστασης
34. end
35. s2:if(i<=N) //έλεγχος ορίων διανυσμάτων
36. begin
37. temp_0=(mem0[i]*mem1[i]); //πολλαπλασιασμός δεδομένων
38. temp_1=temp_1+temp_0; //πρόσθεση αποτελέσματος πολ/σμου
39. nextstate = s3; //ορισμός επόμενης κατάστασης
40. end
41. else
42. nextstate = s4; //ορισμός επόμενης κατάστασης
43. s3:begin
44. i=i+1; //αύξηση δείκτη διανύσματος
45. nextstate = s2; //ορισμός επόμενης κατάστασης
46. end
47. s4:result=temp_1 //καταχώρηση τελικού αποτελέσματος στον
48. endcase // καταχωρητή εξόδου
49. end
50. Endmodule
Κώδικας verilog για την hardware υλοποίηση του 1ου προβλήμματος:(4 πράξεις)
1. `timescale 1ns / 1ps
2. module eso_gin(clk,reset,result);
3. input clk;
4. input reset;
5. output reg signed [31:0] result; //καταχωρητής εξόδου για το αποτέλεμα
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,j,temp_0,temp_1,temp_2,temp_3,temp_4;
10. reg [7:0] mem0 [0:N]; //[wide] R[rows][cols]
11. reg [7:0] mem1 [0:N]; //[wide] R[rows][cols]
12. initial begin //αρχικοποίηση δεδομένων
13. //πρώτο διάνυσμα
14. mem0[0]=0; mem0[1]=1; mem0[2]=2; mem0[3]=3; mem0[4]=4; mem0[5]=5; mem0[6]=6; mem0[7]=7;
Page 51
- 51 -
15. mem0[8]=8; mem0[9]=9; mem0[10]=10; mem0[11]=11; mem0[12]=12; mem0[13]=13; mem0[14]=14;
16. mem0[15]=15; mem0[16]=0;.......
17. //δεύτερο διάνυσμα
18. mem1[0]=2; mem1[1]=2; mem1[2]=14; mem1[3]=2; mem1[4]=4; mem1[5]=10; mem1[6]=12; mem1[7]=0;
19. mem1[8]=10; mem1[9]=2; mem1[10]=14; mem1[11]=2; mem1[12]=4; mem1[13]=10; mem1[14]=12;
20. mem1[15]=15; mem1[16]=2;……
21. end
22. always @ (clk)
23. if (reset)
24. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
25. else
26. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
27. always @(state)
28. begin
29. case(state)
30. s1:begin
31. i=0; temp_1=0; //αρχικοποίηση προσωρινών μεταβλητών
32. nextstate=s2; //ορισμός επόμενης κατάστασης
33. end
34. s2:if(i<N) //έλεγχος ορίων διανυσμάτων
35. begin
36. temp_0 =(mem0[i]*mem1[i]); temp_2 =(mem0[i+1]*mem1[i+1]);
37. temp_3 =(mem0[i+2]*mem1[i+2]); temp_4 =(mem0[i+3]*mem1[i+3]); //πολ/σμός δεδομένων
38.
39. temp_1=temp_1+(temp_0+temp_2+temp_3+temp_4); //πρόσθεση αποτελέσματος πολ/σμου
40. nextstate = s3; //ορισμός επόμενης κατάστασης
41. end
42. else
43. nextstate = s4; //ορισμός επόμενης κατάστασης
44. s3:begin
45. i=i+4; //αύξηση δείκτη διανύσματος nextstate = s2; //ορισμός επόμενης κατάστασης
46. end
47. s4:result=temp_1; //καταχώρηση τελικού αποτελέσματος στον καταχωρητή εξόδου
48. endcase
Page 52
- 52 -
49. end
50. endmodule
Κώδικας verilog για την hardware υλοποίηση του 1ου προβλήμματος:(16 πράξεις)
1. `timescale 1ns / 1ps
2. module eso_gin(clk,reset,result);
3. input clk;
4. input reset;
5. output reg signed [31:0] result; //καταχωρητής εξόδου για το αποτέλεμα
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,temp_0,temp_1,temp_2,temp_3, temp_4,temp_5,temp_6,temp_7,
10. temp_8,temp_9,temp_10,temp_11,temp_12,temp_13,temp_14,
11. temp_15,temp_16;
12. integer temp01,temp02,temp03,temp04;
13. reg [7:0] mem0 [0:N]; //[wide] R[rows][cols]
14. reg [7:0] mem1 [0:N]; //[wide] R[rows][cols]
15.
16. initial begin //αρχικοποίηση δεδομένων
17. //πρώτο διάνυσμα
18. mem0[0]=0; mem0[1]=1; mem0[2]=2; mem0[3]=3; mem0[4]=4; mem0[5]=5; mem0[6]=6; mem0[7]=7;
19. mem0[8]=8; mem0[9]=9; mem0[10]=10; mem0[11]=11; mem0[12]=12; mem0[13]=13; mem0[14]=14;
20. mem0[15]=15; mem0[16]=0;…….
21. //δεύτερο διάνυσμα
22. mem1[0]=2; mem1[1]=2; mem1[2]=14; mem1[3]=2; mem1[4]=4; mem1[5]=10; mem1[6]=12; mem1[7]=0;
23. mem1[8]=10; mem1[9]=2; mem1[10]=14; mem1[11]=2; mem1[12]=4; mem1[13]=10; mem1[14]=12;
24. mem1[15]=15; mem1[16]=2;…….
25. end
26. always @ (clk)
27. if (reset)
28. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
29. else
30. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
Page 53
- 53 -
31. always @(state)
32. begin
33. case(state)
34. s1:begin
35. i=0; temp_1=0; //αρχικοποίηση προσωρινών μεταβλητών
36. nextstate=s2; //ορισμός επόμενης κατάστασης
37. end
38. s2:if(i<N) //έλεγχος ορίων διανυσμάτων
39. begin
40. //πολλαπλασιασμός δεδομένων
41. temp_0=(mem0[i]*mem1[i]); temp_2=(mem0[i+1]*mem1[i+1]); temp_3=(mem0[i+2]*mem1[i+2]);
42. temp_4=(mem0[i+3]*mem1[i+3]); temp_5=(mem0[i+4]*mem1[i+4]); temp_6=(mem0[i+5]*mem1[i+5]);
43. temp_7=(mem0[i+6]*mem1[i+6]); temp_8=(mem0[i+7]*mem1[i+7]); temp_9=(mem0[i+8]*mem1[i+8]);
44. temp_10=(mem0[i+9]*mem1[i+9]); temp_11=(mem0[i+10]*mem1[i+10]);
45. temp_12=(mem0[i+11]*mem1[i+11]); temp_13=(mem0[i+12]*mem1[i+12]);
46. temp_14=(mem0[i+13]*mem1[i+13]); temp_15=(mem0[i+14]*mem1[i+14]);
47. temp_16=(mem0[i+15]*mem1[i+15]);
48.
49. temp01=temp_0 +temp_2 +temp_3 +temp_4; temp02=temp_5 +temp_6 +temp_7 +temp_8;
50. temp03=temp_9+temp_10+temp_11+temp_12; temp04=temp_13+temp_14+temp_15+temp_16;
51.
52. temp_1=temp_1+(temp01+temp02+temp03+temp04); //πρόσθεση αποτελέσματος πολ/σμου
53. nextstate = s3; //ορισμός επόμενης κατάστασης
54. end
55. else
56. nextstate = s4; //ορισμός επόμενης κατάστασης
57. s3:begin
58. i=i+16; //αύξηση δείκτη κατα 16 nextstate = s2; //ορισμός επόμενης κατάστασης
59. end
60. s4:result=temp_1;
61. endcase
62. end
63.endmodule
Page 54
- 54 -
Κώδικας C για τον soft processor του 1ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include <xparameters.h>
4. #include <xiomodule.h>
5. XIOModule gpo;
6. int main()
7. {
8. init_platform();
9. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID); //Initialize the GPO module
10. XIOModule_Start(&gpo); //start the GPO module
11. int i;
12. int b[128]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, //αρχικοποίηση δεδομένων πρώτου διανύσματος
13. .......
14. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
15.
16. int a[128]={2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15, //αρχικοποίηση δεδομένων δεύτερου διανύσματος
17. ......
18. 2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15 };
19. int c=0;
20. for(i=0;i<128;i++){
21. c=c+a[i]*b[i]; //πρόσθεση αποτελέσματος πολ/σμού στην άθροιση
22. }
23. u16 leds = c ;
24. while (1){
25. // write the LED value to port 1 (you can have up to 4 ports)
26. XIOModule_DiscreteWrite(&gpo, 1,leds); //εμφάνιση αποτελέσματος στην έξοδο
27. }
28. return 0;
29.}
Page 55
- 55 -
Κώδικας C για την software υλοποίηση του 1ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h>
3. #include <time.h> //for clock_t, clock()
4. #include <unistd.h>// for sleep()
5. #define BILLION 1000000000;
6. int main()
7. {
8. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
9. struct timespec start, end;
10. clock_gettime(CLOCK_REALTIME, &start);
11. //
12. int i;
13. int b[128]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, //αρχικοποίηση δεδομένων πρώτου διανύσματος
14. .......
15. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
16. int a[128]={2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15, //αρχικοποίηση δεδομένων δεύτερου διανύσματος
17. .......
18. 2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15 };
19. int c=0;
20. for(i=0;i<128;i++)
21. {
22. c=c+a[i]*b[i]; //πρόσθεση αποτελέσματος πολ/σμού στην άθροιση
23. printf("%d\n",c); //εμφάνιση αποτελέσματος στην οθόνη
24. }
25. printf("final result:%d\n",c); //εμφάνιση τελικού αποτελέσματος στην οθόνη
26.
27. //υπολογιμός χρόνου εκτέλεσης προγράμματος
28. clock_gettime(CLOCK_REALTIME, &end);
29. //time_spent = end - start
30. double time_spent=(end.tv_sec-start.tv_sec) +(end.tv_nsec-start.tv_nsec) / BILLION;//time_spent=end-start
31. printf("\n");
32. printf("Time elpased is %.9f seconds", time_spent);return 0; //εμφάνισει χρόνου στην οθόνη σε n
33.}
Page 56
- 56 -
Κώδικας verilog για την hardware υλοποίηση του 2ουπροβλήμματος:
1. `timescale 1ns / 1ps
2. module check(clk,reset,counter);
3. input clk;
4. input reset;
5. output reg [7:0] counter; //καταχωρητής εξόδου
6. reg valid=0;
7. reg [3:0] state, nextstate;
8. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10,s11=11,s12=12,s13=13;
9. integer i,j,k;
10. reg RAM [127:0] ;
11. reg temp;
12. initial
13. begin
14. for(k=0;k<=127;k=k+1)
15. RAM[k]=0; //αρχικοποίηση μνήμης στο 0
16. end
17.
18. always @ (clk)
19. if (reset)
20. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
21. else
22. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
23. always @(state)
24. begin
25. case(state)
26. s1:begin
27. counter=0; i=2; RAM[0]=1; RAM[1]=1; //αρχικοποίηση προσωρινών μεταβλητών
28. nextstate = s7; //ορισμός επόμενης κατάστασης
29. end
30. s2:begin
31. temp=RAM[i];
32. if(temp==0) //αν το temp ειναι “0” διαγράφουμε ολα τα πολ/σιά του
33. nextstate = s3; //ορισμός επόμενης κατάστασης
Page 57
- 57 -
34. else
35. nextstate = s6; //ορισμός επόμενης κατάστασης
36. end
37. s3:begin
38. j=i*i; nextstate = s5;//ορισμός επόμενης κατάστασης
39. end
40. s4:begin
41. RAM[j]=1; //ορισμός θέσεις μνήμης στο ‘’1’’,ο αριθμός δεν είναι πρώτος
42. j=j+I; nextstate = s5;//ορισμός επόμενης κατάστασης
43. end
44. s5:if(j<=127) //ελέγχος αν ο δείκτης j είναι μέσα στα όρια του διανύσματος
45. nextstate = s4; //ορισμός επόμενης κατάστασης
46. else
47. nextstate = s6; //ορισμός επόμενης κατάστασης
48. s6:begin
49. i=i+1; nextstate = s7;//ορισμός επόμενης κατάστασης
50. end
51. s7:if(i<=12)
52. nextstate = s2; //ορισμός επόμενης κατάστασης
53. else
54. nextstate = s8; //ορισμός επόμενης κατάστασης
55. s8:begin
56. i=2; nextstate = s12; //ορισμός επόμενης κατάστασης
57. end
58. s9:begin //αρχίζουμε να μετράμε τους πρώτους αριθμούς
59. temp=RAM[i];
60. if(temp==0)
61. nextstate = s10; //ορισμός επόμενης κατάστασης
62. else
63. nextstate = s11; //ορισμός επόμενης κατάστασης
64. end
65. s10:begin
66. counter=counter+1;//αύξηση καταχωρητή εξόδου κατά ένα nextstate = s11;//ορισμός επόμενης κατάστασης
67. end
Page 58
- 58 -
68. s11:begin
69. i=i+1;//αύξηση δεικτη κατά ένα για να διατρέξουμε ολοι την λίστα
70. nextstate = s12;//ορισμός επόμενης κατάστασης
71. end
72. s12:begin
73. if(i<=127) //διατρέχουμε όλοι την λίστα
74. nextstate = s9; //ορισμός επόμενης κατάστασης
75. else
76. nextstate = s13; //ορισμός επόμενης κατάστασης
77. end
78. s13:begin
79. valid=1; // το valid γίνεται ίσο με “1” μετα το πέρας της διαδικασίας
80. end
81. endcase
82. end
83. endmodule
Κώδικας C για τον soft processor του 2ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include <xparameters.h>
4. #include <xiomodule.h>
5. #include <stdbool.h>
6. XIOModule gpo;
7. int main()
8. {
9. init_platform();
10. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID); //Initialize the GPO module
11. XIOModule_Start(&gpo); // start the GPO module
12. int i,p;
13. bool prime[128];
14. for(i=0;i<128;i++)
15. { prime[i]=true; } //αρχικοποίηση πίνακα σε true
16. for ( p=2; p*p<=128; p++)
Page 59
- 59 -
17. {
18. if (prime[p] == true)
19. {
20. for (int i=p*p; i<=128; i += p)
21. prime[i] = false; //θέτουμε σε false όσους αριθμούς δεν είναι πρώτη
22. }
23. }
24. while (1){
25. // write the LED value to port 1 (you can have up to 4 ports)
26. //XIOModule_DiscreteWrite(&gpo, 1,leds);
27. for (p=2; p<=128; p++) //διατρέχουμε τον πίνακα και αν η τιμή ειναι true
28. { //εμφανίζουμε τον δείκτη,δηλαδή τον αριθμό
29. if (prime[p])
30. { XIOModule_DiscreteWrite(&gpo, 1,p); } //εμφάνιση αποτελέσματος στην έξοδο
31. }
32. }
33. return 0;
34.}
Κώδικας C για την software υλοποίηση του 2ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h>
3. #include <time.h> // for clock_t, clock()
4. #include <unistd.h> // for sleep()
5. #define BILLION 1000000000.0;
6. int main()
7. {
8. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
9. struct timespec start, end;
10. clock_gettime(CLOCK_REALTIME, &start);
11. int n=127;
12. bool prime[n+1];
13. for(int i=0;i<=n;i++) //αρχικοποίηση πίνακα prime σε true
Page 60
- 60 -
14. { prime[i]=true; };
15. for (int p=2; p*p<=n; p++) //διατρέχουμε τον πίνακα για να βρούμε τους πρώτους αριθμούς
16. {
17. if (prime[p] == true)
18. {
19. for (int i=p*p; i<=n; i =i+p)
20. { prime[i] = false; }
21. }
22. }
23. for (int p=2; p<=n; p++) // Print all prime numbers
24. if(prime[p])
25. {printf("%d\n",p); }
26. //υπολογιμός χρόνου εκτέλεσης προγράμματος
27. clock_gettime(CLOCK_REALTIME, &end);
28. double time_spent=(end.tv_sec-start.tv_sec)+(end.tv_nsec-start.tv_nsec) /BILLION;//time_spent=end-start
29. printf("\n");
30. printf("Time elpased is %.9f seconds", time_spent);return 0; //εμφάνιση χρόνου στην οθόνη σε ns
31. }
Κώδικας verilog για την hardware υλοποίηση του 3ου προβλήμματος:
1. `timescale 1ns / 1ps
2. module bin_res(clk,reset,done);
3. input clk;
4. input reset;
5. output reg [7:0] done; //καταχωρητής εξόδου
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10,s11=11,s12=12;
8. parameter N=14;
9. integer i,j;
10. integer m0,m1,m2,m3,m4,m5,m6,m7,m8, n0,n1,n2,n3,n4,n5,n6,n7,n8, b0,b1,b2,b3,b4,b5,b6,b7,b8;
11. integer g1,g2,g3,f;
12. reg [7:0] mem0[0:N][0:N]; //[wide] R[rows][cols]
13.
14. initial begin //αρχικοποίηση δεδομένων,εικόνας μεγέθους 15x15
Page 61
- 61 -
15. mem0[0][0]=135; mem0[0][1]=136; mem0[0][2]=137; mem0[0][3]=139; mem0[0][4]=140; mem0[0][5]=141;
16. mem0[0][6]=142; mem0[0][7]=143; mem0[0][8]=142;mem0[0][9]=141;mem0[0][10]=140; mem0[0][11]=139;
17. mem0[0][12]=138; mem0[0][13]=136; mem0[0][14]=135;
18. ........
19. end
20. always @ (clk)
21. if (reset)
22. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
23. else
24. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
25. always @(state)
26. begin
27. case(state)
28. s1:begin
29. i=0; j=0; //αρχικοποίηση προσωρινών μεταβλητών nextstate=s2;//ορισμός επόμενης κατάστασης
30. end
31. s2:if(i<=12) //διατρέχουμε όλη την εικόνα
32. nextstate = s3; //ορισμός επόμενης κατάστασης
33. else
34. nextstate = s12; //ορισμός επόμενης κατάστασης
35. s3:if(j<=12) //διατρέχουμε όλη την εικόνα
36. nextstate = s4; //ορισμός επόμενης κατάστασης
37. else
38. nextstate = s11; //ορισμός επόμενης κατάστασης
39. s4:begin
40. //υπολογιμός πινικα Ι1
41. m0<=mem0[i][j]%31; m1<=mem0[i][j+1]%31; m2<=mem0[i][j+2]%31; m3<=mem0[i+1][j]%31;
42. m4<=mem0[i+1][j+1]%31; m5<=mem0[i+1][j+2]%31; m6<=mem0[i+2][j]%31;
43. m7<=mem0[i+2][j+1]%31; m8<=mem0[i+2][j+2]%31;
44. //υπολογιμός πινικα Ι2
45. n0<=mem0[i][j]%32; n1<=mem0[i][j+1]%32; n2<=mem0[i][j+2]%32; n3<=mem0[i+1][j]%32;
46. n4<=mem0[i+1][j+1]%32; n5<=mem0[i+1][j+2]%32; n6<=mem0[i+2][j]%32; n7<=mem0[i+2][j+1]%32;
47. n8<=mem0[i+2][j+2]%32;
48. //υπολογιμός πινικα Ι3
Page 62
- 62 -
49. b0<=mem0[i][j]%33; b1<=mem0[i][j+1]%33; b2<=mem0[i][j+2]%33; b3<=mem0[i+1][j]%33;
50. b4<=mem0[i+1][j+1]%33; b5<=mem0[i+1][j+2]%33; b6<=mem0[i+2][j]%33; b7<=mem0[i+2][j+1]%33;
51. b8<=mem0[i+2][j+2]%33;
52. nextstate = s5; //ορισμός επόμενης κατάστασης
53. end
54. s5:begin
55. //Gauss filter για I1
56. g1<=((m0+2*m1+m2+ 2*m3+2*m4+2*m5+ m6+2*m7+ m8)/14)%33;
57. //Gauss filter για I2
58. g2<=((n0+2*n1+n2+ 2*n3+2*n4+2*n5+ n6+2*n7+n8)/14)%33;
59. //Gauss filter για I3
60. g3<=((b0+2*b1+b2+ 2*b3+2*b4+2*b5+ b6+2*b7+b8)/14)%33;
61. nextstate = s6; //ορισμός επόμενης κατάστασης
62. end
63. s6:begin
64. f=(-32*g2+528*g1-496*g3); //υπολογισμός τιμής f
65. nextstate = s7;
66. end
67. s7:begin
68. if(f>=0) //έλεγχος αν το f θετικό
69. begin
70. f =g2+32*(f%1023);
71. nextstate = s9; //ορισμός επόμενης κατάστασης
72. end
73. else
74. begin
75. nextstate = s8; //ορισμός επόμενης κατάστασης
76. end
77. end
78. s8:begin
79. f=f+1023;
80. nextstate = s7; //ορισμός επόμενης κατάστασης
81. end
82. s9:begin
Page 63
- 63 -
83. //ανάθεση τιμής f στο 3x3 μπλοκ της εικόνας
84. mem0[i][j] <=f; mem0[i][j+1] <=f; mem0[i][j+2] <=f; mem0[i+1][j]<=f; mem0[i+1][j+1]<=f;
85. mem0[i+1][j+2]<=f; mem0[i+2][j]<=f; mem0[i+2][j+1]<=f; mem0[i+2][j+2]<=f;
86. done=f; //εμφάνιση τιμής f στην οθόνη
87. nextstate = s10; //ορισμός επόμενης κατάστασης
88. end
89. s10:begin
90. j=j+3;//παίρνουμε επόμενο μπλοκ της εικόνας nextstate = s3;//ορισμός επόμενης κατάστασης
91. end
92. s11:begin
93. i=i+3; //παίρνουμε επόμενο μπλοκ της εικόνας
94. j=0;
95. nextstate = s2; //ορισμός επόμενης κατάστασης
96. end
97. s12:done=1; //το done γίνεται “1” όταν ολοκληρωθεί η διαδικασία
98. endcase
99. end
100. endmodule
Κώδικας C για τον soft processor του 3ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include <xparameters.h>
4. #include <xiomodule.h>
5. #include <stdbool.h>
6. XIOModule gpo;
7. int main()
8. {
9. init_platform();
10.
11. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);//Initialize the GPO module
12. XIOModule_Start(&gpo); // start the GPO module
13. int i,j;
14. int m0,m1,m2,m3,m4,m5,m6,m7,m8, n0,n1,n2,n3,n4,n5,n6,n7,n8, b0,b1,b2,b3,b4,b5,b6,b7,b8;
Page 64
- 64 -
15. int g1,g2,g3;
16. //αρχικοποίηση δεδομένων,εικόνας μεγέθους 15x15
17. int im[15][15]={ {135,136,137,139,140,141,142,143,142,141,140,139,138,136,135},
18. ......
19. {138,139,140,141,142,143,144,145,144,143,142,141,140,138,137}, };
20. for(i=0;i<=12;i=i+3)
21. {
22. for(j=0;j<=12;j=j+3)
23. {
24. //υπολογιμός πινικα Ι1
25. m0=im[i][j]%31; m1=im[i][j+1]%31; m2=im[i][j+2]%31; m3=im[i+1][j]%31; m4=im[i+1][j+1]%31;
26. m5=im[i+1][j+2]%31; m6=im[i+2][j]%31; m7=im[i+2][j+1]%31; m8=im[i+2][j+2]%31;
27. //υπολογιμός πινικα Ι2
28. n0=im[i][j]%32; n1=im[i][j+1]%32; n2=im[i][j+2]%32;n3=im[i+1][j]%32; n4=im[i+1][j+1]%32;
29. n5=im[i+1][j+2]%32; n6=im[i+2][j]%32; n7=im[i+2][j+1]%32; n8=im[i+2][j+2]%32;
30. //υπολογιμός πινικα Ι3
31. b0=im[i][j]%33; b1=im[i][j+1]%33; b2=im[i][j+2]%33; b3=im[i+1][j]%33; b4=im[i+1][j+1]%33;
32. b5=im[i+1][j+2]%33; b6=im[i+2][j]%33; b7=im[i+2][j+1]%33; b8=im[i+2][j+2]%33;
33. //Gauss filter για I1,I2,I3
34. g1=((m0+2*m1+m2 + 2*m3+2*m4+2*m5 + m6+2*m7+m8)/14)%33;
35. g2=((n0+2*n1+n2 + 2*n3+2*n4+2*n5 + n6+2*n7+n8)/14)%33;
36. g3=((b0+2*b1+b2 + 2*b3+2*b4+2*b5 + b6+2*b7+b8)/14)%33;
37. int f;
38. f=(-32*g2+528*g1-496*g3); //υπολογισμός του f
39. if(f>=0) //έλεγχος αν το f θετικό
40. { f=g2+32*(f%1023); }
41. else
42. {
43. while(f<0)
44. { f=f+1023;}
45. f=g2+32*(f%1023);
46. }
47. //ανάθεση τιμής f στο 3x3 μπλοκ της εικόνας
48. im[i][j]=f; im[i][j+1]=f; im[i][j+2]=f; im[i+1][j]=f; im[i+1][j+1]=f; im[i+1][j+2]=f;
Page 65
- 65 -
49. im[i+2][j]=f; im[i+2][j+1]=f; im[i+2][j+2]=f;
50. }
51. }
52. while (1){
53. // write the LED value to port 1 (you can have up to 4 ports)
54. //XIOModule_DiscreteWrite(&gpo, 1,leds);
55. for(i=0;i<15;i++) //διατρέχουμε όλοι την εικόνα
56. {
57. for(j=0;j<15;j++)
58. { XIOModule_DiscreteWrite(&gpo,1,im[i][j]); } //εμφάνιση αποτελέσματος στην έξοδο
59. }
60. }
61. return 0;
62. }
Κώδικας C για την software υλοποίηση του 3ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h>
3. #include <time.h> // for clock_t, clock()
4. #include <unistd.h>// for sleep()
5.
6. #define BILLION 1000000000.0;
7.
8. int main()
9. {
10. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
11. struct timespec start, end;
12. clock_gettime(CLOCK_REALTIME, &start);
13. //
14. int i,j;
15.
16. int m0,m1,m2,m3,m4,m5,m6,m7,m8, n0,n1,n2,n3,n4,n5,n6,n7,n8, b0,b1,b2,b3,b4,b5,b6,b7,b8;
17. int g1,g2,g3;
18. //αρχικοποίηση δεδομένων,εικόνας μεγέθους 15x15
Page 66
- 66 -
19. int im[15][15]={ {135,136,137,139,140,141,142,143,142,141,140,139,138,136,135},
20. ……..
21. {138,139,140,141,142,143,144,145,144,143,142,141,140,138,137},};
22.
23. for(i=0;i<=12;i=i+3)
24. {
25. for(j=0;j<=12;j=j+3)
26. {
27. //υπολογιμός πινικα Ι1
28. m0=im[i][j]%31; m1=im[i][j+1]%31; m2=im[i][j+2]%31; m3=im[i+1][j]%31; m4=im[i+1][j+1]%31;
29. m5=im[i+1][j+2]%31; m6=im[i+2][j]%31; m7=im[i+2][j+1]%31; m8=im[i+2][j+2]%31;
30. //υπολογιμός πινικα Ι2
31. n0=im[i][j]%32; n1=im[i][j+1]%32; n2=im[i][j+2]%32; n3=im[i+1][j]%32; n4=im[i+1][j+1]%32;
32. n5=im[i+1][j+2]%32; n6=im[i+2][j]%32; n7=im[i+2][j+1]%32; n8=im[i+2][j+2]%32;
33. //υπολογιμός πινικα Ι3
34. b0=im[i][j]%33; b1=im[i][j+1]%33; b2=im[i][j+2]%33; b3=im[i+1][j]%33; b4=im[i+1][j+1]%33;
35. b5=im[i+1][j+2]%33; b6=im[i+2][j]%33; b7=im[i+2][j+1]%33; b8=im[i+2][j+2]%33;
36. //Gauss filter για I1,I2,I3
37. g1=((m0+2*m1+m2 + 2*m3+2*m4+2*m5 + m6+2*m7+m8)/14)%33;
38. g2=((n0+2*n1+n2 + 2*n3+2*n4+2*n5 + n6+2*n7+n8)/14)%33;
39. g3=((b0+2*b1+b2 + 2*b3+2*b4+2*b5 + b6+2*b7+b8)/14)%33;
40.
41. int f;
42. f=(-32*g2+528*g1-496*g3); //υπολογισμός του f
43. if(f>=0) //έλεγχος αν το f θετικό
44. { f=g2+32*(f%1023); }
45. else
46. {
47. while(f<0)
48. { f=f+1023; }
49. f=g2+32*(f%1023);
50. }
51. //ανάθεση τιμής f στο 3x3 μπλοκ της εικόνας
52. im[i][j]=f; im[i][j+1]=f; im[i][j+2]=f;
Page 67
- 67 -
53. im[i+1][j]=f; im[i+1][j+1]=f; im[i+1][j+2]=f;
54. im[i+2][j]=f; im[i+2][j+1]=f; im[i+2][j+2]=f;
55. }
56. }
57. for(i=0;i<15;i++)
58. {
59. for(j=0;j<15;j++)
60. { printf("%d ",im[i][j]); } //εμφάνιση τελικής εικόνας
61. printf("\n");
62. }
63. //υπολογιμός χρόνου εκτέλεσης προγράμματος
64. clock_gettime(CLOCK_REALTIME, &end);
65. // time_spent = end - start
66. double time_spent = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / BILLION;
67. printf("\n");
68. printf("Time elpased is %.9f seconds", time_spent);return 0; //εμφάνιση χρόνου στην οθόνη σε ns
69. }
Κώδικας verilog για την hardware υλοποίηση του 4ου προβλήμματος:(σειριακή)
1. `timescale 1ns / 1ps
2. module euc_dis(clk,reset,result);
3. input clk;
4. input reset;
5. output reg signed [31:0] result; //καταχωρητής εξόδου
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,y,temp_0,temp_1,a,b,t0,t1,m;
10. reg [7:0] mem0 [0:N]; // [wide] R[rows][cols] reg [7:0] mem1 [0:N]; // [wide] R[rows][cols]
11. initial begin //αρχικοποίηση δεδομένων
12. //πρώτο διάνυσμα
13. mem0[0]=0; mem0[1]=1; mem0[2]=2; mem0[3]=3; mem0[4]=4; mem0[5]=5; mem0[6]=6; mem0[7]=7;
14. mem0[8]=8; mem0[9]=9;mem0[10]=10; mem0[11]=11; mem0[12]=12; mem0[13]=13; mem0[14]=14;
15. mem0[15]=15; ......
Page 68
- 68 -
16. //δεύτερο διάνυσμα
17. mem1[0]=2; mem1[1]=2; mem1[2]=14; mem1[3]=2; mem1[4]=4; mem1[5]=10; mem1[6]=12;mem1[7]=0;
18. mem1[8]=10; mem1[9]=2; mem1[10]=14; mem1[11]=2; mem1[12]=4; mem1[13]=10; mem1[14]=12;
19. mem1[15]=15;.....
20. end
21.
22. always @ (clk)
23. if (reset)
24. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
25. else
26. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
27. always @(state)
28. begin
29. case(state)
30. s1:begin
31. i=0; temp_1=0;//αρχικοποίηση προσωρινών μεταβλητών nextstate=s2;//ορισμός επόμενης κατάστασης
32. end
33. s2:if(i<=N)
34. begin
35. temp_0=(mem0[i]-mem1[i])*(mem0[i]-mem1[i]); //(xi-yi)^2
36. temp_1=temp_1+temp_0; //προσθέτουμε στο άθροισμα
37. nextstate = s3; //ορισμός επόμενης κατάστασης
38. end
39. else
40. nextstate = s4; //ορισμός επόμενης κατάστασης
41. s3:begin
42. i=i+1;//αύξηση κατά ένα του δείκτη nextstate = s2;//ορισμός επόμενης κατάστασης
43. end
44. s4:begin
45. a=temp_1; m=65536;//2^16 y=0;
46. nextstate = s5; //ορισμός επόμενης κατάστασης
47. end
48. s5:if(m!=0)
49. nextstate = s6; //ορισμός επόμενης κατάστασης
Page 69
- 69 -
50. else
51. nextstate = s9; //ορισμός επόμενης κατάστασης
52. s6:begin
53. b=y|m;//inclusive or y=y>>1;//logical shift right
54. if(a>=b)
55. t0=1;
56. else
57. t0=0;
58. if(t0==1)
59. nextstate = s7; //ορισμός επόμενης κατάστασης
60. else
61. nextstate = s8; //ορισμός επόμενης κατάστασης
62. end
63. s7:begin
64. a=a-b; y=y|m;//inclusive or
65. nextstate = s8; //ορισμός επόμενης κατάστασης
66. end
67. s8:begin
68. m=m>>2; //logical shift right nextstate = s5;//ορισμός επόμενης κατάστασης
69. end
70. s9:result=y; //εμφάνιση τελικού αποτελέσματος στην έξοδο
71. endcase
72. end
73.endmodule
Κώδικας verilog για την hardware υλοποίηση του 4ου προβλήμματος:(4 πράξεις)
1. `timescale 1ns / 1ps
2. module euc_dis(clk,reset,result);
3. input clk;
4. input reset;
5. output reg signed [31:0] result; //καταχωρητής εξόδου
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
Page 70
- 70 -
9. integer i,y,temp_0,temp_1,a,b,t0,t1,m;
10. reg [7:0] mem0 [0:N]; // [wide] R[rows][cols]
11. reg [7:0] mem1 [0:N]; // [wide] R[rows][cols]
12.
13. initial begin//αρχικοποίηση δεδομένων
14. //πρώτο διάνυσμα
15. mem0[0]=0; mem0[1]=1; mem0[2]=2; mem0[3]=3; mem0[4]=4; mem0[5]=5; mem0[6]=6; mem0[7]=7;
16. mem0[8]=8; mem0[9]=9; mem0[10]=10; mem0[11]=11; mem0[12]=12; mem0[13]=13; mem0[14]=14;
17. mem0[15]=15;......
18. //δεύτερο διάνυσμα
19. mem1[0]=2; mem1[1]=2; mem1[2]=14; mem1[3]=2; mem1[4]=4; mem1[5]=10; mem1[6]=12; mem1[7]=0;
20. mem1[8]=10; mem1[9]=2; mem1[10]=14; mem1[11]=2; mem1[12]=4; mem1[13]=10; mem1[14]=12;
21. mem1[15]=15;......
22. end
23. always @ (clk)
24. if (reset)
25. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
26. else
27. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
28. always @(state)
29. begin
30. case(state)
31. s1:begin
32. i=0; temp_1=0;//αρχικοποίηση προσωρινών μεταβλητών nextstate=s2;//ορισμός επόμενης κατάστασης
33. end
34. s2:if(i<=N)
35. begin
36. //(xi-yi)^2 για 4 τιμές του i
37. temp_0=(mem0[i]-mem1[i])*(mem0[i] -mem1[i]) + (mem0[i+1]-mem1[i+1])*(mem0[i+1]-mem1[i+1])+
38. (mem0[i+2]-mem1[i+2])*(mem0[i+2]-mem1[i+2])+(mem0[i+3]-mem1[i+3])*(mem0[i+3]-mem1[i+3]);
39. temp_1=temp_1+temp_0;//προσθέτουμε στο άθροισμα
40. nextstate = s3;//ορισμός επόμενης κατάστασης
41. end
42. else
Page 71
- 71 -
43. nextstate = s4; //ορισμός επόμενης κατάστασης
44. s3:begin
45. i=i+4; //αύξηση κατά 4 του δείκτη
46. nextstate = s2; //ορισμός επόμενης κατάστασης
47. end
48. s4:begin
49. a=temp_1; m =65536;//2^16 y=0;
50. nextstate = s5; //ορισμός επόμενης κατάστασης
51. end
52. s5:if(m!=0)
53. nextstate = s6; //ορισμός επόμενης κατάστασης
54. else
55. nextstate = s9; //ορισμός επόμενης κατάστασης
56. s6:begin
57. b=y|m; //inclusive or
58. y=y>>1; //logical shift right
59. if(a>=b)
60. t0=1;
61. else
62. t0=0;
63. if(t0==1)
64. nextstate = s7; //ορισμός επόμενης κατάστασης
65. else
66. nextstate = s8; //ορισμός επόμενης κατάστασης
67. end
68. s7:begin
69. a=a-b;
70. y=y|m; //inclusive or
71. nextstate = s8; //ορισμός επόμενης κατάστασης
72. end
73. s8:begin
74. m=m>>2; //logical shift right
75. nextstate = s5; //ορισμός επόμενης κατάστασης
76. end
Page 72
- 72 -
77. s9:result=y; //εμφάνιση τελικού αποτελέσματος στην έξοδο
78. endcase
79. end
80. endmodule
Κώδικας verilog για την hardware υλοποίηση του 4ου προβλήμματος:(16 πράξεις)
1. `timescale 1ns / 1ps
2. module euc_dis(clk,reset,result);
3. input clk;
4. input reset;
5. output reg signed [31:0] result; //καταχωρητής εξόδου
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,y,temp_0,temp_1,a,b,t0,t1,m;
10. reg [7:0] mem0 [0:N]; // [wide] R[rows][cols]
11. reg [7:0] mem1 [0:N]; // [wide] R[rows][cols]
12. initial begin //αρχικοποίηση δεδομένων
13. //πρώτο διάνυσμα
14. mem0[0]=0; mem0[1]=1; mem0[2]=2; mem0[3]=3; mem0[4]=4; mem0[5]=5; mem0[6]=6; mem0[7]=7;
15. mem0[8]=8; mem0[9]=9; mem0[10]=10; mem0[11]=11; mem0[12]=12; mem0[13]=13; mem0[14]=14;
16. mem0[15]=15;........
17. //δεύτερο διάνυσμα
18. mem1[0]=2; mem1[1]=2; mem1[2]=14; mem1[3]=2; mem1[4]=4; mem1[5]=10; mem1[6]=12; mem1[7]=0;
19. mem1[8]=10; mem1[9]=2; mem1[10]=14; mem1[11]=2; mem1[12]=4; mem1[13]=10; mem1[14]=12;
20. mem1[15]=15; mem1[16]=2;.....
21. end
22.
23. always @ (clk)
24. if (reset)
25. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
26. else
27. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
Page 73
- 73 -
28. always @(state)
29. begin
30. case(state)
31. s1:begin
32. i=0; temp_1=0; //αρχικοποίηση προσωρινών μεταβλητών
33. nextstate=s2; //ορισμός επόμενης κατάστασης
34. end
35. s2:if(i<N)
36. begin
37. //(xi-yi)^2 για 16 τιμές του i
38. temp_0=(mem0[i]-mem1[i])*(mem0[i]-mem1[i])+(mem0[i+1]-mem1[i+1]) *(mem0[i+1] -mem1[i+1]) +
39. (mem0[i+2]-mem1[i+2]) *(mem0[i+2] -mem1[i+2]) + (mem0[i+3] -mem1[i+3]) *(mem0[i+3] -mem1[i+3]) +
40. (mem0[i+4] -mem1[i+4]) *(mem0[i+4] -mem1[i+4]) + (mem0[i+5] -mem1[i+5]) *(mem0[i+5] -mem1[i+5]) +
41. (mem0[i+6] -mem1[i+6]) *(mem0[i+6] -mem1[i+6]) + (mem0[i+7] -mem1[i+7]) *(mem0[i+7] -mem1[i+7]) +
42. (mem0[i+8] -mem1[i+8]) *(mem0[i+8] -mem1[i+8]) +(mem0[i+9] -mem1[i+9]) *(mem0[i+9] -mem1[i+9]) +
43. (mem0[i+10]-mem1[i+10])*(mem0[i+10]-mem1[i+10])+
44. (mem0[i+11]-mem1[i+11])*(mem0[i+11]-mem1[i+11])+
45. (mem0[i+12]-mem1[i+12])*(mem0[i+12]-mem1[i+12])+
46. (mem0[i+13]-mem1[i+13])*(mem0[i+13]-mem1[i+13])+
47. (mem0[i+14]-mem1[i+14])*(mem0[i+14]-mem1[i+14])+
48. (mem0[i+15]-mem1[i+15])*(mem0[i+15]-mem1[i+15]);
49.
50. temp_1=temp_1+temp_0; //προσθέτουμε στο άθροισμα
51. nextstate = s3; //ορισμός επόμενης κατάστασης
52. end
53. else
54. nextstate = s4; //ορισμός επόμενης κατάστασης
55. s3:begin
56. i=i+16; //αύξηση κατά 16 του δείκτη
57. nextstate = s2; //ορισμός επόμενης κατάστασης
58. end
59. s4:begin
60. a=temp_1;
61. m=65536; //2^16
Page 74
- 74 -
62. y=0;
63. nextstate = s5; //ορισμός επόμενης κατάστασης
64. end
65. s5:if(m!=0)
66. nextstate = s6; //ορισμός επόμενης κατάστασης
67. else
68. nextstate = s9; //ορισμός επόμενης κατάστασης
69. s6:begin
81. b=y|m; //inclusive or
70. y=y>>1; //logical shift right
71. if(a>=b)
72. t0=1;
73. else
74. t0=0;
75.
76. if(t0==1)
77. nextstate = s7; //ορισμός επόμενης κατάστασης
78. else
79. nextstate = s8; //ορισμός επόμενης κατάστασης
80. end
81. s7:begin
82. a=a-b;
83. y=y|m; //inclusive or
84. nextstate = s8; //ορισμός επόμενης κατάστασης
85. end
86. s8:begin
87. m=m>>2; //logical shift right
88. nextstate = s5; //ορισμός επόμενης κατάστασης
89. end
90. s9:result=y; //εμφάνιση τελικού αποτελέσματος στην έξοδο
91. endcase
92. end
93. endmodule
Page 75
- 75 -
Κώδικας C για τον soft processor του 4ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include "xil_printf.h"
4. #include <xparameters.h>
5. #include <xiomodule.h>
6. #include <stdbool.h>
7. #include <math.h>
8. XIOModule gpo;
9.
10. int main()
11. {
12. init_platform();
13. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID); // Initialize the GPO module
14. XIOModule_Start(&gpo); // start the GPO module
15. //αρχικοποίηση δεδομένων
16. int mem1[128]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
17. .......
18. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
19. int mem2[128]={2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15,
20. ......
21. 2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15 };
22. int i,t=0,j;
23. //διατρέχουμε τα διανύσματα και θπολογίζουμε το (xi-yi)^2
24. for(i=0;i<128;i++)
25. { t=t+( (mem1[i]-mem2[i]) * (mem1[i]-mem2[i]) ); }
26. j=sqrt(t); //υπολογισμός ρίζας
27. while (1){
28. // write the LED value to port 1 (you can have up to 4 ports)
29. //XIOModule_DiscreteWrite(&gpo, 1,leds);
30. XIOModule_DiscreteWrite(&gpo,1,j); //εμφάνιση αποτελέσματος στην έξοδο
31. }
32. return 0;
33. }
Page 76
- 76 -
Κώδικας C για την software υλοποίηση του 4ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h>
3. #include <time.h>// for clock_t, clock()
4. #include <unistd.h> // for sleep()
5. #include <math.h>
6. #define BILLION 1000000000.0;
7.
8. int main()
9. {
10.//συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
11.struct timespec start, end;
12.clock_gettime(CLOCK_REALTIME, &start);
13.//αρχικοποίηση δεδομένων
14.int mem1[128]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
15. ......
16. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
17.int mem2[128]={2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15,
18. ......
19. 2,2,14,2,4,10,12,0,10,2,14,2,4,10,12,15};
20.int i,j;
21.int t=0;
22.//διατρέχουμε τα διανύσματα και θπολογίζουμε το (xi-yi)^2
23.for(i=0;i<128;i++)
24. { t=t+( (mem1[i]-mem2[i])*(mem1[i]-mem2[i]) );
25.printf("%d\n",t); //εμφανίζουμε το αποτέλεσμα
26.}
27.j=sqrt(t); //υπολογισμός ρίζας
Page 77
- 77 -
28.printf("\nfinal result:%d",j); //εμφανίζουμε το τελικό αποτέλεσμα
29.//υπολογιμός χρόνου εκτέλεσης προγράμματος
30.clock_gettime(CLOCK_REALTIME, &end);
31.//time_spent=end - start
32.double time_spent=(end.tv_sec-start.tv_sec)+(end.tv_nsec-start.tv_nsec)/BILLION;
33.printf("\n");
34.printf("Time elpased is \t%.9f seconds", time_spent);return 0;//εμφάνιση χρόνου στην οθόνη σε ns
35.}
Κώδικας verilog για την hardware υλοποίηση του 5ου προβλήμματος:
1. `timescale 1ns / 1ps
2. module perfect(clk,reset,value,perfect);
3. input clk;
4. input reset;
5. input [15:0] value; //καταχωρητής εισόδου
6. output reg perfect; //καταχωρητής εξόδου
7. reg [3:0] state, nextstate;
8. parameter s1=1,s2=2,s3=3,s4=4,s5=5;
9. integer i,ifinal,temp_sum=0;
10. reg [15:0] data;
11.
12. always @ (clk)
13. if (reset)
14. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
15. else
16. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
17. always @(state)
18. begin
19. case(state)
20. s1:begin
21. temp_sum=1;
22. data=value; //αρχικοποίηση προσωρινών μεταβλητών
23. nextstate = s2; //ορισμός επόμενης κατάστασης
Page 78
- 78 -
24. end
25. s2:begin
26. i=2; ifinal=data/2; //αρχικοποίηση προσωρινών μεταβλητών
27. nextstate = s3; //ορισμός επόμενης κατάστασης
28. end
29. s3:begin
30. if((data%i)==0) //ελένγχουμε αν η εισοδός μας διαιρείται με το i
31. begin
32. temp_sum=temp_sum+i; //προσθέτουμε το i στο άθροισμα
33. end
34. nextstate = s4; //ορισμός επόμενης κατάστασης
35. end
36. s4:begin
37. i=i+1; //αύξηση δείκτη κατά ένα
38. if(i<=ifinal)
39. nextstate = s3; //ορισμός επόμενης κατάστασης
40. else
41. nextstate = s5; //ορισμός επόμενης κατάστασης
42. end
43. s5:if(temp_sum == data) //το perfect γίνεται “1” αν το άθροισμα που
44. perfect = 1; //υπολογίσαμε είναι ίσο με την είσοδο
45. else
46. perfect = 0;
47. endcase
48. end
49. endmodule
Page 79
- 79 -
Κώδικας C για τον soft processor του 5ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include "xil_printf.h"
4. #include <xparameters.h>
5. #include <xiomodule.h>
6. #include <stdbool.h>
7. XIOModule gpo;
8.
9. int main()
10.{
11.init_platform();
12.XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);//Initialize the GPO module
13.
14.XIOModule_Start(&gpo); // start the GPO module
15.int x=8128;
16.int i;
17.int factorsum=1,value=x,ifinal=value/2,perfect;
18.
19.for(i=2;i<=ifinal;i++)
20. {
21. if(value % i == 0)
22. {factorsum = factorsum + i; }
23. }
24.if(factorsum == value) //το perfect γίνεται “1” αν το άθροισμα που
25. {perfect = 1;} //υπολογίσαμε είναι ίσο με την είσοδο
26.else
27. {perfect = 11;}
28.while (1){
29. //write the LED value to port 1 (you can have up to 4 ports)
30. //XIOModule_DiscreteWrite(&gpo, 1,leds); //εμφάνιση αποτελέσματος στην έξοδο
31. XIOModule_DiscreteWrite(&gpo, 1,perfect); //εμφάνιση αποτελέσματος στην έξοδο
Page 80
- 80 -
32. }
33.return 0;
34.}
Κώδικας C για την software υλοποίηση του 5ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h>
3. #include <time.h> // for clock_t, clock()
4. #include <unistd.h>// for sleep()
5. #define BILLION 1000000000.0
6. int main()
7. {
8. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
9. struct timespec start, end;
10. clock_gettime(CLOCK_REALTIME, &start);
11. int x=8128,i ,factorsum=1,value=x,ifinal=value/2,perfect;
12. for(i=2;i<=ifinal;i++)
13. {
14. if(value % i == 0)
15. {factorsum = factorsum + i; }
16. }
17.
18. if(factorsum == value) //το perfect γίνεται “1” αν το άθροισμα που
19. {perfect = 1;} // υπολογίσαμε είναι ίσο με την είσοδο
20. else
21. {perfect = 0;}
22. if(perfect==1) //εμφάνιση σημαίας perfect στην οθόνη
23. {printf("the number %d is perfect",x);}
24. else
25. {printf("the number %d is NOT perfect",x);}
26.
27. //υπολογιμός χρόνου εκτέλεσης προγράμματος
28. clock_gettime(CLOCK_REALTIME, &end);
29. // time_spent = end - start
Page 81
- 81 -
30. double time_spent = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / BILLION;
31. printf("\n");
32. printf("Time elpased is \t%.9f seconds", time_spent);return 0; //εμφάνιση χρόνου στην οθόνη σε ns
33. }
Κώδικας verilog για την hardware υλοποίηση του 6ου προβλήμματος:
1. `timescale 1ns / 1ps
2. module fib_sec(clk,reset,din,dout);
3. input clk;
4. input reset;
5. input [15:0] din; //καταχωρητής εισόδου
6. output reg [15:0] dout; //καταχωρητής εξόδου για το αποτέλεσμα
7.
8. reg [3:0] state, nextstate;
9. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8;
10. integer i,j,k;
11.
12. reg [15:0] fib=0,n; //αρχικοποίηση προσωρινών μεταβλητών
13.
14. always @ (clk)
15. if (reset)
16. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
17. else
18. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
19.
20. always @(state)
21. begin
22. case(state)
23. s1:begin
24. n=din; //καταχωρηση στο n την τιμή εισόδου
25. if(n==1)
26. nextstate = s2; //ορισμός επόμενης κατάστασης
27. else
Page 82
- 82 -
28. nextstate = s3; //ορισμός επόμενης κατάστασης
29. end
30. s2:begin
31. fib=n;
32. end
33. s3:begin
34. j=0; k=1; //στο j αποθηκευουμε το προσωρινό αποτέλεσμα
35. i=1; //το i είναι μετρητής
36. nextstate = s6; //ορισμός επόμενης κατάστασης
37. end
38. s4:begin
39. j = j + k;
40. nextstate = s5; //ορισμός επόμενης κατάστασης
41. end
42. s5:begin
43. k = j-k; i=i+1;
44. nextstate = s6; //ορισμός επόμενης κατάστασης
45. end
46. s6:if(i<=n)
47. nextstate = s4; //ορισμός επόμενης κατάστασης
48. else
49. nextstate = s7; //ορισμός επόμενης κατάστασης
50. s7:begin
51. fib = j; //εμφάνιση προσωρινού αποτελέσματος στην έξοδο
52. nextstate = s8; //ορισμός επόμενης κατάστασης
53. end
54. s8:dout=fib; //εμφάνιση τελικού αποτελέσματος στην έξοδο
55. endcase
56. end
57. endmodule
Page 83
- 83 -
Κώδικας C για τον soft processor του 6ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include "xil_printf.h"
4. #include <xparameters.h>
5. #include <xiomodule.h>
6. #include <stdbool.h>
7. XIOModule gpo;
8. int main()
9. {
10. init_platform();’
11. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);// Initialize the GPO module
12. XIOModule_Start(&gpo); // start the GPO module
13. int i,j,k,fib,n=20,y; //αρχικοποίηση προσορινών μεταβλητών
14. if(n<=1)
15. {fib=1;}
16. else
17. {
18. j=0;k=1;; //στο j αποθηκευουμε το προσωρινό αποτέλεσμα
19. i=1 //το i είναι μετρητής
20. for(i=1;i<=n;i++)
21. { j=j+k; k= j-k; }
22. fib=j; //εμφάνιση προσωρινού αποτελέσματος στην έξοδο
23. y=fib;
24. }
25. u8 leds1 = y ;
26. while (1){
27. //write the LED value to port 1 (you can have up to 4 ports)
28. //XIOModule_DiscreteWrite(&gpo, 1,leds);
29. XIOModule_DiscreteWrite(&gpo, 1,y); //εμφάνιση αποτελέσματος στην έξοδο
30. }
31. return 0;
32. }
Page 84
- 84 -
Κώδικας C για την software υλοποίηση του 6ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h> // for clock_t, clock()
3. #include <unistd.h>// for sleep()
4. #define BILLION 1000000000.0;
5. int main()
6. {
7. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
8. struct timespec start, end;
9. clock_gettime(CLOCK_REALTIME, &start);
10. int i,j,k,fib,n=20,y;
11. if(n<=1)
12. {fib=1;}
13. else
14. {
15. j=0;k=1; //στο j αποθηκευουμε το προσωρινό αποτέλεσμα
16. i=1; //το i είναι μετρητής
17. for(i=1;i<=n;i++)
18. { j=j+k; k= j-k; printf("%d\n",j); }
19. fib=j;
20. y=fib;
21. }
22. printf("%d-ostos oros=%d",n,y); //εμφανιζουμε τον n-οστό όρο στην οθόνη
23. //υπολογιμός χρόνου εκτέλεσης προγράμματος
24. clock_gettime(CLOCK_REALTIME, &end);
25. double time_spent=(end.tv_sec-start.tv_sec)+(end.tv_nsec-start.tv_nsec)/BILLION;// time_spent=end-start
26. printf("\n");
27. //εμφάνιση χρόνου στην οθόνη σε ns
28. printf("Time elpased is \t%.9f seconds", time_spent);return 0;
29. }
Page 85
- 85 -
Κώδικας verilog για την hardware υλοποίηση του 7ου προβλήμματος
1. `timescale 1ns / 1ps
2. module delta_encoder(clk,reset,done);
3. input clk;
4. input reset;
5. output reg [7:0] done; //καταχωρητής εξόδου
6. reg [2:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,k,data0;
10. reg [7:0] mem [0:N]; //[wide] R[rows][cols]
11. initial begin //αρχικοποίηση δεδομένων
12. mem[0]=1; mem[1]=-1; mem[2]=6; mem[3]=10; mem[4]=15; mem[5]=21; mem[6]=28; mem[7]=36;
13. mem[8]=45; mem[9]=55; mem[10]=66; mem[11]=78; mem[12]=91; mem[13]=105; mem[14]=120;
14. mem[15]=115; mem[16]=1;.......
15. end
16. always @ (clk)
17. if (reset)
18. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
19. else
20. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
21. always @(state)
22. begin
23. case(state)
24. s1:begin
25. done=0; //αρχικοποίηση προσωρινών μεταβλητών
26. i=0; k=0; data0=0;
27. nextstate = s2; //ορισμός επόμενης κατάστασης
28. end
29. s2:begin
30. data0=mem[i]; //αποθηκεύουμε προσωρινά το δεδομένο της θέσης i
31. mem[i]=mem[i]-k; //βρίσκουμε την νέα τιμή και την αποθηκεύουμε
32. nextstate = s3; //ορισμός επόμενης κατάστασης
33. end
Page 86
- 86 -
34. s3:begin
35. k=data0; //αποθηκεύουμε την προηγούμενη τιμή του διανύσματος
36. i=i+1; //αυξάνουμε τον δεικτη κατα ένα
37. done=done+1;
38. if(i<=N) //διατρέχουμε όλο το διάνυσμα
39. nextstate = s2; //ορισμός επόμενης κατάστασης
40. else
41. nextstate = s4; //ορισμός επόμενης κατάστασης
42. end
43. s4:done=1; //το flag γινεται “1” μετά το πέρας της διαδικασίας
44. endcase
45. end
46.endmodule
Κώδικας verilog για την hardware υλοποίηση του 7ουπροβλήμματος(16 πραξεις)
1. `timescale 1ns / 1ps
2. module delta_encoder(clk,reset,done);
3. input clk;
4. input reset;
5. output reg [7:0] done; //καταχωρητής εξόδου
6. reg [2:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,q,w,e,r,t,y,u,o,p,a,s,d,f,g,h,j;
10.integer data0,data1,data2,data3,data4,data5,data6,data7,data8,
11. data9,data10,data11,data12,data13,data14,data15;
12.reg signed [15:0] mem [0:N]; //[wide] R[rows][cols]
13.initial begin //αρχικοποίηση δεδομένων
14.mem[0]=1; mem[1]=-1; mem[2]=6; mem[3]=10; mem[4]=15; mem[5]=21; mem[6]=28; mem[7]=36;
15.mem[8]=45; mem[9]=55; mem[10]=66; mem[11]=78; mem[12]=91; mem[13]=105; mem[14]=120;
16.mem[15]=115; ......
17.end
Page 87
- 87 -
18.always @ (clk)
19. if (reset)
20. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
21. else
22. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
23.always @(state)
24. begin
25. case(state)
26. s1:begin
27. done=0; //αρχικοποίηση προσωρινών μεταβλητών
28. i=0;
29. //previous value
30. q=0; w=0; e=0; r=0; t=0; y=0;u=0; i=0;o=0;p=0; a=0; s=0; d=0; f=0;g=0;h=o;
31. //current value
32. data0 =0;data1 =0;data2=0;data3=0; data4=0; data5=0; data6=0; data7=0;
33. data8 =0;data9 =0;data10=0;data11=0; data12=0; data13=0; data14=0; data15=0;
34. nextstate = s2; //ορισμός επόμενης κατάστασης
35. end
36. s2:begin
37. data0=mem[i]; data1=mem[i+8]; data2=mem[i+16]; data3=mem[i+24]; data4=mem[i+32];
38. data5=mem[i+40]; data6=mem[i+48]; data7=mem[i+56]; data8=mem[i+64];
39. data9=mem[i+72]; data10=mem[i+80]; data11=mem[i+88]; data12=mem[i+96];
40. data13=mem[i+104]; data14=mem[i+112]; data15=mem[i+120];
41. //βρίσκουμε την νέα τιμή και την αποθηκεύουμε
42. mem[i] =mem[i] -q; mem[i+8]=mem[i+8] -w; mem[i+16] =mem[i+16] -e;
43. mem[i+24] =mem[i+24] -r; mem[i+32] =mem[i+32] -t; mem[i+40] =mem[i+40] -y;
44. mem[i+48] =mem[i+48] -u; mem[i+56] =mem[i+56] -o; mem[i+64] =mem[i+64] -p;
45. mem[i+72] =mem[i+72] -a; mem[i+80] =mem[i+80] -s; mem[i+88] =mem[i+88] -d;
46. mem[i+96] =mem[i+96] -f; mem[i+104]=mem[i+104]-g; mem[i+112]=mem[i+112]-h;
47. mem[i+120]=mem[i+120]-j;
48. nextstate = s3; //ορισμός επόμενης κατάστασης
49. end
Page 88
- 88 -
50. s3:begin
51. //αποθηκεύουμε την προηγούμενη τιμή του διανύσματος
52. q=data0; w=data1; e=data2; r=data3; t=data4; y=data5; u=data6; o=data7;
53. p=data8; a=data9; s=data10; d=data11; f=data12; g=data13; h=data14; j=data15;
54. i=i+1; //αυξάνουμε τον δεικτη κατα ένα
55. done=done+1;
56. if(i<=8)
57. nextstate = s2; //ορισμός επόμενης κατάστασης
58. else
59. nextstate = s4; //ορισμός επόμενης κατάστασης
60. end
61. s4:begin
62. done=1; //το flag γινεται “1” μετά το πέρας της διαδικασίας
63. end
64. endcase
65.end
66.endmodule
Κώδικας C για τον soft processor του 7ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include "xil_printf.h"
4. #include <xparameters.h>
5. #include <xiomodule.h>
6. #include <stdbool.h>
7. XIOModule gpo;
8. int main()
9. {
10. init_platform();
11. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);// Initialize the GPO module
12. XIOModule_Start(&gpo); //start the GPO module
13. //αρχικοποίηση δεδομένων
14. int signed mem[128]={1,-1,6,10,15,21,28,36,45,55,66,78,91,105,120,115,
Page 89
- 89 -
15. ......
16. 1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,115,};
17. int i; //αρχικοποίηση προσορινών μεταβλητών
18. int q=0,data0=0;
19. for(i=0;i<=127;i++) //διατρέχουμε το διάνυσμα
20. {
21. data0 =mem[i]; //αποθηκεύουμε την προηγούμενη τιμή
22. mem[i]=mem[i]-q; //αποθηκεύουμε την νεα τιμή
23. q=data0;
24. }
25. while (1){
26. // write the LED value to port 1 (you can have up to 4 ports)
27. //XIOModule_DiscreteWrite(&gpo, 1,leds);
28. for(i=0;i<128;i++)
29. {
30. //εμφάνιση αποτελέσματος στην έξοδο
31. XIOModule_DiscreteWrite(&gpo,1,mem[i]); }
32. for(i=0;i<3000; i++);
33. }
34. return 0;
35.}
Κώδικας C για την soft υλοποίηση του 7ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h> // for clock_t, clock()
3. #include <unistd.h>// for sleep()
4. #define BILLION 1000000000.0;
5. int main()
6. {
7. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
8. struct timespec start, end;
9. clock_gettime(CLOCK_REALTIME, &start);
10. //αρχικοποίηση δεδομένων
11. int signed mem[128]={1,-1,6,10,15,21,28,36,45,55,66,78,91,105,120,115,
Page 90
- 90 -
12. ......
13. 1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,115,};
14. int i; //αρχικοποίηση προσορινών μεταβλητών
15. int q=0,data0=0;
16.
17. for(i=0;i<=127;i++) //διατρέχουμε το διάνυσμα
18. {
19. data0 =mem[i]; //αποθηκεύουμε την προηγούμενη τιμή
20. mem[i]=mem[i]-q; //αποθηκεύουμε την νεα τιμή
21. q=data0;
22. }
23.
24. for(i=0;i<=127;i++)
25. {printf("%d\n",mem[i]);} //εμφανίζουμε το τελικό διανυσμα στην εξοδο
26.
27. printf("\n");
28. //υπολογιμός χρόνου εκτέλεσης προγράμματος
29. clock_gettime(CLOCK_REALTIME, &end);
30. double time_spent=(end.tv_sec-start.tv_sec)+(end.tv_nsec-start.tv_nsec)/BILLION;//time_spent = end - start
31. printf("\n");
32. //εμφάνιση χρόνου στην οθόνη σε ns
33. printf("Time elpased is \t%.9f seconds", time_spent);return 0;
34. }
Κώδικας verilog για την hardware υλοποίηση του 8ου προβλήμματος:
1. `timescale 1ns / 1ps
2. module bubble_sort(clk,reset,valid);
3. input clk;
4. input reset;
5. output reg valid; //καταχωρητής εξόδου
6. reg [3:0] state, nextstate;
7. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8,s9=9,s10=10;
8. parameter N=127; //ορίζει το μέγεθος των διανυσμάτων
9. integer i,j,swapped,t0,t1,t2,temp;
Page 91
- 91 -
10. reg [7:0] mem [0:N]; //[wide] R[rows][cols]
11. initial begin //αρχικοποίηση δεδομένων
12. mem[0]=23; mem[1]=3; mem[2]=8; mem[3]=14; mem[4]=15; mem[5]=21; mem[6]=28; mem[7]=36;
13. mem[8]=45; mem[9]=25; mem[10]=65; mem[11]=75; mem[12]=9; mem[13]=15; mem[14]=120;
14. mem[15]=118; mem[16]=3;.......
15. end
16. always @ (clk)
17. if (reset)
18. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
19. else
20. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
21. always @(state)
22. begin
23. case(state)
24. s1:begin
25. i=0; j=0; valid=0; //αρχικοποίηση προσωρινών μεταβλητών
26. nextstate = s2; //ορισμός επόμενης κατάστασης
27. end
28. s2:if(i<=N) //διατρέχουμε όλο το διάνυσμα
29. nextstate = s3; //ορισμός επόμενης κατάστασης
30. else
31. nextstate = s10; //ορισμός επόμενης κατάστασης
32. s3:if(j<=N-i) //καθε φορά το μεγαλύτερο στοιχείο στο τελος του διανύσματος
33. nextstate = s4; //ορισμός επόμενης κατάστασης
34. else
35. nextstate = s9; //ορισμός επόμενης κατάστασης
36. s4:begin
37. t0=mem[j]; t1=mem[j+1];
38. nextstate = s5; //ορισμός επόμενης κατάστασης
39. end
40. s5:begin
41. if(t0>t1) //σύγκριση στοιχείων
42. nextstate = s6; //ορισμός επόμενης κατάστασης
43. else
Page 92
- 92 -
44. nextstate = s8; //ορισμός επόμενης κατάστασης
45. end
46. s6:begin
47. temp = t0;
48. nextstate = s7; //ορισμός επόμενης κατάστασης
49. end
50. s7:begin
51. mem[j] = t1; mem[j+1] = temp; //μετάθεση στοιχείων όταν χρειάζεται
52. swapped = 1; //γίνεται “1” όταν έχουμε μετάθεση στοιχείων
53. nextstate=s8; //ορισμός επόμενης κατάστασης
54. end
55. s8:begin
56. j=j+1; //αύξηση δείκτη κατά ένα
57. nextstate = s3; //ορισμός επόμενης κατάστασης
58. end
59. s9:begin
60. i=i+1; //καθε φορά μειώνουμε τις θέσεις του διανυσματος που
61. j=0; //διατρέχουμε
62. nextstate = s2; //ορισμός επόμενης κατάστασης
63. end
64. s10:valid=1;
65. endcase
66. end
67. endmodule
Κώδικας C για τον soft processor του 8ου προβλήμματος:
1. #include <stdio.h>
2. #include "platform.h"
3. #include "xil_printf.h"
4. #include <xparameters.h>
5. #include <xiomodule.h>
6. #include <stdbool.h>
7. XIOModule gpo;
Page 93
- 93 -
8. int main()
9. {
10. init_platform();
11.
12. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);// Initialize the GPO module
13. XIOModule_Start(&gpo);// start the GPO module
14. //αρχικοποίηση δεδομένων
15. int mem[128]={23, 3, 8, 14, 15, 21, 28, 36, 45, 25, 65, 75, 9, 15, 120, 118,
16. .......
17. 3,3,36,13, 14, 1, 28, 6, 5, 55, 6, 8, 1, 13, 120, 31,};
18. int i,j,temp;
19. for(i=0;i<128;i++)
20. {
21. for(j=0;j<128-i;j++)
22. {
23. if(mem[j]>mem[j+1]) //σύγκριση
24. {temp =mem[j]; mem[j]=mem[j+1]; mem[j+1]=temp; //swap}
25. }
26. }
27.
28. while (1){
29. // write the LED value to port 1 (you can have up to 4 ports)
30. //XIOModule_DiscreteWrite(&gpo, 1,leds);
31. for(i=0;i<128;i++)
32. {
33. XIOModule_DiscreteWrite(&gpo,1,mem[i]); //εμφάνιση ταξινομημένου πίνακα
34. }
35. }
36. return 0;
37.}
Page 94
- 94 -
Κώδικας C για την software υλοποίηση του 8ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h> // for clock_t, clock()
3. #include <unistd.h>// for sleep()
4. #define BILLION 1000000000.0;
5. int main()
6. {
7. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
8. struct timespec start, end;
9. clock_gettime(CLOCK_REALTIME, &start);
10. //αρχικοποίηση δεδομένων
11. int mem[128]={23,3,8,14,15,21,28 ,36 ,45,25,65,75,9 ,15,120,118,
12. ........
13. 3,3 ,36,13,14,1 ,28 ,6 ,5,55,6 ,8 ,1 ,13,120,31, };
14. int i,j,temp;
15. for(i=0;i<128;i++)
16. {
17. for(j=0;j<128-i;j++)
18. {
19. if(mem[j]>mem[j+1]) //σύγκριση
20. { temp =mem[j]; mem[j] =mem[j+1]; mem[j+1]=temp; //swap }
21. }
22. }
23. for(i=0;i<128;i++)
24. {printf("%d\n",mem[i]);} //εμφάνιση ταξινομημένου διανύσματος
25. //υπολογιμός χρόνου εκτέλεσης προγράμματος
26. clock_gettime(CLOCK_REALTIME, &end);
27. double time_spent =(end.tv_sec - start.tv_sec)+(end.tv_nsec - start.tv_nsec)/BILLION;//time_spent=end-start
28. printf("\n");
35. //εμφάνιση χρόνου στην οθόνη σε ns
29. printf("Time elpased is \t%.9f seconds", time_spent);return 0;
30.}
Page 95
- 95 -
Κώδικας verilog για την hardware υλοποίηση του 9ου προβλήμματος
1. `timescale 1ns / 1ps
2. module hailstone(clk,reset,din,dout,done,counter);
3. input clk;
4. input reset;
5. input [15:0] din; //καταχωρητής εισόδου
6. output reg [15:0] dout; //καταχωρητής εξόδου
7. output reg done; //καταχωρητής εξόδου
8. output reg [15:0] counter; //καταχωρητής εξόδου
9. reg [3:0] state, nextstate;
10. parameter s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7,s8=8;
11. integer i;
12. reg [15:0] n;
13. always @ (clk)
14. if (reset)
15. state <= s1; //αν ενεργοποιηθεί το σήμα reset τότε πηγαίνει στην αρχικη κατάσταση
16. else
17. state <= nextstate; //αν όχι τότε το σύστημα πηγαίνει στην επόμενη κατάσταση
18. always @(state)
19. begin
20. case(state)
21. s1:begin
22. n=din; //αρχικοποίηση προσωρινών μεταβλητών
23. counter=1; nextstate = s2;
24. end
25. s2:if(n!=1)
26. nextstate = s3; //ορισμός επόμενης κατάστασης
27. else
28. nextstate = s5; //ορισμός επόμενης κατάστασης
29. s3:if(n%2==0)
30. begin
31. n=n>>1; nextstate = s4;//ορισμός επόμενης κατάστασης
32. end
33. else
Page 96
- 96 -
34. begin
35. n=(n<<1)+n+1; nextstate = s4;//ορισμός επόμενης κατάστασης
36. end
37. s4:begin
38. dout=n; counter=counter+1; nextstate = s2;//ορισμός επόμενης κατάστασης
39. end
40. s5:done=1;
41. endcase
42. end
43. endmodule
Κώδικας C για τον soft processor του 9ου προβλήμματος
1. #include <stdio.h>
2. #include "platform.h"
3. #include "xil_printf.h"
4. #include <xparameters.h>
5. #include <xiomodule.h>
6. #include <stdbool.h>
7. XIOModule gpo;
8. int main()
9. {
10. init_platform();
11. XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID); // Initialize the GPO module
12. XIOModule_Start(&gpo); // start the GPO module
13. int i,n=27,counter=1;
14. while (1){
15. while(n!=1)
16. {
17. counter=counter+1;
18. if(n%2==0)
19. {n=n/2;}
20. else
21. {n=3*n+1;}
22. //write the LED value to port 1 (you can have up to 4 ports)
Page 97
- 97 -
23. //XIOModule_DiscreteWrite(&gpo, 1,leds);
24. XIOModule_DiscreteWrite(&gpo,1,n); //εμφάνιση αποτελεσμάτων στην έξοδο
25. XIOModule_DiscreteWrite(&gpo,2,counter);//εμφάνιση αποτελεσμάτων στην έξοδο
26. }
27. for(i=0;i<3000; i++);
28. }
29. return 0;
30.}
Κώδικας C για την software υλοποίηση του 9ου προβλήμματος:
1. #include <stdio.h>
2. #include <time.h> // for clock_t, clock()
3. #include <unistd.h>// for sleep()
4. #define BILLION 1000000000.0;
5. int main()
6. {
7. //συναρτήσεις για να μετρήσουμε χρόνο εκτέλεσης προγράμμαατος
8. struct timespec start, end;
9. clock_gettime(CLOCK_REALTIME, &start);
10. int n=27,counter=1;
11. printf("%d\n",n);
12. while(n!=1)
13. {
14. counter=counter+1;
15. if(n%2==0)
16. {n=n/2;}
17. else
18. {n=3*n+1;}
19.
20. printf("%d\n",n);
21. }
22. printf("counter=> %d\n",counter); //εμφάνιση counter στην οθόνη
23. //υπολογιμός χρόνου εκτέλεσης προγράμματος
24. clock_gettime(CLOCK_REALTIME, &end);
Page 98
- 98 -
25. double time_spent=(end.tv_sec-start.tv_sec)+(end.tv_nsec-start.tv_nsec)/BILLION;//time_spent = end - start
26. printf("\n");
27. printf("Time elpased is \t%.9f seconds", time_spent);return 0;
28. //εμφάνιση χρόνου στην οθόνη σε ns
29.}