Documente Academic
Documente Profesional
Documente Cultură
Instr Secventiale
Instr Secventiale
O descriere n limbajul VHDL are dou domenii: un domeniu secvenial i un domeniu concurent. Domeniul secvenial este reprezentat de un proces sau subprogram care conine instruciuni secveniale. Aceste instruciuni sunt executate n ordinea n care apar n cadrul procesului sau subprogramului, ca i n cazul limbajelor de programare. Domeniul concurent este reprezentat de o arhitectur, care conine procese, apeluri concurente de proceduri, asi gnri concurente ale semnalelor i instanieri de componente. Toate activitile descrise de acestea au loc simultan. n aceast lucrare se descrie formatul i modul de utilizare al unor instruciuni secveniale. Sunt prezentate unele probleme legate de sinteza logic a instruciunilor secveniale i sunt ilustrate circuitele sintetizate din aceste instruciuni. n seciunile urmtoare se descriu mai nti unele aspecte legate de procese, cum sunt modul de specificare al unui proces, execuia unui proces, instruciunea wait i deosebirea dintre procesele combinaionale i cele secveniale. Sunt prezentate apoi instruciunile secve niale care pot apare ntr-un proces sau subprogram: asignarea secvenial a semnalelor, asignarea variabilelor, instruciunea if, instruciunea case i instruciunile de buclare. Pe lng acestea, alte instruciuni secveniale sunt instruciunea de apel a unei proceduri i instruciunea de revenire dintr-o procedur sau funcie.
Declaraia unui proces este cuprins ntre cuvintele cheie process i end process. Unui proces i se poate asigna n mod opional un nume pentru identificarea mai uoar a pr ocesului n textul surs. Numele este un identificator i trebuie urmat de caracterul ':' (cu rol de etichet). Acest nume este util i pentru simulare, de exemplu, pentru setarea u nui punct de ntrerupere a execuiei simulrii. Numele poate fi repetat la sfritul declaraiei, dup cuvint ele cheie end process. Lista de sensibilitate (opional) este lista semnalelor la a cror modificare procesul este sensibil. Producerea unui eveniment asupra unuia din semnalele specificate n lista de sensibilitate va determina execuia instruciunilor secveniale din cadrul procesului, similar cu
instruciunile dintr-un program obinuit. Spre deosebire de un limbaj de programare, n limbajul VHDL clauza end process nu specific terminarea execuiei procesului. Procesul va fi executat ntr-un ciclu infinit, iar n cazul n care se specific o list de sensibilitate, procesul va fi doar suspendat dup execuia ultimei instruciuni, pn la producerea unui nou eveniment asupra semnalelor din list. Se menioneaz c un eveniment are loc numai la modific area valorii unui semnal. Astfel, asignarea aceleiai valori la un semnal nu reprezint un ev eniment. n cazul n care lista de sensibilitate lipsete, procesul va fi executat n mod continuu. n acest caz, procesul trebuie s conin o instruciune wait pentru a determina suspendarea procesului i activarea acestuia la apariia unui eveniment sau ndeplinirea unei condiii. n cazul n care lista de sensibilitate este prezent, procesul nu poate conine instruciuni wait. Instruciunea wait este prezentat n seciunea 1.1.2. Partea declarativ a procesului este cuprins ntre cuvintele cheie process i begin. n aceast parte se pot declara tipuri, constante, variabile i subprograme (proceduri i funcii) care sunt locale procesului. Elementele declarate se pot utiliza deci numai n interiorul procesului.
Observaie
n interiorul unui proces nu pot fi declarate semnale, ci numai constante i variabile. Partea de instruciuni a procesului ncepe dup cuvntul cheie begin. Aceast parte conine instruciunile care vor fi executate la fiecare activare a procesului. Nu este permis utilizarea instruciunilor concurente n interiorul unui proces. n Exemplul 1 se prezint declaraia unui proces simplu format dintr -o singur instruciune de asignare secvenial.
Exemplul 1
proc1: process (a, b, c) begin x <= a and b and c; end process proc1;
Exemplul 2
proc2: process begin x <= a and b and c; wait on a, b, c; end process proc2;
Instruciunea wait on a fost ilustrat n exemplele precedente. Instruciunea wait until suspend un proces pn cnd condiia specificat devine adevrat datorit modificrii unuia din semnalele care apar n expresia condiional. Se menioneaz c dac nici un semnal din aceast expresie nu se modific, procesul nu va fi activat, chiar dac expresia condiional este adevrat. Exemplele urmtoare prezint mai multe forme ale instruciunii wait until:
wait until semnal = valoare; wait until semnalevent and semnal = valoare; wait until not semnalstable and semnal = valoare;
unde semnal este numele unui semnal, iar valoare este valoarea care se testeaz. Dac semnalul este de tip bit, atunci pentru valoarea '1' se ateapt frontul cresctor al semnalului, iar pentru '0' frontul descresctor. Instruciunea wait until se poate utiliza pentru implementarea unei funcionri sincrone. n mod obinuit, semnalul testat este un semnal de ceas. De exemplu, ateptarea frontului cresctor al unui semnal de ceas se poate exprima n urmtoarele moduri:
wait until clk = '1'; wait until clk'event and clk = '1'; wait until not clk'stable and clk = '1';
Pentru descrierile destinate sintezei, instruciunea wait until trebuie s fie prima din cadrul procesului. Din aceast cauz, logica sincron descris cu o instruciune wait until nu poate fi resetat n mod asincron. Instruciunea wait for permite suspendarea execuiei unui proces pentru un timp specificat, de exemplu:
wait for 10 ns;
Observaie
Forma wait for expresie_de_timp a instruciunii wait nu se poate utiliza pentru sintez. Se pot combina mai multe condiii ale instruciunii wait ntr-o condiie mixt. n Exemplul 3, procesul proc3 va fi activat la modificarea valorii unuia din semnalele a sau b, dar numai atunci cnd valoarea semnalului clk este '1'.
Exemplul 3
proc3: process begin wait on a, b until clk = '1'; ... end process proc3;
Ca rezultat al execuiei acestei instruciuni ntr-un proces, se evalueaz expresia din dreapta simbolului de asignare i se planific un eveniment care const din modificarea val orii semnalului. Simulatorul va modifica ns valoarea semnalului doar n momentul n care procesul va fi suspendat, iar n cazul n care se utilizeaz clauza after, dup ntrzierea specificat din acest moment. Deci, ntr-un proces semnalele vor fi actualizate doar dup execuia tuturor instruciunilor din cadrul procesului sau la ntlnirea unei instruciuni wait. n mod tipic, sistemele de sintez nu permit utilizarea clauzelor after, sau ignor aceste clauze. Clauzele after sunt ignorate nu numai deoarece interpretarea lor pentru sintez nu este specificat de standarde, ci i pentru c ar fi dificil garanta rea rezultatelor unor asemenea ntrzieri. De exemplu, nu este clar dac ntrzierea ar trebui interpretat ca o nt rziere de propagare minim sau maxim. De asemenea, nu este clar cum trebuie s procedeze programul de sintez dac o ntrziere specificat n codul surs nu poate fi asigurat. O consecin a modului n care se execut asignarea semnalelor n cadrul proceselor este c n cazul n care exist mai multe asignri a unor valori diferite la acelai semnal, va avea efect doar ultima asignare. Astfel, cele dou procese din Exemplul 4 sunt echivalente.
Exemplul 4
proc4: process (a) begin z <= '0'; z <= a; end process proc4; proc5: process (a) begin z <= a; end process proc5;
n concluzie, trebuie s se in cont de urmtoarele aspecte importante la utilizarea instruciunilor de asignare a semnalelor n interiorul proceselor: Orice asignare a unei valori la un semnal devine efectiv numai atunci cnd procesul este suspendat. Pn n acel moment, toate semnalele i pstreaz vechea valoare. Numai ultima asignare a unei valori la un semnal va fi executat efectiv. Deci, nu are sens s se asigneze mai mult de o valoare la un semnal n acelai proces.
1.3. Variabile
Restriciile impuse asupra semnalelor reduc posibilitile de utilizare ale acestora. Deoarece semnalele pot pstra numai ultima valoare asignat, ele nu pot fi utilizate pentru memorarea rezultatelor intermediare sau temporare n cadrul unui proces. Un alt inconvenient este c noile valori sunt asignate semnalelor nu n momentul execuiei instruciunii de asignare, ci dup suspendarea execuiei procesului. Aceasta determin ca analiza unei descrieri s fie dificil. Spre deosebire de semnale, variabilele pot fi declarate n interiorul unui proces i se pot utiliza pentru memorarea rezultatelor intermediare. Variabilele pot fi utilizate ns numai n domeniul secvenial al limbajului VHDL, deci n interiorul proceselor sau subprogramelor, i nu pot fi declarate sau utilizate direct ntr-o arhitectur. Ele sunt deci locale procesului sau subprogramului respectiv.
Exemplul 5
variable variable variable variable variable a, b, c: bit; x, y: integer; index integer range 1 to 10 := 1; t_ciclu: time range 10 ns to 50 ns := 10 ns; mem: bit_vector (0 to 15);
Unei variabile i se atribuie o valoare iniial n faza de iniializare a simulrii. Aceast valoare iniial este fie cea specificat n mod explicit la declararea variabilei, fie o valoare implicit, care este valoarea cea mai din stnga a tipului. De exemplu, pentru tipul bit valoarea iniial implicit este '0', iar pentru tipul integer aceast valoare este -2.147.483.647.
Aceast instruciune este similar cu asignrile din majoritatea limbajelor de progr amare. Spre deosebire de o instruciune secvenial de asignare a semnalelor, asignarea unei variabile este executat instantaneu, deci ntr-un timp de simulare zero. Exist urmtoarele deosebiri principale ntre asignarea semnalelor i a variabilelor: n cazul asignrii semnalelor, se planific un eveniment pentru actualizarea valorii acestora, iar actualizarea se execut numai la suspendarea procesului, n timp ce pe ntru asignarea variabilelor nu se planific un eveniment, iar actualizarea se execut i nstantaneu. La asignarea semnalelor se poate specifica o ntrziere (numai pentru simulare), n timp ce asignarea variabilelor nu poate fi ntrziat. ntr-un proces, doar ultima asignare a unei valori la un semnal este efectiv. n schimb, pot exista numeroase asignri la o variabil n acelai proces, toate fiind efective. Exemplul 6 ilustreaz utilizarea variabilelor pentru memorarea rezultatelor intermediare.
Exemplul 6
library ieee; use ieee.std_logic_1164.all; entity add_1 is port (a, b, cin: in std_logic; s, cout: out std_logic); end add_1; architecture functional of add_1 is begin process (a, b, cin) variable s1, s2, c1, c2: std_logic; begin s1 := a xor b; c1 := a and b; s2 := s1 xor cin; c2 := s1 and cin; s <= s2; cout <= c1 or c2; end process; end functional;
Exemplul anterior descrie un sumator elementar. Acesta nu este modul optim de a descrie un sumator elementar, dar ilustreaz utilizarea variabilelor. Rezultatul se genereaz prin crearea a dou semisumatoare, primul genernd ieirile s1 i c1, iar al doilea genernd ieirile s2 i c2. n final, ieirile sunt asignate celor dou porturi de ieire s i cout prin instruciuni de asignare a semnalelor, deoarece porturile sunt semnale.
1.4. Instruciunea if
Instruciunea if selecteaz pentru execuie una sau mai multe secvene de instruciuni, n funcie de valoarea unei condiii corespunztoare secvenei respective. Sintaxa acestei instruciuni este urmtoarea:
if condiie then secven_de_instruciuni [elsif condiie then secven_de_instruciuni ...] [else secven_de_instruciuni] end if;
Fiecare condiie este o expresie boolean, care se evalueaz la valoarea TRUE sau FALSE. Pot exista mai multe clauze elsif, dar poate exista o singur clauz else. Se evalueaz mai nti condiia de dup cuvntul cheie if, i dac este adevrat, se execut secvena de instruciuni corespunztoare. n caz contrar, dac este prezent clauza elsif, se evalueaz condiia de dup aceast clauz i dac aceast condiie este adevrat, se execut secvena de instruciuni corespunztoare. n caz contrar, dac sunt prezente alte clauze elsif, se continu cu evaluarea condiiei acestor clauze. Dac nici o condiie evaluat nu este adevrat, se ex ecut secvena de instruciuni corespunztoare clauzei else, dac aceasta este prezent.
Exemplul 7
process (a, b) begin if a = b then rez <= 0; elsif a < b then rez <= -1; else rez <= 1; end if; end process;
Instruciunea case conine mai multe clauze when, fiecare specificnd una sau mai multe opiuni. Opiunile reprezint fie o valoare individual, fie un set de valori cu care se compar expresia instruciunii case. n cazul n care expresia este egal cu valoarea individual sau cu una din valorile setului, se execut secvena de instruciuni specificat dup simb o-
lul =>. O secven de instruciuni poate fi format i din instruciunea nul, null. Spre deosebire de anumite limbaje de programare, instruciunile dintr-o secven nu trebuie incluse ntre cuvintele cheie begin i end. Clauza others se poate utiliza pentru a specifica execuia unei secvene de instruciuni n cazul n care valoarea expresiei nu este egal cu nici una din valorile specificate n clauzele when. n cazul n care o opiune este reprezentat de un set de valori, se pot specifica fie valorile individuale din set, separate prin simbolul | avnd semnificaia sau, fie domeniul valorilor, fie o combinaie a acestora, dup cum se arat n exemplul urmtor.
case expresie is when val => secven_de_instruciuni when val1 | val2 | ... | valn => secven_de_instruciuni when val3 to val4 => secven_de_instruciuni when val5 to val6 | val7 to val8 => secven_de_instruciuni ... when others => secven_de_instruciuni end case;
Observaii
ntr-o instruciune case trebuie enumerate toate valorile posibile pe care le poate avea expresia de selecie, innd cont de tipul sau subtipul acesteia. De exemplu, dac expresia de selecie este de tip std_logic_vector de doi bii, trebuie enumerate 81 de valori, deoarece pentru un singur bit pot exista nou valori posibile. Dac nu sunt enumerate toate valorile, trebuie utilizat clauza others. Clauza others trebuie s fie ultima dintre toate opiunile. Exemplul 8 prezint un proces pentru secvenierea valorilor unui tip enumerat reprezentnd strile unui semafor. Procesul este descris cu ajutorul unei instruciuni case.
Exemplul 8
type tip_culoare is (rosu, galben, verde); signal culoare, culoare_urm: tip_culoare; process (culoare) case culoare is when rosu => culoare_urm <= verde; when galben => culoare_urm <= rosu; when verde => culoare_urm <= galben; end case; end process;
Exemplul 9 definete o entitate i o arhitectur pentru o poart SAU EXCLUSIV cu dou intrri. Poarta este descris n mod funcional cu ajutorul unui proces care conine o i nstruciune case.
Exemplul 9
library ieee; use ieee.std_logic_1164.all; entity xor_2 is port (a, b: in std_logic;
x: out std_logic); end xor_2; architecture arh_xor_2 of xor_2 is begin process (a, b) variable tmp: std_logic_vector (1 downto 0); begin tmp := a & b; case tmp is when "00" => x <= '0'; when "01" => x <= '1'; when "10" => x <= '1'; when "11" => x <= '0'; when others => x <= '0'; end case; end process; end arh_xor_2;
Observaie
Singura instruciune de buclare care poate fi utilizat pentru sinteza logic este instruciunea for loop, deoarece la aceasta numrul de iteraii este fix.
Instruciunea are o etichet opional, care poate fi utilizat pentru identificarea i nstruciunii. Instruciunea loop are ca efect repetarea instruciunilor din corpul buclei de un numr nelimitat de ori. n cazul acestei instruciuni, singura posibilitate de terminare a execuiei este utilizarea unei instruciuni exit (prezentat n seciunea 1.6.5).
Condiia este testat naintea fiecrei execuii a buclei. Dac aceast condiie este adevrat, se execut secvena de instruciuni din corpul buclei, dup care controlul este tran s-
10
ferat la nceputul buclei. Execuia buclei se termin atunci cnd condiia testat devine fals, caz n care se execut instruciunea care urmeaz dup clauza end loop.
Exemplul 10
process variable contor: integer := 0; begin wait until clk = '1'; while nivel = '1' loop contor := contor + 1; wait until clk = '0'; end loop; end process;
tat. Se testeaz doar dac acest semnal are valoarea '1' la detectarea unui front cresctor al semnalului clk, i nu se testeaz dac valoarea semnalului nivel s-a modificat de la testarea anterioar. Instruciunile de buclare pot fi imbricate pe mai multe nivele. Deci, corpul buclei unei instruciuni while loop poate conine o alt instruciune de buclare, n particular o instruc iune while loop, dup cum se arat n exemplul urmtor.
E1: E2: while i < 10 loop while j < 20 loop ... end loop E2; end loop E1;
ntr-o instruciune for loop se specific un contor de iteraii i un domeniu. Instruciunile din corpul buclei sunt executate ct timp contorul se afl n domeniul specificat. Dup terminarea unei iteraii, contorului i se asigneaz urmtoarea valoare din domeniu. Domeniul poate fi unul cresctor, specificat prin cuvntul cheie to, sau descresctor, specificat prin cuvntul cheie downto. Acest domeniu poate fi specificat i sub forma unui tip enumerat sau subtip, caz n care nu se specific n mod explicit limitele domeniului n cadrul instruciunii for loop. Limitele domeniului vor fi determinate de compilator din declaraia tipului sau subtipului respectiv. Instruciunea for loop din Exemplul 11 calculeaz ptratele valorilor ntregi cuprinse ntre 1 i 10, pe care le depune n tabloul i_patrat.
Exemplul 11
for i in 1 to 10 loop i_patrat (i) <= i * i; end loop;
Contorul de iteraii din acest exemplu este n mod implicit de tip integer, deoarece tipul acestuia nu a fost definit n mod explicit. Forma complet a declaraiei domeniului pe ntru contorul de iteraii este similar cu cea a unui tip. Pentru exemplul anterior, clauza for poate fi scris i sub forma urmtoare:
11
n unele limbaje de programare, n cadrul buclei se poate asigna o valoare contorului de iteraii (n exemplul anterior, i) pentru a-i modifica valoarea. Limbajul VHDL nu permite ns asignarea unei valori contorului de iteraii sau utilizarea acestuia ca parametru de intrare sau de ieire al unei proceduri. Contorul poate fi utilizat ns ntr -o expresie, cu condiia s nu i se modifice valoarea. Un alt aspect legat de contorul de iteraii este c acesta n u trebuie declarat n mod explicit n cadrul procesului. Acest contor este declarat n mod implicit ca o variabil local a instruciunii de buclare prin specificarea sa dup cuvntul cheie for. Dac exist o alt variabil cu acelai nume n cadrul procesului, cele dou vor fi tratate ca variabile separate. Din cauza interpretrii sintezei instruciunii for loop (descris n seciunea 2.8), limitele domeniului buclei trebuie s fie constante. Aceasta nseamn c limitele nu pot fi def inite utiliznd valoarea unei variabile sau semnal. Aceast restricie determin ca descrierea unor circuite s fie dificil. De exemplu, considerm cazul n care trebuie contorizat numrul de zerouri de la nceputul unei valori ntregi, i deci numrul de iteraii necesar nu este cunoscut dinainte. Descrierea unor asemenea circuite cu ajutorul instruciunilor de buclare este facilitat prin utilizarea instruciunilor next i exit.
La ntlnirea unei instruciuni next n cadrul corpului unei bucle, execuia iteraiei curente este oprit i controlul este transferat la nceputul instruciunii de buclare, fie necondiionat, dac clauza when nu este prezent, fie condiionat, dac aceast clauz este prezent. Contorul de iteraii va fi actualizat, iar dac limita domeniului nu a fost atins, execuia va continua cu prima instruciune din corpul buclei. n caz contrar, execuia instruciunii de b uclare se va termina. n cazul n care exist mai multe nivele de instruciuni de buclare (o bucl coninut ntr-o alt bucl), n cadrul instruciunii next se poate specifica o etichet, aceasta fiind eticheta instruciunii de buclare de nivel imediat superior n care este cuprins instruciunea next. Aceast etichet are doar rolul de a crete claritatea descrierii i nu poate fi diferit de cea a instruciunii de buclare curente. O instruciune next se poate utiliza n locul unei instruciuni if pentru execuia condiionat a unui grup de instruciuni. Utilizarea instruciunii next este ilustrat n seciunea 2.9.
Exist trei forme ale instruciunii exit. Prima este cea n care nu apare o etichet i nici o condiie specificat printr-o clauz when. n acest caz, se va opri n mod necondiionat execuia instruciunii curente de buclare. n cazul n care instruciunea exit apare ntr-o instruciune de buclare aflat n interiorul unei alte instruciuni de buclare, va fi oprit doar ex ecuia instruciunii interioare de buclare, dar execuia instruciunii exterioare de buclare va continua.
12
Dac n instruciunea exit se specific o etichet a unei instruciuni de buclare, la ntlnirea instruciunii exit controlul va fi transferat la eticheta specificat. Dac instruciunea exit conine o clauz when, execuia instruciunii de buclare va fi oprit numai n cazul n care condiia specificat de aceast clauz este adevrat. Urmtoarea instruciune executat depinde de prezena sau absena unei etichete n cadrul instruciunii. Dac se specific o etichet a unei instruciuni de buclare, urmtoarea instruciune executat va fi prima din instruciunea de buclare specificat de acea etichet. Dac nu se specific o etichet, urmtoarea instruciune executat va fi cea de dup clauza end loop a instruciunii de buclare curente. Instruciunea exit se poate utiliza pentru a termina execuia unei instruciuni loop simple, dup cum se arat n Exemplul 12.
Exemplul 12
E3: loop a := a + 1; exit E3 when a > 10; end loop E3;
Exemplul 13
proc6: process (a, b, c) begin x <= a and b and c; end process proc6; proc7: process (a, b) begin x <= a and b and c; end process proc7;
Toate utilitarele de sintez vor interpreta procesul proc6 ca o poart I cu 3 intrri. Unele utilitare de sintez vor interpreta procesul proc7 de asemenea ca o poart I cu 3 intrri, chiar dac la simularea acestui cod procesul nu se va comporta ca atare. La simulare, o modificare a valorii semnalului a sau b va determina execuia procesului, iar valoarea funciei I logic ntre semnalele a, b i c se va asigna semnalului x. Totui, dac se modific valoarea semnalului c, procesul nu este executat, iar semnalul x nu este actualizat. Deoarece nu este clar modul n care un utilitar de sintez ar trebui s genereze un circuit pentru care o tranziie a semnalului c nu determin o modificare a semnalului x, dar o modificare a semnalelor a sau b determin actualizarea semnalului x cu valoarea funciei I logic ntre semnalele a, b i c, exist urmtoarele alternative pentru programele de sintez: Interpretarea procesului proc7 n mod identic cu procesul proc6 (cu o list de sensibilitate care cuprinde toate semnalele din partea dreapt a instruciunilor de asignare a semnalelor din cadrul procesului); Indicarea unei erori la compilare, specificnd faptul c nu se poate realiza sinteza pr ocesului fr o list de sensibilitate complet.
13
A doua variant este preferabil, deoarece proiectantul va trebui s modifice codul surs astfel nct funcionarea circuitului generat s fie aceeai cu rezultatul simulrii funci onale a codului surs. Dei din punct de vedere sintactic procesele pot fi declarate fr o list de sensibilitate i fr o instruciune wait, asemenea procese nu vor fi suspendate niciodat. De aceea, dac se va simula un asemenea proces, timpul de simulare nu va avansa, deoarece faza de iniial izare, n care toate procesele sunt executate pn cnd acestea sunt suspendate, nu se va termina niciodat.
Exemplul 14
proc8: process begin wait on a, b; z <= a and b; end process proc8;
Acest proces va fi implementat prin sintez ca o simpl poart I cu dou intrri. Pentru ca un proces s modeleze un circuit combinaional, acesta trebuie s conin n lista de sensibilitate toate semnalele care sunt intrri ale procesului. Cu alte cuvinte, procesul trebuie reevaluat de fiecare dat cnd una din intrrile circuitului pe care l modeleaz se modific. n acest fel se modeleaz n mod corect un circuit combinaional. Dac un proces nu este sensibil la toate intrrile sale i nu este un proces secvenial, atunci nu poate fi sintetizat, deoarece nu exist un echivalent hardware al unui asemenea proces. Nu toate utilitarele de sintez impun o asemenea regul, astfel nct trebuie acordat atenie la scrierea proceselor combinaionale pentru a nu introduce erori. Asemenea erori vor avea ca efect diferene subtile ntre modelul simulat i circuitul obinut prin sintez, deoarece un proces non-combinaional este interpretat de utilitarul de sintez ca un circuit combinaional. Dac un proces conine o instruciune wait until sau o instruciune if semnal'event, procesul va fi interpretat ca un proces secvenial. Astfel, procesul din Exemplul 15 va fi interpretat ca un proces secvenial.
Exemplul 15
proc9: process begin wait until clk = '1'; z <= a and b; end process proc9;
Prin sinteza acestui proces, rezult circuitul din Figura 1, unde s-a adugat un bistabil la ieire.
14
Exemplul 16
library ieee; use ieee.numeric_std.all; signal num: unsigned (3 downto 0); process (clk) begin if (clk'event and clk = '1') then if rst = '1' then num <= "0000"; else num <= num + "0001"; end if; end if; end process;
Circuitul rezultat n urma sintezei procesului din exemplul anterior este prezentat n Figura 2.
Exemplul 17
library ieee; use ieee.std_logic_1164.all; entity comp is port (a, b: in std_logic_vector (7 downto 0); egal: out std_logic); end comp; architecture functional of comp is begin
15
process (a, b) begin if a = b then egal <= '1'; else egal <= '0'; end if; end process; end functional;
n exemplul anterior, se testeaz egalitatea a dou semnale std_logic_vector, reprezentnd doi vectori de cte 8 bii, rezultnd o valoare de tip std_logic. Circuitul rezultat este prezentat n Figura 3. De notat c, la fel ca i n cazul altor exemple, n practic utilitarul de sintez va elimina ineficienele din circuit (n acest caz, intrrile constante la multiplexor) pentru a rezulta o soluie minimal.
O instruciune if cu ramuri multiple, n care apare cel puin o clauz elsif, este implementat prin mai multe etaje de multiplexoare. Considerm instruciunea if din Exemplul 18.
Exemplul 18
process (a, b, c, s0, s1) begin if s0 = '1' then z <= a; elsif s1 = '1' then z <= b; else z <= c; end if; end process;
Rezultatul implementrii instruciunii if din exemplul anterior este prezentat n Figura 4. Acest circuit este echivalent cu cel rezultat prin implementarea unei instruciuni de asi gnare condiional, care este o instruciune concurent.
Condiiile din ramurile succesive ale unei instruciuni if sunt evaluate independent. n exemplul anterior, condiiile implic cele dou semnale s0 i s1. Pot exista oricte condiii, fiecare din acestea fiind independent de celelalte. Structura instruciunii if asigur faptul c primele condiii vor fi testate naintea celorlalte. n acest exemplu, semnalul s0 a fost testat naintea semnalului s1. Aceast prioritate se reflect n circuitul rezultat, n care multiplex o-
16
rul controlat de semnalul s0 este mai apropiat de ieire dect multiplexorul controlat de semnalul s1. Este important s se rein existena acestei prioriti cu care se testeaz condiiile, astfel nct s fie eliminate condiiile redundante. Considerm instruciunea if din Exemplul 19, care este echivalent cu instruciunea if din Exemplul 18.
Exemplul 19
process (a, b, c, s0, s1) begin if s0 = '1' then z <= a; elsif s0 = '0' and s1 = '1' then z <= b; else z <= c; end if; end process;
Condiia suplimentar s0 = '0' este redundant, deoarece ea va fi testat numai dac prima condiie a instruciunii if este fals. Se recomand evitarea unor asemenea redundane, deoarece nu exist garania c ele vor fi detectate i eliminate de ctre utilitarul de sintez. n cazul instruciunilor if cu ramuri multiple, n mod normal fiecare condiie va fi dependent de semnale i variabile diferite. Dac fiecare ramur este dependent de acelai semnal, atunci este mai avantajos s se utilizeze o instruciune case.
Exemplul 20
process (a, b, en) begin z <= a; if en = '1' then z <= b; end if; end process;
n acest caz, instruciunea if este incomplet deoarece lipsete clauza else. n instruciunea if, semnalul z primete o valoare n cazul n care condiia en = '1' este adevrat, dar rmne la valoarea precedent n cazul n care condiia este fals. Valoarea precedent provine din instruciunea de asignare aflat naintea instruciunii if. Instruciunea if din Exemplul 20 este echivalent cu instruciunea if din Exemplul 21.
17
Exemplul 21
process (a, b, en) begin if en = '1' then z <= b; else z <= a; end if; end process;
n cazul n care instruciunea if este incomplet i nu exist o instruciune anterioar de asignare, se va insera un circuit latch la ieire i va exista o reacie invers de la ieirea circuitului la intrare. Aceasta deoarece valoarea semnalului de la execuia precedent a proces ului este pstrat i aceasta devine valoarea semnalului la execuia curent a procesului. O asemenea form a instruciunii if este utilizat pentru a descrie un bistabil sau un registru cu o intrare de validare, ca n Exemplul 22.
Exemplul 22
process (clk) begin if (clkevent and clk = '1') then if en = '1' then q <= d; end if; end if; end process;
Semnalul q este actualizat cu noua valoare a semnalului d n cazul n care condiia este adevrat, dar nu este actualizat n cazul n care condiia este fals. n acest caz, valoarea precedent a semnalului q este pstrat prin reacia invers secvenial a semnalului q. Circuitul rezultat este prezentat n Figura 5.
Instruciunea if din Exemplul 22 este echivalent cu instruciunea if complet din Exemplul 23.
Exemplul 23
process (clk) begin if (clkevent and clk = '1') then if en = '1' then q <= d; else q <= q; end if; end if; end process;
n cazul n care condiia este fals, se asigneaz semnalului q valoarea anterioar a acestuia, ceea ce este echivalent cu pstrarea valorii sale anterioare.
18
Una din cele mai obinuite erori ntlnite n descrierile VHDL destinate sintezei logice este introducerea neintenionat a reaciei inverse n circuit datorit unei instruciuni if incomplete. Aceasta va insera circuite latch n proiectul sintetizat, ceea ce poate fi problematic pentru circuitele FPGA deoarece ntrzierile pentru cile care conin circuite latch sunt dificil de analizat. Utilitarele de sintez raporteaz, de obicei, inserarea unui circuit latch. Pentru a se evita inserarea unor circuite latch, proiectantul trebuie s se asigure c fiecare semnal cruia i se asigneaz o valoare ntr-un proces combinaional (care este deci un semnal de ieire din proces) primete o valoare n fiecare combinaie posibil a condiiilor. n practic, exist dou posibiliti pentru aceasta: asignarea unei valori unui semnal de ieire n fiecare ramur a instruciunii if i includerea clauzei else, sau iniializarea semnalului printr-o instruciune de asignare necondiionat naintea instruciunii if. n exemplul urmtor, dei instruciunea if pare complet, n cele dou ramuri ale instruciunii asignrile se efectueaz la semnale diferite. De aceea, ambele semnal e z i y vor avea o reacie invers asincron.
Exemplul 24
process (a, b, c) begin if c = '1' then z <= a; else y <= b; end if; end process;
Un alt exemplu este cel n care exist un test redundant al unei condiii care trebuie s fie adevrat (Exemplul 25).
Exemplul 25
process (a, b, c) begin if c = '1' then z <= a; elsif c = '0' then z <= b; end if; end process;
n acest caz, dei instruciunea if pare complet (presupunnd c semnalul c este de tip bit), deoarece pentru fiecare condiie testat sinteza se realizeaz n mod independent, este posibil ca sistemul de sintez s nu detecteze faptul c a doua condiie este redundant. n acest caz, instruciunea if va fi implementat printr-un multiplexor cu trei ci, a treia intrare fiind condiia ramurii else care lipsete, aceasta fiind reacia invers a valorii anterioare. Circuitul implementat pentru acest exemplu este prezentat n Figura 6.
19
Exemplul 26
process (clk) variable num: unsigned (7 downto 0); begin if (clkevent and clk = '1') then if rst = '1' then num := "00000000"; else num := num + 1; end if; rez <= num; end if; end process;
n acest exemplu, n ramura else a instruciunii if se citete valoarea precedent a variabilei num pentru a calcula valoarea urmtoare. Rezult astfel o reacie invers. De notat c n acest exemplu se creeaz de fapt dou registre. Conform regulilor pe ntru reacia invers, variabila num va fi nscris ntr-un registru. Semnalul rez va fi de asemenea nscris ntr-un registru, deoarece toate semnalele crora li se asigneaz o valoare ntr -un proces secvenial vor fi nscrise n registre. Acest registru suplimentar va conine ntotdeauna aceeai valoare ca i registrul variabilei num. Utilitarul de sintez va elimina n mod normal acest registru redundant.
20
Exemplul 27
library ieee; use ieee.std_logic_1164.all; entity potrivire_biti is port (a, b: in std_logic_vector (7 downto 0); potriviri: std_logic_vector (7 downto 0)); end potrivire_biti; architecture functional of potrivire_biti is begin process (a, b) begin for i in 7 downto 0 loop potriviri (i) <= not (a(i) xor b(i)); end loop; end process; end functional;
Prin procesul din acest exemplu, se genereaz un set de comparatoare de cte un bit, care compar biii de acelai rang ai vectorilor a i b. Rezultatul este nscris n vectorul potriviri, care va conine '1' n poziiile n care biii celor doi vectori sunt identici i '0' n celelalte poziii. Procesul din exemplul anterior este echivalent cu urmtorul proces:
process (a, b) begin potriviri (7) potriviri (6) potriviri (5) potriviri (4) potriviri (3) potriviri (2) potriviri (1) potriviri (0) end process;
n acest caz, ordonarea domeniului contorului de iteraii nu are importan, deoarece nu exist conexiune ntre blocurile generate ale circuitului. Aceast ordonare devine impo rtant atunci cnd exist o conexiune ntre aceste blocuri. Aceast conexiune este creat de obicei de ctre o variabil care pstreaz o valoare ntr-o iteraie a buclei, valoare care este citit apoi ntr-o alt iteraie. De obicei, este necesar iniializarea unei asemenea variabile naintea intrrii n bucl. Exemplul 28 prezint un asemenea circuit.
Exemplul 28
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity contorizare_unu is port (v: in std_logic_vector (15 downto 0); num: out signed (3 downto 0)); end contorizare_unu; architecture functional of contorizare_unu is begin process (v) variable rez: signed (3 downto 0); begin rez := (others => '0'); for i in 15 downto 0 loop if v(i) = '1' then
21
rez := rez + 1; end if; end loop; num <= rez; end process; end functional;
Acest exemplu este un circuit combinaional care contorizeaz numrul biilor din vectorul v care sunt '1'. Rezultatul este acumulat pe parcursul execuiei procesului ntr-o variabil numit rez i este asignat apoi semnalului de ieire num la sfritul procesului. Corpul buclei o instruciune if coninnd o asignare a unei variabile reprezint un bloc format dintr-un multiplexor i un sumator, care va fi generat la sintez pentru fiecare iteraie a buclei. Ieirea unui bloc devine intrarea rez a urmtorului bloc. Figura 7 prezint circuitul generat.
n Exemplul 28, domeniul contorului de iteraii al instruciunii for loop a fost specificat n mod explicit ca fiind 15 downto 0. n practic, aceast specificare explicit este utilizat foarte rar pentru accesarea tablourilor, fiind recomandat utili zarea atributelor pentru tablouri. Exist patru posibiliti, n funcie de domeniul cresctor sau descresctor al tablo ului sau de ordinea n care trebuie parcurse elementele tabloului. 1. Dac elementele unui tablou trebuie parcurse de la stnga la dreapta, indiferent de domeniul cresctor sau descresctor al tabloului, se utilizeaz atributul 'range:
for i in v'range loop
2. Dac elementele unui tablou trebuie parcurse de la dreapta la stnga, se utilizeaz atributul 'reverse_range:
for i in v'reverse_range loop
3. Dac elementele unui tablou trebuie parcurse de la indexul minim la cel maxim, ind iferent de domeniul cresctor sau descresctor al tabloului, se utilizeaz atributele 'low i 'high:
for i in v'low to v'high loop
4. n sfrit, dac elementele unui tablou trebuie parcurse de la indexul maxim la cel minim, se utilizeaz atributele 'high i 'low, cu specificarea cuvntului cheie downto:
for i in v'high downto v'low loop
La scrierea subprogramelor, n cazul n care nu se cunoate dinainte dac o variabil sau un semnal de tip tablou va avea un domeniu cresctor sau descresctor, devine foarte important alegerea limitelor corecte pentru instruciunile de buclare. Pentru tipurile tablou care reprezint valori ntregi, cum sunt tipurile signed i unsigned definite n pachetele numeric_std i std_logic_arith, convenia este c bitul din stnga reprezint bitul c.m.s. i bitul din dreapta reprezint bitul c.m.p.s., indiferent de domeniul tabloului. Aceasta nseamn c modul corect pentru accesul acestor tablouri este utilizarea atributului 'range sau 'reverse_range. Astfel, pentru accesul unui tablou n reprezentnd o valoare ntreag ncepnd de la bitul c.m.s. spre bitul c.m.p.s., se va utiliza atributul 'range:
22
Pentru accesul aceluiai tablou ncepnd de la bitul c.m.p.s. spre bitul c.m.s., se va utiliza atributul 'reverse_range:
for i in n'reverse_range loop
Exemplul 29
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity contorizare_unu is port (v: in std_logic_vector (15 downto 0); num: out signed (3 downto 0)); end contorizare_unu; architecture functional of contorizare_unu is begin process (v) variable rez: signed (3 downto 0); begin rez := (others => '0'); for i in v'range loop next when v(i) = '0'; rez := rez + 1; end loop; num <= rez; end process; end functional;
Figura 8. Implementarea unei instruciuni for loop care conine o instruciune next.
Figura 8 prezint circuitul generat prin sinteza descrierii din exemplul anterior. Singura diferen dintre acest circuit i cel din Figura 7 este c este inversat logica de control a multiplexoarelor. Cele dou circuite sunt ns echivalente funcional.
23
Exemplul 30
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity contorizare_zero is port (v: in std_logic_vector (15 downto 0); num: out signed (3 downto 0)); end contorizare_zero; architecture functional of contorizare_zero is begin process (v) variable rez: signed (3 downto 0); begin rez := (others => '0'); for i in v'reverse_range loop exit when v(i) = '1'; rez := rez + 1; end loop; num <= rez; end process; end functional;
Figura 9. Implementarea unei instruciuni for loop care conine o instruciune exit.
Circuitul generat prin sinteza descrierii din exemplul anterior este prezentat n Figura 9. Instruciunea exit este implementat prin porile SAU care determin, pentru iteraia curent i toate iteraiile rmase, selectarea intrrii multiplexoarelor care nu conin circuitul de incrementare atunci cnd condiia instruciunii exit devine adevrat. Se poate observa c implementarea unei instruciuni exit dintr-o bucl este similar cu cea a unei instruciuni if dintr-o bucl.
3. Aplicaii
3.1. Rspundei la urmtoarele ntrebri: a. Care sunt deosebirile dintre asignarea semnalelor i a variabilelor? b. Care este deosebirea dintre instruciunile if cu semnale i instruciunile if cu variabile? c. Cnd este mai avantajoas utilizarea unei instruciuni case n locul unei instruciuni if i care este avantajul utilizrii unei instruciuni case? d. Care este problema utilizrii instruciunilor if incomplete n procesele combinaionale? 3.2. Identificai i corectai erorile din urmtoarea descriere:
24
library ieee; use ieee.std_logic.all; entity t_c is port (clock, reset, enable: in bit; data: in std_logic_vector (7 downto 0); egal, term_cnt: out std_logic); end t_c; architecture t_c of t_c is signal num: std_logic_vector (7 downto 0); begin comp: process begin if data = num then egal = '1'; end if; end process; count: process (clk) begin if reset = '1' then num <= "111111111"; elsif rising_edge (clock) then num <= num + 1; end if; end process; term_cnt <= 'z' when enable = '0' else '1' when num = "1-------" else '0'; end t_c;
-------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Utilizai sistemul de dezvoltare Xilinx ISE pentru compilarea cu succes a acestei descrieri. Corectai apoi erorile semantice ale descrierii. 3.3. Scriei o secven pentru setarea semnalului x la valoarea funciei I logic ntre toate liniile unei magistrale de 8 bii a_bus(7:0). 3.4. Descriei un multiplexor 4:1 de 8 bii utiliznd o instruciune case. Intrrile multiplexorului sunt a(7:0), b(7:0), c(7:0), d(7:0), s(1:0), iar ieirile sunt q(7:0). 3.5. Realizai un decodificator din codul BCD pentru afiajul cu 7 segmente. Intrrile decodificatorului sunt bcd(3:0), iar ieirile sunt led(6:0). 3.6. Descriei memoria FIFO ale crei specificaii i schem bloc sunt prezentate n seciunea 1 din documentul Aplicatie-FIFO.pdf, disponibil pe pagina laboratorului. Creai entitatea i arhitectura pentru modulul fifo8x8, dup cum se indic n seciunea 2 din acelai document.