Documente Academic
Documente Profesional
Documente Cultură
Gheorghe Toacse
DIGITALA
ELECTRONICA
VOL. II
VERILOG HDL
- 2005
EDITURA TEHNICA
II
Aceasta pagina va fi nlocuita . II
III
Si aceasta pagina va fi nlocuita. III
Prefat
a
VERILOG, VERY-LOGIC HDL (limbaj de descriere hardware foarte logic): un nume extraordinar de bine ales pentru un limbaj care a devenit ast
azi fundamental pentru proiectarea circuitelor integrate digitale.
Acum 10 ani, n 1995, scriam n prefata unei c
arti: Limbajul VHDL permite o
exprimare sintetic
a n electronica digital
a at
at la nivel inferior, de poart
a logic
a, c
at
si la nivel superior, de sistem. Tehnicile de proiectare automat
a n electronic
a nu pot
fi aplicate f
ar
a existenta unui astfel de limbaj.
faza
Acum 7 ani, n 1998, predam beneficiarului un proiect scris n VHDL. In
de depanare, beneficiarul mi cere: Adaug
a un registru pe aceast
a iesire. Nici o
problem
a, zic si ncep s
a scriu urm
atoarea portiune de cod VHDL:
-- acesta este modelul VHDL al unui registru de 8 biti
signal extraFf : std_logic_vector(7 downto 0);
process(clk, reset)
begin
if (reset = 1) then
extraFf <= (others => 0);
elsif (clkevent and (clk = 1)) then
extraFf <= semnal;
end if;
end process;
iesire <= extraFf;
Am fost l
asat s
a termin si apoi am fost ntrebat: Vrei s
a vezi cum se scrie acelasi
lucru n Verilog?. Iat
a cum a fost r
aspl
atit
a curiozitatea mea:
// acesta este modelul VerilogHDL al unui registru de 8 biti
always @(posedge clk or posedge reset)
if (reset) iesire <= 0; else
iesire <= semnal;
Acum 6 ani, n 1999, mi s-a cerut proiectarea unui sistem digital cu cerinta expres
a: a se descrie n Verilog. Reactia mea a fost imediat
a: - Nu stiu Verilog.
Replica a venit si mai rapid: - Dar stii VHDL. Verilog este foarte logic. Vei nv
ata
limbajul repede.
In mai putin de dou
a zile, eram fluent n Verilog ca si n VHDL.
Pentru mine ca inginer, descoperirea Verilog a nsemnat nceputul unei noi ere. O
er
a aflat
a sub semnul simplific
arii proiect
arii.
Acum, n 2005, am inclus n acest volum o parte din experienta mea de utilizator
al limbajului Verilog HDL n proiectarea de circuite integrate digitale.
C
at timp proiectantii si companiile lor vor avea ca obiectiv producerea unor bunuri
de calitate mare ntr-un timp scurt, Verilog va continua s
a fie o solutie dominant
a.
Intreaga comunitate a firmelor de productie de procesoare, calculatoare, circuite specifice ASIC utilizeaz
a Verilog ca principal limbaj de modelare.
VI
Electronic
a digital
a
Autorii
Cuprins
1 INTRODUCERE
1.1 Ce este Verilog?
1.2 De ce HDL?
1.3 Terminologia Verilog
1.3.1 Aspectul temporal
1.3.2 Concurenta evenimentelor
1.3.3 Modulul
1.4 Mediul de simulare a modelelor HDL
1.5 Comparatie Verilog-VHDL
1
3
6
6
7
7
21
21
25
25
26
26
27
28
28
34
34
38
38
39
40
41
42
43
43
44
47
47
53
56
57
59
VIII
Electronic
a digital
a
2.8
Directive de compilare
2.8.1 define si undefine
2.8.2 ifdef, ifndef, else, endif
2.8.3 include
2.8.4 timescale
2.9 Stil si calitate
63
63
65
66
66
67
98
100
4 NOT
IUNI AVANSATE DE VERILOG
4.1 Task-uri si functii
4.2 Modelarea memoriilor
4.3 Generarea structurilor hardware
4.4 Modelarea la nivel de poarta logica
4.4.1 Porti cu intrari multiple
4.4.2 Porti cu iesiri multiple
4.4.3 Porti cu iesiri n trei stari
4.4.4 Porti cu iesiri fixe
4.5 Modelarea la nivel de tranzistor
4.6 Task-uri si functii de sistem
4.6.1 Task-uri de afisare
4.6.2 Task-uri de accesare a fisierelor
4.6.3 Task-uri pentru controlul simularii
4.6.4 Task-uri pentru verificari temporale
4.6.5 Functii referitoare la timpul simularii
4.6.6 Functii pentru generarea numerelor aleatorii
4.7 Primitive definite de utilizator
4.8 Accesarea semnalelor n ierarhie
4.9 Functii PLI
4.9.1 Crearea unei aplicatii PLI
4.9.2 Apelarea aplicatiei PLI
4.10 Noutati introduse de standardul IEEE Verilog 1364-2001
103
107
109
113
113
113
114
114
115
118
119
120
122
122
123
123
124
126
127
128
132
133
79
79
80
81
81
85
86
88
89
94
94
96
Cuprins
IX
5 PROBLEME REZOLVATE
5.1 Circuite de prelucrare a impulsurilor
135
5.1.1 Circuite formatoare de impulsuri
135
5.1.2 Generarea unui semnal n avans sau cu ntarziere
138
5.2 Circuit secvential pentru recunoastere de pattern
142
5.3 Verificator de protocol de comunicatie
147
5.4 Generarea semnalului de transport al unui
numarator sincron
150
5.5 Modelarea registrelor
151
5.5.1 Registrul paralel
151
5.5.2 Registrul cu reactie, LFSR
152
5.6 Sincronizarea semnalelor la trecerea ntre doua domenii de ceas162
5.6.1 Sincronizarea unui semnal cu evolutie lenta la trecerea
dintr-un domeniu de ceas de frecventa scazuta ntr-un
domeniu de ceas de frecventa ridicata
163
5.6.2 Sincronizarea unui puls la trecerea dintr-un domeniu de
ceas de frecventa ridicata ntr-un domeniu de ceas de
frecventa scazuta
165
5.6.3 Sincronizarea unui puls la trecerea dintr-un domeniu de
ceas de frecventa scazuta ntr-un domeniu de ceas de
frecventa ridicata
170
5.6.4 Aplicatie la sincronizarea unui bus cu variatie lenta
173
5.6.5 Aplicatie la sincronizarea unui bus cu variatie rapida
(FIFO)
174
5.7 Interfatarea cu CPU
181
5.8 Multiplicator secvential
197
5.9 Modelarea si testarea memoriilor
202
5.10 Modelarea multiplexoarelor
210
5.10.1 Multiplexor modelat cu valori neprecizate
210
5.10.2 Multiplexor n bucla cu bistabil
212
5.10.3 Multiplexor pe bus
216
5.11 Controller pentru memorie SDRAM
217
5.11.1 Modelul Verilog al controllerului SDRAM
217
5.11.2 Mediul de testare al controllerului SDRAM
229
Anexa A MODELAREA SPICE A UNUI INVERSOR CMOS
A.1 Modelul SPICE al tranzistoarelor MOS
A.2 Ridicarea caracteristicii de sarcina IDS (VDS )
pentru tranzistorul NMOS
A.3 Modelul SPICE al inversorului CMOS
A.4 Determinarea caracteristicii de transfer si a parametrilor inversorului CMOS
A.4.1 Nivelurile de tensiune
A.4.2 Marginea de zgomot
A.4.3 Timpul de propagare
A.4.4 Consumul de putere
A.4.5 Factorul de merit
239
240
244
245
246
247
247
250
251
Electronic
a digital
a
Capitolul 1
INTRODUCERE
Aceasta parte a cartii nu se doreste a fi un manual complet al limbajului VerilogHDL,
ci o sursa de nvatare rapida si eficienta a descrierii circuitelor digitale. Cu buna
stiinta, vor fi expuse doar acele caracteristici ale limbajului care sunt mai des folosite
la modelarea sistemelor digitale pentru sintetizabilitate.
Pe parcursul acestei parti apar urmatoarele semne care marcheaza pasaje cu
diferite particularitati:
n
V
Sn
n
T
paragraf care face referire la un modul de test existent pe situl de web al cartii.
Paragrafele de cod Verilog si referirea la numele variabilelor HDL sau la cuvinte
cheie vor fi marcate evidentiat prin scrierea acestora cu caractere tip typesetting. De
remarcat ca, n aceste paragrafe de cod sursa, cuvintele ce contin caractere specifice
limbii romane (a, a, , s, t) au fost nlocuite cu caracterele de origine ale acestora (a,
a, i, s, t). Motivul este acela ca Verilog nu suporta caracterele specific romanesti,
nici macar sub forma de comentarii.
1.1
Ce este Verilog?
Un sistem digital se poate descrie fie schematic, fie textual. Datorita complexitatii
sistemelor actuale, descrierea schematica nu mai permite gestionarea proiectelor mari.
In schimb, descrierea textuala are nenumarate avantaje, cel mai important fiind
usurinta prelucrarii acestei descrieri de catre programele de calculator.
In prezent exista doua limbaje de descriere hardware (HDL = Hardware Description Language) care acopera cea mai mare parte din proiectarea sistemelor digitale:
1
CAPITOLUL 1. INTRODUCERE
Verilog si VHDL.
Verilog este un limbaj de descriere hardware a carui denumire provine din concatenarea cuvintelor din limba engleza Very-logic (foarte logic). VHDL este un
limbaj de descriere hardware a carui denumire provine din concatenarea literei V
(initiala abrevierii VHSIC = Very High Speed Integrated Circuits) si HDL.
VHDL nu este o abreviere pentru Verilog HDL. Verilog si VHDL sunt doua
limbaje de descriere hardware diferite. Intre acestea exista multe asemanari dar exista
si deosebiri.
In continuare, prin HDL se va face referire la limbajele de descriere hardware n
general, incluzand atat Verilog, cat si VHDL.
Un limbaj de descriere hardware este un limbaj utilizat pentru descrierea unui
sistem digital, ca de exemplu un calculator sau o componenta a acestuia. HDL nu este
un limbaj de programare pentru ca nu descrie programe rulate de un procesor. Codul
sursa scris n HDL nu trebuie numit program (cu ntelesul implicit de program
pentru calculator). Este recomandata denumirea codului sursa HDL ca model, cu
ntelesul de model al unui sistem hardware.
Limbajele de descriere hardware ofera suportul pentru proiectarea circuitelor integrate digitale. In HDL se poate descrie un sistem digital modelat la cel mai nalt
nivel, precizandu-se doar comportamentul abstract al acestuia. Mai detaliat, se poate
descrie n HDL structura de registre a unui sistem digital si ecuatiile transferului
de informatii dintre registre. Acest nivel de descriere este denumit RTL (Register
Transfer Level) si este destul de detaliat pentru a fi acceptat ca intrare de catre
programe de calculator care fac trecerea de la model la realizare fizica (sinteza).
Dupa sinteza, descrierea sistemului digital implementat ntr-o anumita tehnologie se
poate genera automat sub forma unui netlist HDL. Netlist (cuvant provenit din limba
engleza din concatenarea cuvintelor net=legatura/retea si list=lista) este denumirea unui model HDL particular: contine o descriere structurala a unor instantieri
de componente descrise ntr-o biblioteca de componente specifice tehnologiei de realizare a circuitului integrat. Netlist-ul este generat automat de catre software. HDL
ofera posibilitatea descrierii unui sistem digital la nivel de porti logice si bistabile.
Proiectantii de tehnologie folosesc tot HDL pentru a modela componentele primitive
ale tehnologiei la nivel de sarme, tranzistoare, rezistoare.
Descrierea textuala a circuitelor electronice digitale n HDL este folosita atat la
proiectarea, cat si la sinteza, la verificarea functionala sau la analiza temporala a
acestora.
Verilog este unul dintre cele doua cele mai folosite limbaje de descriere hardware.
Parerile referitoare la avantajele si dezavantajele fiecaruia sunt foarte diverse. Se
spune ca Verilog este mai usor de nvatat pentru ca este asa cum i spune numele
very logic.
VHDL a fost standardizat n 1987 sub numarul IEEE-1076. Ulterior, lipsa unor
tipuri de date general acceptate a fost rezolvata prin aparitia standardului IEEE1164. VHDL este un limbaj a carui sintaxa seamana cu sintaxa limbajului ADA.
Promovarea limbajului ca standard a fost facuta de catre Departamenul de Aparare
al Statelor Unite.
Verilog HDL a avut o traiectorie diferita, el provenind din mediul industrial. Sintaxa Verilog seamana cu sintaxa limbajului C.
Verilog a fost dezvoltat ca un limbaj de descriere proprietar de catre firma ameri-
1.2. De ce HDL?
1.2
De ce HDL?
CAPITOLUL 1. INTRODUCERE
1.2. De ce HDL?
Legenda:
Specificatii
de proiectare
Model
HDL
RTL
Bibilioteca
de
componente
Simulator
HDL
Fisier
cod HDL
Software
EDA
Sintetizator
hardware
Netlist HDL
la nivel de
poarta logica
Biblioteca
de
tehnologie
Document
Simulator
HDL
Generator
de vectori
de test
+
Monitorizare
Implementare
Model HDL
temporal
Simulator
HDL
Generare de vectori de test. Modulul de proiectat trebuie testat n conjunctie cu modele ale mediului exterior. Modelele care genereaza stimuli se
descriu tot n HDL chiar daca nu ntotdeauna vor fi sintetizate. Capabilitatile
HDL ajuta proiectantul la realizarea unor generatoare de stimuli guvernate de
anumite reguli sau chiar stimuli aleatorii. In plus, producatorii de circuite ofera
modelele HDL ale acestora pentru a putea fi integrate n simularea unor sisteme
mari. Este cazul modelelor de memorie folosite la proiectarea controllerelor de
memorie.
Mediu de simulare. Testarea circuitului proiectat alaturi de modelele circuitelor exterioare acestuia presupune crearea unui model HDL ce le include pe
toate acestea, cu precizarea conexiunilor. Forta unui mediu de simulare consta
si n posibilitatea configurarii acestuia, conform cerintelor beneficiarului (nu ale
proiectantului).
Module de monitorizare/verificare. Verificarea automata presupune existenta unor module HDL care monitorizeaza aparitia unor conditii logice si
lanseaz
a mesaje de atentionare sau de eroare catre proiectant.
CAPITOLUL 1. INTRODUCERE
Netlist post-sintez
a. Sintetizatorul converteste descrierea RTL ntr-o descriere structurala cu instantieri de componente din biblioteca de tehnologie.
Proiectantul are obligatia de a verifica faptul ca netlistul are acelasi comportament ca modelul RTL, prin simularea netlistului n mediul de simulare n care
a validat modelul RTL.
Biblioteci de componente specifice tehnologiei. Simularea netlistului presupune existenta descrierii HDL a fiecarei componente instantiate. Modelele
componentelor sunt realizate de catre proiectantii de tehnologii n diverse limbaje de descriere hardware, suportate de metodologia aleasa de proiectant si
de catre programele EDA (EDA = Electronic Design Automation, totalitatea
programelor ce ofera suport n proiectarea circuitelor electronice).
Model temporal cu parametrii actualizati conform implement
arii.
Post-implementare, dupa ce sunt cunoscute toate detaliile implementarii (plasare, rutare), este necesara o noua verificare, nainte de a se transmite proiectul
catre fabricant. La acest nivel, este necesara cunoasterea ntarzierilor atat a
portilor logice si bistabilelor, cat si a sarmelor de interconectare a acestora.
Documentare. Realizarea unui proiect presupune scrierea unei documentatii
care sa nsoteasca produsul. La aceasta documentatie va face apel si proiectantul n cazul aparitiei unor defecte sau a lansarii n executie a unei versiuni
superioare. Codul HDL, ca documentare a proiectului, este o resursa valoroasa
pentru ca permite simularea unei situatii reale care nu a fost testata anterior.
1.3
Terminologia Verilog
1.3.1
Aspectul temporal
assign #2 w1
assign #2 y
1.3.2
= i1 & s;
= w0 | w1;
Concurenta evenimentelor
Programele software sunt prin excelenta secventiale. Acest lucru este determinat de
faptul ca procesoarele executa programe secventiale. Sistemele hardware sunt concurente. Fiecare poarta logica si executa propria functie logica n mod independent
de existenta altor porti logice.
Un proiectant de software descrie n codul sursa un algoritm secvential, ceea ce va
genera, n final, un program secvential executat de un procesor.
Un proiectant de hardware descrie un comportament al unui sistem digital ce va
genera, n final, o structura de porti si bistabile interconectate. Limbajele de descriere
hardware au facilitati de gestiune a evenimentelor concurente.
Specificatiile existente n corpul modulelor (cod sursa) Verilog sunt concurente
(se executa toate la acelasi moment al timpului de simulare, iar ordinea acestora n
codul sursa nu este relevanta).
De exemplu, portiunea de cod ce urmeaza este echivalenta (si ca rezultat al
simularii si ca hardware generat prin sinteza) cu structura modelata anterior.
assign
assign
assign
assign
#2
#2
#1
#2
y
w0
s_n
w1
=
=
=
=
w0 | w1;
i0 & s_n;
~s;
i1 & s;
1.3.3
Modulul
Urmatorul paragraf prezinta traducerea capitolului 1, Prezentare generala a documentului initial editat de OVI (Open Verilog International) sub titlul de manual de
referinta al limbajului Verilog (LRM = Language Reference Manual), versiunea 1.0,
noiembrie 1991.
Verilog HDL descrie un proiect hardware sau o parte de proiect. Descrierile proiectelor n Verilog HDL sunt modele Verilog. Verilog HDL este at
at un limbaj comportamental, c
at si structural. Modelele Verilog HDL pot descrie at
at functia unui proiect,
c
at si componentele si conexiunile dintre componentele unui proiect. Modelele Verilog
pot fi dezvoltate pe diferite nivele de abstractizare. Aceste nivele de abstractizare si
tipurile de modele ce le corespund sunt urm
atoarele:
CAPITOLUL 1. INTRODUCERE
Definirea unui modul este inclusa ntre cuvintele cheie module si endmodule. Identificatorul ce urmeaza cuvantului cheie module reprezinta numele modulului. Se recomanda utilizarea unor nume sugestive pentru comportamentul sau structura modulului. Optional, modulul poate contine o lista de porturi de intrare/iesire. Ordinea
porturilor poate fi semnificativa la instantierea modulului. Din acest motiv, se recomanda o asociere explicita ntre porturi si sarme n momentul instantierii unui modul.
Identificatorii din lista de porturi trebuie declarati ca intrari, iesiri sau bidirectionali
n partea de definitii a modulului. Sintaxa completa a declaratiei unui modul este
prezentat
a n continuare:
Sn
<modul>
::= module <nume_modul><lista_porturi>? ;
<articol_modul>*
endmodule
<nume_modul>
::=<IDENTIFICATOR>
<lista_porturi>
::=(<port><,<port>>*)
<articol_modul>
::=<declaratie_parametru>
||=<declaratie_port_intrare>
||=<declaratie_port_iesire>
||=<declaratie_port_bidirectional>
||=<declaratie_conexiune>
||=<declaratie_conexiune_reg>
||=<declaratie_timp>
||=<declaratie_intreg>
||=<declaratie_real>
||=<declaratie_eveniment>
||=<instantiere_poarta>
||=<instantiere_primitiva>
||=<instantiere_modul>
||=<redefinire_parametru>
||=<atribuire_continua>
||=<bloc_specify>
||=<specificatie_initial>
||=<specificatie_always>
||=<task>
||=<functie>
<lista_porturi> este o lista de declaratii de nume de porturi despartite prin
virgula. Directia si dimensiunea porturilor este declarata ulterior n corpul modulului.
In corpul modulului pot aparea urmatoarele articole:
10
CAPITOLUL 1. INTRODUCERE
cpuClk_i;
reset_ni;
cpuAddr_i;
data_io;
rdy_o;
//
//
//
//
//
intrare pe 1 bit
intrare pe 1 bit
bus de intrare pe 16 biti
bus de date bidirectional de 32 biti
iesire pe 1 bit
De remarcat ca denumirea porturilor a fost aleasa astfel ncat sa contina informatia referitoare la directia portului, informatie foarte utila la gestionarea unui
cod de dimensiuni mari. Mai multe recomandari referitoare la scrierea codului
Verilog se gasesc n sectiunea 2.9.
<declaratie_conexiune>, <declaratie_conexiune_reg>,
<declaratie_timp>, <declaratie_intreg>, <declaratie_real>: Declaratiile de variabile Verilog modeleaza atat sarme fizice sau abstracte, cat si obiecte
folosite la modelarea comportamentala de nivel nalt (generatoare de vectori de
test ce nu vor fi sintetizate). Descrierea tipurilor de date si a obiectelor Verilog
este prezentata n sectiunea 2.4.
<declaratie_eveniment>: Declarare de conditii (evenimente) care pot determina o actiune. Evenimentele se declara prin cuvantul rezervat event.
<instantiere_poarta>, <instantiere_primitiva>, <instantiere_modul>:
Instantierea unei porti logice definite n limbaj, a unei primitive definite de
utilizator sau a unui modul reprezint
a mecanismul de descriere a structurii unui
modul. Sintaxa specificatiei de instantiere de modul este prezentata n continuarea acestei sectiuni.
11
<redefinire_parametru>: Redefinirea explicita a unui parametru al unui modul n momentul instantierii acestuia se face folosind cuvantul cheie defparam
urmat de numele instantei modulului, numele parametrului si valoarea acestuia.
<atribuire_continua>: Atribuirea continua este introdusa prin cuvantul cheie
assign si este prezentata n sectiunea 2.6.
<bloc_specify>: Timpii de propagare din interiorul unui modul pot fi declarati
ntr-un bloc dedicat, folosind grupul de cuvinte cheie specify si endspecify.
<specificatie_initial>: Specificatia concurenta initial nu este sintetizabil
a. Ea este folosita pentru descrierea comportamentului modulelor care
genereaza vectori de test. Specificatia initial este descrisa n sectiunile 2.6 si
2.7.
<specificatie_always>: Specificatia concurenta always implementeaza un
mecanism de includere a uneia sau a mai multor specificatii secventiale ntr-un
bloc ce se executa concurent cu celalalte specificatii concurente. Specificatia
always este descrisa n sectiunile 2.6 si 2.7.
<task>, <functie>: Un task este similar cu o procedura C: permite includerea
unei sectiuni de cod n diferite locuri ale descrierii modulului. O functie este
similara cu un task, dar spre deosebire de acesta, functia returneaza o singura
valoare, nu poate contine ntarzieri (se executa ntr-un timp nul) si nu poate
apela task-uri. Task-urile si functiile Verilog sunt descrise n sectiunea 4.1.
Instantierea modulului ntr-un alt modul permite crearea unei ierarhii n structura
proiectului. Nu se pot defini module care sa se includa pe ele nsele (imbricate). O
definire de modul nu poate contine o alta definire de modul ntre cuvintele sale cheie
module si endmodule. Un modul include alt modul prin instantierea unei copii a
acestuia. Procesul este similar cu plantarea unor capsule de circuite integrate pe o
placa. Acelasi tip de circuit poate fi plasat de mai multe ori pe un cablaj imprimat,
eventual avand conectari diferite. Similar, un modul poate fi instantiat de mai multe
ori n unul sau mai multe module diferite, instantele putand avea parametrii diferiti.
Specificatia <instantiere_modul> creeaza una sau mai multe instantieri (aparitii)
ale modulului. De exemplu, un model de bistabil D se poate instantia de 16 ori pentru
a genera un registru de 16 biti.
Sintaxa specificatiei de instantiere de modul este prezentata n continuare:
Sn
<instantiere_modul>
::= <nume_modul> <asociere_parametru_valoare> ? <instanta_modul>
<,<instanta_modul>>* ;
<nume_modul>
::= <IDENTIFIER>
<asociere_parametru_valoare>
::= # ( <expresie> <,<expresie>>* )
12
CAPITOLUL 1. INTRODUCERE
<instanta_modul>
::= <nume_instanta> ( <lista_conexiuni_modul>? )
<nume_instanta>
::= <IDENTIFICATOR>
<lista_conexiuni_modul>
::= <conexiune_port_prin_pozitie> <,<conexiune_port_prin_pozitie>>*
||= <conexiune_port_prin_nume> <,<conexiune_port_prin_nume>>*
<conexiune_port_prin_pozitie>
::= <expresie>
||= <NULL>
<conexiune_port_prin_nume>
::= .<IDENTIFICATOR> ( <expresie> )
In continuare sunt prezentate cateva exemple de module Verilog care descriu circuite digitale elementare.
Modul vot majoritar cu trei intrari: descriere algoritmica a propagarii datelor.
n
V
module votMajoritar3Df (
i1,
// intrare de
i2,
// intrare de
i3,
// intrare de
decizie // decizie in
);
input
i1, i2, i3;
output decizie;
wire
wire
wire
vot 1
vot 2
vot 3
urma votului
vot12;
vot13;
vot23;
// operator AND
// operator OR
endmodule
Modul vot majoritar cu trei intrari: descriere cu porti logice definite n limbaj.
13
n
V
module votMajoritar3Gl (
i1,
// intrare de
i2,
// intrare de
i3,
// intrare de
decizie // decizie in
);
input
i1, i2, i3;
output decizie;
wire
wire
wire
and
and
and
or
vot 1
vot 2
vot 3
urma votului
vot12;
vot13;
vot23;
endmodule
n
T
La testarea celor doua module votMajoritar3Df si votMajoritar3Gl, n
mediul de testare testVotMajoritar, se observa aparitia glitch-urilor de hazard
combinational pe iesirile ambelor module testate. De remarcat si variatia variabilelor declarate pentru a monitoriza numarul de cazuri testate. Ca referinta,
figura 1.2 prezinta formele de unda obtinute prin simulare.
n
V
module upDnCounterPreset (
clk,
// intrare de ceas
reset_n,
// semnal de reset asincron
14
CAPITOLUL 1. INTRODUCERE
upDn_n,
ld,
di,
en,
count
//
//
//
//
//
);
input
input
input
input
input[3:0]
input
output[3:0]
reg[3:0]
clk;
reset_n;
upDn_n;
ld;
di;
en;
count;
count;
15
n
T
Ca referinta, figura 1.3 prezinta formele de unda obtinute prin simulare.
n
V
module add1C (
a, // primul operand
b, // al doilea operand
ci, // transport de intrare
s, // rezultatul
co // transport de iesire
);
input
input
input
output
output
a;
b;
ci;
s;
co;
//
//
//
//
endmodule
Sumator complet de 1 bit: descriere la nivel de porti logice.
n
V
module add1Gl (
a, // primul operand
b, // al doilea operand
ci, // transport de intrare
s, // rezultatul
co // transport de iesire
16
CAPITOLUL 1. INTRODUCERE
);
input
input
input
output
output
a;
b;
ci;
s;
co;
wire
wire
wire
c1;
c2;
c3;
and (c1, a,
and (c2, a,
and (c3, b,
or (co, c1,
//
//
//
//
b);
cin);
cin);
c2, c3);
c1
c2
c3
co
=
=
=
=
a and
a and
b and
c1 or
b;
cin;
cin;
c2 or c3;
endmodule
Sumator de 4 biti: descriere structurala cu instantieri de sumatoare de 1 bit.
n
V
module add4St (
a, // primul operand
b, // al doilea operand
ci, // transport de intrare
s, // rezultatul
co // transport de iesire
);
input[3:0]
input[3:0]
input
output[3:0]
output
a;
b;
ci;
s;
co;
wire[2:0]
cr;
// instanta bit 0
add1Gl add1Gl_0 (
.a
(a[0]
.b
(b[0]
.ci
(ci
.s
(s[0]
),
),
),
),
17
.co
(cr[0]
);
// instanta bit 1
add1Gl i_add1Gl_1 (
.a
(a[1]
.b
(b[1]
.ci
(cr[0]
.s
(s[1]
.co
(cr[1]
);
// instanta bit 2
add1Gl i_add1Gl_2 (
.a
(a[2]
.b
(b[2]
.ci
(cr[1]
.s
(s[2]
.co
(cr[2]
);
// instanta bit 3
add1Gl i_add1Gl_3 (
.a
(a[3]
.b
(b[3]
.ci
(cr[2]
.s
(s[3]
.co
(co
);
endmodule
),
),
),
),
)
),
),
),
),
)
),
),
),
),
)
n
V
module addxC (
a, // primul operand
b, // al doilea operand
ci, // transport de intrare
s, // rezultatul
co // transport de iesire
);
parameter width = 8;
// valoare implicita a parametrului
// valoarea actuala poate fi schimbata la instantiere
18
CAPITOLUL 1. INTRODUCERE
input[width-1:0]
input[width-1:0]
input
output[width-1:0]
output
a;
b;
ci;
s;
co;
n
V
module
i0,
i1,
s,
y
);
mux2x1C (
// intrare de date 0
// intrare de date 1
// intrare de selectie
// iesire
input
input
input
output
i0;
i1;
s;
y;
assign y = s ? i1 : i0;
endmodule
Multiplexor 2x1: descriere cu porti logice definite n limbaj.
n
V
module
i0,
i1,
s,
y
);
mux2x1Gl (
// intrare de date 0
// intrare de date 1
// intrare de selectie
// iesire
input
input
input
output
i0;
i1;
s;
y;
wire
s_n;
19
wire
s0, s1;
endmodule
Multiplexor2x1: descriere cu primitive definite de utilizator.
n
V
module
i0,
i1,
s,
y
);
mux2x1tUdp
// intrare
// intrare
// intrare
// iesire
input
input
input
output
i0;
i1;
s;
y;
(
de date 0
de date 1
de selectie
table
// i0 i1 s
0
? 0
1
? 0
?
0 1
?
1 1
0
0 x
1
1 x
endtable
endprimitive
:
:
:
:
:
:
:
y
0;
1;
0;
1;
0;
1;
20
CAPITOLUL 1. INTRODUCERE
n
V
module
i0,
i1,
i2,
i3,
s,
y
);
mux4x1tUdp
// intrare
// intrare
// intrare
// intrare
// intrare
// iesire
input
input
input
input
input[1:0]
output
i0;
i1;
i2;
i3;
s;
y;
wire
wire
mux1;
mux0;
(
de
de
de
de
de
date 0
date 1
date 2
date 3
selectie
n
V
module
i0,
i1,
s,
y
);
mux2x1tTg (
// intrare de date 0
// intrare de date 1
// intrare de selectie
// iesire
input
input
input
output
i0;
i1;
s;
y;
wire
s_n;
21
1.4
Testarea unui model de sistem digital se face ntr-un mediu de simulare similar cu o
masa de laborator.
Ca exemplu, se considera studierea n laborator a comportamentului unei porti
logice. Pe langa circuitul de studiat, pe masa de laborator exista si aparate electronice: sursa de alimentare, sursa de semnal, osciloscop. Conectarea aparatelor la
porturile circutului de studiat se face cu sarme. Ansamblul circuit de studiat-aparate
este un sistem nchis (nu exista conectoare cu ceva din exteriorul mesei).
Similar, ntr-un mediu de simulare sunt instantiate trei tipuri de module:
modelul sistemului de studiat;
modele de generatoare de stimuli (similare generatoarelor de semnal);
modele de monitorizare si verificare (similare aparatelor de masura si control).
Toate aceste module sunt instantiate (incluse) ntr-un modul fara porturi (similar
mesei de lucru din laborator). Conexiunile se fac ntre porturile sistemului de studiat
si porturile corespunzatoare ale generatoarelor de stimuli sau ntre porturile sistemului
de studiat si porturile monitoarelor/verificatoarelor de conditii.
Figura 1.4 prezinta grafic structura unui mediu de simulare Verilog. Modelul
dispozitivului de testat este stimulat prin semnale provenite de la generatorul de
vectori de test. Optional, acesta poate verifica iesirile sistemului si genera stimuli
n consecinta. Pentru verificari automate, se recomanda includerea unuia sau a mai
multor module responsabile pentru verificarea datelor, a protocolului de comunicatie
sau a altor conditii logice complexe. Monitoarele au numai porturi de intrare si genereaza mesaje de eroare sau de atentionare, fara a modifica starea ansamblului.
Modulele generatoare de vectori de test pot prelua din fisiere diverse date folosite
pentru determinarea valorilor semnalelor generate. Modulele de monitorizare a semnalelor si de verificare pot scrie n fisiere externe date sub diferite formate. In plus,
aceste module pot afisa sau scrie n fisiere mesaje informative, de atentionare sau de
eroare.
1.5
Comparatie Verilog-VHDL
22
CAPITOLUL 1. INTRODUCERE
Mediu de testare
Generator
de vectori
de test
Modul
sintetizabil
testat
Monitorizare
si
verificare
q: out bit);
Verilog
module dff (d, clk, q);
input
d, clk;
output q;
q <= d;
endmodule
23
Exemplu: Poart
a AND cu dou
a intr
ari
VHDL
entity and2 is
port (a, b: in bit; y: out bit);
end and2;
architecture basic2 of and2 is
begin
y <= a and b;
end basic2;
Verilog
module and2 (a, b, y);
input
a, b;
output y;
assign y = a & b;
endmodule
Capitolul 2
FUNDAMENTELE
LIMBAJULUI VERILOG
HDL
2.1
Conventii lexicale
Ca orice limbaj, Verilog are un numar de atomi lingvistici. Acesti atomi pot fi operatori, delimitatori, comentarii, numere, siruri, identificatori sau cuvinte cheie rezervate.
Toate cuvintele cheie rezervate sunt scrise cu minuscule. Lista tuturor cuvintelor cheie
este prezentat
a n anexa B. Limbajul Verilog (spre deosebire de VHDL) este un limbaj case-sensitive: literele minuscule au semnificatie diferita de literele majuscule
corespunzatoare.
Delimitatorii de atomi lingvistici sunt caracterul spatiu, caracterul tabulator
si caracterul linie noua. Cu exceptia prezentei acestora n siruri de caractere, aceste
caractere sunt ignorate.
Verilog suporta doua feluri de comentarii:
Comentarii pe o singura linie. Comentariul se ntinde de la aparitia a doua
caractere slash (//) si pana la sfarsitul liniei (marcat de caracterul linie
noua).
Comentarii pe mai multe linii. Comentariul se ntinde ntre marcherul de nceput
/* si marcherul de sfarsit */. Comentariile pe linii multiple nu pot fi incluse
unele n altele.
2.2
26
Includerea unui fisier n altul se face static, la compilare si este echivalenta cu copierea
fisierului inclus n pozitia n care apare directiva de includere de fisiere.
Modulul contine atat descrierea interfetei cu mediul exterior (alte module), cat si
comportamentul sau structura sa. Toate declaratiile facute ntr-un modul sunt locale
acelui modul. Ca o consecinta, nu exista obiecte (semnale) globale ca ntr-un program
software. Semnalele declarate cu acelasi nume, dar n module diferite, sunt semnale
diferite.
Intr-un modul pot fi instantiate alte module pentru a crea o structura ierarhica.
Spre deosebire de VHDL, n Verilog modulul nu are o declaratie explicita si nici
nu contine regiuni explicite pentru declaratii. Semnalele trebuie declarate nainte de
prima referire la acestea, dar declaratia poate fi facuta oriunde n corpul modulului.
Exist
a doua tipuri de subprograme utilizate n mod similar cu procedurile si
functiile C. Definirea subprogramelor are rolul de a condensa codul Verilog n cazul
necesitatii repetarii unor portiuni identice de cod. Exista doua tipuri de subprograme
marcate de cuvintele rezervate: task si function.
2.3
Setul de valori
2.3.1
Numere ntregi
Sn
27
2.3.2
Numere reale
28
2.3.3
S
iruri
Un sir este format dintr-o secventa de caractere incluse ntre ghilimele ( ). Fiecare
caracter este reprezentat pe 8 biti si este tratat ca un ntreg pozitiv. De exemplu,
pentru a stoca mesajul "WAIT" este necesara definirea unei variabile de 32 de biti.
parameter nrChar = 4;
reg[nrChar*8-1:0] mesaj;
...
mesaj <= "WAIT";
Cateva caractere de control pot fi introduse n siruri daca sunt precedate de caracterul backslash (\).
\n
\t
\\
\"
2.4
29
wire outGate1;
reg outGate2;
//
//
//
//
Cu alte cuvinte, semnalul de tip wire modeleaza o sarma obisnuita careia trebuie
sa i se atribuie tot timpul o valoare. Semnalul de tip reg modeleaza o sarma mai
speciala (nu un registru) capabila sa si pastreze valoarea ntre doua actualizari
succesive. Aceasta proprietate a sarmelor de tip reg le face folositoare la modelarea
elementelor de memorare din sistemele digitale (bistabile).
Datele de tip net pot fi declarate cu mai multe cuvinte cheie, n functie de comportamentul acestora:
wire
tri
wor
trior
wand
triand
trireg
tri0
tri1
supply0 Tip utilizat pentru modelarea conexiunii la masa, valoare logica permanent 0.
supply1 Tip utilizat pentru modelarea conexiunii la sursa de alimentare, valoare
logica permanent 1.
30
In Verilog este posibila nedeclararea unei sarme de tip net. In acest caz, declaratia
implicita este de tip wire de 1 bit. Se recomanda neutilizarea acestei reguli Verilog
si declararea explicita a tuturor sarmelor.
Datele de tip register pot fi declarate cu mai multe cuvinte cheie, n functie de
comportamentul acestora:
reg
integer
Tip folosit exclusiv la modelarea la nivel nalt (nu pentru sinteza) fiind
echivalent cu tipul reg pe 32 de biti.
time
real
realtime
Atat sarmele de tip net, cat si cele de tip reg pot fi extinse pe una sau doua dimensiuni. Extinderea pe o dimensiune modeleaza un bus. Extinderea pe doua dimensiuni
modeleaza o matrice de date. Verilog nu ofera suport pentru structuri de date de mai
mult de doua dimensiuni. Dimensiunea vectorilor se precizeaza la declararea sarmei
ntre cuvantul cheie ce desemneaza tipul de sarma si numele acesteia.
parameter
width_p = 16;
wire [7:0]
dataBus;
// bus de 8 biti
reg[width_p-1:0] shReg;
// bus de dimensiune parametrizabila
assign dataBus
= 8hAB; // atribuire catre tot bus-ul
assign dataBus[0]
= 1b0;
// atribuire catre un membru al bus-ului
assign dataBus[2:0] = 3b101; // atribuire catre o portiune din bus
// registru de deplasare in inel de dimensiuni generice
// valoarea viitoare se obtine din valoarea curenta
// deplasata cu un bit la stanga si
// transferul MSb pe pozitia LSb
always @(posedge ck)
shReg <= {shReg[width_p-2:0], shReg[width_p-1]};
Desi nu este impusa nici o restrictie, se recomanda utilizarea indexarii vectorilor
n sens descrescator, de la un numar maxim pana la 0 (nu pana la 1).
Dimensiunea matricilor se precizeaza la declararea sarmei: latimea se declara ntre
cuvantul cheie ce desemneaza tipul de sarma si numele acesteia, iar adancimea se
declara dupa numele semnalului.
parameter
parameter
width_p = 16;
deep_p = 8;
31
reg[15:0]
regFile[255:0];
// declaratie de matrice bidimensionala
// ce poate corespunde unui set de
// 256 registre de cate 16 biti
reg178;
zeroFlag;
wire[15:0]
wire
reg[width_p-1:0]
mem[deep_p-1:0];
// matrice de memorie bidimensionala
// de dimensiuni parametrizabile
wire[width_p-1:0] mem_0;
// vector corespunzator locatiei
// de la adresa 0
assign mem_0 = mem[0];
accesarea registrului de la
adresa 178
accesarea bitului 2 din registrul de
la adresa 178
n
V
module tVer1
reset_ni,
ck_i,
t_i,
qt_o
);
input
input
input
output
(
//
//
//
//
reset_ni;
ck_i;
t_i;
qt_o;
32
assign
d = t_i ^ qt_o;
// operator XOR
n
V
module dff (
reset_ni,
ck_i,
d_i,
qd_o
);
//
//
//
//
input
input
input
output
reset_ni;
ck_i;
d_i;
qd_o;
reg
qd_o;
module tVer2 (
33
reset_ni,
ck_i,
t_i,
qt_o
//
//
//
//
);
input
input
input
output
reset_ni;
ck_i;
t_i;
qt_o;
d = t_i ^ qt_o;
// instantierea bistabilului
dff i_dff(
.reset_ni (reset_ni ),
.ck_i
(ck_i
),
.d_i
(d
), //
//
.qd_o
(qt_o
)
//
//
//
);
endmodule
A treia versiune de modelare ncapsuleaza toata descrierea ntr-o singura specificatie always. Sarma conectata pe intrarea bistabilului nu mai este declarata explicit.
Aceasta versiune este cea mai folosita la proiectarea RTL pentru modelarea unui
bistabil T si are avantajul ca ascunde structura interna pentru a descrie doar comportamentul.
n
V
module tVer3
reset_ni,
ck_i,
t_i,
qt_o
);
input
input
input
output
(
//
//
//
//
reset_ni;
ck_i;
t_i;
qt_o;
34
n
T
In scop de testare, cele trei versiuni de modelare au fost incluse ntr-un
mediu unic de simulare.
2.5
Operatori
Verilog are trei tipuri de operatori: cu unul, doi sau trei operanzi. Operatorii unari
apar n fata operandului, operatorii binari apar ntre cei doi operanzi, iar operatorii
ternari separa cei trei operanzi.
a = ~b;
// ~ este operator unar (complementare logica)
c = d & e;
// & este operator binar (functie logica AND)
f = g ? h : i; // ?: este operator ternar
// (conditie, functie multiplexor)
// daca g=1, f=h, altfel f=i
Tabelul 2.1 prezinta operatorii Verilog n ordinea precedentei acestora.
2.5.1
Operatori aritmetici
35
2.5. Operatori
Operator
+
!
~
&
~&
^
~^
|
~|
*
/
%
+
<<
>>
<
<=
>
>=
==
!=
===
!==
&
^
~^
|
&&
||
?:
Descriere
Operator unar pentru numar pozitiv
Operator unar pentru numar negativ
Operator unar pentru negare logica
Operator unar pentru negare pe biti
Operator de reducere AND (aplicat unui vector produce un bit)
Operator de reducere NAND
Operator de reducere XOR
Operator de reducere XNOR
Operator de reducere OR
Operator de reducere NOR
Operator binar de multiplicare
Operator binar de mpartire
Operator binar modulo
Operator binar de adunare
Operator binar de scadere
Operator binar de deplasare stanga
Operator binar de deplasare dreapta
Operator binar de comparare mai mic
Operator binar de comparare mai mic sau egal
Operator binar de comparare mai mare
Operator binar de comparare mai mare sau egal
Operator binar de egalitate logica
Operator binar de inegalitate logica
Operator binar de egalitate cu selectie
Operator binar de inegalitate cu selectie
Operator binar logica AND pe biti
(aplicat unor operanzi vectori produce un vector)
Operator binar logica XOR pe biti
Operator binar logica XNOR pe biti
Operator binar logica OR pe biti
Operator binar AND logic
(aplicat unor expresii, produce o valoare de adevar a unei conditii)
Operator binar OR logic
Operator ternar conditional
Tabelul 2.1
Operatorii Verilog n ordinea precedentei acestora.
36
begin
4b1110;
4b1000;
-9;
// 14
// 8
// -9
2.5. Operatori
37
38
# Zecimal: 255 + 3 = 2
In cadrul operatiilor aritmetice obiectele de tip net, obiectele de tip reg si numerele ntregi n format cu baza de numeratie sunt considerate numere pozitive fara
semn. Sunt considerate numere ntregi cu semn obiectele de tip integer si numere
ntregi n format zecimal. Numerele negative sunt reprezentate n binar n complement
fata de 2. Daca un bit al unui operand este x atunci rezultatul operatiei aritmetice
este x.
2.5.2
Operatori relationali
fals (0)
15 > 8hx
nedefinit (x)
fals (0)
3 >= 3
adevarat (1)
2.5.3
Operatori de egalitate
39
2.5. Operatori
opA
opB
opC
opD
=
=
=
=
b10x0
b10x0
16BExF
16BEEF
opA == opB
fals (0)
adevarat (1)
adevarat (1)
opC != opD
nedefinit (x)
adevarat (1)
2.5.4
Operatori logici
=
=
=
=
=
=
1b0
1b1
4b1010
4b1001
4b0000
1bx
evaluat
evaluat
evaluat
evaluat
ca
ca
ca
ca
1
1
0
x
fals (0)
sigA || sigB
adevarat (1)
!sigA
adevarat (1)
adevarat (1)
busC || busD
adevarat (1)
!busC
fals (0)
40
!busE
adevarat (1)
!sigF
indecis (x)
2.5.5
0
0
0
0
0
0
0
1
x
x
1
0
1
x
x
1
1
0
x
x
x
0
x
x
x
x
x
x
x
x
z
0
x
x
x
| (or)
0
1
x
z
z
x
x
x
x
~^ (xnor)
0
1
x
z
~ (not)
0
1
1
0
x
x
0
0
1
x
x
1
1
1
1
1
0
1
0
x
x
x
x
1
x
x
1
0
1
x
x
z
x
1
x
x
x
x
x
x
x
z
x
x
x
x
z
x
Tabelul 2.2
Tabelul functiilor implementate de operatorii logici.
Exemple:
sigA
sigB
busC
busD
=
=
=
=
1b0
1b1
4b1010
4b1001
41
2.5. Operatori
busE = 4b0000
sigF = 1bx
sigA & sigB
1b0
sigA | sigB
1b1
~sigA
1b1
4b1000
busC | busD
4b1011
~busC
4b0101
~busE
4b1111
~sigF
1bx
1b0
1bx
2.5.6
Operatori de reducere
evaluat ca 0
|busA
evaluat ca 1
42
^busA
evaluat ca 0
^busB
evaluat ca 1
Operatorul de reducere ^ poate fi folosit pentru a verifica daca un bit dintr-un bus
are valoare x:
busC = 4b10x0
^busC
evaluat ca x
Aceast
a observatie poate fi folosita n specificatii de verificare a coerentei datelor
de pe un bus:
if (^busC === 1bx)
$display("Valoare necunoscuta pe busC = %b", busC);
O alta aplicatie a operatorilor de reducere consta n compararea valorii unui vector cu valoarea ntreaga 0 (toti bitii egali cu 0) sau verificarea ajungerii la capatul
domeniului de reprezentare a numerelor pozitive (toti bitii egali cu 1).
&busC
~|busC
2.5.7
Operatori de deplasare
evaluat ca 8b0010_0111
busA << 2
evaluat ca 8b0111_0000
43
2.5. Operatori
parameter power_p = 7;
1 << power_p
echivalent cu 2 la puterea 7, 8b10000000
opA << opB
2.5.8
Operator conditional
2.5.9
Concatenarea este operatia de alaturare a bitilor ntr-un bus. Doua sau mai multe
expresii care semnifica biti se pot alatura pentru a forma o valoare reprezentata pe
mai multi biti. Operatorii de concatenare sunt caracterele acolade: { si }. O anumita
expresie poate fi replicata de un numar de ori n cadrul concatenarii.
Exemple:
// initializarea cu un pattern
reg[127:0] reg128;
reg128 <= {4{32hDEAD_BEEF}};
// de 4 ori cate 32 de biti
// echivalent cu 128hDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF
// registrul cu deplasare stanga
reg[31:0] leftShReg;
leftShReg <= {leftShReg[30:0], 1b0};
44
2.6
Specificatii concurente
Sn
<atribuire_continua>
::= assign <tarie_driver>? <intarziere>? <lista_de_atribuiri>
<tarie_driver>
::= ( <STRENGTH0> , <STRENGTH1> )
||= ( <STRENGTH1> , <STRENGTH0> )
<intarziere>
45
::= # <numar>
||= # <identificator>
||= # (<expresie_mintypmax><,<expresie_mintypmax>>?<,
<expresie_mintypmax>>?)
<lista_de_atribuiri>
::= <atribuire> <,<atribuire>>*
<atribuire>
::= <nume_semnal> = <expresie>
<STRENGTH0>
::= supply0 || strong0 || pull0 || weak0 || highz0
<STRENGTH1>
::= supply1 || strong1 || pull1 || weak1 || highz1
<expresie_mintypmax>
::= <expresie>
||= <expresie1> : <expresie2> : <expresie3>
Specificatia este introdusa de cuvantul rezervat assign. Precizarea tariei sursei
este optionala si se face sub forma unui cuplu de cuvinte cheie ce precizeaza taria starii
de 0 si a starii de 1. Precizarea ntazierii cu care se face atribuirea este optionala.
Intarzierea este precedata de simbolul # si are valoarea absoluta determinata de directiva timescale. Intarzierea poate fi un numar, un identificator care are asociata
o valoare numerica sau un triplet de valori ale ntarzierii minime, tipice si maxime
despartite prin caracterul doua puncte (:).
Lista de atribuiri contine una sau mai multe atribuiri de semnale. O atribuire de
semnal este formata din numele semnalului caruia i se atribuie o valoare, simbolul de
atribuire = si o expresie din care, n urma evaluarii, rezulta o valoare similara cu cea
a semnalului atribuit.
Exemple de atribuiri continue:
assign (pull0, strong1) #2 dst = src;
// atribuie semnalului dst valoarea src
// cu intarziere de 2 unitati de timp,
// taria semnalului dst fiind "pull0" in
// stare 0 si "strong1" in stare 1
assign #delay dst = src;
// atribuie semnalului dst valoarea src
// cu o intarziere precizata de variabila
// delay
assign #(1:2:3) dst = src; // atribuie semnalului dst valoarea src
// cu intarzierea:
// 1 unitate de timp (minim)
// 2 unitate de timp (tipic)
// 3 unitate de timp (maxim)
46
Specificatia initial este o specificatie concurenta care include una sau mai
multe specificatii procedurale (secventiale). Specificatia initial se executa o singura
data. Executia acesteia ncepe la timpul 0. In cadrul specificatiilor procedurale se pot
include si specificatii de temporizare. Odata executata ultima specificatie secventiala,
specificatia concurenta initial si nceteaza efectul. De mentionat ca, specificatia
initial nu este sintetizabila (nu poate descrie un comportament de hardware real),
ea fiind ignorata de catre toate programele de sinteza. Specificatia initial este
folosita exclusiv pentru modelarea vectorilor de test. Sintaxa specificatiei initial
este urmatoarea:
Sn
<specificatie_initial>
::=initial <specificatie_secventiala>
Specificatia always este o specificatie concurenta, care include una sau mai multe
specificatii procedurale (secventiale), similar cu specificatia initial. Diferenta dintre
acestea consta n faptul ca specificatia always se executa la infinit. Executia acesteia
ncepe la timpul 0. Dupa executia ultimei specificatii secventiale se reia executia
acestora de la nceput, cu prima specificatie aflata dupa cuvantul cheie always. In
cadrul specificatilor procedurale se pot include si specificatii de temporizare. In plus,
specificatia always contine o conditie care determina reluarea executiei specificatiilor.
Sintaxa specificatiei always este urmatoarea:
Sn
<specificatie_always>
::=always <specificatie_secventiala>
Prin natura sa, specificatia always este repetitiva. Din acest motiv, este obligatorie controlarea temporizarii repetarii acesteia. Daca o specificatie always nu are
prevazut un mecanism de temporizare, desi nu este eroare de sintaxa, simularea va fi
blocata la timpul 0 datorita unei bucle infinite cu ntarziere nula.
Codul urmator modeleaza un inversor ideal al carui iesire este conectata la intrare.
Evident, acest circuit oscileaza pe frecventa infinit.
always clk = ~clk;
Precizarea unui timp dupa care se repeta specificatia conduce la un mod foarte
uzual de modelare a unui generator de semnal periodic, de ceas:
always #5 clk = ~clk;
Semnalul clk va avea un comportament periodic similar cu cel al unui semnal de
ceas cu perioada 10ns (semnalul si complementeaza starea la fiecare 5ns).
Detalierea specificatiilor secventiale ce pot aparea n campul
<specificatie_secventiala> este facuta n sectiunea 2.7.
2.7
47
Specificatii secventiale
Sn
<specificatie_secventiala>
::=<atribuire_blocanta>;
||= <atribuire_neblocanta>;
||= if (<conditie>) <specificatie_secventiala>
||= if (<conditie>) <specificatie_secventiala>
else <specificatie_secventiala>
||= case (<expresie>) <articol_case>+ endcase
||= casez (<expresie>) <articol_case>+ endcase
||= casex (<expresie>) <articol_case>+ endcase
||= forever <specificatie_secventiala>
||= repeat (<expresie>) <specificatie_secventiala>
||= while (<expresie>) <specificatie_secventiala>
||= for (<atribuire>; <expresie>; <atribuire>)
<specificatie_secventiala>
||= <control_intarziere> <specificatie_secventiala>
||= <control_eveniment> <specificatie_secventiala>
||= wait (<expresie>) <specificatie_secventiala>
||= -> <nume_eveniment>;
||= <bloc_secvential>
||= <bloc_paralel>
||= <activare_task>
||= <activare_task_sistem>
||= disable <nume_task>;
||= disable <nume_bloc>;
||= force <atribuire>;
||= release <net>;
2.7.1
48
a sarmei asociate. Expresia din partea dreapta a simbolului de atribuire (=) poate fi
interpretata ca un circuit combinational sursa pentru semnal.
In schimb, atribuirile secventiale nu modifica instantaneu valoarea unei variabile
ci programeaza modificarea valorii acesteia. Acest mecanism poate fi nteles ca
plasarea valorii ntr-un registru a carui iesire devine vizibila doar la momentul de
timp planificat. Atribuirea n sine are durata zero, dar registrul mentine valoarea
pana la o noua modificare a acesteia, chiar daca sursa ce a generat valoarea este
dezactivata.
Atribuirile secventiale pot fi interpretate ca atribuiri declansate cu ntarziere.
Evenimentul de declansare apare cand simularea executiei modelului HDL ajunge la
acea specificatie. Momentul la care se evalueaza o atribuire secventiala poate fi controlat prin specificatii de control al evenimentelor, specificatii de control al timpului,
specificatii conditionale (if, case) sau specificatii de iteratii.
Exist
a doua tipuri de atribuiri secventiale:
Atribuiri secventiale blocante (atriburi cu simbolul =) si
Atribuiri secventiale neblocante (atriburi cu simbolul <=).
Distinctia dintre cele doua tipuri de atribuiri este usurata daca se asociaza acestora conceptele VHDL de variabila si de semnal. In VHDL, variabila este un
obiect ce are asociata o valoare posibil de modificat instantaneu printr-o atribuire
specifica. Variabila este un obiect abstract, folosit doar ca obiect de stocare temporara a unei valori, pe parcursul descrierii unui algoritm secvential. Semnalul n
VHDL este un obiect ce are asociat atat o valoare instantanee, cat si un driver
de semnal (signal driver, n limba engleza). Driverul de semnal este o multime
de cupluri valoare-timp (timpul avand valori crescatoare), care modeleaza forma de
unda planificata (programata) pentru acel semnal. O atribuire de semnal VHDL nu
modifica instantaneu valoarea acestuia, ci adauga o nregistrare la driverul acestuia.
Odata cu scurgerea timpului de simulare, fiecare semnal si actualizeaza valoarea daca
n driver exista o nregistrare planificata la timpul curent de simulare.
VHDL precizeaza reguli explicite referitoare la gestiunea nregistrarilor din driverul
unui semnal, n functie de momentele de aparitie si de timpii relativi asociati acestora.
Aceleasi concepte pot fi aplicate, desi nu sunt explicit enuntate, si atribuirilor blocante
si neblocante existente n Verilog.
Atribuiri secventiale blocante. O atribuire secventiala blocanta are sintaxa
prezentata n continuare. Se remarca simbolul de atribuire =.
Sn
49
Sn
Sn
a, b, c, d, e, f;
initial
50
begin
// valori initiale
a = 1b0;
b = 1b0;
c = 1b0;
// modificari ale valorilor cu atribuiri blocante
a = #10 1b1;
b = #2 1b1;
c = #4 1b1;
#50
a = #10 1b0;
b = #2 1b0;
c = #4 1b0;
end
initial
begin
// valori initiale
d <= 1b0;
e <= 1b0;
f <= 1b0;
// modificari ale valorilor cu atribuiri neblocante
d <= #10 1b1;
e <= #2 1b1;
f <= #4 1b1;
#50
d <= #10 1b0;
e <= #2 1b0;
f <= #4 1b0;
end
// monitorizarea modificarilor
initial
begin
$monitor("%M %t a=%b, b=%b, c=%b, d=%b, e=%b, f=%b",
$time, a, b, c, d, e, f);
#100
$display("%M %t NOTE: Simularea s-a sfarsit.", $time);
$stop;
end
endmodule
Mesajele generate sunt:
#
#
#
#
blockingNonblocking
blockingNonblocking
blockingNonblocking
blockingNonblocking
0
2
4
10
a=0,
a=0,
a=0,
a=1,
b=0,
b=0,
b=0,
b=0,
c=0,
c=0,
c=0,
c=0,
d=0,
d=0,
d=0,
d=1,
e=0,
e=1,
e=1,
e=1,
f=0
f=0
f=1
f=1
51
#
#
#
#
#
#
#
#
#
blockingNonblocking 12
blockingNonblocking 16
blockingNonblocking 52
blockingNonblocking 54
blockingNonblocking 60
blockingNonblocking 76
blockingNonblocking 78
blockingNonblocking 82
blockingNonblocking 100
e=1, f=1
e=1, f=1
e=0, f=1
e=0, f=0
e=0, f=0
e=0, f=0
e=0, f=0
e=0, f=0
sfarsit.
Formele de unda ale semnalelor sunt prezentate n figura 2.1. Se remarca faptul
ca semnalele c, d, e, care au fost atribuite cu specificatii neblocante, si modifica
valorile la timpul 0ns (respectiv 50ns) plus ntarzierea planificata (10ns, 2ns
si 4ns). In acest caz, ntarzierile sunt relative la acelasi moment de timp. In
schimb, semnalele care au fost atribuite cu specificatii neblocante, si modifica
valorile la timpi ce trebuie nsumati. a si modifica valoarea la 10ns dupa timpul
curent, b la 2ns dupa modificarea lui a, iar c la nca 4ns dupa schimbarea
semnalului b.
52
n
T
=
=
=
=
1
1
0
1
53
n
T
Simularea comparativa a modulului RTL si a celui produs dupa sinteza
evidentiaza eroarea n comportamentul celor doua modele. Figura 2.3 prezinta formele
de unda ale celor doua module (RTL si la nivel de poarta logica) instantiate n acelasi
mediu de test.
2.7.2
Specificatii conditionale
54
Sn
if (<conditie>) begin
<specificatii_secventiale1>
end
[else begin
<specificatii_secventiale0>
end]
Executia specificatiei if consta n evaluarea conditiei urmata de executarea unui
grup de specificatii, n functie de valoarea de adevar a acesteia. Un caz particular, dar foarte ntalnit, este cel al specificatiei conditionale n care, indiferent de
valoarea de adevar a conditiei, se atribuie valori aceluiasi semnal. In acest caz,
specificatia if modeleaza comportamentul unui multiplexor: conditia reprezinta circuitul combinational de generare a intrarii de selectie. De exemplu, sintetizatorul
produce structura din figura 2.4 pornind de la codul sursa urmator:
if (a_i && b_i) begin // selectia este AND intre doua intrari
y_o <= c_i ^ d_i;
end
else begin
y_i <= e_i | f_i;
end
Specificatiile conditionale pot fi incluse unele n altele. In acest caz, se recomanda
folosirea delimitatorilor begin si end pentru evitarea ambiguitatilor (carui if i corespunde else?). Alternativa else este optionala.
Exemplul urmator prezinta folosirea specificatiilor conditionale pentru modelarea
unui registru cu functie completa. Tabelul de functionare este descris n continuare:
// nr. |reset clk en ld cnt sh up lf | out++
// -----------------------------------------------// 1 | 0
X
X
X
X
X
X X | 0
// 2 | 1
^
0
X
X
X
X X | out
// 3 | 1
^
1
1
X
X
X X | data
// 4 | 1
^
1
0
1
X
1 X | out+1
// 5 | 1
^
1
0
1
X
0 X | out-1
// 6 | 1
^
1
0
0
1
X 1 | out<<1
// 7 | 1
^
1
0
0
1
X 0 | out>>1
// 8 | 1
^
1
0
0
0
X X | out
55
56
end
end
end
end
2.7.3
Specificatii de selectie
Sn
case (<expresie>)
valoare{, valoare}: <specificatii_secventiale>
[default:
<specificatii_secventiale>]
endcase
Specificatiile alternative casex si casez permit existenta valorilor x si z n expresiile valorilor. Acestea sunt cazuri care trebuie folosite cu grija deoarece ascund
potentiale pericole la sinteza.
Executia specificatiei case ncepe cu evaluarea expresiei. Valoarea evaluata se
compara secvential, ncepand cu prima valoare ce apare n lista. Daca se gaseste
o identitate, se executa specificatiile secventiale ce i corespund si apoi se ncheie
executia specificatiei case. Ca o consecinta, daca doua valori sunt egale, se executa
grupul de specificatii asociat primei aparitii a acelei valori. Daca valoarea la care a fost
evaluata expresia nu a fost gasita, se executa specificatiile care apar dupa cuvantul
rezervat default. Folosirea default nu este obligatorie. Se recomanda folosirea
acesteia pentru evitarea buclelor nedorite ce pot aparea n circuitele combinationale
modelate incorect.
Ca exemplu, este prezentata modelarea unei unitati logico-aritmetice.
// opcod-uri asociate operatiilor
define ADD
3b000
// suma operanzilor
define SUB
3b001
// diferenta operanzilor
define XOR
3b010
// XOR pe biti intre operanzi
define AND
3b011
// AND pe biti intre operanzi
define PASS_L 3b100
// trece operand stanga
define NEG_L
3b101
// trece operand stanga negat bit cu bit
module caseEx (
func_i,
leftOp_i,
rightOp_i,
rez_o
);
input[2:0]
//
//
//
//
func_i;
functie
operand stanga
operand dreapta
rezultat
57
input[7:0]
input[7:0]
output[7:0]
reg[7:0]
leftOp_i;
rightOp_i;
rez_o;
rez_o;
2.7.4
Specificatii de iteratii
Exista patru tipuri de specificatii pentru iteratii. Sintaxa acestora este prezentata n
continuare.
Sn
forever
<specificatii_secventiale>
repeat (<expresie>)
<specificatii_secventiale>
while (<expresie>)
<specificatii_secventiale>
for (<atribuire_initiala>; <expresie>; <atribuire_pas>)
<specificatii_secventiale>
Specificatia forever se executa pana la aparitia unei specificatii disable. Pentru
a nu se repeta la acelasi moment al simularii, specificatia forever trebuie sa includa
un control temporal. Cu acesta specificatie se poate modela un semnal de ceas, dupa
cum urmeaza:
reg clk;
initial begin
clk <= 1b0;
#5 forever
#10 clk <= ~clk;
end
58
ADS_COMANDA
8h20
ADS_INDICATORI 8h20
write(ADS_INDICATORI, 16h0000);
// anuleaza starea indicatorilor
write(ADS_COMANDA, 16h0001);
// bit0=1 semnifica "lanseaza comanda..."
break(2);
// asteapta 2 perioade de ceas
read(ADS_INDICATORI);
// citeste adresa registrului de indicatori
while (mpuData_i[15])
// testeaza bit15 al datelor citite
// bit15=1 semnifica "comanda terminata"
read(ADS_INDICATORI);
// continua citirea indicatorilor
// pana cand actiunea este terminata
// (bit15=1)
break(2);
// executa alte actiuni...
Specificatia for se executa de un numar precizat de ori. In plus fata de specificatia
repeat, aceasta specificatie permite accesarea de catre specificatiile secventiale a indexului iteratiei. Indexul trebuie explicit declarat ca integer. Indexul are o valoare
initiala si se modifica la fiecare iteratie conform atribuire_pas. La fiecare iteratie
se verific
a starea de adevar a unui expresii n care intra indexul.
Specificatia for este folosita frecvent atat la initializarea matricilor ce modeleaza
structuri de memorie, cat si la modelarea diversilor algoritmi ce necesita controlul
iteratiilor.
parameter adsDim_p
= 10;
59
parameter dataDim_p
//
//
//
//
= 16;
reg[dataDim_p-1:0]
integer
memory[(1<<adsDim_p)-1 : 0];
init_mirror; // index pentru specificatia "for"
// initializare memorie
initial begin
for (init_mirror = 0;
// valoare initiala
init_mirror < (1<<adsDim_p);
// conditie
init_mirror = init_mirror + 1); // actualizare index
begin
if (init_mirror == 0) begin
// plasarea unui "marcher" la o anumita adresa
memorie[init_mirror] <= 16hDEAD_BEEF;
end
else begin
// intializarea datei cu valoarea adresei
memorie[init_mirror] <= init_mirror;
end
end
end
Desi nu este cel mai indicat mod de descriere, operatiile efectuate la adunarea
numerelor binare pot fi exprimate cu o specificatie for, dupa cum urmeaza:
parameter
width_p = 4;
integer
i;
reg
tmp;
// transport temporar
always @(a_i or b_i or ci_i) begin
tmp = ci_i;
for (i = 0; i < width_p; i = i + 1) begin
s_o[i] = a_i[i] ^ b_i[i] ^ tmp;
tmp
= (a_i[i] & b_i[i]) | (a_i[i] & tmp) | (b_i[i] & tmp);
end
co_o = tmp;
end
2.7.5
60
Controlul evenimentelor.
Controlul nt
arzierii consta din specificarea unui interval de timp ntre momentul aparitiei specificatiei si momentul executarii efective a acesteia. O ntarziere
a executiei specificatiei secventiale este marcata n cod prin precedarea acesteia de
simbolul # si de un numar ce reprezinta numarul de unitati de timp cu care va fi
ntarziata executia.
Sn
#<intarziere> <specificatie_secventiala>
Specificatia ce are asociata o ntarziere trebuie nteleasa ca asteapta ntarzierea
impusa nainte de executia specificatiei asociate.
Exemplu:
Sn
initial begin
#5 semnal = 1;
#6 semnal = 2;
#2 semnal = 3;
end
// specificatia 1
// specificatia 2
// specificatia 3
Sn
#<intarziere> ;
Un caz particular, dar nu lipsit de utilitate practica, l reprezinta ntarzierea explicita cu 0 unitati de timp:
#0 ;
Semnificatia acesteia este: nu se avanseaza timpul de simulare pana la terminarea
tuturor evenimentelor programate a avea loc la acest moment de timp. De exemplu,
urmatoarele cupluri de specificatii au comportamente diferite:
// atribuire blocanta plasata inaintea celei neblocante
always @(posedge clk)
sigBloc_B1
= sigBloc_B1 + 1;
always @(posedge clk)
sigNebloc_B1 <= sigBloc_B1;
61
Front pozitiv
0 -> x
0 -> x
0 -> 1
x -> 1
z -> 1
Tabelul 2.3
Asocierea fronturilor unui semnal cu evenimentele acestuia.
Sn
@ <eveniment> <specificatie_secventiala>
Exemple:
@(posegde clk)
@(posedge clk or negedge reset_n)
@(semnalA or semnalB)
n
V
timescale 1ns/1ps
module clkreset_noGen(
clk_o,
// semnal de ceas
62
reset_no
);
// perioada de ceas
parameter tCkPer_p
parameter phaseCk_p
parameter phaseRst_p
parameter resetWidth_p
output
output
reg
reg
clk_o;
reset_no;
clk_o;
reset_no;
Sn
63
2.8
counter = 0;
data = intReg;
Directive de compilare
Directivele de compilare nu descriu sisteme hardware, ci transmit simulatorului anumite informatii utilizate n procesul de simulare. La compilarea unei directive de
compilare, efectul acesteia ramane pana la terminarea procesului de compilare, care
poate contine chiar mai multe fisiere. Directivele de compilare se identifica n cod prin
cuvintele cheie rezervate precedate de caracterul (). Efectul unor directive de compilare poate fi ntrerupt de directive de compilare complementare. Lista directivelor
de compilare Verilog este prezentata n continuare:
define si undefine: utilizate pentru substitutie de texte, similar cu utilizarea
directivei C #define. O substitutie impusa cu define este valabila pana la
aparitia directivei undefine sau pana la compilarea tuturor fisierelor.
ifdef, ifndef, else, endif: utilizate pentru compilari conditionate.
default_nettype: utilizata pentru stabilirea tipului de sarma implicit, n
cazul nedeclararii acestora. In lipsa acestei directive, sarma implicita este de
tip wire pe 1 bit.
include: utilizata pentru includerea in-line a textului dintr-un fisier n codul
sursa, n locul aparitiei directivei.
resetall: utilizata pentru anularea tuturor directivelor de compilare anterioare.
timescale: utilizata pentru asocierea unei valori absolute unitatii de timp
Verilog.
unconnected_drive, nounconnected_drive: utilizata pentru asocierea implicita a porturilor de intrare neconectate cu valori logice 0 sau 1.
cell_define, endcell_define: utilizata pentru declararea unui modul ca
celul
a posibil de accesat din rutine PLI.
2.8.1
define si undefine
64
define WIDTH
reg[WIDTH-1:0]
32
dataBus;
sdramMode;
wrAddr;
// scriere registre
always @(posedge mpuClk_i or posedge mpuReset_ni) begin
if (mpuReset_ni) begin
sdramMode <= 4b110_0;
end
else begin
//incarca sdramMode din bitii de date 6, 5, 4 si 0
if (load && (mpuAddr_i == SDRAM_MODE_ADDR)) begin
sdramMode <= {mpuData_i[6:4], mpuData_i[0]};
end
end
end
always @(posedge mpuClk_i or posedge mpuReset_ni) begin
if (mpuReset_ni) begin
wrAddr <= 16b0;
end
else begin
if (load && (mpuAddr_i == WR_ADDR)) begin
wrAddr <= mpuData_i;
end
end
end
// citire registre
always @(posedge mpuClk_i or posedge mpuReset_ni) begin
if (mpuReset_ni) begin
mpuData_o <= 16b0;
end
else begin
case (mpuAddr_i)
SDRAM_MODE_ADDR:
mpuData_o <= {9b0, sdramMode[3:1], 3b0, sdramMode[0]};
...
WR_ADDR: mpuData_o <= wrAddr;
...
65
default:
endcase
end
end
2.8.2
Aceste directive de compilare sunt utilizate pentru compilari conditionate. De exemplu, n cazul n care sistemul va fi implementat ca ASIC, dar se va face nainte
un prototip de validare implementat pe FPGA, anumite module specifice tehnologiei
(memorii, circuite PLL, circuite aritmetice specifice) vor trebui nlocuite. Este nsa
de dorit a se mentine un singur set de fisiere sursa. Folosind directive de compilare
se poate face un numar minim de schimbari pentru a configura un singur cod sursa
specific pentru fiecare tehnologie. Portiunea de cod de mai jos va fi inclusa ntr-un
fisier separat, (inclus n codul sursa cu directiva include) si semnalat ca fiind modul
de alegere a tehnologiei pe care se va face implementarea:
define FPGA_tech
//define ASIC_tech
66
Evitarea unor re-definiri succesive n cazul includerii unui fisier n mai multe surse se
poate face prin folosirea directivei ifndef sau a directivelor ifdef si else.
ifndef WIDTH
ifdef WIDE_MODE
define WIDTH 16
else
define WIDTH
8
endif
endif
2.8.3
include
Directiva include este utilizata pentru includerea in-line a textului dintr-un fisier
n codul sursa, n locul aparitiei directivei. Textul ce apare n fisierul inclus poate
contine orice specificatii Verilog, nu neaparat un modul ntreg. Aceasta directiva se
poate apela atat din afara, cat si n interiorul descrierii unui modul.
Este recomandata mentinerea ntr-un fisier separat a directivelor de definire. De
multe ori se doreste doar compilarea unui fisier, iar includerea fisierului de definitii
n fiecare fisier sursa ar determina o eroare de redefinire. Redefinirile multiple pot fi
evitate daca n fisierul inclus, nainte de sectiunea de definiri, se verifica daca definirile
nu au fost deja facute (ca efect al includerii ntr-un fisier sursa compilat anterior).
Continutul unui fisier (incl.h) este prezentat n continuare:
ifndef DEFINED_ONCE
define DEFINED_ONCE
//
//
//
//
//
//
//
// sectiune
define GAIN_ADDRESS
define OFFSET_ADDRESS
...
endif
6
7
// definiri
In unul sau mai multe fisiere sursa poate fi inclus fisierul incl.h astfel:
include "incl.h"
2.8.4
timescale
Sn
67
2.9
// intarziere 3.1 ns
// intarziere 3.1 ns
// intarziere 3 ns
Stil si calitate
68
69
Exemple: width_p,
Semnalele interne, fiind cu vizibilitate locala si fiind atat citite, cat si atribuite n
interiorul modulelor, nu vor avea nici un sufix. Se recomanda evitarea terminarii
numelor identificatorilor cu caracterul de subliniere (_) deoarce multe programe
EDA l folosesc pentru a delimina portiuni de caractere la formarea automata
a numelor. Acest lucru poate produce nu doar confuzie, dar si erori foarte greu
de gasit n netlistul obtinut prin sinteza.
Un caz particular l constituie identificatorii definiti n directive de compilare
define. Directiva define implementeaza un mecanism de substituire de text
si este similara cu directiva #define din limbajul C. Directiva define poate
sa apara si n afara specificatiilor de module si are vizibilitate asupra tuturor
fisierelor sursa ce se compileaza n continuare. Pentru a identifica mai usor
denumirile macro-urilor asociate prin aceasta directiva se recomanda folosirea
majusculelor pentru numele acestora.
// coduri de comenzi
define CMD_IDLE
3h0
define CMD_WRITE
3h1
define CMD_READ
3h2
define CMD_BCAST
3h7
//Adresa de start a setului de registre
define REGS_START_ADDRESS
16h2000
//Adresele relative ale registrelor
define ADDR_CH_CNTRL
8h00
define ADDR_CH1_CNTRL
8h02
define ADDR_CH2_CNTRL
8h03
Folosirea delimitatorilor begin si end. Desi folosirea acestor demitatori
nu este necesara daca se include o singura specificatie, este o buna practica a
se folosi acestia n toate cazurile. Ca rezultat, se obtine un cod cu un aspect
uniform, usor de urmarit si de corectat sintactic. Pentru a alinia cuvintele cheie
ce apartin aceleiasi specificatii (if, else) si a specificatiilor secventiale dintr-un
bloc se recomanda folosirea a doua caractere spatiu sau a caracterului tabulator.
Recomandarea este exemplificata prin urmatoarea portiune de cod.
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
outRange <= 1b0;
startOp <= 1b0;
end
else begin
if (devSel && (cpuAddr_i == ADDR_STATUS)) begin
outRange <= cpuD_i[0];
startOp <= cpuD_i[1];
end
70
else begin
if (setOutRange) begin
outRange <= 1b1;
end
if (resetStartOp) begin
startOp <= 1b0;
end
end
end
end
end
Far
a respectarea acestei recomandari, aceeasi portiune poate fi scrisa, (perfect
legal) dupa cum urmeaza:
always @(posedge cpuClk_i)
if (!cpuReset_ni) begin
outRange <= 1b0;
startOp <= 1b0;
end
else
if (devSel && (cpuAddr_i == ADDR_STATUS)) begin
outRange <= cpuD_i[0];
startOp <= cpuD_i[1];
end
else begin
if (setOutRange)
outRange <= 1b1;
if (resetStartOp)
startOp <= 1b0;
end
Desi cele doua portiuni de cod sunt echivalente, n exemplul recomandat se
remarca usurinta cu care se verifica nchiderea tuturor delimitatorilor begin cu
delimitatori end corespunzatori ca numar.
Ca test, se propune gasirea erorii existente n codul urmator. Care delimitator
begin nu are corepondent end?
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
outRange <= 1b0;
startOp <= 1b0;
end
else begin
if (devSel && (cpuAddr_i == ADDR_STATUS)) begin
outRange <= cpuD_i[0];
startOp <= cpuD_i[1];
71
end
else begin
if (setOutRange) begin
outRange <= 1b1;
end
if (resetStartOp)
startOp <= 1b0;
end
end
Un alt argument n favoarea respectarii acestei recomandari este eliminarea
ambiguitatii ramurilor else n cazul unor specificatii if imbricate.
always @(posedge clk_i)
if (!reset_ni)
rdAddr <= 1b0;
else
if (en)
if (ld)
rdAddr <= 1b0;
else
if (inc)
rdAddr <= rdAddr + 1;
// primul if
// al doilea if
// carui if apartine acest else?
72
73
74
U2_add1C(
(a[2]
),
(b[2]
),
(coU2
),
(sU3[2] ),
(coU3
)
75
a;
b;
s1;
s2;
s3;
co1, c02, c03;
// sumator pe 8 biti
addxC #(8) Sum1(
.a (a
),
.b (b
),
.ci (1b0
),
.s (s1
),
.co (co1
)
);
Transmiterea parametrilor cu directive defparam:
defparam Sum2.width = 8;
defparam Sum3.width = 4;
// sumator pe
addxC Sum2(
.a (a
.b (b
.ci (1b0
.s (s2
.co (co2
);
// sumator pe
addxC Sum3(
.a (a[3:0]
.b (b[3:0]
.ci (1b0
.s (s3
.co (co3
);
8 biti
),
),
),
),
)
4 biti
),
),
),
),
)
Declararea s
armelor la nceputul modulului. Declararea variabilelor care
modeleaza sarme (wire si reg) se poate face oriunde n cod. Singura conditie
este ca declaratia sa preceada prima referire la sarma respectiva. Totusi, este
recomandata plasarea grupata, imediat dupa declararea porturilor, a tuturor
declaratiilor de sarme. Nerespectarea aceastei reguli ar putea determina ca, la
76
mutarea unor specificatii, declaratia unor sarme sa ramana mai jos producand
inutile erori de sintaxa.
Verilog permite declararea implicita a unui tip de sarma, de obicei sarma de tip
wire de un bit. Se recomanda totusi declararea explicita a tuturor sarmelor si
totodata adaugarea unui mic comentariu despre semnificatia acestora.
Scrierea a maxim 80 de caractere pe o linie de cod. Desi n marea majoritate a timpului codul sursa este vizualizat pe monitor, uneori este utila imprimarea acestuia pe hartie. Pentru a evita consumarea timpului cu formatarea
codului astfel ncat sa se tipareasca n ntregime, este de preferat scrierea codului cu nu mai mult de 80 de caractere pe linie. In Verilog, o specificatie poate fi
scrisa pe mai multe linii, fara a fi necesara o delimitare explicita.
Nefolosirea constantelor numerice n cod. Se recomanda evitarea folosirii
constantelor numerice n codul sursa. O constanta folosita direct n cod este
foarte putin vizibila la depanarea codului. In schimb, daca marimile constante se asociaza unui identificator cu o denumire sugestiv aleasa, acestea pot
fi usor localizate n cod. Actualizarea valorii constante ntr-un singur loc se
va propaga automat n cod, n cazul apelarii acestei valori de catre mai multe
specificatii. Declararea constantelor se face prin directiva de compilare define.
Se recomanda folosirea majusculelor pentru identificatorii ce definesc constante.
// Numar de biti de adresa si de date
define ADDR_BIT_NO
8
define DATA_BIT_NO
8
// Adresele relative ale registrelor
define ADDR_CH_CNTRL
8h00
define ADDR_CH1_CNTRL
8h02
define ADDR_CH2_CNTRL
8h03
...
output[DATA_BIT_NO-1:0] cpuData_o;
reg[DATA_BIT_NO-1:0]
cpuData_o;
...
reg[DATA_BIT_NO-1:0]
devCtrl;
reg[DATA_BIT_NO-1:0]
devCh1Ctrl;
reg[DATA_BIT_NO-1:0]
devCh2Ctrl;
...
// scrierea registrului de control de catre CPU
assign wrCtrl = devSel_i &
(cpuAddr_i[ADDR_BIT_NO-1:0] == ADDR_CH_CNTRL);
always @(posedge cpuClk_i)
if (!cpuReset_ni) devCtrl <= b0; else
if (wrCtrl)
devCtrl <= cpuData_i;
// citirea registrelor de catre CPU
always @(posedge cpuClk_i)
if (!cpuReset_ni) cpuData_o <= b0; else
case (cpuAddr_i[ADDR_BIT_NO-1:0])
77
Capitolul 3
MODELAREA
CIRCUITELOR
ELEMENTARE
Acest capitol prezinta modalitatea uzuala de modelare a blocurilor digitale n vederea
sintetizabilitatii. Alte modalitati de modelare, a bibliotecilor de componente primitive
sau a mediilor de testare, sunt considerate notiuni avansate si sunt tratate separat
n capitolul 4. Altfel spus, se prezinta n acest capitol modelarea RTL a diverselor
structuri ntalnite n circuitele integrate digitale.
3.1
Circuite combinationale
3.1.1
A, B, C, D;
F;
// iesirea se declara ca wire
F = ~(A&B | C&D); // se folosesc regulile de precedenta ale
// operatorilor
Modelarea cu assign are avantajul unei descrieri concise, foarte apropiata de realizarea fizica si foarte intuitiva. Semnalele care apar n stanga sunt iesirile, iar
semnalele care apar n dreapta simbolului de atribuire (=) sunt intrarile circuitului
combinational.
79
80
Un lucru important la modelarea pentru sintetizabilitate este constientizarea numarului de intrari ale unui circuit combinational.
wire[7:0]
wire[7:0]
wire
assign G =
assign H =
assign I =
assign J =
assign K =
3.1.2
aBus;
bBus;
G, H, I, J, K;
(aBus == 8h78);
// semnale de 8 biti
//
//
(aBus == bBus);
//
//
//
(|aBus);
//
//
(~|(aBus~^bBus)); //
(aBus[0] & &bBus); //
//
//
//
//
//
//
//
// lipseste intrarea D
81
WARNING:
The signals <D> are missing in the sensitivity list of always block.
Unul din motivele cele mai frecvente pentru modelarea circuitelor combinationale cu specificatie always este cazul modelarii multiplexoarelor cu multe intrari de
selectie, cu specificatie secventiala case. Trebuie acordata atentie existentei specificatiei default. Altfel, circuitul rezultat din sinteza va contine un latch. Se remarca
faptul ca lista intrarilor contine atat intrarile de date, cat si intrarea de selectie.
wire[1:0]
sel;
wire
i0, i1, i2, i3;
reg
mux;
always @(sel or i0 or i1 or i2 or i3)
case (sel)
2b00:
mux <= i0;
2b01:
mux <= i1;
2b10:
mux <= i2;
default: mux <= i3;
endcase
Figura 3.1 prezinta structurile hardware sintetizate din codul prezentat n aceasta
sectiune.
3.2
Circuite de multiplexare
3.3
Codificator/decodificator
82
Figura 3.1 Structuri obtinute prin sinteza modelelor de circuite combinationale prezentate
n sectiunea 3.1.
83
3.3. Codificator/decodificator
Y
Y
Y
Y
Y
Y
Y
Y
Y
<=
<=
<=
<=
<=
<=
<=
<=
<=
3b111;
3b110;
3b101;
3b100;
3b011;
3b010;
3b001;
3b000;
3bx;
//
//
//
//
//
//
//
//
//
//
7
6
5
4
3
2
1
0
nici o intrare activa
sau mai mult de o intrare activa
endcase
In cazul acceptarii la intrare a mai multor biti egali cu 1, circuitul codificator
trebuie sa impuna o prioritate. Modelarea prioritatilor se poate face cu specificatia
casex. Spre deosebire de specificatia case, specificatia casex accepta descrierea
intrarilor indiferente (dont care, n limba engleza). De remarcat ca, n cazul n care
expresia de selectie corespunde mai multor optiuni casex, este executata specificatia
ce corespunde primei coincidente dintre variabila de selectie si expresiile listate.
always @(A)
casex(A)
8b1xxx_xxxx:
8b01xx_xxxx:
8b001x_xxxx:
8b0001_xxxx:
8b0000_1xxx:
8b0000_01xx:
8b0000_001x:
8b0000_0001:
default:
endcase
Y
Y
Y
Y
Y
Y
Y
Y
Y
<=
<=
<=
<=
<=
<=
<=
<=
<=
3b111;
3b110;
3b101;
3b100;
3b011;
3b010;
3b001;
3b000;
3bx;
//
//
//
//
//
//
//
//
//
7
6
5
4
3
2
1
0
nici o intrare activa
n
T
n
V
module encoder(
A_i,
E_i,
Y_o,
E_o
);
//
//
//
//
intrarea codificatorului
validare intrare
iesirea codificatorului
validare iesire
84
input[7:0]
input
output[2:0]
output
A_i;
E_i;
Y_o;
E_o;
reg[2:0]
reg
Y_o;
E_o;
always @(A_i or
if (E_i) begin
casex(A_i)
8b1xxx_xxxx:
8b01xx_xxxx:
8b001x_xxxx:
8b0001_xxxx:
8b0000_1xxx:
8b0000_01xx:
8b0000_001x:
8b0000_0001:
default:
endcase
end
else begin
{E_o, Y_o} <=
end
// intrare de date
// intrare de validare
E_i)
{E_o,
{E_o,
{E_o,
{E_o,
{E_o,
{E_o,
{E_o,
{E_o,
{E_o,
// intrari codificator
Y_o}
Y_o}
Y_o}
Y_o}
Y_o}
Y_o}
Y_o}
Y_o}
Y_o}
<=
<=
<=
<=
<=
<=
<=
<=
<=
4b1_111;
4b1_110;
4b1_101;
4b1_100;
4b1_011;
4b1_010;
4b1_001;
4b1_000;
4b0_000;
//
//
//
//
//
//
//
//
//
7
6
5
4
3
2
1
0
nici o intrare activa
endmodule
Circuitul decodificator se poate descrie folosind operatorul de deplasare stanga,
pornind de la interpretarea functiei decodificatorului: deplaseaz
a spre st
anga un bit 1
pe iesire cu num
arul de pozitii precizat la intrare.
wire[2:0]
A;
wire[7:0]
Y;
assign Y = (1b1 << A);
Se observa ca daca A=3b000, atunci Y=8b0000_0001.
Daca A=3b001, atunci Y=(8b0000_0001 << 1)=8b0000_0010.
Daca A=3b111, atunci Y=(8b0000_0001 << 7)=8b1000_0000.
Urmatorul model prezint
a un circuit decodificator cu intrare de validare.
module decoder(
A_i,
E_i,
Y_o
);
input[2:0]
A_i;
// intrarea decodificatorului
// validare intrare
// iesirea decodificatorului
85
3.4. Latch D
input
output[7:0]
E_i;
Y_o;
reg[7:0]
Y_o;
3.4
Latch D
O linie lipsa n codul anterior, determina aparitia dupa sinteza a unui latch nedorit,
prezentat n figura 3.3.
86
3.5
Bistabil D/RS
87
// bistabil D cu
always @(posedge
if (reset) q <=
q <=
Se observa ca modificarea valorii bistabilului q este posibila la activarea semnalului de reset, indiferent de semnalul de ceas. Daca semnalul de reset este inactiv
(reset=0), modelul se reduce la cel al unui bistabil D elementar. Bistabilele cu set si
reset asincrone se recomanda a fi evitate n proiectare. La modelarea acestora trebuie
observata necesitatea prioritatii tratarii intrarilor asincrone.
Bistabilele cu intrari de set si/sau reset sincrone sunt cazuri particulare de circuite
secventiale si se modeleaza corespunzator.
// bistabil D cu reset sincron activ high
always @(posedge clk)
// reset sincron => nu apare in lista
// clk resetSync | q+
// de senzitivitati (descrierea
// --------------------// evenimentului de declansare a
// ^
1
| 0
// specificatiei always)
// ^
0
| d
if (resetSync) q <= 1b0; else
q <= d;
// bistabil D cu reset sincron activ low
// clk resetSync | q+
// --------------------// ^
0
| 0
// ^
1
| d
always @(posedge clk)
if (~resetSync_n) q <= 1b0; else
q <= d;
// bistabil D cu set si reset sincron active low
// clk setSync_n resetSync_n | q+
// -------------------------------// ^
0
x
| 1
// ^
1
0
| 0
// ^
1
1
| d
always @(posedge clk)
if (~setSync_n)
q <= 1b1; else
// set prioritar
if (~resetSync_n) q <= 1b0; else
q <= d;
//
//
//
//
//
//
88
//
1
^
1
0
| 0
//
1
^
1
1
| d
always @(posedge clk or negedge resetAsync_n)
if (~resetAsync_n) q <= 1b0; else // reset asincron
// (exista in lista de
// descriere a evenimentului)
if (~setSync_n)
q <= 1b1; else // set prioritar
if (~resetSync_n) q <= 1b0; else
q <= d;
// bistabil D cu set si reset sincron active low si
// reset asincron activ low
// resetAsync_n
clk setSync_n resetSync_n | q+
// ---------------------------------------------//
0
x
x
x
| 0
//
1
^
0
x
| 1
//
1
^
1
0
| 0
//
1
^
1
1
| q (pastreaza starea)
always @(posedge clk or negedge resetAsync_n)
if (~resetAsync_n) q <= 1b0; else // reset asincron
if (~setSync_n)
q <= 1b1; else // set prioritar
if (~resetSync_n) q <= 1b0;
// nu exista else,
// pastreaza starea
3.6
Bistabil T/JK
3.7. Num
ar
atoare sincrone
89
// 1
^ 1 | ~q
// 1
^ 0 | q
// implicit
always @(posedge clk or negedge reset_n)
if (~reset_n) q <= 1b0; else
if (t)
q <= ~q;
// bistabil T cu reset sincron activ low
// clk reset_n t | q+
// -------------------// ^
0
x | 0
// ^
1
1 | ~q
// ^
1
0 | q
// implicit
always @(posedge clk)
if (~reset_n) q <= 1b0; else
if (t)
q <= ~q;
Bistabilul JK are un model dedus din tabelul de functionare a acestuia, lasand
implicit cazul cand iesirea se pastreaza.
// bistabil JK cu reset asincron activ low
// reset_n clk j k | q+
// ----------------------// 0
x x x | 0
// 1
^ 0 0 | q
// implicit
// 1
^ 0 1 | 0
// 1
^ 1 0 | 1
// 1
^ 1 1 | ~q
always @(posedge clk or negedge reset_n)
if (~reset_n)
q <= 1b0;
else
case({j,k})
2b01 : q <= 1b0;
2b10 : q <= 1b1;
2b11 : q <= ~q;
default: ;
// nu atribuie nimic, pastreaza valoarea
endcase
3.7
Num
ar
atoare sincrone
Numaratoarele sunt circuite foarte des folosite n circuitele integrate digitale. Modelul
unui numar
ator poate fi descris similar cu cel al unui registru cu particularizarea ca
intrarea provine dintr-un circuit combinational de incrementare a iesirii.
reg[7:0]
count;
always @(posedge clk or negedge reset_n)
if (~reset_n)
count <= 8b0;
// initializarea asincrona a numaratorului
90
else
count <= count + 1; // starea viitoare este (starea curenta + 1)
Un numarator cu facilitati de numarare n sens crescator si n sens descrescator
este prezentat n continuare. In plus, a fost prevazuta o intrare suplimentara de
validare a numararii.
// numarator in sens crescator/descrescator si validare a numararii
// reset_n clk en up | count+
// ---------------------------// 0
x
x
x |
0
// 1
^
0
x | count
(pastreaza starea)
// 1
^
1
1 | count+1 (numara in sens crescator)
// 1
^
1
0 | count-1 (numara in sens descrescator)
reg[7:0]
count;
always @(posedge clk or negedge reset_n)
if (~reset_n) begin
count <= 8b0;
// initializarea asincrona a numaratorului
end
else begin
if (en) begin
if (up) begin
count <= count + 1; // starea viitoare este
// (starea curenta + 1)
end
else begin
count <= count - 1; // starea viitoare este
// (starea curenta - 1)
end
end
// daca en=0, pastreaza starea
end
De remarcat faptul ca numararea se face n binar pe numarul de biti pe care
a fost declarat semnalul count. Dupa 8b1111_1111 urmeaza n sens crescator
8b0000_0000.
Ca exemplu, este prezentat n continuare modelul unui numarator n binar n sens
crescator sau descrescator, cu modificare dinamica a valorii de terminare a numararii.
Caracteristicile numaratorului sunt:
Latime parametrizabila;
Indicator de terminare a numararii pentru comparare cu valoarea impusa;
Valoare de terminare a numararii implementata ca intrare n numarator;
Control al sensului de numarare;
Reset asincron;
Semnal de ncarcare sincrona.
3.7. Num
ar
atoare sincrone
91
n
T
n
V
module counter(
data,
count_to,
92
Port
data
count_to
up_dn
Dimensiune
width
width
1
Directie
intrare
intrare
intrare
load
cen
clk
reset
count
tercnt
1
1
1
1
width
1
intrare
intrare
intrare
intrare
iesire
iesire
Functie
data de ncarcare
limita numararii
1 = numarare n sens crescator,
0 = numarare n sens descrescator
semnal de ncarcare, activ n 0
validare numarare, activ n 1
semnal de ceas
reset asincron, activ n 1
iesirea numaratorului
indicator de terminare a numararii,
activ n 1
Tabelul 3.1
reset
0
1
1
1
1
load
x
0
1
1
1
cen
x
x
0
1
1
up_dn
x
x
x
0
1
Functie
initializeaza
ncarca
pastreaza starea
numara n sens descrescator
numara n sens crescator
Tabelul 3.2
Descrierea function
arii num
ar
atorului.
up_dn,
load,
cen,
clk,
reset,
count,
tercnt
);
parameter width = 8;
input[width-1 : 0]
input[width-1 : 0]
input
input
input
input
input
output[width-1 : 0]
93
3.7. Num
ar
atoare sincrone
output
tercnt;
reg[width-1 : 0]
count;
94
3.8
3.8.1
Figura 3.8 prezinta graful de tranzitii al unui semi-automat. Codul Verilog, prezinta
codificarea starilor modelata cu parametru. Acest lucru permite ulterior o modificare
rapida a codurilor starilor, fara a fi necesara revizuirea ntregului cod sursa. In cazul
unor decizii mai complexe, se pot utiliza specificatii if, operatori conditionali ?: sau
chiar specificatii case cu selectia pe baza de intrari. Structura rezultata din sinteza
este prezentata n figura 3.9.
n
V
module semiAutomat(
clk_i,
reset_ni,
a_i,
stare_o
);
input
input
input
output[1:0]
//
//
//
//
intrare de ceas
intrare de reset
intrare a semi-automatului
starea semi-automatului
clk_i;
reset_ni;
a_i;
stare_o;
95
96
3.8.2
mealyImediat1_o;
mealyImediat2_o;
mooreImediat_o;
mealyIntarziere_o;
mooreIntarziere_o;
s0_p:
if (a_i) begin
mealyImediat2_o <= 1b1;
end
else begin
mealyImediat2_o <= 1b0;
end
s1_p:
mealyImediat2_o <= 1b0;
s2_p:
mealyImediat2_o <= 1b0;
s3_p:
mealyImediat2_o <= ~a_i;
default: mealyImediat2_o <= 1b0;
endcase
always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) begin
mealyIntarziere_o <= 1b0;
end
97
98
else begin
mealyIntarziere_o <= ((stare_o == s1_p) & a_i) |
((stare_o == s3_p) & ~a_i);
end
assign mooreImediat_o = (stare_o == s1_p) |
(stare_o == s2_p) |
(stare_o == s3_p);
always @(posedge clk_i or negedge
if (~reset_ni) begin
mooreIntarziere_o <= 1b0;
end
else begin
mooreIntarziere_o <= (stare_o
(stare_o
(stare_o
end
3.8.3
reset_ni)
== s1_p) |
== s2_p) |
== s3_p);
n
n
T
V
module semafor (
clk_i,
reset_ni,
senzor_i,
rosu_o,
galben_o,
verde_o
);
input
input
input
output
output
output
clk_i;
reset_ni;
senzor_i;
rosu_o;
galben_o;
verde_o;
// codificarea starilor
parameter wait_p = 2b00;
stareCurenta;
stareViitoare;
rosu_o;
galben_o;
verde_o;
// registru de stare
always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) stareCurenta <= wait_p; else
stareCurenta <= stareViitoare;
// circuit combinational pentru stare viitoare si iesiri
always @(stareCurenta or senzor_i) begin
case (stareCurenta)
wait_p: begin
rosu_o
<= 1b1;
galben_o <= 1b0;
verde_o <= 1b0;
if (senzor_i) begin
stareViitoare <= start_p;
end
else begin
stareViitoare <= wait_p;
end
end
start_p: begin
rosu_o
<= 1b1;
galben_o <= 1b1;
verde_o <= 1b0;
stareViitoare <= run_p;
end
run_p: begin
rosu_o
<= 1b0;
galben_o <= 1b0;
verde_o <= 1b1;
if (senzor_i) begin
stareViitoare <= run_p;
end
else begin
stareViitoare <= wait_p;
end
end
default: begin
rosu_o
<= 1b1;
99
100
3.8.4
Automat cu st
ari codificate one-hot
O alternativa foarte utilizata este codificarea starilor cu un bit pentru fiecare stare.
Ca o consecinta, modelarea se poate face la nivel de bistabil. In acest caz, structura
de automat nu mai este asa de evidenta. Modelarea one-hot a semaforului este
prezentat
a n continuare. Se observa definirea unui bistabil (cu nume propriu) pentru
fiecare stare. Starea initiala este stabilita prin proiectarea valorilor primite de bistabilele de stare la reset. Binenteles, totdeauna va exista un singur bistabil cu valoare
1. Structura rezultata din sinteza este prezentata n figura 3.10.
n
V
module semaforOneHot (
clk_i,
reset_ni,
senzor_i,
rosu_o,
galben_o,
verde_o
);
input
input
input
output
output
output
clk_i;
reset_ni;
senzor_i;
rosu_o;
galben_o;
verde_o;
101
Capitolul 4
NOT
IUNI AVANSATE DE
VERILOG
4.1
Task-uri si functii
Task-urile si functiile permit executia unor proceduri n mai multe locuri ale descrierii
hardware. De asemenea, ele permit partajarea unor descrieri de dimensiuni mari n
proceduri mai mici, mai usor de citit si de depanat n codul sursa. Atat task-urile,
cat si functiile pot lucra cu argumente de tip intrare, iesire sau bidirectionale.
Diferentele ntre task-uri si functii sunt urmatoarele:
O functie se executa la un singur moment al simularii. Un task poate contine
specificatii de control temporal.
O functie trebuie sa aiba cel putin un parametru de intrare. Un task poate avea
zero sau mai multe argumente de orice tip.
O functie ntoarce o valoare. Un task nu ntoarce o valoare.
O functie este utilizata ca un operand ntr-o expresie. Un task ntoarce o valoare
ntr-un argument de iesire.
Task-urile si functiile pot fi folosite atat pentru modelarea modulelor sintetizabile,
cat si pentru modelarea modulelor folosite n mediul de testare.
n
T
De exemplu, se pot defini o functie si un task pentru calculul valorii negate
a unei marimi ntregi. Un task ntoarce rezultatul ntr-un argument de iesire. Apelul
unui task va fi:
negare(valoareInitiala, valoareNegata);
Task-ul va primi parametrul de intrare valoareInitiala va determina valoarea
negata si o va atribui parametrului de iesire valoareNegata. O functie care va face
acelasi lucru va ntoarce direct valoarea negata. Apelul functiei va fi:
103
104
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
valoareNegata = negare(valoareInitiala);
Sn
Sintaxa definirii unui task este urmatoarea:
<task> ::= task <nume_task>;
<declaratii_task>
<specificatii>
endtask
<declaratii_task> ::= <declaratii_parametrii>
||= <declaratii_intrari>
||= <declaratii_iesiri>
||= <declaratii_bidirectionale>
||= <declaratii_reg>
||= <declaratii_timp>
||= <declaratii_intregi>
||= <declaratii_reali>
||= <declaratii_evenimente>
Ca exemplu, sunt prezentate task-urile ce modeleaza citirea si scrierea unui set de
registre printr-o interfata de catre un procesor. Aceste task-uri nu sunt sintetizabile. Ele modeleaza comportamentul unui procesor care furnizeaza stimuli circuitului
proiectat pentru sintetizabilitate.
task write;
// parametrii formali ai task-ului
input[15:0] addr;
input[15:0] data;
begin
// pregatire valori pentru semnalele de control
mpuCs_no
<= 1b0;
mpuTs_no
<= 1b0;
mpuRdWr_no <= 1b0;
mpuAddr_o
<= addr;
mpuData_o
<= data;
@(posedge mpuClk_i);
mpuTs_no
<= 1b1;
// interogare indicator de validare a scrierii
while (mpuRdy_ni)
@(posedge mpuClk_i);
// scrierea a fost efectuata, inactivare comanda
mpuCs_no
<= 1b1;
mpuRdWr_no <= 1b1;
// mesaj pentru depanare
$display("%M %t NOTA: Scriere de catre CPU (addr=%hH, data=%hH).",
$time, addr, data);
@(posedge mpuClk_i);
end
105
endtask
task read;
input[15:0] addr;
begin
// pregatire valori pentru semnalele de control
mpuCs_no
<= 1b0;
mpuTs_no
<= 1b0;
mpuRdWr_no
<= 1b1;
mpuAddr_o
<= addr;
mpuData_o
<= 16b0;
@(posedge mpuClk_i);
mpuTs_no
<= 1b1;
// interogare indicator de validare a citirii
while (mpuRdy_ni)
@(posedge mpuClk_i);
// citirea a fost efectuata, inactivare comanda
mpuCs_no
<= 1b1;
mpuTs_no
<= 1b1;
@(posedge mpuClk_i);
// mesaj pentru depanare (data citita)
$display("%M %t NOTA: Citire de catre CPU (addr=%hH, data=%hH).",
$time, addr, mpuData_i);
$stop;
end
endtask
Apelarea task-urilor se face din interiorul unei specificatii initial:
initial
begin
// write(adresa, data);
write(16h0, 16h0039);
// read (adresa);
read (16h0);
write(sdram_mode_addr, 16h0060);
n
T
Formele de unda rezultate n urma simularii modulului MPU descris cu
task-uri sunt prezentate n figura 4.1.
Sn
Sintaxa definirii unei functii este urmatoarea:
106
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
107
else
// MSB=1 => numar negativ
modulo = ~formalInitial + 1;
end
endfunction
// complement fata de 2
n
V
Structura rezultata n urma sintezei unui modul al carui comportament
este descris cu functia modulo este prezentata n figura 4.2.
4.2
Modelarea memoriilor
108
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
S-au prevazut doua optiuni de initializare: toata memoria nscrisa cu 0 sau memoria nscris
a cu datele existente ntr-un fisier extern. In acest ultim caz, datele sunt
citite din fisier n variabila de memorie cu functia sistem $readmemh, prezentata n
sectiunea 4.6.
n
V
module dpMem (
clk_i,
// semnal de ceas
// port de scriere
wrAddr_i,
// adresa de scriere
we_ni,
// validare scriere (write enable), activ low
data_i,
// date de intrare
// port de citire
rdAddr_i,
// adresa de citire
re_ni,
// validare citire (read enable), activ low
data_o
// date de iesire
);
parameter
parameter
parameter
width_p
= 32;
addrBits_p= 10;
memInit_p = 1b1;
parameter
memZero_p = 1b1;
//
//
//
//
//
//
latime date
numar de biti de adresa
1=memorie initializata,
0=memorie neinitializata
1=memorie initializata cu 0,
0=memorie initializata cu
clk_i;
wrAddr_i;
we_ni;
data_i;
rdAddr_i;
re_ni;
data_o;
data_o;
109
n
T
Modele comportamentale pentru memorii SDRAM/DDR pot fi gasite pe
situl firmei Micron Technology (http://www.micron.com) sau pe pagina web a cartii.
Aceste modele nu sunt sintetizabile.
4.3
110
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
Pentru memorii se utilizeaza modelele firmei Micron. Modelul modulului de memorie este prezentat n continuare:
n
V
111
.We_n
.Dqm
(sdrWe_i
(sdrDm_i[2*i+1:2*i]
),
)
);
end
// o instanta SDRAM 256Mb (32M x 8)
// pentru memoria de sume de control
defparam UsdramEcc.Debug = 0;
mt48lc32m8a2 UsdramEcc(
.Dq
(sdrEcc_io
),
.Addr (sdrAddr_i
),
.Ba
(sdrBank_i
),
.Clk
(sdrCk_i
),
.Cke
(sdrCke_i
),
.Cs_n (sdrCs_i
),
.Ras_n (sdrRas_i
),
.Cas_n (sdrCas_i
),
.We_n (sdrWe_i
),
.Dqm
(sdrDm_i[8] )
);
endgenerate
endmodule
Reprezentarea grafica a ierarhiei modulului sdramModule este prezentata n figura
4.3.
Specificatia generate poate genera si structuri sintetizabile, asa cum este cazul
exemplului unui sumator de 32 de biti format din 4 sumatoare de cate 8 biti. Structura
rezultata din sinteza este prezentata n figura 4.4.
n
V
module addGen (
112
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
a_i,
b_i,
ci_i,
s_o,
co_o
//
//
//
//
//
primul operand
al doilea operand
transport de intrare
rezultatul
transport de iesire
);
input[31:0]
input[31:0]
input
output[31:0]
output
a_i;
b_i;
ci_i;
s_o;
co_o;
113
endmodule
4.4
4.4.1
Porti cu intr
ari multiple
Portile cu intrari multiple modeleaza porti logice avand o singura iesire si un numar
neprecizat de intrari. Functia logica implementata corespunde cuvintelor rezervate:
and, nand, or, nor, xor, xnor.
Sn
Sintaxa instantierii portilor cu intrari multiple este urmatoarea:
<tip_poarta> [nume_instanta] (iesire, intrare1, intrare2, ...);
Primul terminal este iesirea, restul terminalelor, oricate la numar, sunt asociate
intrarilor.
Tabelele de adevar asociate acestor porti sunt prezentate n tabelul 4.1:
4.4.2
Portile cu iesiri multiple modeleaza porti logice avand o singura intrare si un numar
neprecizat de iesiri. Functia logica implementata corespunde cuvintelor rezervate:
buf si not. Aceste porti sunt folosite pentru stabilirea explicita a fan-out-ului unei
porti logice fizice.
Sn
Sintaxa instantierii portilor cu iesiri multiple este urmatoarea:
buf [nume_instanta] (intrare, iesire1, iesire2, ...);
not [nume_instanta] (intrare, iesire1, iesire2, ...);
Primul terminal este intrarea, restul terminalelor, oricate la numar, sunt asociate
iesirilor.
Tabelele de adevar asociate acestor porti sunt prezentate n tabelul 4.2.
114
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
and
0
1
x
z
0
1
1
1
1
1
1
0
x
x
x
1
x
x
x
z
1
x
x
x
nand
0
1
x
z
or
0
1
x
z
0
0
1
x
x
1
1
1
1
1
x
x
1
x
x
z
x
1
x
x
nor
0
1
x
z
xor
0
1
x
z
0
0
1
x
x
1
1
0
x
x
x
x
x
x
x
z
x
x
x
x
xnor
0
1
x
z
0
0
0
0
0
0
1
0
x
x
1
0
1
x
x
1
0
0
0
0
0
1
0
x
x
x
0
x
x
x
x
x
0
x
x
1
0
1
x
x
z
0
x
x
x
z
x
0
x
x
x
x
x
x
x
z
x
x
x
x
Tabelul 4.1
Tabelul de adev
ar ale portilor logice cu intr
ari multiple.
buf
iesire
0
0
1
1
x
x
z
x
not
iesire
0
1
1
0
x
x
z
x
Tabelul 4.2
Tabelul de adev
ar ale portilor logice cu iesiri multiple.
4.4.3
Portile cu iesiri n trei stari modeleaza porti logice avand o intrare de validare care
determina trecerea iesirii n stare de nalta impedanta. Functia logica implementata
corespunde cuvintelor rezervate: bufif0, bufif1, notif0, notif1.
Sn
Sintaxa instantierii portilor cu iesiri n trei stari este urmatoarea:
<tip_poarta> [nume_instanta] (iesire, intrare, control);
Tabelele de adevar asociate acestor porti sunt prezentate n tabelul 4.3. Valorile alternative 0/z si 1/z semnifica cele doua valori ale iesirii, n functie de taria
semnalelor de date si de control.
4.4.4
Portile cu iesiri fixe modeleaza porti logice fara intrare, avand o singura iesire. Pot
fi interpretate ca generatoare de 0 sau de 1 logic. Conectarea unei asemenea porti
la o sarma determina mentinerea starii logice a acelei sarme, n absenta altei surse
115
bufif0
Data
0
1
x
z
0
0
1
x
x
Control
1
x
z
z 0/z 0/z
z 1/z 1/z
z
x
x
z
x
x
0
1
0
z
z
Control
1
x
z
z 1/z 1/z
z 0/z 0/z
z
x
x
z
x
x
notif0
Data
0
1
x
z
bufif1
Data
0
1
x
z
0
z
z
z
z
Control
1
x
z
0 0/z 0/z
1 1/z 1/z
x
x
x
x
x
x
0
z
z
z
z
Control
1
x
z
1 1/z 1/z
0 0/z 0/z
x
x
x
x
x
x
notif1
Data
0
1
x
z
Tabelul 4.3
Tabelul de adev
ar ale portilor cu iesiri n trei st
ari.
Sn
Sintaxa instantierii portilor cu iesiri fixe este urmatoarea:
pullup [nume_instanta] (iesire);
pulldown [nume_instanta] (iesire);
4.5
Verilog este un limbaj ce contine descrierea urmatoarelor modele ce corespund tranzistoarelor MOS (unidirectionale): nmos, pmos, cmos, rnmos, rpmos, rcmos.
Sn
Sintaxa instantierii tranzistoarelor MOS este urmatoarea:
pmos [nume_instanta] (iesire, intrare, control);
nmos [nume_instanta] (iesire, intrare, control);
cmos [nume_instanta] (iesire, intrare, controlN, controlP);
rpmos [nume_instanta] (iesire, intrare, control);
rnmos [nume_instanta] (iesire, intrare, control);
rcmos [nume_instanta] (iesire, intrare, controlN, controlP);
De remarcat ca desi tranzistoarele MOS reale sunt simetrice, modelele Verilog sunt
unidirectionale, avand pentru date intrare si iesire.
116
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
0
0
1
x
z
Control
1
x
z
z 0/z 0/z
z 1/z 1/z
z
x
x
z
z
z
nmos
rnmos
0
Data 1
x
z
0
z
z
z
z
Control
1
x
z
0 0/z 0/z
1 1/z 1/z
x
x
x
z
z
z
Tabelul 4.4
Tabelul de adev
ar ale tranzistoarelor MOS.
Sn
Sintaxa instantierii portilor de transmisiune MOS este urmatoarea:
tran [nume_instanta] (portA, portB);
rtran [nume_instanta] (portA, portB);
tranif0 [nume_instanta] (portA, portB, control);
tranif1 [nume_instanta] (portA, portB, control);
rtranif0 [nume_instanta] (portA, portB, control);
rtranif1 [nume_instanta] (portA, portB, control);
Modelarea la nivel de tranzistor este utilizata de producatorii de tehnologii electronice sau de inginerii care simuleaza functionarea circuitului integrat pe baza structurii fizice, pentru a valida un netlist nainte de fabricatie.
Ca exemplificare, se prezinta cazul modelarii a doua multiplexoare 2:1 descrise la
nivel de tranzistor MOS. Ca metodologie de lucru, schema s-a desenat cu un editor
grafic capabil sa genereze automat modelul Verilog. Schema este prezentata n figura
4.5.
Fisierele generate automat sunt prezentate n continuare:
n
T
n
V
inv.v
/* Verilog model created from schematic inv.sch -Feb 17, 2005 23:21 */
module inv( IN, OUT );
input IN;
output OUT;
wire VDD = 1b1;
117
N1
N2
N3
P3
P2
P1
(
(
(
(
(
(
OUT,
N_1,
N_2,
OUT,
OUT,
OUT,
N_1,
N_2,
GND,
VDD,
VDD,
VDD,
IN1
IN2
IN3
IN3
IN2
IN1
);
);
);
);
);
);
118
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
endmodule // nand3
xfer.v
/* Verilog model created from schematic xfer.sch -Feb 17, 2005 23:21 */
module xfer( D, GN, GP, S );
output D;
input GN, GP, S;
pmos P ( D, S, GP );
nmos N ( D, S, GN );
endmodule // xfer
muxtranzlev.v
/* Verilog model created from schematic muxtranzlev.sch -Feb 17, 2005 23:21 */
module muxtranzlev( I0A, I0B, I1A, I1B, SEL, SEL_C, YA, YB );
input I0A, I0B, I1A, I1B;
input [2:0] SEL;
output SEL_C, YA, YB;
wire N_116;
wire N_117;
wire N_115;
wire N_94;
wire N_95;
nand3 I108 ( .IN1(SEL[2]),.IN2(SEL[1]),.IN3(SEL[0]),.OUT(N_115));
xfer I118 ( .D(N_95), .GN(SEL_C), .GP(N_115), .S(I1B) );
xfer I119 ( .D(N_94), .GN(SEL_C), .GP(N_115), .S(I1A) );
xfer I73 ( .D(N_94), .GN(N_115), .GP(SEL_C), .S(I0A) );
xfer I74 ( .D(N_95), .GN(N_115), .GP(SEL_C), .S(I0B) );
inv I82 ( .IN(N_116), .OUT(YB) );
inv I79 ( .IN(N_117), .OUT(YA) );
inv I78 ( .IN(N_95), .OUT(N_116) );
inv I77 ( .IN(N_94), .OUT(N_117) );
inv I109 ( .IN(N_115), .OUT(SEL_C) );
endmodule // muxtranzlev
4.6
Verilog contine cateva task-uri si functii predefinite n limbaj. Nu toate acestea sunt
foarte folosite. In aceasta sectiune sunt prezentate doar cele folosite mai des n testarea
119
4.6.1
Task-uri de afisare
Task-urile de sistem pentru afisare sunt utilizate pentru afisarea mesajelor n fereastra
de mesaje a simulatorului.
$display: afiseaza un mesaj formatat n momentul executiei specificatiei.
$strobe: task similar cu $display dar cu executie amanata pana la sfarsitul ciclului curent de simulare. Afiseaza valorile actualizate ale semnalelor cu atribuiri
blocante.
$write: task similar cu $display dar fara a trece la linie noua la sfarsitul
mesajului. Posibil de folosit pentru compunerea secventiala a mesajelor ce vor
aparea pe un singur rand.
$monitor: afiseaza un mesaj formatat la fiecare modificare a valorii unui semnal.
Acest task este apelat o singura data si are efect pe tot parcursul simularii. Taskul poate fi activat si dezactivat explicit prin apelul task-urilor $monitoroff si
$monitoron.
Exemplu:
always @(posedge clock)
// afiseaza un mesaj la fiecare front de ceas
$display(%m %t: a=%b b=%b, $time, a, b);
initial
// afiseaza un mesaj la fiecare modificare a semnalelor a sau b
$monitor(%m %t: a=%b b=%bb, $time, a, b);
Modul de reprezentare a marimilor afisate de catre task-urile de afisare poate fi
controlat prin optiuni:
%b - valoare exprimata n baza 2
%o - valoare exprimata n baza 8
120
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
4.6.2
De foarte multe ori, pentru verificarea proiectelor este necesara preluarea unor date
din fisiere: initializarea memoriilor, controlarea setului de stimuli generati.
$fopen deschide un fisier pentru scriere. Functia ntoarce un pointer la fisier
(32 de biti).
$fmonitor, $fdisplay, $fstrobe si $fwrite scriu mesajele n fisier similar
task-urilor $monitor, $display, $strobe, $write.
$fclose nchide un fisier si elibereaza pointerul la fisier.
$readmemb, $readmemh se folosesc pentru citirea datelor dintr-un fisier ntr-o
variabila de memorie de tip matrice bidimensionala. Datele sunt exprimate n
binar daca citirea se face cu $readmemb sau n hexazecimal daca citirea se face
cu $readmemh.
Exemplul 1:
// parametrii de configurare a generatorului de stimuli
parameter param1_p
= 1;
parameter param2_p
= 2;
parameter param3_p
= 3;
121
parameter
cmdFile_p
= "cmdFile.mem"; //
//
= "log.out";
//
//
fisier
pentru
fisier
pentru
de comenzi, deschis
citire
de mesaje, descris
scriere
parameter
logFile_p
reg[23:0]
cmdMem[99:0];
integer
logPtr;
initial begin
logPtr = $fopen(logFile_p);
// deschide fisier pentru scriere
$readmemb(cmdFile_p, cmdMem); // initializeaza matricea cmdMem cu
// continutul fisierului cu numele
// transmis prin parametrul cmdFile_p
// scrie in fisierul de mesaje valorile parametrilor cu care a fost
// instantiat modulul
$fdisplay(logPtr, "%M NOTE: parametrul 1 = %0d", param1_p);
$fdisplay(logPtr, "%M NOTE: parametrul 2 = %0d", param2_p);
$fdisplay(logPtr, "%M NOTE: parametrul 3 = %0d", param3_p);
end
Exemplul 2:
parameter initOn_p = 1b1;
// 0 = memorie neinitializata,
// 1 = memorie initializata
parameter initFile_p = 1b1;
// 0 = initializare (date=adresa)
// 1 = initializare din fisier
parameter fileName_p = "mem1kx32.mem";
// fisier cu date de initializare
// 1024 de linii a cate 8 cifre hexa
reg[31:0]
integer
// initializarea memoriei
initial begin
if (initOn_p) begin
// memorie initializata
if(initFile_p) begin
// memorie initializata din fisier
$readmemh(fileName_p, mem);
end
else begin
// memorie initializata (data=adresa)
for (i=0;i<1024;i=i+1)
mem[i] = i;
end
end
end
122
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
4.6.3
4.6.4
Task-urile de sistem pentru verificari temporale pot fi apelate n cadrul unui test-bench
(modul generator de vectori de test) sau n cadrul unui bloc specify din interiorul
unui modul.
$setup (eveniment_date, eveniment_ref, limita); Violarea timpului de
setup este raportata daca timpul scurs de la eveniment_date pana la
eveniment_ref este mai scurt decat limita.
Exemplu: $setup (data, posedge clk, 5);
$hold (eveniment_ref, eveniment_date, limita); Violarea timpului de
hold este raportata daca timpul scurs de la eveniment_ref pana la
eveniment_date este mai scurt decat limita.
Exemplu: $hold (posedge clk, data, 2);
$setuphold (eveniment_date, eveniment_ref, limita_s, limita_h);
Efectul acestui task reprezinta o nsumare a efectelor $setup si $hold.
Exemplu: $setuphold (data, posedge clk, 5, 2);
$period (eveniment_ref, limita); Violarea perioadei este raportata daca
timpul scurs ntre doua evenimente succesive este mai scurt decat limita.
Exemplu: $period (posedge clk, 16);
$width (eveniment_ref, limita); Violarea de latime este raportata daca
timpul scurs ntre un eveniment si urmatorul eveniment complementar este mai
scurt decat limita.
Exemplu: $width (posedge clk, 8);
$skew (eveniment_1, eveniment_2, limita); Violarea de skew este raportata daca timpul scurs ntre eveniment_1 si eveniment_2 este mai lung decat
limita.
Exemplu: $skew (posedge clk1, posedge clk2, 3);
123
$recovery (eveniment_ref, eveniment_date, limit); Violarea este raportata daca timpul scurs ntre eveniment_ref si eveniment_date este mai lung
decat limita.
Exemplu: $recovery (posedge set, data, 5);
4.6.5
4.6.6
Functia $random ntoarce un numar aleatoriu ntreg reprezentat pe 32 de biti. Specificarea valorii initiale (seed, n limba engleza) este optionala. Apelarea functiei
$random avand ca parametru aceeasi valoare initiala va ntoarce aceeasi valoare la
fiecare simulare.
Pentru a restrange domeniul numerelor aleatorii se poate folosi operatorul modulo
(%).
Exemple:
integer a;
a = $random % 10;
integer b;
124
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
b = {$random} % 10;
reg[7:0] c;
c = $random;
//
//
//
//
reg[63:0] d;
d = {$random, $random}; // numar aleatoriu pe 64 de biti
parameter seed = 1;
initial
semnal = $random(seed);
4.7
Modelarea unei biblioteci de tehnologie presupune proiectarea unui model comportamental al fiecarei componente primitive. Complexitatea sistemelor actuale, cu
milioane de porti logice, determina necesitatea unei mari puteri de calcul n cazul
simularii la nivel de poarta logica, dupa sinteza, sau n final, dupa plasare si rutare.
Din acest motiv, este binevenita posibilitatea de a proiecta modele mai rapide pentru
componente ce au o functie relativ simpla si apar instantiate de foarte multe ori. Este
cazul primitivelor din bibliotecile de tehnologie.
Primitivele definite de catre utilizator furnizeaza suportul pentru largirea setului
de componente elementare folosite n descrierea structurala a unui proiect. Trebuie
remarcat faptul ca n simulare modelul unei primitive se executa mult mai rapid decat
modelul RTL echivalent. Instantierea primitivelor definite de catre utilizator poate fi
facuta similar cu instantierea oricarui modul.
Exist
a doua tipuri de primitive definite de catre utilizator:
primitive combinationale;
primitive secventiale.
O primitiva definita de catre utilizator are o singura iesire si una sau mai multe
intrari. Iesirea poate primi valorile 0, 1 sau x (valoarea z nu este admisa).
Primitivele definite de catre utilizator sunt independente de module si pot exista exclusiv n afara acestora. Sintaxa definirii unei primitive este prezentata n
continuare. Cuvintele cheie ce includ o declaratie de primitiva sunt primitive si
endprimitive.
Sn
<UDP> ::=primitive<nume>(<nume_terminal_iesire>,
125
<nume_terminal_intrare> <,<nume_terminal_intrare>>*);
<declaratie_UDP>+ <specificatie_UDP_initial>?
<tabela_definitie>
endprimitive
n
V
Tn
CP
(01)
(01)
(x1)
(x1)
(0x)
(0x)
(?0)
:
:
:
:
:
:
:
:
Qt
?
?
1
0
1
0
?
:
:
:
:
:
:
:
:
Qt+1
1; //
0; //
1; //
0;
1;
0;
-; //
126
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
(??) ?
endtable
endprimitive
4.8
127
rtlModule U_rtlModule (
.a (a ),
...
);
tbModule U_tbModule (
.a (a ),
...
);
4.9
Functii PLI
128
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
datele necesare si transmite unui program extern. Acesta poate afisa n timp
real imaginea, similar unui monitor adevarat.
Co-simularea unor module mixte (digital-analogice). In acest caz aplicatiile PLI
functioneaza precum un canal de legatura ntre diferitele tipuri de simulatoare
care ruleaza independent, fiecare simuland portiunile din proiect corespunzatoare.
Depanarea unor proiecte complexe uneori nu este usor de realizat doar cu facilitatile oferite de simulatoare. De aceea, uneori, este mult mai eficient sa se
apeleze la aplicatii PLI care sa extraga anumite informatii specifice procesului
de depanare.
4.9.1
O aplicatie PLI este un program scris de catre utilizator folosind limbajul C/C++,
care este executat de catre simulatorul Verilog. Aplicatia PLI interactioneaza cu simulatorul prin citirea si modificarea valorilor semnalelor din cadrul proiectului simulat.
Etapele crearii unei aplicati PLI sunt urmatoarele:
Definirea numelui pentru functia sau task-ul prin intermediul carora se apeleaza
aplicatia PLI.
Definirea unor rutine C/C++ care sa fie rulate de catre simulator la apelul sau
la compilarea functiei/task-ului din codul Verilog.
Inregistrarea functiei/task-ului Verilog si a rutinelor C/C++ asociate n structurile specifice simulatorului Verilog. Prin procesul de nregistrare se face o
legatura ntre numele functiei/task-ului si rutinele ce urmeaza a fi executate.
Compilarea surselor C/C++ ale aplicatiei PLI pentru a obtine o biblioteca
dinamica urmand ca aceasta sa fie ncarcata de compilatorul Verilog la pornirea
simularii.
Ca exemplu de aplicatie PLI se prezinta o functie Verilog care calculeaza logaritmul
n baza 2 al argumentului de intrare.
Definirea numelui pentru functia sau task-ul prin intermediul c
areia
se apeleaz
a aplicatia PLI. Se alege un nume sugestiv, log2(n), unde argumentul n poate fi o constanta, parametru, sau net (wire sau reg). Ca limbaj
de dezvoltare se alege ANSI C. Limbajul ANSI C este preferat limbajului C++
datorit
a portabilitatii acestuia pe diferite platforme (Windows, Linux, Solaris).
Toate functiile care compun interfata PLI sunt specifice simulatorului si sunt
oferite sub forma de biblioteca statica nsotita de un fisier header n care se specific
a antetele functiilor din interfata PLI. Pentru aceasta aplicatie se folosesc
rutinele VPI care au asociate fisierul vpi_user.h.
/***************************************************************
* Fisiere incluse
***************************************************************/
129
#include
#include
#include
#include
#include
#include
<stdlib.h>
<stdio.h>
<string.h>
<math.h>
<time.h>
"vpi_user.h"
*/
*/
*/
*/
130
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
131
132
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
/****************************************************************
* Structura necesara initializarii rutinelor VPI
***************************************************************/
void (*vlog_startup_routines[])() = {
log2_register,
0
};
Compilarea surselor C/C++ ale aplicatiei PLI pentru a obtine o bibliotec
a dinamic
a urm
and ca aceasta s
a fie nc
arcat
a de compilatorul
Verilog la pornirea simul
arii. Compilarea fisierelor C se realizeaza cu orice
compilator C, folosind un mediu integrat sau apeluri la linie de comanda. In
faza de link-editare a fisierelor, trebuie precizata calea catre biblioteca statica
ce contine functiile interfetei PLI. Aceasta biblioteca se gaseste n distributia
fiecarui compilator Verilog ce ofera suport PLI. In mod particular, s-a folosit
simulatorul ModelSim pe o platforma Windows. Simulatorul ModelSim ofera
biblioteca numita mtipli.lib. Pentru o compilare la linie de comanda pentru
platforme Windows, se poate folosi urmatoarea secventa de comenzi (calea catre
distributia de ModelSim nu este absoluta, ci este specifica fiecarui utilizator):
cl -c -IC:\modeltech_5.7g\include log2.c
link -dll -export:vlog_startup_routines log2.obj
c:\modeltech_5.7g\win32\mtipli.lib /out:log2.dll
Ca rezultat, se obtine o biblioteca dinamica (log2.dll, n cazul platformei Windows) care trebuie ncarcata de catre simulator la ncarcarea proiectului. Modalitatea de ncarcare a unei aplicatii PLI este specifica fiecarui tip de simulator.
In cazul particular al simulatorului ModelSim, trebuie specificat n fisierul de
initializare (modelsim.ini) calea catre bibiotecile dinamice ce contin aplicatii
PLI prin intermediul variabilei Veriuser:
; List of dynamically loaded objects for Verilog PLI applications
Veriuser = ./log2.dll
Incarcarea proiectului n simulator se face asemanator cu situatiile n care nu
sunt implicate aplicatii PLI.
4.9.2
Aplicatia PLI este apelata prin intermediul functiilor din codul Verilog. Un exemplu
de modul Verilog n care se apeleaza functia PLI $log2 este prezentat n continuare.
Se observa apelarea functiei cu diferite tipuri de obiecte, transmise ca argument.
n
T
133
4.10. Nout
ati introduse de standardul IEEE Verilog 1364-2001
module tstPli();
parameter param = 230;
wire[7:0]
reg[7:0]
integer
wire_sig;
reg_sig;
int = 279;
wire[7:0]
wire[7:0]
wire[7:0]
wire[7:0]
rez_param;
rez_wire;
rez_reg;
rez_int;
initial begin
reg_sig = 63;
end
assign wire_sig
= 15;
assign
assign
assign
assign
=
=
=
=
rez_param
rez_wire
rez_reg
rez_int
$log2(param);
$log2(wire_sig);
$log2(reg_sig);
$log2(int);
//
//
//
//
log2(230)
log2(15)
log2(63)
log2(279)
=
=
=
=
8
4
6
9
endmodule
4.10
Nout
ati introduse de standardul IEEE Verilog
1364-2001
bloc de configurare
specificatie generate
functii care ntorc constante
adresarea indexata a vectorilor
matrici multidimensionale
selectia unui domeniu al matricilor
aritmetica cu numere cu semn
operator de ridicare la putere
task-uri si functii re-entrante
operator ce desemneaza o lista de senzitivitati completa
liste de senzitivitati cu caracter de despartire virgula (,)
134
CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG
Capitolul 5
PROBLEME REZOLVATE
Acest capitol prezinta cateva probleme avansate de proiectare, care nu se rezolva
ntotdeauna cu solutia clasica. Toate problemele au fost ntalnite n practica de
zi cu zi la firma eASIC. Din acest motiv, unele rezolvari fac apel la metodologia de
proiectare a circuitelor integrate digitale n aceasta tehnologie. Bibliotecile complete
pentru simulare si sinteza se gasesc pe situl firmei eASIC (http://www.easic.com).
5.1
De foarte multe ori modulele de control transmit comenzi sub forma unor impulsuri.
Intr-un sistem sincron, se poate defini impulsul ca fiind un semnal cu o durata activa
mult mai scurta decat perioada inactiva. Intr-un sistem sincron, latimea semnalului
este ntotdeauna un numar ntreg de perioade de ceas.
5.1.1
Acest paragraf prezinta proiectarea unui circuit secvential sincron avand o intrare si
o iesire. Intrarea este generata de un sistem sincron si este activa n starea 1 un
numar oarecare Ni de perioade de ceas. Iesirea este ntotdeauna activa un numar par
No de perioade de ceas, astfel:
daca Ni este par, atunci No = Ni ;
daca Ni este impar, atunci No = Ni + 1.
Pentru exemplificare, figura 5.1 prezinta descrierea sistemului prin forme de unda.
Se presupune ca exista cel putin doua perioade de ceas pauza ntre doua pulsuri
consecutive.
135
136
S1
S0
0/0
/1
Se observa ca automatul are numai doua stari ntre care comuta. Descrierea
acestui automat este prezentata n continuare:
reg
stare;
137
toggle;
puls_o = puls_i | toggle;
Daca se doreste iesirea direct din registru, atunci codul trebuie modificat astfel:
reg
reg
toggle;
puls_o;
138
In acest caz, schema rezultata dupa sinteza este similara cu cea prezentata n figura
5.5. Iesirea va fi ntarziata cu un tact fata de cea din implementarea precedenta (figura
5.4).
Figura 5.5 Generatorul de impulsuri descris ca bistabil T, cu iesire din registru. Schem
a
dup
a sintez
a.
Se observa ca, desi schemele rezultate (figurile 5.4 si 5.5) prezinta structura unor
automate (bucla peste un registru/bistabil), modelul Verilog nu este similar celui
propus pentru descrierea automatelor n general. Pentru automate cu putine stari,
este uneori preferata scrierea modelului rezultat din transcrierea n Verilog a ecuatiilor
de tranzitie a iesirilor.
5.1.2
Acest paragraf prezinta proiectarea unui circuit secvential sincron ce are la baza un
bistabil RS. Se face ipoteza ca semnalele R si S nu sunt active simultan si ca exista cel
putin doua tacte consecutive n care nici unul nu este activ. Este necesara generarea
a doua semnale cu forma de unda identica cu cea a iesirii bistabilului RS. Primul
semnal trebuie sa fie ntarziat cu un tact iar al doilea n avans cu un tact fata de
semnalul de referinta (iesirea bistabilului RS). In plus, este necesara monitorizarea
valorii de adevar a ipotezei ca R si S nu sunt active simultan.
Formele de unda ce descriu sistemul sunt prezentate n figura 5.6.
n
V
n
T
module rs(
ck,
reset_ni,
r_i,
s_i,
rs_o,
rsAvans_o,
rsIntarziat_o
);
input
input
input
input
output
output
output
ck;
reset_ni;
r_i;
s_i;
rs_o;
rsAvans_o;
rsIntarziat_o;
reg
reg
rs_o;
rsIntarziat_o;
139
140
end
endmodule
Schema rezultata prin sinteza este prezentata n figura 5.7.
Exist
a doua ipoteze asociate intrarilor:
intr
arile R si S nu sunt niciodata active simultan;
exista cel putin doua tacte n care nici o intrare nu este activa, ntre activarea
uneia dintre cele doua intrari.
Verificarea primei ipoteze este echivalenta cu a spune ca functia logica AND ntre
cele doua intrari nu are niciodata valoarea de adevar 1.
always @(posedge ck) begin
if (r_i && s_i) begin
$display("%M %t EROARE: R si S sunt simultan active", $time);
$stop;
end
end
Verificarea celei de-a doua ipoteze presupune existenta unor informatii despre
istoria semnalelor n ultimele doua perioade de ceas. Figura 5.8 prezinta formele
de unda ale semnalelor utilizate la verificarea ipotezei.
Ecuatiile logice ale acestora sunt:
rOrS = r_i | s_i;
rOrS_r1 este versiunea ntarziata cu un tact a semnalului rOrS;
rOrS_r2 este versiunea ntarziata cu un tact a semnalului rOrS_r1;
141
142
5.2
Abordarea clasica a acestui proiect presupune implementarea circuitului de recunoastere a secventei printr-un automat. Organigrama sau graful de tranzitie care
descriu functionarea acestuia vor fi dependente de secventa care se doreste a fi recunoscuta. Cu alte cuvinte, daca ulterior proiectarii, beneficiarul schimba secventa
ce trebuie recunoscuta, atunci tot procesul de proiectare se reia de la nceput.
In continuare este prezentata proiectarea sistemului dupa metodologia clasica de
implementare cu automat. Graful de tranzitie este prezentat n figura 5.11. Automatul are o intrare de date si o iesire cu semnificatia potrivire_o. Automatul
proiectat este de tip Moore. Secventa de recunoscut este codata n graful de
tranzitie al automatului.
Numararea potrivirilor se face cu un numarator n sens crescator care este incrementat la fiecare activare a iesirii potrivire_o. Un comparator monitorizeaza
143
S0
reset_n
1
S1
1
S5
S4
S2
S3
valoarea numaratorului si seteaza un bistabil n cazul n care aceasta valoare este 100.
Incrementarea ulterioara a numaratorului este inhibata prin conditionarea acesteia
de depasire_o=0.
Schema bloc a ntregului circuit este prezentata n figura 5.12.
Codul Verilog care modeleza circuitul contine specificatii corespunzatoare blocurilor proiectate.
n
n
V
T
// starile
define S0
define S1
define S2
define S3
define S4
define S5
automatului
3b000
3b001
3b010
3b011
3b100
3b101
module recPatt(
ck,
reset_ni,
dataIn_i,
potrivire_o,
depasire_o
);
144
dataIn_i
potrivire_o
Automat
CU
Numarator
sens
crescator
7
=100
reset_ni
depasire_o
input
input
input
output
output
ck;
reset_ni;
dataIn_i;
potrivire_o;
depasire_o;
reg
reg
reg[6:0]
reg[2:0]
potrivire_o;
depasire_o;
numarator;
stare;
else begin
stare <= S2;
end
S2: if (!dataIn_i) begin
stare <= S0;
end
else begin
stare <= S3;
end
S3: if (!dataIn_i) begin
stare <= S4;
end
else begin
stare <= S3;
end
S4: if (!dataIn_i) begin
stare <= S5;
end
else begin
stare <= S1;
end
S5: if (!dataIn_i) begin
stare <= S0;
end
else begin
stare <= S1;
end
default: stare <= S0;
endcase
end
end
always @(posedge ck)
if (!reset_ni) begin
potrivire_o <= 1b0;
end
else begin
potrivire_o <= (stare == S4) & (~dataIn_i);
end
always @(posedge ck)
if (!reset_ni) begin
numarator <= 7b0;
end
else begin
if (potrivire_o && ~depasire_o) begin
numarator <= numarator + 1;
145
146
end
end
always @(posedge ck)
if (!reset_ni) begin
depasire_o <= 1b0;
end
else begin
if (numarator==7d100) begin
depasire_o <= 1b1;
end
end
endmodule
O abordare alternativa a acestei probleme porneste de la observatia ca o secventa
de date poate fi memorata ntr-un lant de bistabile, pentru a se avea acces la o
istorie a semnalului. Avand la dispozitie istoria semnalului, la fiecare moment se
poate decide daca secventa impusa a fost recunoscuta sau nu. Schimbarea ulterioara
a secventei nu va modifica decat existenta unor inversoare (care codifica informatia
despre pattern). Schema bloc a circuitului care implementeaza acest principiu este
prezentat
a n figura 5.13. Circuitul este format dintr-un lant de bistabile ale caror
iesiri sunt inversate sau nu, conform patternului ce trebuie recunoscut. Ulterior aceste
semnale sunt colectate ntr-o poarta AND pentru a genera semnalul potrivire_o.
dataIn_i
potrivire_o
n
V
reg[3:0]
data_r;
always @(posedge ck)
if (!reset_ni) begin
data_r <= 4b0;
potrivire_o <= 1b0;
end
else begin
data_r <= {data_r[2:0], dataIn_i};
// urmatoarea linie codifica patternul prin pozitia inversoarelor
potrivire_o <= &{data_r[3], data_r[2], data_r[1], ~data_r[0],
147
~dataIn_i};
end
Se remarca claritatea sporita a codului propus n varianta cu registru de deplasare
fata de varianta cu automat.
5.3
Un protocol uzual de comunicare ntre doua module ale unui sistem digital este protocolul bazat pe cerere si confirmare. Modulul sursa trimite o cerere catre modulul
destinatie prin activarea unui semnal cerere. Acest semnal este tinut activ pana cand
modulul destinatie valideaza cererea. Cererea este validata cand modulul destinatie
activeaza pentru o perioada de tact semnalul confirmare. Se presupune ca modulul
sursa mentine cererea activa pana la primirea confirmarii iar modulul destinatie emite
ntotdeaunda (mai devreme sau mai tarziu) un puls de validare asociat fiecarei cereri
receptionate. Aceste ipoteze pot fi infirmate n cazul n care unul dintre module are
o anomalie de proiectare. Acest lucru este mai neplacut n cazul n care cele doua
module, sursa si destinatie, sunt proiectate de catre proiectanti diferiti.
Se justifica astfel existenta unui monitor/verificator de protocol care sa spioneze semnalele de cerere si de confirmare si sa semnaleze abaterile de la protocolul
impus. Cateva cazuri de abateri de la protocol sunt prezentate n figura 5.14:
cerere abandonata nainte de primirea confirmarii;
cerere mentinuta dupa primirea confirmarii;
confirmare emisa fara cerere;
confirmare emisa simultan cu cererea.
148
cerere
Modul sursa
confirmare
Modul destinatie
Modul
mesaj de eroare
verificare protocol
eroare
Figura 5.15 Pozitia unui modul de monitorizare a protocolului n cadrul unui mediu de
simulare.
ale cererii si confirmarii vor intra ntr-un circuit combinational care va face distinctia
ntre cazurile corecte si cazurile eronate. Codul Verilog este prezentat n continuare
iar schema obtinuta prin sinteza este prezentata n figura 5.16.
n
V
n
T
module monProtocol(
ck_i,
reset_ni,
cerere_i,
confirmare_i,
eroare_o
);
input
input
input
input
output
ck_i;
reset_ni;
cerere_i;
confirmare_i;
eroare_o;
reg
reg
reg
cerere_r;
confirmare_r;
eroare_o;
149
150
5.4
n
n
V
T
n
V
reg[msb:0] counter;
always @(posedge Ck) begin
counter
<= counter + 1;
151
5.5
5.5.1
Modelarea registrelor
Registrul paralel
Schema bloc a unui registru de deplasare, cu ncarcare si iesire n paralel, este prezentata n figura 5.19.
ld
sh
ck
d
q
152
ld
1
0
0
sh
X
1
0
ck
q
d
q << 1
q
Semnificatie
Incarcare
Deplasare stanga
Pastrare stare
Tabelul 5.1
Tabelul de adev
ar al registrului de deplasare paralel.
n
V
n
T
module paralelReg (
ck,
ld,
sh,
di,
do
);
input
input
input
input[3:0]
output[3:0]
reg[3:0]
ck;
ld;
sh;
di;
do;
do;
5.5.2
LFSR (Linear Feed-back Shift Register) este un registru de deplasare care are o reactie
realizata cu o poarta XOR. Acest tip de constructie poate genera o secventa de stari
pseudoaleatorii. Numarul de stari generate de un LFSR cu latime de N biti este de
2N 1 (n cazul n care polinomul caracteristic este prim). Diferenta ntre LFSR si un
153
numarator, care are 2N stari, consta n faptul ca circuitul combinational al LFSR este
mult mai mic (deci circuitul are arie mai mica si functioneaza mai rapid). Circuitele
LFSR se utilizeaza cand se doreste o secventa de numarare aleatorie sau o secventa
indiferent
a dar de dimensiuni maxime pentru un anumit cost de hardware.
La intrarea portii XOR se introduc bitii corespunzatori polinomului care caracterizeaza circuitul. Acest polinom este dependent de latimea registrului. De exemplu,
pentru o latime de 8 biti, polinomul caracteristic este: f (x) = x8 + x6 + x5 + x + 1.
Schema bloc a unui LFSR de 8 biti este prezentata n figura 5.21.
CK
[7]
[6]
[5]
[4]
[3]
[2]
[1]
n
V
module lfsr8(
ck_i,
reset_ni,
en_i,
data_o
);
input
ck_i;
[0]
154
input
input
output[7:0]
reg[7:0]
reset_ni;
en_i;
data_o;
data_o;
n
V
module lfsr(
ck_i,
reset_ni,
en_i,
data_o
);
parameter
input
input
input
output[width-1:0]
reg[width-1:0]
width = 4;
ck_i;
reset_ni;
en_i;
data_o;
data_o;
begin
case (width)
1: lfsrPoly =
2: lfsrPoly =
3: lfsrPoly =
4: lfsrPoly =
5: lfsrPoly =
6: lfsrPoly =
7: lfsrPoly =
8: lfsrPoly =
9: lfsrPoly =
10: lfsrPoly =
11: lfsrPoly =
12: lfsrPoly =
13: lfsrPoly =
14: lfsrPoly =
15: lfsrPoly =
16: lfsrPoly =
17: lfsrPoly =
18: lfsrPoly =
19: lfsrPoly =
20: lfsrPoly =
21: lfsrPoly =
22: lfsrPoly =
23: lfsrPoly =
24: lfsrPoly =
25: lfsrPoly =
26: lfsrPoly =
27: lfsrPoly =
28: lfsrPoly =
29: lfsrPoly =
30: lfsrPoly =
31: lfsrPoly =
32: lfsrPoly =
33: lfsrPoly =
34: lfsrPoly =
35: lfsrPoly =
36: lfsrPoly =
37: lfsrPoly =
38: lfsrPoly =
39: lfsrPoly =
40: lfsrPoly =
41: lfsrPoly =
42: lfsrPoly =
43: lfsrPoly =
44: lfsrPoly =
45: lfsrPoly =
1b1;
2b11;
3b011;
4b0011;
5b00101;
6b000001;
7b0000011;
8b01100011;
9b000010001;
10b0000001001;
11b00000000101;
12b000010011001;
13b0000000011011;
14b01100000000011;
15b000000000000011;
16b0000000000101101;
17b00000000000001001;
18b000000000010000001;
19b0000000000001100011;
20b00000000000000001001;
21b000000000000000000101;
22b0000000000000000000011;
23b00000000000000000100001;
24b000000000000000000011011;
25b0000000000000000000001001;
26b00000000000000000110000011;
27b000000000000000000110000011;
28b0000000000000000000000001001;
29b00000000000000000000000000101;
30b000000000000011000000000000011;
31b0000000000000000000000000001001;
32b00011000000000000000000000000011;
33b000000000000000000010000000000001;
34b0000000000000000001100000000000011;
35b00000000000000000000000000000000101;
36b000000000000000000000000100000000001;
37b0000000000000000000000010100000000101;
38b00000000000000000000000000000001100011;
39b000000000000000000000000000000000010001;
40b0000000000000000000101000000000000000101;
41b00000000000000000000000000000000000001001;
42b000000000000000001100000000000000000000011;
43b0000000000000000000000000000000000001100011;
44b00000000000000001100000000000000000000000011;
45b000000000000000000000000000000000000000011011;
155
156
n
T
In mediul de testare s-a instantiat modulul lfsr cu diversi parametrii, ca
n exemplul urmator:
wire[2:0]
wire[3:0]
data3;
data4;
157
.en_i
.data_o
(en
(data4
),
)
);
n
T
In continuare sunt prezentate fisiere intermediare obtinute n cursul implementarii unui LSFR n tehnologie eASIC. Fisierele cu bibliotecile necesare simularii
se afla pe situl de web al cartii. Intregul set de biblioteci poate fi gasit pe situl firmei
eASIC.
In urma sintezei modulului lfsr cu parametrul width = 4, se obtine un netlist
cu instantieri de primitive din biblioteca specifica de tehnologie. Fisierul rezultat,
prezentat n continuare, poate fi simulat cu conditia compilarii bibliotecii de tehnologie
ce contine descrierea comportamentului tuturor primitivelor.
module lfsr_syn ( ck_i, reset_ni, en_i, data_o );
output [3:0] data_o;
input ck_i, reset_ni, en_i;
wire
N13, n2, n3, n4, n6, n8, n9, n11, n12;
dffe data_o_reg1 ( .Q(data_o[1]), .CK(ck_i), .D(n2), .EN(N13) );
dffe data_o_reg2 ( .Q(data_o[2]), .CK(ck_i), .D(n3), .EN(N13) );
dffe data_o_reg3 ( .Q(data_o[3]), .CK(ck_i), .D(n4), .EN(N13) );
dffe data_o_reg0 ( .Q(data_o[0]), .CK(ck_i), .D(n12), .EN(N13) );
l3i_40_x3 U8 ( .Y(n8), .A(data_o[1]), .B(n9), .C(n6) );
inv U9 ( .Y(n9), .A(data_o[0]) );
inv U16 ( .Y(n6), .A(n11) );
l3j_45_x3 U18 ( .Y(n4), .A(n8), .B(n11), .C1(data_o[0]),
.C2(data_o[1]) );
l2c_dd_x3 U19 ( .Y(n3), .A(data_o[3]), .B(n11) );
l2c_dd_x3 U20 ( .Y(n2), .A(data_o[2]), .B(n11) );
l3i_4c_x3 U21 ( .Y(n12), .A(data_o[1]), .B(reset_ni), .C(n6) );
l2c_77_x3 U22 ( .Y(n11), .A(reset_ni), .B(en_i) );
l2c_77_x3 U23 ( .Y(N13), .A(reset_ni), .B(n11) );
endmodule
Ulterior, netlist-ul ce contine primitive de nivel nalt este asociat cu resursele
logice existente, plasat si n final rutat. La finalul implementarii se genereaza un fisier
netlist cu informatii specifice resurselor folosite n tehnologia aleasa. Acest fisier poate
fi simulat n acelasi mediu de testare, cu sau fara informatie de timp de propagare
prin logica si pe sarme. Formele de unda rezultate n urma simularii celor trei modele
(RTL, post sinteza si post map-are/plasare/rutare) sunt prezentate n figura 5.22.
In figura 5.23, se prezinta o imagine marita a formelor de unda, imagine n care se
observa includerea informatiilor temporale n modelul post map-are/plasare/rutare.
n
T
158
// technology FA250L
// Current time: 25_07_2005-12:40:49
//-----------------------------------------------------
data_o[3] = n19;
data_o[2] = n23;
data_o[1] = n28;
data_o[0] = n21;
n15 = ck_i;
n16 = reset_ni;
n17 = en_i;
159
160
endmodule
161
162
5.6
O problema deosebita n proiectarea sistemelor digitale o reprezinta trecerea semnalelor dintr-un domeniu de ceas n altul. Riscul l reprezinta faptul ca este posibil
ca n simulare totul sa functioneze corect, dar n realitate chip-ul sa nu functioneze
sau sa functioneze aleatoriu. Motivul l constituie negarantarea ndeplinirii conditiilor
163
5.6.1
Acest tip de sincronizare este foarte frecventa pentru semnale de control (cu semnificatie pe bit) programate de catre microprocesor. In cele mai multe cazuri, registrele
asociate acestor semnale de control sunt scrise o singura data, n etapa de initializare
a sistemului. Ca exemplu, se poate mentiona semnalul de validare a functionarii unui
controller de memorie, activat de catre microprocesor dupa scurgerea unui interval
de timp impus de contrangerile chip-ului de memorie. Acest semnal este initial (la
reset) n stare 0 si este scris de catre procesor cu valoarea 1. Acest eveniment este
singular (semnalul ramane 1 pentru totdeauna) si este interpretat de catre controller
ca validare a nceperii initializarii memoriei.
Evident, aparitia acestui eveniment (setarea semnalului de catre procesor) cu o
oarecare ntarziere pe celalalt domeniu de ceas este acceptabila. Singura constangere
impusa este ca sa fie minimizata starea de metastabilitate a semnalelor din domeniul
de ceas de destinatie. Din acest motiv, sincronizarea semnalului prin trecerea acestuia
prin doua bistabile avand ca ceas ceasul de destinatie, este o solutie acceptabila.
Codul Verilog al circuitului de sincronizare a unui semnal la trecerea dintr-un
domeniu de ceas lent ntr-un domeniu de ceas mai rapid este prezentat n continuare.
Formele de unda rezultate sunt prezentate n figura 5.24.
n
n
V
T
164
module outSync_s2f (
bitS_i,
clkF_i,
resetF_ni,
bitF_o
);
input
input
input
output
//
//
//
//
//
bitS_i;
clkF_i;
resetF_ni;
bitF_o;
clkS
clkF_i
bitS_i
bitF_r
bitF_o
reg
reg
|
|
|
|
|
| | | | | | | | | | | | | | | | | |
_|-----------------------|________
__|-----------------------|_______
____|-----------------------|_____
bitF_r;
bitF_o;
De remarcat faptul ca acest circuit este corect exclusiv pentru sincronizarea semnalelor de un bit, cu semnificatie individuala. O solutie pentru sincronizarea unui bus
este prezentata n sectiunea 5.6.4.
5.6.2
165
Exista numeroase cazuri n care o actiune ce are loc ntr-un domeniu de ceas rapid
trebuie transmisa n domeniul unui ceas lent. Actiunea, semnalata printr-un puls cu
latime de o perioada de ceas rapid, poate avea loc ntre momentele determinate de
fronturile ceasului lent. Din aceasta cauza sunt necesare procesari ale pulsului pentru
a asigura transmiterea acestuia ca un puls pe domeniul de ceas lent.
O solutie simpla, dar dependenta de raportul dintre frecventele ceasurilor sursa si
destinatie, consta din latirea pulsului astfel ncat latimea pulsului sa fie egala cu
cel putin o perioada a ceasului destinatie. In acest mod se garanteaza ca semnalul va
fi esantionat la destinatie activ cel putin pe un front al semnalului de ceas. Ceasurile
fiind asincrone, este posibil, ca n anumite cazuri, pulsul sa fie esantionat la destinatie
ca activ chiar n doua perioade de ceas succesive. Din acest motiv, trebuie prevazut un
circuit de detectie de front care sa garanteze ca la iesirea acestuia pulsul are latimea
exact de o perioada de ceas. In plus, ram
ane problema sincronizarii semnalului prin
trecerea prin doua bistabile pe ceasul de destinatie. Circuitul consta din:
latire a pulsului la destinatie astfel ncat latimea acestuia sa fie mai mare decat o
perioada a ceasului de destinatie (operatie dependenta de frecventele ceasurilor
sursa si destinatie);
sincronizare a pulsului prin trecerea prin doua bistabile pe ceasul de destinatie;
detectia de front pentru generarea unui puls cu latime de o perioada pe ceasul
de destinatie.
Codul Verilog al circuitului de sincronizare a unui puls la trecerea dintr-un domeniu de ceas rapid ntr-un domeniu de ceas mai lent este prezentat n continuare.
Formele de unda rezultate sunt prezentate n figura 5.25. Schema rezultata din sinteza este prezentata n figura 5.26. Ipoteza este ca frecventa ceasului de destinatie
este de maxim 4 ori mai mica decat frecventa ceasului sursa.
n
n
V
T
module pulseSyncFq_f2s (
clkF_i,
resetF_ni,
pulseF_i,
clkS_i,
resetS_ni,
pulseS_o
);
input
input
clkF_i;
resetF_ni;
166
input
pulseF_i;
input
input
output
clkS_i;
resetS_ni;
pulseS_o;
//
//
//
//
//
//
//
//
//
//
//
//
clkF_i
pulseF_i
pulseF_r1
pulseF_r2
pulseF_r3
pulseF_r4
pulseF_or
clkS_i
pulseS_r1
pulseS_r2
pulseS_r3
pulseS_o
reg
reg
reg
reg
reg
reg
reg
reg
reg
| | | | | | | | | | | | | | | | | | | | | | | | | |
__|-|______________________________________________
____|-|____________________________________________
______|-|__________________________________________
________|-|________________________________________
__________|-|______________________________________
____|---------|____________________________________
|
|
|
|
|
|
_____|---------------|_____________________________
_____________|---------------|_____________________
_____________________|---------------|_____________
_____________________________________|-------|_____
pulseF_r1;
pulseF_r2;
pulseF_r3;
pulseF_r4;
pulseF_or;
pulseS_r1;
pulseS_r2;
pulseS_r3;
pulseS_o;
167
if (~resetF_ni) begin
pulseF_or <= 1b0;
end
else begin
pulseF_or <= pulseF_i | pulseF_r1 | pulseF_r2 |
pulseF_r3 | pulseF_r4;
end
end
// preia pulsul pe ceasul de destinatie, cu inca doua intarzieri
always @(posedge clkS_i) begin
if (~resetS_ni) begin
pulseS_r1 <= 1b0;
pulseS_r2 <= 1b0;
pulseS_r3 <= 1b0;
end
else begin
pulseS_r1 <= pulseF_or;
pulseS_r2 <= pulseS_r1;
pulseS_r3 <= pulseS_r2;
end
end
// detectie de front negativ
always @(posedge clkS_i) begin
if (~resetS_ni) begin
pulseS_o <= 1b0;
end
else begin
pulseS_o <= pulseS_r3 & ~pulseS_r2;
end
end
endmodule
Uneori raportul ntre frecventele de ceas ale celor doua domenii nu este cunoscut n
momentul proiectarii. Solutia prezentata anterior nu este convenabila daca se ncearca
generalizarea ei si extinderea domeniului de frecvente. O solutie independenta de
frecventa este prezentata n continuare. Solutia consta n existenta unui bistabil
RS care este setat de catre pulsul din domeniul destinatie si resetat dupa primirea
confirmarii aparitiei pulsului pe domeniul destinatie.
Codul Verilog al circuitului de sincronizare a unui puls la trecerea dintr-un domeniu de ceas rapid ntr-un domeniu de ceas mai lent, independent de frecventele de ceas,
este prezentat n continuare. Formele de unda rezultate sunt prezentate n figura 5.27.
Schema rezultata din sinteza este prezentata n figura 5.28.
n
n
V
T
168
module pulseSync_f2s (
clkF_i,
resetF_ni,
pulseF_i,
clkS_i,
resetS_ni,
pulseS_o
);
input
input
input
input
input
output
//
//
//
//
//
//
clkF_i;
resetF_ni;
pulseF_i;
clkS_i;
resetS_ni;
pulseS_o;
clkF_i
pulseF_i
syncPendF
clkS_i
plsS_r1
plsS_r2
| | | | | | | | | | | | | | | | | | | | | | | | | |
__|-|______________________________________________
____|---------------|______________________________
|
|
|
|
|
|
|
_________|---------------|_________________________
_________________|---------------|_________________
//
//
//
//
//
pulseS_w
pulseS_o
syncPendS
clrF
clkF_i
reg
reg
reg
reg
wire
reg
reg
_________|-------|_________________________________
_________________|-------|_________________________
_________________|---------------|_________________
__________________|---------------|________________
| | | | | | | | | | | | | | | | | | | | | | | | | |
pulseS_o;
syncPendS;
plsS_r1;
plsS_r2;
pulseS_w;
syncPendF;
clrF;
169
170
end
else begin
if (pulseS_w) begin
syncPendS <= 1b1;
end
end
end
end
endmodule
5.6.3
La trecerea unui puls dintr-un domeniu de frecventa lenta ntr-un domeniu de frecventa
ridicata latimea pulsului scade. Se poate garanta ca, la esantionarea pulsului pe
frecventa de destinatie, pulsul este gasit activ cel putin la o esantionare. In acest
caz, apare nsa o noua problema: pulsul din domeniul destinatie (efect) poate aparea
171
naintea celui din domeniul sursa (cauza). Acest lucru se poate ntampla daca se utilizeaza un circuit simplu de sincronizare pe ceasul de destinatie urmat de un circuit
de detectie de front crescator.
n
V
clkS_i;
resetS_ni;
ldS_i;
clkF_i;
resetF_ni;
ldF_o;
clkS_i
|
|
|
ldS_i
_|-----------|____________
clkF_i | | | | | | | | | | | | |
ldF_r1 __|-----------|___________
ldF_r2 ____|-----------|_________
ldF_r3 ______|-----------|_______
ldF_o
______|-|_________________
activ lent
^
activ rapid
^
reg
reg
172
end
end
endmodule
n
n
V
T
module ldSync_s2f (
clkS_i,
resetS_ni,
ldS_i,
clkF_i,
resetF_ni,
ldF_o
);
input
input
input
input
input
output
//
//
//
//
clkS_i;
resetS_ni;
ldS_i;
clkF_i;
resetF_ni;
ldF_o;
clkS_i
ldS_i
ldS_r
clkF_i
|
|
|
|
|
_|-------|________________________
_________|-------|________________
| | | | | | | | | | | | | | | | |
//
//
//
//
ldF_r1
ldF_r2
ldF_r3
ldF_o
reg
reg
reg
173
__________|-------|______________
____________|-------|____________
______________|-------|__________
______________________|-|________
ldS_r;
ldF_r1, ldF_r2, ldF_r3;
ldF_o;
5.6.4
Sincronizarea unui bus nu se poate face identic cu sincronizarea unui singur bit. Sincronizarea unui bus prin trecerea fiecarui bit prin circuite dedicate (prezentate n
sectiunea 5.6.1) este total incorecta. Justificarea consta n faptul ca datorita imposibilitatii realizarii identice a bistabilelor, este posibila aparitia n domeniul de ceas de
destinatie a unei stari inexistente n domeniul de ceas sursa. De exemplu, un semnal
de 2 biti ce comuta n domeniul sursa ntre valorile 00 si 11 poate genera n domeniul
destinatie succesiunea de stari 00, 01, 11.
Solutia propusa consta n trecerea bus-ului de date n domeniul destinatie n momentul n care exista garantia ca datele sunt stabile n domeniul sursa. Ideea este de a
174
5.6.5
175
comanda
incarcare
date pe ceas
lent
LD
D
date
pe
ceas
lent
LD
Q
date
pe
ceas
rapid
176
data_i
0
D
LD
Registru date
pe domeniu destinatie
df1
D
LD
D
LD
D
LD
1
data_o
df2
valid_i
2
LD
df3
3
wrAddr
CU
rdAddr
CU
ckSrc
ckDst
Numarator
adrese scriere
Numarator
adrese citire
valid_o
CU
sincronizare
detectare de
fronturi
ckSrc_i
ckDst_i
Numarator locatii
CD
numLoc
=2
n
V
Tn
rstDst_ni,
data_o,
valid_o
);
parameter dataWidth = 32;
input
input
input[dataWidth-1:0]
input
input
input
output[dataWidth-1:0]
output
ckSrc_i;
rstSrc_ni;
data_i;
valid_i;
ckDst_i;
rstDst_ni;
data_o;
valid_o;
reg[dataWidth-1:0]
reg
data_o;
valid_o;
reg[dataWidth-1:0]
reg[dataWidth-1:0]
reg[dataWidth-1:0]
reg[dataWidth-1:0]
df0;
df1;
df2;
df3;
reg[1:0]
reg[1:0]
reg[1:0]
reg
reg[2:0]
wire
wrAddr;
rdAddr;
numLoc;
validInT;
validInDst;
numLocEq2;
177
178
179
end
assign numLocEq2 = (numLoc == 2d2);
// numarator al locatiilor "pline" din FIFO
wire cuNumLoc = validInDst[2] ^ validInDst[1];
wire cdNumLoc = numLocEq2;
always @(posedge ckDst_i)
if (~rstDst_ni) begin
numLoc <= 2b00;
end
else begin
case ({cuNumLoc, cdNumLoc})
2b10: numLoc <= numLoc + 1;
2b01: numLoc <= numLoc - 1;
endcase
end
// registru de iesire pentru date
always @(posedge ckDst_i)
if (~rstDst_ni) begin
data_o <= h0;
end
else begin
if (numLocEq2) begin
case (rdAddr)
2d0:
data_o <= df0;
2d1:
data_o <= df1;
2d2:
data_o <= df2;
default: data_o <= df3;
endcase
end
end
// semnal de validare a datelor la iesire
always @(posedge ckDst_i)
if (~rstDst_ni) begin
valid_o <= 1b0;
end
else begin
valid_o <= numLocEq2;
end
endmodule
Figura 5.34 prezinta cateva forme de unda relevante pentru descrierea circuitului
de sincronizare a datelor.
Figura 5.35 prezinta structura rezultata n urma sintezei circuitului de sincronizare
180
181
5.7
Interfatarea cu CPU
Adresa
0x00
0x04
0x08
0x10
0x20
0x30
Descriere
Registru de configurare, semnificatie pe bit
Registru de comanda, semnificatie pe bit
MSB adresa
LSB adresa
Registru de date scrise n SDRAM
Registru de date citite din SDRAM
Tabelul 5.2
Descrierea setului de registre de configurare si a accesului CPU la
memorie.
CONFIG_REG (0x0)
15:8 frecv: frecventa (exprimata n MHz)
7
nefolosit
6:4
burstSize: dimensiune burst
3
sdramCntrlEn: pornire sdramCntrl
2:0
casLatency: latenta CAS
RDWR_REG (0x4)
15:9 nefolositi
8
rdCmd: comanda de citire (activa high)
7:1
nefolositi
0
wrCmd: comanda de scriere (activa high)
MSB_ADDR_REG (0x8)
15:9 nefolositi
8:0
msbAddr: adresa de acces a memoriei[24:16]
182
183
LSB_ADDR_REG (0x10)
15:0 lsbAddr: adresa de acces a memoriei[15:0]
WRITE_DATA_REG (0x20)
15:0 wrData: data ce urmeaza a fi scrisa n SDRAM
READ_DATA_REG (0x30)
15:0 rdData: data ce a fost citita din SDRAM
Registrul CONFIG_REG contine biti folositi pentru controlul software al configurarii
sdramCntrl. Controllerul lanseaza spre SDRAM secventa de initializare daca bitul
sdramCntrlEn comuta din 0 n 1. In acel moment se esantioneaza datele necesare configurarii SDRAM: burstSize, casLatency. Frecventa de lucru, frecv, este transmisa
blocului de control al sdramCntrl n scopul determinarii momentelor de timp cand
este necesara lansarea unei comenzi de refresh.
Registrul RDWR_REG contine 2 biti care comanda accesul CPU la memorie. Daca
CPU seteaza bitul wrCmd, sdramCntrl lanseaza o cerere de scriere n SDRAM la
adresa {msbAddr, lsbAddr} a datelor wrData. La terminarea actiunii bitul wrCmd
este resetat automat iar adresa {msbAddr, lsbAddr} este incrementata.
Daca CPU seteaza bitul rdCmd, sdramCntrl lanseaza o cerere de citire din SDRAM
de la adresa {msbAddr, lsbAddr}.
Datele citite se stocheaza n registrul READ_DATA_REG. La terminarea actiunii, bitul
rdCmd este resetat automat iar adresa {msbAddr, lsbAddr} este incrementata.
Tabelul 5.3 prezinta descrierea interfetei modulului proiectat.
Figura 5.37 prezinta detaliile de implementare a instantierii registrelor si a modului de scriere a acestora de catre CPU. Se observa ca o scriere are loc doar n cazul
n care semnalele de control selecteaza dispozitivul curent (cpuCs_ni=0) si exista o
cerere (cpuRq_i=1) iar cererea este de scriere (cpuRdWr_i=0). Rezulta ca raspunsul
la ntrebarea cand se scrie? este atunci cand doWr=1. Din figura se observa ca
semnalul doWr valideaza un demultiplexor pe al carui port de selectie intra adresa
CPU (cpuAddr_i). Iesirile demultiplexorului reprezinta semnalele de ncarcare asociate fiecarui registru n parte. Rezulta ca raspunsul la ntrebarea unde se scriu
184
Port
cpuClk_i
cpuReset_ni
cpuCs_ni
cpuAddr_i[9:0]
cpuRdWr_ni
cpuData_o[15:0]
cpuData_i[15:0]
cpuRq_i
cpuAck_o
sysClk_i
sysReset_ni
sysFrecv_o[7:0]
sysBurstSize_o[2:0]
sysSdramCntrlEn_o
sysCasLatency_o
sysRdRq_o
sysWrRq_o
sysAck_i
sysAddr_o[24:0]
sysWrData_o[15:0]
sysRdData_i[15:0]
Descriere
semnal de ceas al CPU
semnal de reset al CPU, activ n 0
selectare dispozitiv, activ n 0
adresa CPU
tipul comenzii CPU (0=citire, 1=scriere)
data de iesire spre CPU (folosita la citire)
data de intrare de la CPU (folosita la scriere)
cerere de la CPU
confirmare cerere de la CPU
semnal de ceas, utilizat de restul sistemului,
frecventa mai ridicata decat cpuClk_i
semnal de reset activ n 0
frecventa (exprimata n MHz)
dimensiune burst
validare pornire sdramCntrl
latenta CAS
comanda de citire din memorie
comanda de scriere n memorie
confirmare a comenzii de la sistem
adresa de acces a memoriei
data ce urmeaza a fi scrisa n SDRAM
data ce a fost citita din SDRAM
Tabelul 5.3
datele? este n registrul care a fost validat prin aplicarea adresei lui pe cpuAddr_i.
Raspunsul la ntrebarea ce date se scriu n registrul selectat este datele provenite
de la CPU pe magistrala corespunzatoare cpuData_i.
Figura 5.38 prezinta detaliile de implementare a citirii registrelor si generarea
semnalului de confirmare cpuAck_o. Continutul registrelor se multiplexeaza pe baza
adresei de citire primite de la CPU. Datele se genereaza tot timpul dar se valideaza
(cpuAck_o) doar n conditiile n care se cere o operatie de citire (cpuCs_ni=0,
cpuRq_i=1 iar cpuRdWr_i=1).
Fiecare registru prezinta particularitati de interfatare cu restul sistemului care
functioneaza pe un ceas asincron fata de CPU (sysClk_i). Solutiile de sincronizare
sunt adaptate fiecarui caz n parte.
Registrul CONFIG_REG contine date de configurare. In mod normal, acestea sunt
scrise o singura data, ulterior ramanand constante. Strategia abordata n acest caz,
prezentat
a n figura 5.39, consta n sincronizarea semnalului de ncarcare a registrului
(ld0) si trecerea datelor ulterior pe ceasul sysClk_i.
Registrul RDWR_REG contine doi biti care, daca sunt setati prin scriere de catre
CPU, determina generarea unor cereri de acces la memoria controlata de restul sis-
185
cpuData_i
ld0
15
4 3
CONFIG_REG (0X00)
casLatency
sdramCntrlEn
3
3
#00
#04
cpuCs_ni
ld4
RDWR_REG (0X04)
wrCmd
rdCmd
#08
doWr
cpuRdw_ni
cpuData_i
#10
ld8
MSB_ADDR_REG (0X08)
msbAddr
cpuRq_i
#20
cpuData_i
ld10
15
LSB_ADDR_REG (0X10)
lsbAddr
#30
cpuData_i
ld20
16
15
WRITE_DATA_REG (0X20)
wrData
10
ld30
cpuAddr_i
burstSize
frecv
15
10
16
READ_DATA_REG (0X30)
rdData
temului. Cererile sunt lansate prin porturile de iesire sysRdRq_o si sysWrRq_o sincron pe sysClk_i. Bitii registrului RDWR_REG sunt monitorizati prin interogare de
catre CPU pentru a se cunoaste daca actiunea curenta a fost sau nu ncheiata. La
aparitia confirmarii din partea sistemului (sysAck_i) trebuie sa se reseteze cererea
(sysRdRq_o sau sysWrRq_o). Totodata, trebuie transmisa informatia de actualizare
a starii bitilor rdCmd si wrCmd aflati pe ceasul cpuClk_i. Circuitul prezentat n figura
5.40 sincronizeaza comenzile de cerere si confirmare la trecerea domeniilor de ceas n
ambele sensuri.
Registrele MSB_ADDR_REG, LSB_ADDR_REG si WRITE_DATA_REG pot fi considerate
constante n momentul citirii acestora pe ceasul sysClk_i, cu conditia ca n software
sa se respecte ipotezele de proiectare referitoare la succesiunea operatiilor:
Scriere:
scriere MSB_ADDR_REG;
scriere LSB_ADDR_REG;
scriere WRITE_DATA_REG;
scriere RDWR_REG cu valoare 0x0001H;
citire RDWR_REG, daca este egal cu 0x0000H, atunci operatia de scriere se
considera ncheiata.
Citire:
scriere MSB_ADDR_REG;
scriere LSB_ADDR_REG;
scriere RDWR_REG cu valoare 0x0100H;
186
casLatency
sdramCntrlEn
burstSize
1b0
frecv
3
3
8
data0
#00
16
wrCmd
7b0
rdCmd
7b0
7
7
data4
#04
16
msbAddr
9
7b0
data8
16
lsbAddr
#10
data20
#20
16
data30
rdData
#30
16
16DEAD
16
cpuAddr_i
cpuData_o
16
#08
data10
16
wrData
10
cpuCs_ni
cpuRdw_ni
doRd
D
cpuAck_o
cpuRq_i
doW
cpuClk_i
187
ldSync_s2f
ld0
ld0Sys
casLatency
3
sdramCntrlEn
sysSdramCntrl_o
burstSize
frecv
sysCasLatency_o
sysBurstSize_o
sysFrecv_o
CONFIG_REG (0X00)
Figura 5.39 Sincronizarea CONFIG REG.
n
V
include "cpuIntfAddr.h"
module cpuIntf(
// Interfata cpu
cpuClk_i,
cpuReset_ni,
188
cpuData_i[8]
LD
sysAck_i
D
sincroclkSys
rdCmd
sysRdRq_o
detectare front
crescator
pulseSync_f2s
ld4
cpuData_i[0]
LD
set (cpu)
reset (sistem)
sysAck_i
D
sincroclkSys
wrCmd
sysWrRq_o
detectare front
crescator
set (cpu)
reset (sistem)
cpuCs_ni,
cpuAddr_i,
cpuRdWr_ni,
cpuData_o,
cpuData_i,
cpuRq_i,
cpuAck_o,
// Interfata sys
sysClk_i,
//
//
//
//
//
//
//
);
189
sysAck_i
16
ld30
sysRdRq_o
LD
sysRdData_i
ldCpu Dcpu
ldSys
16
Dsys
rdData
// Interfata CPU
input
cpuClk_i;
input
cpuReset_ni;
input
cpuCs_ni;
input[9:0]
cpuAddr_i;
input
cpuRdWr_ni;
output[15:0]
cpuData_o;
input[15:0]
cpuData_i;
input
cpuRq_i;
output
cpuAck_o;
// Interfata sys
input
sysClk_i;
input
sysReset_ni;
output[2:0]
sysCasLatency_o;
output
sysSdramCntrlEn_o;
output[2:0]
sysBurstSize_o;
output[7:0]
sysFrecv_o;
output[24:0]
sysAddr_o;
output[15:0]
sysWrData_o;
output
sysWrRq_o;
input[15:0]
sysRdData_i;
output
sysRdRq_o;
input
sysAck_i;
reg[15:0]
reg
cpuData_o;
cpuAck_o;
reg[2:0]
reg
reg[2:0]
sysCasLatency_o;
sysSdramCntrlEn_o;
sysBurstSize_o;
190
reg[7:0]
reg[24:0]
reg[15:0]
reg
sysFrecv_o;
sysAddr_o;
sysWrData_o;
sysWrRq_o;
reg[2:0]
casLatency;
reg
sdramCntrlEn;
reg[2:0]
burstSize;
reg[7:0]
frecv;
reg
wrCmd;
reg
rdCmd;
reg[8:0]
msbAddr;
reg[15:0]
lsbAddr;
reg[15:0]
wrData;
reg[15:0]
rdData;
wire
doRd;
reg
doRd_r;
reg[3:0] sysWrCmd_r;
reg[3:0] sysRdCmd_r;
reg sysRdRq_o;
reg[15:0] sysRdData_r;
wire
wire
wire
wire
wire
wire
wire
wire
wire
wire
doWr;
ld0;
ld4;
ld8;
ld10;
ld20;
ld30;
ldSys_f;
ldSys_s;
cpuAck;
191
192
else begin
if (cpuAck) begin
wrCmd <= 1b0;
rdCmd <= 1b0;
end
end
end
end
// sincronizare comanda de scriere pe domeniul
// de ceas mai rapid (sysClk_i)
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
sysWrCmd_r <= 4b0;
end
else begin
sysWrCmd_r <=
{~sysWrCmd_r[2] & sysWrCmd_r[1], sysWrCmd_r[1:0], wrCmd};
end
end
// implementarea comenzii de scriere pe ceasul rapid
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
sysWrRq_o <= 1b0;
end
else begin
if (sysWrCmd_r[3]) begin
sysWrRq_o <= 1b1;
end
else begin
if (sysAck_i) begin
sysWrRq_o <= 1b0;
end
end
end
end
// sincronizare comanda de citire pe domeniul
// de ceas mai rapid (sysClk_i)
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
sysRdCmd_r <= 4b0;
end
else begin
sysRdCmd_r <=
{~sysRdCmd_r[2] & sysRdCmd_r[1], sysRdCmd_r[1:0], rdCmd};
end
end
// implementarea comenzii de citire pe ceasul rapid
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
sysRdRq_o <= 1b0;
end
else begin
if (sysRdCmd_r[3]) begin
sysRdRq_o <= 1b1;
end
else begin
if (sysAck_i) begin
sysRdRq_o <= 1b0;
end
end
end
end
// sincronizarea confirmarii a comenzii de la sistem
// pe domeniul de ceas mai lent (cpuClk_i)
pulseSync_f2s i_rdwr_reg(
.clkF_i
(sysClk_i
),
.resetF_ni (sysReset_ni ),
.pulseF_i
(sysAck_i
),
.clkS_i
(cpuClk_i
),
.resetS_ni (cpuReset_ni ),
.pulseS_o
(cpuAck
)
);
// MSB_ADDR_REG 0x08 ***************************************
// semnal de incarcare pentru registrii de la adresa MSB_ADDR_REG
assign ld8 = (doWr & (cpuAddr_i == MSB_ADDR_REG));
// registrul pe cpuClk_i
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
msbAddr <= 9b0;
end
else begin
if (ld8) begin
msbAddr <= cpuData_i[8:0];
end
end
end
193
194
195
196
.pulseS_o
(ldSys_s
);
// citirea registrilor de catre CPU
// semnal care valideaza o citire
assign doRd = ~cpuCs_ni & cpuRdWr_ni & cpuRq_i;
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
doRd_r <= 1b0;
end
else begin
doRd_r <= doRd;
end
end
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
cpuData_o <= 16b0;
end
else begin
case (cpuAddr_i)
CONFIG_REG
: cpuData_o <= {frecv, 1b0, burstSize,
sdramCntrlEn, casLatency};
RDWR_REG
: cpuData_o <= {7b0, rdCmd, 7b0, wrCmd};
MSB_ADDR_REG
: cpuData_o <= {7b0, msbAddr};
LSB_ADDR_REG
: cpuData_o <= lsbAddr;
WRITE_DATA_REG : cpuData_o <= wrData;
READ_DATA_REG : cpuData_o <= rdData;
default
: cpuData_o <= 16hDEAD;
endcase
end
end
// registrul care memoreaza confirmarea de la CPU
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
cpuAck_o <= 1b0;
end
else begin
cpuAck_o <= doWr | doRd;
end
end
endmodule
Mediul de testare contine pe langa modulul proiectat o instantiere a unui modul
ce modeleaza comportamentul CPU si o instantiere aunui modul ce modeleaza com-
197
n
T
CPU este modelata sub forma unor task-uri de citire si de scriere registre.
Aceste task-uri sunt apelate fie explicit, fie n mod aleatoriu. Modelul controllerului
de memorie este modelat sub forma unui tabel bidimensional care mentine o copie a
datelor si furnizeaza semnale de validare a cererilor la un interval de timp aleatoriu.
tstCpuIntf
cpuDummy
cpuIntf
sdramCntrlDummy
5.8
Multiplicator secvential
n
n
V
T
module mult (
ck,
reset_ni,
start_i,
opA_i,
opB_i,
198
opA_i
opB_i
start_i
cale de
date
cale de control
LD
LD
DEC
Logica
de
stare
stare
curenta
opB_r
opA_r
stare urmatoare
Registru
de
stare
opBzero
=0
CLR
LD
acc
Logica
CLR
iesirilor
LD
decB
IdRez
IdAcc
IdOp
rezValid_o
rezultat_o,
rezValid_o
);
input
input
input
input[7:0]
input[7:0]
output[15:0]
output
ck;
reset_ni;
start_i;
opA_i;
opB_i;
rezultat_o;
rezValid_o;
rezultat_o
199
.ldRez_o
.ldOp_o
.decB_o
.ldAcc_o
(ldRez
(ldOp
(decB
(ldAcc
),
),
),
)
);
multCaleDate UmultCaleDate (
.ck
(ck
),
.reset_ni
(reset_ni
),
.opA_i
(opA_i
),
.opB_i
(opB_i
),
.rezultat_o (rezultat_o ),
.opBzero_o (opBzero
),
.ldRez_i
(ldRez
),
.ldOp_i
(ldOp
),
.decB_i
(decB
),
.ldAcc_i
(ldAcc
)
);
endmodule
module multCaleDate (
ck,
reset_ni,
opA_i,
opB_i,
rezultat_o,
opBzero_o,
ldRez_i,
ldOp_i,
decB_i,
ldAcc_i
);
input
input
input[7:0]
input[7:0]
output[15:0]
reg[15:0]
ck;
reset_ni;
opA_i;
opB_i;
rezultat_o;
rezultat_o;
200
input
input
input
ldOp_i;
decB_i;
ldAcc_i;
// incarca operanzii
// decrementeaza operand B
// incarca registru acumulator
reg[7:0] opA_r;
reg[7:0] opB_r;
reg[15:0] acc;
// stocare operandA
always @(posedge ck)
if (~reset_ni) opA_r <= 0; else
if (ldOp_i)
opA_r <= opA_i;
// stocare operandB
always @(posedge ck)
if (~reset_ni) opB_r <= 0; else
if (ldOp_i)
opB_r <= opB_i; else
if (decB_i)
opB_r <= opB_r - 1;
assign opBzero_o = (opB_r == 0);
// acumulator rezultat partial
always @(posedge ck)
if (~reset_ni) acc <= 0; else
if (ldOp_i)
acc <= 0; else
if (ldAcc_i)
acc <= acc + opA_r;
always @(posedge ck)
if (~reset_ni) rezultat_o <= 0; else
if (ldOp_i)
rezultat_o <= 0; else
if (ldRez_i)
rezultat_o <= acc;
endmodule
// codificarea
define INIT
define SET_UP
define DEC
define ADD
define FINAL
stariilor automatului
3b000
3b001
3b010
3b011
3b100
module multCaleControl(
ck,
reset_ni,
start_i,
rezValid_o,
201
opBzero_i,
ldRez_o,
ldOp_o,
decB_o,
ldAcc_o
);
input
input
ck;
reset_ni;
// porturi de intrare/iesire
input
start_i;
//
output
rezValid_o; //
//
reg
rezValid_o;
primare
incepere operatie de multiplicare
rezultat valid
(terminare multiplicare)
202
end
end
//modelarea iesirilor imediate ale automatului
assign ldRez_o = (stare == FINAL);
assign ldOp_o = (stare == INIT) & start_i;
assign decB_o = (stare == DEC);
assign ldAcc_o = (stare == ADD);
always @(posedge ck) begin
if (~reset_ni) begin
rezValid_o <= 1b0;
end
else begin
if (ldRez_o) begin
rezValid_o <= 1b1;
end
else begin
rezValid_o <= 1b0;
end
end
end
endmodule
Schemele la nivel RTL rezultate n urma sintezei sunt prezentate n figurile 5.44,
5.45 si 5.46.
5.9
Acest paragraf prezinta modelarea unei memorii RAM cu un singur port. Acesta este
un model comportamental. In simularile profesionale modelul trebuie mbunatatit cu
informatii despre constrangerile temporale.
203
204
Dir
in
in
in
in
in
in
out
Dimensiune
1
8
16
1
1
1
16
Semnificatie
Ceasul memoriei activ pe frontul pozitiv
Adresa memoriei
Datele de intrare n memorie
Semnal de selectie a memoriei
Semnal de validare a scrierii
Semnal de activare a iesirilor
Datele de iesire din memorie
Tabelul 5.4
Semnificatiile porturilor unei memorii cu un singur port.
memoriei sunt caracterizate prin formele de unda din figurile 5.47, respectiv 5.48:
n
V
module singlePortMem (
clk,
addr,
di,
205
ce,
we,
oe,
dout
);
parameter initLocation = "fisier";
// "fisier": date in fisier extern "memContent.dat"
// "zero": toate locatiile contin data=0
// "adresa": fiecare locatie contine data=adresa
// "x": toate locatiile initializate cu bx
// "aleatoriu": toate locatiile intializate aleatoriu
// declaratia porturilor
input
clk;
// ceasul memoriei
input[7:0]
addr; // bus de adrese
input[15:0] di;
// bus date de intrare
input
ce;
// semnal de selectie a memoriei
input
we;
// semnal de validare a scrierii
input
oe;
// semnal de activare a iesirii
output[15:0] dout; // bus date de iesire
reg[15:0]
dout;
// declaratia de memorie
reg [15:0] mem [0:255];
// memorie sincrona
always @(posedge clk) begin
if(ce) begin
if(we) begin
mem[addr] <= di;
// scrierea in memorie a datelor de pe
end
else begin
// bus-ul de intrare di
if(oe) begin
dout <= mem[addr]; // citirea din memorie
end
end
end
else begin
dout <= 16bz;
// cand memoria nu este selectata
// portul de date de iesire este in starea HighZ
end
end
integer i;
// initializarea memoriei
initial begin
if (initLocation == "fisier") begin
206
//
//
//
//
continutul
continutul
continutul
continutul
de
de
de
de
la
la
la
la
locatia
locatia
locatia
locatia
0
1
2
3
0000000000000100
0000000000000101
...
207
// continutul de la locatia 4
// continutul de la locatia 5
Dac
a initLocation="zero", toate locatiile memorie sunt initializate cu 0.
Dac
a initLocation="adresa", toate locatiile memorie sunt initializate cu valoarea adresei la care se afla.
Dac
a initLocation="x", toate locatiile memorie sunt initializate cu valoare
indiferenta "x".
Dac
a initLocation="aleatoriu", toate locatiile memorie sunt initializate cu
valori aleatorii.
Dac
a initLocation nu are nici una din valorile mentionate, se genereaza un
mesaj de eroare si se opreste simularea.
Task-ul de citire este prezentat n continuare:
task Read;
input[7:0] addr_task;
begin
// Adresa de unde se face citirea
addr <= addr_task;
// Semnalele de control setate pentru operatia de citire
we <= 1b0;
oe <= 1b1;
ce <= 1b1;
@(posedge clk);
#1
$display("%M %t NOTA: citire adresa=%d, data=%hH", $time,
addr_task, dout);
end
endtask
Apelul task-ului de citire este de forma:
Read(<adresa de citire>);
Task-ul de scriere este prezentat n continuare:
task Write;
input[7:0] addr_task;
input[15:0] di_task;
begin
$display("%M %t NOTA: scriere adresa=%d, data=%hH", $time,
addr_task, di_task);
// Adresa unde se face scrierea
addr <= addr_task;
208
Un model Verilog care foloseste task-urile prezentate mai sus este prezentat n
continuare:
n
T
module tstSinglePortMem();
reg
reg[7:0]
reg[15:0]
reg
reg
reg
wire[15:0]
clk;
addr;
di;
ce;
we;
oe;
dout;
//descrierea task-urilor
task Read;
...
endtask
task Write;
...
endtask
task Dump;
...
endtask
// valoarea initiala a ceasului
initial clk <= 0;
// generator de ceas
always #5 clk <= ~clk;
initial begin
@(posedge clk);
Dump("dumpMem.dat");
Read (8h00);
Read (8h01);
Read (8h02);
Read (8h03);
Write(8h00,16hFFF0);
Write(8h01,16hFF0F);
Write(8h02,16hF0FF);
Write(8h03,16h0FFF);
@(posedge clk);
$stop;
Dump("dumpMem.dat");
@(posedge clk);
$display("%M %t NOTA: Terminare simulare", $time);
$stop;
end
209
210
5.10
Modelarea multiplexoarelor
5.10.1
Multiplexorul 2:1 este un circuit combinational cu trei intrari (doua de date si una de
selectie) si o iesire. Tabelul de adevar al acestuia este prezentat n tabelul 5.5.
T
inand cont de setul de valori Verilog (0, 1, x, z), se poate concluziona ca tabelul
5.5 nu este complet. Practic, pentru ca setul de valori Verilog are patru valori distincte, ar trebui ca tabelul de adevar al circuitului multiplexor 2:1 sa aiba 43 = 64
linii.
Ce valoare logica are iesirea y daca intrarea sel=1bx? Ar trebui sa fie i0, i1 sau
1bx?
Ce valoare logica are iesirea y daca sel=1bx, i1=i0=1b0? Ar trebui sa fie 1b0
sau 1bx?
Pentru a evidentia diferentele dintre diferite tipuri de modelare, sunt prezentate
n continuare patru specificatii care modeleaza multiplexoare. Formele de unda corespunzatoare sunt prezentate n figura 5.49.
211
sel
0
0
0
0
1
1
1
1
i1
0
0
1
1
0
0
1
1
i0
0
1
0
1
0
1
0
1
y
0
1
0
1
0
0
1
1
Tabelul 5.5
Tabelul de adev
ar al circuitului multiplexor 2:1.
212
5.10.2
Multiplexor n bucl
a cu bistabil
Acest paragraf prezinta un caz de modelare RTL si la nivel de poarta logica pentru un
bistabil RS sincron. Bistabilul va fi implementat n tehnologie eASIC si va prezenta
n netlist-ul la nivel de poarta logica o instantiere de multiplexor. Comportamentul
multiplexorului va fi descris cu specificatia Verilog de primitiva, lucru care asigura o
viteza de simulare superioara, necesara simularilor la acest nivel.
Codul RTL este prezentat n continuare. Bistabilul are un semnal de reset sincron
global (care actioneaza asupra tuturor bistabilelor din sistem). In plus, exista doua
semnale de set si reset sincrone, particulare acestui bistabil. Conditia de set este
realizata ca un SI logic ntre doua semnale.
n
V
module srFf (
clk_i,
reset_ni,
rSync_i,
sSync1_i,
sSync2_i,
iesire_o
);
input
input
clk_i;
reset_ni;
213
input
input
input
output
rSync_i;
sSync1_i;
sSync2_i;
iesire_o;
reg iesire_o;
always @(posedge clk_i) begin
if (~reset_ni) begin
iesire_o <= 1b0;
end
else begin
if (sSync1_i && sSync2_i) begin
iesire_o <= 1b1;
end
else begin
if (rSync_i) begin
iesire_o <= 1b0;
end
end
end
end
endmodule
// set sincron
// reset sincron
n3 = clk_i;
n4 = reset_ni;
n5 = rSync_i;
n6 = sSync1_i;
n7 = sSync2_i;
iesire_o = n8;
srFf_cell_17796 srFf_cell_17796 (
.i3n(n8), .ms(n9), .xa(n6), .xb(n4), .xc1(N_VCC),
214
.xc2(n7), .ck(n3));
srFf_cell_17780 srFf_cell_17780 (
.x(n9), .xa(n4), .xb(n5), .xc1(n7), .xc2(n6));
endmodule
module srFf_cell_17796 (i3n, ms, xa, xb, xc1, xc2, ck);
//PLACED
//DUMMYPORT U7_nand2x.xc1
//DUMMYINST inv6xa_1
output i3n;
input ms, xa, xb, xc1, xc2, ck;
wire qn, mn, xn, xc;
wire x;
inv6xa inv6xa_1 (.x(x), .xn(xn));
inv8xb iesire_o_reg_inv8xb (.i3n(i3n), .i3(qn));
dffx iesire_o_reg_dffx (.qn(qn), .mn(mn), .ck(ck));
muxy iesire_o_reg_muxy (.mn(mn), .ms(ms), .m1(xn), .m0(qn));
lutx_7f U7_lutx (.xn(xn), .xa(xa), .xb(xb), .xc(xc));
nand2x U7_nand2x (.xc(xc), .xc1(xc1), .xc2(xc2));
// defparam U7_lutx.lut_data = 8h7f;
endmodule
module srFf_cell_17780(x, xa, xb, xc1, xc2);
//PLACED
//DUMMYPORT
//DUMMYINST u5333_muxy
output x;
input xa, xb, xc1, xc2;
wire xn, xc;
muxy u5333_muxy (.mn(mn), .ms(1b1), .m1(xn), .m0(1b1));
inv6xa U6_inv6xa (.x(x), .xn(xn));
lutx_02 U6_lutx (.xn(xn), .xa(xa), .xb (xb), .xc(xc));
nand2x U6_nand2x (.xc(xc), .xc1(xc1), .xc2(xc2));
// defparam U6_lutx.lut_data = 8h02;
endmodule
Se observa ca bistabilul a fost implementat n doua eCell-uri.
215
xa
rSync_i
xb
sSync1_i
sSync2_i
xc
8h02
sSync1_i
xa
reset_ni
xb
VCC
sSync2_i
xn
m1
d
xc
8h7f
iesire_o
m0
216
endprotect
endmodule
endcelldefine
Primitiva ce descrie comportamentul multiplexorul este:
primitive p_mux21 (q, data1, data0, dselect);
output q;
input data1, data0, dselect;
// FUNCTION : TWO TO ONE MULTIPLEXER
table
//data1 data0 dselect :
q
0
0
?
:
0 ;
1
1
?
:
1 ;
0
1
?
?
1
1
:
:
0 ;
1 ;
?
0
?
1
endtable
endprimitive
0
0
:
:
0 ;
1 ;
n
T
Pe situl cartii se gaseste mediul de simulare comparativa al modelelor RTL
si la nivel de porti logice.
Mai multe detalii despre tehnologia eASIC si bibliotecile de simulare si sinteza
complete se pot gasi pe situl firmei eASIC.
5.10.3
Multiplexor pe bus
217
data1,
sel,
out
);
input[7:0]
input[7:0]
input[7:0]
output[7:0]
data0;
data1;
sel;
out;
5.11
5.11.1
218
000H
PREINCARCARE(PA)
AUTOREFRESH(AR1,AR2)
INCARCARE REGISTRU MOD(LMR)
0
Initializare
Init_st
ShReg(17)
1
001H
1
NOP
nop_st
1
rf_rq
002H
2
act_st
5
004H
Refresh
Idle_act_st
6
Idle_arf_st
1
ACTIVARE
010H
NOP
020H
NOP
0
008H
AUTOREFRESH
arf_st
RQ
arf_term
oper_st
7
040H
Idle_1_st
8
NOP
Idle_2_st
9
NOP
Idle_3_st
NOP
0
200H
10
Idle_wr_st
WRITE / READ
Operatii
080H
100H
rwCrt
NOP
11
pr_st
400H
PREINCARCARE
reg
reg
reg
reg
idle2St;
idle3St;
idleWrSt;
prSt;
arfSt |
(idleArfSt & ~arTerm);
219
220
actSt;
221
222
223
end
// secventa de initializare SDRAM
assign lmr
= initShReg[17];
assign ar2
= initShReg[10];
assign ar1
= initShReg[3];
assign pa
= initShReg[1];
Semnalele de comanda ale memorie SDRAM sunt descrise pe baza starilor automatului si starii registrului de initializare. Toate iesirile din modul provin din
registru. Adresa si banca trimise spre memoria SDRAM provin din adresa clientului SDRAM sau sunt generate intern, n functie de starea automatului. Figura 5.54
prezinta schema rezultata din sinteza pentru logica iesirilor.
reg[11:0]
reg[1:0]
reg
reg
reg
reg
reg[31:0]
addr_o;
ba_o;
cs_no;
ras_no;
cas_no;
we_no;
dqEn;
224
225
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
we_no <= 1b1;
end
else begin
we_no <= ~(lmr | pa |
(operSt & ~rwnCrt) | prSt);
end
end
always @(posedge clk_i or negedge reset_ni) begin
if(~reset_ni) begin
dqEn <= 32b0;
end
else begin
dqEn <= {32{(~rwnCrt & (operSt | idle1St |
idle2St | idle3St))}};
end
end
Actiunea de remprospatare a continutului memoriei (refresh, n limba engleza)
este modelata cu ajutorul unui numarator care seteaza un bistabil pentru activarea
cererii de refresh spre automat. Bistablul este resetat cand automatul lanseaza cererea
de refresh spre memoria SDRAM. Figura 5.55 prezinta schema rezultata din sinteza
pentru circuitul de refresh.
reg
rfRq;
// cerere de refresh
reg[10:0]
reg[6:0]
226
227
end
end
// terminat starile IDLE dupa comanda de refresh
assign arTerm
= rfIdle[6];
// generator intervale de timp de refresh
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
rfCounter <= perRefresh_p;
end
else if(|rfCounter) begin
rfCounter <= rfCounter - 1;
end
else begin
rfCounter <= perRefresh_p;
end
end
// cerere refresh
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
rfRq <= 1b0;
end
else begin
if (~|rfCounter) begin
rfRq <= 1b1;
end
else begin
if (arfSt) begin
rfRq <= 1b0;
end
end
end
end
Interfata cu clientul SDRAM se face print-un set de registre care stocheaza tipul
actiunii (citire sau scriere) si adresa la care se cere accesul. Adresa accesata este
ulterior decodificata n banca, rand si coloana SDRAM. Confirmarea spre client este
trimisa pe baza starii automatului. Figura 5.56 prezinta schema rezultata din sinteza
pentru circuitul de interfatare dintre client si controllerul SDRAM.
reg
reg[1:0]
reg[11:0]
reg[7:0]
reg[3:0]
rwnCrt;
baCrt;
rowCrt;
colCrt;
ackDel;
228
229
end
// confirmare spre client
assign ack_o
= rwnCrt ? ackDel[3] :
(operSt | idle1St | idle2St | idle3St);
Legarea blocurilor functionale ntr-un modul este prezentata grafic n figura 5.57.
5.11.2
n
T
230
231
Mediu de testare
client
controller
memorie
SDRAM
SDRAM
SDRAM
monitor
protocol
Task-ul de scriere are ca parametrii adresa de scriere si patru date scrise n burst.
Task-ul de citire are ca parametrii adresa de citire si patru date asteptate n urma
citirii (pentru verificare).
In lipsa unor comenzi de citire/scriere este apelat task-ul break avand ca parametru numarul de perioade de tact n care nu se lanseaza nici o comanda.
// *** cerere de scriere **********************************
task write;
// parametrii formali ai task-ului
input[21:0] ad_t;
input[31:0] d0_t;
input[31:0] d1_t;
input[31:0] d2_t;
input[31:0] d3_t;
begin
// $display("%M %t NOTA: ad=%0d, d0=%0d, d1=%0d, d2=%0d, d3=%0d",
//
$time, ad_t, d0_t, d1_t, d2_t, d3_t);
rq_o
<= 1b1;
rw_no
<= 1b0;
addrClient_o <= ad_t;
data_o
<= d0_t;
@(posedge clk_i);
while (~ack_i)
@(posedge clk_i);
rq_o
<= 1b0;
rw_no
<= 1bx;
addrClient_o <= bx;
data_o
<= d1_t;
@(posedge clk_i);
232
data_o
<= d2_t;
@(posedge clk_i);
data_o
<= d3_t;
@(posedge clk_i);
end
endtask
// *** cerere de citire ************************************
task read;
// parametrii formali ai task-ului
input[21:0] ad_t;
input[31:0] d0_t;
input[31:0] d1_t;
input[31:0] d2_t;
input[31:0] d3_t;
begin
rq_o
<= 1b1;
rw_no
<= 1b1;
addrClient_o <= ad_t;
data_o
<= bx;
@(posedge clk_i);
while (~ack_i)
@(posedge clk_i);
rq_o
<= 1b0;
rw_no
<= 1bx;
addrClient_o <= bx;
if ((^(d0_t) !== 1bx) && (data_i !== d0_t)) begin
$display("%M %t EROARE: data 0 asteptata=%0d, citita=%0d",
d0_t, data_i);
$stop;
end
@(posedge clk_i);
if ((^d1_t !== 1bx) && (data_i !== d1_t)) begin
$display("%M %t EROARE: data 1 asteptata=%0d, citita=%0d",
d1_t, data_i);
$stop;
end
@(posedge clk_i);
if ((^d2_t !== 1bx) && (data_i !== d2_t)) begin
$display("%M %t EROARE: data 2 asteptata=%0d, citita=%0d",
d2_t, data_i);
$stop;
end
@(posedge clk_i);
if ((^(d3_t) !== 1bx) && (data_i !== d3_t)) begin
$display("%M %t EROARE: data 3 asteptata=%0d, citita=%0d",
d3_t, data_i);
$time,
$time,
$time,
$time,
233
$stop;
end
@(posedge clk_i);
end
endtask
// *** lipsa cerere ***************************************
task break;
// parametrii formali ai task-ului
input[31:0] nrClocks_t;
begin
rq_o
<= 1b0;
rw_no
<= 1bx;
addrClient_o <= bx;
data_o
<= bx;
repeat (nrClocks_t)
@(posedge clk_i);
end
endtask
Pentru o testare intensiva, task-urile pot fi apelate fie individual, fie n mod
repetat, fie n mod aleatoriu. In exemplul urmator clientul cere un acces de scriere
la adresa 0, urmat de o cerere de citire de la aceeasi adresa (cu asteptarea acelorasi
date). Ulterior, se lanseaza o simulare infinita a unor scrieri si citiri aleatorii. Pentru verificarea datelor citite, s-a optat pentru solutia scrierii unor date provenite din
bitii de adresa (n acest mod, se pot determina datele asteptate la citire n functie de
adresa accesata).
integer
reg[1:0]
reg[11:0]
reg[7:0]
reg[21:0]
crtVector = 1;
baTmp;
rowTmp;
colTmp;
adsTmp;
initial
begin
break(10);
// write(adresa, data0, data1, data2, data3);
// read (adresa, data0, data1, data2, data3);
// break (nrTacte);
// scriere si citire adresa 0
write(22h0, 0, 1, 2, 3);
break(5);
read (22h0, 0, 1, 2, 3);
break(5);
if (nrVectors_p === 0) begin
234
235
din SDRAM si o compara cu cea din memoria interna. Daca cele doua nu coincid
nseamna ca modulul testat nu functioneaza corect.
De remarcat faptul ca pentru scurtarea timpului de simulare si a memoriei alocate
de simulator se poate decide micsorarea artificiala a spatiului de memorie accesat de
catre client, fara ca aceasta sa necesite o modificare asupra controllerului SDRAM.
n
T
module monitor(
clk_i,
reset_ni,
// interfata client
rq_i,
ack_i,
rw_ni,
addrClient_i,
dataFromSdram_i,
dataToSdram_i
);
parameter
// semnal de ceas
// semnal de reset asincron, activ in 0
//
//
//
//
//
//
memSizeLog = 22;
input
clk_i;
input
reset_ni;
// interfata client
input
rq_i;
input
ack_i;
input
rw_ni;
input[21:0] addrClient_i;
input[31:0] dataFromSdram_i;
input[31:0] dataToSdram_i;
// stocarea adresei curente de scriere/citire
reg[21:0]
addrClientReg;
// matrice de memorie de referinta
reg[31:0]
mirrorMem[(1<<memSizeLog)-1:0];
reg[2:0]
wrPend;
// semnal activ pe durata burst-ului de scriere
reg[2:0]
rdPend;
// semnal activ pe durata burst-ului de citire
wire
wire
acceptWr; //
//
acceptRd; //
//
236
237
dataFromSdram_i);
$stop;
end;
end
else begin
if (rdPend[1]) begin
if (mirrorMem[addrClientReg+2] !== dataFromSdram_i) begin
$display("%M %t EROARE adresa=%d, dataExp=%h, dataSdram=%h.",
$time, (addrClientReg+2), mirrorMem[addrClientReg+2],\
dataFromSdram_i);
$stop;
end;
end
else begin
if (rdPend[2]) begin
if (mirrorMem[addrClientReg+3] !== dataFromSdram_i) begin
$display("%M %t EROARE adresa=%d,dataExp=%h,dataSdram=%h.",
$time, (addrClientReg+3), mirrorMem[addrClientReg+3],
dataFromSdram_i);
$stop;
end;
end
end
end
end
// initializare memorie de referinta
integer i;
integer sfertSpatiuAdresare = (1<<(memSizeLog-2));
initial
for (i=0;i<=(sfertSpatiuAdresare-1);i=i+1) begin
mirrorMem[i]
<= {16b0, i[15:0]};
mirrorMem[i+sfertSpatiuAdresare]
<= {16b0, i[15:0]};
mirrorMem[i+2*sfertSpatiuAdresare] <= {16b0, i[15:0]};
mirrorMem[i+3*sfertSpatiuAdresare] <= {16b0, i[15:0]};
end
endmodule
Anexa A
MODELAREA SPICE A
UNUI INVERSOR CMOS
A.1
Pentru modelarea SPICE a unui circuit CMOS trebuie alese modelele potrivite pentru tranzistoarele NMOS si PMOS. Instantierea unui tranzistor MOS ntr-un model
SPICE se face folosind urmatoarea sintax
a:
<numeInst> <nodDrena> <nodGrila> <nodSursa> <nodSubstrat> <model>
L=<lungime> W=<latime>
Numele tranzistorului MOS, <numeInst>, trebuie sa nceapa cu litera M.
<nodDrena> <nodGrila> <nodSursa> <nodSubstrat> sunt numerele nodurilor
pentru drena, poarta, sursa si substrat. <model> este numele modelului de tranzistor
folosit (descris n continuare). L si W sunt lungimea si latimea portii, exprimate n
metri.
SPICE pune la dispozitie 4 modele de dispozitive MOSFET, care difera prin
modul de descriere a caracteristicilor (vezi sectiunea 1.5.1.2 din volumul I). Parametrul LEVEL (nivel, n limba engleza) specifica modelul care trebuie folosit:
LEVEL=1: Model bazat pe ecuatiile dispozitivului idealizat, fara considerarea
tuturor efectelor secundare (efecte de ordin 2);
LEVEL=2: Model fizic, care include majoritatea efectelor secundare;
LEVEL=3: Semi-Empiric - ncearca sincronizarea curbelor calculate cu cele
masurate;
239
240
LEVEL=4: Empiric.
Pentru modelele de nivelurile 1, 2 si 3, caracteristicile de curent continuu sunt
definite de parametrii tranzistorului: VTO, KP, LAMBDA, PHI si GAMMA. Acesti
parametri sunt calculati de SPICE, daca parametrii de proces (NSUB, TOX, ...) sunt
disponibili, dar valorile definite de utilizator suprascriu valorile calculate. In tabelul
A.2 se prezinta lista completa a parametrilor dispozitivelor MOSFET pentru nivelurile
1, 2 si 3.
In SPICE, modelul unui tranzistor are sintaxa:
.MODEL <nume_model> <tip_tranzistor> <lista_parametri>
Parametrii tipici de nivel 3 ai unor tranzistoare MOS n tehnologia 1.2 m sunt:
Modelul unui tranzistor NMOS
.MODEL CMOSN NMOS LEVEL=3 PHI=0.600000 TOX=2.1200E-08
+XJ=0.200000U
+TPG=1 VTO=0.7860 DELTA=6.9670E-01 LD=1.6470E-07 KP=9.6379E-05
+UO=591.7 THETA=8.1220E-02 RSH=8.5450E+01 GAMMA=0.5863
+NSUB=2.7470E+16 NFS=1.98E+12 VMAX=1.7330E+05 ETA=4.3680E-02
+KAPPA=1.3960E-01 CGDO=4.0241E-10 CGSO=4.0241E-10
+CGBO=3.6144E-10 CJ=3.8541E-04 MJ=1.1854 CJSW=1.3940E-10
+MJSW=0.125195 PB=0.800000
Modelul unui tranzistor PMOS
.MODEL CMOSP PMOS LEVEL=3 PHI=0.600000 TOX=2.1200E-08
+XJ=0.200000U
+TPG=-1 VTO=-0.9056 DELTA=1.5200E+00 LD=2.2000E-08 KP=2.9352E-05
+UO=180.2 THETA=1.2480E-01 RSH=1.0470E+02 GAMMA=0.4863
+NSUB=1.8900E+16 NFS=3.46E+12 VMAX=3.7320E+05 ETA=1.6410E-01
+KAPPA=9.6940E+00 CGDO=5.3752E-11 CGSO=5.3752E-11
+CGBO=3.3650E-10 CJ=4.8447E-04 MJ=0.5027 CJSW=1.6457E-10
+MJSW=0.217168 PB=0.850000
Semnul + la nceputul liniei n modelul SPICE reprezinta o continuare a liniei
anterioare.
A.2
O schema electrica pentru studiul caracteristicilor IDS (VDS ) ale tranzistorului NMOS
este prezentata n figura A.1.
Pentru descrierea SPICE a acestui circuit se foloseste modelul urmator:
NR
1
2
Nume
LEVEL
VTO
3
4
5
6
KP
GAMMA
PHI
LAMBDA
7
8
9
RD
RS
CBD
10
CBS
11
IS
12
PB
13
CGSO
14
CGDO
15
CGBO
16
RSH
17
CJ
18
MJ
19
CJSW
20
MJSW
21
JS
Parametru
identificator de nivel
tensiunea de prag la polarizare
zero
factorul de castig al procesului
parametrul prag de substrat
potentialul la suprafata
modulatia lungimii canalului
(doar la MOS1 si MOS2)
rezistenta ohmica de drena
rezistenta ohmica de sursa
capacitatea jonctiunii
drena-substrat (la polarizare
de substrat zero)
capacitatea jonctiunii
sursa-substrat (la polarizare
de substrat zero)
curentul de saturatie al
jonctiunii de substrat
potentialul jonctiunii de
substrat
capacitatea de suprapunere
grila-sursa pe unitatea de
latime a canalului
capacitatea de suprapunere
grila-drena pe unitatea
de latime a canalului
capacitatea de suprapunere
grila-substrat pe unitatea de
lungime a canalului
rezistenta pe patrat a zonelor
difuzate drena si sursa
capacitatea pe metru pentru
jonctiunea de substrat (la
polarizare de substrat zero)
coeficientul de gradare a
jonctiunii de substrat
capacitatea de perete lateral a
jonctiunii de substrat pe metru
(la polarizare de substrat zero)
coeficientul de gradare pentru
peretele lateral a jonctiunii
de substrat
curentul de saturatie al
jonctiunii de substrat
241
Unit.
V
Implicit
1
0.0
Ex.
A/V2
V1/2
V
1/V
2.0e-5
0.0
0.6
0.0
3.1e-5
0.37
0.65
0.02
ohm
ohm
F
0.0
0.0
0.0
1.0
1.0
20fF
0.0
20fF
1.0e-14
1.0e-15
0.8
0.87
F/m
0.0
4.0e-11
F/m
0.0
4.0e-11
F/m
0.0
2.0e-10
ohm/[]
0.0
10.0
F/m2
0.0
2.0e-4
0.5
0.5
F/m
0.0
1.0e-9
0.50
0.33
1.0
Tabelul A.1
Parametrii modelului SPICE a tranzistorului MOS (partea nt
ai).
242
22
23
TOX
NSUB
24
25
NSS
NFS
26
TPG
27
XJ
28
29
30
LD
UO
UCRIT
31
UEXP
32
UTRA
33
VMAX
34
NEFF
35
36
KF
AF
37
FC
38
DELTA
39
THETA
40
ETA
41
KAPPA
42
TNOM
m
1/cm3
1.0e-7
0.0
1.0e-7
4.0e15
1/cm2
1/cm2
0.0
0.0
1.0e10
1.0e10
1.0
0.0
1M
m
cm2 /Vs
V/cm
0.0
600
1.0e4
0.8M
700
1.0e4
0.0
0.1
0.0
0.3
m/s
0.0
5.0e4
1.0
5.0
0.0
1.0
1.0e-26
1.2
0.5
0.0
1.0
1/V
0.0
0.1
0.0
1.0
0.2
0.5
27
50
Tabelul A.2
Parametrii modelului SPICE a tranzistorului MOS (partea a doua).
243
244
A.3
Dupa ce modelele tranzistoarelor folosite au fost definite (sau alese dintr-o biblioteca
de tehnologie), se poate descrie circuitul de studiat. Descrierea SPICE a inversorului
CMOS urmareste schema din figura A.3.
Modelul SPICE este urmatorul:
* Modelul tranzistorului NMOS
.MODEL CMOSN NMOS LEVEL=3 PHI=0.600000 TOX=2.1200E-08 XJ=0.200000U
+TPG=1 VTO=0.7860 DELTA=6.9670E-01 LD=1.6470E-07 KP=9.6379E-05
+UO=591.7 THETA=8.1220E-02 RSH=8.5450E+01 GAMMA=0.5863
+NSUB=2.7470E+16 NFS=1.98E+12 VMAX=1.7330E+05 ETA=4.3680E-02
+KAPPA=1.3960E-01 CGDO=4.0241E-10 CGSO=4.0241E-10
+CGBO=3.6144E-10 CJ=3.8541E-04 MJ=1.1854 CJSW=1.3940E-10
+MJSW=0.125195 PB=0.800000
* Modelul tranzistorului PMOS
.MODEL CMOSP PMOS LEVEL=3 PHI=0.600000 TOX=2.1200E-08 XJ=0.200000U
+TPG=-1 VTO=-0.9056 DELTA=1.5200E+00 LD=2.2000E-08 KP=2.9352E-05
+UO=180.2 THETA=1.2480E-01 RSH=1.0470E+02 GAMMA=0.4863
245
V DD
V DD
C SBp
C GSp
pMOS
nMOS
D
C DBp
C DBn
C GDp
C GDn
vI
vO
iDp vO
vI
vI
iC
D
pMOS
iDn
nMOS
S
C GSn
C SBn
C COX
CL
C GB
a)
b)
Figura A.3 Inversor CMOS.
A.4
246
Factorul de merit.
A.4.1
Nivelurile de tensiune
60000ns,0V r
VIL
VIH
VOL
VOH
=
=
=
=
A.4.2
247
1.75 V
2.5 V
0.8 V
4.6 V
Marginea de zgomot
A.4.3
Timpul de propagare
Timpul de propagare se determina folosind diferite scenarii pentru factorul de ncarcare de iesire. Pentru aceasta se adauga o capacitate pe sarcina. Bibliotecile de
tehnologie folosite pentru sinteza circuitelor integrate digitale folosesc un model de
caracterizare a timpilor de propagare n functie de timpul de tranzitie a semnalului de
intrare si a capacitatii totale de iesire. Timpul de tranzitie reprezinta timpul n care
semnalul de intrare si modifica amplitudinea ntre 10 si 90 procente din tensiunea de
alimentare. Capacitatea totala de iesire reprezinta suma capacitatilor pe care circuitul
de studiat genereaza semnalul de iesire.
Un exemplu de astfel de matrice pentru caracterizarea timpilor de propagare este:
lu_table_template(inv_template) {
variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance;
index_1 ("1.000, 2.000, 3.000");
index_2 ("0.100, 0.400, 0.700");
}
Rezulta ca, pentru o caracterizare completa, este necesara o masurare a timpilor
de propagare folosind fiecare din combinatiile timpului de tranzitie a semnalului de
intrare si capacitatii totale de iesire.
Daca timpul de tranzitie a semnalului de intrare este 1ns si capacitatea de iesire
este de 0.1 pF, modelul SPICE care masoara timpii de propagare ai inversorului
CMOS este urmatorul:
* instantierea tranzistoarelor MOS care formeaza inversorul CMOS
M1 OUT IN GND GND CMOSN L=4U W=3U
M2 OUT IN VDD VDD CMOSP L=4U W=6U
* Instantierea capacitatii de sarcina (0.1 pF)
C OUT GND 0.1p
248
Figura A.5 Diagramele de tensiune la intrare (a) si la iesire (b) ale inversorului CMOS.
600ns,5V 601ns,0V r
249
de
de
de
de
tranzitie
tranzitie
propagare
propagare
low-high:
high-low:
low-high:
high-low:
tlh = 3.45 ns
thl = 1.86 ns
tplh = 1.82 ns
tphl = 1.22 ns
1.0969E-08
targ=
7.2840E-08
trig=
6.1871E-08
250
thl
tplh
tphl
=
=
=
5.8944E-09
5.4046E-09
3.3103E-09
targ=
targ=
targ=
3.7388E-08
6.5905E-08
3.3810E-08
trig=
trig=
trig=
3.1493E-08
6.0500E-08
3.0500E-08
A.4.4
Consumul de putere
251
Curentul de intrare este foarte mic, deci puterea consumata la intrare este neglijabila.
A.4.5
Factorul de merit
= 1.52ns
Anexa B
CUVINTE CHEIE
REZERVATE ALE
VERILOG HDL
Limbajul Verilog are un numar de cuvinte cheie rezervate. Acestea sunt scrise ntotdeauna cu minuscule. Cuvintele rezervate nu pot fi folosite pentru a desemna
identificatori.
always
bufif0
cmos
edge
endfunction
event
function
inout
medium
nmos
or
primitive
rcmos
rpmos
small
strong1
time
triand
vectored
while
and
bufif1
deassign
else
endmodule
for
highz0
input
module
nor
output
pulldown
reg
rtran
specify
supply0
tran
trior
wait
wire
assign
case
default
endspecify
endprimitive
force
highz1
integer
macromodule
not
parameter
pullup
release
rtranif0
specparam
supply1
tranif0
trireg
wand
wor
253
begin
casex
defparam
end
endtable
forever
if
join
nand
notif0
pmos
pull0
repeat
rtranif1
strength
table
tranif1
tri0
weak0
xnor
buf
casez
disable
endcase
endtask
fork
initial
large
negedge
notif1
posedge
pull1
rnmos
scalared
strong0
task
tri
tri1
weak1
xor
Anexa C
MEMENTO LIMBAJ
VERILOG
Aceasta anexa prezinta limbajul Verilog foarte condensat. S-au inclus doar acele
specificatii folosite frecvent n modelarea sistemelor digitale ce urmeaza a fi sintetizate.
Forma grafica permite copierea paginii pentru o referinta rapida.
Versiunea electronica poate fi accesata de pe situl cartii:
http://vega.unitbv.ro/electronica_digitala
255
256
Anexa D
CONT
INUT SIT CARTE
Situl web al acestei cartii este:
http://vega.unitbv.ro/electronica_digitala
Pe situl cartii pot fi gasite:
Modelele Verilog ale tuturor circuitelor prezentate n carte.
Mediile de testare Verilog ale tuturor circuitelor prezentate n carte.
Bibliotecile de simulare specifice tehnologiei eASIC.
Forma electronica a paginii cu descrierea condensata a limbajului Verilog.
Referinta web la o versiune de evaluare a unui simulator Verilog. O licenta
de evaluare pentru 30 de zile se poate obtine urmand indicatiile din pagina de
web si folosind parola:
ElectronicaDigitalaSimulatorHDL
257
Bibliografie
[1] J. Bhasker. A Verilog HDL Primer, 2nd Edition. Star Galaxy Publishing, ISBN
0-9650391-7-X, 1999.
[2] eASIC Corp. www.easic.com. Referinta web.
[3] Mentor Graphics. www.model.com. Referinta web.
[4] Micron Technology Inc. www.micron.com. Referinta web.
[5] Synplicity Inc. www.synplicity.com. Referinta web.
[6] Open Verilog International. OVI Verilog HDL LRM Version 1.0. 1991.
[7] Z. Navabi. Verilog Digital System Design. McGraw-Hill, ISBN 0-07-047164-9,
1999.
[8] D. Smith. HDL Chip Design. Doone Publications, ISBN 0-9651934-3-8, 1996.
[9] S. Sutherland. The Verilog PLI Handbook, 1th Edition. Kluwer Academic Publisher, ISBN 0-7923-8489-X, 1999.
[10] D. Thomas, P. Moorby. The Verilog Hardware Description Language, 4th Edition.
Kluwer Academic Publisher, ISBN 0-7923-8166-1, 1998.
259
Index
abreviere
ASIC, 3
EDA, 6
HDL, 1
LRM, 7
PLI, 127
RTL, 2
VHDL, 2
baze de numeratie, 27
cod Verilog
codificator, 83
decodificator, 43, 84
multiplexor, 1820, 81
numarator, 13
registru cu functii multiple, 55
sumator, 1517
vot majoritar, 12
comentarii // /* */, 25
concurenta evenimentelor, 7
directive
define/undefine, 63
ifdef/ifndef/else/endif, 65
include, 66
timescale, 6, 66
functii sistem
random, 123
time, 123
functionalitate
automate
cu ntarziere, 96
imediate, 96
Mealy, 96
Moore, 96
bistabil, 86
bistabil T, 88
codificator, 83
decodificator, 84
latch, 86
multiplexor, 81
glitch, 13
ierarhie
accesarea semnalelor, 126
modul memorie, 111
mediu de simulare/testare, 21
model SPICE
inversor CMOS, 240
tranzistor NMOS, 240
tranzistor PMOS, 240
modelare
automate sincrone, 94
bistabil D, 86
bistabil T, 88
circuite logice combinationale
always, 80
assign, 79
codificator, 81
cu tranzistoare definite n limbaj, 115
decodificator, 84
latch, 85
memorii, 107
multiplexor, 81
numarator, 90
porti logice definite n limbaj, 113
primitive definite de utilizator, 124
reset sincron/asincron, 87
modul, 7, 25
netlist, 2, 157, 213
numere aleatorii, 123
one-hot, 217
260
INDEX
proiectare
bottom-up, 3
top-down, 4
261
write, 119
Verilog, 1, 133
sintaxa
always, 46
assign, 44
descriere modul, 9
functie, 105
initial, 46
instantiere modul, 11
specificatii secventiale, 47
task, 104
specificatii concurente
always, 46
assign, 44
generate, 109
initial, 46
specificatii secventiale
atribuire, 47
blocanta =, 48
neblocanta <=, 49
control temporal, 59
ntarziere, 60
evenimente (posedge/negedge), 61
if, 53
iterative
for, 58
forever/disable, 57
repeat, 58
while, 58
lista de senzitivitati, 80
selectie
case, 56
casex, 56
casez, 56
task, 207
task-uri sistem
display, 119
finish, 122
fopen/fclose/fmonitor/fdisplay/fstrobe/fwrite,
120
monitor, 119
readmemb/readmemh, 120
stop, 122
strobe, 119
verificari temporale, 122