Η VHDL (VHSIC hardware description language ή γλώσσα περιγραφής υλικού VHSIC) είναι μια γλώσσα περιγραφής υλικού που χρησιμοποιείται στον αυτοματισμό ηλεκτρονικών σχεδιάσεων (electronic design automation) για την περιγραφή ψηφιακών και μεικτών (mixed-signal) συστημάτων, όπως οι συστοιχίες επιτόπια προγραμματιζόμενων πυλών (FPGA) και τα ολοκληρωμένα κυκλώματα.

Πηγαίος κώδικας σε VHDL για έναν αθροιστή με πρόσημο.

Ιστορία Επεξεργασία

Η VHDL αναπτύχθηκε αρχικά από το Υπουργείο Άμυνας των ΗΠΑ για την τεκμηρίωση των κυκλωμάτων ASIC που χρησιμοποιούσαν οι εταιρείες-προμηθευτές στον εξοπλισμό τους. Η VHDL δημιουργήθηκε δηλαδή σαν εναλλακτική λύση αντί των μεγάλων και πολύπλοκων εγχειριδίων που βασίζονταν στις λεπτομέρειες της εκάστοτε υλοποίησης.

Η ιδέα της προσομοίωσης της τεκμηρίωσης οδήγησε στην ανάπτυξη λογικών προσομοιωτών που μπορούσαν να διαβάσουν τα αρχεία VHDL. Το επόμενο βήμα ήταν η ανάπτυξη εργαλείων λογικής σύνθεσης που διάβαζαν την VHDL και παρήγαγαν έναν ορισμό της φυσικής υλοποίησης του κυκλώματος.

Επειδή το Υπουργείο Άμυνας απαιτούσε η σύνταξη να βασίζεται στην Ada, ώστε να μην χρειαστεί να επανεφευρεθούν ιδέες που είχαν ήδη δοκιμαστεί την ανάπτυξη της Ada, η VHDL δανείζεται πολλά χαρακτηριστικά από την Ada, όσον αφορά τις έννοιες και τη σύνταξη.

Η αρχική έκδοση της VHDL, που σχεδιάστηκε για να αποτελέσει το πρότυπο 1076-1987 του IEEE, περιλάμβανε αρκετούς τύπους δεδομένων, όπως τους αριθμητικούς ακέραιους (integer) και πραγματικούς (real), τους λογικούς (bit και boolean), χαρακτήρες (character) και χρόνο (time), καθώς και πίνακες από bit (bit_vector) και από character (string).

Ένα πρόβλημα που έμεινε άλυτο σε αυτήν την έκδοση ήταν η χρήση "λογικής πολλαπλών τιμών" ("multi-valued logic"), όπου λαμβάνονται υπόψη το σθένος οδήγησης ενός σήματος (μηδενικό, ασθενές ή ισχυρό) και οι άγνωστες τιμές. Αυτό απαιτούσε το πρότυπο IEEE 1164, που όριζε τύπους λογικής 9 τιμών: τον βαθμωτό std_ulogic και την ανυσματική έκδοσή του std_ulogic_vector.

Το ανανεωμένο IEEE 1076 του 1993, ανέμεσα σε άλλες αλλαγές, έκανε την σύνταξη πιο συνεπή, επέτρεψε μεγαλύτερη ευελιξία στα ονόματα που χρησιμοποιούνταν, επέκτεινε τον τύπο character για να επιτρέπει τους εκτυπώσιμους χαρακτήρες του ISO-8859-1, πρόσθεσε τον τελεστή xnor.

Μικρές αλλαγές του προτύπου (το 2000 και το 2002) πρόσθεσαν την ιδέα των προστατευμένων τύπων (που είναι παρόμοιοι με την έννοια των κλάσεων της C++) και αφαίρεσαν κάποιους περιορισμούς από τους κανόνες αντιστοίχισης θυρών (port mapping rules).

Εκτός από το πρότυπο IEEE 1164, εμφανίστηκαν πολλά θυγατρικά πρότυπα που επέκτειναν την λειτουργικότητα της γλώσσας. Το πρότυπο IEEE 1076.2 πρόσθεσε καλύτερο χειρισμό τύπων δεδομένων πραγματικών και μιγαδικών αριθμών. Το πρότυπο IEEE 1076.3 εισήγαγε τους τύπους με πρόσημο και χωρίς πρόσημο (signed/unsigned types) για τη διευκόλυνση των αριθμητικών λειτουργιών σε διανύσματα. Το πρότυπο IEEE 1076.1 (γνωστό και ως VHDL-AMS) περιλαμβάνει επίσης επεκτάσεις για τη σχεδίαση αναλογικών και μεικτών κυκλωμάτων.

Κάποια άλλα πρότυπα υποστηρίζουν ευρύτερη χρήση της VHDL, όπως το VITAL (VHDL Initiative Towards ASIC Libraries) και οι επεκτάσεις για σχεδίαση κυκλωμάτων μικροκυμάτων.

Τον Ιούνιο του 2006, η Τεχνική Επιτροπή της VHDL (VHDL Technical Committee) της Accellera (στην οποία είχε ανατεθεί από τον IEEE η εργασία για την επόμενη αναθεώρηση του προτύπου) ενέκρινε το αποκαλούμενο Draft 3.0 της VHDL-2006. Διατηρώντας πλήρη συμβατότητα με τις παλιότερες εκδόσεις, το προτεινόμενο αυτό πρότυπο παρέχει διάφορες επεκτάσεις που διευκολύνουν τη συγγραφή και τη διαχείριση κώδικα σε VHDL. Βασικές αλλαγές είναι η ενσωμάτωση θυγατρικών προτύπων (1164, 1076.2, 1076.3) στο βασικό πρότυπο 1076, ένα μεγαλύτερο σύνολο τελεστών, πιο ευέλικτη χρήση των εντολών case και generate, ενσωμάτωση του VHPI (διεπαφής προς τις γλώσσες C και C++) και ένα υποσύνολο της PSL (Property Specification Language). Οι αλλαγές αυτές βελτιώνουν την ποιότητα του παραγόμενου κώδικα VHDL, κάνουν τα testbenches πιο ευέλικτα και επιτρέπουν τη χρήση της VHDL σε ένα ευρύτερο πεδίο περιγραφών επιπέδου συστήματος.

Τον Φεβρουάριο του 2008 η Accellera ενέκρινε την VHDL 4.0 (ανεπίσημα γνωστή και ως VHDL 2008), η οποία αντιμετώπιζε πάνω από 90 προβλήματα που είχαν ανακαλυφθεί κατά τη δοκιμαστική περίοδο της έκδοσης 3.0 και περιλαμβάνει εμπλουτισμένους γενικούς τύπους (enhanced generic types). Το 2008 η Accellera διένειμε την VHDL 4.0 στον IEEE προσπαθώντας να την περιλάβει στο πρότυπο IEEE 1076-2008. Το πρότυπο IEEE 1076-2008 της VHDL δημοσιεύτηκε τον Ιανουάριο του 2009.

Σχεδίαση Επεξεργασία

Η VHDL συνήθως χρησιμοποιείται για τη συγγραφή μοντέλων σε κείμενο που περιγράφουν ένα λογικό κύκλωμα. Ένα πρόγραμμα σύνθεσης μπορεί να επεξεργαστεί ένα τέτοιο μοντέλο μόνο αν είναι μέρος της λογικής σχεδίασης, επομένως χρησιμοποιείται ένα πρόγραμμα προσομοίωσης για να δοκιμαστεί η λογική σχεδίαση χρησιμοποιώντας μοντέλα προσομοίωσης που αναπαριστούν τα λογικά κυκλώματα που αντιστοιχούν στη σχεδίαση. Η συλλογή αυτή από μοντέλα προσομοίωσης συνήθως αποκαλείται testbench.

Η VHDL έχει δομές που χειρίζονται τον παραλληλισμό που υπάρχει στις σχεδιάσεις υλικού, αλλά αυτές οι δομές (διεργασίες ή processes) διαφέρουν στη σύνταξη σε σύγκριση με τις παράλληλες δομές της Ada (εργασίες ή tasks). Όπως και η Ada, η VHDL έχει ισχυρούς τύπους (strongly typed) και δεν κάνει διάκριση μεταξύ κεφαλαίων και μικρών γραμμάτων. Για την απευθείας αναπαράσταση συχνών λειτουργιών του υλικού, υπάρχουν πολλά χαρακτηριστικά της VHDL που δεν υπάρχουν στην Ada, όπως ένα μεγαλύτερο σύνολο από λογικές πράξεις όπως η nand και η nor. Η VHDL επιτρέπει επίσης τη δεικτοδότηση πινάκων σε σειρά από μικρότερο προς μεγαλύτερο δείκτη ή αντίστροφα - και οι δύο συμβάσεις χρησιμοποιούνται στο υλικό, ενώ στην Ada και στις περισσότερες άλλες γλώσσες προγραμματισμού χρησιμοποιείται μόνο ο πρώτος τρόπος δεικτοδότησης.

Η VHDL έχει δυνατότητες εισόδου και εξόδου σε αρχεία και μπορεί να χρησιμοποιηθεί σαν γλώσσα γενικών καθηκόντων για επεξεργασία κειμένου, αλλά τα αρχεία χρησιμοποιούνται συνήθως από ένα testbench προσομοίωσης για τον ορισμό διεγέρσεων (stimuli), αλληλεπίδραση με τον χρήστη και για τη σύγκριση των ληφθέντων δεδομένων με τα επιθυμητά δεδομένα. Παρόλα αυτά, οι περισσότεροι σχεδιαστές αφήνουν αυτήν την εργασία στον προσομοιωτή.

Για έναν προγραμματιστή χωρίς εμπειρία είναι σχετικά εύκολο να παράγει κώδικα που προσομοιώνεται με επιτυχία αλλά δε μπορεί να παραχθεί σαν πραγματική υλοποίηση, ή είναι πολύ μεγάλος για να χρησιμοποιηθεί στην πράξη.

Η σχεδίαση του υλικού μπορεί να γίνει σε ένα ολοκληρωμένο περιβάλλον ανάπτυξης για VHDL (για υλοποίηση FPGA τέτοια είναι το Xilinx ISE, το Altera Quartus, το Synopsys Synplify και το Mentor Graphics HDL Designer), ώστε να παραχθεί το σχηματικό διάγραμμα RTL του επιθυμητού κυκλώματος. Μετά από αυτό, το παραγόμενο σχηματικό διάγραμμα μπορεί να επαληθευτεί με χρήση λογισμικού προσομοίωσης που δείχνει τις κυματομορφές των εισόδων και των εξόδων του κυκλώματος μετά την δημιουργία του κατάλληλου testbench. Η δημιουργία του σωστού testbench για ένα κύκλωμα ή έναν κώδικα σε VHDL απαιτεί τον σωστό ορισμό των εισόδων.

Όταν ένα μοντέλο σε VHDL μεταφράζεται σε "πύλες και γραμμές" που αντιστοιχίζονται σε μια προγραμματιζόμενη λογική συσκευή όπως ένα CPLD ή ένα FPGA, τότε το πραγματικό υλικό είναι αυτό που ρυθμίζεται και δεν "εκτελείται" ο κώδικας VHDL σε κάποιου τύπου επεξεργαστή.

Πλεονεκτήματα Επεξεργασία

Το βασικό πλεονέκτημα της VHDL, όταν αυτή χρησιμοποιείται για σχεδίαση συστημάτων, είναι ότι επιτρέπει την περιγραφή (μοντελοποίηση) και την επαλήθευση (προσομοίωση) του επιθυμητού συστήματος, πριν τα εργαλεία σύνθεσης μεταφράσουν τη σχεδίαση σε πραγματικό υλικό (πύλες και γραμμές).

Ένα άλλο όφελος της VHDL είναι ότι επιτρέπει τον ορισμό ταυτόχρονων συστημάτων (concurrent systems). Η VHDL είναι γλώσσα ροής δεδομένων, σε αντίθεση με τις διαδικαστικές γλώσσες προγραμματισμού όπως η BASIC, η C και η συμβολική γλώσσα, οι οποίες εκτελούνται ακολουθιακά, με κάθε εντολή να ακολουθεί την προηγούμενη.

Ένα έργο σε VHDL έχει πολλές εφαρμογές. Ένα μπλοκ υπολογισμού (calculation block) δημιουργείται μια φορά αλλά μπορεί να χρησιμοποιηθεί σε άλλα έργα. Μπορούν επίσης να ρυθμιστούν διάφορες παράμετροι διαμόρφωσης και λειτουργίας του μπλοκ (παράμετροι χωρητικότητας, το μέγεθος της μνήμης, η βάση των στοιχείων (element base), η σύνθεση μπλοκ και η δομή διασύνδεσης).

Ένα έργο σε VHDL είναι επίσης μεταφέρσιμο. Αν έχει δημιουργηθεί για μια βάση στοιχείων, μπορεί να μεταφερθεί σε μια άλλη βάση, για παράδειγμα σε ένα VLSI με διάφορες τεχνολογίες.

Παραδείγματα σχεδίασης Επεξεργασία

Στην VHDL, μια σχεδίαση αποτελείται τουλάχιστον από μια οντότητα (entity) που περιγράφει τη διεπαφή και μια αρχιτεκτονική (architecture) που περιέχει την πραγματική υλοποίηση. Επιπλέον, οι περισσότερες σχεδιάσεις εισάγουν στον κώδικά τους μονάδες της βιβλιοθήκης (library modules). Κάποιες σχεδιάσεις περιλαμβάνουν πολλαπλές αρχιτεκτονικές και ρυθμίσεις (configurations).

Μια απλή πύλη AND σε VHDL μοιάζει με τον κώδικα που ακολουθεί:

-- (αυτό είναι σχόλιο της VHDL)

-- εισάγει την std_logic από τη βιβλιοθήκη IEEE
library IEEE;
use IEEE.std_logic_1164.all;

-- αυτό είναι μια οντότητα
entity ANDGATE is
  port ( 
    I1 : in std_logic;
    I2 : in std_logic;
    O  : out std_logic);
end entity ANDGATE;

-- αυτό είναι μια αρχιτεκτονική
architecture RTL of ANDGATE is
begin
  O <= I1 and I2;
end architecture RTL;

Σε αρχάριους της VHDL, το παραπάνω παράδειγμα μπορεί να μοιάζει μεγάλο σε έκταση, σε σχέση με τη λειτουργικότητά του, πολλά μέρη του όμως είναι είτε προαιρετικά, είτε χρειάζεται να γραφούν μόνο μια φορά. Απλές συναρτήσεις όπως αυτή συνήθως είναι μέρη μιας μεγαλύτερης μονάδας, αντί να υπάρχει μια μονάδα για κάτι τόσο απλό. Επιπλέον, η χρήση στοιχείων όπως ο τύπος std_logic μπορεί να φαίνονται ότι δε χρειάζονται - κάποιος θα μπορούσε να χρησιμοποιήσει τον ενσωματωμένο τύπο bit και να αποφύγει την εισαγωγή της βιβλιοθήκης στην αρχή του κώδικα. Η χρήση όμως αυτής της λογικής 9 τιμών (U,X,0,1,Z,W,H,L,-) αντί για απλά bit (0,1) προσφέρει τον σχεδιαστή ένα πολύ ισχυρό εργαλείο προσομοίωσης και αποσφαλμάτωσης, το οποίο λείπει από τις άλλες γλώσσες περιγραφής υλικού.

Στα επόμενα παραδείγματα φαίνεται ότι ο κώδικας VHDL μπορεί να γραφεί πολύ πιο σύντομα. Παρόλα αυτά, ένας σχεδιαστής με εμπειρία συνήθως αποφεύγει αυτές τις σύντομες μορφές και χρησιμοποιεί ένα πιο εκτεταμένο στυλ συγγραφής, για λόγους αναγνωσιμότητας και συντήρησης.

Συντιθέμενες δομές και πρότυπα VHDL Επεξεργασία

Η VHDL συχνά χρησιμοποιείται για δυο σκοπούς: την προσομοίωση ηλεκτρονικών σχεδιάσεων και τη σύνθεσή τους. Η σύνθεση είναι η διδαδικασία της μεταγλώττισης της VHDL και η αντιστοίχισή της με μια τεχνολογία υλοποίησης όπως τα FPGA ή τα ASIC. Πολλοί κατασκευαστές FPGA διαθέτουν δωρεάν (ή φτηνά) εργαλεία σύνθεσης VHDL για χρήση στα τσιπ τους, ενώ τα εργαλεία ASIC είναι συχνά πολύ ακριβά.

Δεν είναι όλες οι δομές της VHDL κατάλληλες για σύνθεση. Για παράδειγμα, πολλές δομές που ασχολούνται με το χρονισμό (όπως η wait for 10 ns;) δεν μπορούν να συντεθούν, αν και ισχύουν στην προσομοίωση. Αν και διαφορετικά εργαλεία σύνθεσης έχουν διαφορετικές δυνατότητες, υπάρχει ένα κοινό υποσύνολο της VHDL, το οποίο μπορεί να συντεθεί και ορίζει ποιες δομές της γλώσσας και ποια ιδιώματα αντιστοιχούν σε κοινό υλικό για πολλά εργαλεία σύνθεσης. Το IEEE 1076.6 ορίζει το υποσύνολο της γλώσσας που θεωρείται το επίσημο υποσύνολο για σύνθεση.

Ακολουθούν κάποια παραδείγματα κώδικα που μπορεί να συντεθεί:

πρότυπο MUX Επεξεργασία

Ο πολυπλέκτης ή 'MUX', όπως συχνά αποκαλείται, είναι μια απλή δομή που είναι πολύ κοινή στη σχεδίαση υλικού. Το παρακάτω παράδειγμα δείχνει έναν απλό MUX δύο-σε-ένα, με εισόδους A και B, επιλογέα S και έξοδο X. Γενικά υπάρχουν πολλοί άλλοι τρόποι να εκφραστεί ο ίδιος MUX σε VHDL.

X <= A when S = '1' else B;

Πρότυπο μανταλωτή (latch) Επεξεργασία

Ένας διαφανής μανταλωτής (transparent latch) είναι ένα bit μνήμης που ενημερώνεται όταν εμφανίζεται σήμα ενεργοποίησης. Όπως και πριν, υπάρχουν και άλλοι τρόποι να εκφραστεί αυτό σε VHDL.

-- πρότυπο μανταλωτή 1:
Q <= D when Enable = '1' else Q;

-- πρότυπο μανταλωτή 2:
process(D,Enable)
begin
  if Enable = '1' then
    Q <= D;
  end if;
end process;

Δισταθής Πολυδονητής τύπου D (D flip-flop] Επεξεργασία

Ο παρακάτω δισταθής πολυδονητής τύπου D (D flip-flop] λαμβάνει δείγματα από ένα σήμα εισόδου σε κάθε ανοδική (ή καθοδική) ακμή ενός ρολογιού. Το παράδειγμα έχει ασύγχρονη επαναφορά (τύπου active-high) και λαμβάνει δείγματα στην ανοδική ακμή του ρολογιού.

DFF : process(RST, CLK)
begin
  if RST = '1' then
    Q <= '0';
  elsif rising_edge(CLK) then
    Q <= D;
  end if;
end process DFF;

Ένας άλλος κοινός τρόπος να εκφραστεί στην VHDL η συμπεριφορά που προκαλείται από ακμές σημάτων είναι με την ιδιότητα σήματος 'event'. Ανάμεσα στο όνομα του σήματος και στο όνομα της ιδιότητας πρέπει να γραφτεί μια μονή απόστροφος.

DFF : process(RST, CLK)
begin
  if RST = '1' then
    Q <= '0';
  elsif CLK'event and CLK = '1' then
    Q <= D;
  end if;
end process DFF;

Παράδειγμα: μετρητής Επεξεργασία

Το επόμενο παράδειγμα είναι ένας μετρητής προς τα πάνω με ασύγχρονη επαναφορά (reset), παράλληλη φόρτωση και ρυθμιζόμενο εύρος. Δείχνει πώς μπορεί να χρησιμοποιηθεί ο τύπος, πώς γίνεται η μετατροπή τύπων μεταξύ 'unsigned' και 'std_logic_vector', καθώς και τα χαρακτηριστικά γενικού προγραμματισμού της VHDL (generics). Τα τελευταία έχουν στενή σχέση με τις παραμέτρους ή τα πρότυπα άλλων κλασικών γλωσσών προγραμματισμού, όπως η C ή η C++.

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;    -- για τον τύπο unsigned

entity COUNTER is
  generic (
    WIDTH : in natural := 32);
  port (
    RST   : in std_logic;
    CLK   : in std_logic;
    LOAD  : in std_logic;
    DATA  : in std_logic_vector(WIDTH-1 downto 0);
    Q     : out std_logic_vector(WIDTH-1 downto 0));
end entity COUNTER;

architecture RTL of COUNTER is
  signal CNT : unsigned(WIDTH-1 downto 0);
begin
  process(RST, CLK) is
  begin
    if RST = '1' then
      CNT <= (others => '0');
    elsif rising_edge(CLK) then
      if LOAD = '1' then
        CNT <= unsigned(DATA); -- ο τύπος μετατρέπεται σε unsigned
      else
        CNT <= CNT + 1;
      end if;
    end if;
  end process;

  Q <= std_logic_vector(CNT); -- ο τύπος μετατρέπεται ξανά σε std_logic_vector
end architecture RTL;

Πιο πολύπλοκοι μετρητές μπορούν να προσθέσουν εντολές if/then/else στο rising_edge(CLK) elsif για να προσθέσουν και άλλες συναρτήσεις, όπως η ενεργοποίηση μέτρησης, η παύση ή η επανεκκίνηση μετά από κάποια τιμή, παράγοντας σήματα εξόδου (όπως τα σήματα μέτρησης τερματικών). Αυτά τα στοιχεία ελέγχουν πρέπει να δομούνται με την κατάλληλη σειρά και ιεραρχία, ώστε να παράγουν τις επιθυμητές προτεραιότητες και να ελαχιστοποιείται ο απαιτούμενος αριθμός λογικών επιπέδων.

Δομές για χρήση στην προσομοίωση Επεξεργασία

Ένα μεγάλο υποσύνολο της VHDL δε μπορεί να μεταφραστεί σε υλικό. Το υποσύνολο αυτό είναι γνωστό σαν το μη-συντιθέμενο (non-synthesizable) υποσύνολο ή το υποσύνολο μόνο για εξομοίωση (simulation-only subset) της VHDL και μπορεί να χρησιμοποιηθεί μόνο για πρωτότυπη υλοποίηση, προσομοίωση και αποσφαλμάτωση. Για παράδειγμα, ο εξής κώδικας θα δημιουργήσει ένα ρολόι με συχνότητα 50 MHz. Μπορεί, για παράδειγμα, να χρησιμοποιηθεί για να δοθεί ένα σήμα ρολογιού σε μια σχεδίαση κατά τη διάρκεια της προσομοίωσης. Αποτελεί όμως δομή μόνο για την εξομοίωση και δε μπορεί να υλοποιηθεί σε υλικό. Στο πραγματικό υλικό το σήμα του ρολογιού παράγεται εξωτερικά και μπορεί να κλιμακωθεί εσωτερικά με τη χρήση λογικής χρήστη ή εξειδικευμένου υλικού.

process
begin
  CLK <= '1'; wait for 10 ns;
  CLK <= '0'; wait for 10 ns;
end process;

Αυτές οι δομές μόνο για προσομοίωση μπορούν να χρησιμοποιηθούν για την γρήγορη κατασκευή πολύπλοκων κυματομορφών. Μια τέτοια κυματομορφή μπορεί για παράδειγμα να χρησιμοποιηθεί σαν διάνυσμα ελέγχου για μια πολύπλοκη σχεδίαση ή σαν πρωτότυπο για κάποια λογική προς σύνθεση που θα υλοποιηθεί στο μέλλον.

process
begin
  wait until START = '1'; -- περίμενε μέχρι να εμφανιστεί σήμα START
  
  for i in 1 to 10 loop -- περίμενε για μερικές περιόδους ρολογιού...
    wait until rising_edge(CLK);
  end loop;

  for i in 1 to 10 loop 	-- γράψε τους αριθμούς 1 έως 10 στο DATA, 1 κάθε κύκλο
    DATA <= to_unsigned(i, 8);
    wait until rising_edge(CLK);
  end loop;

  -- περίμενε μέχρι να αλλάξει η έξοδος
  wait on RESULT;
  
  -- δώσε σήμα ACK για την περίοδο του ρολογιού
  ACK <= '1';
  wait until rising_edge(CLK);
  ACK <= '0';
  
  -- ...
end process;

Δείτε επίσης Επεξεργασία

Βιβλιογραφία Επεξεργασία

Εξωτερικοί σύνδεσμοι Επεξεργασία