Δημοκρίτειο Πανεπιστήμιο Θράκης Τμήμα Ηλεκτρολόγων Μηχανικών & Μηχανικών Υπολογιστών Συστήματα VLSI Παραδείγματα ασκήσεων Άσκηση 1 Καλείστε να περιγράψετε το παρακάτω κύκλωμα σε VHDL. Το κύκλωμα αποτελείται από 3 flip-flops τα οποία ενεργοποιούνται στη θετική ακμή του σήματος ρολογιού και μια πύλη NOR 3 εισόδων. Μπορείτε να επιλέξετε όποιο τρόπο περιγραφής δομικό ή συμπεριφοράς επιθυμείτε. Λύση logic [2:0] x; always_ff @ (posedge clk) x[2] <= x[1]; x[1] <= x[0]; x[0] <= ~(x[0] x[1] x[2] ); 1
Άσκηση 2 Σας δίνεται η παρακάτω περιγραφή σε VHDL η οποία υλοποιεί μια FSM 4 καταστάσεων. Η κάθε κατάσταση κωδικοποιείται με 2 δυαδικά ψηφία cs1 και cs0. Μαζί με την περιγραφή σε VHDL σας δίνεται και το διάγραμμα μετάβασης καταστάσεων που αντιστοιχεί στην περιγραφή αυτή. Καλείστε να συμπληρώσετε πάνω στις ακμές του διαγράμματος μετάβασης καταστάσεων τις συνθήκες προκαλούν την κάθε μετάβαση αφού συμβουλευτείτε την περιγραφή της VHDL. Το ίδιο πρέπει να κάνετε και για τις τιμές της εξόδου x και y δείχνοντας τις τιμές που λαμβάνουν τα σήματα αυτά σε κάθε κατάσταση. module 4statefsm( input logic a,b,clk, output logic x,y); logic cs1,cs0; logic ns1,ns0; always_ff @ (posedge clk) cs1 <= ns1; cs0 <= ns0; always_ff @ (posedge clk) if(a==1) ns1 <= 0; ns0 <= 0; else if(cs1==0 & cs0==0 & b==0) ns1 <= 1; ns0 <= 0; else if(cs1==0 & cs0==1 & b==1) ns1 <= 1; ns0 <= 1; else if(cs1==1 & cs0==0 & b==0) ns1 <= 0; ns0 <= 1; else if(cs1==1 & cs0==1 & b==0) ns1 <= 0; ns0 <= 0; assign x = (cs1==0 & cs0==1); assign y = (cs1==1 & (cs0==1 a==b)); module Λύση 2
Άσκηση 3 Σας δίνεται το σχηματικό του datapath ενός κυκλώματος το οποίο σχεδιάστηκε για να υλοποιεί τις παρακάτω τέσσερις εργασίες. 1. X Memory[NUMA] 2. NUMA NEXT + 1; 3. NEXT Memory[NEXT] 4. SUM SUM+X; Οι μεταβλητές Χ, NUMA, SUM και NEXT αντιστοιχούν στους τέσσερις καταχωρητές του datapath. Στην απλή περίπτωση η εκτέλεση των εντολών θα διαρκούσε 4 κύκλους ρολογιού (η μια εργασία μετά την άλλη). Οργανώστε την εκτέλεση των τεσσάρων εργασιών με τέτοιο τρόπο ώστε να επιτύχεται τη μέγιστη δυνατή παραλληλία κατά την εκτέλεση τους μειώνοντας τους κύκλους ρολογιού που απαιτούνται για την εκτέλεση τους. Η επιλογή σας πρέπει να μπορεί να υλοποιηθεί στο datapath που σας δίνεται. Λύση 1. Χ <- Memory[NUMA], NUMA <- NEXT + 1 2. NEXT <- Memory[NEXT], SUM <- SUM+X 3
Άσκηση 4 Περιγράψετε σε SystemVerilog το παραπάνω κύκλωμα με όποιο τρόπο επιθυμείτε. Τα σήματα που υπάρχουν στο σχήμα θεωρήστε ότι είναι εξωτερικά του κυκλώματος και πρέπει να τα συμπεριλάβετε στη δήλωση του entity. Η περιγραφή σε SystemVerilog αρκεί να πετυχαίνει την ίδια λειτουργία. Δεν είναι ανάγκη να ακολουθήσει τη δομή και ένα ιεραρχικό σχεδιασμό. Τα σήματα Load και Clear των καταχωρητών δειγματοληπτούνται από την ακμή του ρολογιού Φ (εχουν δηλαδή σύγχρονη συμπεριφορά). Λύση module datapath #(parameter N=8)( input logic LoadA,ClearA, input logic LoadSum,ClearSum, input logic EnAdd, input logic LoadAcc, input logic clk); logic [N-1:0] A,Sum,Acc,DataBus; always_ff @(posedge clk) if(cleara) A<=0; else if(loada) A<=DataBus; if(clearsum) Sum<=0; else if(loadsum) Sum<=A+DataBus; if(loadacc) Acc<=DataBus; assign DataBus = (EnAdd==1)? Sum : Acc; module 4
Άσκηση 5 Στην άσκηση αυτή θα εξερευνήσετε τη χρονική συμπεριφορά του κυκλώματος που σας δίνεται στο σχήμα που ακολουθεί. Η δομή και οι καθυστερήσεις των στοιχείων του κυκλώματος περιορίζουν τη συχνότητα του ρολογιού με την οποία μπορούμε να λειτουργήσουμε με ασφάλεια το κύκλωμα. Κάθε πύλη του κυκλώματος θεωρήστε πως παρουσιάζει την ίδια καθυστέρηση είτε κάνει μια μετάβαση 0->1 είτε 1->0. Η καθυστέρηση των αντιστροφέων είναι ίση με 50+100f ενώ των πυλών NAND και NOR είναι ίση με 100+150f, όπου με f συμβολίζουμε το fanout της κάθε πύλης το οποίο για την άσκηση αυτή ισούται με το πλήθος των άλλων πυλών ή flip flop που οδηγεί η έξοδος της πύλης. Για τα flip flop θεωρήστε t SETUP = t CLK-Q =t HOLD =50ps. 1. Αρχικά πρέπει να βρείτε το κρίσιμο μονοπάτι του κυκλώματος. Το μονοπάτι δηλαδή που παρουσιάζει τη μέγιστη καθυστέρηση. 2. Ποια είναι η μέγιστη συχνότητα που μπορείτε να λειτουργήσετε το κύκλωμα αυτό; Παραβιάζει το κύκλωμα τον περιορισμό του χρόνου hold των flip-flops; Εξηγείστε την απάντηση σας 5
Λύση Στο σχήμα φαίνονται οι καθυστερήσεις (σε ps) των πυλών ανάλογα με το fanout (f) της καθεμίας Α Β 3. Το κρίσιμο μονοπάτι του κυκλώματος είναι αυτό που παρουσιάζει τη χειρότερη αθροιστική καθυστέρηση λογικών πυλών. Ολα τα μονοπάτια του κυκλώματος ξεκινούν και τελειώνουν σε ένα καταχωρητή: Από έξοδο Α-> είσοδο C, έξοδο B-> είσοδο C, έξοδο C-> είσοδο C. Το χειρότερο από πλευράς καθυστέρησης είναι αυτό που ξεκινάει από την έξοδο του C και καταλήγει στην είσοδο του C και περιλαμβάνει τις λογικές πύλες 1->2->6->5->4->7->είσοδος C με συνολική καθυστέρηση συνδυαστικής λογικής 1500ps = 1.5ns. 4. H μέγιστη συχνότητα (ελάχιστη περίοδος) λειτουργίας του κυκλώματος επηρεάζεται επίσης από την καθυστέρηση clk->q των flip-flops, το χρόνο setup των flip-flops και το clock skew. Υποθέτωντας πως το clock skew είναι 0, η ελάχιστη περίοδος καθορίζεται από το μονοπάτι με τη χειρότερη καθυστέρηση (τα άλλα υπολογίζουν νωρίτερα και απλώς περιμένουν τη διάδοση των σημάτων) ως εξής: T " " t "&'( + T *+,&-./"(" ") + t 23456 =50ps + 1500ps+50ps=1.6ns Τα άλλα δύο μονοπάτια έχουν εμφανώς μικρότερη καθυστέρηση T 7 8 t "&'( + T *+,&-./"(7 8) + t 23456 =50ps + 750ps (πύλες 3->4->7)+50ps=850ps=0.85ns T 9 8 t "&'( + T *+,&-./"(9 8) + t 23456 =50ps + 1000ps (πύλες 6->5->4->7)+50ps=1100ps=1.1ns C 5. Για να ικανοποιείτε ο περιορισμός του hold που θέτουν τα flip flops αρκεί T :;<= T 8<?(@AB + T <;CA8@AB. Στην περίπτωση μας αυτό πάντα ισχύει καθώς ο χρόνος clkq των flip flops είναι ίσος με το χρόνο hold. 6
Άσκηση 6 Στο σχήμα που ακολουθεί παρουσιάζεται η υλοποίηση ενός επεξεργαστή που εκτελεί μια εντολή σε ένα κύκλο ρολογιού. Ο επεξεργαστής αυτός δε διαθέτει μονάδα ελέγχου και όλα τα σήματα ελέγχου είναι κωδικοποιημένα απευθείας πάνω σε κάθε εντολή. Ολες οι εντολές έχουν την παρακάτω δομή. Το πεδίο RC περιέχει τη διεύθυνση εγγραφής του αρχείου καταχωρητών ενώ τα πεδία RA, RB είναι οι διευθύνσεις ανάγνωσης από το αρχείο καταχωρητών. Προσέξτε πως το αρχείο καταχωρητών εγγράφεται σε κάθε κύκλο ρολογιού, ενώ επιτρέπει την ταυτόχρονη ανάγνωση των τιμών δύο καταχωρητών του στον ίδιο κύκλο. Για παράδειγμα η εκτέλεση μιας εντολής αριθμητικής πράξης R[3]<-R[2]+R[1] (εντολή add $R3, $R2, $R1) κωδικοποιείται ως εξής: 011 (3), 010 (2), 001 (1), 00 (add), 0, 0, *, 00000000000000000 Η εντολή που εκτελειταί σε κάθε κύκλο ρολογιού φορτώνεται από την ΙΜΕΜ χρησιμοποιώντας ως διεύθυνση την τιμή του καταχωρητή PC (program counter). Α) Ποιος είναι ο κωδικός που αντιστοιχεί στην εντολή LD $R6, [$R3+5] (R[6]<-DMEM[R3+5]) η οποία φορτώνει στον καταχωρητή R6 τα δεδομένα της DMEM που αντιστοιχούν στη διεύθυνση που προκύπτει από το άθροισμα των περιεχομένων του καταχωρητή R3 και της immediate σταθεράς 5. Β) Ποιες αλλαγές θα χρειαζόταν το datapath του επεξεργαστή και η κωδικοποίηση των εντολών ώστε να μπορεί να υποστηρίζει εντολές διακλάδωσης υπο-συνθήκη (branch on equal) οι οποίες θα εκτελούσαν την παρακάτω λειτουργία; if ($RA == $RB) PC = PC + 4 + signext(immediate) else PC=PC+4 Η σύγκριση $RA==$RB αναφέρεται στα περιεχόμενα των καταχωρητών RA και RB και όχι στις θέση Α και Β του αρχείου καταχωρητών. Λύση Α) Η εντολή θα είναι: RC RA RB ALU S W Unused Immediate 110 011 000 00 1 0 * 00 0101 Οι τιμές των bits για τον καταχωρητή RB είναι αδιάφορες. 7
Β) Από την ALU, μπορούμε να χρησιμοποιήσουμε την έξοδο zero, η οποία είναι 1 όταν το αποτέλεσμα της πράξης της ALU είναι ίσο με μηδέν, διαφορετικά είναι 0. Επίσης, θα χρησιμοποιήσουμε το ελεύθερο bit, ως σήμα Branch Enable. Θα υπολογίσουμε το AND αυτόν το δύο σημάτων, και θα οδηγήσουμε έναν πολυπλέκτη. Ανάλογα με την τιμή του σήματος, θα επιλέγεται η κατάλληλη τιμή για να αλλάξει ο Program Counter.Θα χρειαστεί και ένας επιπλέον αθροιστής. Η εντολή θα είχε την παρακάτω μορφή: RC RA RB ALU S W BE Immediate αδιάφορες RA_addr RB_addr 01 0 0 1 Immed_value Στο σχήμα φαίνεται η προτεινόμενη μορφή του datapath. 8
Άσκηση 7 Θέλουμε να σχεδιάσουμε ένα κύκλωμα το οποίο θα μπορεί να «θυμάται» τη μέγιστη τιμή που πέρασε από την είσοδο του και να είναι σε θέση να μετράει τον αριθμό των κύκλων που η μέγιστη τιμή παρέμεινε χωρίς να αλλάξει. Η περιγραφή σε VHDL ενός τέτοιου κυκλώματος σας δίνεται έτοιμη. Το κύκλωμα αποτελείται από μία είσοδο των 3 δυαδικών ψηφίων (χωρίς να μετράμε το σήματα του ρολογιού και της αρχικοποιήσης) και δύο εξόδους των 3 και 4 δυαδικών ψηφίων αντίστοιχα. Στην είσοδο inp καταφθάνουν σε κάθε ακμή του ρολογιού διαδοχικά δεδομένα. Στη μία έξοδο, τη max_val, παραμένει η μεγαλύτερη τιμή που έχει περάσει έως τώρα από την είσοδο inp. Αντίστοιχα, στην έξοδο max_count εξάγεται ο αριθμός των κύκλων ρολογιού που η μέγιστη τιμή παραμένει χωρίς να αλλάζει. Για παράδειγμα, αν η είσοδος inp έπαιρνε τις τιμές 5, 6, 4, 3, 1, 0, 3, 7, 4, 6 για 10 διαδοχικούς κύκλους ρολογιού τότε οι έξοδοι max_val και max_count θα έπαιρναν τις εξής τιμες: max_val = 5, 6, 6, 6, 6, 6, 6, 7, 7, 7 max_c-ount = 1, 1, 2, 3, 4, 5, 6, 1, 2, 3 module find_and_count_minimum( input logic clk,rst_n, input logic [2:0] in, output logic [3:0] max_count, output logic [2:0] max_val); logic [3:0] count; logic [2:0] current_max; assign max_count = count; assign max_val = current_max; always_ff @(posedge clk, negedge rst_n) if( rst_n ==0) count <= 0; current_max <= 0; else if(in > current_max) //new max value found current_max <= in; count <= 1; else // new value less than current maximum count <= count + 1; module Αντιστοιχίστε την περιγραφή σε VHDL στο κύκλωμα που σας δίνεται μερικώς ολοκληρωμένο πιο κάτω. 9
Λύση 10
Άσκηση 8 Στην άσκηση αυτή καλείστε να σχεδιάσετε έναν επεξεργαστή ο οποίος εκτελεί σε διαδοχικούς κύκλους ρολογιού μόνο μία εντολή και πάντα την ίδια. Η εντολή καλείτε με την κωδική ονομασία subleq (SUbtract and Branch if Less than or EQual to zero) και η λειτουργία της ορίζεται ως εξής: subleq a, b, c ; Mem[b] = Mem[b] - Mem[a] ; if (Mem[b] 0) goto c Η εκτέλεση της εντολής απαιτεί την ανάγνωση 3 τελεστών, a, b και c οι οποίοι βρίσκονται τοποθετημένοι σε διαδοχικές θέσεις μνήμης στη μνήμη εντολών. Κατά την εκτέλεση της εντολής διαβάζονται τα δεδομένα που βρίσκονται στις διευθύνσεις a και b της μνήμης δεδομένων και αφού υπολογίστει η διαφορά τους, το αποτέλεσμα εγγράφεται στη θέση μνήμης με διεύθυνση b. Αν η διαφορά που υπολογίστηκε είναι μικρότερη του 0 τότε η εκτέλεση του πρόγράμματος μεταβαίνει στη θέση μνήμης (της μνήμης εντολών) που δείχνει η διεύθυνση c. Αν όχι τότε η εκτέλεση μεταβαίνει στην αμέσως επόμενη διεύθυνση. Θέτωντας το c ίσο με την επόμενη προς εκτέλεση εντολή ουσιαστικά απενεργοποιούμε το άλμα υπο-συνθήκη. Για παράδειγμα ο κώδικας subleq A0, B0 subleq A1, B1, 1000 Θα ήταν αποθηκευμένος στη μνήμη εντολών ως εξής: 0000: A0 0001: B0 0010: 0011 0011: A1 0100: B1 0101: 1000 1 η εντολή 2 η εντολή Εφόσον η πρώτη εντολή δε θέλει να εκτελέσει κάποιο άλμα στη θέση μνήμης 0010 βρίσκεται η διεύθυνση της επόμενης προς εκτέλεσης εντολής, δηλαδή η 0011. Στη μνήμη εντολών δεν αποθηκεύεται κάποια πληροφορία σχετικά με την εντολή (είναι πάντα η ίδια εντολή subleq) αλλά μόνο οι διευθύνσεις a, b, και c σε 3 διαδοχικές θέσεις για κάθε εντολή. H λειτουργία του επεξεργαστή φαίνεται στον παρακάτω ψευδο-κώδικα. program_counter = 0 while (program_counter >= 0): a = inst_memory[program_counter] b = inst_memory[program_counter+1] c = inst_memory[program_counter+2] if (a < 0 or b < 0): program_counter = -1 else: 11
data_memory[b] = data_memory[b] - data_memory[a] if (data_memory[b] > 0): program_counter = program_counter + 3 else: program_counter = c Οι διευθύνσεις a, b και c έχουν εύρος 16 δυαδικών ψηφίων. Οργανώστε τη λειτουργία του επεξεργαστή σε μια FSMD σύμφωνα με τον παραπάνω αλγόριθμο. Το πλήθος των κύκλων που απαιτείται για την εκτέλεση της κάθε εντολής είναι δικιά σας επιλογή. Για την υλοποίηση που διαλέξατε καλείστε να δώσετε και ένα διάγραμμα που να δείχνει την οργάνωση του datapath του επεξεργαστή σας (όχι της FSM) όπου θα φαίνονται καθαρά οι καταχωρητές που χρησιμοποιήσατε, η μνήμη δεδομένων και εντολών, οι μονάδες υπολογισμού και όσοι πολυπλέκτες χρειάζονται ανάλογα με την οργάνωση που ακολουθήσατε. Λύση Η σχεδίαση του επεξεργαστή μπορεί να χωριστεί σε 3 τμήματα: a) προσπέλαση των παραμέτρων a,b,c από τη μνήμη εντολών (Instruction Memory, Inst_Mem), b) προσπέλαση των δεδομένων A,B από τη μνήμη δεδομένων (Data_Mem), c) εκτέλεση της αφαίρεσης και εγγραφή του αποτελέσματος πίσω στη μνήμη δεδομένων, d) επιλογή της νέας διεύθυνσης του Program counter. a) Η προσπέλαση της μνήμης εντολών μπορεί να γίνει με δύο τρόπους. Εφόσον τα δεδομένα που θέλουμε να προσπελάσουμε βρίσκονται στη θέση στην οποία δείχνει ο program counter (pc) και στις δύο επόμενες (pc+1, pc+2), μπορούμε να έχουμε αυτές τις τρεις τιμές στην είσοδο ενός πολυπλέκτη, ο οποίος επιλέγει κάθε φορά ποια διεύθυνση θα διαβαστεί από τη μνήμη εντολών. Μια δεύτερη προσέγγιση είναι η χρήση ενός ενδιάμεσου σήματος, του pc_temp, το οποίο καθορίζει ποια θέση μνήμης θα διαβαστεί. Στην αρχή εκτέλεσης της κάθε εντολής παίρνει την τιμή του program counter (για την προσπέλαση του a), και στη συνέχεια αυξάνεται κατά 1 μετά από κάθε προσπέλαση (για την προσπέλαση των b,c). b) Η προσπέλαση της μνήμης δεδομένων γίνεται με τη χρήση των διευθύνσεων a,b, επιλέγοντας κάθε φορά αυτή που θέλουμε να διαβάσουμε μέσω ενός πολυπλέκτη. Η προσπέλαση της μνήμης δεδομένων μπορεί να γίνει παράλληλα με αυτή της μνήμης εντολών εφόσον έχουμε αποθηκεύσει ήδη τη διεύθυνση μνήμης που χρειαζόμαστε (a,b,c). Για παράδειγμα, καθώς διαβάζουμε το b από τη διεύθυνση εντολών μπορούμε ήδη να διαβάσουμε το data_mem[a] από τη μνήμη δεδομένων, αφού έχουμε ήδη αποθηκεύσει το a στον προηγούμενο κύκλο. c) Μετά την προσπέλαση της μνήμης δεδομένων εκτελούμε την πράξη B-A και αποθηκεύουμε το αποτέλεσμα στη μνήμη. Ο πολυπλέκτης ο οποίος οδηγεί τη διεύθυνση της μνήμης δεδομένων πρέπει να επιλέξει το b, καθώς θέλουμε να αποθηκεύσουμε το αποτέλεσμα στο data_mem[b]. d) Τέλος, ο Program counter παίρνει τη νέα του τιμή με βάση τις τιμές των a,b, το πρόσημο της διαφοράς και της τιμής του c. Παρακάτω φαίνονται οι δύο υλοποιήσεις με τις αντίστοιχες FSMD. 12
13
Άσκηση 9 Στην άσκηση αυτή θα επιχειρήσουμε να δημιουργήσουμε κύκλωμα που να υλοποιεί ένα μηχανισμό απεικόνισης «διευθύνσεων» (8-bit) μέσω ενός αρχείου καταχωρητών. Το κύκλωμα διαχειρίζεται ένα αποθηκευτικό χώρο 8 θέσεων, μέσα στον οποίο φυλλάσει «διευθύνσεις» που δίδονται ως είσοδοι. Για κάθε θέση, φυλάσσει την πληροφορία εαν η θέση είναι σε χρήση. H διεπαφή του κυκλώματος φαίνεται στο σχήμα που ακολουθεί. Το σύστημα διαθέτει 8 θέσεις αποθήκευσης για «διευθύνσεις» πλάτους 8 bits (πεδίο DATA στο παραπάνω σχήμα), για καθεμία από τις οποίες υπάρχει ένδειξη για το εαν είναι σε χρήση ή όχι (πεδίο VALID στο παραπάνω σχήμα). - Ο χρήστης εισάγει μια «διεύθυνση» προς αποθήκευση μέσω των εισόδων (DATA-IN[7:0]), έχοντας θέσει το σήμα DATA-ALLOC. Το κύκλωμα αναζητά ελεύθερη θέση για χρήση. o Εφόσον βρει, σημειώνει ότι η θέση αυτή είναι σε χρήση (θέτοντας το πεδίο VALID), αποθηκεύει την είσοδο, και στην έξοδο (DATA-OUT, πλάτους 3 bits) αναφέρει τον αριθμό αυτής της θέσης. Στο παραπάνω σχήμα, η θέση 4 είναι ελεύθερη για χρήση, οπότε η έξοδος θα έπρεπε να αναφέρει τον αριθμό 4. o Εαν δεν βρεθεί ελεύθερη θέση, τότε το κύκλωμα θέτει το σήμα FULL. Καμία από τις ήδη αποθηκευμένες τιμές δεν επηρεάζεται. - Για να ελευθερώσει θέση, ο χρήστης θέτει το σήμα DATA-FREE, και στην είσοδο DATACONSUME παρέχει τον αριθμό της θέσης που θέλει να αποδεσμεύσει. - Η αρχική κατάσταση του κυκλώματος είναι: FULL=0, VALID=0 για τις 8 θέσεις αποθήκευσεις. Περιγράψτε τη λειτουργία του παραπάνω κυκλώματος σε VHDL. Αν το επιθυμείτε καλό είναι να δώσετε πρώτα μια βασική περιγραφή της λειτουργίας του κυκλώματος που υλοποιήσατε είτε περιγραφικά είτε με κάποιο σχήμα συνοδευτικά με τον κώδικά της VHDL. 14
Λυση Για απλότητα στην επίλυση, θα θεωρήσουμε ότι δεν επιτρέπεται ταυτόχρονα δέσμευση (DATA_ALLOC) και αποδέσμευση (DATA_FREE) θέσης. 1. Εύρεση πρώτης ελεύθερης θέσης Σύμφωνα με την εκφώνηση, valid[i]=0 σημαίνει ότι η θέση i είναι ελεύθερη. Για να βρούμε την πρώτη valid[i] θέση χρησιμοποιούμε έναν 8:1 Priority Encoder ως εξής: Ο Priority Encoder (PE) παίρνει ως είσοδο (input) ένα 8-bit vector και επιστρέφει έξοδο (output) ένα 8-bit vector, στο οποίο υπάρχει το πολύ ένα '1' στο bit εκείνο όπου βρίσκεται το πρώτο '1' στην input. Πχ: Αν ο PE δε βρεί κανένα '1' στο input, τότε ενεργοποιεί το σήμα FULL. Παρατηρήστε ότι η είσοδος του PE είναι το ανεστραμμένο valid (αναζητούμε την πρώτη ελεύθερη θέση, άρα το πρώτο '0'). 2. Εμφάνιση στην έξοδο και εγγραφή στο register file Η έξοδος DATA_OUT είναι η weighted binary κωδικοποίηση της πρώτης ελεύθερης θέσης, άρα αρκεί ένας 8-to-3 decoder για τη μετατροπή του: Σε περίπτωση που το σήμα δέσμευσης είναι ενεργοποιημένο (DATA_ALLOC='1'), πρέπει να αποθηκεύσουμε τα δεδομένα εισόδου (DATA_IN) στην αντίστοιχη θέση (data[i] = DATA_IN): Με παρόμοιο τρόπο θα πρέπει να μαρκάρουμε τη θέση αυτή ως κατειλλημένη, δηλ. valid[i] = '1'. 15
3. Αποδέσμευση θέσης Η αποδέσμευση θέσης είναι πολύ πιο απλή διαδικασία, κι απαιτεί μόνο να αποκωδικοποιήσουμε τη θέση που αποδεσμεύεται (DATA_CONSUME) και να μαρκάρουμε τη θέση αυτή ως ελεύθερη, δηλ. valid[i] = '0'. Ο μηδενισμός των δεδομένων που είναι αποθηκευμένα στη θέση αυτή (data[i]) δεν είναι απαραίτητος. Η περιγραφή του κυκλώματος σε System Verilog παρακάτω: module mapper ( input logic clk, input logic rst, // Allocation Requests input logic [7:0] data_in, input logic data_alloc, output logic full, output logic [2:0] data_out, // Free-up input logic data_free, input logic [2:0] data_consume); logic [7:0] valid; // 8 positions logic [7:0] data; // 8 positions // Helpful intermediate signals logic [7:0] first_free_pos; logic [2:0] free_binary; logic full_s; // Request Outputs ------------------------------------------------------- assign data_out = free_binary; assign full = full_s; // Full & Free positions ---------------------------------------------- // Priority encoder (finds the first NON-valid position & sets full) always_comb full_s = 1'b0; first_free_pos = 0; if (valid[0] == 1'b0) first_free_pos[0] = 1'b1; else if (valid[1] == 1'b0) first_free_pos[1] = 1'b1; else if (valid[2] == 1'b0) first_free_pos[2] = 1'b1; else if (valid[3] == 1'b0) first_free_pos[3] = 1'b1; 16
else if (valid[4] == 1'b0) first_free_pos[4] = 1'b1; else if (valid[5] == 1'b0) first_free_pos[5] = 1'b1; else if (valid[6] == 1'b0) first_free_pos[6] = 1'b1; else if (valid[7] == 1'b0) first_free_pos[7] = 1'b1; else full_s = 1'b1; // Decode first empty-position (one-hot to weighted binary) assign free_binary = (first_free_pos==8'b00000001)? 3'b000 : (first_free_pos==8'b00000010)? 3'b001 : (first_free_pos==8'b00000100)? 3'b010 : (first_free_pos==8'b00001000)? 3'b011 : (first_free_pos==8'b00010000)? 3'b100 : (first_free_pos==8'b00100000)? 3'b101 : (first_free_pos==8'b01000000)? 3'b110 : 3'b111; // Default (111) asserted when first_free_pos[7]=1 b1 OR first_free_pos = 8 b00000000 (in the second case, it's full) // Valid + Data Registers ------------------------------------------------ always_ff @(posedge clk or posedge rst) if (rst == 1'b1) valid <= 8'b00000000; else // Does NOT support simultaneous Allocation AND Freeing if (data_alloc == 1'b1 && full_s == 1'b0) // should store new request only when not full valid[free_binary +: 1] <= 1'b1; data[free_binary +: 1] <= data_in; else if (data_free == 1'b1) // free-up a position (only set valid to '0', no need to reset data) valid[data_consume +: 1] <= 1'b0; module 17
Άσκηση 10 Στο παρακάτω σχήμα σας δίνεται η υλοποίηση ενός elastic buffer ο οποίος συνδέει δύο κανάλια που ακολουθούν μεταφορά δεδομένων με χειραψία ready/valid. Με άλλα λόγια στον ένα κύκλο μπορεί να εγγράψει στον καταχωρητή του μια νέα έγκυρη τιμή από τα αριστερά (δηλαδή όταν valid_in=1) μόνο όταν αυτός είναι άδειος, δηλαδή ready_out=1.ενώ από τον επόμενο κύκλο δε μπορεί να δεχθεί νέα δεδομένα, προτού τα ήδη αποθηκευμένα δεδομένα διαβαστούν προς το κανάλι στα δεξιά του (δηλαδή όταν valid_out=ready_in=1). Στη συνέχεια θέλουμε να φτιάξουμε την παρακάτω συνδεσμολογία όπου ένας elastic buffer τροφοδοτεί δύο άλλους όμοιους elastic buffers. Η δουλειά μας είναι να σχεδιάσουμε το κύκλωμα σε SystemVerilog το οποίο θα διαμοιράζει τις τιμές του elastic buffer Α στους B και C διατηρώντας πλήρως τη λειτουργία του πρωτοκόλλου χειραψίας ready/valid. Καλείστε να σχεδιάσετε δύο εκδοχές του κυκλώματος αυτού: 1) Οι τιμές που εμφανίζονται στον Α μοιράζονται στους B και C μόνο όταν είναι και οι δύο διαθέσιμοι. Με άλλα λόγια καμία μετακίνηση δε συμβαίνει αν και δύο elastic buffers Β και C δεν εμφανίσουν ready_out=1. 2) Οι τιμές του Α μοιράζονται στον πρώτο διαθέσιμο elastic buffer Β και C. Αρκεί δηλαδή το ready_out ενός από τους δύο να είναι 1 ώστε ο κατάλληλος elastic buffer να λάβει τα δεδομένα του A. Κατά την μετακίνηση των δεδομένων, τα δεδόμενα διαγράφονται από τον A και εγγράφονται σε έναν μόνο από τους δύο elastic buffer. (Σε περίπτωση που και οι δύο είναι διαθέσιμοι επιλέξτε έναν με μεγαλύτερη προτεραιότητα) 18
Λύση Περίπτωση 1 assign data_to_b = data_from_a; assign data_to_c = data_from_a; //1st Case //Both B and C will get Data, else none. assign ready_to_a = ready_from_b & ready_from_c; assign valid_to_b = valid_from_a & ready_from_b & ready_from_c; assign valid_to_c = valid_from_a & ready_from_b & ready_from_c; Περίπτωση 2 assign data_to_b = data_from_a; assign data_to_c = data_from_a; //2nd Case //Only B or C will get Data, given priority to B assign ready_to_a = ready_from_b ready_from_c; assign valid_to_b = valid_from_a; assign valid_to_c = valid_from_a & ~ready_from_b; 19
Άσκηση 11 Για τον παρακάτω αλγόριθμο σε C σχεδιάστε μια FSMD που τον υλοποιεί σωστά σε υλικό. Λυση 20
Για να μειωθεί η καθυστέρηση μπορούμε να εισάγουμε μία επιπλέον μεταβλητή η οποία θα υπολογίζει τη διαφορά temp1-temp2 ή temp2-temp1. Τότε θα είχαμε: O ισοδύναμος αλλαγμένος κώδικας σε αυτή την περίπτωση θα ήταν ο παρακάτω: TEMP_FUNC: while(1){ while(!go); busy = 1; i = 0; while(i<256){ temp1 = A[i]; i++; temp2 = A[i]; if(temp1 > temp2){ sum = sum + (temp1-temp2); }else{ sum = sum + (temp2-temp1); } i++; } Val = sum; busy = 0; } 21
Άσκηση 12 Σχεδιάσαμε το παρακάτω κύκλωμα και δεν είμαστε ευχαριστημένοι από την ελάχιστη περίοδο του ρολογιού στην οποία μπορούμε να το λειτουργήσουμε. Ποια είναι η ελάχιστη περίοδος ρολογιού που επιτρέπει στο κύκλωμα μας να λειτουργεί σωστά. Θεωρήστε ότι T CLKQ = 0.5 ns και T SETUP =0.5ns. Αποφασίζουμε να χρησιμοποιήσουμε επιπλέον pipeline καταχωρητές ώστε να μειώσουμε την ελάχιστη περίοδο ρολογιού στα 6 ns. Σε ποια σημεία θα προσθέτατε pipeline καταχωρητές για να πετύχετε αυτό το στόχο; Λυση Για να λειτουργεί το κύκλωμα χωρίς timing violations θα πρέπει για κάθε μονοπάτι να ισχύει η σχέση (1). Τ Τ FGHIJ T 8<?( + d "-*M (1) Οπότε για να βρούμε την ελάχιστη επιτρεπτή περίοδο πρέπει να βρούμε το μονοπάτι με το μεγαλύτερο delay. Απ όλα τα μονοπάτια του παραπάνω κυκλώματος (από flip-flop σε flip-flop) βρίσκουμε ότι η χειρότερη καθυστέρηση είναι 2+1+5+4=12ns. 22
Τ 0,5 0,5 + 12 T 13ns Οπότε η ελάχιστη περίοδος είναι 13ns. Για να είναι η τελική περίοδος 6ns, θα πρέπει d "-*M Τ T 23456 T 8<?( d "-*M 6 0,5 0,5 = 5ns Άρα η χειρότερη καθυστέρηση δεν θα πρέπει να ξεπερνάει τα 5ns. Για να το πετύχουμε αυτό πρέπει να εισάγουμε νέους καταχωρητές προσέχοντας όμως να μην χαλάσουμε τον χρονισμό των σημάτων και άρα χαλάσουμε τη λειτουργία του αρχικού κυκλώματος. Ζωγραφίζουμε τις 2 γραμμές που φαίνονται παρακάτω με κόκκινο χρώμα γύρω από το υποκύκλωμα με καθυστέρηση 5ns ώστε η χειρότερη καθυστέρηση να είναι 5ns. 23
Σε κάθε σημείο που η κόκκινη γραμμή τέμνει την μαύρη γραμμή εισάγουμε έναν καταχωρητή και το τελικό κύκλωμα μοιάζει με το παρακάτω. Όπως βλέπουμε η μεγαλύτερη καθυστέρηση είναι αυτή των 5ns και η λειτουργία του κυκλώματος είναι η ίδια. 24