Scopul final al modelarii unui sistem digital intr-un limbaj de descriere hardware nu este simularea acestuia. Simularea este doar o etapa intermediara care confera proiectantului garantia ca sistemul modelat este conform specificatiilor comportamentale cerute. Un model VHDL
comportamental trebuie sa fie convertit la o structura hardware. Aceasta conversie este facuta automat de programe de sinteza hardware. Regulile prezentate in acest capitol descriu modul in care trebuie folosite constructiile VHDL pentru a fi convertite in structuri hardware de catre produsele software de sintetiza si optimizare.Structura obtinuta dupa sinteza automata este determinata direct de catre modul in care au fost utilizate constructiile VHDL in codul sursa. Scopul acestui capitol este de a prezenta modul in care trebuie descris comportamentul unui sistem digital pentru ca dupa sinteza sa se obtina rezultatele asteptate.
1 Modelarea circuitelor logice combinationale
Un circuit digital este considerat combinational (CLC) daca, la orice moment, valoarea logica a iesirilor este determinata direct numai de valorile logice ale intrarilor. Sintetizatorul VHDL trateaza sistemele logice ale caror iesiri sunt modificate in momentele determinate de un front sau un palier al unui
semnal ca fiind sisteme secventiale. Recomandari generaleModelul unui CLC se poate realiza cu urmatoarele constructii VHDL:
Sintetizatorul ignora intarzierile precizate in specificatiile de atribuiri de semnale (clauze 'after') sau in specificatii 'wait for'.
Procesele care modeleaza circuite combinationale au urmatoarele particularitati:
Sintetizatorul genereaza ecuatiile logice Booleene pentru portiunile de cod VHDL in care apar instantieri de porti logice sau operatori logici. Optimizatorul minimizeaza functiile logice si asociaza ecuatiilor rezultate porti din biblioteca tehnologiei.
Daca modelul VHDL este identic cu modelul unei componente aflate in biblioteca, atunci se va asocia acea componenta. De exemplu, codul care urmeaza este sintetizat sub forma unui multiplexor aflat in biblioteca de tehnologie:
process (a, b, sel)
begin
if (sel = '0') then
cout <= a ;
elsif (sel = '1') then
cout <= b ;
else
cout <= 'X' ;
end if ;
end process ;
In general, sintetizatorul nu poate asocia unei portiuni de cod VHDL o componenta de nivel inalt din biblioteca. Astfel, pentru codul care urmeaza se va asocia o structura de porti logice, desi codul descrie un semisumator de un bit aflat in biblioteca. Fortarea sintezei cu componente de nivel mai inalt se poate face prin optiuni de sinteza (impunerea unor componente preferentiale pentru sinteza).
Cout <= a xor b xor cin ; S <= (a and b) or (a and cin) or (b and cin) ;Modelarea multiplexoarelor cu specificatii 'case' sau 'if'
Procesele care contin specificatii 'case' sau 'if' sunt sintetizate sub forma unor multiplexoare cu conditia ca respectivele specificatii sa fie complete, adica:
process (a, b, sel)
begin
if (sel = '0') then
cout <= a ;
elsif (sel = '1') then
cout <= b ;
end if ; -- EROARE !!
end process ;
process (a, b, sel)
begin
if (sel = '0') then
cout <= cout ; -- EROARE !!
elsif (sel = '1') then
cout <= b ;
end if ;
end process ;
- semnale din afara procesului dar care nu apar in lista de senzitivitati:
process (a, sel)
begin
if (sel = '0') then
cout <= a ;
elsif (sel = '1') then
cout <= b ; -- EROARE !!
end if ;
end process ;
in cazul folosirii tipurilor de date std_logic se recomanda asigurarea completitudinii specificatiilor 'case' si 'if' prin folosirea clauzei 'others'.
process (sel, in1, in2, in3, in4)
begin
case sel is
when "00" =>
cout <= in1 ;
when "01" =>
cout <= in2 ;
when "10" =>
cout <= in3 ;
when others =>
cout <= in4 ;
end case ;
end process ;
in cazul in care specificatia
'case' nu precizeaza valoarea iesirii pentru toate cazurile, se considera ca iesirea nu se modifica si, in consecinta, va aparea pe iesire un nedorit latch. Codul care urmeaza va produce prin sinteza un latch pe iesirea cout datorita faptului ca semnalul sel de tip std_logic poate lua si alte valori nu numai cele precizate ca si conditii ("XX", "HL", ...).process (sel, in1, in2, in3, in4)
begin
case sel is
when "00" =>
cout <= in1 ;
when "01" =>
cout <= in2 ;
when "10" =>
cout <= in3 ;
when "11" =>
cout <= in4 ;
end case ;
end process ;Operatorii aritmetici (suma, diferenta, comparare) sunt asociati prin sinteza cu celule complexe existente in biblioteca de tehnologie. De exemplu, pentru codul care urmeaza sintetizatorul va genera un sumator de 6 biti implementat cu doua sumatoare de cite 4 biti. Daca in tehnologia selectata nu exista celule sumatoare, sintetizatorul va genera ecuatiile booleene iar optimizatorul va genera structura de porti asociata.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity sixbitadder is
port (a, b: in std_logic_vector(5 downto 0);
outp: out std_logic_vector(5 downto 0));
end sixbitadder ;
architecture arch_sixbitadder of sixbitadder is
begin
outp <= a + b ;
end arch_sixbitadder ;
O anumita resursa poate fi folosita in comun daca operatorul implementat nu se executa in aceleasi conditii. De exemplu, codul care urmeaza se poate sintetiza in doua moduri:
architecture arch of ent is
begin
outp <= a + b when sel = '0' else
a + c ;
end arch ;
O varianta, prezentata in figura 1, consta din folosirea a doua sumatoare, cite unul pentru fiecare aparitie a operatorului '+'. Iesirile sumatoarelor intra intr-un multiplexor selectat cu se
mnalul sel.A doua varianta, prezentata in figura 2, se bazeaza pe observatia ca cele doua sumatoare nu sunt folosite in acelasi timp. Se poate concepe o structura cu un singur sumator. O intrare este semnalul
a iar celalata provine din multiplexarea semnalelor b si c cu semnalul de selectie sel.
Figura 1
Arhitectura sintetizata cu doua sumatoare.Aceasta varianta poate fi descrisa intr-un proces astfel:
process (sel, a, b, c)
variable in_add : std_logic_vector(5 downto 0);
begin
if sel = '0' then
in_add <= b ;
else
in_add <= c ;
end if ;
outp <= a + in_add ;
end process ;

Figura 2
Arhitectura sintetizata cu un sumator.Modelarea unor circuite logice combinationale complexe
Un sumator de patru biti poate fi modelat cu o specificatie 'for' astfel:
process (a, b, ci)
variable c_temp: std_logic ;
begin
c_temp := ci;
for i in 0 to 3 loop
s(i) <= a(i) xor b(i) xor c_temp ;
c_temp := (a(i) and b(i)) or
(a(i) and c_temp) or
(b(i) and c_temp) ;
end loop ;
cout <= c_temp ;
end process ;
Un barrel shifter poate fi modelat cu functii combinationale. Pentru a nu apare latch-uri dupa sinteza, este necesar ca toate specificatiile 'if' si 'case' sa fie complete.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
package extra_types is
subtype eight_vector is
std_logic_vector (7 downto 0);
end extra_type;
library IEEE;
use IEEE.std_logic_1164.all;
use work.extra_types.all;
entity barrel_shift is
port (
data: in eight_vector;
mode,direction : in std_logic;
result: out eight_vector;
);
end barrel_shift;
architecture behavior of barrel_shift is
function shift (data:eight_vector; direction: std_logic) return std_logic_vector is
variable temp: eight_vctor;
begin
if (direction ='1') then
temp:= sh_left(data,1);
else
temp:= sh_right(data,1);
end if;
return (temp);
end shift;
function rotate (data: eight_vector; direction: std_logic) return std_logic_vector is
variable temp: eigth_vector;
begin
if (direction ='1') then
temp:= data (6 downto 0) & data(7);
else
temp:= data (0) & data(7 downto 1);
end if;
return (temp);
end rotate;
begin
process (data,mode,direction)
begin
if (mode='1') then
result <=shift (data,direction);
else
result <=rotate (data,direction);
end process;
end behavior;
2 Modelarea circuitelor logice secventiale
Un circuit digital este considerat secvential (CLS) daca valoarea logica a iesirilor este determinata atit de valorile logice ale intrarilor cit si de starea in care se afla
circuitul.Starea circuitului este determinata de valorile memorate in registre. Sintetizatorul VHDL recunoaste doua tipuri de descrieri secventiale:
explicite si implicite.Modelul unui CLS se poate realiza cu urmatoarele constructii VHDL:
Sistemele secventiale se recomanda a fi proiectate ca sisteme sincrone.
Sintetizarea sistemelor sincrone presupune ca toate operatiile logice sunt determinate de aparitia unui front activ al unui semnal de ceas. Codul urmator prezinta modul in care un proces asincron poate fi convertit la un proces sincron.
-- process asincron
process (enable, d)
begin
if enable = '1' then
q <= d ;
end if ;
end process ;
-- process sincron
process
begin
wait until clock'event and clock = '1' ;
if enable = '1' then
q <= d ;
end if ;
end process ;
Lista de senzitivitati a fost inlocuita cu o specificatie
'wait' care modeleaza aparitia unui front de ceas.Pentru a modela un semnal de ceas sintetizabil trebuie urmate citeva recomandari:
Specificatiile prin care sintetizatorul deduce semnalul de ceas sunt prezentate in tabelul 3:
|
Front activ pozitiv |
wait until clk'event and clk = '1' ; |
|
|
wait until not clk'stable and clk = '1' ; |
|
|
wait until clk'event and clk = '1' and clk'last_value = '0' ; |
|
Front activ negativ |
wait until clk'event and clk = '0' ; |
|
|
wait until not clk'stable and clk = '0' ; |
|
|
wait until clk'event and clk = '0' and clk'last_value = '1' ; |
|
Reset la punerea sub tensiune |
wait until clk'event and clk = '0' or reset'event and reset = '1' ; |
Tabelul 3
Specificatii VHDL pentru modelarea semnalului de ceas al sistemelor secventiale sincrone.Modelarea implicita a automatelor
Modelul implicit al automatelor descrie numai actiuniile care au loc in cadrul unui ciclu de tact. Nu exista o declaratie explicita a unui registru de stare. Sintetizatorul implementeaza registrul de stare pornind de la descrierea secventiala a starilor.
Procesul care descrie un automat in mod implicit trebuie sa satisfaca urmatoarele constringeri:
Exemplu
Controler pentru accesul la o memorie RAM, modelat ca un automat implicit.
library IEEE;
use IEEE.std_logic_1164.all;
package mem_types is
subtype mem_vector is
std_logic_vector (3 downto 0);
end mem_type;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.mem_types.all;
entity rdwr_ctrl is
port (
mem_op, read_not_write, clk, reset: in std_vector;
membus : inout mem_vector;
rd, wr : inout std_logic
);
end rdwr_ctrl;
architecture imp_fsm of rdwr_ctrl is
signal data : mem_vector;
signal membus_int: mem_vector;
signal state : std_logic_vector(1 downto 0);
signal next_state: std_logic_vector(1 downto 0);
begin
membus <= membus_int when (wr='1') else
"ZZZZ";
process
begin
wait until (clk'event and clk='1');
if (reset='0') then
data <= "0000";
membus_int <= "0000";
rd <= '0';
wr <= '0';
else
if (mem_op ='1') then
if (read_not_write ='1') then
rd <= '0';
wr <= '0';
wait until (clk'event and clk='1');
data <= membus;
rd <= '0';
else
wr <= '1';
membus_int <= data;
wait until (clk'event and clk='1');
wr <= '0';
end if;
end if;
end if;
end process;
end imp_fsm;
Modelarea implicita se recomanda in cazurile in care automatul trebuie sa genereze anumite forme de unda. Trecerea de la o stare la alta este marcata prin aparitia unei modificari in formele de unda generate la iesire.
Modelul explicit al automatelor specifica un registru de stare caruia ii atribuie explicit valori.
Procesul care descrie un automat in mod explicit trebuie sa satisfaca urmatoarele constringeri:

Figura 4
Schema bloc a unui automat modelat explicit.Modelarea explicita a unui automat se bazeaza pe reprezentarea clasica prezentata in figura 4.
Modelarea explicita a unui automat include urmatoarele constructii VHDL:
case state is
when INIT =>
if (mem_op = ’1’) then
if (read_not_write = ’1’) then
next_state <= READ ;
else
next_state <= WRITE ;
end if ;
else
next_state <= INIT ;
end if ;
when …
when OTHERS =>
next_state <= INIT ;
ed case ;
process
begin
wait until clk = ’0’ and clk ’ event ;
state <= next_state ;
end ;
rd <= ’1’ when (state = READ) else ’0’ ; wr <= ’1’ when (state = WRITE) else ’0’ ; membus <= membus_int when not wr else ”0000” ;
wait until (clk = ’1’ and clk ’ event) ; if (reset = ’0’) then data <= ”0000” ; membus_int <= ”0000” ; state <= INIT ; end if ;
Exemplu
Controler pentru accesul la o memorie RAM, modelat ca un automat explicit.
Descriere explicita intr-un singur bloc:
library IEEE;
use IEEE.std_logic_1164.all;
package mem_types is
subtype mem_vector is
std_logic_vector (3 downto 0);
end mem_type;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.mem_types.all;
entity rdwr_ctrl is
port (
mem_op, read_not_write, clk, reset: in std_vector;
membus : inout mem_vector;
rd, wr : inout boolean
);
end rdwr_ctrl;
architecture behavior of rdwr_ctrl is
signal data : mem_vector;
signal membus_int: mem_vector;
signal state : std_logic_vector (1 downto 0);
constant INT : std_logic_vector (1 downto 0):= "00";
constant READ : std_logic_vector (1 downto 0):= "01";
constant WRITE : std_logic_vector (1 downto 0):= "10";
begin
membus <= membus_int when (wr='1') else
"ZZZZ";
process
begin
wait until (clk'event and clk='1');
if (reset='0') then
data <= "0000";
membus_int <= "0000";
state <= INIT ;
else
case state is
when INIT =>
if (mem_op ='1') then
if (read_not_write='1') then
state <= READ;
rd <= '1';
else
state <= WRITE;
membus_init <= data;
wr <= '1';
end if;
else
state <= INIT;
end if;
when READ =>
state <= INIT;
rd <= '0';
data <= membus;
when WRITE =>
state <= INIT;
wr <= '0';
when others =>
state <= INIT;
end case;
end if;
end process;
end behavior;
Descriere in trei blocuri procedurale:
library IEEE;
use IEEE.std_logic_1164.all;
package mem_types is
subtype mem_vector is
std_logic_vector (3 downto 0);
end mem_type;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.mem_types.all;
entity rdwr_ctrl is
port (mem_op, read_not_write, clk, reset: in std_logic;
membus : inout mem_vector;
rd, wr : inout boolean
);
end rdwr_ctrl;
architecture exp_fsm of rdwr_ctrl is
type statetype is (INIT, READ, WRITE);
signal data : mem_vector;
signal membus_int: mem_vector;
signal state : statetype;
signal next_state: statetype;
begin
rd <= (state= READ);
wr <= (state= WRITE);
membus <= membus_int when (wr) else "ZZZZ";
process
begin
wait until (clk'event and clk='1');
if (reset='0') then
data <= "0000";
membus_int <= "0000";
state <= INIT ;
else
state <= next_state ;
if (state = WRITE) then
membus_int <= data;
end if;
if (state = READ) then
data <= membus;
end if;
end if;
end process;
process(state, mem_op, read_not_write)
begin
if (state = INIT) then
if (mem_op = '1') then
if (read_not_write = '1') then
next_state <= READ;
else
next_state <= WRITE;
end if;
else
next_state <= INIT;
end if;
else
next_state <= INIT;
end if;
end process;
end exp_fsm;
Modelarea explicita se recomanda in cazurile in care automatul este descris prin organigrama sau graf de tranzitii. in acest caz, accentul este pus pe semnificatia starilor in care se afla automatul.
3 Modelarea semnalului de initializa
reToate sistemele secventiale necesita un semnal de initializare care sa asigure atingerea unei stari predefinite, inainte de pornirea efectiva a sistemului. Pentru automatele modelate implicit sau explicit se pot defini semnale de initializa
re sincrona, asincrona sau la punerea sub tensiune. Pentru un registru, se poate defini un semnal de initializare asincron.Initializarea la pornire (
power-on reset - engl.) poate fi implementata prin precizarea unei valori initiale pentru un semnal sau variabila. Sintetizatorul va genera o eroare daca se incearca initializarea unei iesiri combinationale.entity dff is
port (q: out std_:logic := ’0’;
data: in std_:logic ;
clk: in std_:logic) ;
end dff ;
Exista doua variante de modelare.
in cazul unui proces cu specificatii
'wait', conditia de intializare (reset'event and reset = '1') trebuie inclusa alaturi de cea de ceas.in cazul uni proces cu lista de senzitivitati, numele semnalului de intializare trebuie pus alaturi de cel al semnalului de ceas in lista de senzitivitati.
in ambele cazuri, starea semnalului de reset trebuie testata prima.
Model de registru cu reset asincron:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity dff8_sr is
port (d: in std_logic_vector (0 to 7);
clk: in std_logic;
set: in std_logic;
reset: in std_logic;
q: out std_logic_vector (0 to 7));
end dff8_sr;
architecture a0 of dff8_sr is
begin
process
begin
wait until ((clk'event and clk='1') or
(reset'event and reset='0') or
(set'event and set='0');
if (set='0') then
q <= "11111111";
elsif (reset='0') then
q <= "00000000";
elsif (clk'event and clk='1') then
q <= d;
end if;
end process;
end a0 ;
Model de automat cu reset asincron:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity parity_check is
port (
parity_error: out std_logic_vector;
data_in : in std_logic_vector;
data_ready : in std_logic_vector;
clk, reset : in std_logic
);
end parity_check;
architecture exp_fsm of parity_check is
begin
process (clk, reset)
type state_type is (idle, get_data, par_check);
variable cur_state : state_type;
variable bit_count : std_logic_vector (2 downto 0);
variable parity_reg: std_logic;
begin
if (reset='0') then
cur_state := idle;
parity_error <= "0";
elsif (clk='1' and clk'event) then
case (cur_state) is
when idle =>
if (data_ready ='0') then
cur_state := get_data;
parity_reg := '0';
bit_count := "000";
end if;
when get_data =>
parity_reg := parity_reg xor data_in;
bit_count := bit_count + 1;
if (bit_count ="000") then
cur_state := get_data;
end if;
when par_check =>
parity_reg := parity_reg xor data_in;
parity_error <= not parity_reg;
end case;
end if;
end process;
end exp_fsm;
Reset sincron
Semnalul de reset sincron trebuie tratat ca o intrare preferentiala in automat. Aceasta intrare este testata in toate starile. Activarea intrarii determina trecerea in starea initiala, sincron cu urmatorul front activ al semnalului de ceas.
Reset sincron pentru automat descris explicit:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity jmp_exp is
port (address: out std_logic_vector (2 downto 0);
read: out std_logic;
data: in std_logic_vector (3 downto 0);
clk: in std_logic;
reset: in std_logic);
end jmp_exp;
architecture exp_fsm of jmp_exp is
begin
process
constant NOP : std_logic := ’0’;
constant JMP : std_logic := ’1’;
variable ir : std_logic_vector (3 downto 0);
variable pc : std_logic_vector (2 downto 0);
type state_type is (load, jump) ;
variable cur_state: state_type;
begin
wait until (clk'event and clk='1');
if (reset='0') then
address <= "000";
read <= '0';
ir := "0000";
pc := "000";
cur_state := load;
else
case (cur_state) is
when load =>
address <= pc;
read <= '1';
cur_state := jump;
when jump =>
ir := data;
read <= '0';
cur_state := load;
case (ir(3)) is
when NOP =>
pc := pc + '1';
when JMP =>
pc := ir(2 dowto 0);
when OTHERS =>
pc := pc + '1';
end case;
end case;
end if;
end process;
end exp_fsm;
4 Modelarea sistemelor complexe pentru sintetizabilitate
Modelarea unui sistem complex presupune parcurgerea urmatoarelor etape de proiectare: