Cuprins
• 7.1. Functii de rezolutie
• 7.2. Semnale gardate. Deconectare
• 7.3. Instructiunea GENERATE
7.1.Functii de rezolutie
• Se utilizeaza pentru a rezolva valoarea unui semnal atunci cind semnalul are mai multe drivere (surse)
• In VHDL este ilegal ca un semnal cu mai multe drivere sa nu fie rezolvat
• Functia de rezolutie: – Se scrie de catre programator
– Se apeleaza de catre simulator:
• Atunci cind cel putin unul din driverele semnalului are un eveniment.
• La aparitia acelui eveniment se executa functia care va returna o valoare obtinuta din valorile tuturor driverelor semnalului.
• Spre deosebire de alte HDL in VHDL nu exista functii de rezolutie predefinite.
Functii de rezolutie
• O functie de rezolutie – are un singur parametru de intrare
• Care este intotdeauna un unconstrained array cu elemente de tipul semnalului
– si returneaza o singura valoare: • Valoarea are tipul semnalului si se numeste valoare
rezolvata
– Parametrul de intrare este unconstrained array deoarece atunci cind se scrie functia nu se cunoaste cite drivere va avea semnalul in momentul apelului functiei.
• Pentru un semnal rezolvat (declarat ca atare) se apeleaza functia de rezolutie chiar daca semnalul are un singur driver.
Declararea unui semnal rezolvat
Exemplu gresit:
TYPE fourval IS (X,L,H,Z);
SUBTYPE fourval_rez IS frez fourval;
-- frez este functia de rezolutie
-- Ex e gresit deoarece functia de rezolutie nu a fost specificata sau declarata.
In concluzie, pt declararea unui semnal rezolvat trebui respectata o succesiune stricta de pasi:
PACKAGE frezpack IS
TYPE fourval IS (X,L,H,Z);
TYPE fourval_vector IS ARRAY(NATURAL RANGE<>) OF
fourval;
FUNCTION frez(t: fourval_vector) RETURN fourval;
SUBTYPE fourval_rez IS frez fourval;
END PACKAGE frezpack;
Declararea unui semnal rezolvat Un semnal rezolvat poate fi declarat in doua moduri:
1. ca subtip rezolvat
2. prin utilizarea functiei de rezolutie in declararea semnalului.
Exemplu (continuare):
USE WORK.frezpack.ALL;
ENTITY ex IS
END;
ARCHITECTURE ex_rezolvat OF ex IS
SIGNAL s1,s2: fourval_rez;--modul 1
SIGNAL s3: frez fourval;--modul 2
BEGIN
…
END ARCHITECTURE;
Functii de rezolutie: exemplu
In mod normal o functie de rezolutie e asociativa si comutativa pentru ca rezultatul
returnat sa nu depinda de ordinea in care se parcurg intrarile functiei (adica
driverele semnalului) deoarece programatorul nu controleaza ordinea respectiva.
Exemplu de functie de rezolutie pentru tipul fourval:
Taria valorilor tipului fourval:
X
H L
Z
Scade taria
X inseamna valoare nedeterminata,
Z inseamna impedanta ridicata.
L si H au aceeasi tarie.
Atunci cind exista cel putin un driver L si cel putin unul H functia de rezolutie
va returna X.
Functii de rezolutie: exemplu
Tabelul dupa care functioneaza functia:
X L H Z
X X X X X
L X L X L
H X X H H
Z X L H Z
Functii de rezolutie: exemplu Functia din exemplu:
PACKAGE BODY frezpack IS
FUNCTION frez(t: fourval_vector) RETURN fourval IS
VARIABLE result: fourval:=Z;--se initializeaza cu
--valoarea cea mai slaba a tipului fourval
BEGIN
FOR i IN t’RANGE LOOP --t’RANGE parcurge tot tabloul t CASE t(i) IS
WHEN X => result:=X; RETURN result;
WHEN L=>
CASE result IS
WHEN X|H => result:=X;
RETURN result;
WHEN L|Z => result:=L;
END CASE;
WHEN H=>
CASE result IS
WHEN X|L => result:=X;
RETURN result;
WHEN H|Z => result:=H;
END CASE;
WHEN Z => NULL;--result ramine neschimbat
END CASE;
END LOOP;
RETURN result;
END FUNCTION frez;
END PACKAGE BODY;
Observatie: In acest caz functia s-ar fi putut implementa si cu IF in loc de CASE, dar
cu CASE e o metoda mai generala.
Functii de rezolutie pentru magistrale
• Daca exista mai multe dispozitive conectate la o magistrala trebuie avut grija ca la un moment dat un singur dispozitiv sa controleze magistrala: – Trebuie tratata situatia cind mai multe dispozitive vor sa controleze
magistrala • => e conflict
• Se semnaleaza printr-o valoare speciala “multiple drivers” returnata de functia de rezolutie
– Trebuie tratata si situatia cind nici un dispozitiv nu controleaza magistrala:
• Functia de rezolutie va returna o valoare speciala “not driven” • Aceasta valoare o are si un semnal ca sa arate ca dispozitivul respectiv nu
controleaza magistrala
• Valorile speciale se pot lua dintre valorile neutilizate ale magistralei (de ex valori negative de adrese) sau
• Daca nu exista valori neutilizate atunci – Se va transforma tipul magistralei intr-un record – se mai adauga inca un cimp la valorile normale ale magistralei
Exemplu Presupunem ca avem o magistrala de date si adrese, iar valorile adreselor pot fi
doar intregi nenegativi, deci se pot alege doua valori negative ca valori speciale.
PACKAGE busrez IS
TYPE xtype IS RECORD
addr: INTEGER;--are doar valori >=0
data: INTEGER;
--cimp_suplimentar: INTEGER;
END RECORD;
CONSTANT notdriven: xtype:=(-1,-1);
CONSTANT multipledrivers: xtype :=(-2,-2);
TYPE xtype_vector IS ARRAY(NATURAL RANGE <>) OF xtype;
FUNCTION xf(t:xtype_vector) RETURN xtype;
SUBTYPE xbus IS xf xtype;
END PACKAGE busrez;
PACKAGE BODY busrez IS
FUNCTION xf(t:xtype_vector) RETURN xtype IS
VARIABLE result: xtype:=notdriven;
VARIABLE count: INTEGER:=0;
BEGIN
IF t’LENGTH=0 THEN --’LENGTH atribut ce retunreaza lungimea unui tablou
result:=notdriven;
REPORT “nici un driver” SEVERITY WARNING;
END IF;-- situatia poate aparea doar pt semnale gardate, ale caror drivere se pot
--deconecta
FOR i IN t’RANGE LOOP
IF t(i) /= notdriven THEN
count := count +1;
result:=t(i);
END IF;
IF count>1 THEN
result:=multipledrivers;
REPORT “mai multe drivere !” SEVERITY ERROR;
RETURN result;
END IF;
END LOOP;
IF count=0 THEN
REPORT “nici un driver !” SEVERITY WARNING;
END IF;
RETURN result;
END xf;
END PACKAGE BODY busrez;
7.2. Semnale gardate •Declaratia de semnale are sintaxa:
SIGNAL list_of_signals: [resolution_function] signal_type [signal_kind] [:=expression];
unde signal_kind poate fi BUS sau REGISTER
•Definitie: semnalele gardate sint semnale speciale declarate a fi BUS sau REGISTER.
•Semnalele gardate trebuie sa fie semnale rezolvate si deci trebuie sa aiba functie de
rezolutie.
•Semnalelor gardate li se pot asigna valori doar in interiorul unor blocuri gardate.
•Catre semnalele gardate se pot face
- asignari concurente gardate sau
- asignari secveniale, dar
- NU se pot face asignari concurente negardate.
Semnale gardate
•In interiorul unui bloc gardat, atunci cind semnalul GURAD devine FALSE, va
avea loc deconectarea driverului semnalului gardat
•Deconectarea are loc dupa o perioada de timp numita disconnect time.
•Atunci cind garda este TRUE, driverul semnalului primeste valori conform
instructiunii de asignare de semnal
•In cazul unui semnal negardat care are o asignare concurenta gardata, atunci
cind garda devine FALSE nu se deconecteaza driverul semnalului, ci driverul isi
mentine valorile anterioare, fara a lua in considerare noile valori care ar putea fi generate de instructiunea de asignare de semnal (am spus ca driverul se
dezactiveaza)
•A se vedea exemplul.
• Timpul dupa care se face deconectarea unui semnal gardat poate fi specificat prin disconnect_specification (dupa declararea semnalului):
DISCONNECT nume_semnal_gardat: signal_type AFTER time_expression;
• Deconectarea unui driver este un eveniment, deci se va apela functia de
rezolutie.
Exemplu ARCHITECTURE guarded_ex OF exemplu IS
SIGNAL semnal_gardat: wired_or BIT REGISTER;
SIGNAL semnal_negardat: wired_and BIT;--nu e nevoie sa fie semnal rezolvat
BEGIN
b: BLOCK(guard_expression)
BEGIN
semnal_gardat <= GUARDED expression1 AFTER time1;
semnal_negardat <= GUARDED expression2 AFTER time2;
END BLOCK b;
END ARCHITECTURE;
Exemplul este echivalent cu:
Exemplu (continuare) ARCHITECTURE guarded_ex OF exemplu IS
SIGNAL semnal_gardat: wired_or BIT REGISTER;
SIGNAL semnal_negardat: wired_and BIT;--nu e nevoie sa fie semnal rezolvat
BEGIN b: BLOCK(guard_expression)
BEGIN
p1: PROCESS
BEGIN
IF GUARD THEN
semnal_gardat <= expression1 AFTER time1;
ELSE
semnal_gardat <= NULL; -- se deconecteaza
-- semnal<=NULL inseamna deconectarea driverului
END IF;
WAIT ON GUARD, signals_in_expression1;
END PROCESS p1;
p2: PROCESS
BEGIN
IF GUARD THEN
semnal_negardat <= expression2 AFTER time2;
END IF;
--nu are ELSE deoarece NU SE INTIMPLA NIMIC atunci cind
-- GUARD = FALSE
WAIT ON GUARD, signals_in_expression2;
END PROCESS p2;
END BLOCK b;
END ARCHITECTURE;
Diferentele intre BUS si REGISTER
• Dupa locul unde pot aparea: – Semnalele gardate BUS pot fi
• atit semnale declarate local intr-o arhitectura cit si
• Porturi ale unei entitati
– Semnalele gardate REGISTER pot fi • Doar semnale declarate local.
• Dupa modul cum se face deconectarea ultimului driver: – La un semnal gardat BUS:
• Daca se deconecteaza toate driverele, trebuie specificata valoarea pe care sa o aiba semnalul
• Adica functia de rezolutie trebuie sa specifice o valoare pt cazul cind nici un driver nu este conectat.
– La un semnal gardat REGISTER: • Cind se deconecteaza ultimul driver, semnalul isi va pastra valoarea anerioara
• Nu se apeleaza functia de rezolutie la deconectarea ultimului driver
• => functia de rezolutie nu trebuie neaparat sa specifice o valoare pt acest caz.
Exemplu de multiplexor 4:1 cu
semnale gardate
USE WORK.my_pack.ALL; -- my pack contine functia de rezolutie sau_cablat
ENTITY mux IS
GENERIC(mux_del: TIME:= 5ns);
PORT(din: IN BIT_VECTOR(3 DOWNTO 0);
sel: IN BIT_VECTOR(1 DOWNTO 0);
z: OUT BIT);
END mux;
ARCHITECTURE cu_semnale_gardate OF mux IS
SIGNAL temp: sau_cablat BIT BUS; -- in acest caz poate fi si REGISTER
BEGIN
b0: BLOCK (sel=“00”)
BEGIN
temp<= GUARDED din(0);
END BLOCK b0;
b1: BLOCK (sel=“01”) BEGIN temp<= GUARDED din(1);
END BLOCK b1;
b2: BLOCK (sel=“10”) BEGIN
temp<= GUARDED din(2); END BLOCK b2;
b3: BLOCK (sel=“11”) BEGIN
temp<= GUARDED din(3);
END BLOCK b3; z <= temp AFTER mux_del;
END ARCHITECTURE;
-- in acest caz nu are mare importanta cum e functia de rezolutie, deoarece
-- semnalul temp va avea un singur driver la un moment dat, restul de 3
-- drivere fiind deconectate.
7.3. Instructiunea GENERATE
• Este utilizata in special pentru descrierea structurilor regulate
• reprezinta un mecanism de compliare
conditionata in VHDL
• Sintaxa instructiunii este:
label_id: generation_scheme GENERATE
concurrent_statements
END GENERATE [label_id];
GENERATE (continuare)
• Schema de generare poate fi de tip: – FOR : indexul utilizat nu trebuie declarat – IF : nu are ELSIF si nici ELSE
– IF si FOR nu au nici o semantica de executie (nici o legatura cu instructiunile secventiale IF si LOOP FOR)
• Instructiunile concurente din corpul lui GENERATE sunt in mod tipic (dar nu neaparat) instantieri de componente.
• Compilatorul expandeaza codul din interiorul lui GENERATE. – De exemplu daca se utilizeaza o schema de generare de tip
FOR cu 5 iteratii si in corpul lui GENERATE se utilizeaza o instructiune de instantiere de componenta, atunci vor aparea 5 instantieri de componenta in codul expandat.
Exemplu Descriem un registru de deplasare pe 4 biti utilizind GENERATE.Registrul e
alcatuit din 4 bistabile de tip D.
Descrierea bistabilului D:
ENTITY dff_1 IS
GENERIC(tp: time:=1ns);
PORT(d, clk, reset: IN BIT;
q, qb: OUT BIT);
END dff_1;
ARCHITECTURE behave OF dff_1 IS
BEGIN
PROCESS(reset, clk, d)
BEGIN
IF(reset='0') AND reset'EVENT THEN
q<='0' AFTER tp;
qb<='1' AFTER tp;
ELSIF(clk='1') AND clk'EVENT AND clk'LAST_VALUE='0‘ THEN
q<= d AFTER tp;
qb<=NOT d AFTER tp;
END IF;
END PROCESS;
END ARCHITECTURE;
CONFIGURATION dff_cfg OF dff_1 IS
FOR behave END FOR;
END CONFIGURATION;
-- registrul de deplasare:
ENTITY shift_reg IS
GENERIC(len: NATURAL:=4);
PORT(reset, clock, a: IN BIT; b:OUT BIT);
END shift_reg;
D D D D
clk clk clk clk
Q Q Q Q
reset reset reset reset
reset
clock
b a
z(0) z(1) z(2) z(3) z(4)
Registrul de deplasare
shift_reg
Fig 11. Registru de deplasare realizat cu bistabile de tip D (D flip-flops)
Schema de generare de tip FOR
-- Instructiunea GENERATE cu
-- schema de generare de tip FOR
ARCHITECTURE shift_gen_1 OF shift_reg IS
COMPONENT dff IS
GENERIC(tp:TIME:=1ns);
PORT(d, clk, reset: IN BIT;
q, qb: OUT BIT);
END COMPONENT;
SIGNAL z: BIT_VECTOR(0 TO 4);
BEGIN
z(0)<=a;
g: FOR i IN 0 TO 3 GENERATE
dffx: dff PORT MAP(z(i), clock, reset, z(i+1), OPEN);
END GENERATE;
b<=z(4);
END shift_gen_1;
GENERATE cu schema de tip FOR
si IF
Dezavantajul acestei descrieri este ca nu sunt tratate unitar, in cadrul instructiunii GENERATE, bistabilele de la capetele registrului de deplasare.
Acest lucru se poate face combinind schema de generare de tip FOR cu
scheme de tip IF: -- Instructiunea GENERATE cu scheme de generare de tip
-- FOR si IF
ARCHITECTURE shift_gen_2 OF shift_reg IS
COMPONENT dff IS
GENERIC(tp:TIME:=1ns);
PORT(d, clk, reset: IN BIT;
q, qb: OUT BIT);
END COMPONENT;
SIGNAL z:BIT_VECTOR(1 TO len-1);
BEGIN
g1: FOR i IN 0 TO (len-1) GENERATE
g2: IF i=0 GENERATE
dffx: dff PORT MAP(d=>a, clk=> clock,
reset=>reset, q=>z(1), qb=>OPEN);
END GENERATE g2;
g3: IF i=(len-1) GENERATE
dffx: dff PORT MAP(d=>z(len-1), clk=>clock,
reset=>reset, q=>b, qb=>OPEN);
END GENERATE; --g3
g4: IF (i>0) AND (i<len-1) GENERATE
dffx: dff PORT MAP(z(i), clock,
reset, z(i+1), OPEN);
END GENERATE g4;
END GENERATE; -- g1
END ARCHITECTURE shift_gen_2;
Configuratie pentru GENERATE
Configuratia registrului de deplasare: -- Configuratia pentru arhitectura shift_gen_2 va fi:
CONFIGURATION cfg_gen OF shift_reg IS FOR shift_gen_2
FOR g1
FOR g2
FOR ALL: dff USE CONFIGURATION WORK.dff_cfg;
END FOR;
END FOR;--g2
FOR g3
FOR ALL: dff USE ENTITY WORK.dff_1(behave);
END FOR;
END FOR;--g3
FOR g4
FOR ALL: dff USE ENTITY WORK.dff_1(behave);
END FOR;
END FOR;--g4
END FOR; -- g1
END FOR; -- shift_gen_2 END cfg_gen;
entity test_shift_reg is
end;
architecture a_test of test_shift_reg is
COMPONENT shift_reg IS
GENERIC(len: NATURAL:=4);
PORT(reset, clock, a: IN BIT; b:OUT BIT);
END COMPONENT;
SIGNAL insig, r, cl, outsig: BIT;
BEGIN
l: shift_reg PORT MAP(r, cl, insig, outsig);
cl<=NOT cl AFTER 50ns;
r<='1', '0' after 3ns, '1' after 40ns;
insig<='1' after 145ns, '0' after 380ns, '1' after
1680ns;
end;
O entitate de test a registrului de
deplasare: