Σχεδίαση κυκλωμάτων με SystemVerilog: 2o μέρος

Σχετικά έγγραφα
Σχεδίαση κυκλωμάτων με VHDL: 2o μέρος

K24 Ψηφιακά Ηλεκτρονικά 9: Flip-Flops

ΗΜΥ 210 ΣΧΕΔΙΑΣΜΟΣ ΨΗΦΙΑΚΩΝ ΣΥΣΤΗΜΑΤΩΝ. Χειµερινό Εξάµηνο 2016 ΔΙΑΛΕΞΗ 15: Καταχωρητές (Registers)

ΗΜΥ 210: Σχεδιασμός Ψηφιακών Συστημάτων. Καταχωρητές 1

Ολοκληρωμένα Κυκλώματα

6 η Θεµατική Ενότητα : Σχεδίαση Συστηµάτων σε Επίπεδο Καταχωρητή

«Σχεδιασμός Ολοκληρωμένων Κυκλωμάτων» Χειμερινό εξάμηνο Μηχανές Πεπερασμένων Καταστάσεων

26-Nov-09. ΗΜΥ 210: Λογικός Σχεδιασμός, Χειμερινό Εξάμηνο Καταχωρητές 1. Διδάσκουσα: Μαρία Κ. Μιχαήλ

Περίληψη. ΗΜΥ-210: Λογικός Σχεδιασµός Εαρινό Εξάµηνο Παράδειγµα: Καταχωρητής 2-bit. Καταχωρητής 4-bit. Μνήµη Καταχωρητών

«Σχεδιασμός Ψηφιακών Συστημάτων σε FPGA» Εαρινό εξάμηνο Διάλεξη 8 η : Μηχανές Πεπερασμένων Κaταστάσεων σε FPGAs

Πανεπιστήμιο Πατρών Τμήμα Φυσικής Εργαστήριο Ηλεκτρονικής. Ψηφιακά Ηλεκτρονικά. Καταχωρητές και Μετρητές 2. Επιμέλεια Διαφανειών: Δ.

Επιβεβαίωση ορθής λειτουργίας απλών ψηφιακών κυκλωμάτων

Εισαγωγή στην πληροφορική

«Σχεδιασμός Ολοκληρωμένων Κυκλωμάτων» Χειμερινό εξάμηνο Ακολουθιακός Κώδικας

Ελίνα Μακρή

ΤΙΤΛΟΣ ΕΡΓΑΣΤΗΡΙΑΚΗΣ ΑΣΚΗΣΗΣ ΑΣΥΓΧΡΟΝΟΙ ΜΕΤΡΗΤΕΣ

ΨΗΦΙΑΚΑ ΣΥΣΤΗΜΑΤΑ ΚΑΡΑΓΚΙΑΟΥΡΗΣ ΝΙΚΟΛΑΟΣ

ΗΥ220: Εργαστήριο ψηφιακών κυκλωμάτων

Ηλεκτρολόγοι Μηχανικοί ΕΜΠ Λογική Σχεδίαση Ψηφιακών Συστημάτων Διαγώνισμα κανονικής εξέτασης Θέμα 1ο (3 μονάδες)

Δημοκρίτειο Πανεπιστήμιο Θράκης Τμήμα Ηλεκτρολόγων Μηχανικών & Μηχανικών Υπολογιστών. Συστήματα VLSI. Πρόοδος Άνοιξη 2018

ΑΣΚΗΣΗ 9. Tα Flip-Flop

Ασύγχρονοι Απαριθμητές. Διάλεξη 7

Άσκηση 3 Ένα νέο είδος flip flop έχει τον ακόλουθο πίνακα αληθείας : I 1 I 0 Q (t+1) Q (t) 1 0 ~Q (t) Κατασκευάστε τον πίνακα

ΤΙΤΛΟΣ ΕΡΓΑΣΤΗΡΙΑΚΗΣ ΑΣΚΗΣΗΣ ΚΑΤΑΧΩΡΗΤΕΣ ΟΛΙΣΘΗΤΕΣ

Πανεπιστήμιο Πατρών. Τμήμα Ηλεκτρολόγων Μηχανικών και Τεχνολογίας Υπολογιστών

Εργαστήριο Ψηφιακών Κυκλωμάτων

Κεφάλαιο 6. Σύγχρονα και ασύγχρονα ακολουθιακά κυκλώματα

ΤΙΤΛΟΣ ΕΡΓΑΣΤΗΡΙΑΚΗΣ ΑΣΚΗΣΗΣ ΣΥΓΧΡΟΝΟΙ ΜΕΤΡΗΤΕΣ

ΗΥ220 Εργαστήριο Ψηφιακών Κυκλωμάτων

Πανεπιστήμιο Πατρών Τμήμα Φυσικής Εργαστήριο Ηλεκτρονικής. Ψηφιακά Ηλεκτρονικά. Ακολουθιακή Λογική. Επιμέλεια Διαφανειών: Δ.

Κεφάλαιο 3 ο Ακολουθιακά Κυκλώματα με ολοκληρωμένα ΤΤL

7.1 Θεωρητική εισαγωγή

Ψηφιακή Λογική Σχεδίαση

Υπάρχουν δύο τύποι μνήμης, η μνήμη τυχαίας προσπέλασης (Random Access Memory RAM) και η μνήμη ανάγνωσης-μόνο (Read-Only Memory ROM).

8.1 Θεωρητική εισαγωγή

ΤΙΤΛΟΣ ΕΡΓΑΣΤΗΡΙΑΚΗΣ ΑΣΚΗΣΗΣ ΟΙ ΚΑΤΑΧΩΡΗΤΕΣ ΚΑΙ Η ΥΛΟΠΟΙΗΣΗ ΤΟΥΣ ΜΕ FLIP-FLOP ΚΑΙ ΠΥΛΕΣ

ΗΜΥ 210: Σχεδιασμό Ψηφιακών Συστημάτων, Χειμερινό Εξάμηνο 2008

Σχεδιασμός Ψηφιακών Συστημάτων

100 ΕΡΩΤΗΣΕΙΣ ΜΕ ΤΙΣ ΑΝΤΙΣΤΟΙΧΕΣ ΑΠΑΝΤΗΣΕΙΣ ΓΙΑ ΤΟ ΜΑΘΗΜΑ ΨΗΦΙΑΚΑ ΚΥΚΛΩΜΑΤΑ

Κ. ΕΥΣΤΑΘΙΟΥ, Γ. ΠΑΠΑΔΟΠΟΥΛΟΣ ΠΑΤΡΑ

Σχεδίαση κυκλωμάτων σε SystemVerilog: 1o μέρος

ΠΕΡΙΕΧΟΜΕΝΑ ΠΕΡΙΕΧΟΜΕΝΑ.3 ΑΣΥΓΧΡΟΝΟΣ ΔYΑΔΙΚΟΣ ΑΠΑΡΙΘΜΗΤΗΣ.5 ΑΣΥΓΧΡΟΝΟΣ ΔΕΚΑΔΙΚΟΣ ΑΠΑΡΙΘΜΗΤΗΣ.7 ΑΣΥΓΧΡΟΝΟΣ ΔΕΚΑΔΙΚΟΣ ΑΠΑΡΙΘΜΗΤΗΣ ΜΕ LATCH.

ΤΙΤΛΟΣ ΕΡΓΑΣΤΗΡΙΑΚΗΣ ΑΣΚΗΣΗΣ ΣΕΙΡΙΑΚΗ ΠΡΟΣΘΕΣΗ

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ Ανώτατο Εκπαιδευτικό Ίδρυμα Πειραιά Τεχνολογικού Τομέα. Σχεδίαση Ψηφιακών Συστημάτων. Ενότητα: ΚΑΤΑΧΩΡΗΤΕΣ - ΑΠΑΡΙΘΜΗΤΕΣ

Θέμα 1ο (3 μονάδες) Υλοποιήστε το ακoλουθιακό κύκλωμα που περιγράφεται από το κατωτέρω διάγραμμα

Οργάνωση της φυσικής δομής του ολοκληρωμένου κυκλώματος

ΑΣΚΗΣΗ 10 ΣΧΕΔΙΑΣΗ ΑΚΟΛΟΥΘΙΑΚΩΝ ΚΥΚΛΩΜΑΤΩΝ

7 η Θεµατική Ενότητα : Καταχωρητές, Μετρητές και Μονάδες Μνήµης

Εργαστήριο Οργάνωσης Η/Υ. Δαδαλιάρης Αντώνιος

Ηλεκτρολόγοι Μηχανικοί ΕΜΠ Λογική Σχεδίαση Ψηφιακών Συστημάτων Διαγώνισμα κανονικής εξέτασης 2017

ΤΕΧΝΟΛΟΓΙΚΟ ΕΚΠΑΙ ΕΥΤΙΚΟ Ι ΡΥΜΑ (Τ.Ε.Ι.) ΚΡΗΤΗΣ Τµήµα Εφαρµοσµένης Πληροφορικής & Πολυµέσων. Ψηφιακή Σχεδίαση. Κεφάλαιο 5: Σύγχρονη Ακολουθιακή

Κυκλώματα αποθήκευσης με ρολόι

Ψηφιακά Συστήματα. 8. Καταχωρητές

ΗΥ220: Εργαστήριο σχεδίασης ψηφιακών κυκλωμάτων Χριστόφορος Κάχρης

Κεφάλαιο 7 ο. Γ. Τσιατούχας. VLSI Technology and Computer Architecture Lab. Ακολουθιακή Λογική 2

Ολοκληρωμένα Κυκλώματα - Φθινόπωρο 2014 Γ. Δημητρακόπουλος. Εργαστηριακή άσκηση 2

Σχεδίαση Ψηφιακών Συστημάτων

Μνήμη και Προγραμματίσιμη Λογική

Σωστή απάντηση το: Γ. Απάντηση

Περίληψη. ΗΜΥ-210: Λογικός Σχεδιασµός Εαρινό Εξάµηνο Μετρητής Ριπής (Ripple Counter) Μετρητές (Counters) Μετρητής Ριπής (συν.

Πανεπιστήμιο Δυτικής Μακεδονίας. Τμήμα Μηχανικών Πληροφορικής & Τηλεπικοινωνιών. Ψηφιακή Σχεδίαση

Παραδείγματα σχεδίασης με μηχανές πεπερασμένων καταστάσεων

Σχεδίαση CMOS Ψηφιακών Ολοκληρωμένων Κυκλωμάτων

Ενότητα ΑΡΧΕΣ ΑΚΟΛΟΥΘΙΑΚΗΣ ΛΟΓΙΚΗΣ LATCHES & FLIP-FLOPS

Δείγμα Τελικής Εξέτασης στο ΗΜΥ213. Διδάσκοντας: Γιώργος Ζάγγουλος

Μετρητής Ριπής ΛΟΓΙΚΗ ΣΧΕΔΙΑΣΗ. Αναφορά 9 ης. εργαστηριακής άσκησης: ΑΦΡΟΔΙΤΗ ΤΟΥΦΑ Α.Μ.:

Ακολουθιακά Κυκλώµατα. ΗΜΥ 210: Λογικός Σχεδιασµός, Εαρινό Εξάµηνο Ακολουθιακά Κυκλώµατα (συν.) Ακολουθιακή Λογική: Έννοια

Ψηφιακή Λογική Σχεδίαση

ΚΕΦΑΛΑΙΟ 6 ΒΑΣΙΚΑ ΑΚΟΛΟΥΘΙΑΚΑ ΚΥΚΛΩΜΑΤΑ. 6.1 Εισαγωγή

ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ

ΠΡΟΓΡΑΜΜΑ ΣΠΟΥ ΩΝ ΠΛΗΡΟΦΟΡΙΚΗΣ

ΗΥ220 Εργαστήριο Ψηφιακών Κυκλωµάτων

6.1 Καταχωρητές. Ένας καταχωρητής είναι μια ομάδα από f/f αλλά μπορεί να περιέχει και πύλες. Καταχωρητής των n ψηφίων αποτελείται από n f/f.

Σχεδίαση της Μονάδας Ελέγχου

Α. ΣΚΟΔΡΑΣ ΠΛΗ21 ΟΣΣ#2. 14 Δεκ 2008 ΠΑΤΡΑ ΕΛΛΗΝΙΚΟ ΑΝΟΙΚΤΟ ΠΑΝΕΠΙΣΤΗΜΙΟ 2008 Α. ΣΚΟΔΡΑΣ ΧΡΟΝΟΔΙΑΓΡΑΜΜΑ ΜΕΛΕΤΗΣ

ΥΠΟΥΡΓΕΙΟ ΠΑΙΔΕΙΑΣ ΚΑΙ ΠΟΛΙΤΙΣΜΟΥ ΔΙΕΥΘΥΝΣΗ ΑΝΩΤΕΡΗΣ ΚΑΙ ΑΝΩΤΑΤΗΣ ΕΚΠΑΙΔΕΥΣΗΣ ΥΠΗΡΕΣΙΑ ΕΞΕΤΑΣΕΩΝ ΠΑΓΚΥΠΡΙΕΣ ΕΞΕΤΑΣΕΙΣ 2009 ΑΠΑΝΤΗΣΕΙΣ

Xρονισμός ψηφιακών κυκλωμάτων

Ψηφιακή Σχεδίαση Ενότητα 10:

ΑΣΚΗΣΗ 8 ΚΑΤΑΧΩΡΗΤΕΣ - REGISTERS

Γενική οργάνωση υπολογιστή «ΑΒΑΚΑ»

ΕΙΔΙΚΟΤΗΤΑ: ΤΕΧΝΙΚΟΣ ΕΦΑΡΜΟΓΩΝ ΠΛΗΡΟΦΟΡΙΚΗΣ ΜΑΘΗΜΑ: ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΠΛΗΡΟΦΟΡΙΚΗ

ΘΕΜΑΤΑ & ΕΝΔΕΙΚΤΙΚΕΣ ΛΥΣΕΙΣ

Παράδειγμα αντιστοίχισης κυκλώματος σε FPGA

ΗΜΥ 210: Σχεδιασμός Ψηφιακών Συστημάτων. Μετρητές 1

ΗΥ220 Εργαστήριο Ψηφιακών Κυκλωμάτων

7 η διάλεξη Ακολουθιακά Κυκλώματα

Σχεδιασμός Ψηφιακών Συστημάτων

K15 Ψηφιακή Λογική Σχεδίαση 7-8: Ανάλυση και σύνθεση συνδυαστικών λογικών κυκλωμάτων

ΗΜΥ 210: Σχεδιασμός Ψηφιακών Συστημάτων. Ακολουθιακά Κυκλώματα: Μανδαλωτές και Flip-Flops 1

ε. Ένα κύκλωμα το οποίο παράγει τετραγωνικούς παλμούς και απαιτείται εξωτερική διέγερση ονομάζεται ασταθής πολυδονητής Λ

Η κανονική μορφή της συνάρτησης που υλοποιείται με τον προηγούμενο πίνακα αληθείας σε μορφή ελαχιστόρων είναι η Q = [A].

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Κεφάλαιο 10 ο. Γ. Τσιατούχας. VLSI Systems and Computer Architecture Lab. Ακολουθιακή Λογική 2

ΗΜΥ211 Εργαστήριο Ψηφιακών Συστημάτων

ΑΣΚΗΣΗ 10 ΣΥΓΧΡΟΝΟΙ ΑΠΑΡΙΘΜΗΤΕΣ

ΥΠΟΥΡΓΕΙΟ ΠΑΙΔΕΙΑΣ ΚΑΙ ΠΟΛΙΤΙΣΜΟΥ ΔΙΕΥΘΥΝΣΗ ΑΝΩΤΕΡΗΣ ΚΑΙ ΑΝΩΤΑΤΗΣ ΕΚΠΑΙΔΕΥΣΗΣ ΥΠΗΡΕΣΙΑ ΕΞΕΤΑΣΕΩΝ ΠΑΓΚΥΠΡΙΕΣ ΕΞΕΤΑΣΕΙΣ 2006 ΑΠΑΝΤΗΣΕΙΣ

ΑΣΚΗΣΗ 7 FLIP - FLOP

Πανεπιστήμιο Πατρών Τμήμα Φυσικής Εργαστήριο Ηλεκτρονικής. Ψηφιακά Ηλεκτρονικά. Μονάδες Μνήμης και Διατάξεις Προγραμματιζόμενης Λογικής

Σχεδίαση κυκλωμάτων ακολουθιακής λογικής

Περιγραφή Κυκλωμάτων με χρήση της VHDL. Καταχωρητές και χρονισμός με ρολόι

Transcript:

Σχεδίαση κυκλωμάτων με SystemVerilog: 2o μέρος Γιώργος Δημητρακόπουλος Περιγραφή κυκλωμάτων με προγραμματιστικές δομές υψηλού επιπέδου Κύριος στόχος των γλωσσών περιγραφής υλικού είναι να απαλλάξουν το σχεδιαστή από τις μικρές λεπτομέρειες της ψηφιακής σχεδίασης αφήνοντας τον ελεύθερο να σκεφτεί τη λειτουργία και τη δομή του κυκλώματος τους σε υψηλότερο επίπεδο χρησιμοποιώντας προγραμματιστικές δομές όμοιες με αυτές των γλωσσών προγραμματισμού, όπως συνθήκες if then, επιλογές με case καθώς και επαναληπτικές δομές τύπου for loop. Με αυτό τον τρόπο ο σχεδιαστής μπορεί να ανταπεξέλθει ευκολότερα στη σχεδίαση πολύ σύνθετων κυκλωμάτων, να επιτύχει υψηλότερες επιδόσεις, αλλά και να ολοκληρώσει τη σχεδίαση με τα λιγότερα δυνατά λάθη. Σε κάθε περίπτωση την ευθύνη της μετατροπή της περιγραφής της λειτουργίας του κυκλώματος σε ένα ισοδύναμο κύκλωμα που θα αποτελείται από πύλες και flip-flops, την αναλαμβάνει το εργαλείο της λογικής σύνθεσης. Στη SystemVerilog οι προγραμματιστικές δομές που μας επιτρέπουν να περιγράψουμε τη λειτουργία του κυκλώματος σε ένα υψηλότερο επίπεδο αφαίρεσης μπορούν να χρησιμοποιηθούν μόνο μέσα σε always μπλοκς. Κάθε δομή always αναπαριστά ένα μικρό κύκλωμα το οποίο εκτελεί μια συγκεκριμένη λειτουργία ανταποκρινόμενο στις αλλαγές των εισόδων του. Όλα τα always μπλοκς του κυκλώματος που περιγράφουμε λειτουργούν ταυτόχρονα όπως ακριβώς θα έκαναν και οι διάφορες μονάδες υλικού σε ένα πραγματικό κύκλωμα. Τα always μπλοκς που χρησιμοποιούμε για την περιγραφή των κυκλωμάτων χωρίζονται σε δύο κατηγορίες. Στα μπλοκς συνδυαστικής λογικής και στα μπλοκς ακολουθιακής λογικής τα οποία είναι μικτά από τη φύση τους καθώς μας επιτρέπουν να περιγράφουμε ακολουθιακή λογική (flip-flops) μαζί με τη συνδιαστική λογική που τα οδηγεί. Μία περιγραφή συνδυαστικής λογικής θα έμοιαζε ως εξής: x = a & b; if (a == 1'b1) y = 1 b0; y = 1 b1; ; Σε αυτό το μπλοκ πραγματοποιούνται αναθέσεις στα σήματα x και y. Επομένως, αν και στα always μπλοκς δεν απαιτείται να δηλώσουμε ποια σήματα λειτουργούν ως είσοδοι και ποια ως έξοδοι, παρόλα αυτά, για τη διεργασία αυτή τα σήματα x και y έμμεσα παίζουν το ρόλο των εξόδων εφόσον είναι τα μόνα στα οποία ανατίθεται μια ένα τιμή. Αντίστοιχα, τα σήματα που καθορίζουν τις τιμές των αναθέσεων στα x και y παίζουν έμμεσα το ρόλο των εισόδων και δεν είναι άλλα από τα σήματα a και b. H ανάθεση στο σήμα x συνδυάζει μέσω του λογικού ΚΑΙ τα σήματα a και b, ενώ η ανάθεση στο y πραγματοποιείται μέσω της προγραμματιστικής δομής if. Επομένως, κοιτώντας και τις δύο αναθέσεις, καταλαβαίνουμε πως η λειτουργία του μπλοκ αυτού καθορίζεται από τις τιμές των σημάτων a και b. Ας υποθέσουμε πως τη χρονική στιγμή t 0 = 10ns τα σήματα a και b είχαν τις τιμές '1' και '0' αντίστοιχα. Τότε σύμφωνα με τις αναθέσεις του μπλοκ την ίδια χρονική στιγμή τα σήματα x και y θα είχαν πάρει τις τιμές '0' και '0' αντίστοιχα. Οι τιμές των x και y διατηρούνται σταθερές μέχρις ότου να αλλάξει κάποιο από τα a και b. Επομένως μετά την ανάθεση των τιμών στα x και y το μπλοκ δεν εκτελεί καμιά νέα δουλειά και μπορεί να απενεργοποιηθεί. Αν όμως σε μια μεταγενέστερη χρονική στιγμή έστω τη στιγμή t 1 = 12nsec το a γίνει ίσο με 0 τότε το μπλοκ οφείλει να ενεργοποιηθεί υπολογίζοντας τις νέες τιμές για τα x και y. Όταν ένα σήμα που λειτουργεί έμμεσα ως είσοδος αλλάξει τιμή τότε το μπλοκ ενεργοποιείται υπολογίζοντας νέες τιμές για τις αναθέσεις που περιγράφονται μέσα στο σώμα του. Εφόσον τα σήματα x και y αντιδρούν απευθείας στις αλλαγές των σημάτων a και b που συμμετέχουν στη λίστα ενεργοποίησης, αυτό σημαίνει πως η περιγραφή αντιστοιχεί σε ένα κύκλωμα συνδυαστικής λογικής όπου οι έξοδοι του κυκλώματος υπολογίζονται μόνο με βάση τις τρέχουσες εισόδους και όχι παλαιότερες τιμές. 1

Για να καταλάβουμε όμως τον τρόπο με τον οποίο οι περιγραφές μας «εκτελούνται» αναθέτοντας νέες τιμές στα σήματα που συμμετέχουν στο σώμα των διεργασιών πρέπει να τις αντιμετωπίσουμε σαν κομμάτια ενός προγράμματος λογισμικού. Αντίθετα με τις απευθείας αναθέσεις που πραγματοποιούνται ταυτόχρονα, οι αναθέσεις μέσα στα μπλοκ always λαμβάνουν χώρα σειριακά η μια μετά την άλλη. Η «εκτέλεση» του κάθε μπλοκ μοιάζει με ένα ατέρμονο βρόγχο όπου μετά το τέλος των αναθέσεων μιας επανάληψης μπλοκ ξαναξεκινά μόνο όταν αλλάξει κάποιο από τα σήματα που λειτουργούν έμμεσα ως είσοδοι του μπλοκ. Στο τελευταίο παράδειγμα παρατηρούμε πως οι αναθέσεις στο σήμα y είναι ανεξάρτητες από τις τιμές του b. Επομένως θα μπορούσαμε να χωρίσουμε το μπλοκ αυτό σε δύο παράλληλα μπλοκς το κάθε ένα θα αναλάμβανε και την ανάθεση σε ένα σήμα. module dummylogic ( input logic a, input logic b, output logic x, output logic y); -- the assignment of y deps only on a if (a==1'b1) y = 1'b0; y = 1 b1; - the assignment of x deps on both a and b x = a & b; module Φυσικά θα μπορούσαμε να είχαμε πετύχει την ίδια λειτουργία χρησιμοποιώντας δύο απευθείας αναθέσεις στα σήματα x και y χωρίς να χρησιμοποιήσουμε τις δύο διεργασίες: assign y = (a)? 1 b0 : 1 b1; assign x = a & b; Γι' αυτό το απλό παράδειγμα όντως κάτι τέτοιο θα ήταν η ενδεικνυόμενη λύση. Όμως για την περίπτωση πιο σύνθετων κυκλωμάτων η χρήση προγραμματιστικών δομών όπως αυτή του if-then- κάνει πιο εύκολη την περιγραφή της λειτουργίας του κυκλώματος και καθιστά τον κώδικα της SystemVerilog ευανάγνωστο και περισσότερο κατανοητό. Πρέπει να προσέξετε πως υπο-συνθήκη αναθέσεις signal = (<condition>)? <val_when_condition_true> : <val2_when_condition_false> δεν επιτρέπονται μέσα σε μπλοκ always παρά μόνο έξω από αυτά ως απευθείας αναθέσεις. Από το προηγούμενο παράδειγμα μπορούμε να παρατηρήσουμε πως η δομή if-then- αντιστοιχεί απευθείας στη λειτουργία ενός πολυπλέκτη του οποίου η είσοδος ελέγχου συνδέεται στο ισοδύναμο κύκλωμα της συνθήκης του if ενώ οι είσοδοι δεδομένων του πολυπλέκτη συνδέονται στην έξοδο της λογικής που περιγράφουν η αναθέσεις μέσα στο σώμα του if. if (a==b) x = y + 1; x = b; Σε πολλές περιπτώσεις οι συνθήκες if βρίσκονται εμφωλευμένες η μια μέσα στην άλλη περιγράφοντας έμμεσα προτεραιότητες στην ικανοποίηση των συνθηκών για κάθε ανάθεση. Οι συνθήκες που βρίσκονται στις εξωτερικές δομές if εμφανίζουν μεγαλύτερη προτεραιότητα καθώς ελέγχουν τους πολυπλέκτες που βρίσκονται πιο κοντά στην έξοδο του κυκλώματος. Η αντιστοιχία αυτή φαίνεται στο παράδειγμα που ακολουθεί. 2

if (a) if (!b) x = y; x = 0; x = b; Ο πιο δεξιά πολυπλέκτης (πιο κοντά στην έξοδο) δίνει στο x την τιμή του b όταν η συνθήκη a= 1 δεν ικανοποιείτε. Αντίθετα, όταν a= 1 τότε το x ανατίθεται υπο-συνθήκη ανάλογα με την τιμή του b. Επομένως, σε αυτή την περίπτωση η ανάθεση του x προκύπτει από την έξοδο ενός δεύτερου πολυπλέκτη ο οποίος ελέγχεται από το b και δίνει στην έξοδο του είτε το y είτε το 0. Η έξοδος του δεύτερου πολυπλέκτη δεν περιγράφεται άμεσα σε αυτή τη διεργασία, προκύπτει όμως έμμεσα εξαιτίας του εμφωλευμένου if που αναθέτει και αυτό μια νέα τιμή στο x. Στην περίπτωση που μέσα σε ένα μπλοκ always με συνθήκες if ανατίθενται περισσότερα από ένα σήματα, αυτό σημαίνει πως κατά τη λογική σύνθεση γεννιούνται και περισσότεροι πολυπλέκτες όπως στο παράδειγμα που ακολουθεί. assign xt <= (a)? 1 b1 : y; if (a) x = xt; y = 1 b0; y = b; x = b; Σto παράδειγμα αυτό πρέπει να προσέξετε πως το σήμα xt υπολογίζεται από μια απ ευθείας υπο-συνθήκη ανάθεση έξω από το μπλοκ και χρησιμοποιείτε (διαβάζετε) από μια ανάθεση μέσα στο μπλoκ. Μια τέτοια περιγραφή είναι πολύ συνήθης καθώς τόσο τα μπλοκ always (μαζί με όλες τις αναθέσεις τους) όσο και οι απευθείας αναθέσεις αντιστοιχούν σε μπλοκς υλικού τα οποία συνυπάρχουν και λειτουργούν παράλληλα και συνδέονται μεταξύ τους μέσω σημάτων. Κάθε φορά που περιγράφουμε ένα κύκλωμα συνδυαστικής λογικής χρησιμοποιώντας μπλοκς πρέπει να σεβόμαστε ένα απλό κανόνα. Η ανάθεση κάθε σήματος μέσα σε ένα μπλοκ που αναπαριστά την έξοδο ενός κυκλώματος συνδυαστικής λογικής πρέπει να καλύπτει όλους τους δυνατούς συνδυασμούς των έμμεσων εισόδων της. Στη λανθασμένη περίπτωση του παραδείγματος που ακολουθεί στο y ανατίθεται μια τιμή όταν το a είναι ίσο με 1 και όχι στην περίπτωση που το a=0. Αυτό έχει ως αποτέλεσμα στην περίπτωση που a=0 να θυμόμαστε την παλιά τιμή του y. H συμπεριφορά αυτή ταιριάζει με αυτή του latch o οποίος ενεργοποιείτε όταν a=1. Για να αποφύγουμε τη γέννηση ενός latch πρέπει να ακολουθήσουμε το παράδειγμα της σωστής εκδοχής: ΛΑΘΟΣ ΣΩΣΤΟ if (a) if (a) y = b; y = b; y = 0; Τέλος σε πολλές περιπτώσεις συνδυαστικής λογικής απαιτείται να περιγράψουμε επαναληπτικούς αλγορίθμους οι οποίοι εξετάζουν διαδοχικά τα μπιτς της εισόδου του κυκλώματος. Χαρακτηριστικό παράδειγμα είναι τα κυκλώματα διαιτησίας σταθερής προτεραιότητας (αλλιώς τα ονομάζουμε κωδικοποιητές προτεραιότητας). Στην περίπτωση αυτή η είσοδος του κυκλώματος αναπαριστά αιτήσεις (request) και η έξοδος τις εγκρίσεις (grant). Για κάθε νέο διάνυσμα αιτήσεων, εγκρίνεται η ενεργή αίτηση η οποία βρίσκεται στην πιο δεξιά θέση του διανύσματος. 3

Η περιγραφή του κυκλώματος αυτού σε SystemVerilog μπορεί να γίνει απλά εκμεταλλευόμενοι τις δομές επανάληψης for μέσα σε μπλοκς always (αν και χρησιμοποιούνται για παρόμοιους λόγους αυτά τα for loops δεν πρέπει να συγχέονται με τα for generate loops που είδαμε νωρίτερα). module arbiter #(parameter N = 8) ( input logic [N-1:0] req, output logic [N-1:0] grant); logic found; found = 0; grant = 0; for (i=0; i < N; i=i+1) if (req[i] &&!found) grant[i] = 1; found = 1; module Ακολουθιακή λογική Αυτό που ξεχωρίζει ένα ακολουθιακό από ένα αμιγώς συνδυαστικό κύκλωμα είναι ότι μπορεί και θυμάται παλαιότερες τιμές των σημάτων του με βάση τις οποίες καθορίζει την έξοδο του σε κάθε χρονική στιγμή. Τα ακολουθιακά κυκλώματα τα οποία σχεδιάζουμε χρησιμοποιούν ακμοπυροδοτητά flip-flops για την αποθήκευση ενδιάμεσων χρονικά τιμών του κυκλώματος. Σε ένα τέτοιο κύκλωμα κάθε αλλαγή των εξόδων του πραγματοποιείται μόνο κατά τις θετικές (ή αρνητικές) ακμές του ρολογιού. Σε όλη την διάρκεια του κύκλου ρολογιού τα σήματα διαδίδονται κατάλληλα μέσα στη συνδυαστική λογική και με το τέλος του υπολογισμού περιμένουν στις εισόδους των flip-flop. Με την άφιξη της ακμής του ρολογιού τα σήματα αυτά περνούν από την είσοδο του flip-flop στην έξοδο του όπου και αποθηκεύονται μέχρι την επόμενη ακμή του ρολογιού πυροδοτώντας εκ νέου ένα κύκλο υπολογισμού στα κυκλώματα της συνδυαστικής λογικής. Για να μπορέσουμε να περιγράψουμε τη λειτουργία των flip-flops και κατ' επέκταση οποιοδήποτε άλλου ακολουθιακού κυκλώματος θα πρέπει να περιγράψουμε με σαφήνεια πως όλες οι αλλαγές στις εξόδους των flip-flops πραγματοποιούνται μόνο κατά τις ακμές του ρολογιού. H SystemVerilog μας επιτρέπει να εκφράσουμε αυτή τη συνθήκη συγχρονισμού μέσω ενός γεγονότος που ελέγχει την ύπαρξη μιας θετικής ακμή του ρολογιού. @(posedge clk) x <= a; Στο παράδειγμα αυτό η ανάθεση x <= a πραγματοποιείται με τη θετική ακμή του ρολογιού, περιγράφοντας τη λειτουργία ενός flip-flop με έξοδο το x και είσοδο το a. Η πλήρης περιγραφή ενός flip-flop σε VHDL φαίνεται παρακάτω: module dff ( input logic d, input logic clk, output logic q); q <= d; module Από την περιγραφή του flip-flop πρέπει να προσέξουμε τρία νέα στοιχεία: Το μπλοκ always που χρησιμοποιείται είναι τύπου always_ff και ελέγχεται αποκλειστικά και μόνο από τη θετική ακμή του ρολογιού clk και όχι από την είσοδο d η οποία βρίσκεται στο δεξί μέρος της ανάθεσης του q. Αυτό συμβαίνει γιατί στα flip-flops η είσοδος d δεν καθορίζει τη χρονική στιγμή που θα πυροδοτηθεί το flip-flop και επομένως δεν επηρεάζει 4

την ενεργοποίηση ή μη της μπλοκ. Στο flip-flop η είσοδος d φέρει απλά την τιμή που θα περάσει στην έξοδο με την άφιξη της ακμής του ρολογιού. Οι αναθέσεις των σημάτων μέσα στο μπλοκ always_ff είναι τύπου <= και όχι τύπου = οι οποίες χρησιμοποιούνται μόνο για την περιγραφή συνδυαστικής λογικής. Στις περιγραφές της συνδυαστικής λογικής με διεργασίες απαιτούσαμε οι αναθέσεις σε κάποιο σήμα να καλύπτουν όλες τις πιθανές εκδοχές της εισόδου, δηλαδή όταν υπάρχει ανάθεση στη μονοπάτι if-then να ακολουθεί και μια ανάθεση στο κομμάτι της συνθήκης. Η απαίτηση αυτή παρατηρούμε πως δεν τηρείται στην περιγραφή του flip-flop. Έτσι όταν δεν υπάρχει θετική ακμή του ρολογιού τότε η έξοδος q θυμάται την παλιά της τιμή που είναι και το ζητούμενο. Επειδή όμως τώρα η ανανέωση της τιμής του q γίνεται μόνο στις θετικές ακμές δε υπονοείται έμμεσα ένας μανδαλωτής όπως στην περίπτωση μιας ελλιπούς περιγραφής συνδυαστικής λογικής αλλά ένα flip-flop. Ας εμβαθύνουμε περισσότερο στην περιγραφή ακολουθιακής λογικής προσπαθώντας να περιγράψουμε ένα καταχωρητή των 4 δυαδικών ψηφίων με επίτρεψη φόρτωσης. Το κύκλωμα αυτό αποτελείται από 4 flip-flops στην είσοδο των οποίων τοποθετείται ένας πολυπλέκτης (των 4 δυαδικών ψηφίων). Ο πολυπλέκτης καθορίζει αν κάθε flip-flop θα φορτωθεί με μια νέα τιμή όταν το σήμα επίτρεψης είναι ενεργό ή αν θα φορτωθεί, μέσω της γραμμής ανάδρασης, με την παλιά τιμή που έχει ήδη αποθηκευμένη. Επομένως το κύκλωμα του καταχωρητή με επίτρεψη φόρτωσης αποτελείται από ένα αμιγώς ακολουθιακό μέρος (τα flip-flops) και ένα αμιγώς συνδυαστικό μέρος (τους πολυπλέκτες). Για την περιγραφή του κυκλώματος αυτού έχουμε 2 επιλογές. Είτε να διαχωρίσουμε πλήρως την συνδυαστική από την ακολουθιακή λογική όπως φαίνεται στην αριστερή περιγραφή είτε να τις περιγράψουμε ενοποιημένες όπως φαίνεται στη δεξιά περιγραφή. module register_with_enable ( input logic clk, input logic load, input logic [3:0] din, output logic [3:0] dout); logic [3:0] dcur; logic [3:0] dnew; assign dout = dcur; // mux with direct signal assignment assign dnew <= (load)? din: dcur; // flip-flop description: Flip-flop input // is the output of the mux dcur <= dnew; module module register_with_enable ( input logic clk, input logic load, input logic [3:0] din, output logic [3:0] dout); logic [3:0] dcur; assign dout = dcur; // mixed description // combinational logic embedded inside // the always_ff block if (load) dcur <= din; module Στην πρώτη περίπτωση περιγράψαμε τη λειτουργία του πολυπλέκτη στην είσοδο του καταχωρητή μέσω μιας απευθείας ανάθεσης η οποία έδινε στο ενδιάμεσο σήμα dnew είτε την τιμή din είτε την τρέχουσα dcur έξοδο του καταχωρητή, ενώ το μπλοκ always_ff που ακολουθούσε απλά φόρτωνε την τιμή dnew μέσα στον καταχωρητή dcur με την επόμενη ακμή του ρολογιού. Αντίθετα στη δεύτερη περίπτωση τόσο η επιλογή όσο και η ανάθεση στο dcur πραγματοποιήθηκαν μέσα στο ίδιο μπλοκ always_ff. Ουσιαστικά μετά την θετική ακμή του ρολογιού το dcur λαμβάνει την τιμή του din μόνο όταν το load='1'. H ανάθεση μέσα σε θετική ακμή αυτόματα σημαίνει τη γέννηση flip-flops για το dcur, ενώ η παρουσία μιας συνθήκης if παραπέμπει σε ένα πολυπλέκτη. Φυσικά για να ήταν η περιγραφή του πολυπλέκτη πλήρης θα έπρεπε να περιλαμβάνει και μία ανάθεση για την περίπτωση που το load='0'. Εφόσον το μπλοκ always_ff ελέγχεται από μια ακμή του ρολογιού μπορούμε να παραλείψουμε αυτή 5

την ανάθεση αναγκάζοντας σε αυτή την περίπτωση το dcur να θυμάται την παλιά του τιμή (περιγράφοντας έμμεσα την ανάδραση από την έξοδο του flip-flop στη μια είσοδο δεδομένων του πολυπλέκτη). Σε κάθε περίπτωση όταν έχω μια ανάθεση μέσα σε ένα μπλοκ always_ff που ελέγχεται από τη θετική ακμή ενός σήματος τότε όλες οι αναθέσεις που πραγματοποιούνται μέσα σε αυτό το μπλοκ καταλήγουν σε ένα καταχωρητή (flip-flop) ενός ή περισσότερων δυαδικών ψηφίων ανάλογα με το εύρος των σημάτων στα οποία γίνεται η ανάθεση. Οι δομες if ή(και) case που μπορεί να συνοδεύουν τις αναθέσεις αυτές απλά αντιστοιχούν στους πολυπλέκτες (ή τη συνδυαστική λογική γενικότερα) που καθορίζει ποια νέα τιμή θα εμφανιστεί στην είσοδο των καταχωρητών. Το μικρό παράδειγμα που ακολουθεί παρουσιάζει ακριβώς αυτή την ιδιότητα των περιγραφών της ακολουθιακής λογικής σε SystemVerilog. Στο παράδειγμα μας θέλουμε να περιγράψουμε την υπο-συνθήκη ανάθεση στο σήμα z ανάλογα με την τιμή του σήματος sel. Ο κορμός της περιγραφής μας θα ήταν όπως παρακάτω: if (sel) z<-a; z<-b; Ανάλογα όμως με το μπλοκ always που τοποθετούμε την περιγραφή αυτή οδηγούμαστε σε διαφορετικές υλοποιήσεις. Φυσικά και στις δύο είναι παρών ο πολυπλέκτης που υλοποιεί την επιλογή. // use blocking assignments = if (sel) z = a; z = b; // use non-blocking assignements <= if (sel) z <= a; z <= b; Στην πρώτη περίπτωση ο κώδικας τοποθετήθηκε μέσα σε ένα μπλοκ που ελέγχεται έμμεσα από τα σήματα a, b και sel και οδήγησε στη σύνθεση συνδυαστικής λογικής, ενώ στη δεύτερη περίπτωση ο κώδικας τοποθετήθηκε μέσα σε ένα μπλοκ always_ff που ελέγχεται από ένα σήμα clk και όλη η δουλειά γίνεται μόνο στη θετική ακμή του σήματος αυτού, με αποτέλεσμα τη σύνθεση ενός flip-flop για το σήμα q. Tέλος είναι κρίσιμο να προσέξετε τη χρήση διαφορετικών τελεστών ανάθεσης (= και <=) στην κάθε περίπτωση. Οι διαφορές τους θα εξηγηθούν στη συνέχεια. Στο επόμενο παράδειγμα βλέπουμε ένα process το οποίο είτε φορτώνει νέες τιμές στους δύο καταχωρητές είτε ανταλλάσσει τις τιμές τους ανάλογα με τις τιμές των σημάτων ελέγχου. always @(posedge clk) if (load) out1<=a; out2<=b; if (swap) out1<=out2; out2<=out1; 6

Αρχικοποίηση ακολουθιακής λογικής Kάθε ακολουθιακό κύκλωμα βασίζει τη λειτουργία του στην εσωτερική κατάσταση που αποθηκεύει στα flip-flops από τα οποία αποτελείται. Με την έναρξη της λειτουργίας του κυκλώματος η εσωτερική κατάσταση πρέπει να αρχικοποιηθεί σε μια γνωστή εκ των προτέρων τιμή, εξασφαλίζοντας έτσι την ορθή λειτουργία του κυκλώματος και τη σωστή αντίδραση του στις αλλαγές των εισόδων του. Η αρχικοποίηση των κυκλωμάτων συνήθως πραγματοποιείται μέσω της ενεργοποίησης ενός εξωτερικού σήματος reset. Επομένως ένας απλός καταχωρητής ο οποίος αρχικοποιείται στη τιμή 000 με την έναρξη λειτουργίας του κυκλώματος (όταν το reset='1') μπορεί να μοντελοποιηθεί σε SystemVerilog με την παρακάτω διεργασία (σύγχρονη εκδοχή). Με βάση αυτή την περιγραφή και όπως προκύπτει και από το διάγραμμα χρονισμού των σημάτων, το reset επιδρά στο κύκλωμα με την επόμενη ακμή του ρολογιού (σύγχρονο reset). Επομένως αν και το σήμα reset ενεργοποιήθηκε πριν τη θετική ακμή του ρολογιού δε θα επηρεάσει την ανάθεση του q αφού η διεργασία δε θα δει ποτέ αυτή την αλλαγή. ΣΥΓΧΡΟΝΗ ΑΡΧΙΚΟΠΟΙΗΣΗ if (reset) q <= 0; // normal mode ΑΣΥΓΧΡΟΝΗ ΑΡΧΙΚΟΠΟΙΗΣΗ always_ff @(posedge clk or posedge rst) if (reset) q <= 0; // normal mode Αντίθετα σε πολλές περιπτώσεις τα ffs που έχουμε στη διάθεση μας, όπως για παράδειγμα αυτά που υπάρχουν μέσα στα ολοκληρωμένα κυκλώματα επαναδιατασσόμενης λογικής (FPGAs), διαθέτουν μια δικιά τους πόρτα αρχικοποίησης, η οποία μας επιτρέπει να θέσουμε την έξοδο τους στην τιμή '0', απευθείας, και ανεξάρτητα από την παρουσία της ακμής του ρολογιού (ασύγχρονη αρχικοποίηση). Ωστόσο, για να μοντελοποιήσουμε αυτή τη συμπεριφορά, πρέπει να μπορούμε να περιγράψουμε τα μπλοκ always_ff με τέτοιο τρόπο, ώστε να είναι ευαίσθητα και στο σήμα αρχικοποίησης αλλά και στις ακμές του ρολογιού, όπως φαίνεται στη στήλη ασύγχρονη αρχικοποίηση του παραπάνω σχήματος. Σε αυτή την περίπτωση στη λίστα ενεργοποίησης του μπλοκ συμμετέχει τόσο το σήμα ρολογιού όσο και το σήμα αρχικοποίησης. Μέσα στο μπλοκ ελέγχεται πρώτα η ενεργοποίηση του σήματος αρχικοποίησης οδηγώντας την έξοδο σε μια σταθερή τιμή ενώ όταν το σήμα αρχικοποίησης έχει σβήσει επανερχόμαστε στην κανονική λειτουργία του κυκλώματος. Η περίπτωση της ασύγχρονης αρχικοποίησης είναι η μοναδική στην οποία επιτρέπεται στη λίστα ενεργοποίησης μιας διεργασίας που περιγράφει ακολουθιακή λογική να συμμετέχει και κάποιο άλλο σήμα μαζί με το σήμα ρολογιού. Οποιαδήποτε άλλη περίπτωση ακολουθιακής λογικής που δεν απαιτεί ασύγχρονη αρχικοποίηση περιγράφεται αυστηρά με μπλοκς always_ff τα οποία ενεργοποιούν μόνο οι ακμές ενός σήματος ρολογιού. Η ασύγχρονη αρχικοποίηση εμπεριέχει κινδύνους για την ορθή λειτουργία του κυκλώματος μας, κυρίως όσον αφορά την πιθανότητα πρόκλησης μετασταθερότητας στα flip-flops του κυκλώματος. Το πρόβλημα αυτό αντιμετωπίζεται αν εξωτερικά από το κύκλωμα μας έχουμε εξασφαλίσει πως οι μεταβάσεις στο σήμα reset έχουν συγχρονιστεί με το σήμα ρολογιού και πραγματοποιούνται μακρυά χρονικά από την ακμή δειγματοληψίας του ρολογιού. Τέτοια προβλήματα δε θα μας απασχολήσουν σε αυτή τη φάση. Μετρητές/καταχωρητές Στη συνέχεια ας δούμε πως μπορούμε να περιγράψουμε σε SystemVerilog με τις κατάλληλες δομές ευρέως χρησιμοποιούμενα κυκλώματα όπως μετρητές και ακολουθιακοί ολισθητές. Για τους απλούς δυαδικούς μετρητές θα περιγράψουμε μια πλούσια 7

τους εκδοχή η οποία επιτρέπει στο χρήστη να επιτρέψει η όχι τη μέτρηση, να καθορίσει τη φορά της, να φορτώσει μια νέα τιμή στο μετρητή καθώς και να ελέγξει κάθε πότε ο μετρητής μηδενίζεται. Η τελευταία αυτή η ιδιότητα μας επιτρέπει να σχεδιάσουμε εύκολα μετρητές χρονικών διαστημάτων (timers). module counter #( parameter N = 8) ( input logic clk, input logic rst, input logic cnten, input logic lden, input logic [N-1:0] ldval, output logic done, output logic [N-1:0] count); logic [N-1:0] countval; assign count = countval; assign done <= (countval==0)? 1'b1 : 1 b0; always_ff @(posedge clk or posedge rst) if (rst) countval <= 0; if (lden) countval <= ldval; if (cnten) countval <= countval + 1; module O καταχωρητής των Ν δυαδικών ψηφίων countval διατηρεί στην έξοδο του την τρέχουσα τιμή του μετρητή. O καταχωρητής αυτός αλλάζει την τιμή του μόνο στη θετική ακμή του ρολογιού ή ασύγχρονα με την ενεργοποίηση του σήματος reset. Οταν το rst=0 και έρθει μια ακμή του ρολογιού τότε η νέα τιμή που θα φορτωθεί στο countval περνάει από δύο σε σειρά πολυπλέκτες. Αν το loaden= 1 τότε στον καταχωρητή countval φορτώνεται η εξωτερική τιμή loadval. Αν όμως το loaden=0 τότε στον καταχωρητή θα φορτωθεί είτε η αυξημένη κατά 1 τιμή του, όταν CountEn=1 ή η παλιά τιμή που ήδη είχε. Ταυτόχρονα, κάθε φορά που η τιμή του καταχωρητή countval είναι ίση με 0 τότε ενεργοποιείται το σήμα done μέσω της απευθείας αναθέσεις (έξω από το μπλοκ always_ff) του παραδείγματος μας. Το κύκλωμα παραγωγής του done είναι κύκλωμα συνδυαστικής λογικής το οποίο οδηγείται από την έξοδο του καταχωρητή countval. Η παραπάνω περιγραφή αντιπροσωπεύει μια γενική δομή για κυκλώματα μετρητών. Αφαιρώντας μέρος της λειτουργίας του γενικού κυκλώματος μπορούμε να σχεδιάσουμε απλούστερα κυκλώματα όπως το διαιρέτη συχνότητας που φαίνεται στο παράδειγμα που ακολουθεί. module freq_divider_by_16 ( input logic CorexClk, input logic ResetxN, output logic Div16XClk); logic [3:0] CountReg; always_ff @(posedge CorexClk) 8

if (!ResetxN) CountReg <= 0; CountReg <= CountReg + 1; assign Div16xClk = CountReg[3]; module Ένα επιπλέον χρήσιμο παράδειγμα μετρητή είναι αυτό του μετρητή Johnson του οποίου η περιγραφή και το σχηματικό φαίνονται στο παρακάτω σχήμα. O μετρητής Johnson δεν είναι τίποτε άλλο από ένα ακολουθιακό καταχωρητή ολίσθησης (shift register) ο οποίος επανατροφοδοτεί το λιγότερο σημαντικό ψηφίο του καταχωρητή με την ανεστραμμένη εκδοχή του πιο σημαντικού ψηφίου που ολισθαίνει έξω από τον καταχωρητή. module johnsoncounter #( parameter N = 8) ( input logic clk, output logic [N-1:0] count); logic [N-1:0] countval; assign count = countval; // left shift countval[ν-1:1] <= countval[n-1:0]; countval[0] <= ~countval[n-1]; module Δύο μπλοκς always μπορούν να επικοινωνήσουν μέσω των αναθέσεων των σημάτων τους καθορίζοντας από κοινού τη λειτουργία του κυκλώματος. Σε αυτή την περίπτωση οι έμμεσες έξοδοι κάθε μπλοκ (τα σήματα που αναθέτει στο σώμα του) χρησιμοποιούνται ως είσοδοι σε ένα άλλο μπλοκ είτε στις συνθήκες των δομών if είτε στην δεξιά πλευρά των αναθέσεων. Στη συνέχεια παρουσιάζουμε δύο τέτοια παραδείγματα. logic s1, s2, s3, s4; // 1 st process if (s1) s3 = s2; s3 = 0; // 2 nd process if (s1) s4 = s3; s4 = s1; logic [3:0] cnt_a; logic [3:0] cnt_b; // 1 st process cnt_a <= cnt_a + 1; // 2 nd process if (cnt_a == 0) cnt_b <= cnt_b+1; Στην πρώτη περίπτωση η έξοδος s3 της πρώτης διεργασίας χρησιμοποιείτε ως είσοδος στην άλλη διεργασία (βρίσκεται στη δεξιά πλευρά της ανάθεσης). Για να είναι σωστή η περιγραφή της συνδυαστικής λογικής που περιγράφουν από κοινού οι δύο 9

διεργασίες εφόσον το s3 συμμετέχει ως είσοδος στη δεύτερη διεργασία πρέπει να συμμετέχει στη λίστα ενεργοποίησης της διεργασίας αυτής. Στην δεύτερη περίπτωση οι δύο διεργασίες περιγράφουν δύο μετρητές των 4 δυαδικών ψηφίων, τον cnt_a και τον cnt_b. O πρώτος μετρητής περιγράφεται στην πρώτη διεργασία και αυξάνει την τιμή του σε κάθε κύκλο ρολογιού ενώ ο δεύτερος αυξάνει την τιμή του μόνο σε εκείνους τους κύκλους (μετά από θετική ακμή) που η τιμή του μετρητή cnt_a είναι ίση με 0. Ενώ οι αναθέσεις σε ένα σήμα πρέπει να γίνονται όλες στο ίδιο μπλοκ always (ή σε μια απευθείας ανάθεση) για την αποφυγή πολλαπλών οδηγητών στο ίδιο σήμα, οι αναγνώσεις του σήματος μπορεί να γίνονται σε πολλά σημεία στην περιγραφή. ΑΡΧΕΙΟ ΚΑΤΑΧΩΡΗΤΩΝ Ο τρόπος που μοντελοποιήσαμε τους καταχωρητές, τους μετρητές και τους ολισθητές μπορεί να χρησιμοποιηθεί για τη μοντελοποίηση μικρών αρχείων καταχωρητών που διαλέγουμε να υλοποιήσουμε μέσω flip-flop και λογικών πυλών. Για μεγαλύτερες μονάδες μνήμης μέσα στα ολοκληρωμένα κυκλώματα αντί για αρχεία καταχωρητών είμαστε υποχρεωμένοι να χρησιμοποιήσουμε έτοιμες προσχεδιασμένες SRAM οι οποίες σχεδιάζονται σε επίπεδο τρανζίστορ και δεν μπορούν να προκύψουν μέσω περιγραφών σε SystemVerilog και λογικής σύνθεσης. Σε αυτή την περίπτωση η μόνη αυτοματοποίηση που μας παρέχεται είναι η επιλογή του μεγέθους των μνημών αυτών και ίσως και της γεωμετρίας του φυσικού τους σχεδίου μέσω ειδικών memory compilers οι οποίοι συνθέτουν το φυσικό σχέδιο των μνημών τρανζίστορ προς τρανζίστορ. Η περιγραφή της λειτουργίας ενός σύγχρονου αρχείου καταχωρητών με 16 θέσεις των 32 μπιτ η καθεμία με μια πόρτα ανάγνωσης και εγγραφής φαίνεται στο παράδειγμα που ακολουθεί. To κύκλωμα αυτό μπορεί να εκτελέσει είτε μία εγγραφή είτε μία ανάγνωση σε ένα κύκλο ρολογιού στη διεύθυνση address. module ram_32_16 ( input logic clk, // Clock input logic we, // write enable input logic [ 3:0] address, // address vector input logic [31:0] datain, output logic [31:0] dataout); logic [15:0] [31:0] ram; if (we) ram[address] <= datain; dataout <= ram[address]; module Αρχικά ας ασχοληθούμε με τη δήλωση του σήματος που χρησιμοποιείται για τη μοντελοποίηση όλων των flip-flops του αρχείου καταχωρητών. Στο παράδειγμα αυτό θέλουμε να μοντελοποιήσουμε ένα αρχείο καταχωρητών των 16 θέσεων (επομένως θα χρειαστούμε 4 μπιτς για κάθε διεύθυνση) των 32 μπιτς η καθεμία. Για να το κάνουμε αυτό χρειαζόμαστε ένα πίνακα (array) των 16 θέσεων όπου σε κάθε θέση θα βρίσκαμε ένα logic [31:0], δηλαδή μια δυαδική λέξη των 32 δυαδικών ψηφίων. Για να εμφανίσουμε στη SystemVerilog μια τέτοια δισδιάστατη δομή από σήματα χρειάζεται να τη δηλώσουμε ως εξής: logic [15:0] [31:0] ram; Βοηθάει να αντιμετωπίζεται το σήμα αυτό ως μια συνεχόμενη συλλογή από 16 πεδία όπου το κάθε πεδίο είναι των 32 μπιτ. Έτσι, κάθε φορά που απευθυνόμαστε σε μια θέση του σήματος ram, ουσιαστικά απευθυνόμαστε σε ένα πεδίο τύπου logic [31:0]. Έτσι θα μπορούμε να γράψουμε την παρακάτω ανάθεση: ram[2] <= 32 b0010_0010_0000_1011_0110_0111_1111_1011; Εφόσον κάθε ram[i] είναι ένα logic [31:0] σημαίνει πως μπορούμε να απευθυνθούμε στα bits του vector αυτού χρησιμοποιώντας ακόμη μια αγκύλη. Δηλαδή αν γράψουμε X <= ram[2][3]; Αναθέτουμε στο X στο 3ο μπιτ του δεύτερου πεδίου (δλδ για τη μνήμη μας την τιμή που βρίσκεται στη διεύθυνση 2) Εφόσον όλες οι αναθέσεις στο σήμα ram γίνονται μετά την ακμή του ρολογιού, για κάθε ένα από τα bit του δημιουργείται και ένα flip-flop. Οταν το σήμα επίτρεψης εγγραφής we=1 τότε η είσοδος γράφεται στη αντίστοιχη θέση. Αντίθετα όταν 10

πραγματοποιείται ανάγνωση η έξοδος dataout οδηγείται από κάποιο καταχωρητή της μνήμης ο οποίος επιλέγεται μέσω ενός πολυπλέκτη ανάλογα με την τιμή του address. Σε αυτή την περίπτωση αποκωδικοποιητής και πολυπλέκτης είναι το ίδιο πράγμα και οδηγούν σε μια υλοποίηση με AND OR πύλες για την αποκωδικοποίηση και συλλογή του τελικού αποτελέσματος. Αυτό που πρέπει να προσέξετε είναι πως πέρα από τα flip flops του αρχείου καταχωρητών κατά τη λογική σύνθεση γεννιέται και ακόμη ένας καταχωρητής για την έξοδο dataout. Περιγραφή FSM Οι μηχανές πεπερασμένων καταστάσεων χρησιμοποιούνται ευρέως στα ψηφιακά κυκλώματα που σχεδιάζουμε. Η περιγραφή του ισοδύναμου κυκλώματος της FSM σε SystemVerilog ακολουθεί μια τυποποιημένη περιγραφή που αποτελείται από δύο βασικά μέρη όπως θα δούμε παρακάτω. Στην εικόνα που ακολουθεί φαίνεται μια FSM στην οποία διακρίνουμε τα εξής μέρη: Single always_ff block 1. Την αρχική κατάσταση η οποία αναπαρίσταται με έναν διπλό κύκλο (δεν είναι δεσμευτικό). Στην περίπτωση ενεργοποίησης του σήματος αρχικοποίησης Reset μεταβαίνουμε σε αυτήν την κατάσταση ανεξάρτητα από την τρέχουσα κατάσταση του κυκλώματος. 2. Τις καταστάσεις της FSM οι οποίες αναπαρίστανται με ένα κύκλο και συνοδεύονται από ένα όνομα. 3. Τα βέλη των μεταβάσεων που ενώνουν δύο καταστάσεις (ή καταλήγουν στην ίδια κατάσταση) τα οποία μπορεί είτε να ελέγχονται από κάποια συνθήκη είτε όχι, π.χ., η μετάβαση S0 -> S1 πραγματοποιείται όταν η είσοδος start παίρνει την τιμή 1, ενώ η μετάβαση S3 -> S4 συμβαίνει ανεξάρτητα από τις τρέχουσες τιμές των εισόδων. Δεν πρέπει να ξεχνάμε πως οι μεταβάσεις πραγματοποιούνται σε κάθε θετική ακμή του ρολογιού. 4. Τις τιμές των εξόδων που αντιστοιχούν σε κάθε κατάσταση. Για να καταφέρουμε να μοντελοποιήσουμε μια μηχανή πεπερασμένων καταστάσεων πρέπει: 1. Να αναπαραστήσουμε τις καταστάσεις. 2. Να μπορούμε να αποθηκεύσουμε την τρέχουσα κατάσταση. 3. Να καθορίσουμε τις μεταβάσεις από τη μια κατάσταση στην άλλη. 4. Να υπολογίζουμε τις τιμές εξόδου που αφορούν την κάθε κατάσταση. Στη συνέχεια θα περιγράψουμε έναν πρότυπο τρόπο, ο οποίος μας επιτρέπει να καλύψουμε όλες τις παραπάνω προϋποθέσεις. Για την περιγραφή της FSM χρησιμοποιούμε ένα μπλοκ always_ff για τον υπολογισμό της επόμενης κατάστασης και την αποθήκευση της τρέχουσας κατάστασης. To μπλοκ αυτό ουσιαστικά μοντελοποιεί με έναν ενοποιημένο τρόπο τη λογική επόμενης κατάστασης και τον καταχωρητή κατάστασης της FSM. Αντίθετα με το σύνολο των απευθείας αναθέσεων περιγράφουμε τη λογική εξόδου που δίνει τιμές στα σήματα εξόδου της FSM λαμβάνοντας υπόψιν την τρέχουσα κατάσταση. To παράδειγμα που ακολουθεί υλοποιεί την αρχική fsm σύμφωνα με την πρότυπη περιγραφή. typedef enum {IDLE, stoken, sspray} fsm_state; fsm_state state; // state holding registers and state transition logic 11

always_ff @ (posedge clk or negedge rst) if (!rst) state <= sidle; case (state) sidle: if (token) state <= stoken; state <= sidle; //redundant can be omitted stoken: state <= sspray; sspray: if (tdone) state <= sidle; state <= sspray; // redundant can be omitted case // output logic assign clrt = (state == stoken); assign spray = (state == stoken state == sspray); Η πρώτη προϋπόθεση της πρότυπης περιγραφής FSM έχει να κάνει με την κωδικοποίηση των καταστάσεων. Στην περιγραφή μας αποφεύγουμε να διαλέξουμε οποιαδήποτε κωδικοποίηση και συνεχίζουμε να αναφερόμαστε στις καταστάσεις με τα συμβολικά τους ονόματα. Για να το κάνουμε αυτό πρέπει να ορίσουμε ένα τύπο enumeration στον οποίο να συμπεριλάβουμε μια συμβολική ονομασία για κάθε κατάσταση. Στο παράδειγμα ορίζουμε τον τύπο fsm_state τον οποίο ακολουθεί και ο καταχωρητής κατάστασης της FSM που ονομάσαμε state. Ανάλογα με την κωδικοποίηση που θα διαλέξει το εργαλείο της λογικής σύνθεσης θα αλλάξει και το πλήθος των flip-flop από τα οποά αποτελείται ο καταχωρητής state. Με την ενεργοποίηση του reset αναθέτουμε στον καταχωρητή state την τιμή της αρχικής κατάστασης (η IDLE στην περίπτωση μας). Στη συνέχεια όταν το reset είναι απενεργοποιημένο σε κάθε θετική ακμή του ρολογιού αναθέτουμε στον καταχωρητή κατάστασης μια νέα κατάσταση λαμβάνοντας υπόψιν την τρέχουσα κατάσταση (μέσω του case) και των τιμών των εισόδων που εμφανίζονται ως συνθήκες σε κάποιες από τις μεταβάσεις της FSM. case state S1: if (in) state <= S2 Τρέχουσα κατάσταση Συνθήκη εισόδου για μετάβαση από S1 σε S2 Εφόσον όλες οι αλλαγές στο state πραγματοποιούνται στις θετικές ακμές του ρολογιού, αυτό σημαίνει πως το εργαλείο λογικής σύνθεσης θα αναθέσει το state σε ένα σύνολο από flip-flops. Στη συνθήκη case ελέγχουμε την έξοδο αυτών των flip-flops (παλιά τιμή του state) και υπολογίζουμε μια καινούρια κατάσταση που ανατίθεται στο state. Αν καμμιά από τις συνθήκες αλλαγής κατάστασης δεν ενεργοποιηθεί τότε η τιμή της κατάστασης της FSM παραμένει ίδια με αυτή του προηγούμενου κύκλου. Αυτή τη συμπεριφορά δεν είναι ανάγκη να την περιγράψουμε καθώς στις περιπτώσεις που το state δε παίρνει νέα τιμή το αναγκάζουμε να θυμάται την παλιά του. H επιλογή case διαφέρει από τις εμφωλευμένες if καθώς επιτρέπει παράλληλες επιλογές δημιουργώντας έτσι ένα μεγάλο πολυπλέκτη ανάλογα με τις επιλογές που εμφανίζονται. Η περιγραφή της FSM ολοκληρώνεται με την περιγραφή της λογικής εξόδου μέσα από ένα σύνολο απευθείας αναθέσεων ίσο με το πλήθος των εξόδων της FSM. Ελέγχουμε σε ποια κατάσταση βρίσκεται το state και δίνουμε αντίστοιχα τη σωστή τιμή στο σήμα εξόδου. Όπως φαίνεται στην ανάθεση που ακολουθεί το σήμα εξόδου spray μπορεί να οδηγείται στο λογικό 1 σε περισσότερες σε δύο καταστάσεις της fsm. assign spray = (state == stoken state == sspray); 12

Πως υπολογίζονται οι αναθέσεις Στο παράδειγμα που ακολουθεί πραγματοποιούνται δύο αναθέσεις μέσα στο μπλοκ always_ff κατά τη θετική ακμή του ρολογιού. Η μία στο σήμα FCA και η άλλη στο σήμα claim. Επειδή οι αναθέσεις αυτές πραγματοποιούνται στη θετική ακμή του ρολογιού προκύπτει πως μετά τη λογική σύνθεση τα σήματα αυτά θα ανατεθούν στις εξόδους δύο flip-flop. Η υπόλοιπη λογική που περιγράφεται αντιστοιχεί σε κομμάτια συνδυαστικής λογικής όπως πύλες OR, AND και πολυπλέκτες η οποία καταλήγει στις εισόδους των δύο flip-flop που αφορούν στα σήματα FCR και claim 01: 02 : 03: FCR <= ER or xmit; 04: if (!merge) 05: claim <= FCR; 06: 07: claim <= FDDI; 08: Όταν παρατηρήσουμε την περιγραφή και τις κυματομορφές βλέπουμε πως ενώ το FCR οδηγείται στο λογικό 1 στον κύκλο 2, η τιμή αυτή δεν «περνάει» στο claim αμέσως (ανάθεση στη γραμμή 05) αλλά στον επόμενο κύκλο ρολογιού. Η συμπεριφορά αυτή είναι λογική καθώς το FCR που βρίσκεται στη δεξιά πλευρά της ανάθεσης του claim προέρχεται από την έξοδο του flip-flop που αντιστοιχεί στο FCR και επομένως θα λάβει τη νέα του τιμή με την επόμενη ακμή του ρολογιού. Για να μπορέσετε να καταλάβετε καλύτερα την παραπάνω πρέπει να κατανοήσετε τον τρόπο που υπολογίζονται οι αναθέσεις τύπου <= (non-blocking assignments) μέσα σε μπλοκς always_ff. Με την ενεργοποίηση ενός μπλοκ always_ff αρχικά υπολογίζονται όλα τα δεξιά μέρη των αναθέσεων χρησιμοποιώντας ταυτόχρονα για όλες τις αναθέσεις τις παλιές γνωστές τιμές των σημάτων. Επειδή μια ανάθεση <= προηγείται μιας άλλης αυτό δε σημαίνει πως μπλοκάρει ή αναγκάζει την επόμενη να την περιμένει. Όλες οι αναθέσεις <= εξετάζονται ταυτόχρονα. Μετά τον υπολογισμό του δεξιού μέρους όλων των αναθέσεων με το τέλος του μπλοκ οι τιμές που έχουν υπολογιστεί ανατίθενται ταυτόχρονα στα σήματα στη αριστερή πλευρά των αναθέσεων. To παράδειγμα που ακολουθεί αποτελείται από τρείς αναθέσεις, οι οποίες δείχνουν να εξαρτώνται η μία από το αποτέλεσμα της άλλης. Πως όμως αυτό «εκτελείτε» στη SystemVerilog; Πριν την εκκίνηση θεωρούµε πως a=1, b=0, c=0 always_ff @(..clk) b <= a; c <= b; d <= c; Το clk αλλάζει To µπλοκ ενεργοποιείται Το b προγραµµατίζεται να γίνει 1 στο τέλος του µπλοκ Το c προγραµµατίζεται να γίνει 0 στο τέλος του µπλοκ (µέχρι τώρα γνωστή τιµή του b) Το d προγραµµατίζεται να γίνει 0 στο τέλος του µπλοκ (µέχρι τώρα γνωστή τιµή του c) Με το τέλος της διεργασίας γίνονται όλες οι αναθέσεις ταυτόχρονα: b <-1, c<-0, d <- 0. Η λειτουργία που αντιστοιχεί στον παραπάνω κώδικα είναι η εξής: Όταν ενεργοποιηθεί το μπλοκ always, υπολογίζεται πρώτα η 13

δεξιά πλευρά όλων των αναθέσεων ταυτόχρονα χρησιμοποιώντας τις τιμές που γνωρίζουμε εκείνη τη στιγμή (τις παλιές τιμές). Αφού ολοκληρωθεί το βήμα αυτό, όλες οι αναθέσεις πραγματοποιούνται ταυτόχρονα στο τέλος του μπλοκ. Έτσι με άλλα λόγια, το Β παίρνει την τιμή του Α, το C παίρνει την παλιά τιμή του B, και το C παίρνει την παλιά τιμή του D. Αν και η ανάθεση στο C γράφτηκε μετά την ανάθεση του B αυτό δε σημαίνει πως το C θα περιμένει να ολοκληρωθεί η ανάθεση στο B ώστε τελικά να δει την τιμή του να ισούται με A. Εφόσον όλες οι αναθέσεις πραγματοποιούνται στο τέλος του μπλοκ μπορούμε να χρησιμοποιήσουμε περισσότερες από μια αναθέσεις στο ίδιο σήμα μέσα σε κάθε μπλοκ χωρίς αυτό να δημιουργεί τον κίνδυνο πολλαπλής οδήγησης. Στην περίπτωση αυτή μόνο η τελευταία στη σειρά ανάθεση (πιο κοντά στο τέλος του μπλοκ) θα χρησιμοποιηθεί και οι τιμές όλων των υπολοίπων θα αγνοηθούν. Για παράδειγμα οι δύο εκδοχές που ακολουθούν θα έχουν ακριβώς το ίδιο αποτέλεσμα. logic a,b,c,d,y; always_ff @ ( clk) y <= a c; y <= a & b; y <= c & d; logic a,b,c,d,y; always_ff @( clk) y <= c & d; Το γεγονός ότι μόνο η τελευταία ανάθεση σε ένα μπλοκ θα χρησιμοποιηθεί τελικά μας επιτρέπει να περιγράψουμε αναθέσεις με προτεραιότητες με δύο τρόπους: always_ff () if (sel[0]) if (sel[3]) Z<=0; always_ff () if (sel[3]) Ζ<=0 if (sel[0]) Στην πρώτη περίπτωση που φαίνεται στο αριστερό κομμάτι κώδικα η συμπεριφορά περιγράφεται με ανεξάρτητες if δομές, από τις οποίες η τελευταία έχε την υψηλότερη προτεραιότητα. Στη δεύτερη περίπτωση όλες οι περιπτώσεις αντιμετωπίζονται πιο αυστηρά χρησιμοποιώντας εμφωλευμένες if επιτρέποντας έτσι μόνο μια ανάθεση στο Z ανάλογα με τους συνδυασμούς των σημάτων sel. Επειδή όλες οι αναθέσεις θα ολοκληρωθούν με την έξοδο από το μπλοκ μόνο η τελευταία θα έχει πραγματικό αποτέλεσμα. Έτσι τα δύο μπλοκς είναι ισοδύναμα ως προς τη συμπεριφορά και τη δομή του κυκλώματος που περιγράφουν. Θα μπορούσαμε να χρησιμοποιήσουμε τις πολλαπλές αναθέσεις στο ίδιο σήμα για να αποφύγουμε τη γέννηση latches στην περίπτωση κυκλωμάτων συνδυαστικής λογικής απλά φροντίζοντας να δώσουμε αρχικές τιμές στα σήματα μας. Y = 0 ; --default values if (a) then Y = b; c = a b; if (a && b) then c = 1 b0; Στα δύο παραπάνω παραδείγματα, οι δομές if δεν διαθέτουν το απαιτούμενο μονοπάτι. Η παράλειψη αυτή δε δημιουργεί πρόβλημα καθώς με την ενεργοποίηση του process τα σήματα y και c, αντίστοιχα, λαμβάνουν μια τιμή η οποία θα παραμείνει μέχρι το τέλος αν δε ικανοποιηθούν οι συνθήκες των if. Έτσι, σε κάθε περίπτωση τα σήματα y και c θα οδηγούνται σε μια τιμή χωρίς την ανάγκη να θυμούνται τις παλιές τους τιμές. H χρήση των αναθέσεων τύπου <= (non blocking assignments) ενώ πρέπει να επιλέγονται πάντα στην περίπτωση ακολουθιακής λογικής πρέπει να αποφεύγονται στις περιγραφές κυκλωμάτων συνδυαστικής λογικής. Γενικά στις περιγραφές συνδυαστικής λογικής θα θέλαμε οι νέες τιμές που αναθέτουμε σε ένα σήμα να μπορούν να είναι άμεσα ορατές στις αναθέσεις των επόμενων σημάτων, ότι δηλαδή θα συνέβαινε στην κανονική λειτουργία ενός κυκλώματος συνδυαστικής λογικής. Για να πετύχουμε αυτή 14

τη συμπεριφορά μέσα σε ένα μπλοκ πρέπει να χρησιμοποιήσουμε τις αναθέσεις τύπου = (blocking assignments). Οι αναθέσεις αυτές πραγματοποιούνται και γίνονται ορατές απευθείας και δεν περιμένουν την ολοκλήρωση του μπλοκ always. logic a,b,c; logic y, vx; vx = a b; if ( c ) vx = 0; y <= vx; process; Πριν την εκκίνηση θεωρούµε πως τα σήµατα είχαν την τιµή 0 Το α αλλάζει 0->1 => Η διεργασία ενεργοποιείτε Το vx παίρνει αµέσως την τιµή (1 or 0)=1 H συνθήκη δεν ενεργοποιείται. Το vx µένει στο 1 από την προηγούµενη ανάθεση Το y προγραµµατίζεται να γίνει όσο και το vx στο τέλος της διεργασίας, δηλαδή ίσο µε την τρέχουσα τιµή (1) του vx που έχει πάρει από την πρώτη ανάθεση Με το τέλος της διεργασίας γίνονται όλες οι αναθέσεις στα σήµατα ταυτόχρονα: y <-1 Αντίθετα οι αναθέσεις τύπου = πρέπει να αποφεύγονται στις περιγραφές ακολουθιακής λογικής. Ας δούμε γιατί μέσω μιας περιγραφής ενός καταχωρητή ολίσθησης ο οποίος μπορεί να αρχικοποιηθεί με την ενεργοποίηση ενός σήματος reset. if (reset) s_q1 <= 0; s_q2 <= 0; q3 <= 0; q3 <= s_q2; s_q2 <= s_q1; s_q1 <= d; Όπως ήταν αναμενόμενο εφόσον οι αναθέσεις στα σήματα q3, s_q2, s_q1 γίνονται στη θετική ακμή του ρολογιού αντιστοιχίζεται σε κάθε ένα από αυτά και ένα flip flop. Επίσης, εφόσον και τα τρία σήματα είναι τύπου signal όλες οι αναθέσεις σε αυτά προγραμματίζονται κατά τη διάρκεια του process και «εκτελούνται» με το τέλος του περιμένοντας την εκ νέου ενεργοποίηση του. Έτσι όταν το reset=0, to q3 παίρνει την παλιά τιμή του s_q2 (έξοδος αντίστοιχου flip flop), το s_q2 την παλιά τιμή του s_q1 (έξοδος αντίστοιχου flip flop) και το s_q1 την τιμή του d. Αν στην περιγραφή είχαμε υιοθετήσει τη χρήση αναθέσεων τύπου = για την ακολουθιακή λογική, τότε το αποτέλεσμα που θα παίρναμε μετά τη λογική σύνθεση θα ήταν πολύ διαφορετικό. if (reset) s_q1 <= 0; v_q2 <= 0; q3 <= 0; q3 <= v_q2; v_q2 <= s_q1; s_q1 <= d; if (reset) s_q1 <= 0; v_q2 = 0; q3 <= 0; q3 <= v_q2; v_q2 = s_q1; s_q1 <= d; 15

O λόγος για την εξαφάνιση του ενός καταχωρητή στην περίπτωση της δεύτερης περιγραφής είναι η ανάθεση στο v_q2. H χρήση του τελεστή ανάθεσης = (blocking assignment) στο v_q2 επιβάλλει την άμεση ενημέρωση του v_q2 με την τρέχουσα τιμή του s_q1, αυτή δηλαδή που είχε με την έναρξη του process (έξοδος του flip-flop s_q1). Η τιμή αυτή είναι αυτή που τελικά θα ανατεθεί στο q3 στο τέλος του process. Επειδή το v_q2 είναι ένα απλό αντίγραφο της τιμής του s_q1, το flip flop που αντιστοιχούσε πριν στο s_q2 δεν έχει λόγο να υφίσταται αφού η τιμή του s_q1 περνά απευθείας στο q3 μέσω της ανάθεσης στο variable v_q2. 16