ΠΛΕ- 027 Μικροεπεξεργαστές 4ο μάθημα: γλώσσα περιγραφής υλικού Verilog Αρης Ευθυμίου
Τι είναι η γλώσσα Verilog Γλώσσα περιγραφής υλικού (hardware descripjon language) Επιτρέπει τη περιγραφή (μοντελοποίηση) ψηφιακών συστημάτων Γιατί όχι διαγράμματα κυκλωμάτων, πίνακες αλήθειας, χάρτες Karnaugh,... ; Ταχύτητα ανάπτυξης μοντέλου Δυνατότητα απευθείας προσομοίωσης Δυνατότητα «σύνθεσης» υλικού: μετάφρασης σε «δίκτυο» λογικών πυλών και βελτιστοποίησης (βλ. χάρτες Karnaugh κτλ) ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 2
Τι είναι (2) Είναι γλώσσα προγραμματισμού; Ναι όταν χρησιμοποιείται για έλεγχο/οδήγηση προσομοίωσης ενός συστήματος (test- bench): παροχή εισόδου, έλεγχος εξόδου Οχι όταν περιγράφει πραγματικό υλικό Τρία επίπεδα περιγραφής: Επίπεδο διαρθρωτικό (structural): περιγράφει τις συνδέσεις μεταξύ λογικών πυλών ή άλλων μονάδων Υποσύνολο συνθέσιμης περιγραφής «συμπεριφοράς» (synthesizable behavioural) Υποσύνολο μή- συνθέσιμης περιγραφής «συμπεριφοράς» (non- synthesizable behavioural) για test- benches, αρχικά μοντέλα συστημάτων ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 3
Τυπική χρήση SYNTHESIZABLE VERILOG (DESIGN) BEHAVIOURAL VERILOG (TEST-BENCH) LOGIC SYNTHESIS TOOL SIMULATOR GATE-LEVEL VERILOG (THE NETLIST) ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 4
Τιμές Βασικό δομικό κομμάτι είναι το bit με 4 «λογικές» τιμές: 0, 1 προφανώς! x δεν ξέρουμε την τιμή (ή δεν μας ενδιαφέρει) z δεν οδηγείται (τρι- κατάστατη οδήγηση) Οι τιμές μεταδίδονται μέσω καλωδίων nets Κρατούνται σε καταχωρητές registers Συνδιάζονται με τελεστές δημιουργώντας λογικές εκφράσεις Οι εκφράσεις μπορούν να εκχωριθούν (assign) σε καλώδια ή καταχωρητές ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 5
Καλώδια Τα καλώδια αναπαριστούν συνδέσεις μονάδων Υπάρχουν διάφοροι τύποι, αλλά το πιο κοινό είδος ονομάζεται wire Δεν κρατούν τιμές απλά τις μεταφέρουν wire z; assign z = x & y; Αναθέσεις τιμών σε καλώδια γίνονται μόνο μία φορά Οποιαδήποτε αλλαγή στα x,y εμφανίζεται αμέσως στο z ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 6
Καταχωρητές (reg) Ενας reg κρατάει μια τιμή που του εκχωρείται μέχρι την επόμενη εκχώριση όπως μια μεταβλητή σε γλώσσα προγραμματισμού Χρησιμοποιείται για να περιγράψει στοιχεία αποθήκευσης flip- flops, μανταλωτές (latches), μνήμες, Χρησιμοποιείται και για συνδιαστική λογική, γιατί είναι πιο βολικός από το τύπο net αλλά θέλει προσοχή στη χρήση/σύνταξη για να μην υπονοήσει (infer) στοιχείο αποθήκευσης ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 7
Διανύσματα Ενα bit δεν μπορεί να κάνει πολλά! Συνήθως χρειαζόμαστε μια ομάδα από bits, όπου η θέση καθενός έχει σημασία (π.χ. αναπαράσταση ενός αριθμού) λέγονται διανύσματα (vectors) υπάρχουν και σε reg και σε wire Περιγραφή διανύσματος: [ upper : lower ] Καλύτερα upper >= lower lower μπορεί να είναι οποιοσδήποτε αριθμός (όχι υποχρεωτικά 0) Η Verilog συμπληρώνει με 0 στα αριστερά ότι bit λείπουν κατά την ανάθεση Νεώτερες εκδόσεις της γλώσσας προσθέτουν προσημασμένους τύπους reg, wire ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 8
Διανύσματα - παράδειγμα wire [31:0] data; reg [31:16] upper_half; reg [15:0] lower_half; always @(data) begin lower_half = data[15:0]; upper_half = data[31:0]; end `define WORD_RANGE 31:0 `define LO_RANGE 15:0 `define HI_RANGE 31:16 wire [`WORD_RANGE] data; reg [`HI_RANGE] upper_half; reg [`LO_RANGE] lower_half; // this is a comment ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 9
Oδηγίες (direcjves) μεταφραστή Ορισμοί σταθερών και macro Ενσωμάτωση αρχείων Μετάφραση υπό συνθήκη Οδηγία κλίμακας χρόνου `define INCLUDE 1 `ifdef INCLUDE `include my_header.v `endif `timescale 1ns / 10ps // reference time unit 1ns, precision 10ps // values must be 1, 10 or 100 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 10
Σταθερές - literals Οι σταθερές συνήθως έχουν δηλωμένο μέγεθος και ξεκινούν με size base size σε bits, b binary, o octal, h hexadecimal, d decimal Το x ή z θέτει 1 bit για b, 3 bit για o, 4 bit για h Αν το πιο σημαντικό bit είναι 0, x or z, επεκτείνεται αυτόματα μέχρι το αριστερό άκρο wire [31:0] data1, [15:0] data2; wire enable; tri [31:0] bus; // tri declares a tri-state wire, i.e. can be [0,1,z] assign enable = 1 b0; // b = binary assign data1 = 32 h0000_0000; // h = hex (underscore is ignored, helps visually) assign data2 = 16 d256; // d = decimal assign bus = 32 bz; // assigns z to all 32 bits of the bus assign data2 = 16 b0101 // assigns 0000000000000101 to data2 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 11
Συνένωση διανυσμάτων Για συνένωση διανυσμάτων, χρησιμοποιούμε: { vector1, vector2,..., vectorn } Για συνένωση n φορές του ίδιου διανύσματος, χρησιμοποιούμε: { n { vector } } Μπορεί να χρησιμοποιηθεί και στο αριστερό μέρος μιας ανάθεσης wire [31:0] data1, [15:0] data2, [3:0] data3; wire a, b, c, d; assign data3 = 4 b0011; assign data2 = {4{data3}}; // assigns 0011001100110011 to data2 assign data1 = {16 d0, data2}; // assigns 00000000000000000011001100110011 to data1 assign {a,b,c,d} = data3; ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 12
Τελεστές ArithmeJc: + - * / % Logical: &&! Bitwise: & ^ ~ ~^ Comparison: ==!= > < >= <= ReducJon: & ~& ~ ^ ~^ Shi : << >> ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 13
Αριθμητικές πράξεις wire [3:0] x, y, sum, diff, prod, div, mod; assign x = 4 b1100; // 12 assign y = 4 b0011; // 3 assign sum = x + y; // sum gets 15 assign prod = x * y; // prod gets lower 4 bits of 8 b10_0100, i.e. 4 b0100 assign div = x / y; // div gets 4 assign mod = x % y; // mod gets 0 Αν οποιοδήποτε bit τελεστέου έχει x ή z, όλα τα bit του αποτελέσματος είναι x Αν το αποτέλεσμα έχει μεγαλύτερο μήκος σε bits, μόνο τα λιγότερο σημαντικά bits εκχωρούνται αν γίνει υπερχείλιση,... wire [3:0] x, y, sum, carry; assign x = 4 b1100; // 12 assign y = 4 b0100; // 4 assign sum = x + y; // 4 b0000 assign {carry, sum} = x + y; // 5 b1_0000 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 14
Συγκρίσεις, λογικές πράξεις Συγκρίσεις υποθέτουν ότι οι τελεστέοι είναι προσημασμένοι ακέραιοι Οι λογικές πράξεις υποθέτουν ότι οι τελεστέοι είναι 1 bit (boolean) υπάρχουν ειδικοί τελεστές για δυαδικές πράξεις wire [3:0] x, y, z; assign x = 4 b1100; // 12 assign y = 4 b0011; // 3 assign z = (((x == 4 d0) && (y > x))!(y < 4 d10)) ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 15
Δυαδικές (λογικές) πράξεις Bitwise AND Bitwise OR Bitwise XOR Bitwise NOT & ^ ~ wire[3:0] a, b, z1, z2, z3, z4; assign a = 4 b1100; // 12 assign b = 4 b0111; // 7 assign z1 = a & b; // z1 gets 0100 assign z2 = a b; // z2 gets 1111 assign z3 = a ^ b; // z3 gets 1011 assign z4 = ~a; // z4 gets 0011 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 16
Τελεστές αναγωγής (reducjon) Αναγωγική AND / NAND Αναγωγική OR / NOR Αναγωγική XOR / XNOR &expr ~&expr expr ~ expr ^expr ~^expr Κάνει τη λογική πράξη σε όλα τα bit ενός διανύσματος, μεταξύ τους wire[3:0] a, b; wire z1, z2, z3, z4, z5; assign a = 4 b1100; assign b = 4 b0111; assign z1 = &a; // z1 gets (1 & 1 & 0 & 0) = 0 assign z2 = &a[3:2]; // z2 gets (1 & 1) = 1 assign z3 = b; // z3 gets (0 1 1 1) = 1 assign z4 = ^a; // z4 gets (1 ^ 1 ^ 0 ^ 0) = 0 assign z5 = ~^b; // z5 gets ~(0 ^ 1 ^ 1 ^ 1) = ~(1) = 0 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 17
Τελεστές ολίσθησης Αριστερή ολίσθηση << Δεξιά ολίσθηση >> Συμπληρώνονται με 0 wire [3:0] a, b, z1, z2, z3, z4; assign a = 4 b1100; assign b = 4 b0111; assign z1 = a << 1; // z1 gets 1000 assign z2 = a >> 2; // z2 gets 0011 assign z3 = a >> 5; // z3 gets 0000 assign z4 = a << 5; // z4 gets 0000 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 18
Ενότητες (modules) Η ενότητα είναι το δομικό στοιχείο κατασκευής ιεραρχικών κυκλωμάτων μοιάζουν με κλάσεις σε ΟΟ γλώσσες προγραμματισμού Αφού οριστεί, μια ενότητα μπορεί να χρησιμοποιηθεί πολλές φορές ως συστατικό άλλων ενοτήτων υπόσταση - instance Για παράδειγμα μια λογική πύλη AND αποτελεί μια ενότητα Η υψηλότερου επιπέδου (top level) ενότητα αποτελεί το (συνολικό) κύκλωμα δέν υπάρχουν instances της ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 19
Επικοινωνία ενοτήτων Οι υποστάσεις ενοτήτων επικοινωνούν μέσω θυρών (port) Κάθε θύρα είναι ένα ονομαζόμενο σήμα ή διάνυσμα σημάτων Θύρες εισόδου πρέπει να συνδεθούν με (οδηγηθούν από) regs ή wires Θύρες εξόδου οδηγούν wires της (υπερ)ενότητας στην οποία τοποθετείται μια υπόσταση της ενότητας ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 20
Δηλώσεις ορισμάτων/θυρών Τρία είδη: Σήματα/διανύσματα εισόδου εξόδου αμφίδρομα (bidirecjonal) module foo (x, y, z); input wire [6:0] x; // vector of input wires output wire [13:0] y; // vector of output wires inout tri z; // tri-state input/output assign y = {x, {7{z}}; assign z = y[0]? 1 bz : x[0]; // drive z with x[0] if y[0] is true endmodule // P.S. Can you see a problem with the circuit above? ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 21
Υποστάσεις instances module foo (x, y); input wire x; output wire y; assign y = ~x; endmodule module bar (a, b); input wire a; output wire b; Instance name module foo (x, y); input wire x; output wire y; assign y = ~x; endmodule module bar (a, b); input wire a; output wire b; foo u_foo(a, b); // positional args endmodule foo u_foo(.x(a),.y(b) ); // named args endmodule Η υπόσταση χρειάζεται ένα όνομα Οι πόρτες συνδέονται είτε με τη σειρά ορισμού, είτε, καλύτερα, με τα ονόματα θυρών ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 22
Διεργασίες Τα κυκλώματα δεν «υπολογίζουν» σειριακά όπως τα προγράμματα όλα τα τμήματα λειτουργούν ταυτόχρονα Τα συνδιαστικά κυκλώματα ανταποκρίνονται σε κάθε αλλαγή εισόδου, ξανα- υπολογίζοντας την έξοδό τους Τα ακολουθιακά κυκλώματα ανταποκρίνονται στις μεταβολές του σήματος ρολογιού Η Verilog παρέχει δομές διεργασιών για να χειριζόμαστε αυτές τις δύο κατηγορίες κυκλωμάτων ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 23
Διεργασίες Κάθε διεργασία έχει επικεφαλίδα (header) και κύριο σώμα (body) Η επικεφαλίδα ορίζει μια λίστα από σήματα τα οποία η διεργασία πρέπει να παρακολουθεί για αλλαγές τιμών (sensijvity list) Το κύριο σώμα ορίζει τί πρέπει να γίνει όταν ένα σήμα εισόδου αλλάξει σε απλές περιπτώσεις είναι ένα σύνολο εντολών που υπολογίζει το σήμα εξόδου Εκχωρίσεις τιμών επιτρέπονται μόνο σε reg μέσα σε διεργασίες ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 24
Συνδιαστικές διεργασίες module NAND (x, y, z); input wire x, y; output reg z; always @(x or y) z = ~(x & y); endmodule module mux(a, b, c, q); input a,b,c; output q; reg q; always @( a or b or c ) if (c == 1 b1) q = a; else q = b; endmodule module decode_2_to_4 (x, z); input wire [1:0] x; output reg [3:0] z; always @(x) begin : decode_proc z[0] = (x == 2 b00); z[1] = (x == 2 b01); z[2] = (x == 2 b10); z[3] = (x == 2 b11); end endmodule // If items are missing from // the sensitivity list, the // logic will not simulate // correctly. always @(x) z = ~(x & y); ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 25
Ακολουθιακές διεργασίες module D_LATCH (d, ck, q); input d, ck; output q; reg q; always @( d or ck ) if (ck == 1 b1) q = d; endmodule module D_FF(d, ck, q); input d, ck; output q; reg q; always @( posedge ck ) q <= d; endmodule Η επικεφαλίδα περιέχει μια ακμή ρολογιού, ή έναν αριθμό από σήματα, αλλά δεν εκχωρούνται τιμές σε όλες τις περιπτώσεις υπονοείται μανταλωτής (latch) συχνό λάθος. ο χρήστης ήθελε συνδιαστική διεργασία ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 26
Αναθέσεις τιμών Τρία είδη ανάθεσης τιμών: Συνεχόμενη (conjnuous): εντολή assign η έξοδος ξανα- υπολογίζεται αυτόματα όταν αλλάζει μία από τις εισόδους μόνο για καλώδια: wire, tri, αναθέσεις σε καλώδια μόνο με assign ή ως έξοδοι modules Φραγής (blocking): με τον τελεστή = όπως σε γλώσσες προγραμματισμού: η σειρά εκτέλεσης έχει σημασία π.χ. a = #5 b; Μή- φραγής (non- blocking): με τον τελεστή <= η σειρά δεν έχει σημασία π.χ. a <= #5 b; καθυστέρηση ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 27
Φραγή και αναθέσεις Στις αναθέσεις φραγής, η επόμενη εντολή εκτελείται αφού γίνει η ανάθεση (και περάσει η καθυστέρηση, #.. αν υπάρχει) Αντίθετα στις αναθέσεις μή- φραγής, η επόμενη εντολή εκτελείται «ταυτόχρονα» με την ανάθεση Παράδειγμα (έστω a = 0, b=1) a = b; c = a + 1; a <= b; c <= a + 1; Αποτέλεσμα: a = 1, c = 2 Αποτέλεσμα: a = 1, c = 1 ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 28
Αναθέσεις τιμών - κανόνες Σε ακολουθιακές διεργασίες δεν χρησιμοποιούμε αναθέσεις φραγής Πρέπει να υπάρχει μία μόνο διεργασία που εκχωρεί τιμή σε ένα reg Σε συνδιαστικές διεργασίες χρησιμοποιούμε αναθέσεις φραγής always @( posedge ck or posedge rst) if (rst == 1 b1) q <= 1 b0; else q <= d; always @(x or y) begin : logic_proc z = (x == 2 b00); if (y == 1 b1) z = x[0]; end ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 29
Εντολές ελέγχου Υπάρχουν εντολές ελέγχου if- then- else, case, και επαναλήψεων: while, for, forever Χρησιμοποιούμε begin end για περισσότερες από μία εντολή οι περιπτώσεις της case, δεν χρειάζονται break σαν την C και αν χρειάζονται περισσότερες εντολές πρέπει να περικλείονται σε begin end. reg [N-1:0] out; always @(*) begin case (sel) 0: out <= #(`MUX_D) in0; 1: out <= #(`MUX_D) in1; endcase end ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 30
Τμήματα inijal Εκτός από τα τμήματα always, υπάρχει ένας άλλος τρόπος για περιγραφή διεργασιών με την εντολή inijal Αυτές οι διεργασίες δεν χρησιμοποιούνται για σύνθεση κυκλωμάτων αλλά μόνο για μοντελοποίηση υψηλού επιπέδου και οδήγηση προσομοίωσης (test- bench) Χρήσεις: αρχικοποίηση reg σημάτων καλύτερα να χρησιμοποιεί κανείς ένα σήμα reset παραγωγή σημάτων εισόδου για έλεγχο κυκλώματος ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 31
Πίνακες - μνήμες Πίνακες από reg, ενός ή πολλών bit (διανύσματα) Χρήσιμοι για μοντέλα μνήμης, αλλά δεν μπορούν να συνθέσουν κυκλώματα Προσοχή δεν μπορεί κανείς να γράψει/διαβάσει μεμονομένα bits απευθείας χρειάζεται ανάθεση σε προσωρινή μεταβλητή reg [7:0] memory [0:1024]; reg [9:0] addr; reg [7:0] dout; reg [7:0] din; always @(memory or addr); begin dout = memory[addr]; end always @(posedge clk) begin if (write_enable == 1 b1) memory[addr] <= din; end // 1K bytes of memory // read from memory at address addr // write only if the enable signal is set // write to memory at address addr ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 32
Παράδειγμα Παραμετροποιημένος ακμοπυροδότητος καταχωρητής με ασύνχρονο μηδενισμό και έλεγχο φόρτωσης module dff_le_r (q, d, lden, reset, clk); parameter N = 1; output reg [N-1:0] q; input clk; input reset; input lden; input [N-1:0] d; always @(posedge clk or negedge reset) begin if (!reset) q <= 'h0; else if (lden) begin q <= #`DFF_D d; end end endmodule dff_le_r #32 pc(.q(pc_r),.d(nextpc),.lden(1'b1),.clk(clk),.reset(reset) ); ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 33
Συναρτήσεις συστήματος $finish τέλος προσομοίωσης $display εμφάνιση κειμένου στην οθόνη $display("r[%2d] = 0x%h", i, rf.rf[i]); // $readmemb( <filename>, memory_name); // $readmemb( <filename>, memory_name [, start [, end]]); reg [7:0] memory [0:1023]; integer addr; initial begin $readmemb( memory.dat, memory); $display( Contents of memory ); for (addr = 0; addr < 1024; addr = addr + 1) $displayb(memory[addr]); end ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 34
Προσομοιωτής Icarus Χρειάζεται μετάφραση πρίν την προσομοίωση Μετάφραση: iverilog - o test file1.v file2.v Προσομοίωση: vvp test Για να δούμε τα αποτελέσματα γενικά χρησιμοποιούμε έναν απεικονιστή σημάτων (waveform viewer) gtkwave Επίδειξη ΠΛΕ 027 Μικροεπεξεργαστές 2011-2012 35