+ All Categories
Home > Documents > 3 INTRODUCERE ÎN LIMBAJUL DE DESCRIERE HARDWARE …ece.ubm.ro/clp/index_files/Curs_3_4.pdf ·...

3 INTRODUCERE ÎN LIMBAJUL DE DESCRIERE HARDWARE …ece.ubm.ro/clp/index_files/Curs_3_4.pdf ·...

Date post: 10-Feb-2019
Category:
Upload: volien
View: 221 times
Download: 0 times
Share this document with a friend
28
Capitolul 3 3 INTRODUCERE ÎN LIMBAJUL DE DESCRIERE HARDWARE – VHDL 3.1 Generalităţi Acest limbaj a fost dezvoltat la mijlocul anilor ’80 de către departamentul de apărare al Statelor Unite în colaborare cu IEEE (Institute of Electrical and Electronical Enginner). Abrevierea VHDL derivă din VHSIC Hardware Description Language (limbajul de descriere hard VHSIC), abrevierea VHSIC însemnând la rândul ei Very High Speed Integrated Circuit. În continuare sunt enumerate câteva din caracteristicile limbajului: - proiectele pot fi descompuse ierarhic; - fiecare element al proiectului are o interfaţă bine definită (pentru a se asigura conectivitatea cu celelalte elemente ale proiectului) şi specificaţii comportamentale precise (pentru a putea fi simulat); - specificaţiile comportamentale pot fi exprimate sub formă de algoritm sau ca şi structură hard, aceasta pentru ca funcţionarea elementului să fie bine definită; - prin intermediul limbajului VHDL pot fi modelate noţiunile de concurenţă, timing şi sincronizare a semnalelor, se permite astfel modelarea circuitelor atât sincrone cât şi asincrone; - proiectul modelat în VHDL poate fi simulat funcţional (dacă funcţionează corect d.p.d.v. logic) cât şi din punctul de vedere al comportării în timp (întârzierile). Popularitatea şi mai ales utilitatea limbajului VHDL a crescut mai ales din momentul din care s-au dezvoltat şi un set de unelte pentru sinteză (synthesis tools). Acest set de programe poate crea structuri de circuite logice direct din descrierile VHDL comportamentale. Folosind limbajul VHDL pot fi proiectate, simulate şi sintetizate atât circuitele combinaţionale simple cât şi sisteme complexe cu microprocesor. Limbajul VHDL a fost standardizat pentru prima dată de IEEE în 1987 (VHDL- 87) şi a fost extins în 1993 (VHDL-93). 3.2 Design Flow Înainte de a studia limbajul în sine este util să studiem puţin mediul în care este integrat. Într-un proiect care are la bază descrierea VHDL a circuitului există ţiva paşi care trebuie urmaţi, aceştia sunt denumiţi adesea design flow. Aceşti paşi sunt evidenţiaţi în figura 3.1.
Transcript

Capitolul 3

3 INTRODUCERE ÎN LIMBAJUL DE DESCRIERE HARDWARE – VHDL

3.1 Generalităţi Acest limbaj a fost dezvoltat la mijlocul anilor ’80 de către departamentul de apărare al Statelor Unite în colaborare cu IEEE (Institute of Electrical and Electronical Enginner). Abrevierea VHDL derivă din VHSIC Hardware Description Language (limbajul de descriere hard VHSIC), abrevierea VHSIC însemnând la rândul ei Very High Speed Integrated Circuit. În continuare sunt enumerate câteva din caracteristicile limbajului: - proiectele pot fi descompuse ierarhic; - fiecare element al proiectului are o interfaţă bine definită (pentru a se asigura

conectivitatea cu celelalte elemente ale proiectului) şi specificaţii comportamentale precise (pentru a putea fi simulat);

- specificaţiile comportamentale pot fi exprimate sub formă de algoritm sau ca şi structură hard, aceasta pentru ca funcţionarea elementului să fie bine definită;

- prin intermediul limbajului VHDL pot fi modelate noţiunile de concurenţă, timing şi sincronizare a semnalelor, se permite astfel modelarea circuitelor atât sincrone cât şi asincrone;

- proiectul modelat în VHDL poate fi simulat funcţional (dacă funcţionează corect d.p.d.v. logic) cât şi din punctul de vedere al comportării în timp (întârzierile).

Popularitatea şi mai ales utilitatea limbajului VHDL a crescut mai ales din momentul din care s-au dezvoltat şi un set de unelte pentru sinteză (synthesis tools). Acest set de programe poate crea structuri de circuite logice direct din descrierile VHDL comportamentale. Folosind limbajul VHDL pot fi proiectate, simulate şi sintetizate atât circuitele combinaţionale simple cât şi sisteme complexe cu microprocesor. Limbajul VHDL a fost standardizat pentru prima dată de IEEE în 1987 (VHDL-87) şi a fost extins în 1993 (VHDL-93).

3.2 Design Flow

Înainte de a studia limbajul în sine este util să studiem puţin mediul în care este integrat. Într-un proiect care are la bază descrierea VHDL a circuitului există câţiva paşi care trebuie urmaţi, aceştia sunt denumiţi adesea design flow. Aceşti paşi sunt evidenţiaţi în figura 3.1.

Introducere în limbajul de descriere hardware – VHDL

27

3.1 Fazele urmate pentru descrierea şi sintetizarea circuitelor în VHDL

Etapa iniţială (de descriere) începe prin stabilirea blocurilor funcţionale la nivel de diagrame bloc. Proiectele complexe sunt de obicei ierarhizate, VHDL-ul este un mediu care permite definirea modulelor şi a interfeţelor corespunzătoare, urmând ca detaliile funcţionale să fie adăugate ulterior. Pasul următor constă în scrierea codului VHDL pentru fiecare modul . Orice editor text poate fi folosit pentru descrierea modulelor deoarece VHDL este un limbaj bazat pe text. Totuşi mediile de proiectare includ editoare de text specializate pentru VHDL, editoare care uşurează mult sarcina proiectanţilor prin facilităţile pe care le oferă: evidenţiere automată a cuvintelor cheie, tipare cu structurile de program cel mai frecvent folosite, verificare automată a sintaxei codului VHDL şi accesarea rapidă a compilatorului. Odată scris codul trebuie compilat, această operaţie este efectuată de un compilator VHDL care va analiza codul atât din punctul de vedere al erorilor de sintaxă ci şi din punctul de vedere al compatibilităţii modulului cu alte module la care se referă. De asemenea prin compilare sunt create informaţii interne care sunt necesare simulatorului pentru analiza ulterioară a proiectului. În simularea proiectului descris în cod VHDL se apelează la un simulator de obicei integrat în mediul de proiectare. Un astfel de simulator permite utilizatorului să aplice semnale de intrare circuitului proiectat şi să observe comportarea circuitului analizând semnalele de ieşire. În proiecte de anvergură mică semnalele de intrare se pot aplica manual iar cele de ieşire pot fi studiate fiecare în parte. Dar pentru proiecte mai mari aceasta poate devenii o sarcină foarte anevoioasă astfel că VHDL-ul oferă posibilitatea de a crea aşa numitele test-bench-uri care permit generarea automată a semnalelor de intrare şi compararea semnalelor de ieşire cu semnalele de ieşire aşteptate. Etapa de simulare este cuprinsă într-o etapă mai largă de verificare. Astfel există două moduri de a verifica un proiect, primul este verificarea funcţională, când circuitul este studiat din punct de vedere al funcţionării logice, întârzierile şi parametrii fiind consideraţi nuli. Cel de al doilea mod de verificare, este cel în care se studiază comportarea circuitului ţinându-se cont de întârzierile estimate, cum ar fi întârzieri de setup şi hold time în cazul bistabilelor sau întârzierilor prin porţi în cazul circuitelor combinaţionale. Este o practică bună ca cele două tipuri de verificări să fie făcute cu atenţie în această etapă pentru a evita aşa numita fază finală (vezi figura

Capitolul 3

28

3.1), totuşi mai pot apărea surprize deoarece întârzierile dintr-un circuit sunt foarte dependente de rezultatele sintezei şi al asamblării (fitting stage) proiectului pentru un anumit tip de circuit programabil. După verificare suntem pregătiţi să trecem la etapa finală. Primul pas în această fază este sinteza (synthesis) codului VHDL, care constă în convertirea codului într-un set de primitive sau componente care pot fi asamblate în tehnologia către care este orientat proiectul (FPGA sau CPLD). Pentru PLD-uri sau CPLD-uri sculele de sinteză trebuie să genereze două nivele de ecuaţii SOP (Sum-of-Product = suma produselor). În cazul circuitelor ASIC este generată o listă de porţi şi un netlist care specifică modul în care aceste porţi sun interconectate. Proiectantul poate să “ajute” sculele de sinteză prin specificarea unor constrângeri specifice tehnologiei, cum ar fi număr de nivele logice sau puterea bufferelor logice. În etapa de asamblare (fitting) este folosit un program (fitter) pentru plasarea (mapping stage) primitivelor sau a componentelor sintetizate în spaţiul oferit de circuitul programabil. În cazul CPLD-urilor aceasta constă în atribuirea ecuaţiilor elementelor AND-OR disponibile. Pentru un ASIC acest proces constă în întocmirea unei “hărţi” de porţi logice şi găsirea unei modalităţi de plasare a acesteia în cipul fizic, iar procesul este numit place-and-route. În această etapă se mai pot exercita câteva constrângeri asupra proiectului cum ar fi plasarea anumitor module în chip sau atribuirea de pini intrărilor şi ieşirilor externe. Faza finală este cea de verificarea întârzierilor (timing verification). Abia în această fază apar întârzierile reale din circuit, întârzieri datorate lungimi traseelor, încărcărilor electrice şi a altor factori. La fel ca în decursul oricărui proces de proiectare este posibil să avansezi doi paşi înainte si apoi să revi un pas înapoi sau chiar mai rău. După cum se poate observa şi în figura 3.1 fiecare etapă oferă posibilitatea de a revenii asupra soluţiilor. Problema cea mai nedorită este acea de a fi obligat să revii din faza finală , de exemplu când un proiect sintetizat ocupă mai mult spaţiu decât cel oferit de circuitul FPGA sau CPLD folosit. În aceste cazuri trebuie revenit asupra proiectului şi trebuie regândit, aceasta demonstrează că oricât de performante ar fi uneltele folosite pentru sinteză şi implementare acestea nu pot substitui gândirea proiectantului.

3.3 Structura unui cod VHDL

VHDL a fost proiectat ca şi program structurat, împrumutându-se unele idei de la limbajele de programare soft Pascal şi Ada. O idee de bază este acea de a definii o interfaţă a modulului hard în timp ce detaliile interne sunt ascunse. Astfel o entitate (entity) VHDL este o simplă declarare a intrărilor şi ieşirilor modulului în timp ce arhitectura (architecture) VHDL este o descriere structurală sau comportamentală detailată a funcţionării modulului. Figura 3.2(a) ilustrează acest concept. Acest concept formează bazele proiectării ierarhice a sistemelor, şi anume arhitectura entităţii de la nivelul cel mai superior poate conţine (instantiate) alte entităţi ale căror arhitecturi sunt “invizibile” de la nivelele superioare. După cum se poate observa în figura 3.2(b) o arhitectură de la nivel superior poate folosii entităţi de la nivelul inferior de mai multe ori, iar mai multe arhitecturi de la nivel superior pot folosii aceeaşi entitate de la nivel inferior fiecare la rândul ei.

Introducere în limbajul de descriere hardware – VHDL

29

Figura 3.3.a) Conceptul entitate-arhitectură; b)Conceptul de ierarhie

În fişierul text al unui fişier VHDL declararea entităţii şi definirea arhitecturii se face separat, vezi figura 3.3. În tabelul T3.1 este prezenta un program VHDL simplu care descrie funcţionarea porţii ŞI (AND) cu o intrare inhibată cunoscută şi sub denumirea de poartă BUT-NOT.

Tabelul T3.1 Program VHDL pentru poarta BUT-NOT

Figura 3.3 Structura unui fişier

VHDL

În proiecte mai complexe este posibil ca entităţile şi arhitecturile să fie definite în fişiere separate pe care compilatorul le va “potrivii” în funcţie de numele declarate. VHDL-ul ignoră spaţiile şi liniile despărţitoare, acestea putând fi folosite pentru a face

Capitolul 3

30

codul mai uşor de citit, pentru a comenta o linie de program se foloseşte simbolizarea prin două linii succesive (--), după care se introduce linia de comentariu. În VHDL sunt definite şiruri de caractere speciale care sunt denumite şi cuvinte cheie (keywords) sau cuvinte dedicate. În exemplu din tabelul T3.1 aceste cuvinte cheie sunt: entity, port, is, in ,out, end, architecture, begin, when, else şi and. Codul VHDL mai conţine şi aşa numiţii identificatori (Identifires): Inhibit, X,Y, BIT, Z, şi Inhibit_arch, aceste litere sau şiruri de litere, trebuie să înceapă şi să se sfârşească cu o literă, dar pot să conţină şi numere sau linii de picior(?) şi sunt definite de programator. Cuvintele cheie şi identificatorii pot fi scrişi cu atât cu majuscule cât şi cu litere mici, nu sunt “case sensitive”. Sintaxa pentru declararea entităţii este prezentată în tabelul T3.3.

Tabelul T3.2 Sintaxa VHDL pentru declararea entităţii

entity entity-name is

port (signal-names : mode signal-type;

signal-names : mode signal-type;

signal-names : mode signal-type);

end entity-name;

Pe lângă cuvintele cheie în codul VHDL mai apar următoarele elemente: - entity-name = un nume selectat de utilizator pentru a denumi entitatea; - signal-names = o listă de unul sau mai mulţi identificatori selectaţi de utilizator,

separaţi prin virgulă care denumesc semnalele externe; - mode = unul din următoarele patru cuvinte rezervate, specificând direcţia

semnalului: o in – pentru semnal de intrare în entitate; o out – pentru semnal de ieşire din entitate, cu menţiunea că, valoarea

semnalului nu poate fi “citită” înăuntrul entităţii, ci numai de alte entităţi care-l folosesc;

o buffer – defineşte un semnal de ieşire din entitate, iar valoare lui poate fi citită şi în interiorul arhitecturii din entitate;

o inout – defineşte un semnal de intrare/ieşire din entitate, acest se foloseşte frecvent pentru a descrie pini three-state.

A se observa că după ultimul semnal definit nu se mai pune punct şi virgulă. În tabelul T3.3 este prezentată sintaxa pentru declararea arhitecturii. Numele entităţii (entity-name) trebuie să fie acelaşi cu cel folosit la definirea entităţii. Numele arhitecturii (architecture-name) este un identificator definit de utilizator, dacă se doreşte poate fi la fel cu cel al entităţii sau diferit. Semnalele externe ale arhitecturii sunt cele moştenite de la entitate, de asemenea se pot definii şi semnale interne (signal declaration), dar care vor acţiona doar local în arhitectură. Declaraţiile

Introducere în limbajul de descriere hardware – VHDL

31

enumerate în tabelul T3.3 pot apărea în orice ordine. Sintaxa pentru definirea unui semnal este următoarea:

signal signal-name: signal-type;

Tabelul T3.3 Sintaxa VHDL pentru declararea arhitecturii

În cadrul unei arhitecturii se pot definii unul sau mai multe semnale interne, iar acestea în cadrul unei diagrame logice au ca şi corespondent traseele. Semnalele pot fi atât scrise cât şi citite în cadrul arhitecturii. În limbajul VHDL variabilele (variables) sunt identice semnalelor doar că ele nu au corespondent fizic într-un circuit. În tabelul T3.3 ele nu apar deoarece ele se definesc la nivel mult mai jos în cadrul funcţiilor, procedurilor şi al proceselor, după cum vom vedea mai târziu. Declararea variabilelor se face identic cu cea a semnalelor:

variable variable-name: variable-type;

3.4 Tipuri şi constante

Toate semnalele, variabilele şi constantele dintr-un program VHDL trebuie să aibă asociat un tip (type). În cadrul tipului se specifică un set de valori pe care le poate lua obiectul (semnal, variabilă …) şi de asemenea există şi un set de operatori (+, AND etc)asociaţi tipului respectiv. Limbajul VHDL are doar câteva tipuri predefinite, vezi tabelul T3.3.

Tabellu T3.4 Tipuri predefinite în VHDL

Tipurile bit şi bit-vector sunt destul de puţin folosite, în schimb versiunile definite de utilizator ale tipului respectiv sunt mult mai folositoare după cum vom vedea mai departe. Tipul integer (întreg) cuprinde domeniul numerelor întregi incluzând domeniul (–3.147483.647 , + 3.147483.647) adică (–2 31 , +231-1). Tipul boolean are

Capitolul 3

32

două valori true şi false. Tipul character (caracter) include toate caracterele din setul de caractere ISO* (International Organization of Standardization) exprimate pe 8 biţi, primele 128 fiind caractere ASCII. În tabelul T3.5 sunt prezentaţi operatorii specifici tipurilor integer şi boolean.

Tabelul T3.5 Operatori predefiniţi specifici tipurilor integer şi boolean

Operatori (operanzi întregi) Operatori (operanzi logici) + adunare and ŞI - scădere or SAU * înmulţire nand ŞI-NU / împărţire nor SAU-NU mod împărţire modulo xor SAU-EXCLUSIV rem împărţire modulo cu rest xnor SAU-EXCLUSIV-NOT abs valoare absolută not complementare ** ridicare la putere

Cele mai folosite tipuri în programele VHDL sunt aşa numitele tipuri definite de utilizator (user defined types), unul dintre acestea este tipul enumerare (enumerated type) definit printr-o înşiruire de valori. Declararea tipului enumerare se face conform tabelului T3.6.

Tabelul T3.6 Sintaxa VHDL pentru declararea tipului şi a constantelor

Value-list (lista de valori) reprezintă înşiruirea (enumerarea) tuturor elementelor posibile pentru respectivul tip, separate prin virgulă. Valorile enumerate pot fi atât caractere cât şi identificatori definiţi de utilizator. Un tip foarte important este std_logic, vezi tabelul T3.7, care este un tip standard definit de utilizator (standard user defined logic type) şi este parte a package-ului standard IEEE 1164 pe care îl vom trata ulterior. Acest tip include pe lângă valorile logice 0 şi 1 alte şapte valori care îşi găsesc utilitate în simularea unui semnal logic dintr-un circuit real. După cum se poate observa în tabelul T3.6 limbajul VHDL permite definirea de subtip (subtype) corespunzător unui tip. Valorile unui subtip trebuie să într-un domeniu continu faţă de valorile tipului de bază. Pentru tipul enumerare, “continu “ se referă la poziţia valorilor din lista valorilor corespunzătoare tipului de bază. A se

*"ISO" este un cuvânt derivat din cuvântul grecesc „isos”, care înseamnă „egal” şi este rădăcina prefixului „iso-„ care este folosit în termeni ca: izometric (se spune despre entităţi care au dimensiuni egale), izonomie (egalitate a legilor sau a oamenilor în faţa legii), etc.

Introducere în limbajul de descriere hardware – VHDL

33

observa că ordinea elementelor dintr-un şir trebuie specificată în ordină crescătoare sau descrescătoare (to sau downto).

Tabelul T3.7 Valori definite în cadrul tipului std_logic

În orice limbaj constantele contribuie la lizibilitatea, mentenabilitatea, şi portabilitatea unui program. Sintaxa VHDL pentru declararea constantelor este prezentată în tabelul T3.6, pentru o mai bună înţelegere în continuare se prezintă şi câteva exemple. constant BUS_SIZE: integer :=32; -- reprezintă lăţime componentei constant MSB: integer := BUS_SIZE-1; -- numărul de biţi ai lui MSB constant Z: character := ‘Z’; -- sinonim valorii de înaltă impedanţă Se observă că valoarea unei constante poate fi chiar şi o expresie. O altă categorie foarte importantă de tip definit de utilizator este tipul matrice (array type). Acest tip defineşte o matrice ca fiind un set de elemente de acelaşi în care fiecare element este selectat printr-un index de matrice (array index) În tabelul T3.8 sunt prezentate câteva versiuni de sintaxă folosite în declararea unei arii.

Tabelul 3.8 Sintaxa VHDL pentru declararea unei arii

În primele două exemple start şi end sunt definiţi de tipul integer şi stabilesc numărul total de elemente al ariei. În ultimele trei exemple toate valorile unui tip existent sau numai un subset de valori vor fi cuprinse de arie. Exemple de matrici sunt date în tabelul T3.9.

Capitolul 3

34

Tabelul T3.9 Exemple de declaraţii de arii

Unul dintre exemplele mai interesante este cel în care o constantă WORD_LEN este folosită în cadrul declaraţiei de arie, exemplificând astfel că valoarea domeniului poate fi dată de o expresie. Cel de al treilea exemplu şi mai interesant ne artă că un element al ariei poate fi la rândul lui o arie, aceasta rezultând într-o matrice bidimensională. Se consideră implicit că elementele unei matrici sunt ordonate de la stânga la dreapta la fel ca şi domeniul index, astfel cel mai din stânga element al ariilor mountly_count, word,reg_file este 1, 31, 1. Dacă se doreşte accesarea unui singur element din matrice se va folosii numele matrice iar în paranteze indexul elementului, exemplu mountly_count(11) aceasta pentru a accesa cel de al 11-lea element al ariei mountly_count. O matrice literală se defineşte (array literals) prin înşiruirea între paranteze a valorilor elementelor. Elementele variabilei B de tipul byte pot primii toate valoarea 1 logic scriind o expresie de forma:

B := (‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’);

Limbajul VHDL permite de asemenea notaţii mai scurte, de exemplu pentru a atribui valoarea 0 logic tuturor biţilor variabilei W de tip word, mai puţin biţilor cei mai puţini semnificativi corespunzători fiecărui byte se va scrie expresia:

W := (0=>’1’, 8=>’1’, 16=>’1’, 24=>’1’, others=>’0’);

Expresiile anterioare pot fi rescrise folosind şirurile de caractere, după cum urmează:

B := “11111111”;

W:= “11111110111111101111111011111110”;

Este posibil de asemenea să se facă referire la un subset de valori (slice) dintr-o matrice, specificând începutul şi sfârşitul indicilor elementelor din subset, exemple cu referire la tipurile din tabelul T3.9: M(6 to 9), B(3 downto 0), W(15 downto 8) etc.

Introducere în limbajul de descriere hardware – VHDL

35

Folosind operatorul concatenare & (concatenation operator) se pot alătura elementele unei matrici în ordinea în care sunt scrise, de la stânga la dreapta., de exemplu prin concatenarea ‘0’ & ’1’ & ‘1Z’ se obţine “011Z”. Cel mai important tip de matrice des întâlnit în programele VHDL este cel aparţinând standardului logic definit de utilizator IEEE 1164 (std_logic_vector), definiţia acestui standard este:

type STD_LOGIC_VECTOR is array (natural range < > ) of STD_LOGIC

3.5 Funcţii şi proceduri

La fel ca şi în alte limbaje de nivel înalt şi în VHDL o funcţie acceptă un anumit număr de argumente şi returnează un rezultat. Atât argumentele cât şi rezultatul returnat de o funcţie sunt de un tip predeterminat. Sintaxa VHDL prin care se defineşte o funcţie este prezentată în tabelul T3.10. După ce se dă un nume funcţiei (function -name) se poate definii o listă de parametri formali care vor fi folosiţi în structura funcţiei (signal-names : signal-types;…), toţi aceşti parametrii trebuie să fi de acelaşi tip. Din tabelul T3.10 se poate observa că în cadrul unei funcţii se pot definii local tipuri, constante, variabile şi de asemenea funcţii şi proceduri imbricate (nested). Între cuvintele cheie begin şi end este cuprinsă o serie de instrucţiuni secvenţiale care sunt executate ori de câte ori este apelată funcţia . În tabelul T3.11 este prezentat un exemplu de descriere a unei funcţii în limbaj VHDL. În cadrul funcţiei cuvântul cheie return indică momentul din care funcţia returnează o valoare care trebuie să fie de tipul celei definite la declararea funcţiei.

Tabelul T3.10 Sintaxa VHDL pentru

definirea unei funcţii

Tabelul T3.11 Program VHDL pentru descrierea funcţiei de

interdicţie (inhibit)

Capitolul 3

36

Standardul logic IEEE defineşte multe funcţii care lucrează cu tipurile standard std_logic şi std_logic_vector, aceste funcţii definesc operaţiile logice şi aritmetice de bază (and, or, +, - …). Facilitatea overload operators (supraîncărcarea operatorilor) oferită de VHDL îi permite utilizatorului să apeleze o funcţie care este invocată ori de câte ori se foloseşte unul din operatorii cunoscuţi (and, or, +, etc). În VHDL pot să existe câteva definiţii diferite pentru fiecare operator (overload), dar compilatorul va alege în mod automat definiţia care se potriveşte tipului de operanzi cu care este asociat operatorul. Un exemplu elocvent de definire a operatorului and din cadrul pachetului (package) standard IEEE definit pentru operanzi de tip std_logic este prezentat în tabelul T3.13.

Tabelul T3.12 Definirea operatorului and

pentru valori de tip STD_LOGIC în cadrul package-ului IEEE 1164

Argumentele funcţiei (intrările) trebuie să fie de tipul std_ulogic sau de subtipul std_logic. În cod mai este definit subtipul UX01, pentru valoarea returnată de funcţie. Tipul stdlogic_table o matrice bidimensională 9 X 9 care are ca şi index o pereche de valori de tipul std_ulogic. În tabelul T3.12 (and_table,) valorile sunt astfel aranjate încât atunci când ambii indecşi (linie(L), coloană (R)), sunt ‘0’ sau ‘L’ (L= un zero logic mai slab), valoarea returnată este ‘0’, iar când ambele valori ale indecşilor sunt ‘1’ sau ‘H’ (H= un unu logic mai slab), valoarea returnată va fi ‘1’, în alte cazuri apar numai valorile ‘U’ sau ‘X’. Se poate observa că denumirea funcţiei este pusă între ghilimele, ceea ce denotă că operatorul and este “supraîncărcat” (overload operator). Partea “executabilă” a funcţiei este o simplă declaraţie care returnează elementele indexate ale funcţiei în funcţie de valoarea celor două intrări L şi R.

Introducere în limbajul de descriere hardware – VHDL

37

Datorită faptului că VHDL-ul este un limbaj puternic tipizat, adesea apare necesitatea convertiri unui semnal sau variabile dintr-un anumit tip în altul. Package-ul IEEE 1164 conţine câteva astfel de funcţii de conversie, de exemplu din BIT în STD_LOGIC sau invers. O conversie foarte utilizată şi care nu este definită, din cauză că proiecte diferite pot avea nevoie de o interpretare diferită a numerelor (ex. numere cu semn sau fără semn), este conversia din STD_LOGIC_VECTOR în integer. În tabelele 3.13 şi 3.14 sunt prezentate exemple pentru conversia mai sus amintită. Funcţia CONV_INTEGER din tabelul T3.13 foloseşte un algoritm simplu de iterare. Semnificaţiile instrucţiunilor FOR, CASE şi WHEN vor fi descrise mai pe larg într-o secţiune care urmează (momentan ne bazăm pe cunoştinţele d-voastră prealabile de programare), instrucţiunea null înseamnă “nu face nimic”. Domeniul pe care se manifestă instrucţiunea de ciclare FOR, se specifică în cod prin sintaxa “X’range”, în care semnul apostrof dat după numele unui semnal specifică folosirea unui atribut (“attribute”). În cazul nostru atributul este range care este implicit, se aplică numai ariilor şi are semnificaţia “parcurge indexul ariei de la stânga la dreapta”. Conversia în sens invers din integer în STD_LOGIC_VECTO este funcţia CONV_STD_LOGIC_VECTOR şi este prezentată în tabelul T3.13. Tabelul T3.13 Funcţie VHDL pentru conversia din STD_LOGIC_VECTOR în integer

În acest caz pe lângă valoarea întreagă care trebuie convertită (ARG) mai trebuie specificat şi pe câţi biţi să fie exprimat rezultatul (SIZE). Variabila (result) declarată local în funcţie are o valoare a indexului dependentă de valoarea intrării (SIZE), din acest motiv valoarea atribuită acestei intrări a funcţiei trebuie să fie o constantă sau o mărime care este recunoscută de compilator. Pentru efectuarea conversiei în funcţie s-a folosit algoritmul de împărţiri succesive. În limbajul VHDL mai este definită noţiunea de procedură (procedure) care este similară cu funcţia doar că nu returnează o valoare. La fel cum o funcţie poate fi apelată în locul unei expresii şi o procedură poate fi apelată în locul unei declaraţii. Dacă argumentele unei proceduri sunt declarate de tipul out sau inout, va exista totuşi o valoare returnată.

Capitolul 3

38

Tabelul T3.14 Funcţie VHDL pentru conversia din integer în STD_LOGIC_VECTOR

3.6 Biblioteci şi package-uri

O bibliotecă (library) VHDL este locul unde compilatorul depune toate informaţiile despre un anumit proiect şi anume toate fişierele intermediare folosite în analiza, simularea şi sinteza proiectului. Pentru un proiect VHDL dat compilatorul creează şi foloseşte în mod automat o bibliotecă numită work. Un proiect complex conţine de obicei mai multe fişiere, fiecare incluzând diferite unităţi de proiect, cum ar fi entităţi şi arhitecturi. În momentul în care un compilator analizează fiecare fişier din proiect, el plasează rezultatele în biblioteca work şi de asemenea din această bibliotecă ia informaţii despre alte entităţi dacă este cazul. Astfel un proiect mai complex va putea fi împărţit în mai multe fişiere, iar compilatorul le va analiza pe fiecare în parte. Deoarece nu toate informaţiile necesare unui proiect se află în bibliotecă work (care este de obicei un subdirector în cadrul proiectului) trebuie să ne referim la o bibliotecă standard care conţine elemente (funcţii, tipuri, etc) predefinite. În VHDL această referire se face folosind directiva library la începutul codului VHDL, ex. library ieee;. Prin specificarea numelui bibliotecii se obţine acces la toate entităţile şi arhitecturile aflate în biblioteca respectivă, dar nu dă acces la tipurile definite acesta fiind rolul package-urilor şi al directivei use. Un package este un fişier care conţine obiecte definite care pot fi folosite în alte programe. Tipurile de obiecte care se află într-un package sunt: semnale, definiri de tipuri, constante, funcţii, proceduri şi declarări de componente. Un proiect poate folosii un package dacă în codul VHDL se include directiva use, de exemplu pentru a apela toate componentele definite în package-ul standard IEEE 1164 scriem următoarea secvenţă de cod: use ieee.std_logic_1163.all;, unde ieee este numele unei librării care a fost dat împreună cu directiva library. Sintaxa std_logic_1164 este numele unui fişier care conţine componentele definite, iar sufixul all îi spune compilatorului să le folosească pe toate. În locul respectivului sufix se poate scrie numai numele unei anumite componente care să fie luată în considerare de compilator, ex. use ieee.std_logic_1163.std_ulogic.

Introducere în limbajul de descriere hardware – VHDL

39

Definirea package-urilor nu se limitează doar la cele standard aflate în biblioteci, utilizatorul poate el însuşi să-şi definească package-uri conform sintaxei din tabelul T3.15.

Tabelul T3.15 Sintaxa VHDL pentru declararea unui package

Toate obiectele declarate între cuvântul cheie package şi primul cuvânt cheie end sunt “vizibile “ în toate fişierele din proiect care folosesc package-ul respectiv, iar obiectele care urmează cuvântului cheie package body sunt vizibile doar local. În prima parte a sintaxei funcţiile sunt doar declarate (function declarations) nu şi definite ceea ce înseamnă că este vizibil doar numele funcţiei, argumentele şi tipurile, definiţia funcţiei fiind dată în corpul package-ului (package body) şi nu este vizibilă pentru utilizatorul funcţiei.

3.7 Elemente de descriere structurală

Începând cu acest paragraf vom studia partea “executabilă” a unei arhitecturi, practic inima unui cod scris în limbaj VHDL. Reamintim dintr-un paragraf anterior că o arhitectură este formată dintr-o serie de instrucţiuni concurente (concurrent statement), fiecare astfel de instrucţiune fiind executată simultan cu celelalte instrucţiuni din arhitectură. Această executare concurenţială a anumitor instrucţiuni distinge limbajul VHDL faţă de alte limbaje de programare în care instrucţiunile se execută secvenţială (câte una la un moment dat). Instrucţiunile concurente sunt necesare pentru a putea simula comportamentul circuitelor modelate, în care componentele interacţionează unele cu altele în mod continuu şi nu numai la anumite momente ordonate în timp. Într-o arhitectură VHDL dacă ultima instrucţiune modifică starea unui semnal care este folosit de prima instrucţiune din arhitectură atunci simulatorul se va întoarce la prima instrucţiune şi o va reactualiza cu noua valoare, cu alte cuvinte simulatorul va continua să propage schimbările şi să reactualizeze valorile semnalelor până când circuitul simulat se stabilizează.

Capitolul 3

40

Sintaxa VHDL conţine câteva instrucţiuni concurenţiale şi de asemenea un mecanism de grupare a instrucţiunilor secvenţiale astfel încât ele să funcţioneze ca şi o sigură instrucţiune concurenţială. Cea mai elementară instrucţiune concurenţială este instrucţiunea component, a cărei sintaxă este prezentată în tabelul T3.16. Tabelul T3.16 Sintaxa VHDL pentru instrucţiunea component

Numele componentei (component_name) este numele unei entităţi definite anterior care trebuie utilizată sau instanţiată (multiplicată). Fiecare instrucţiune component care invocă numele entităţi creează o “clonă” (instanţă) respectivei entităţi care se va distinge printr-un nume unic dat de o etichetă (label). Cuvântul cheie port map introduce o listă care asociază porturile componentelor rezultate din instanţierea unei entităţi cu arhitectura corespunzătoare entităţii instanţiate. Această listă se poate scrie în două moduri: poziţional şi asociativ. În modul poziţional de atribuire semnalele din listă sunt asociate cu porturile entităţii în aceeaşi ordine în care apar în entitate. În modul de atribuire asociativ fiecare port al entităţii se asociază unui semnal folosind operatorul “=>”, iar asocierea poate fi făcută în orice ordine. Înainte de a fi instanţiată într-o arhitectură, o componentă trebuie să fie declarată în cadrul arhitecturii, sintaxa de declarare este prezentată în tabelul 3.17. După cum se poate observa în tabel declararea unei componente este asemănătoare cu declararea porturilor entităţii ce urmează a fi instanţiate. Componentele folosite în arhitectură pot să fie de două tipuri: a) componente descrise anterior care sunt specifice proiectului sau, b) componente care sunt apelate din bibliotecile standard. Pentru a pune cap la cap toate cele discutate până aici, în tabelul T3.18 este prezentată descrierea VHDL completă a unui detector de numere prime, iar în figura 3.4 este prezentată descrierea simbolică cu porţi logice a detectorului de numere prime.

Tabelul T3.17 Sintaxa pentru declararea unei componente

Introducere în limbajul de descriere hardware – VHDL

41

Circuitul din figura 3.4 va pune o valoare 1 logic la ieşirea F ori de câte ori la intrare se va afla forma binară a unuia dintre numerele prime: 1,3,5,7,11,13, altfel ieşirea F va avea valoare 0 logic. Prin declararea entităţii se declară intrările şi ieşirile circuitului. În cadrul arhitecurii sunt declarate toate semnalele care vor fi folosite de asemenea şi numele componentelor (INV, AND2, AND3, AND4) care sunt predefinite şi vor fi apelate din biblioteca IEEE. Deoarece descrierea circuitului este concurenţială în orice ordine am introduce componentele se va sintetiza acelaşi circuit, iar funcţionarea va fi aceeaşi. Tabelul 3.18 Exemplu de descriere structurală în limbaj VHDL a unui detector de numere prime

Figura 3.4 Diagrama logică a detectorului de numere prime

Capitolul 3

42

Acest mod de descriere a unui circuit poartă numele de descriere structurală (structural description), deoarece defineşte exact elementele şi interconexiunile dintre ele. O descriere structurală pură este echivalentă cu o descriere schematică sau cu un netlist (listă de conexiuni între elementele unui circuit). Există proiecte în care este necesar să se creeze copii multiple a unui element în cadrul unei arhitecturi. După cum se va studia mai târziu un sumator pe n biţi se poate crea din n sumatoare pe un bit. Limbajul VHDL include o instrucţiune (generate) care permite crearea unei structuri repetitive folosind un fel de buclă, fără a fi necesar să instanţiem separat fiecare element. Sintaxa instrucţiuni generate este prezentată în tabelul T3.19.

Tabelul T3.19 Sintaxa VHDL

pentru bucla for-generate

Identificatorul (indetifier) este implicit declarat ca şi variabilă compatibilă cu domeniul (range), iar instrucţiunile concurente (concurent statement) se execută odată pentru fiecare valoare din domeniu a identificatorului.

Identificatorul trebuie folosit în zona de declarare a instrucţiunilor concurenţiale. În tabelul T3.20 este prezentat un exemplu de utilizare a instrucţiunii generate, în cazul creării unei porţi inversoare pe 8-biţi. Valoarea constantei trebuie cunoscută în momentul în care programul VHDL este compilat.

Tabelul T3.20 Entitatea şi arhitectura VHDL corespunzătoare unei porţi inversoare pe 8-biţi

Introducere în limbajul de descriere hardware – VHDL

43

Tabelul T3.21 Sintaxa VHDL pentru declararea constantei generic

În unele aplicaţii este util să se proiecteze şi să se compileze o entitate împreună cu arhitectura corespunzătoare care să conţină unii parametrii (cum ar fi lăţimea busului) care nu sunt specificaţi, această facilitate este introdusă de constanta generic a cărei sintaxă este prezentată în tabelul T3.21. Rolul constantei generic (vezi constanta width, tabelul T3.22) va fi definit în continuare în cadrul arhitecturii, dar o valoare îi va fi atribuită numai când entitatea va fi instanţiată în cadrul altei arhitecturi (vezi tabelul T3.23). În cadrul definirii componentelor, constantelor generic li se atribuie valori folosind instrucţiunea generic map, asemănătoare cu instrucţiunea port map. În tabelul T3.22 se dă un exemplu de definire a unui bus inversor de lăţime variabilă care combină instrucţiunile generic şi generate. Un exemplu de folosire a instrucţiunii generic este dat în tabelul T3.23 unde se definesc multiple copii ale unui inversor.

Tabelul T3.22 Descriere în limbaj VHDL a unui bus de lăţime variabilă

Capitolul 3

44

Tabelul T3.23 Entitate şi arhitectură VHDL care definesc un bus inversor

3.8 Elemente specifice proiectării concurenţiale

Dacă instrucţiunile de declarare a componentelor ar fi singurele instrucţiuni concurenţiale ale limbajului VHDL, acesta nu ar fi decât un limbaj puternic tipizat care ar face o descriere ierarhică sub formă de netlist a circuitelor. Limbajul VHDL dispune însă de modalităţi mai complexe de descriere a circuitelor este vorba de descrierea concurenţială a cărei introducere am făcut-o în paragraful anterior (urmează să fie dezvoltată în continuare) şi de descrierea secvenţială. În tabelul T3.24 se prezintă două elemente de limbaj VHDL care apar în descrierile de tip concurenţial. Primul din cele două elemente este instrucţiunea de atribuire concurenţială de semnal (signal-name<=expression). Tipul expresiei (expression) trebuie să fie compatibil cu cel al semnalului (signal-name). Pentru a exemplifica atribuirea concurenţială de semnal arhitectura detectorului de numere prime prezentat într-un paragraf anterior este rescrisă în stil concurenţial (vezi tabelul T3.25). Spre deosebire de descrierea anterioară (descriere structurală) porţile şi conexiunile dintre ele nu mai apar explicit, ci se folosesc operatori VHDL definiţi implicit în biblioteca IEEE (and, or, not). Se observă că operatorul not are prioritatea cea mai mare, astfel că nu este necesar să se utilizeze paranteze pentru expresii de genul “not N(2)”.

Introducere în limbajul de descriere hardware – VHDL

45

Tabelul T3.24 Sintaxa VHDL pentru atribuire concurenţială de semnal

Tabelul T3.25 Descriere concurenţială a arhitecturii detectorului de numere prime

Conform tabelului 3.24 mai există o opţiune de atribuire concurenţială de semnalelor şi anume atribuirea condiţională folosind cuvintele cheie when şi else. În acest caz o expresie booleană (boolean-expression)combină termeni booleeni individuali folosind operatori impliciţi (and, or, not)Termenii booleeni sunt de obicei variabile sau rezultate ale unor comparaţii făcute cu ajutorul operatorilor relaţionali (=, /= (inegaliate), >, >=, <, <= (mai mic sau egal)). În tabelul T3.26 este dat un exemplu al utilizării atribuiri condiţionale de semnal secvenţial. Comparaţia unui bit de tip std_logic cum ar fi N(3) se face în funcţie de caracterele literale ‘1’ sau ‘0’, iar rezultatul returnat este de tip boolean. Rezultatul acestor comparaţii se combină într-o expresie booleană plasată între cuvintele cheie when, else. Clauza else este obligatorie deoarece setul de condiţii dintr-o expresie trebuie să acopere toate combinaţiile posibile. Un alt tip de atribuire concurenţială este atribuirea concurenţială de semnal selectivă, a cărei sintaxă este prezentată în tabelul T3.26. În acest tip de instrucţiune, se evaluează expresia dată (expression), iar când una dintre valori se potriveşte cu una dintre opţiuni (choices) atunci identificatorului signal-name i se va atribui valoarea corespunzătoare signal-value. Opţiunea choices corespunzătoare fiecărei clauze when poate să fie o singură valoare sau o listă de valori separate între ele prin bara verticală ( | ). Cuvântul cheie others poate fi folosit împreună cu ultima clauză when pentru a acoperii toate valorile pe care le poate lua expresia de evaluare. În tabelul T3.27 este prezentată o altă arhitectură a detectorului de numere prime în care se foloseşte atribuirea concurenţială selectivă de semnal. Toate

Capitolul 3

46

opţiunile pentru care F ia valoarea ‘1’ ar fi putut fi scrise folosind o singură clauză when, dar pentru o înţelegere mai bună s-au folosit mai multe clauze.

Tabelul T3.26 Sintaxa VHDL

pentru atribuire concurenţială selectivă de semnal

Tabelul T3.27 Arhitectura VHDL corespunzătoare detectorului de numere prime

folosind atribuire concurenţială selectivă de semnal

3.9 Elemente specifice proiectării comportamentale (secvenţiale)

În paragraful anterior am putut vedea câteva descrieri comportamentale concurenţiale, dar pentru ca aceste descrieri comportamentale să fie mai complete este necesar să definim noi elemente de limbaj. Un element de descriere comportamentală cheie este procesul. Un proces (process) este o colecţie de instrucţiuni secvenţiale care se execută în paralel cu alte instrucţiuni concurenţiale sau alte procese. În cadrul unui proces utilizatorul poate definii interacţiuni complexe ale semnalelor şi evenimentelor într-o manieră care în timpul simulării se execută instantaneu (zero simulated time) şi care se sintetizează sub forma unui circuit combinaţional sau secvenţial. Instrucţiunea process poate fi folosită la fel ca o instrucţiune concurenţială şi are sintaxa prezentată în tabelul T3.28. Într-un proces sunt vizibile numai tipurile, semnalele constantele funcţiile şi procedurile care fac parte din aceeaşi arhitectură cu procesul, însă toate elementele enumerate mai sus cu excepţia semnalelor pot fi definite şi local în proces. În cadrul

Introducere în limbajul de descriere hardware – VHDL

47

unui proces, variabilele au rolul de a păstra stări, ele nu sunt vizibile în afara procesului, iar corespondentul fizic într-un circuit real poate să fie (dar nu întotdeauna) un semnal aceasta depinzând de felul în care sunt descrise. Sintaxa VHDL pentru definirea unei variabile este asemănătoare cu cea pentru definirea unui semnal, “variable variable-names: variable-types;”.

Tabelul T3.28 Sintaxa VHDL pentru definirea unui proces

Semnalele care se află în paranteze alături de cuvântul cheie process, determină dacă procesul rulează sau dacă va fi suspendat, această listă de semnale poartă numele de listă de senzitivităţi (sensitivity list). Presupunem că un proces este suspendat iniţial, dacă unul dintre semnalele aflate în lista de senzitivităţi îşi schimbă valoarea, procesul se va declanşa reluându-se executarea instrucţiunilor de la prima până la ultima. Dacă oricare dintre semnalele din lista de senzitivităţi îşi schimbă valoarea ca rezultat al rulării anterioare a procesului, atunci procesul se reia din nou, astfel că acesta va rula până în momentul în care nici unul dintre semnale nu-şi mai schimbă valoarea. Toate evenimentele din cadrul unui proces au loc, în cadrul unei simulări într-un “timp de simulare” egal cu zero. Un proces descris corect în VHDL se va suspenda după una sau mai multe rulări, trebuie să se evite modelarea proceselor care nu se suspendă niciodată. Lista de senzitivităţi este opţională, procesele care nu au listă de senzitivităţi încep să ruleze în cadrul simulării la momentul zero, aceste procese vom vedea ulterior sunt utile pentru modelarea test bench-urilor. Limbajul VHDL are câteva tipuri de instrucţiuni secvenţiale. Un prim tip este atribuirea secvenţială de semnal (sequential signal-assignment), aceasta are aceeaşi sintaxă ca şi versiunea concurenţială , “signal-name<=expression;”. Un tip de atribuire similară există şi pentru variabile, dar diferă operatorul de atribuire, “variable-name := expression”. În tabelul T3.29 se prezintă o nouă arhitectură a detectorului de numere prime rescrisă ca şi proces. În cadrul acestei arhitecturi (prime6_arch) există doar o singură instrucţiune concurenţială, aceasta este instrucţiunea process. În lista de senzitivităţi a procesului apare intrarea N, iar în cadrul procesului se definesc variabile, definirea de semnale nu este permisă.

Capitolul 3

48

O altă instrucţiune secvenţială este instrucţiunea if, tipurile de sintaxă care se pot folosii pentru această instrucţiune sunt prezentate în tabelul T3.30. În prima formă a acestei instrucţiuni o expresie booleană este testată (boolean epression) şi se va executa o instrucţiune secvenţială (sequeential statement) dacă expresia testată este adevărată. În cea de a doua formă se mai adaugă şi clauza else urmată de o altă instrucţiune secvenţială care se execută în cazul în care expresia testată este falsă (nu se verifică). Pentru a crea un model if-then-else imbricat în limbajul VHDL se introduce cuvântul cheie elsif. O instrucţiune secvenţială care conţine clauza elsif se execută dacă expresia booleană care-i corespunde este adevărată şi toate expresiile precedente sunt false. Instrucţiunea secvenţială corespunzătoare clauzei finale else se execută dacă toate expresiile booleene precedente au fost false.

Tabelul T3.29 Arhitectura VHDL a detectorului de numere prime descrisă ca şi proces

Tabelul T3.30 Sintaxa VHDL corespunzătoare instrucţiunii if

Introducere în limbajul de descriere hardware – VHDL

49

O altă versiune de arhitectură a detectorului de numere prime este prezentată în tabelul T3.31, de această dată descrierea VHDL este făcută folosindu-se instrucţiunea if. În acest caz se foloseşte o variabilă NI de tipul întreg folosită pentru a păstra valoarea întreagă rezultată în urma convertiri intrării N. Expresiile booleene din tabelul T3.31 nu se suprapun, aceasta înseamnă că numai una dintre ele este adevărată la un moment dat. În acest caz folosirea instrucţiunii if imbricate s-a făcut doar în scop didactic, era suficient să se folosească forma mai simplă a instrucţiuni. În cazul în care trebuie aleasă o singură alternativă din multitudinea de alternative oferite de valorile pe care le poate lua un semnal sau o expresie, se va apela la instrucţiunea case, care este mai explicită şi poate să se sintetizeze într-un circuit mai optim. Sintaxa instrucţiunii case este prezentată în tabelul T3.33. Această instrucţiune evaluează o expresie dată, alege valoarea care se potriveşte din una din alternative (choices) şi execută instrucţiunea secvenţială corespunzătoare. Alternativele (choices) sunt reprezentate de o singură valoare sau de un set de valori separate prin bare verticale, aceste alternative trebuie să se excludă una pe cealaltă şi trebuie să includă toate valorile posibile ale expresiei evaluate, altfel se foloseşte clauza others.

Tabelul T3.31 Arhitectura VHDL a detectorului de numere prime folosind instrucţiunea if

Tabelul T3.32 Sintaxa VHDL

corespunzătoare instrucţiunii case

Tabelul T3.33 Arhitectura VHDL a detectorului

de numere prime folosind instrucţiunea case

Capitolul 3

50

În tabelul T3.33 este prezentată o nouă arhitectură pentru detectorul de numere prime, de această dată modelarea în limbaj VHDL s-a realizat utilizând instrucţiunea case. O altă clasă importantă de instrucţiuni secvenţiale sunt instrucţiunile loop, forma cea mai simplă a sintaxei este prezentată în tabelul T3.33. O altă formă mai cunoscută a acestui tip de instrucţiuni este for loop cu sintaxa prezentată în tabelul T3.35. Variabila identifier se declară implicit şi este de acelaşi tip cu domeniul (range), pe care îl parcurge de la stânga la dreapta câte o valoare per iteraţie.

Tabelul T3.34 Sintaxa de bază

a instrucţiunii loop

Tabelul T3.35 Sintaxa instrucţiunii for loop

Tabelul T3.36 Arhitectura VHDL a detectorului de numere prime folosind instrucţiunea for loop

Alte două instrucţiuni secvenţiale care se pot executa în cadrul unei instrucţiuni loop sunt exit şi next. Instrucţiunea exit are rolul de a transfera

Introducere în limbajul de descriere hardware – VHDL

51

executarea programului primei instrucţiuni aflate după cuvântul cheie end corespunzător încheierii buclei. Cea de a doua instrucţiune, next are rolul de a abandona executarea instrucţiunilor din buclă care urmează după ea şi de a trece la o nouă iteraţie (parcurgere a buclei). Un exemplu de arhitectură în care se foloseşte instrucţiunea for loop este prezentat în tabelul T3.36. Aceasta este o descriere pur comportamentală a arhitecturii detectorului de numere prime. Pentru a explica “puterea “ unei instrucţiuni loop s-a mărit valoarea lui N la 16. Descrierea din tabelul T3.36 este pur didactică deoarece operatorul mod care presupune împărţire nu este sintetizabil. Tabelul T3.37 Sintaxa instrucţiunii

while loop

Ultima instrucţiune de ciclare studiată este instrucţiunea while loop, a cărei sintaxă este prezentată în tabelul T3.37. În acest tip de instrucţiune expresia booleană (boolean-expression) este testată înaintea de fiecare iteraţie, iar bucla se execută numai dacă valoarea expresiei este adevărată.

3.10 Definirea întârzierilor

Nici unul dintre exemplele VHDL prezentate până în acest punct nu tratează întârzierile care apar în circuitele reale, dar limbajul permite modelarea acestor întârzieri. Unul dintre cuvintele cheie care permit introducerea întârzierilor este after care poate fi asociat cu orice tip de atribuire de semnal (secvenţială, concurenţială, condiţională şi selectată). Arhitectura porţi logice interdicţie (BUT-NOT), poate fi rescrisă după cum urmează:

Z <= ‘1’ after 4ns when X = ‘1’ and Y =’0’ else ‘0’ after 3 ns;

Această poartă este astfel modelată încât semnalul de ieşire faţă de cel de intrare va avea o întârziere de 4ns la tranziţia din 0 în 1 şi 3ns la tranziţia din 1 în 0. O altă instrucţiune care invocă dimensiunea timp este instrucţiunea secvenţială wait. Aceasta poate fi folosită pentru a suspenda executarea unui proces pentru o anumită perioadă de timp. În tabelul T3.38 este prezentat un program aşa numit test-bench, care foloseşte instrucţiunea wait pentru a genera formele de undă simulate necesare la testarea funcţionării porţii logice interdicţie. Cele două instrucţiuni care invocă dimensiunea timp prezentate anterior nu sunt sintetizabile ele sunt utile însă la modelarea test-bench-urilor.

Capitolul 3

52

Tabelul T3.38 Test-bench-ul corespunzător porţii logice de interdicţie

3.11 Sinteza circuitelor modelate cu limbajul VHDL

După cum s-a afirmat şi la începutul acestei secţiuni limbajul VHDL a fost mai întâi dezvoltat ca limbaj de descriere şi simulare a circuitelor şi abia mai târziu acest limbaj a fost adaptat pentru sinteză. Astfel că limbajul are multe caracteristici şi construcţii care nu pot fi sintetizate. Subsetul de instrucţiuni şi programe prezentate în această secţiune sunt sintetizabile majoritatea. Trebuie de reţinut că modul în care este descris un circuit în VHDL, se răsfrânge asupra “calităţi” circuitului sintetizat, în continuare sunt prezentate câteva recomandări: - Structurile de control seriale de tipul if-elsif-elsif-else pot fi sintetizate sub forma

unui lanţ serial de porţi logice, ceea ce favorizează întârzierile, astfel că în acest caz este mai bine să se folosească instrucţiunile de selecţie case sau with dacă condiţiile se exclud reciproc.

- În cazul în care se folosesc instrucţiuni condiţionale în cadrul unui proces, dacă pentru o anumită combinaţie a intrărilor se omite specificarea valori pe care trebuie să o ia aibă ieşirea, compilatorul va crea un latch la ieşire care să poată păstra vechea valoare a semnalului de ieşire care altfel ar trebui să se schimbe. În general generarea unui astfel de latch nu este dorită.

- Instrucţiunile de ciclare creează în general copii multiple ale logicii combinaţionale descrise în cadrul instrucţiunii. Dacă se doreşte folosirea unei singure astfel copii a logici combinaţionale într-o secvenţă de paşi atunci trebuie să se proiecteze un circuit secvenţial.

Introducere în limbajul de descriere hardware – VHDL

53

Este posibil ca sinteza unor construcţii şi structuri ale limbajului să nu fie posibilă cu anumite

programe de sinteză, pentru aceasta trebuie consultată documentaţia respectivelor programe

pentru a vedea ce este şi ce nu este sintetizabil.


Recommended