Sunteți pe pagina 1din 271

Dan Nicula

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

Inca o pagina ce va fi nlocuita. IV

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

In prezent, Verilog este un limbaj folosit n toate etapele de proiectare a circuitelor


integrate digitale:
specificatii;
modelarea RTL;
generare de vectori de test;
mediu de simulare;
module de monitorizare/verificare;
netlist post-sintez
a;
biblioteci de componente specifice tehnologiei;
model temporal cu parametrii actualizati conform implement
arii;
documentare.
Pentru un utilizator care nvat
a pentru prima oar
a un limbaj de descriere hardware, alegerea Verilog este foarte justificat
a. Simplitatea si apropierea acestuia de
hardware permit utilizatorului ncep
ator at
at concentrarea asupra proiect
arii arhitecturale, c
at si satisfactia unei eficiente a proiect
arii. Utilizatorii avansati g
asesc n
Verilog satisfactia unui limbaj matur, folosit n mod curent pentru proiectarea unor
circuite integrate reale.
Pentru utilizatorii ncep
atori, acest volum prezint
a o pagina cu limbajul Verilog
condensat, pagin
a ce se doreste a fi o referint
a rapid
a pentru proiectantul Verilog
HDL.
Utilizatorii avansati pot g
asi n aceast
a carte solutii eficiente, optimizate pentru
implementare hardware, la probleme ce par simple la nivel algoritmic. Modelarea
pentru sintetizabilitate si modelarea pentru obtinerea unui circuit care s
a functioneze
la frecvent
a maxim
a sunt dou
a idei pe care s-a concentrat acest volum.
Toate portiunile de cod si mediile de testare asociate pot fi accesate pe situl c
artii.
La aceeasi adres
a se g
asesc indicatii pentru obtinerea unei licente de evaluare a unui
simulator Verilog. Situl web al acestei c
artii este:
http://vega.unitbv.ro/electronica_digitala
Anexa din finalul acestui volum prezint
a simularea unei porti inversoare n SPICE.
Anexa este realizat
a cu contributia dl. Corneliu ZAHARIA.
Acest volum este rodul anilor de predare a cursurilor de Limbaje de descriere
hardware si Proiectarea circuitelor integrate, la specializarea Ingineria Calculatoarelor de la Universitatea TRANSILVANIA din Brasov. Experienta contactului cu
lumea real
a a proiectantilor de circuite integrate digitale a fost asigurat
a prin participarea la activitatea de cercetare si dezvoltare a firmei eASIC (http://www.easic.com).
Probleme practice avansate, prezentate n ultimul capitol al acestui volum, au fost
nt
alnite n activitatea curent
a la aceast
a firm
a.
Brasov, Septembrie 2005.

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

2 FUNDAMENTELE LIMBAJULUI VERILOG HDL


2.1 Conventii lexicale
2.2 Structura codului Verilog
2.3 Setul de valori
2.3.1 Numere ntregi
2.3.2 Numere reale
2.3.3 Siruri
2.4 Tipuri de date si obiecte
2.5 Operatori
2.5.1 Operatori aritmetici
2.5.2 Operatori relationali
2.5.3 Operatori de egalitate
2.5.4 Operatori logici
2.5.5 Operatori logici pe vectori
2.5.6 Operatori de reducere
2.5.7 Operatori de deplasare
2.5.8 Operator conditional
2.5.9 Operatori de concatenare si replicare
2.6 Specificatii concurente
2.7 Specificatii secventiale
2.7.1 Specificatii de atribuire secventiale
2.7.2 Specificatii conditionale
2.7.3 Specificatii de selectie
2.7.4 Specificatii de iteratii
2.7.5 Specificatii de control temporal

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

3 MODELAREA CIRCUITELOR ELEMENTARE


3.1 Circuite combinationale
3.1.1 Modelarea circuitelor logice cu assign
3.1.2 Modelarea circuitelor logice cu always
3.2 Circuite de multiplexare
3.3 Codificator/decodificator
3.4 Latch D
3.5 Bistabil D/RS
3.6 Bistabil T/JK
3.7 Numaratoare sincrone
3.8 Automate secventiale sincrone
3.8.1 Semi-automat descris cu o singura specificatie
3.8.2 Modelarea iesirilor automatelor
3.8.3 Modelarea automatelor ca registru de stare si circuit
combinational
3.8.4 Automat cu stari codificate one-hot

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

Anexa B CUVINTE CHEIE REZERVATE ALE VERILOG HDL


Anexa C MEMENTO LIMBAJ VERILOG
Anexa D CONT
INUT SIT CARTE

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

cod sursa Verilog;

Sn

descrierea sintaxei unei specificatii Verilog;

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?

cana Gateway Design System Corporation ntre 1983-1985.


Succesul de care s-a bucurat simulatorul Verilog (Verilog-XL) produs de Gateway
Design Automation a determinat o crestere rapida a acestei firme. Ca efect, n 1989,
Cadence Design Systems (cea mai mare firma din domeniul productiei de software
pentru suportul proiectarii de circuite integrate) a achizitionat atat firma Gateway
Design Automation, cat si limbajul Verilog HDL produs de catre aceasta.
In 1990, Cadence Design Systems a decis deschiderea limbajului Verilog HDL catre
public. In 1991, se formeaza organizatia OVI (Open Verilog International) cu scopul
de a promova si standardiza limbajul Verilog.
Verilog HDL este standardizat cu numarul IEEE-1364. In plus, acest standard
defineste o colectie de rutine software care permit interfatarea dintre Verilog si alte
programe (de obicei C). Colectia de rutine este cunoscuta sub numele de PLI (Programming Language Interface).
Standardizarea Verilog a determinat aparitia unor mici companii care ofereau simulatoare Verilog. Exista simulatoare care accepta descrieri mixte Verilog si VHDL.

1.2

De ce HDL?

Se pot remarca doua scopuri ale modelarii unui sistem digital:


Realizarea sistemului cu cost minim ntr-un timp scurt si
Evitarea erorilor de proiectare.
Primul motiv nu mai are nevoie de nici un fel de comentariu. Viteza de crestere
extrem de mare pentru domeniul circuitelor integrate este unanim recunoscuta. Orice
ntarziere a aparitiei unui produs nou pe piata poate aduce companiei producatoare
pierderi nsemnate.
Al doilea motiv nu este foarte usor de acceptat de catre cei mai familiarizati cu
dezvoltarea de produse software. Mai n gluma, mai n serios, se poate spune ca:
Hard-ul nu-i ca soft-ul. O greseala gasita tardiv n software, chiar dupa ce produsul
a fost livrat utilizatorului final poate fi usor remediata cu o noua versiune sau o
peticire (patch, n limba engleza). Noua versiune se poate distribui dintr-un sit
de web, fara costuri prea mari pentru producatorul de software.
In general, n hardware, greseala costa mult mai mult decat n software. Pentru un
circuit dedicat pentru o aplicatie (ASIC = Application Specific Integrated Circuit),
repararea unei greseli poate nsemna refacerea integrala a circuitului si suportarea
integrala a costurilor extrem de mari de productie.
Versiunile alpha sau beta din productia de software sunt nlocuite cu mii de
ore de verificare automata n productia de hardware. Toate procedurile de verificare
ale circuitelor integrate contemporane se bazeaza pe existenta HDL si a modelelor
textuale.
Derularea unui proiect pornind de la descrierea sa schematica presupune utilizarea unei metodologii de proiectare de jos n sus (bottom-up, n limba engleza).
Metodologia bottom-up presupune desenarea schemei modulelor elementare (cu simboluri de primitive existente ntr-o biblioteca de tehnologie) si ulterior conectarea acestora pentru a forma sistemul. Este de neconceput aceasta abordare pentru proiectarea
unui sistem mare, cum ar fi un procesor.

CAPITOLUL 1. INTRODUCERE

Metodologia de proiectare a sistemelor digitale actuale, de mari dimensiuni este o


metodologie de sus n jos (top-down, n limba engleza). Metodologia top-down
presupune modelarea sistemului la nivel nalt (comportamental) nainte de a defini
detaliile de implementare. Cateva din avantajele acestei metodologii sunt precizate
n continuare:
Sistemele digitale actuale nu mai pot fi st
ap
anite prin descriere schematic
a. Limbajele HDL ofera suport pentru metodologia de proiectare topdown.
Posibilitatea corect
arii greselilor de conceptie n faze foarte timpurii.
Avand un model al ntregului sistem, se poate evalua functionarea acestuia n
conexiune cu alte circuite. De exemplu, se poate simula functionarea unui ntreg
produs realizat sub forma de circuite integrate montate pe un cablaj imprimat,
chiar daca unele componente nu sunt realizate.
Multe sisteme actuale nu sunt exclusiv hardware, ci hardware - software. Existenta unui model de simulare al sistemului hardware nainte ca
acesta sa fie realizat fizic, permite munca n paralel a echipelor de dezvoltare de
software si de hardware. Prin aceasta, dezvoltarea de software este suprapusa n
timp peste dezvoltarea de hardware. Mai mult, se pot testa programele software
mpreuna cu modelul de simulare hardware.
Posibilitatea partaj
arii proiect
arii si a lucrului n echip
a. Fiecare echipa
se poate concentra pe implementarea modulului ce i-a fost atribuit, avand totodata la dispozitie un model de simulare, de referinta, a ntregului sistem.
Independent
a fat
a de tehnologia de implementare. De multe ori se
doreste conversia unui proiect dintr-o tehnologie n alta. Motivele sunt diverse: realizarea unui prototip cu dispozitive programabile nainte de lansarea n
productie ca un circuit specific sau realizarea aceluiasi produs ntr-o tehnologie
mai moderna sau mai ieftina. Conversia tehnologiei este posibila prin reutilizarea modelului HDL.
Reutilizarea codului. Module cu o functie specifica pot fi utilizate de catre
un proiectant n mai multe produse sau chiar pot fi vandute ca module separate.
De exemplu, proiectantul unui circuit cu acces USB va putea decide preluarea
unui controller USB produs de alta firma, concentrandu-se pe aspectele specifice
ale circuitul sau.
In figura 1.1 este reprezentata grafic metodologia de proiectare top-down a circuitelor integrate digitale. Se remarca faptul ca descrierea textuala n HDL este
prezenta n toate etapele de proiectare.
Specificatii. Uneori se includ portiuni de cod HDL n specificatii pentru a se
exemplifica functia unui modul.
Modelarea RTL. Codul scris de proiectant se verifica prin simulare, iar ulterior
serveste ca intrare pentru programele de sinteza de hardware. Aceasta este etapa
principala de proiectare a sistemului digital.

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

Figura 1.1 Reprezentarea grafic


a a metodologiei de proiectare top-down a circuitelor
integrate digitale. Pozitia HDL n cadrul acestei metodologii.

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

Verilog, ca un limbaj de descriere hardware, are caracteristici conceptual diferite de


cele ale limbajelor de programare (software). Principalele caracteristici ale HDL sunt
aspectul temporal si concurenta evenimentelor.

1.3.1

Aspectul temporal

Orice componenta hardware are un timp de propagare. Transferul datelor ntre


diferite componente hardware se face prin sarme de conexiune care au si ele o anumita ntarziere. Valoarea si combinarea acestor ntarzieri determina functionarea
sau nu a circuitului modelat, la frecventa necesara.
Variabilele (semnalele) Verilog modeleaza sarmele de interconexiune ale modulelor.
Din acest motiv, specificatiile de atribuire de semnal pot modela si ntarzierile. In
Verilog, unitatile de timp sunt relative, raportate la unitatea fizica de timp specificata
prin directiva timescale.
Circuitele logice combinationale pot fi modelate tinand cont de ntarzierile existente. Ca exemplu, se prezinta modelul structurii interne a unui multiplexor, modelat
cu porti logice cu ntarzieri asociate.
// #<N> = <N> unitati de timp
assign #1 s_n = ~s;
// ~ simbolul operatorului logic NOT
assign #2 w0 = i0 & s_n;
// & simbolul operatorului logic AND

1.3. Terminologia Verilog

assign #2 w1
assign #2 y

1.3.2

= i1 & s;
= w0 | w1;

// | simbolul operatorului logic OR

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;

Pentru a usura munca proiectantului de hardware (care este tentat sa aiba o


gandire algoritmica secventiala), limbajul Verilog prevede existenta unei specificatii
concurente care nglobeaza specificatii secventiale. Specificatia always este o specificatie concurenta. Specificatiile ce apar n corpul acesteia sunt specificatii secventiale
(ordinea n care apar acestea n codul sursa este relevanta). Executia specificatiei
always consta n executarea secventiala a tuturor specificatiilor continute de aceasta
pana la sfarsit sau pana la aparitia unei specificatii de ntarziere.

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

algoritmic: un model care implementeaz


a un algoritm al proiectului prin constructii de nivel nalt ale limbajului;
RTL: un model care descrie curgerea datelor ntre registre si modul de procesare a acestora;
nivel de poart
a: un model care descrie portile logice si conexiunile dintre porti
logice ntr-un proiect;
nivel de comutare: un model care descrie tranzistoarele si nodurile de stocare
(a informatiei) dintr-un dispozitiv si conexiunile dintre ele.
Blocul elementar de constructie n Verilog HDL este modulul. Formatul modulului
faciliteaz
a proiectarea top-down si bottom-up. Un modul contine modelul unui
proiect sau a unei p
arti de proiect. Modulele pot ncorpora alte module pentru a forma
un model ierarhic care descrie cum se includ componentele unui proiect n ansamblul
proiectului. Constructiile Verilog HDL, asa cum sunt declaratiile si specificatiile, sunt
incluse n module. Limbajul Verilog HDL comportamental este un limbaj structurat
si procedural, la fel ca limbajul de programare C.
Constructiile comportamentale ale limbajului sunt utilizate n cadrul modelelor
algoritmice si RTL. Limbajul comportamental are urm
atoarele capabilit
ati:
proceduri structurate pentru executie secvential
a sau concurent
a;
controlul explicit al timpului la care se activeaz
a o procedur
a, specificat at
at de
expresii ce desemneaz
a nt
arzieri, c
at si de schimb
arile valorii care determin
a
evenimente;
evenimente desemnate explicit s
a determine activarea si dezactivarea actiunilor
n cadrul altor proceduri;
constructii procedurale pentru operatii conditionale, de decizie, de selectie sau
de iteratii;
proceduri denumite task-uri care pot avea parametrii si durate non-zero;
proceduri denumite functii care permit definirea unor noi operatori;
operanzi aritmetici, logici, pe biti si de reducere pentru constructia de expresii.
Constructiile structurale ale Verilog HDL sunt utilizate pentru modelele la nivel
de poart
a si la nivel de comutare. Limbajul structural are urm
atoarele capabilit
ati:
un set complet de primitive combinationale;
primitive pentru poart
a de transmisiune si dispozitive rezistive;
abilitatea de a modela structuri MOS.

In Verilog HDL, acuratetea model


arii structurale este mbun
at
atit
a de specificatii
de nt
arzieri prin primitive si preciz
ari ale t
ariei porturilor de iesire. Valorile semnalelor pot avea diferite t
arii si o gam
a complet
a de valori ambigue pentru a reduce
pesimismul conditiilor necunoscute.

1.3. Terminologia Verilog

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

<declaratie_parametru>: Parametrul este o constanta de modul care poate


avea o valoare implicita ce poate fi modificata n momentul instantierii modulului. Doua instante ale aceluiasi modul pot avea valori diferite ale unui parametru.
Modificarea parametrului se poate face cu <asociere_parametru_valoare> sau
cu <redefinire_parametru>.
Exemple:
//Modificarea parametrului prin <asociere_parametru_valoare>
sumator #(8) U1Sumator (...); // instanta de sumator pe 8 biti
sumator #(4) U2Sumator (...); // instanta de sumator pe 4 biti
//Modificarea parametrului prin <redefinire_parametru>
defparam U2Sumator.width = 16;
sumator U2Sumator (...);
// instanta de sumator pe 16 biti
<declaratie_port_intrare>, <declaratie_port_iesire>,
<declaratie_port_bidirectional>: Declaratiile directiei si ale dimensiunilor
porturilor.
Exemple:
input
input
input[15:0]
inout[31:0]
output

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.

1.3. Terminologia Verilog

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;

assign vot12 = (i1 & i2);


assign vot13 = (i1 & i3);
assign vot23 = (i2 & i3);

// operator AND

assign decizie = vot12 | vot13 | vot23;

// operator OR

endmodule
Modul vot majoritar cu trei intrari: descriere cu porti logice definite n limbaj.

13

1.3. Terminologia Verilog

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;

(vot12, i1, i2);


// vot12 = i1 and i2
(vot13, i1, i3);
(vot23, i2, i3);
(decizie, 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.

Figura 1.2 Vot majoritar: forme de und


a rezultate n urma test
arii.

Numarator sincron reversibil cu presetare: descrierea comportamentala.

n
V

module upDnCounterPreset (
clk,
// intrare de ceas
reset_n,
// semnal de reset asincron

14

CAPITOLUL 1. INTRODUCERE

upDn_n,
ld,
di,
en,
count

//
//
//
//
//

sens de numarare: 1=crescator, 0=descrescator


semnal de presetare
valoare presetata
validarea numararii
iesirea numaratorului

);
input
input
input
input
input[3:0]
input
output[3:0]
reg[3:0]

clk;
reset_n;
upDn_n;
ld;
di;
en;
count;
count;

// ld en upDn_n clk | count*


// ------------------------------// 1
x
x
^
| di
// 0
1
1
^
| count + 1
// 0
1
0
^
| count - 1
// 0
0
x
^
| count
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
// reset asincron
count <= 4b0;
end
else begin
if (ld) begin
// preset sincron
count <= di;
end
else begin
if (en) begin
// numarare validata
if (upDn_n) begin
// numarare in sens crescator
count <= count + 1;
end
else begin
// numarare in sens descrescator
count <= count - 1;
end
end
end
end
end
endmodule

15

n
T
Ca referinta, figura 1.3 prezinta formele de unda obtinute prin simulare.

1.3. Terminologia Verilog

Figura 1.3 Num


arator: forme de und
a rezultate n urma test
arii.

Sumator complet de 1 bit: descriere comportamentala cu operator aritmetic.

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;

assign {co, s} = a + b + ci;

//
//
//
//

suma celor 3 intrari,


reprezentata pe 2 biti,
este atribuita
concatenarii bitilor co si s

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;

xor sum (s, a, b, cin);

// s = a xor b xor cin

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;

// transport intermediar intre biti

// instanta bit 0
add1Gl add1Gl_0 (
.a
(a[0]
.b
(b[0]
.ci
(ci
.s
(s[0]

),
),
),
),

17

1.3. Terminologia Verilog

.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

),
),
),
),
)

),
),
),
),
)

),
),
),
),
)

Sumator de dimensiuni generice: descriere comportamentala parametrizabila.

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;

assign {co, s} = a + b + ci;


endmodule
Multiplexor 2x1: descriere comportamentala.

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

1.3. Terminologia Verilog

wire

s0, s1;

not (s_n, s);


nand (s0, i0, s_n);
nand (s1, i1, s);
nand (y, s0, s1);

// s0 = not(i0 and s_n)

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

mux2x1 (y, i0, i1, s);


endmodule
primitive
output
input
input
input

mux2x1 (y, i0, i1, s);


y;
// primul port este iesirea
i0;
i1;
s;

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;

aceasta linie este doar un comentariu

Multiplexor 4x1: descriere structurala cu primitive mux2x1 definite de utilizator.

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

mux2x1 (mux1, i2, i3, s[1]);


mux2x1 (mux0, i0, i1, s[1]);
mux2x1 (y, mux0, mux1, s[0]);
endmodule
Multiplexor: descriere cu poarta de transmisiune.

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;

// not (iesire, intrare)


not (s_n, s);

1.4. Mediul de simulare a modelelor HDL

21

// cmos (iesire, intrare, controlN, comtrolP)


cmos(y, i0, s_n, s);
cmos(y, i1, s, s_n);
endmodule

1.4

Mediul de simulare a modelelor HDL

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

Exista nenumarate comparatii ntre Verilog si VHDL. In acest paragraf nu se face


o comparatie completa a celor doua limbaje de descriere hardware. In schimb, se
prezinta doua sisteme digitale mici (o poarta si un bistabil) modelate n cele doua
limbaje.
Avantaje evidente ale Verilog HDL:

22

CAPITOLUL 1. INTRODUCERE

Mediu de testare

Generator
de vectori
de test

Modul
sintetizabil
testat

Monitorizare
si
verificare

Figura 1.4 Mediu de simulare: dispozitiv de testat, generator de vectori, monitor.

tipuri de date simple si eficiente;


porti logice definite n limbaj;
cod mai concentrat.
Avantaje evidente ale VHDL:
suport puternic pentru descriere de vectori de test si lucru cu fisiere;
posibilitatea modelarii sistemelor analogice sau de comanda si control (motoare
electrice, senzori).
Exemplu: Bistabil D
VHDL
entity dff is
port (d, clk: in bit;
end dff;

q: out bit);

architecture basic of dff is


begin
process (clk)
begin
if (rising_edge(clk)) then
q <= d;
end if;
end process;
end basic;

Verilog
module dff (d, clk, q);
input
d, clk;
output q;

always @(posedge clk)

q <= d;

endmodule

23

1.5. Comparatie Verilog-VHDL

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

Structura codului Verilog

In Verilog exista o singura entitate lingvistica: modulul. In afara modulului nu


pot exista decat directive de compilare. In interiorul modulului pot aparea atat
specificatii, cat si directive de compilare. Includerea ntr-un cod sursa Verilog a codului Verilog existent ntr-un alt fisier se face prin directiva de compilare include.
25

26

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

Verilog are un set de valori simplu, definit n limbaj.


0: valoare logica 0 sau conditie falsa;
1: valoare logica 1 sau conditie adevarata;
x: valoare logica necunoscuta;
z: stare de nalta impedanta.
Valoarea z la intrarea unei porti logice este interpretata ca fiind x. Caracterele x
si z pot fi minuscule sau majuscule.
Exist
a trei tipuri de constante n Verilog:
Numere ntregi;
Numere reale;
Siruri.
Pentru a usura interpretarea acestora, se pot utiliza caractere de subliniere (_)
pentru a desparti caracterele ce desemneaza constante. Caracterul de subliniere nu
poate fi primul caracter.

2.3.1

Numere ntregi

Numerele ntregi pot fi scrise n forma implicita ca numere reprezentate n baza 10


sau ca valori exprimate ntr-o baza de numeratie precizata explicit. Numerele ntregi
sunt echivalente cu scrierea acestora n binar. Numerele negative sunt reprezentate
sub forma de complement fata de 2.
Sintaxa reprezentarii numerelor ntregi este:

Sn

2.3. Setul de valori

27

[dimensiune] <baza_de_numeratie> <valoare>


Un numar n format cu baza explicita este totdeauna considerat pozitiv. Daca
dimensiunea nu este precizata se considera o valoare implicita dependenta de implementarea simulatorului (de obicei 32 de biti).
Bazele de numeratie acceptate sunt:
baza 2: desemnata de litera b sau litera B;
baza 8: desemnata de litera o sau litera O;
baza 10: desemnata de litera d sau litera D;
baza 16: desemnata de litera h sau litera H.
Exemple:
13
-13

numarul 13 exprimat n baza 10 (n binar 1101)


numarul -13 exprimat n baza 10 (n binar, pe 4 biti 1011,
iar pe 5 biti 10011)
4b1010
numarul 10 exprimat n binar pe 4 biti
12o327
numar exprimat pe 12 biti n baza 8
16hBEEF
numar exprimat pe 16 biti n baza 16
8d-3
numar exprimat ilegal (valoarea nu poate fi negativa)
-8d3
numar exprimat legal ca fiind complementul fata de 2 al numarului
pozitiv 3, reprezentat pe 8 biti (echivalent cu 8b1111_1101)
16 h DEAD
forma legala cu spatii ntre dimensiune si caracterul
si ntre baza de numeratie si valoare
4 b0010
forma ilegala cu spatii ntre caracterul si baza de numeratie
widthb1010
forma ilegala, dimensiunea nu poate fi un parametru sau o expresie
b1010
forma legala, dimensiunea poate lipsi (numarul este reprezentat
pe numarul maxim de biti, n acest caz 4)
hFF
numar exprimat n baza 16, reprezentat pe 8 biti
8b101
numar exprimat n baza 2, reprezentat pe 8 biti ca
8b00000101
8b0000_0101
numar echivalent cu forma anterioara (caracterele _ sunt ignorate)
3b0110_0101
numar echivalent cu 3b101 (caracterele din stanga sunt trunchiate
daca valoarea are mai multi biti decat dimensiunea precizata explicit)
8b0_11_0_0101 folosire legala a caracterului de subliniere pentru delimitare
8b_0110_0101 folosire ilegala a caracterului de subliniere la nceputul valorii
8d260
numar echivalent cu 4 n baza 10 (provenit din trunchierea
caracterului cel mai semnificativ al reprezentarii n binar
9b1_0000_0100.)
8bx
valoare nedefinita extinsa pe 8 biti xxxxxxxx
4bz
valoare z extinsa pe 4 biti zzzz

2.3.2

Numere reale

Numerele reale pot fi reprezentate sub doua forme:

28

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

Numere zecimale (cu virgula). Exemple: 3.14, -0.268, 11.1512


Numere n format stiintific (cu exponent). Exemple: 3.1415E2 (314,15), 1.0E3
(1000,0), 5E-3 (0,005), 1_234.567_89 (1234,56789), 5.3E-3. Forma: 5. este
ilegal
a deoarece dupa punctul zecimal trebuie sa apara cel putin o cifra.
Numerele reale nu sunt sintetizabile. Numerele reale sunt automat convertite la numere ntregi prin rotunjire.

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
\\
\"

trece la linie noua (CR)


tabulator (TAB)
caracterul \
caracterul apostrof dublu (")

2.4

Tipuri de date si obiecte

Verilog are doua grupe de tipuri de date:


Tipul net: Acest tip de date modeleaza o conexiune fizica ntre elementele structurale. Valoarea unei date de acest tip este determinata de sursa sa, care poate
fi o specificatie de atribuire continua (assign) sau o instantiere de componenta.
Dac
a nu exista nici o sursa (driver de semnal), atunci data de tip net pastreaza
valoarea implicita z. Cel mai folosit tip din aceasta categorie este tipul wire.
Tipul register: Acest tip de date modeleaza un element abstract de stocare a
datelor. Valorile obiectelor de acest tip pot fi atribuite din interiorul specificatiilor always si initial. Valoarea implicita a acestui tip de date este x.
Sarmele de conexiune modelate n Verilog pot fi de tip net sau de tip register.
Diferenta dintre cele doua tipuri consta n modul n care se actualizeaza valoarea
obiectelor de acest tip. O sarma de tip net are valoarea continuu atribuit
a de
c
atre driverul ei. O sarma de tip register si p
astreaz
a valoarea p
an
a la
urm
atoarea atribuire a unei noi valori. Este absolut incorect
a afirmatia
conform c
areia obiectele de tip register modeleaz
a registre formate din
bistabile. Ca exemplu, se prezinta n continuare doua modele de porti logice, modelate cu cele doua tipuri de date.

29

2.4. Tipuri de date si obiecte

wire outGate1;
reg outGate2;

// declara un obiect de tip net (wire)


// declara un obiect de tip register (reg)

assign outGate1 = a & b; // iesirea outGate1 este continuu evaluata


// conform expresiei (a AND b)
always @(a or b)
outGate2 <= a & b;

//
//
//
//

iesirea outGate2 este evaluata conform


expresiei (a AND b) doar cand exista o
modificare a semnalului a sau
a semnalului b

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

Tip folosit cel mai frecvent pentru declararea de sarme. Corespunde


modelului unei sarme fizice.

tri

Tip identic n sintaxa si semantica cu wire, este folosit pentru semnalarea


posibilelor surse multiple pentru un semnal.

wor

Tip de sarma ce modeleaza conexiunea OR cablat.

trior

Tip identic n sintaxa si semantica cu wor.

wand

Tip de sarma ce modeleaza conexiunea AND cablat.

triand

Tip identic n sintaxa si semantica cu wand.

trireg

Tip de sarma ce modeleaza o sarma cu ncarcare capacitiva, capabila sa


retina ultima valoare dupa ce sursa semnalului a intrat n stare de nalta
impedanta.

tri0

Tip ce modeleaza sarme cu surse multiple care iau valoarea 0 n cazul


n care toate sursele semnalului au intrat n stare de nalta impedanta.

tri1

Tip ce modeleaza sarme cu surse multiple care iau valoarea 1 n cazul n


care toate sursele semnalului au intrat n stare de nalta impedanta.

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

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

Tip folosit cel mai frecvent pentru declararea de sarme cu memorie.


Este folosit pentru modelarea iesirilor de bistabile.

integer

Tip folosit exclusiv la modelarea la nivel nalt (nu pentru sinteza) fiind
echivalent cu tipul reg pe 32 de biti.

time

Tip folosit exclusiv la modelarea la nivel nalt pentru stocarea si


manipularea valorilor ce semnifica timp.

real

Tip folosit exclusiv la modelarea la nivel nalt pentru stocarea si


manipularea valorilor ce semnifica numere reale.

realtime

Tip identic n sintaxa si semantica cu tipul real.

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

2.4. Tipuri de date si obiecte

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];

// atribuirea unui membru al matricii


// bidimensionale catre un vector

assign reg178 = regFile[178]; //


//
assign zeroFlag = reg178[2]; //
//

accesarea registrului de la
adresa 178
accesarea bitului 2 din registrul de
la adresa 178

Exemplul urmator prezinta folosirea declaratiilor de tip wire si reg n cazul


modelarii structurale a unui bistabil T implementat cu un bistabil D si o poarta
XOR.
Prima versiune de modelare descrie bistabilul D cu o specificatie always. Din acest
motiv, sarma qt_o (asociata portului de iesire cu acelasi nume) a fost declarata de
tip reg. Comportamentul sarmei d (intern
a modulului) a fost descris cu o specificatie
continu
a assign. Din acest motiv, sarma d a fost declarata de tip wire.

n
V

module tVer1
reset_ni,
ck_i,
t_i,
qt_o
);
input
input
input
output

(
//
//
//
//

reset asincron activ in 0


semnal de ceas
intrarea bistabilului T
iesirea bistabilului T

reset_ni;
ck_i;
t_i;
qt_o;

// iesire declarata ca reg


reg
qt_o;
// sarma interioara declarata ca wire
wire
d;

32
assign

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

d = t_i ^ qt_o;

// operator XOR

always @(posedge ck_i or negedge reset_ni) begin


if (!reset_ni) begin
qt_o <= 1b0;
end
else begin
qt_o <= d;
end
end
endmodule
A doua versiune de modelare ncapsuleaza descrierea bistabilul D ntr-un modul
denumit dff. In interiorul acestui modul, portul de iesire qd_o a fost declarat reg
deoarece a fost atribuit din specificatie always. In schimb, la instantierea modului
dff n modulul tffVer2, portul sau de iesire qd_o este conectat la portul de iesire
qt_o al modulului tffVer2 cu o sarma obisnuita de tip wire.

n
V

module dff (
reset_ni,
ck_i,
d_i,
qd_o
);

//
//
//
//

reset asincron activ in 0


semnal de ceas
intrarea bistabilului D
iesirea bistabilului D

input
input
input
output

reset_ni;
ck_i;
d_i;
qd_o;

reg

qd_o;

// port de iesire de tip reg, atribuit in always

always @(posedge ck_i or negedge reset_ni) begin


if (!reset_ni) begin
qd_o <= 1b0;
end
else begin
qd_o <= d_i;
end
end
endmodule

module tVer2 (

33

2.4. Tipuri de date si obiecte

reset_ni,
ck_i,
t_i,
qt_o

//
//
//
//

reset asincron activ in 0


semnal de ceas
intrarea bistabilului T
iesirea bistabilului T

);
input
input
input
output

reset_ni;
ck_i;
t_i;
qt_o;

// declararea sarmei d (interna modulului)


wire
d;
assign

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
)
//
//
//
);

asociere dintre portul de intrare d_i


si sarma d
asociere dintre portul de iesire qd_o
si sarma qt_o (conectata la iesirea
modulului tVer2)

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 asincron activ in 0


semnal de ceas
intrarea bistabilului T
iesirea bistabilului T

reset_ni;
ck_i;
t_i;
qt_o;

34

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

// declaratia iesiri de tip reg


reg
qt_o;
always @(posedge ck_i or negedge reset_ni) begin
if (!reset_ni) begin
qt_o <= 1b0;
end
else begin
qt_o <= t_i ^ qt_o;
end
end
endmodule

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

Operatorii aritmetici sunt:


+ plus (unar si binar);
- minus (unar si binar);
* multiplicare;
/ mpartire;
% modulo.
Operatorii + si - sunt sintetizabili. Operatorul * este sintetizat ca un circuit combinational de catre unele sintetizatoare. Operatorii / si % se recomanda a nu se folosi
n cod ce urmeaza a fi sintetizat.

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

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

Dimensiunea rezultatului operatiilor aritmetice depinde de dimensiunea celui mai


mare operand si de dimensiunea si tipul obiectului destinatie. Daca se atribuie unui
obiect un rezultat pe mai putini biti, atunci rezultatul se extinde cu zerouri. In cazul
obiectului destinatie de tip ntreg, rezultatul ezultatul se extinde si extinde bitul de
semn (0 pentru numere pozitive si 1 pentru numere negative). Daca se atribuie unui
obiect un rezultat pe mai multi biti atunci, rezultatul se trunchiaza la numarul de
biti ai obiectului destinatie.
Exemple:
module testOpAritm();
reg[3:0]
reg[4:0]
reg[5:0]
reg[7:0]
integer
reg[7:0]
initial
opA =
opB =
opH =

opA, opB, opC;


opD;
opE;
opF;
opG;
opH;

begin
4b1110;
4b1000;
-9;

// 14
// 8
// -9

opC = opA + opB; // suma evaluata pe 4 biti


$display("Binar: %b + %b = %b, Zecimal: %0d + %0d = %0d",
opA, opB, opC, opA, opB, opC);
opD = opA + opB; // suma evaluata pe 5 biti
$display("Binar: %b + %b = %b, Zecimal: %0d + %0d = %0d",
opA, opB, opD, opA, opB, opD);
opE = opA + opB; // suma evaluata pe 6 biti
$display("Binar: %b + %b = %b, Zecimal: %0d + %0d = %0d",
opA, opB, opE, opA, opB, opE);
opF = opA * opB; // multiplicare evaluata la 8 biti
$display("Binar: %b * %b = %b, Zecimal: %0d * %0d = %0d",
opA, opB, opF, opA, opB, opF);
opC = opB - opA; // diferenta evaluata pe 4 biti
$display("Binar: %b - %b = %b, Zecimal: %0d - %0d = %0d",
opB, opA, opC, opB, opA, opC);
opD = opB - opA; // diferenta evaluata pe 5 biti
$display("Binar: %b - %b = %b, Zecimal: %0d - %0d = %0d",
opB, opA, opD, opB, opA, opD);
opE = opB - opA; // diferenta evaluata pe 6 biti

2.5. Operatori

$display("Binar: %b - %b = %b, Zecimal: %0d - %0d = %0d",


opB, opA, opE, opB, opA, opE);
opG = opB - opA; // diferenta evaluata ca numere intregi
$display("Binar: %b - %b = %b, Zecimal: %0d - %0d = %0d",
opB, opA, opG, opB, opA, opG);
opC = opA / opB; // impartire
$display("Binar: %b / %b = %b, Zecimal: %0d / %0d = %0d",
opA, opB, opC, opA, opB, opC);
opC = opA % opB; // modulo
$display("Binar: %b mod %b = %b, Zecimal: %0d mod %0d = %0d",
opA, opB, opC, opA, opB, opC);
$display("-9 reprezentat pe 8 biti. Binar: %b, Zecimal: %0d",
opH, opH);
opF = opB + opH; // scadere cu numere "negative".
// Rezultat asteptat -1
$display("Binar: %b - %b = %b, Zecimal: %0d - %0d = %0d",
opB, opH, opF, opB, opH, opF);
opH = opF + 3;

// adunare cu numere "negative".


// Rezultat asteptat +2
$display("Binar: %b + %b = %b", opF, 3, opH);
$display("Zecimal: %0d + %0d = %0d", opF, 3, opH);
end
endmodule
In urma simularii, se obtine urmatorul text:
#
#
#
#
#
#
#
#
#
#
#
#
#

Binar: 1110 + 1000 = 0110, Zecimal: 14 + 8 = 6


Binar: 1110 + 1000 = 10110, Zecimal: 14 + 8 = 22
Binar: 1110 + 1000 = 010110, Zecimal: 14 + 8 = 22
Binar: 1110 * 1000 = 01110000, Zecimal: 14 * 8 = 112
Binar: 1000 - 1110 = 1010, Zecimal: 8 - 14 = 10
Binar: 1000 - 1110 = 11010, Zecimal: 8 - 14 = 26
Binar: 1000 - 1110 = 111010, Zecimal: 8 - 14 = 58
Binar: 1000 - 1110 = 11111111111111111111111111111010,
Zecimal: 8 - 14 = -6
Binar: 1110 / 1000 = 0001, Zecimal: 14 / 8 = 1
Binar: 1110 mod 1000 = 0110, Zecimal: 14 mod 8 = 6
-9 reprezentat pe 8 biti. Binar: 11110111, Zecimal: 247
Binar: 1000 - 11110111 = 11111111, Zecimal: 8 - 247 = 255
Binar: 11111111 + 00000000000000000000000000000011 = 00000010

37

38

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

# 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

Operatorii relationali sunt:


> mai mare;
< mai mic;
>= mai mare sau egal;
<= mai mic sau egal.
Rezultatul unui operator relational este adevarat (1) sau fals (0).
Exemple:
15 > 12

fals (0)

15 > 8hx

nedefinit (x)

b1000 >= b011110

fals (0)

3 >= 3

adevarat (1)

2.5.3

Operatori de egalitate

Operatorii de egalitate sunt:


== egalitate logica;
!= inegalitate logica;
=== egalitate cu selectie;
!== inegalitate cu selectie.
Rezultatul unui operator de egalitate este adevarat (1) sau fals (0).
Exemple:

39

2.5. Operatori

opA
opB
opC
opD

=
=
=
=

b10x0
b10x0
16BExF
16BEEF

opA == opB

fals (0)

opA === opB

adevarat (1)

2b11 === 8b3

adevarat (1)

opC != opD

nedefinit (x)

opC !== opD

adevarat (1)

2.5.4

Operatori logici

Operatorii logici sunt:


&& AND logic;
|| OR logic;
! negarea unara.
Rezultatul unui operator logic este reprezentat pe un bit: 0, 1 sau x (indecis). Operanzii vectori sunt evaluati ca 0 daca au toate valorile 0, altfel sunt evaluati ca 1.
Exemple:
sigA
sigB
busC
busD
busE
sigF

=
=
=
=
=
=

1b0
1b1
4b1010
4b1001
4b0000
1bx

evaluat
evaluat
evaluat
evaluat

ca
ca
ca
ca

1
1
0
x

sigA && sigB

fals (0)

sigA || sigB

adevarat (1)

!sigA

adevarat (1)

busC && busD

adevarat (1)

busC || busD

adevarat (1)

!busC

fals (0)

40

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

!busE

adevarat (1)

!sigF

indecis (x)

2.5.5

Operatori logici pe vectori

Operatorii logici pe vectori sunt:


~ negare bit cu bit;
& AND pe biti;
| OR pe biti;
^ XOR pe biti;
~^ XNOR pe biti.
Operatorii logici pe vectori opereaza bit cu bit. Rezultatul unui operator pe vector
este tot un vector, avand dimensiunea operanzilor. Tabelele functiilor implementate
de operatorii logici sunt prezentate n tabelul 2.2.
& (and)
0
1
x
z
^ (xor)
0
1
x
z

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

busC & busD

4b1000

busC | busD

4b1011

~busC

4b0101

~busE

4b1111

~sigF

1bx

sigA & sigF

1b0

sigB & sigF

1bx

2.5.6

Operatori de reducere

Operatorii de reducere sunt:


& AND ntre toti bitii vectorului;
~& inversul operatorului &;
| OR ntre toti bitii vectorului;
~| inversul operatorului |;
^ XOR ntre toti bitii vectorului;
~^ inversul operatorului ^.
Operatorii de reducere se aplica unui operand vector si produc rezultat pe un bit.
Acesti operatori sunt foarte utili n exprimarea unor functii pe vectori de dimensiune
parametrizabila.
Exemple:
busA = 4b1010
busB = 4b1011
&busA

evaluat ca 0

|busA

evaluat ca 1

42

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

^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

1 daca toti bitii sunt egali cu 1

~|busC

1 daca toti bitii sunt egali cu 0 (echivalent cu busC === b0)

2.5.7

Operatori de deplasare

Operatorii de deplasare sunt:


<< deplasare stanga;
>> deplasare dreapta.
Operatorii de deplasare produc deplasarea bitilor operandului din stanga cu numarul
de pozitii precizat n dreapta, n directia precizata de operator.
Exemple:
reg[7:0] busA;
...
busA = 8b1001_1100
...
busA >> 2

evaluat ca 8b0010_0111

busA << 2

evaluat ca 8b0111_0000

43

2.5. Operatori

Operatorii de deplasare sunt foarte folositi pentru a descrie operatii de nmultire


si mpartire cu numere puteri ale lui 2 sau descrierea exponentierii n binar.
1 << 3

1 deplasat stanga cu 3 biti, echivalent cu 2 la puterea 3,


echivalent cu 4b1000

parameter power_p = 7;
1 << power_p
echivalent cu 2 la puterea 7, 8b10000000
opA << opB

echivalent cu opA nmultit cu 2 la puterea opB

opA >> opB

echivalent cu opA mpartit la 2 la puterea opB

Acest operator este utilizat si la modelarea unui decodificator:


input[3:0] dcd_i;
output[7:0] dcd_o;
// rezultatul este un vector de 8 biti avand un singur bit 1,
// pe pozitia cu index egal cu dcd_i
assign dcd_o = (1b1 << dcd_i);

2.5.8

Operator conditional

Exista un singur operator conditional:


<conditie> ? <expresie1> : <expresie0>
In cazul conditiei adevarate, operatorul ntoarce valoarea <expresie1>. Altfel, operatorul ntoarce valoarea <expresie0>. Comportamentul este similar cu cel al
circuitului multiplexor. Exemple:
assign y = sel ? i1 : i0;

2.5.9

Operatori de concatenare si replicare

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

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

// registrul cu deplasare in inel


reg[31:0] inelReg;
inelReg <= {inelReg[30:0], inelReg[31]};
// extindere de semn a vectorilor cu
// semnificatie de numere intregi (cu semn)
wire[7:0]
sign8;
wire[15:0] sign16;
assign sign16 = {{8{sign8[7]}}, sign8};
// sign8 = 8b0001_1111 (pozitiv) => sign16 = 16b0000_0000_0001_1111
// sign8 = 8b1001_1111 (negativ) => sign16 = 16b1111_1111_1001_1111
Operatorii de concatenare au cateva limitari:
In sirul de concatenare nu sunt admise constante cu dimensiuni neprecizate
(ilegal {busA, 5}, dar legal {busA, 4d5})
Numarul de repetari nu poate fi decat o constanta (ilegal {num{2b10}}, dar
legal {3{2b10}}).

2.6

Specificatii concurente

Specificatiile concurente se executa n paralel, indiferent de pozitia n care apar n


codul sursa. Fiecare specificatie concurenta are semnificatia proprie, independent
de celelalte specificatii concurente. Fiecare specificatie concurenta este executata
asincron fata de celelalte specificatii concurente. Un task nu se poate apela ntr-o
specificatie concurenta.
Exist
a trei tipuri de specificatii concurente:
specificatia assign (numita si specificatia de atribuire continua);
specificatia initial (constructie lexicala procedurala executata o singura data);
specificatia always (constructie lexicala procedurala executata la infinit).
Specificatia assign se poate considera ca este forma cea mai simpla de a modela
circuite logice combinationale. Sintaxa specificatiei assign este urmatoarea:

Sn

<atribuire_continua>
::= assign <tarie_driver>? <intarziere>? <lista_de_atribuiri>
<tarie_driver>
::= ( <STRENGTH0> , <STRENGTH1> )
||= ( <STRENGTH1> , <STRENGTH0> )
<intarziere>

2.6. Specificatii concurente

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

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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. Specificatii secventiale

2.7

47

Specificatii secventiale

Specificatiile secventiale (procedurale) sunt specificatii ce pot aparea doar n corpul


specificatiilor concurente initial sau always. Aceste specificatii se executa strict n
ordinea n care apar n codul sursa. Mai multe specificatii secventiale pot fi grupate
ntr-un bloc ce se comporta ca o singura specificatie prin delimitarea sa prin cuvintele
cheie begin si end.
Constructiile HDL concurente permit descrierea hardware la un nivel relativ detaliat. Modelarea unui circuit digital la nivel de porti logice si atribuiri continue este
foarte apropiata de structura fizica a circuitului. In schimb, acest tip de constructii
nu permit un nivel suficient de abstractizare necesar descrierii sistemelor complexe de
mari dimensiuni.
Sintaxa specificatiilor secventiale este prezentata n continuare:

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

Specificatii de atribuire secventiale

Atribuirile secventiale se deosebesc de atribuirile continue prin modul lor de actiune.


Atribuirile continue (realizate prin specificatia assign) atribuie valori variabilelor
de tip net similar modului n care iesirea unei porti logice determina valoarea logica

48

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

<semnal> = <control_timp> <expresie>


O atribuire blocanta este similara ca si actiune cu variabilele VHDL. Modificarea
valorii unui semnal printr-o atribuire blocanta se face imediat, n momentul
executiei acesteia, nainte de executia specificatiilor secventiale care i urmeaza
ntr-un bloc secvential.
Campul <semnal> din stanga operatorului = poate desemna un singur semnal,
o portiune dintr-un vector sau o concatenare de semnale.

2.7. Specificatii secventiale

49

Campul <control_timp> este optional si poate consta dintr-un control temporal


(#2) sau control de eveniment (@(posedge clk)). In lipsa unui control temporal
se considera conditia ndeplinita la momentul executarii atribuirii blocante.
Operatorul = este similar cu cel folosit la atribuirile concurente.
Atribuiri secventiale neblocante. O atribuire secventiala neblocanta are
sintaxa prezentata n continuare. Se remarca simbolul de atribuire <=.

Sn

<semnal> <= <control_timp> <expresie>


Atribuirile secventiale neblocante permit programarea unor atribuiri unui semnal, fara a opri (bloca) fluxul de executie a specificatilor secventiale ce i urmeaza.
Campul <semnal> din stanga operatorului <= poate desemna un singur semnal,
o portiune dintr-un vector sau o concatenare de semnale.
Campul <control_timp> este optional si poate consta dintr-un control temporal
(#2) sau control de eveniment (@(posedge clk)). In lipsa unui control temporal
se considera conditia ndeplinita la momentul executarii atribuirii blocante.
Operatorul <= este similar cu operatorul relational mai mic sau egal. Daca
operatorul <= apare ntr-o expresie, simulatorul l interpreteaza ca operator
relational. Daca operatorul <= apare ntr-o constructie de atribuire secventiala,
simulatorul l interpreteaza ca operator de atribuire secventiala neblocanta.
Simulatorul evalueaza atribuirile neblocante n doua etape.
In prima etapa, simulatorul evalueaza expresia din dreapta simbolului <=.
Simultan, se evalueaza controlul temporal. Ca efect, se planifica o schimbare a valorii semnalului la valoarea si momentul de timp determinate.
Far
a a schimba valoarea curenta a semnalului, simulatorul si continua
executarea specificatiilor secventiale.
La sfarsitul evenimentelor asociate timpului curent de simulare, nainte de a
incrementa timpul de simulare, simulatorul verifica planificarile existente
si actualizeaza valorile semnalelor ce au planificari la timpul curent de
simulare. Apoi timpul de simulare este incrementat.
Exemplul care urmeaza prezinta diferentele dintre cele doua tipuri de atribuiri
secventiale.

Sn

module blockingNonblocking ();


reg

a, b, c, d, e, f;

initial

50

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

2.7. Specificatii secventiale

#
#
#
#
#
#
#
#
#

blockingNonblocking 12
blockingNonblocking 16
blockingNonblocking 52
blockingNonblocking 54
blockingNonblocking 60
blockingNonblocking 76
blockingNonblocking 78
blockingNonblocking 82
blockingNonblocking 100

a=1, b=1, c=0, d=1,


a=1, b=1, c=1, d=1,
a=1, b=1, c=1, d=1,
a=1, b=1, c=1, d=1,
a=1, b=1, c=1, d=0,
a=0, b=1, c=1, d=0,
a=0, b=0, c=1, d=0,
a=0, b=0, c=0, d=0,
NOTA: Simularea s-a

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.

Figura 2.1 Forme de und


a pentru exemplificarea atribuirilor secventiale blocante si neblocante.

In codul RTL, se recomanda evitarea folosirii specificatiilor de atribuire blocante


si folosirea exclusiva a celor neblocante. Unele sintetizatoare nu accepta specificatii
always n care apar ambele tipuri de specificatii, generand mesaje de atentionare
referitoare la posibilitatea comportamentului diferit al modelului la nivel de poarta
logica generat fata de codul sursa RTL.
Pentru exemplificarea acestei recomandari, este prezentat cazul a doua specificatii
always, una modeland specificatii de atribuire blocante, iar alta modeland specificatii
de atribuire neblocante.
Specificatia always este o specificatie concurenta. Din acest motiv, ordinea n care
apar diverse specificatii always n codul sursa nu ar trebui sa aiba vreo importanta.
Totusi, datorita naturii secventiale a parcurgerii fisierului sursa, specificatiile always
sunt evaluate secvential de catre simulator (chiar daca la acelasi timp de simulare).
Utilizarea n acelasi modul a atribuirilor blocante si neblocante genereaza comportamente diferite ale unui cod sursa, n functie de ordinea specificatiilor concurente
(always) n fisierul sursa. Comportamentul evidentiat depinde de simulator, dar este
evident ca nici un proiectant nu doreste scrierea unui cod care sa se comporte diferit
n functie de simulatorul utilizat.

52

n
T

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

// atribuire blocanta plasata inaintea celei neblocante


always @(posedge clk) sigBloc_B1
= sigBloc_B1 + 1;
always @(posedge clk) sigNebloc_B1 <= sigBloc_B1;
// atribuire neblocanta plasata inaintea celei blocante
always @(posedge clk) sigNebloc_B2 <= sigBloc_B2;
always @(posedge clk) sigBloc_B2
= sigBloc_B2 + 1;
Sa presupunem cazul initial, cand toate semnalele au valoarea 0.
In primul caz, specificatia always cu atribuire blocanta apare n fisierul sursa
naintea celei ce foloseste atribuire neblocanta. Semnalul sigBloc_B1 si va actualiza
valoarea imediat (sigBloc_B1=1). Semnalul sigNebloc_B1 si planifica schimbarea
valorii n sigBloc_B1=1, dar schimbarea efectiva se va petrece la sfarsitul ciclului
curent de simulare.
In al doilea caz, specificatia always cu atribuire blocanta apare n fisierul sursa
dup
a cea care foloseste atribuire neblocanta. Semnalul sigNebloc_B2 si planifica
schimbarea valorii n sigBloc_B2=0, dar schimbarea efectiva se va petrece la sfarsitul
ciclului curent de simulare. In schimb, semnalul sigBloc_B2 si va actualiza valoarea
imediat (sigBloc_B2=1).
Ca efect, dupa primul front activ al semnalului de ceas, valorile celor patru semnale
vor fi:
sigBloc_B1
sigNebloc_B1
sigNebloc_B2
sigBloc_B2

=
=
=
=

1
1
0
1

Se recomanda rularea testului pe un simulator Verilog pas-cu-pas si observarea


ordinii efective n care se executa specificatiile always (specificatii concurente din
punct de vedere al limbajului HDL). A se observa momentul cand se avanseaza timpul
de simulare n raport cu ordinea de executie a specificatiilor always).
Pentru a se facilita ntelegerea, se reia codul cu comentarii referitoare la executia
initiala, la primul front pozitiv al semnalului de ceas.
// atribuire blocanta plasata inaintea celei neblocante
// aici sigBloc_B1 = 0, sigNebloc_B1 = 0
always @(posedge clk) sigBloc_B1
= sigBloc_B1 + 1;
// aici sigBloc_B1 = 1, sigNebloc_B1 = 0
// sigBloc_B1 si-a modificat deja valoarea
always @(posedge clk) sigNebloc_B1 <= sigBloc_B1;
// aici sigBloc_B1 = 1, sigNebloc_B1 = 0
// s-a planificat o modificare a valorii sigNebloc_B1 (1, 0ns)
// noua valoare va deveni valoare curenta doar la terminarea
// ciclului curent de simulare

2.7. Specificatii secventiale

53

// atribuire neblocanta plasata inaintea celei blocante


always @(posedge clk) sigNebloc_B2 <= sigBloc_B2;
// aici sigBloc_B2 = 0, sigNebloc_B2 = 0
// s-a planificat o modificare a valorii sigNebloc_B1 (0, 0ns)
// noua valoare va deveni valoare curenta doar la terminarea
// ciclului curent de simulare
always @(posedge clk) sigBloc_B2
= sigBloc_B2 + 1;
// aici sigBloc_B2 = 1, sigNebloc_B2 = 0
// sigBloc_B2 si-a modificat valoarea
//
//
//
//
//

inainte de a se relua executia specificatiilor always,


se actualizeaza semnalele pe baza atribuirilor planificate:
sigBloc_B1 = 1, sigNebloc_B1 = 1
sigBloc_B2 = 1, sigNebloc_B2 = 0
apoi se avanseaza ciclul de simulare si se continua simularea

Se remarca faptul ca unele sintetizatoare nu fac distinctie ntre simbolurile de atribuire


secventiale ceea ce conduce la sintetizarea defectuoasa. La simularea netlistului postsinteza se va observa un comportament diferit de cel al surselor RTL. Structura generata de catre sintetizator este prezentata n figura 2.2.

Figura 2.2 Structur


a generat
a de c
atre sintetizator pentru exemplul cu specificatii blocante
si neblocante.

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

Sintaxa specificatiilor conditionale (if) este urmatoarea:

54

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

Figura 2.3 Forme de und


a la simularea comparativ
a RTL - netlist post-sintez
a.

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

2.7. Specificatii secventiale

55

Figura 2.4 Structur


a de multiplexor plus logic
a sintetizat
a din specificatia conditional
a.

Codul Verilog ce implementeaza aceasta functie prezinta specificatii conditionale


multiple, incluse unele n altele, unele cu alternativa else.
always @(posedge clk_i or negedge reset_ni) begin
if (!reset_ni) begin
registru_o <= 8b0;
// linia nr. 1
end
else begin
if (enable_i) begin
// linia nr. 3|4|5|6|7|8
if (load_i) begin
registru_o <= data_i;
// linia nr. 3
end
else begin
if (count_i) begin
if (up_i) begin
// linia nr. 4|5
registru_o <= registru_o + 1;
// linia nr. 4
end
else begin
registru_o <= registru_o - 1;
// linia nr. 5
end
end
else begin
// linia nr. 6|7
if (sh_i) begin
if (left_i) begin
registru_o <= registru_o << 1; // linia nr. 6
end
else begin
registru_o <= registru_o >> 1; // linia nr. 7
end
end // linia nr. 8 ("if (sh_i)" nu are "else")
end

56

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

end
end
end
end

2.7.3

// linia nr.2 ("if (enable_i)" nu are "else")

Specificatii de selectie

Specificatiile de selectie permit evaluarea unei expresii si deciderea pe baza valorii


acesteia a specificatiilor ce urmeaza a se executa. Sintaxa specificatiilor case este
urmatoarea:

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

2.7. Specificatii secventiale

input[7:0]
input[7:0]
output[7:0]
reg[7:0]

leftOp_i;
rightOp_i;
rez_o;
rez_o;

always @(func_i or leftOp_i or rightOp_i) begin


case (func_i)
ADD
: rez_o <= leftOp_i + rightOp_i;
SUB
: rez_o <= leftOp_i - rightOp_i;
XOR
: rez_o <= leftOp_i ^ rightOp_i;
AND
: rez_o <= leftOp_i & rightOp_i;
PASS_L : rez_o <= leftOp_i;
NEG_L : rez_o <= ~leftOp_i;
default : rez_o <= 8b0;
endcase
end
endmodule

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

// primul front la 5ns


// complementeaza la fiecare 10ns

58

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

Specificatia repeat se executa de numarul de ori precizat de o expresie. Cateva


exemple sunt prezentate n continuare.
// deplaseaza stanga cu 5 pozitii
repeat (5)
shReg <= shReg << 1;
// asteapta scurgerea a nrPerioade de ceas
repeat (nrPerioade)
@(posedge clk);
Specificatia while se executa atata timp cat expresia evaluata este adevarata.
Aceasta specificatie este foarte utilizata pentru modelarea actiunilor de asteptare sau
de sincronizare ntre procese. De exemplu, modelul de nivel nalt al unui procesor
folosit pentru generarea unor stimuli pentru un sistem hardware comandat, include
proceduri (definite ca task-uri) de scriere, de citire si de pauza (nici o actiune). O
procedura software de polling impune scrierea unui registru care determina executia
unei comenzi urmata de citirea unui registru de stare pana cand un anumit bit este
gasit setat. Acesta este semnalul ca actiunea initiata a fost terminata si ca procesorul
poate initia noi comenzi.
define
define

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;

// latimea bus-ului de adrese

59

2.7. Specificatii secventiale

parameter dataDim_p
//
//
//
//

= 16;

// latimea bus-ului de date

declaratie de memorie de dimensiune parametrizabila


2^adsDim_p x dataDim_p
implicit de dimensiune 2^10 x 16
(spatiu de adrese intre 0 si 1023)

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

Specificatii de control temporal

Unei specificatii secventiale i se poate asocia un mecanism de control al temporizarii.


Controlul ntarzierii;

60

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

Specificatia initial si ncepe executia la timpul 0. La acel moment, semnal nu


primeste nici o valoare, deci va avea valoarea x. Dupa 5 unitati de timp se executa
specificatia 1, iar semnal va lua valoarea 1. Dupa nca 6 unitati de timp (deci la 11
unitati de la nceputul simularii) semnal ia valoarea 2. Dupa nca 2 unitati de timp
(deci la 13 unitati de la nceputul simularii) semnal ia valoarea 3, pe care o pastreaza
pana la sfarsitul simularii.
Specificarea ntarzierii se poate face chiar n lipsa unei specificatii asociate. In acest
caz, semnificatia este asteapta ntarzierea impusa nainte de executia urmatoarei
specificatii.

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

2.7. Specificatii secventiale

// atribuire blocanta plasata inaintea celei neblocante


// cu intarziere zero explicita
always @(posedge clk) #0 sigBloc_B1
= sigBloc_B1 + 1;
always @(posedge clk)
sigNebloc_B1 <= sigBloc_B1;
Controlul evenimentelor consta din specificarea unei conditii bazate pe semnale care determina executia specificatiei asociate. Evenimentele pot fi controlate de
fronturi de semnale sau de niveluri de semnale. Controlul evenimentului asociat unei
specificatii secventiale determina ntarzierea executiei specificatiei pana la ndeplinirea
conditiei impuse.
Controlul evenimentelor pe baza de fronturi poate actiona pe frontul pozitiv, pe
cel negativ sau pe ambele. Fronturile se precizeaza prin cuvintele rezervate posedge
si negedge. Lipsa unuia din aceste cuvinte semnifica ambele fronturi.
Fronturile sunt asociate evenimentelor prezentate n tabelul 2.3.
Front negativ
1 -> x
1 -> z
1 -> 0
x -> 0
z -> 0

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)

semnal <= semnal + 1;


semnal <= 8b0;
semnal <= bz;

In exemplul anterior, cuvantul rezervat or nu reprezinta un operator logic ci un


liant pentru o conditie cu semnale multiple.
Urmatorul modul implementeaza un generator parametrizabil pentru semnale de
ceas si de reset (sincronizat cu semnalul de ceas).

n
V

timescale 1ns/1ps
module clkreset_noGen(
clk_o,

// semnal de ceas

62

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

reset_no
);
// perioada de ceas
parameter tCkPer_p
parameter phaseCk_p
parameter phaseRst_p
parameter resetWidth_p

output
output
reg
reg

// semnal de reset activ in 0

= 10; // implicit frecventa de 100 MHz


= 0; // faza initiala a ceasului
= 4; // faza activarii reset-ului
// masurata in perioade de ceas
= 3; // latimea semnalului de reset masurata
// in perioade de ceas

clk_o;
reset_no;
clk_o;
reset_no;

// generare semnal de ceas


initial begin
// valoare initiala
clk_o <= 1b0;
// asteapta intarzierea determinata de faza initiala
#(phaseCk_p);
// complementeaza la fiecare semi-perioada
forever #(tCkPer_p/2) clk_o <= ~clk_o;
end
// generare semnal de reset activ in 0
initial begin
reset_no <= 1b1;
// asteapta activarea reset-ului
repeat(phaseRst_p) @(posedge clk_o);
// activeaza reset
reset_no <= 1b0;
// asteapta dezactivarea reset-ului
repeat(resetWidth_p) @(posedge clk_o);
// dezactiveaza reset
reset_no <= 1b1;
end
endmodule
Controlul evenimentelor pe baza de niveluri implementeaza un mecanism de ntarziere a executiei unei specificatii pana la ndeplinirea unei conditii complexe. Daca
la aparitia specificatiei, conditia este deja adevarata, executia specificatiei asociate
ntarzierii are loc imediat. Altfel, executia specificatiei asociate este amanata pana la
ndeplinirea conditiei impuse.

Sn

63

2.8. Directive de compilare

wait (<expresie>) <specificatie_secventiala>


Exemple:
wait (counter > 22)
wait (rdy)
wait (reset_ni);

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

Directiva de compilaredefine este utilizata pentru substitutia de texte. Alternativ,


ea poate fi utilizata pentru a controla compilarea conditionata a unor portiuni de cod.
Exemple:

64

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

define WIDTH
reg[WIDTH-1:0]

32
dataBus;

// definire latime bus


// declarare bus de latime configurabila

// definire adrese relative pentru un set de registre


define SDRAM_MODE_ADDR
8h00
...
define WR_ADDR
8h08
reg[3:0]
reg[15:0]

sdramMode;
wrAddr;

// registru de mod al controlerului SDRAM


// registru pentru adresa de scriere

// 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

2.8. Directive de compilare

default:
endcase
end
end

2.8.2

mpuData_o <= 16hDEAD; // adresa neimplementata

ifdef, ifndef, else, endif

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

// decomentati linia ce corespunde tehnologiei

In codul sursa, componentele specifice tehnologiei se vor instantia conditionat de


definirea sau nu a tehnologiei corespunzatoare:
ifdef FPGA_tech
// instanta de PLL specifica tehnologiei FPGA
pllBlk UpllBlk (
.inClk
(ddrClk
),
.shClk
(shClk
),
.clk
(
),
.resyncClk (resyncClk ),
.SDR_CK
(SDR_CK
),
.SDR_CK_N (SDR_CK_N )
);
endif
ifdef ASIC_tech
// declaratii de sarme nefolosite
wire nc0, nc1;
// instanta de DLL specifica tehnologiei ASIC
ASIC_DLL UASIC_DLL(
.CLK
(ddrClk
),
.DQS
(1b0
),
.RST
(~ddrReset_n
),
.CLK360 ({resyncClk, SDR_CK} ),
.CLK270 ({shClk,nc0}
), // iesirea este pe 2 biti, dar
.CLK180 ({SDR_CK_N, nc1}
), // numai unul este folosit
.CLK90
(
)
);
endif

66

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

//
//
//
//
//
//
//

indicator care daca a fost definit


determina saltul peste sectiunea de
definiri
la prima includere se defineste
indicatorulastfel incat la urmatoarele
includeri sa se gaseasca falsa
conditia de intrare in aceasta

// 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

In Verilog toate ntarzierile sunt exprimate n unitati de timp. Directiva timescale


este utilizata pentru asocierea unei valori absolute unitatii de timp Verilog.

Sn

67

2.9. Stil si calitate

timescale <unitate_timp> / <precizie>


Directiva timescale specifica unitatea de masura a timpului pentru ntarzieri si
precizia ntarzierilor mentionate n toate modulele, pana la aparitia unei alte asemenea
directive. Este recomandat ca toate fisierele apartinand unui proiect sa contina aceeasi
directiva timescale.
<unitate_timp> precizeaza valoarea absoluta a unitatii de timp.
<precizie> specifica precizia cu care se vor rotunji valorile fractionale.
Exemplu:
timescale 1ns / 100ps
Directiva stabileste valoarea absoluta a unitatii de timp la 1ns si precizia de rotunjire a valorilor ce reprezinta timp la 100ps.
assign #3.14 A = B & C
assign #3.1 A = B & C
assign #3
A = B & C

2.9

// intarziere 3.1 ns
// intarziere 3.1 ns
// intarziere 3 ns

Stil si calitate

Acest paragraf si propune sa prezinte recomandarile autorilor referitoare la modul de


scriere a codului Verilog. Nerespectarea acestor recomandari nu nseamna ca este un
cod scris gresit. Dar, orice firma impune tuturor proiectantilor un anumit stil al
codului sursa n scopul usurarii ntelegerii ulterioare a acestuia. Regulile mentionate
n continuare vor fi folosite la scrierea codului sursa prezentat n aceasta carte.
Numele identificatorilor. Modul de alegere a numelor pentru obiectele Verilog este un semn al maturitatii si al experientei inginerului. In experinta
didactica, autorii au ntalnit multe module scrise foarte bine de catre studenti,
dar cu nume care nu sugereaza nici pe departe ce modeleaza acele module. Nume
de module ca: test, lab_meu, raspuns_paul, sx2005 sau altele similare, nu dau
nici cea mai mica indicatie asupra comportamentului sau structurii modulului
Verilog.
Este de dorit ca numele identificatorilor sa fie sugestive pentru rolul acestora
n cadrul modelului Verilog. De exemplu, identificatorul counter nu sugereaza
prea multe despre rolul pe care l are numaratorul modelat n cadrul sistemului.
Nici counter16 nu aduce prea mult
a informatie pentru ca, oricum, numarul de
biti al numaratorului se poate vedea din declaratia acestuia
(reg[15:0] counter16;). O denumire mai sugestiva ar fi rdAddr (adresa de
citire a unei memorii) sau pulseCounter (un numarator al unor pulsuri) sau
delayCntr (un numarator folosit pentru contorizarea unei ntarzieri). Cu totul
nerecomandate sunt denumirile derutante, care sugereaza ceva diferit de ceea ce
modeleaza de fapt. De exemplu, denumirea counter asociata iesirii unui circuit
combinational.
De multe ori nu este usor de exprimat cu putine litere semnificatia unui semnal.
Nu trebuie totusi exagerat cu denumiri extrem de lungi de genul numelor de
indieni: adresa_de_citire_a_memoriei_fifo_din_blocul_de_receptie. O

68

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

denumire mai potrivita, cu prescurtarea unor cuvinte, ar fi: rd_ads_rec. Se


iveste problema delimitarii portiunilor de litere.
Nu este la fel ca un semnal sa fie denumit rdadsrec sau rd_ads_rec sau
rdAdsRec. Evident, prima forma este nerecomandata. Cea de-a doua forma
presupune separarea atomilor ce prescurteaza cuvinte diferite prin caracterul de
subliniere (_). Este o decizie buna, nsa determina artificial lungirea numelor.
Acest lucru scade productivitatea scriitorului de cod si determina ca liniile de
cod sa fie uneori prea lungi. A treia forma, denumita n jargon inCaps, presupune folosirea majusculelor pe post de delimitatori. In acest caz, numele
identificatorilor este scurtat la minim. Cu putin exercitiu, aceasta forma devine
foarte intuitiva pentru cititorul unui cod scris de altcineva.
Se remarca faptul ca Verilog face distinctie ntre numele identificatorilor scrise
cu litere mari si mici. De exemplu, urmatorii identificatori desemneaza obiecte
diferite: rdadsrec, rdAdsRec, RdAdsRec, rdadsRec. Evident, aparitia unor
asemenea nume poate fi o greseala de tastare si va fi imediat semnalata la
analiza sintactica a codului Verilog. Dar daca proiectantul a declarat cu intentie
un semnal cu numele rdadsRec si altul cu numele rdAdsRec atunci o eroare de
tastare nu mai este semnalata ca eroare de sintaxa si va fi mai greu de depistat.
Numele porturilor si ale parametrilor. O atentie particulara trebuie acordata alegerii numelor pentru porturi si parametrii deoarece acestea reprezinta
imaginea exterioara a modulului proiectat. Semnalele au vizibilitate doar n interiorul modulului. Denumirile porturilor si ale parametrilor vor fi nsa vazute
si vor trebui ntelese, de catre alti ingineri care folosesc (instantiaza) acel modul.
In plus, este foarte util pentru un scriitor de cod Verilog sa stie imediat daca
un identificator reprezinta un parametru, un port de intrare, un port de iesire
sau un semnal intern acelui modul. De exemplu, se va putea imediat constata o eroare ntr-o specificatie de genul assign width_p = 1b0 daca se
va stii ca identificatorul width_p este de fapt un parametru caruia nu i se
poate atribui o valoare folosind specificatia assign. Sau, o specificatie de genul
assign data_o = data_i va sugera imediat ca este vorba nu doar de o simpla
atribuire de semnale, ci de modelarea unei sarme care trece prin modul fara nici
o prelucrare (daca data_o este port de iesire, iar data_i este port de intrare).
Asemenea tip de conexiune (feed-through, n limba engleza) nu este ilegal,
dar trebuie folosit cu atentie.
Pentru usoara identificare a obiectului denumit, se recomanda stabilirea unor
conventii de denumire a porturilor si a parametrilor. Codul prezentat n acesta
carte se conformeaza urmatoarelor reguli:
Porturile de intrare au nume sufixate cu caracterele _i (daca este intrare
activa n 1) si _ni (daca este intrare activa n 0). Exemple: data_i,
reset_ni, flag_i, rdRq_i, rdAddr_i.
Porturile de iesire au nume sufixate cu caracterele _o (daca este iesire
activa n 1) si _no (daca este iesire activa n 0). Exemple: data_o, stat_o,
rdRq_o, rdAddr_o, ras_no, cas_no, cs_no.
Porturile bidirectionale au nume sufixate cu caracterele _io. Exemple:
data_io, cpuData_io.

69

2.9. Stil si calitate

Parametrii au nume sufixate cu caracterele _p.


length_p, messageOn_p.

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

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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

2.9. Stil si calitate

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?

Codul recomandat este urmatorul:


always @(posedge clk_i) begin
if (!reset_ni) begin
rdAddr <= 1b0;
end
else begin
if (en) begin
if (ld) begin
rdAddr <= 1b0;
end
else begin
if (inc) begin
rdAddr <= rdAddr + 1;
end
end
end
end
O alternativa de scriere mai condensata, n cazul specificatiilor always care
atribuie valori doar unui semnal este prezentata n continuare:
always @(posedge cpuClk_i)
if (!cpuReset_ni)

outRange <= 1b0; else

72

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

if (devSel && (cpuAddr_i == ADDR_STATUS))


outRange <= cpuD_i[0]; else
if (setOutRange)
outRange <= 1b1;
always @(posedge cpuClk_i)
if (!cpuReset_ni)
startOp <= 1b0; else
if (devSel && (cpuAddr_i == ADDR_STATUS))
startOp <= cpuD_i[1]; else
if (resetStartOp)
startOp <= 1b0;
Existenta unui antet al fisierului. Este recomandata existenta unor informatii la nceputul fiecarui fisier sursa, marcate ca fiind comentarii n Verilog. Forma
grafica a acestui antet (header, n limba engleza) nu este importanta. In
schimb, este important ca antetul sa fie simplu, dar sa contina toate informatiile
relevante necesare:
Numele proiectului din care face parte fisierul;
Numele autorului;
Numele fisierului (pentru a aparea n cazul imprimarii codului sursa);
Scurta descriere a modulului descris n acel fisier;
Tabelul modificarilor asupra codului (cu siguranta codul va fi modificat n
timp pentru a adauga noi caracteristici sau a rezolva defectele observate).
Ca exemplu, n continuare se prezinta formatul antetul utilizat pentru fisierele
ce nsotesc aceasta carte.
/************************************************************
*
Proiect: Carte "Electronica digitala"
*
Autor: Dan NICULA (DN)
*
Email: dan.nicula@vega.unitbv.ro
* Nume fisier: upDnCounter.v
*
Descriere: Numarator reversibil
*
Revizii:
* Data
Autor
Modificari
* Aug 20, 2005
DN
Versiune initiala
* Aug 27, 2005
DN
Adaugat optiune de preset sincron
*************************************************************/
De remarcat ca, n antetul propus, nu s-au adaugat caracterele * si la sfarsitul
fiecarei linii. Desi ar parea frumos, adaugarea de texte ulterior ar impune realinierea caracterelor *, ceea ce ar consuma un timp pretios.
Comentarii. Este recomandata adaugarea comentariilor n cod simultan cu
scrierea codului, nu ulterior. Exista doua feluri de comentarii:
comentarii pe linii multiple, referitoare la blocuri mari de cod si
comentarii pe un singur rand sau la sfarsitul randului, referitoare la o
anumita expresie sau specificatie.

2.9. Stil si calitate

73

Comentariile trebuie sa aiba urmatoarele caracteristici:


sa fie scurte;
sa fie relevante;
sa fie plasate naintea portiunii de cod la care se face referire.
Lista porturilor unui modul se recomanda a fi scrisa cate un singur port pe un
rand. In acest fel, se poate scrie n dreptul fiecarui port o scurta descriere, ca
si comentariu.
module add1C (
a, // primul operand
b, // al doilea operand
ci, // transport de intrare
s, // rezultatul
co // transport de iesire
);
Comentariile trebuie sa fie relevante pentru specificatia sau identificatorul la
care face referire. De exemplu, urmatoarele comentarii nu sunt foarte relevante:
always @(posedge clk or negedge reset_n)
if (!reset_n) rd_addr <= 16b0; else
// reseteaza rd_addr
if (updt_cnt) rd_addr <= rd_addr + 1; // incrementeza rd_addr
Este evident (din specificatia existenta pe acelasi rand cu comentariul)
ca rd_addr se incrementeaza. Este evidenta si conditia de incrementare a acestui
registru. Ce nu este evident, si ar trebui sa fie precizat printr-un comentariu, este
semnificatia registrului rd_addr n cadrul sistemului. De exemplu, n continuare
se prezinta acelasi cod cu comentarii considerate relevante:
// rd_addr: adresa de citire a memoriei de stocare
// a datelor acceptate
always @(posedge clk or negedge reset_n)
if (!reset_n)
rd_addr <= 16b0; else
// updt_cnt: semnal generat de blocul de receptie
if (updt_cnt)
rd_addr <= rd_addr + 1;
Asocierea explicit
a a porturilor cu semnalele, la instantierea unui
modul. Alternativa asocierii prin pozitie nu este recomandata deoarece poate
genera erori nu numai n cazul asocierii gresite, ci si n cazul adaugarii sau
eliminarii unor porturi ale modulului. In plus, este recomandata plasarea pe o
linie de cod a unui singur cuplu port-semnal actual cu posibilitatea de a adauga
un comentariu la sfarsitul liniei. In cazul prezentat n continuare, asocierea
dintre porturi si semnale se face prin pozitie. Va fi greu de gasit greseala pentru
ca, n anumite cazuri, raspunsul este corect chiar daca au fost facute conexiuni
gresite.

74

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

add1C U0_add1C( a[0], b[0], 1b0, sU1[0], coU1);


add1C U1_add1C( a[1], b[1], coU1, coU2, sU2[1]);
Dac
a pentru unele porturi denumirea semnalelor asociata este sugestiva, pentru
a vedea ce port este conectat la masa (asociat cu 1b0) trebuie sa se deschida
un alt fisier si sa se verifice ordinea porturilor la declararea modulului add1C.
Modul recomandat de instantierea unui modul este ca n exemplul urmator:
add1C
.a
.b
.ci
.s
.co
);

U2_add1C(
(a[2]
),
(b[2]
),
(coU2
),
(sU3[2] ),
(coU3
)

// transport provenit de la U2_add1C


// transportul se propaga la U4_add1C

Continutul unui fisier surs


a. Se recomanda ca un fisier sa contina descrierea
unui singur modul. In plus, daca numele fisierului este identic cu numele modulului descris n acel fisier, cautarea descrierii unui modul este mult usurata.
Exceptie de la aceasta recomandare o fac fisierele ce contin descrierea unor
biblioteci de componente. In acest caz, mai multe descrieri de module sunt
incluse n acelasi fisier si sunt compilate printr-o singura comanda. Este total
neinspirata includerea a doua module cu cod Verilog n acelasi fisier deoarece
cautarea celui de-al doilea modul (a carui nceput se afla undeva prin mijlocul
fisierului) va fi foarte anevoioasa. Uneori, se recomanda includerea unor fisiere
cu directiva de compilare include. Este cazul plasarii unor parametri posibil
de configurat separat de codul sursa ce nu trebuie modificat. Aceste fisiere
se recomanda a fi denumite cu alta extensie decat .v pentru a nu fi selectate
alaturi de fisierele ce contin declaratii de module. Extensia acestor fisiere nu
este impusa, dar se recomanda a fi .h.
Se recomanda pastrarea fisierelor sursa Verilog n directoare distincte, n functie
de rolul lor. In folderul src se vor pastra fisierele Verilog ce descriu sistemul
proiectat, fisiere care n final se vor sintetiza. Fisierele care modeleaza mediul de
simulare, vor fi plasate ntr-un alt folder, denumit sim. Fisierele ce contin date
referitoare la sinteza (constrangeri de timp, asocieri de pini) vor fi plasate ntr-un
folder separat denumit syn. Aceasta ordine a fisierelor permite altor membrii
ai echipei de proiectare un acces rapid la fisiere. Totodata, fisierele generate
de diverse produse software vor fi plasate automat n folderele corespunzatoare:
folderul sim fisiere generate la simulare si folderul syn fisiere generate la sinteza.
Transmiterea parametrilor cu directive defparam. Functionarea sau structura unui modul poate fi modificata prin folosirea unor parametri. Parametrii
reprezinta constante pentru instantierea modulelor si au valori implicite, precizate n cadrul declaratiei de module. Valorile implicite ale parametrilor pot fi
modificate n momentul instantierii modulelor sau prin directive de compilare
defparam. A doua metoda, daca este suportata de programele de sinteza, are
cateva avantaje. Avantajul principal consta n faptul ca se pot schimba numai

75

2.9. Stil si calitate

anumite valori ale parametrilor, fara a se cunoaste ordinea definirii acestora n


module. In plus, folosirea directivei defparam produce o mai buna documentare
a codului sursa. In continuare sunt prezentate doua exemple de transmitere a
parametrilor.
Transmiterea parametrilor la instantierea modulelor:
wire[7:0]
wire[7:0]
wire[7:0]
wire[7:0]
wire[3:0]
wire

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

CAPITOLUL 2. FUNDAMENTELE LIMBAJULUI VERILOG HDL

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])

2.9. Stil si calitate

77

ADDR_CH_CNTRL : cpuData_o <= devCtrl;


ADDR_CH1_CNTRL: cpuData_o <= devCh1Ctrl;
ADDR_CH2_CNTRL: cpuData_o <= devCh2Ctrl;
...
endcase
Se remarca faptul ca modificarea spatiului de adrese sau chiar a numarului de
biti de adrese sau de date, se poate face prin modificarea valorilor definite, fara
modificari n codul sursa.

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

Portile logice si circuitele logice n general se pot modela individual cu specificatii


de atribuire continua (assign) sau cu specificatii de atribuire procedurale (always).
Alternativ, circuitele logice secventiale pot fi modelate n cadrul specificatiilor always
care descriu simultan registrele si logica ce determina starea lor viitoare (cazuri prezentate n sectiunile 3.7 si 3.8).

3.1.1

Modelarea circuitelor logice cu assign

Circuitul logic combinational caracterizat de functia AOI (And-Or-Invert)


F = A.B + C.D poate fi descris astfel:
wire
wire
assign

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

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

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); //
//
//
//

8 intrari, functia este 1 daca


intrarea este egala cu 8h78
16 intrari, functia este 1 daca
intrarea aBus (8 biti) este egala cu
intrarea bBus (8 biti)
8 biti, OR pe biti,
echivalent cu (aBus != 0)
16 biti, echivalent cu (aBus==bBus)
7 biti, AND intre toti bitii
semnalului bBus si bitul [0]
al semnalului aBus,
echivalent cu &{aBus[0], bBus}

Modelarea circuitelor logice cu always

Modelarea circuitelor logice cu specificatii always are avantajul posibilitatii folosirii


specificatiilor secventiale (if, case) pentru definirea unor functii mai complexe. Insa,
modelarea circuitelor logice cu specificatii procedurale necesita o atentie sporita deoarece contine o redundanta. Lista de senzitivitati a specificatiei always trebuie
sa contina toate semnalele ce apar n dreapta simbolurilor de atribuire procedurala.
Neaparitia unui semnal de intrare n lista de descriere a evenimentului asociat specificatiei always poate determina aparitia unui latch n urma sintezei. Daca vectorii de
test sunt bine alesi, defectul se poate pune n evidenta si la nivel RTL.
Circuitul logic combinational caracterizat de functia AOI (And-Or-Invert) F =
A.B + C.D poate fi descris astfel:
wire
A, B, C, D;
reg
L;
always @(A or B or C or D)

//
//
//
//

iesirea se declara ca reg


cuvantul or este doar "liantul"
pentru lista de senzitivitati
(nu semnifica operatorul logic OR)

L <= ~(A&B | C&D);


Cum se sintetizeaza urmatoarea specificatie?
always @(A or B or C)
M <= ~(A&B | C&D);

// lipseste intrarea D

Se observa ca iesirea M nu se re-evalueaza daca se modifica intrarea D deoarece aceasta


nu este prezenta in lista de senzitivitati. Sintetizatoarele actuale recunosc o potentiala
greseala si emit mesaje de atentionare ca:
@W:Incomplete sensitivity list - assuming completeness
@W:Referenced variable D is not in sensitivity list

3.2. Circuite de multiplexare

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

Circuitul multiplexor 2:1 poate fi modelat cu operatorul conditional: dac


a selectia
este 1, la iesire se propag
a intrarea de date 1, altfel la iesire se propag
a intrarea de
date 0.
wire
mux
assign mux = sel ? i1 : i0;
Alternativa secventiala permite utilizarea specificatiei if:
reg
mux;
always @(sel or i0 or i1)
if (sel)
mux <= i0;
else
mux <= i1;
Circuitele de multiplexare cu numar mai mare de intrari de selectie pot fi modelate
cu specificatia case, asa cum a fost prezentat n sectiunea 3.1.

3.3

Codificator/decodificator

Modelarea codificatoarelor se poate face folosind specificatia case, pornind de la


tabelul de adevar al acestor functii: codificarea n binar a indexului bitului egal cu 1

82

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

Figura 3.1 Structuri obtinute prin sinteza modelelor de circuite combinationale prezentate
n sectiunea 3.1.

83

3.3. Codificator/decodificator

n vectorul de intrare. Circuitul codificator descris n exemplul urmator presupune


existenta unui singur bit egal cu 1 ntre cei 8 biti de intrare.
always @(A)
case(A)
8b1000_0000:
8b0100_0000:
8b0010_0000:
8b0001_0000:
8b0000_1000:
8b0000_0100:
8b0000_0010:
8b0000_0001:
default:

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

In continuare este prezentat modelul unui circuit codificator cu prioritate cu intrare


si iesire de validare.

n
T

n
V

module encoder(
A_i,
E_i,
Y_o,
E_o
);

//
//
//
//

intrarea codificatorului
validare intrare
iesirea codificatorului
validare iesire

84

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

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

// circuit nevalidat la intrare


4b0_000;

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;

always @(A_i or E_i)


// intrari codificator
if (E_i) Y_o <= (1b1 << A_i); else
Y_o <= 8b0;
// circuit nevalidat la intrare
endmodule

3.4

Latch D

Circuitele latch trebuie modelate cu un semnal de mentinere a starii. O atentie


deosebita trebuie acordata modelarii nedorite a unor structuri de tip latch. Urmatorul
cod Verilog modeleaza un circuit multiplexor, similar celui prezentat n figura 3.2.
always @(sel or in0 or in1 or in2 or in3)
case (sel)
2b00 : y <= in0;
2b01 : y <= in1;
2b10 : y <= in2;
2b11 : y <= in3;
endcase

Figura 3.2 Multiplexor 4:1.

O linie lipsa n codul anterior, determina aparitia dupa sinteza a unui latch nedorit,
prezentat n figura 3.3.

86

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

always @(sel or in0 or in1 or in2 or in3)


case (sel)
2b00 : y <= in0;
2b01 : y <= in1;
2b10 : y <= in2;
//2b11 : y <= in3; // optiune lipsa
endcase

Figura 3.3 Latch nedorit ap


arut n urma unei specificatii case incomplete.

Modelul circuitului latch elementar este prezentat n continuare. Se observa faptul


ca latch-ul re-evalueaza iesirea conditionat de semnalul de ceas si de semnalul de
date. Dac
a semnalul de ceas este 1, atunci iesirea copiaz
a intrarea. Altfel, iesirea nu
este re-evaluat
a si, n consecint
a, valoarea acesteia este p
astrat
a (conform definitiei
semnalului de tip reg).
// latch D
always @(clk or d)
if (clk)
q <= d;

3.5

Bistabil D/RS

Bistabilul este circuitul elementar pe care se bazeaza sistemele secventiale. Modelarea


acestuia se face cu specificatie always pornind de la descrierea functionarii acestuia: n
momentele determinate de frontul pozitiv al semnalului de ceas, bistabilul memoreaz
a
intrarea.
// bistabil D
always @(posedge clk)
q <= d;
Se observa ca specificatia q <= d; se executa numai n momentele aparitiei unui
front pozitiv de ceas (@(posedge clk)). Valoarea initiala a bistabilului, nainte de
primul front activ, este neprecizata, fiind x n modelul de simulare. Pentru a modela
un semnal de reset asincron, modelul trebuie modificat astfel:

87

3.5. Bistabil D/RS

// bistabil D cu
always @(posedge
if (reset) q <=
q <=

reset asincron activ high


clk or posedge reset)
1b0; else
d;

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;
//
//
//
//
//
//

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

88

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

//
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

Bistabilul T se modeleaza similar cu bistabilul D, considerand descrierea functionarii


acestuia: dac
a n momentul unui front activ al semnalului de ceas intrarea este egal
a
cu 1, atunci bistabilul T si complementeaz
a starea, altfel bistabilul T si p
astreaz
a
starea.
// clk t | q+
// -----------// ^ 1 | ~q
// ^ 0 | q
// implicit
always @(posedge clk)
if (t) q <= ~q;
Se remarca faptul ca bistabilul T porneste din starea x si are doar posibilitatea
de a-si complementa starea. Ca o consecinta, modelul anterior va prezenta tot timpul q=x. Pentru initializarea bistabilului T este necesara modelarea unei conditii de
resetare, sincrona sau asincrona.
// bistabil T cu reset asincron activ low
// reset_n clk t | q+
// -------------------// 0
x x | 0

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

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

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

Figura 3.4 Simbolul bloc al num


ar
atorului.

Simbolul bloc al numaratorului este prezentat n figura 3.4.


Descrierea porturilor este prezentata n tabelul 3.1:
Descrierea functionarii numaratorului este realizata prin tabelul 3.2.
Cand valoarea numaratorului este egala cu valoarea de la portul count_to, semnalul tercnt (terminal count, n limba engleza) este activat. Semnalul tercnt
poate fi conectat la intrarea load printr-un inversor pentru a initializa sincron numaratorul la valoarea predefinita de la portul data.
Numaratorul are un numar de biti parametrizabil (width) si 2width stari, de la
000...0, pana la 111...1. Numaratorul este activ pe frontul crescator al semnalului
de ceas clk.
Semnalul reset implementeaza aducerea asincrona la zero a numaratorului.
Intrarea count_to are width biti. Cand iesirea numaratorului ajunge la count_to,
iesirea tercnt devine 1 pentru o perioada de ceas.
Intrarea up_dn controleaza daca numaratorul numara n sens crescator
(up_dn = 1) sau n sens descrescator (up_dn = 0), ncepand cu urmatorul front activ
de ceas.
Numaratorul este ncarcat cu valoarea data prin aplicarea valorii logice 0 pe intrarea load. Operatia de ncarcare este sincrona cu frontul pozitiv al semnalului de
ceas.
Intrarea de validare, cen este activa n 1. Cand cen = 1, numararea este activata.
Cand cen = 0, numararea este inhibata, valoarea count ramanand neschimbata.
Modelul Verilog este prezentat n continuare:

n
T

n
V

module counter(
data,
count_to,

92

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

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

Descrierea porturilor num


ar
atorului.

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]

// valoare implicita a numarului de biti


data;
count_to;
up_dn;
load;
cen;
clk;
reset;
count;

93

3.7. Num
ar
atoare sincrone

output

tercnt;

reg[width-1 : 0]

count;

always @(posedge clk or posedge reset)


if (reset) begin
count <= b0;
// initializare asincrona
end
else begin
if (load) begin
count <= data;
// incarcare sincrona
end
else begin
if (cen) begin
if (up_dn) begin
count <= count + 1; // numarare in sens crescator
end
else begin
count <= count - 1; // numarare in sens descrescator
end
end
end
end
// indicator de terminare numarare
assign tercnt = (count == count_to);
endmodule
Figura 3.5 prezinta o aplicatie a numaratorului pentru width=5.

Figura 3.5 Aplicatie a num


ar
atorului pentru width=5.

Formele de unda ale numaratorului sunt prezentate n figura 3.6.


Schema provenita din sinteza codului Verilog ce descrie numaratorul este prezentata n figura 3.7.

94

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

Figura 3.6 Formele de und


a ale num
ar
atorului.

Figura 3.7 Num


ar
ator: structur
a sintetizat
a.

3.8

Automate secventiale sincrone

Automatele secventiale sincrone sunt circuite esentiale pentru descrierea partii de


control a unui sistem digital. In functie de necesitati, automatele se pot proiecta
de tip Mealy sau Moore. Codarea starilor este foarte importanta pentru frecventa
maxima de functionare a automatului proiectat. Pentru frecvente mari, se recomanda
codificarea starilor cu un bit pentru fiecare stare (one-hot, n limba engleza). Acest
stil de codificare este foarte utilizat deoarece asigura obtinerea unei frecvente de lucru
mari chiar daca numarul de bistabile de stare este mai mare decat cel minim. In continuare se prezinta diverse descrieri de automate si modelele Verilog asociate.
Automatele sincrone pot fi modelate n Verilog folosind specificatia case inclusa n
corpul unei specificatii always. Informatia de stare va fi stocata ntr-un registru. In
cadrul fiecarei ramuri a specificatiei case va fi descris comportamentul automatului
pentru starea respectiva.

3.8.1

Semi-automat descris cu o singur


a specificatie

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(

3.8. Automate secventiale sincrone

Figura 3.8 Graf de tranzitii al unui semi-automat.

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;

//definirea codurilor starilor automatului


parameter s0_p = 2b00;
parameter s1_p = 2b01;
parameter s2_p = 2b10;
parameter s3_p = 2b11;
//registrul de stare
reg[1:0] stare_o;
//modelarea tranzitiilor

95

96

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

always @(posedge clk_i or negedge reset_ni)


if (~reset_ni) begin
stare_o <= s0_p;
// stare initiala
end
else begin
case (stare_o)
s0_p:
if (a_i) begin
stare_o <= s0_p;
end
else begin
stare_o <= s1_p;
end
s1_p:
stare_o <= a_i ? s0_p : s2_p;
s2_p:
stare_o <= s3_p;
s3_p:
stare_o <= s0_p;
default: stare_o <= s0_p;
endcase
end
endmodule

3.8.2

Modelarea iesirilor automatelor

In functie de cum sunt proiectate iesirile, automatele pot fi clasificate n:


Mealy: iesirile depind de atat de starea curenta, cat si de intrarile automatului;
Moore: iesirile depind exclusiv de starea curenta a automatului.
In functie de latenta iesirilor, automatele pot fi clasificate n:
Automate imediate: iesirile depind combinational de starea curenta;
Automate cu nt
arziere: iesirile depind cu o ntarziere de un ceas fata de
starea curenta.
Cele patru moduri de modelare a iesirilor sunt exemplificate n continuare.
wire
reg
wire
reg
reg

mealyImediat1_o;
mealyImediat2_o;
mooreImediat_o;
mealyIntarziere_o;
mooreIntarziere_o;

assign mealyImediat1_o = ((stare_o == s1_p) & a_i) |


((stare_o == s3_p) & ~a_i);
always @(stare_o or a_i)
case (stare_o)

3.8. Automate secventiale sincrone

Figura 3.9 Structura sintetizat


a a semi-automatului.

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

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

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);

Modelarea automatelor ca registru de stare si circuit


combinational

O alternativa de modelare a automatelor consta n modelarea structurilor elementare


ce compun automatul: registru de stare si circuite logice combinationale. In acest
caz, exista o declaratie explicita a unui registru de stare nsotit de o specificatie care
determina schimbarea starii n momentul frontului activ al semnalului de ceas.

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;

3.8. Automate secventiale sincrone

parameter start_p = 2b01;


parameter run_p
= 2b10;
reg[1:0]
reg[1:0]
reg
reg
reg

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

CAPITOLUL 3. MODELAREA CIRCUITELOR ELEMENTARE

galben_o <= 1b0;


verde_o <= 1b0;
stareViitoare <= wait_p;
end
endcase
end
endmodule

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.

Figura 3.10 Structura rezultat


a din sintez
a pentru automatul modelat one-hot.

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;

3.8. Automate secventiale sincrone

// declarare bistabile de stare


reg
wait_st;
// 1=automat in starea wait
reg
start_st;
// 1=automat in starea start
reg
run_st;
// 1=automat in starea run
// bistabile de stare
always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) wait_st <= 1b1; else
// stare initiala
wait_st <= (wait_st & ~senzor_i) |
(run_st & ~senzor_i);
always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) start_st <= 1b0; else
start_st <= (wait_st & senzor_i);
always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) run_st
<= 1b0; else
// stare initiala
run_st
<= start_st |
(run_st & senzor_i);
// iesiri imediate
assign rosu_o
= wait_st | start_st;
assign galben_o = start_st;
assign verde_o = run_st;
// verificare: doar o singura stare activa la un moment dat
always @(posedge clk_i)
if ((wait_st + start_st + run_st) != 1b1) begin
$display
("%M %t EROARE: Stare FSM eronata (wait=%b, start=%b, run=%b)",
$time, wait_st, start_st, run_st);
$stop;
end
endmodule

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

4.1. Task-uri si functii

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);

// adresa definita cu define

// interogheaza un indicator pana cand este gasit 0


read(rdaddr_addrL);
while (mpuData_i[15])
read(rdaddr_addrL);
...
end

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

Figura 4.1 Forme de und


a rezultate n urma simul
arii modulului MPU descris cu task-uri.

<function> ::= function <domeniu_sau_tip>? <nume_functie> ;


<declaratii_functie>+
<specificatii>
endfunction
<domeniu_sau_tip> ::= <domeniu>
||= integer
||= real
<declaratii_functie> ::= <declaratii_parametrii>
||= <declaratii_intrari>
||= <declaratii_iesiri>
||= <declaratii_bidirectionale>
||= <declaratii_reg>
||= <declaratii_timp>
||= <declaratii_intregi>
||= <declaratii_reali>
||= <declaratii_evenimente>
Precizarea domeniului (dimensiunii n biti a valorii ntoarse) este optionala. Implicit, functiile ntorc un bit.
Definirea functiei contine o declaratie implicita a unei variabile de tip reg, interna
functiei, avand numele functiei. Dimensiunea acestei variabile este specificata ca
<domeniu> al functiei. In definitia functiei trebuie sa existe o atribuire de valoare catre
aceasta variabila. La iesirea din functie, valoarea variabilei avand numele functiei se
considera ca fiind valoarea la care s-a evaluat functia.
Exemplul urmator prezinta definirea si utilizarea unei functii de calcul a valorii
absolute a unui vector ce reprezinta un numar ntreg cu semn.
// definirea functiei modulo
function [7:0] modulo;
// parametrii formali ai functiei
input[7:0]
formalInitial;
begin
if (~formalInitial[7])
// MSB=0 => numar pozitiv
modulo = formalInitial;

107

4.2. Modelarea memoriilor

else
// MSB=1 => numar negativ
modulo = ~formalInitial + 1;
end
endfunction

// complement fata de 2

// declararea unei sarme


wire[7:0] valoareModulo;
// apelul functiei modulo
assign valoareModulo
= modulo(valoareIntrare);

n
V
Structura rezultata n urma sintezei unui modul al carui comportament
este descris cu functia modulo este prezentata n figura 4.2.

Figura 4.2 Structura rezultat


a n urma sintezei unui modul a c
arui comportament este
descris cu functia modulo.

4.2

Modelarea memoriilor

In marea majoritate a cazurilor, sistemele digitale integrate actuale includ o memorie


sau au acces la o memorie externa.
Memoriile integrate pe chip se genereaza, de obicei, cu programe specializate sub
forma unei descrieri fizice si a uneia comportamentale. Modelul comportamental este
utilizat de catre proiectantul RTL pentru a simula ntreg chip-ul. Modelul fizic se
utilizeaz
a n etapa de realizare fizica a chip-ului.
In cazul folosirii unor chip-uri externe de memorie este necesara o simulare globala
a chip-ului proiectat interconectat la memorie. Din acest motiv este necesar un model
comportamental al memoriei. De obicei producatorii de chip-uri de memorie ofera
(gratuit sau contra cost) modelele comportamentale ale memoriilor produse.
Se poate concluziona ca multi ingineri au ocazia sa scrie (sau macar sa nteleaga si
sa modifice) modele de memorie, fie ca angajat al firmelor producatoare de memorii,
fie ca proiectanti utilizatori de chip-uri de memorie sau memorii integrate.
In continuare este prezentat modelul unei memorii RAM sincrone dual-port. Memoria este parametrizata ca latime si ca adancime.

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

// date din fisier


// nume fisier cu date de initializare
parameter
fileName_p = "dpMem1kx32.dat";
input
// port de scriere
input[addrBits_p-1:0]
input
input[width_p-1:0]
// port de citire
input[addrBits_p-1:0]
input
output[width_p-1:0]
reg[width_p-1:0]

clk_i;

wrAddr_i;
we_ni;
data_i;
rdAddr_i;
re_ni;
data_o;
data_o;

// matrice de memorie ((2^addrBits_p) x width_p)


reg[width_p-1:0]
mem[(1<<addrBits_p)-1:0];
// initializare memorie
integer i;
// index pentru specificatia for
initial begin
if (memInit_p) begin

4.3. Generarea structurilor hardware

109

// matricea de memorie este initializata


if (memZero_p) begin
// matricea de memorie este initializata cu 0
for (i=0;i<(1<<addrBits_p);i=i+1)
mem[i] = b0;
end
else begin
// matricea de memorie este initializata cu date din fisier
$readmemh(fileName_p, mem);
end
end
end
// scriere memorie
always @(posedge clk_i)
if (~we_ni) mem[wrAddr_i] <= data_i;
// citire memorie
always @(posedge clk_i)
data_o <= (~re_ni) ? mem[rdAddr_i] : bz;
endmodule

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

Generarea structurilor hardware

Versiunea 2001 a standardului Verilog introduce o facilitate de a genera instante


multiple de module si primitive. Modulele generate pot fi create conditional sau
particularizate prin specificatii de decizie (if) sau de selectie (case). Patru noi cuvinte
cheie au fost adaugate limbajului Verilog cu aceasta ocazie:
generate: cuvant cheie de nceput a specificatiei;
endgenerate: cuvant cheie de sfarsit a specificatiei;
genvar: declaratie de index (valoare pozitiva) a specificatiei generate;
localparam: constanta locala.
Pentru exemplificarea utilizarii specificatiei generate se prezinta modelul unui
modul de memorie realizat din 4 chip-uri de memorie de 512Mb (32M x 16) folosit
pentru stocarea datelor si un chip de memorie de 256Mb (32M x 8) folosit pentru
stocarea sumelor de control. Memoria rezultata are dimensiunea 2Gb (32M x 64).
Fiecare locatie de 64 de biti are asociati 8 biti (cate 1 bit pentru fiecare byte) pentru
o suma de control.

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

// modul SDRAM 2Gb (32Mx64)


module sdramModule (
sdrCk_i,
// semnal de ceas
sdrCke_i,
// validare ceas (clock enable)
sdrDq_io,
// date
sdrEcc_io,
// date de control (Error Correction Code)
sdrAddr_i,
// adresa
sdrBank_i,
// banca
sdrCs_i,
// selectie chip (chip select)
sdrRas_i,
// ras
sdrCas_i,
// cas
sdrWe_i,
// validare scriere (write enable)
sdrDm_i
// masca de date
);
inout[63:0] sdrDq_io;
inout[7:0] sdrEcc_io;
input[12:0] sdrAddr_i;
input[1:0] sdrBank_i;
input sdrCk_i;
input sdrCke_i;
input sdrCs_i;
input sdrRas_i;
input sdrCas_i;
input sdrWe_i;
input[8:0] sdrDm_i;
genvar i;
generate

// variabila folosita ca index de specificatia generate

// 4 instante SDRAM 512Mb (32M x 16) pentru memoria de date


for (i=0;i<4;i=i+1) begin: Usdram
// activeaza mesajele doar de la un chip de memorie
defparam UsdramDate.Debug = (i==0 ? 1 : 0);
mt48lc32m16a2 UsdramDate(
.Dq
(sdrDq_io[16*i+15:16*i] ),
.Addr (sdrAddr_i
),
.Ba
(sdrBank_i
),
.Clk
(sdrCk_i
),
.Cke
(sdrCke_i
),
.Cs_n (sdrCs_i
),
.Ras_n (sdrRas_i
),
.Cas_n (sdrCas_i
),

111

4.3. Generarea structurilor hardware

.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.

Figura 4.3 Reprezentarea grafic


a a ierarhiei modulului de memorie SDRAM.

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

Figura 4.4 Structura rezultat


a din sintez
a sumatorului de 32 de biti descris cu specificatie
de generare.

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;

// declara bitii de transport


wire[4:0]
carry;
// bitul zero reprezinta transportul de intrare la LSB (=0)
assign carry[0] = 1b0;
// bitul MSB este transportul final al sumatorului
assign co_o = carry[4];
genvar i;
// variabila folosita ca index de specificatia generate
generate
// 4 instante addxC
for (i=0;i<4;i=i+1) begin: Uadder
defparam Uadd.width = 8;
addxC Uadd(
.a_i (a_i[8*i+7:8*i] ),
.b_i (b_i[8*i+7:8*i] ),
.ci_i (carry[i]
),
.s_o (s_o[8*i+7:8*i] ),
.co_o (carry[i+1]
)
);
end
endgenerate

4.4. Modelarea la nivel de poart


a logic
a

113

endmodule

4.4

Modelarea la nivel de poart


a logic
a

Verilog este un limbaj ce contine descrierea urmatoarelor modele ce corespund portilor


logice:
Porti cu intrari multiple (and, nand, or, nor, xor, xnor);
Porti cu iesiri multiple (buf, not);
Porti cu iesiri n trei stari (bufif0, bufif1, notif0, notif1);
Porti cu iesiri fixe (pullup, pulldown).

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

Porti cu iesiri multiple

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

Porti cu iesiri n trei st


ari

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

Porti cu iesiri fixe

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

4.5. Modelarea la nivel de tranzistor

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.

de semnal. De obicei, se folosesc asemenea porti conectate n interiorul modulului pe


intrarile care pot fi lasate neconectate la instantierea modulului respectiv. Existenta
unei porti cu iesire fixa pe intrare nu va permite propagarea starii x n interiorul
modulului. Exista doua tipuri de asemenea porti: pullup (trage semnalul la valoarea
sursei de alimentare, echivalenta starii logice 1) si pulldown (trage semnalul la
masa, echivalenta starii logice 0). De remarcat ca aceste trageri sunt slabe.
Existenta unei alte surse de semnal, va anula efectul portii cu iesire fixa.

Sn
Sintaxa instantierii portilor cu iesiri fixe este urmatoarea:
pullup [nume_instanta] (iesire);
pulldown [nume_instanta] (iesire);

4.5

Modelarea la nivel de tranzistor

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

Dispozitivele ale caror nume ncep cu litera r modeleaza dispozitive rezistive. In


cazul trecerii unui semnal prin aceste dispozitive, taria semnalului se diminueaza.
Tabelul 4.4 descrie functionarea modelelor de tranzistoare MOS.
pmos
rpmos
0
Data 1
x
z

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.

In plus, sunt descrise n limbaj si urmatoarele porti de transmisiune bidirectionale:


tran, tranif0, tranif1, rtran, rtranif0, rtranif1.

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

4.5. Modelarea la nivel de tranzistor

Figura 4.5 Schema a dou


a multiplexoare 2:1 la nivel de tranzistor.

wire GND = 1b0;


nmos N ( OUT, GND, IN );
pmos P ( OUT, VDD, IN );
endmodule // inv
nand3.v
/* Verilog model created from schematic nand3.sch -Feb 17, 2005 23:21 */
module nand3( IN1, IN2, IN3, OUT );
input IN1, IN2, IN3;
output OUT;
wire VDD = 1b1;
wire GND = 1b0;
wire N_1;
wire N_2;
nmos
nmos
nmos
pmos
pmos
pmos

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

Task-uri si functii de sistem

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

4.6. Task-uri si functii de sistem

119

sistemelor descrise n Verilog. Task-urile si functiile sistem nu sunt sintetizabile ci


ofera doar suport pentru testare.
Task-uri de afisare: $display, $write, $strobe, $monitor;
Task-uri de accesare a fisierelor: $fopen, $fdisplay, $readmemb, $readmemh;
Task-uri pentru controlul simularii: $stop, $finish;
Task-uri pentru verific
ari temporale: $setup, $hold, $setuphold, $width,
$period, $skew, $recovery;
Functii referitoare la timpul simularii: $time;
Functii pentru generarea numerelor aleatorii: $random.

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

%d - valoare exprimata n baza 10


%h - valoare exprimata n baza 16
%e - valoare exprimata ca real n format exponential
%f - valoare exprimata ca real n format zecimal
%g - valoare exprimata ca real n formatul cel mai scurt
%c - caracter ASCII
%s - sir de caractere
%m - numele modulului ce a generat mesajul si a ierarhiei acestuia n cadrul
proiectului
%t - timpul curent de simulare
\n - caracter special rand nou
\t - caracter special tab
\\ - caracter special \
\" - caracter special "
%% - caracter special %

4.6.2

Task-uri de accesare a fisierelor

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

4.6. Task-uri si functii de sistem

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];

// memorie de stocare a comenziilor

integer

logPtr;

// pointer la fisier de mesaje

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

mem[(1<<10)-1:0];// memorie (1K X 32)


i;
// variabila index pentru specificatia for

// 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

Task-uri pentru controlul simul


arii

$stop: determina suspendarea simularii. Ulterior se pot lansa comenzi n mod


interactiv cu scop de depanare sau repornirea simularii din punctul n care a
fost suspendata. Apelarea acestui task se face la momentele de timp la care
se doreste oprirea temporara a simularii pentru verificarea unor semnale sau
conditii.
$finish: determina terminarea simularii si a programului de simulare, cu
ntoarcerea controlului sistemului de operare. Apelarea acestui task se face la
rularea simularii fara interfata grafica, eventual cu apeluri succesive ale simularii
cu parametri diferiti.

4.6.4

Task-uri pentru verific


ari temporale

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);

4.6. Task-uri si functii de sistem

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

Functii referitoare la timpul simul


arii

Functia de sistem $time ntoarce valoarea timpului de simulare reprezentata ca un


ntreg de 64 de biti scalata cu valoarea absoluta a unitatii de timp asociata modulului
n care a fost apelata functia. Functia $time poate fi apelata ca parametru din taskuri de afisare cu optiunea %t. Forma de afisare a timpului poate fi modificata prin
apelul task-ului de sistem $timeformat.
Exemplu:
// verificarea parametrilor transmisi la instantiere
initial begin
$display("%M %t EROARE: Valoare interzisa pentru parametrul 1 (%0d).",
$time, param1_p);
$stop;
end
// verificarea protocolului cerere-confirmare
always @(posedge clk)
if (ack && !rq) begin
$display("%M %t EROARE: Confirmare fara cerere.", $time);
$stop;
end
Mesajele produse n fereastra de mesaje sunt:
# readMemSim 0 EROARE: Valoare interzisa pentru parametrul 1 (10).
# readMemSim 135 EROARE: Confirmare fara cerere.

4.6.6

Functii pentru generarea numerelor aleatorii

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;

// intoarce un numar intre -9 si 9

124

CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG

b = {$random} % 10;

reg[7:0] c;
c = $random;

//
//
//
//

intoarce un numar intre 0 si 9


operatorul de concatenare interpreteaza
valoarea intoarsa de $random ca fiind
pozitiva, fara semn

// doar cei 8 LSB intorsi de $random se


// atribuie lui c (poate fi interpretat ca
// un numar pozitiv cu valori intre 0 si 255)

reg[63:0] d;
d = {$random, $random}; // numar aleatoriu pe 64 de biti
parameter seed = 1;

// valoare de initializare a generatorului de


// numere aleatorii

initial
semnal = $random(seed);

4.7

// atribuie semnalului o valoare aleatorie,


// pe baza parametrului seed

Primitive definite de utilizator

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

4.7. Primitive definite de utilizator

<nume_terminal_intrare> <,<nume_terminal_intrare>>*);
<declaratie_UDP>+ <specificatie_UDP_initial>?
<tabela_definitie>
endprimitive

n
V
Tn

Ca exemple, sunt prezentate un multiplexor si un bistabil


D modelate cu primitive definite de catre utilizator.
// multiplexor 2:1
primitive multiplexer (mux, control, dataA, dataB);
output mux;
input control, dataA, dataB;
table
//control dataA dataB mux
0
1
0
: 1;
0
1
1
: 1;
0
1
x
: 1;
0
0
0
: 0;
0
0
1
: 0;
0
0
x
: 0;
1
0
1
: 1;
1
1
1
: 1;
1
x
1
: 1;
1
0
0
: 0;
1
1
0
: 0;
1
x
0
: 0;
x
0
0
: 0;
x
1
1
: 1;
endtable
endprimitive

// Bistabil activ pe front crescator si iesire negata


primitive p_ff (Q, D, CP);
output Q;
reg
Q;
input D, CP;
table
// D
1
0
1
0
1
0
?

CP
(01)
(01)
(x1)
(x1)
(0x)
(0x)
(?0)

:
:
:
:
:
:
:
:

Qt
?
?
1
0
1
0
?

:
:
:
:
:
:
:
:

Qt+1
1; //
0; //
1; //
0;
1;
0;
-; //

front pozitiv de ceas, D=1


front pozitiv de ceas, D=0
comutarea ceasului din sau in x

nici o schimbare pe front negativ

126

CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG

(??) ?
endtable
endprimitive

4.8

-; // ignora fronturile intrarii D

Accesarea semnalelor n ierarhie

Limbajul Verilog asociaza fiecarui identificator un nume unic al ierarhiei n cadrul


proiectului. Acest lucru face posibila apelarea identificatorului si din afara modulului n care a fost declarat acesta. Numele ierarhic este format din atasarea tuturor
modulelor din ierarhie despartite prin caracterul punct (.). Accesarea unor identificatori din afara modulului n care au fost definiti se utilizeaza la spionarea unor
semnale din modulul RTL n scopul verificarii unor conditii logice, mentinand codul
de verificare n afara modulului ce urmeaza a fi sintetizat.
// module ce va fi sintetizat
module rtlModule(
a,
...
);
input[7:0] a;
...
subModule U_subModule(
...
);
...
endmodule
// submodul al modulului ce va fi sintetizat
module subModule(
...
);
...
reg
eroare;
always @(posedge clk) begin
...
eroare <= 1b0;
...
eroare <= 1b1;
...
end
...
endmodule
// modulul de varf, fara porturi
module testTop();

127

4.9. Functii PLI

rtlModule U_rtlModule (
.a (a ),
...
);

// instantiere a modulului proiectat

tbModule U_tbModule (
.a (a ),
...
);

// instantiere a generatorului de semnal

always @(posedge clk)


// daca semnalul "eroare" din submodulul "U_subModule" inclus in
// "U_rtlModule" este atunci se afiseaza un mesaj
if (U_rtlModule.U_subModule.eroare) begin
$display("%M %t NOTA: eroare generata in ...", $time);
$stop;
end
endmodule

4.9

Functii PLI

Verilog ofera posibilitatea de extindere a functionalitatii unui simulator prin PLI


(Programming Language Interface, n limba engleza). Prin PLI se ofera posibilitatea simulatorului de Verilog sa apeleze programe externe, sa realizeze schimburi
de informatii si sa sincronizeze executia programelor externe cu cea a simulatorului. Interfata PLI este specifica doar limbajului de descriere hardware Verilog. Prin
folosirea aplicatiilor PLI se rezolva ntr-un mod facil o serie ntreaga de probleme cum
ar fi:
Incapsularea unor module prin abstractizare si descriere n limbajul C pentru a
le proteja mpotriva copierii structurii modulului sau pentru a mbunatati viteza
de simulare.
Accesarea unor biblioteci de functii complexe puse la dispozitie de limbajele de
programare de nivel nalt (de exemplu, bibliotecile matematice ale limbajului
C).
Citirea unor fisiere ce contin date de intrare pentru un anumit modul. Capabilitatile limbajului Verilog de a citi fisiere ce contin descrieri ale unor stimuli de
intrare sunt medii, iar pentru structuri mai complexe ale fisierelor si vectorilor
de intrare folosirea aplicatiilor PLI devine necesara.
Prelucrarea n mod particular a datelor de iesire. Majoritatea simulatoarelor
ofer
a medii grafice pentru afisarea semnalelor din proiect, dar uneori apar situatii
n care se doreste o formatare diferita a datelor de iesire. De exemplu, n
simularea unui controller video pentru un monitor, o aplicatie PLI poate extrage

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

Crearea unei aplicatii PLI

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

4.9. Functii PLI

#include
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<string.h>
<math.h>
<time.h>
"vpi_user.h"

/* biblioteca standard ANSI C


/* biblioteca in/out standard ANSI C
/* biblioteca de siruri standard ANSI C

*/
*/
*/

/* biblioteca PLI VPI IEEE 1364

*/

Definirea unor rutine C/C++ care s


a fie rulate de c
atre simulator la
apelul sau la compilarea functiei/task-ului din codul Verilog.
Rutina apelata de catre simulator n momentul compilarii log2_compiletf. Aceasta rutina este apelata nainte de nceperea simularii. Scopul ei este de a verifica corectitudinea folosirii functiei/task-ului:
numar de parametri, tipul parametrilor, blocul din care a fost apelata. La
folosirea acestei rutine trebuie sa se tina seama de faptul ca, fiind nainte de
nceperea simularii, structura interna a simulatorului nu este initializata.
De aceea, orice ncercare de a citi sau modifica valori ale semnalelor interne
modulului va genera erori. Rutina parcurge lista argumentelor folosind un
iterator (o structura speciala specifica interfetei PLI) si verifica numarul
si tipul argumentelor.
/************************************************************
* Rutina compiletf
***********************************************************/
int log2_compiletf (char *user_data)
{
vpiHandle systf_handle, arg_itr, arg_handle;
int arg_type;
// citeste parametrii task-ului si verifica argumentul NULL
systf_handle = vpi_handle(vpiSysTfCall, NULL);
arg_itr = vpi_iterate(vpiArgument, systf_handle);
if (arg_itr == NULL)
{ vpi_printf("EROARE: functia $log2 trebuie sa aiba \
un argument.\n");
return (0);
}
// verifica daca primul argument este NULL
arg_handle = vpi_scan(arg_itr);
if (arg_handle == NULL)
{ vpi_printf("EROARE: functia $log2 trebuie sa aiba \
un argument.\n");
return (0);
}
// determina tipul argumentului
arg_type = vpi_get(vpiType, arg_handle);

130

CAPITOLUL 4. NOT
IUNI AVANSATE DE VERILOG

if (arg_type != vpiIntegerVar && arg_type != vpiConstant &&


arg_type != vpiReg && arg_type != vpiParameter &&
arg_type != vpiNet)
{ vpi_printf("EROARE: argumentul functiei $log2 trebuie \
sa fie un intreg, un parametru, \
un semnal reg sau un semnal wire.\n");
return(0);
}
// verifica alte argumente
arg_handle = vpi_scan(arg_itr);
if (arg_handle != NULL)
{ vpi_printf("EROARE: functia $log2 accepta \
un singur argument.\n");
return(0);
}
return (0);
}
Rutina apelata de simulator pentru a determina lungimea, n numar de
biti, a rezultatului ntors de catre functie - log2_sizetf.
In cazul task-urilor, aceasta functie nu este necesara.
/***********************************************************
* Rutina sizetf
**********************************************************/
int log2_sizetf (char *user_data)
{ // functia intoarce o valoare reprezentata pe 32 de biti
return (32);
}
Rutina apelata de catre simulator n momentul simularii, la apelul unei
functii /task n codul Verilog - log2_calltf. Rutina obtine un handle
(pointer tipic interfetei PLI care identifica obiectele din baza de date interna a simulatorului) catre primul argument. Citirea valorii unui obiect
(actiune posibila doar n cazul obiectelor care permit stocarea unei valori)
se poate realiza n mai multe formate. In cazul acestei functii este necesara
obtinerea valorii ca numar ntreg. Dupa calculul logaritmului n baza 2 a
datei de intrare, aplicatia trebuie sa returneze valoarea calculata. Acest lucru se realizeaza prin modificarea valorii obiectului corespunzator functiei
Verilog (identificat prin handle-ul systf_handle). Citirea sau modificarea
unei valori a unui obiect se realizeaza cu ajutorul unor structuri de date
specializate si specifice interfetei PLI s_vpi_value.
/***********************************************************
* Rutina calltf
**********************************************************/
int log2_calltf (char *user_data)
{ vpiHandle systf_handle, arg_itr, arg_handle;

131

4.9. Functii PLI

s_vpi_value arg_val, ret_val;


// formateaza iesirea
ret_val.format = vpiIntVal;
// citeste argumentul functiei utilizand un iterator
systf_handle
= vpi_handle(vpiSysTfCall, NULL);
arg_itr
= vpi_iterate(vpiArgument ,systf_handle);
arg_handle
= vpi_scan(arg_itr);
arg_val.format = vpiIntVal;
vpi_get_value(arg_handle, &arg_val);
// calculaeza logaritmul in baza 2 al
// argumentului de intrare
ret_val.value.integer =
(int) ceil(log(arg_val.value.integer)/log(2));
// intoarce rezultatul
vpi_put_value(systf_handle, &ret_val, NULL, vpiNoDelay);
return (0);
}
Inregistrarea functiei/task-ului Verilog si a rutinelor C/C++ asociate

n structurile specifice simulatorului Verilog. Inregistrarea se realizeaza
folosind o structura de date tipica interfetei PLI - s_vpi_systf_data. Fiecarei
noi functii/task adaugate aplicatiei PLI i va corespunde o asemenea structura
ai carei membri sunt initializati ntr-o functie separata. Aceste structuri trebuie
transmise simulatorului, proces realizat cu ajutorului unui sir global de pointeri (adrese) care contine toate functiile care initializeaza structurile de tipul
s_vpi_systf_data. In cazul exemplului propus exista o singura functie.
/***************************************************************
* Inregistrarea functiei $log2
**************************************************************/
void log2_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysFunc;
// tipul PF al rutinei PLI
tf_data.sysfunctype = vpiSysFuncInt; // tipul de data intors
tf_data.tfname = "$log2";
// numele task-ului Verilog
tf_data.calltf = log2_calltf;
// numele functiei C
// apelate la rulate
tf_data.compiletf = log2_compiletf; // numele functiei C
// apelate la compilare
tf_data.sizetf = log2_sizetf;
// dimensiunea intoarsa
vpi_register_systf(&tf_data);
}

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

Apelarea aplicatiei PLI

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

functii extinse de acces la fisiere


extensie automata a latimii peste 32 de biti
definirea explicita a parametrilor la instantiere
combinarea declaratiilor de porturi si de directie
combinarea declaratiilor de directie si de tip
atribuire initiala pentru semnale de tip reg
nlocuirea termenului registru cu termenul variabila
directive de compilare conditionala mbunatatite
directiva de compilare line
atribute

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

Circuite de prelucrare a impulsurilor

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

Circuite formatoare de impulsuri

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.

Figura 5.1 Formele de und


a pentru generatorul de impulsuri.

135

136

CAPITOLUL 5. PROBLEME REZOLVATE

Problema poate fi rezolvata cu un automat de tip Mealy imediat, pornind de la o


interpretare echivalenta a functionarii:
daca intrarea este gasita 1, iesirea este activata pentru doua perioade de ceas
succesive;
intrarea este indiferent
a (nu se testeaza) n cea de-a doua perioada de ceas.
Graful de tranzitii al unui automat Mealy imediat, a carui functionare se bazeaza
pe observatia anterioara, este prezentat n figura 5.2.
1/1

S1

S0
0/0
/1

Figura 5.2 Graful de tranzitie al automatului care genereaz


a un impuls de l
atime num
ar
par de perioade de ceas.

Se observa ca automatul are numai doua stari ntre care comuta. Descrierea
acestui automat este prezentata n continuare:
reg

stare;

always @(posedge ck) begin


case (stare)
1b0: if (puls_i) begin
stare <= 1b1;
end
else begin
stare <= 1b0;
end
1b1: begin
stare <= 1b0;
end
default: stare <= 1b0;
endcase
end
// activeaza pulsul de iesire daca stare=1 sau daca puls_i=1
assign puls_o = stare ? 1b1 : puls_i;
Se remarca faptul ca automatul definit anterior nu are semnal de reset. In practica,
n cazul acestui exemplu nici nu este necesar. In simulare nsa, automatul trebuie adus
ntr-o stare cunoscuta. Acest lucru se poate face prin existenta clauzei default pentru
specificatia case, fie prin initializarea variabilei reg stare = 1b0;.

5.1. Circuite de prelucrare a impulsurilor

137

Evident, un automat cu doua stari poate fi implementat cu un singur bistabil. In


figura 5.3 se prezinta forma de unda a iesirii unui bistabil comandat astfel:
daca puls_i=1b0 atunci toggle = 1b0 (resetare);
daca puls_i=1b1 atunci toggle = ~toggle (complementare).
Iesirea puls_o este obtinut
a printr-o poarta logica SAU avand ca intrari puls_i
si toggle.
Functionarea circuitului poate fi descrisa astfel: semnalul puls_o este activat daca
semnalul puls_i este activat sau daca semnalul toggle este activat (prin aceasta
ntelegand ca latimea semnalului puls_i a fost un numar impar de pulsuri de ceas).

Figura 5.3 Formele de und


a pentru generatorul de impulsuri si bistabilul toggle.

Codul Verilog care descrie sistemul este prezentat n continuare:


reg
assign

toggle;
puls_o = puls_i | toggle;

always @(posedge ck)


toggle <= puls_i & ~toggle;
Schema rezultata dupa sinteza este prezentata figura 5.4.

Figura 5.4 Generatorul de impulsuri descris ca bistabil T. Schem


a dup
a sintez
a.

Daca se doreste iesirea direct din registru, atunci codul trebuie modificat astfel:
reg
reg

toggle;
puls_o;

always @(posedge ck)


begin
toggle <= puls_i & ~toggle;
puls_o <= puls_i | toggle;
end

138

CAPITOLUL 5. PROBLEME REZOLVATE

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

Generarea unui semnal n avans sau cu nt


arziere

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.

Figura 5.6 Forme de und


a ce descriu bistabilul RS.

Semnalul ntarziat se obtine din iesirea bistabilului RS trecuta printr-un bistabil


de tip D. Semnalul n avans va trebui obtinut combinational. Din analiza formelor de
unda prezentate n figura 5.6, reiese ecuatia logica:
iesire_avans = S | (iesire_rs & ~R)
Codul Verilog care modeleaza acest circuit este prezentat n continuare:

5.1. Circuite de prelucrare a impulsurilor

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;

always @(posedge ck)


if (~reset_ni) begin
rs_o <= 1b0;
end
else begin
if (r_i) begin
rs_o <= 1b0;
end
else begin
if (s_i) begin
rs_o <= 1b1;
end
end
end
// iesire in avans
assign rsAvans_o = s_i | (rs_o & ~r_i);
// iesire intarziata
always @(posedge ck)
if (~reset_ni) begin
rsIntarziat_o <= 1b0;
end
else begin
rsIntarziat_o <= rs_o;

139

140

CAPITOLUL 5. PROBLEME REZOLVATE

end
endmodule
Schema rezultata prin sinteza este prezentata n figura 5.7.

Figura 5.7 Schema rezultat


a prin sintez
a (bistabil RS cu semnale nt
arziate si n avans).

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;

5.1. Circuite de prelucrare a impulsurilor

141

Figura 5.8 Formele de und


a ale semnalelor utilizate la verificarea ipotezei asupra intr
arilor
RS.

rOrS_intarziat = rOrS_r1 | rOrS_r2;


eroare = rOrS_intarziat & rOrS.
Codul Verilog care modeleaza aceste ecuatii este:
wire rOrS;
// SAU logic intre intrari
assign rOrS = r_i | s_i;
reg rOrS_r1;
reg rOrS_r2;
wire rOrS_intarziat;
// intarzieri
always @(posedge ck) begin
rOrS_r1 <= rOrS;
rOrS_r2 <= rOrS_r1;
end
// semnal activ doua tacte "in umbra" semnalelor R sau S
assign rOrS_intarziat = rOrS_r1 | rOrS_r2;
reg eroare;
// verificare conditie eroare si emitere mesaj
always @(posedge ck) begin
if (rOrS_intarziat && rOrS) begin
eroare <= 1b1;
$display("%M %t EROARE: R si S sunt activate incorect", $time);
$stop;
end
else begin
eroare <= 1b0;
end
end

142

CAPITOLUL 5. PROBLEME REZOLVATE

Logica echivalenta circuitului de generare a erorii este prezentata n figura 5.9.

Figura 5.9 Logica echivalent


a circuitului de generare a erorii.

5.2

Circuit secvential pentru recunoastere de pattern

Specificatiile de proiectare ale acestui circuit sunt:


Sistem sincron, cu reset sincron activ n 0;
Recunoaste pattern-ul secvential 11100 prin activarea iesirii potrivire_o pentru un tact.
Numara aparitiile pattern-ului si activeaza iesirea depasire_o la peste 99 de
aparitii. Iesirea depasire_o odata setata nu mai este resetata decat prin activarea intrarii de reset sincron. Recunoasterea pattern-ului se realizeaza si dupa
activarea iesirii depasire_o.
Formele de unda ce descriu functionarea circuitului sunt prezentate n figura 5.10.

Figura 5.10 Formele de und


a ce descriu functionarea circuitului de recunoastere de pattern.

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

5.2. Circuit secvential pentru recunoastere de pattern

S0

reset_n

1
S1

1
S5

S4

S2

S3

Figura 5.11 Graful de tranzitie al automatului pentru recunoastere de pattern.

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

CAPITOLUL 5. PROBLEME REZOLVATE

dataIn_i

potrivire_o
Automat

CU

Numarator
sens
crescator
7

=100

reset_ni

depasire_o

Figura 5.12 Schema bloc a circuitului de recunoastere de pattern, implementat cu automat.

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;

always @(posedge ck) begin


if (!reset_ni) begin
stare <= S0;
end
else begin
case (stare)
S0: if (!dataIn_i) begin
stare <= S0;
end
else begin
stare <= S1;
end
S1: if (!dataIn_i) begin
stare <= S0;
end

5.2. Circuit secvential pentru recunoastere de pattern

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

CAPITOLUL 5. PROBLEME REZOLVATE

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

Figura 5.13 Schema bloc a circuitului de deplasare pentru implementarea recunoasterii de


pattern.

Codul Verilog care modeleaza circuitul de deplasare este prezentat n continuare.

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],

5.3. Verificator de protocol de comunicatie

147

~dataIn_i};
end
Se remarca claritatea sporita a codului propus n varianta cu registru de deplasare
fata de varianta cu automat.

5.3

Verificator de protocol de comunicatie

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.

Figura 5.14 Protocol bazat pe cerere si confirmare.

Pozitia unui modul de monitorizare a protocolului n cadrul unui mediu de simulare


este prezentata grafic n figura 5.15. Se observa faptul ca modulul are doar intrari,
provenite de la cererea modulului sursa si confirmarea modulului destinatie. Modulul
de verificare nu trebuie sa aiba iesiri, mesajele de eroare putand fi prezentate ca mesaje
text. Ca o alternativa, se poate proiecta o iesire cu semnificatia eroare de protocol.
Aceasta iesire ar putea fi folosita, ntr-un sistem cu microprocesor, la activarea unei
ntreruperi.
Abordarea proiectarii acestui circuit porneste de la observatia ca toate erorile
sunt depistate prin corelarea valorilor curente ale cererii si confirmarii cu valorile
anterioare (din tactul precedent) ale acestora. Este nevoie ca cele doua semnale sa fie
memorate n doua bistabile. Iesirile celor doua bistabile, mpreuna cu valorile curente

148

CAPITOLUL 5. PROBLEME REZOLVATE

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.

Figura 5.16 Schema sintetizat


a pentru modulul de verificare a protocolului de comunicare
ntre dou
a module.

n
V

n
T

module monProtocol(
ck_i,
reset_ni,
cerere_i,
confirmare_i,
eroare_o
);

5.3. Verificator de protocol de comunicatie

input
input
input
input
output

ck_i;
reset_ni;
cerere_i;
confirmare_i;
eroare_o;

reg
reg
reg

cerere_r;
confirmare_r;
eroare_o;

always @(posedge ck_i)


if (!reset_ni) begin
cerere_r <= 1b0;
confirmare_r <= 1b0;
end
else begin
cerere_r <= cerere_i;
confirmare_r <= confirmare_i;
end
always @(posedge ck_i)
if (!reset_ni) begin
eroare_o <= 1b0;
end
else begin
case({cerere_i, cerere_r, confirmare_i, confirmare_r})
4b0000: eroare_o <= 1b0;
4b0001: eroare_o <= 1b1;
4b0010: eroare_o <= 1b1;
4b0011: eroare_o <= 1b1;
4b0100: eroare_o <= 1b1;
4b0101: eroare_o <= 1b0;
4b0110: eroare_o <= 1b1;
4b0111: eroare_o <= 1b1;
4b1000: eroare_o <= 1b0;
4b1001: eroare_o <= 1b1;
4b1010: eroare_o <= 1b1;
4b1011: eroare_o <= 1b1;
4b1100: eroare_o <= 1b0;
4b1101: eroare_o <= 1b1;
4b1110: eroare_o <= 1b0;
4b1111: eroare_o <= 1b1;
default: eroare_o <= 1b1;
endcase
end

149

150

CAPITOLUL 5. PROBLEME REZOLVATE

always @(posedge ck_i)


if (eroare_o)
$display("%M %t eroare_o de protocol", $time);
endmodule

5.4

Generarea semnalului de transport al unui


num
ar
ator sincron

Se considera proiectarea unui numarator sincron prevazut cu o iesire de semnalizare


a depasirii (overflow, n limba engleza).
Solutia banala consta n conectarea tuturor iesirilor unui numarator la o poarta
SAU-NU. Descrierea Verilog a acestui caz este prezentata n continuare.

n
n
V
T

always @(posedge Ck) begin


counter <= counter + 1;
ovf
<= ~|counter;
end
Schema rezultata dupa sinteza este prezentata n figura 5.17.

Figura 5.17 Schema sintetizat


a pentru num
ar
atorul cu semnalizare a dep
asirii.

Un dezavantaj consta n faptul ca numarul de intrari n poarta OR este egal cu


numarul de biti ai numaratorului. O solutie independenta de numarul de biti ai
numaratorului este prezentata n continuare. Solutia se bazeaza pe observatia ca
la comutarea din 11...1 n 00...0 este singura data cand bitul cel mai semnificativ comut
a din 1 n 0. Altfel spus, depasirea este marcata de starea 0 a celui mai
semnificativ bit, daca n tactul anterior acest bit a fost 1.

n
V

reg[msb:0] counter;
always @(posedge Ck) begin
counter
<= counter + 1;

151

5.5. Modelarea registrelor

counter_msb_r <= counter[msb];


ovf
<= counter_msb_r & ~counter[msb];
end
Schema rezultata dupa sinteza (figura 5.18) prezinta un bistabil pentru ntarzierea
celui mai semnificativ bit urmat de o poarta AND (cu o intrare inversata). Solutia
este independenta de numarul de biti ai numaratorului.

Figura 5.18 Schema recomandat


a pentru num
ar
atorul cu semnalizare a dep
asirii.

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

Figura 5.19 Schema bloc a unui registru de deplasare, cu nc


arcare si iesire n paralel.

Registrul functioneaza astfel:


Dac
a semnalul de ncarcare ld (Load) este activ, atunci datele de intrare di
sunt stocate n registru.
Dac
a semnalul de deplasare sh (Shift) este activ, atunci cuvantul memorat de
registru este deplasat spre stanga cu un bit.
Tabelul 5.1 prezinta actiunile registrului.
Descrierea Verilog a unui astfel de registru este prezentata n continuare:

152

CAPITOLUL 5. PROBLEME REZOLVATE

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;

always @(posedge ck) begin


if (ld) begin
do <= di;
end
else begin
if (sh) begin
// deplasare stanga realizata prin concatenarea celor mai putini
// semnificativi biti ai registrului cu un bit zero.
do <= {do[2:0], 1b0};
end
end
end
endmodule
Schema acestui registru, sintetizat, este prezentata n figura 5.20.

5.5.2

Registrul cu reactie, LFSR

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

5.5. Modelarea registrelor

Figura 5.20 Registru de deplasare, cu nc


arcare si iesire n paralel, schem
a dup
a sintez
a.

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]

Figura 5.21 Schema bloc a unui LFSR de 8 biti.

Descrierea Verilog a unui astfel de registru este prezentata n continuare:

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]

CAPITOLUL 5. PROBLEME REZOLVATE

reset_ni;
en_i;
data_o;
data_o;

// registru de deplasare cu MSB format din XOR pe vectori


// polinom caracteristic x8+x6+x5+x+1
always @(posedge ck_i) begin
if (~reset_ni) begin
data_o <= b1;
end
else begin
if (en_i) begin
data_o <= {~^{data_o[6], data_o[5], data_o[1], data_o[0]},
data_o[7:1]};
end
end
end
endmodule
In continuare este prezentat un model de LFSR parametrizabil. Modelul are avantajul ca permite mentinerea unui cod unic si transmiterea dimensiunii registrului doar
n momentul instantierii acestuia. Codul are ca parametru dimensiunea registrului
exprimata n numar de biti. Pe baza dimensiunii, se determina printr-o functie constanta polinomul caracteristic. Ulterior, functia XNOR se aplica ntre bitii registrului
mascati cu polinomul asociat. Modelarea are la baza ideea ca poarta AND permite
trecerea unei intrari daca cealalta este 1 sau blocheaza intrarea (0) daca cealalta
intrare este 0. Functiile constante sunt o caracteristica introdusa de Verilog-2001.

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;

// functia de asociere a polinomului cu latimea LFSR


function integer lfsrPoly (input integer width);

5.5. Modelarea registrelor

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

CAPITOLUL 5. PROBLEME REZOLVATE

46: lfsrPoly = 46b0000000000000000000000000110000000000000000011;


47: lfsrPoly = 47b00000000000000000000000000000000000000000100001;
48: lfsrPoly = 48b000000000000000000011000000000000000000000000011;
49: lfsrPoly = 49b0000000000000000000000000000000000000001000000001;
50: lfsrPoly = 50b00000000000000000000001100000000000000000000000011;
default : lfsrPoly = 1b1;
endcase
end
endfunction
wire[width-1:0] polynom;
// asociaza dimensiunii polinomul caracteristic
assign polynom = lfsrPoly(width);
// registru de deplasare cu MSB format din XOR pe vectori
always @(posedge ck_i) begin
if (~reset_ni) begin
data_o <= b1;
end
else begin
if (en_i) begin
data_o <= {~^(data_o & polynom), data_o[width-1:1]};
end
end
end
endmodule

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;

// instantiere LFSR de 3 biti


lfsr #(3) lfsr3(
.ck_i
(ck
),
.reset_ni (reset_n ),
.en_i
(en
),
.data_o
(data3
)
);
// instantiere LFSR de 4 biti
lfsr #(4) lfsr4(
.ck_i
(ck
),
.reset_ni (reset_n ),

157

5.5. Modelarea registrelor

.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

//----------------------------------------------------// Generated by eMap Ver 1.0.11 - eTools 4.1.2


Build Fri 05/28/05

158

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.22 Formele de und


a rezultate n urma simul
arii celor trei modele (RTL, post
sintez
a si post map-are/plasare/rutare) ale LFSR pe 4 biti.

Figura 5.23 Imagine m


arit
a a formelor de und
a rezultate n urma simul
arii. Se remarc
a
nt
arzierile modelului post map-are/plasare/rutare.

// technology FA250L
// Current time: 25_07_2005-12:40:49
//-----------------------------------------------------

//-----------------------------------------------------// Top module


//-----------------------------------------------------module core_lfsr ( data_o, ck_i, reset_ni, en_i );
output [3:0] data_o;
input ck_i, reset_ni, en_i;
wire n32, n31, n30, n29, n28, n27, n26, n25, n24, n23, n22, n21, n19,
n17, n16, n15;
supply1 N_VCC;
assign
assign
assign
assign
assign
assign
assign

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;

5.5. Modelarea registrelor

cell_2413 cell_2413 ( .i2n(n29), .i2(n26) );


cell_2412 cell_2412 ( .i2n(n27), .i2(n22) );
cell_2411 cell_2411 ( .x(n24), .xa(n29), .xb(n21), .xc1(N_VCC),
.xc2(n22) );
cell_2398 cell_2398 ( .i2n(n28), .i2(n27) );
cell_2396 cell_2396 ( .i3n(n21), .ms(n30), .xa(n31), .xb(n29),
.xc1(N_VCC), .xc2(n27), .ck(n15) );
cell_2395 cell_2395 ( .i3n(n19), .ms(n30), .xa(n26), .xb(n24),
.xc1(n21), .xc2(n28), .ck(n15) );
cell_2394 cell_2394 ( .i3n(n22), .ms(n30), .xa(N_VCC), .xb(n26),
.xc1(N_VCC), .xc2(n23), .ck(n15) );
cell_2392 cell_2392 ( .i2n(n30), .i2(n25) );
cell_2382 cell_2382 ( .i3n(n31), .i3(n16) );
cell_2381 cell_2381 ( .i1n(n26), .yc1(n16), .yc2(n17) );
cell_2379 cell_2379 ( .i3n(n23), .ms(n30), .xa(N_VCC), .xb(n26),
.xc1(N_VCC), .xc2(n19), .ck(n15) );
cell_2378 cell_2378 ( .i2n(n32), .i2(n31) );
cell_2377 cell_2377 ( .i1n(n25), .yc1(n32), .yc2(n26) );
endmodule

module cell_2413 ( i2n, i2 );


//PLACED
output i2n;
input i2;
inv6xb u36_inv6xb ( .i2n(i2n), .i2(i2) );
endmodule

module cell_2412 ( i2n, i2 );


//PLACED
output i2n;
input i2;
inv6xb u34_inv6xb ( .i2n(i2n), .i2(i2) );

159

160

CAPITOLUL 5. PROBLEME REZOLVATE

endmodule

module cell_2411 ( x, xa, xb, xc1, xc2 );


//PLACED
//DUMMYPORT U8_nand2x.xc1
output x;
input xa, xb, xc1, xc2;
wire xn, xc;
inv6xa U8_inv6xa ( .x(x), .xn(xn) );
lutx_fe U8_lutx ( .xn(xn), .xa(xa), .xb(xb), .xc(xc) );
nand2x U8_nand2x ( .xc(xc), .xc1(xc1), .xc2(xc2) );
endmodule

module cell_2398 ( i2n, i2 );


//PLACED
output i2n;
input i2;
inv6xb u35_inv6xb ( .i2n(i2n), .i2(i2) );
endmodule

module cell_2396 ( i3n, ms, xa, xb, xc1, xc2, ck );


//PLACED
//DUMMYPORT U21_nand2x.xc1
output i3n;
input ms, xa, xb, xc1, xc2, ck;
wire qn, mn, xn, xc;
inv8xb data_o_reg0_inv8xb ( .i3n(i3n), .i3(qn) );
dffx data_o_reg0_dffx ( .qn(qn), .mn(mn), .ck(ck) );
muxy data_o_reg0_muxy ( .mn(mn), .ms(ms), .m1(xn), .m0(qn) );
lutx_54 U21_lutx ( .xn(xn), .xa(xa), .xb(xb), .xc(xc) );
nand2x U21_nand2x ( .xc(xc), .xc1(xc1), .xc2(xc2) );
endmodule

module cell_2395 ( i3n, ms, xa, xb, xc1, xc2, ck );


//PLACED
output i3n;
input ms, xa, xb, xc1, xc2, ck;
wire qn, mn, xn, xc;
inv8xb data_o_reg3_inv8xb ( .i3n(i3n), .i3(qn) );

5.5. Modelarea registrelor

dffx data_o_reg3_dffx ( .qn(qn), .mn(mn), .ck(ck) );


muxy data_o_reg3_muxy ( .mn(mn), .ms(ms), .m1(xn), .m0(qn) );
lutx_13 U18_lutx ( .xn(xn), .xa(xa), .xb(xb), .xc(xc) );
nand2x U18_nand2x ( .xc(xc), .xc1(xc1), .xc2(xc2) );
endmodule

module cell_2394 ( i3n, ms, xa, xb, xc1, xc2, ck );


//PLACED
//DUMMYPORT U20_lutx.xa, u62_nand2x.xc1
output i3n;
input ms, xa, xb, xc1, xc2, ck;
wire qn, mn, xn, xc;
inv8xb data_o_reg1_inv8xb ( .i3n(i3n), .i3(qn) );
dffx data_o_reg1_dffx ( .qn(qn), .mn(mn), .ck(ck) );
muxy data_o_reg1_muxy ( .mn(mn), .ms(ms), .m1(xn), .m0(qn) );
lutx_3f U20_lutx ( .xn(xn), .xa(xa), .xb(xb), .xc(xc) );
nand2x u62_nand2x ( .xc(xc), .xc1(xc1), .xc2(xc2) );
endmodule

module cell_2392 ( i2n, i2 );


//PLACED
output i2n;
input i2;
inv6xb u37_inv6xb ( .i2n(i2n), .i2(i2) );
endmodule

module cell_2382 ( i3n, i3 );


//PLACED
output i3n;
input i3;
inv8xb u38_inv8xb ( .i3n(i3n), .i3(i3) );
endmodule

module cell_2381 ( i1n, yc1, yc2 );


//PLACED
output i1n;
input yc1, yc2;
wire yc;
inv8xa U22_inv8xa ( .i1n(i1n), .i1(yc) );

161

162

CAPITOLUL 5. PROBLEME REZOLVATE

nand2y U22_nand2y ( .yc(yc), .yc1(yc1), .yc2i(yc2) );


endmodule

module cell_2379 ( i3n, ms, xa, xb, xc1, xc2, ck );


//PLACED
//DUMMYPORT U19_lutx.xa, u63_nand2x.xc1
output i3n;
input ms, xa, xb, xc1, xc2, ck;
wire qn, mn, xn, xc;
inv8xb data_o_reg2_inv8xb ( .i3n(i3n), .i3(qn) );
dffx data_o_reg2_dffx ( .qn(qn), .mn(mn), .ck(ck) );
muxy data_o_reg2_muxy ( .mn(mn), .ms(ms), .m1(xn), .m0(qn) );
lutx_3f U19_lutx ( .xn(xn), .xa(xa), .xb(xb), .xc(xc) );
nand2x u63_nand2x ( .xc(xc), .xc1(xc1), .xc2(xc2) );
endmodule

module cell_2378 ( i2n, i2 );


//PLACED
output i2n;
input i2;
inv6xb u39_inv6xb ( .i2n(i2n), .i2(i2) );
endmodule

module cell_2377 ( i1n, yc1, yc2 );


//PLACED
output i1n;
input yc1, yc2;
wire yc, yc2n;
inv8xa U23_inv8xa ( .i1n(i1n), .i1(yc) );
nand2y U23_nand2y ( .yc(yc), .yc1(yc1), .yc2i(yc2n) );
invi U23_invi ( .yc2n(yc2n), .yc2(yc2) );
endmodule

5.6

Sincronizarea semnalelor la trecerea ntre dou


a
domenii de ceas

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

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

163

de setup si hold ale bistabilelor ce comut


a pe ceasul de destinatie, n cazul n care
semnalul de date se modifica pe un ceas sursa asincron fata de cel de destinatie.
De cele mai multe ori exista cazuri de treceri ale semnalelor ntre doua domenii
de ceas chiar n sisteme simple, cu procesoare nglobate. De exemplu, n cazul n
care procesorul functioneaza pe o frecventa iar restul sistemului pe alta frecventa (de
obicei mai mare), trecerea semnalelor ntre procesor si restul sistemului este inevitabila. In continuarea acestui paragraf vor fi analizate trei tipuri de circuite folosite la
sincronizarea unor tipuri de semnale particulare.
sincronizare de semnal cu evolutie lenta la trecerea dintr-un domeniu de ceas de
frecventa scazuta ntr-un domeniu de ceas de frecventa ridicata;
sincronizare de puls la trecerea dintr-un domeniu de ceas de frecventa ridicata
ntr-un domeniu de ceas de frecvent
a scazuta;
sincronizare de puls la trecerea dintr-un domeniu de ceas de frecventa scazuta
ntrn domeniu de ceas de frecventa ridicata.
Exista circuite simple care realizeaza cu succes sincronizarea semnalelor dar au dezavantajul ca se bazeaza pe o anumita relatie ntre frecventele celor doua domenii (sursa
si destinatie). La circuitele de sincronizare de pulsuri se vor prezenta cele mai simple
solutii dar si solutii mai complexe dar independente de raportul ntre frecventele celor
doua domenii de ceas.

5.6.1

Sincronizarea unui semnal cu evolutie lent


a la trecerea
dintr-un domeniu de ceas de frecvent
a sc
azut
a ntr-un
domeniu de ceas de frecvent
a ridicat
a

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

CAPITOLUL 5. PROBLEME REZOLVATE

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;

// doua bistabile pe ceasul de destinatie


always @(posedge clkF_i) begin
if (~resetF_ni) begin
bitF_r <= 1b0;
bitF_o <= 1b0;
end
else begin
bitF_r <= bitS_i;
bitF_o <= bitF_r;
end
end
endmodule

Figura 5.24 Formele de und


a pentru circuitul de sincronizare a unui semnal la trecerea
dintr-un domeniu de ceas lent ntr-un domeniu de ceas mai rapid.

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. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

5.6.2

165

Sincronizarea unui puls la trecerea dintr-un domeniu de


ceas de frecvent
a ridicat
a ntr-un domeniu de ceas de
frecvent
a sc
azut
a

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

CAPITOLUL 5. PROBLEME REZOLVATE

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;

// intarzie de 4 ori pulsul de pe ceasul sursa


always @(posedge clkF_i) begin
if (~resetF_ni) begin
pulseF_r1 <= 1b0;
pulseF_r2 <= 1b0;
pulseF_r3 <= 1b0;
pulseF_r4 <= 1b0;
end
else begin
pulseF_r1 <= pulseF_i;
pulseF_r2 <= pulseF_r1;
pulseF_r3 <= pulseF_r2;
pulseF_r4 <= pulseF_r3;
end
end
// construieste un puls de latime 5 perioade de ceas sursa
always @(posedge clkF_i) begin

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

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

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.25 Formele de und


a pentru circuitul de sincronizare a unui puls la trecerea dintr-un
domeniu de ceas rapid ntr-un domeniu de ceas mai lent, dependent de raportul frecventelor.

Figura 5.26 Schema rezultat


a din sinteza circuitului de sincronizare a unui puls la trecerea
dintr-un domeniu de ceas rapid ntr-un domeniu de ceas mai lent, dependent de raportul
frecventelor.

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

| | | | | | | | | | | | | | | | | | | | | | | | | |
__|-|______________________________________________
____|---------------|______________________________
|
|
|
|
|
|
|
_________|---------------|_________________________
_________________|---------------|_________________

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

//
//
//
//
//

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;

assign pulseS_w = plsS_r1 & ~plsS_r2;


always @(posedge clkF_i) begin
if (~resetF_ni) begin
syncPendF <= 1b0;
clrF
<= 1b0;
end
else begin
clrF
<= syncPendS;
if (pulseF_i) begin
syncPendF <= 1b1;
end
else begin
if (clrF) begin
syncPendF <= 1b0;
end
end
end
end
always @(posedge clkS_i) begin
if (~resetS_ni) begin
plsS_r1
<= 1b0;
plsS_r2
<= 1b0;
pulseS_o
<= 1b0;
syncPendS <= 1b0;
end
else begin
plsS_r1
<= syncPendF;
plsS_r2
<= plsS_r1;
pulseS_o <= pulseS_w;
if (~plsS_r1) begin
syncPendS <= 1b0;

169

170

CAPITOLUL 5. PROBLEME REZOLVATE

end
else begin
if (pulseS_w) begin
syncPendS <= 1b1;
end
end
end
end
endmodule

Figura 5.27 Formele de und


a pentru circuitul de sincronizare a unui puls la trecerea
dintr-un domeniu de ceas rapid ntr-un domeniu de ceas mai lent, independent de raportul frecventelor.

Figura 5.28 Schema rezultat


a din sinteza circuitului de sincronizare a unui puls la trecerea
dintr-un domeniu de ceas rapid ntr-un domeniu de ceas mai lent, independent de raportul
frecventelor.

5.6.3

Sincronizarea unui puls la trecerea dintr-un domeniu de


ceas de frecvent
a sc
azut
a ntr-un domeniu de ceas de
frecvent
a ridicat
a

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

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

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

/***** COD NERECOMANDAT *****/


module ldSyncBad_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
_|-----------|____________
clkF_i | | | | | | | | | | | | |
ldF_r1 __|-----------|___________
ldF_r2 ____|-----------|_________
ldF_r3 ______|-----------|_______
ldF_o
______|-|_________________
activ lent
^
activ rapid
^

reg
reg

ldF_r1, ldF_r2, ldF_r3;


ldF_o;

always @(posedge clkF_i) begin


if (~resetF_ni) begin
ldF_r1 <= 1b0;
ldF_r2 <= 1b0;
ldF_r3 <= 1b0;
ldF_o <= 1b0;
end
else begin
ldF_r1 <= ldS_i;
ldF_r2 <= ldF_r1;
ldF_r3 <= ldF_r2;
ldF_o <= ldF_r2 & ~ldF_r3;

172

CAPITOLUL 5. PROBLEME REZOLVATE

end
end
endmodule

Figura 5.29 Formele de und


a pentru circuitul nerecomandat de sincronizare a unui puls la
trecerea dintr-un domeniu de ceas lent ntr-un domeniu de ceas mai rapid, independent de
raportul frecventelor. Se observ
a aparitia pulsului activ n domeniul de destinatie naintea
activ
arii acestuia n domeniul surs
a.

In scopul evitarii aparitiei pulsului efect naintea pulsului cauza se recomanda


ntarzierea pulsului cu o perioada de ceas n domeniul sursa si detectarea frontului
cazator al semnalului sincronizat n domeniul de destinatie.
Codul Verilog al circuitului de sincronizare a unui puls la trecerea dintr-un domeniu de ceas lent ntr-un domeniu de ceas mai rapid, independent de frecventele de ceas,
este prezentat n continuare. Formele de unda rezultate sunt prezentate n figura 5.30.
Schema rezultata din sinteza este prezentata n figura 5.31.

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

|
|
|
|
|
_|-------|________________________
_________|-------|________________
| | | | | | | | | | | | | | | | |

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

//
//
//
//

ldF_r1
ldF_r2
ldF_r3
ldF_o

reg
reg
reg

173

__________|-------|______________
____________|-------|____________
______________|-------|__________
______________________|-|________

ldS_r;
ldF_r1, ldF_r2, ldF_r3;
ldF_o;

always @(posedge clkS_i) begin


if (~resetS_ni) begin
ldS_r <= 1b0;
end
else begin
ldS_r <= ldS_i;
end
end
always @(posedge clkF_i) begin
if (~resetF_ni) begin
ldF_r1 <= 1b0;
ldF_r2 <= 1b0;
ldF_r3 <= 1b0;
ldF_o <= 1b0;
end
else begin
ldF_r1 <= ldS_r;
ldF_r2 <= ldF_r1;
ldF_r3 <= ldF_r2;
ldF_o <= ~ldF_r2 & ldF_r3;
end
end
endmodule

5.6.4

Aplicatie la sincronizarea unui bus cu variatie lent


a

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

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.30 Formele de und


a pentru circuitul de sincronizare a unui puls la trecerea
dintr-un domeniu de ceas lent ntr-un domeniu de ceas mai rapid, independent de raportul frecventelor.

Figura 5.31 Schema rezultat


a din sinteza circuitului de sincronizare a unui puls la trecerea
dintr-un domeniu de ceas lent ntr-un domeniu de ceas mai rapid, independent de raportul
frecventelor.

intercepta semnalul de modificare a datelor pe domeniul sursa, de a-l ntarzia si a-l


sincroniza pe ceasul de destinatie (ca un singur bit). Ulterior, acest semnal va determina ncarcarea datelor din registru de pe ceasul sursa ntr-un registru din domeniul
de ceas de destinatie. Conditia de functionare a acestui circuit este ca bus-ul sa fie
modificat rar, nu mai des de odata la trei perioade de ceas sursa (lent).
Figura 5.32 prezinta schema de principiu a sincronizarii unui bus la trecerea ntre
doua domenii de ceas.

5.6.5

Aplicatie la sincronizarea unui bus cu variatie rapid


a
(FIFO)

Solutia prezentata n sectiunea 5.6.4 nu poate fi folosita la transferul rapid al datelor


ntre doua domenii de ceas datorita faptului ca datele trebuie mentinute ntr-un registru n domeniul sursa mai mult de un tact. Presupunand ca datele se modifica
la sursa pe fiecare tact, solutia prezentata nu poate fi folosita. Totusi, este evident
ca, din punct de vedere al ratei de transfer, nu este nici o problema ca datele ce vin
continuu pe o frecventa lenta sa fie transferate fara pierderi ntr-un domeniu de ceas
de frecventa mai mare.
In acest caz solutia consta n folosirea unei memorii FIFO (First-In-First-Out)
asincrona, dual-clock: scrierea si citirea se fac pe ceasuri de frecvente diferite.
Principiul consta n stocarea datelor n memoria FIFO pe ceasul domeniului sursa
si citirea acestora pe ceasul domeniului destinatie. Datorita faptului ca frecventa
de scriere este mai mare decat cea de citire, se pot ntampla cazuri ca memoria
sa se goleasca. Presupunand un flux continuu la intrare, fluxul de iesire din FIFO

175

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

comanda
incarcare
date pe ceas
lent

circuit sincronizare bit


(ldSync_s2f)
comanda
incarcare
date pe ceas
rapid

LD
D

date
pe
ceas
lent

LD
Q

ceas lent (domeniu sursa)


ceas rapid (domeniu destinatie)

date
pe
ceas
rapid

Figura 5.32 Schema de principiu a sincroniz


arii unui bus la trecerea ntre dou
a domenii de
ceas.

va avea momente cand va fi ntrerupt. In functie de raportul celor doua frecvente,


ntreruperile din fluxul de date vor fi mai dese sau mai rare. In orice caz, va trebui
generat un semnal care sa marcheze n domeniul destinatie daca datele sunt sau nu
valide. Care este adancimea necesara pentru memoria FIFO? Teoretic, doua locatii
sunt suficiente. In acest caz datele trebuie citite din FIFO ntr-un interval de o
perioada de ceas lent din momentul n care datele au fost scrise n FIFO. La frecvente
apropiate adancimea de doua niveluri se dovedeste a fi riscanta. Riscul l reprezinta
nendeplinirea timpilor de setup si hold la primul registrul din domeniul destinatie. Sa
presupunem o adancime de 4 locatii. In continuare se prezinta o rezolvare a problemei
cu o memorie FIFO implementata cu registre.
Sunt necesare 4 registre pentru stocarea datelor si doua numaratoare de adrese:
un numarator pentru adresa de scriere incrementat pe ceasul de scriere (sursa) si un
numarator al adresei de citire incrementat pe ceasul de citire (destinatie). Fiecare
din cele doua numaratoare au cate 2 biti si numara doar n sens crescator n mod
circular. Numaratorul adresei de citire este incrementat la fiecare front de ceas sursa
sau ori de cate ori datele de intrare sunt validate (cazul extrem este cand datele de
intrare sunt validate continuu). Simultan, un bistabil T si comuta starea. Iesirea
bistabilului T este un semnal care comuta la fiecare front activ al ceasului sursa.
Acest semnal de un bit este sincronizat pe ceasul destinatie prin trecerea prin doua
bistabile. Detectand ambele fronturi ale acestui semnal se obtine un set de impulsuri
(pe ceasul destinatie) care sunt asociate fiecarei scrieri n memoria FIFO. Acest tren
de impulsuri incrementeaza un numarator al locatiilor pline (scrise si necitite) pe
domeniul de ceas destinatie. Daca acest numarator are valoarea 2, se decide lansarea
unei citiri. La fiecare citire, numaratorul de locatii se decrementeaza. In mod normal,
dupa catva timp, numaratorul de locatii va oscila ntre valorile 1 si 2. Numaratorul de
locatii are posibilitatea de a numara atat n sens crescator, cat si n sens descrescator.
In cazul n care ambele comenzi sunt activate simultan, numaratorul si pastreaza
starea (o scriere la o adresa si o citire de la alta adresa au avut loc simultan).
De remarcat ca, n acest fel, chiar daca actiunile de scriere si citire asincrone pot
fi apropiate n timp, adresele la care au loc acestea sunt la interval de cel putin doua

176

CAPITOLUL 5. PROBLEME REZOLVATE

locatii. Se asigura astfel stabilitatea datelor n momentul trecerii acestora pe ceasul


de destinatie.
Figura 5.33 prezinta schema de principiu a sincronizarii datelor cu memorie FIFO
implementata cu registre.
ckSrc_i

Registru de stocare a datelor (FIFO)


df0

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

Figura 5.33 Schema de principiu a sincroniz


arii datelor cu memorie FIFO implementat
a
cu registre.

Se remarca faptul ca sincronizarea semnalului valid_i implica o ntarziere ntre


momentul cand datele sunt scrise si momentul cand datele sunt citite. Intre aceste
doua momente datele se afla n FIFO. Presupunand un flux continuu de date de
intrare, rezulta o limitare legata de raportul frecventelor ceasurilor sursa si destinatie.
Pentru ca circuitul sa functioneze corect pana la un raport de frecvente sursa/destinatie aproximativ unitar, ar trebui crescuta adancimea FIFO. Folosind mediul de
testare existent pe pagina de web a cartii se poate determina exact valoarea maxima
a raportului de frecvente pan
a la care circuitul prezentat functioneaza corect.

n
V
Tn

Codul Verilog ce modeleaza circuitul FIFO este prezentat n


continuare. Mediul de testare se afla pe situl cartii.
module dataSync(
ckSrc_i,
//
rstSrc_ni,
data_i,
//
valid_i,
//
//
ckDst_i,
//

ceas de frecventa scazuta, domeniul sursa


date de intrare, pe ceasul sursa
validarea datelor de intrare,
poate fi activ (1) tot timpul
ceas de frecventa ridicata, domeniul destinatie

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

rstDst_ni,
data_o,
valid_o

// date de iesire, pe ceasul destinatie


// validarea datelor la iesire

);
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;

// registre care modeleaza cele 4 locatii ale FIFO


always @(posedge ckSrc_i)
if (~rstSrc_ni) begin
df0 <= h0;
df1 <= h0;
df2 <= h0;
df3 <= h0;
end
else begin
if (valid_i && (wrAddr == 2d0)) begin
df0 <= data_i;
end
if (valid_i && (wrAddr == 2d1)) begin
df1 <= data_i;
end
if (valid_i && (wrAddr == 2d2)) begin

177

178

CAPITOLUL 5. PROBLEME REZOLVATE

df2 <= data_i;


end
if (valid_i && (wrAddr == 2d3)) begin
df3 <= data_i;
end
end
// adresa de scriere (pe ceasul domeniului sursa)
always @(posedge ckSrc_i)
if (~rstSrc_ni) begin
wrAddr <= 2b00;
end
else begin
if (valid_i) begin
wrAddr <= wrAddr + 1;
end
end
// complementare daca valid_i=1, pentru sincronizare
always @(posedge ckSrc_i)
if (~rstSrc_ni) begin
validInT <= 1b0;
end
else begin
if (valid_i) begin
validInT <= ~validInT;
end
end
// sincronizare semnal valid_i
always @(posedge ckDst_i)
if (~rstDst_ni) begin
validInDst <= 3b0;
end
else begin
validInDst <= {validInDst[1:0], validInT};
end
// adresa de citire (pe ceasul domeniului destinatie)
always @(posedge ckDst_i)
if (~rstDst_ni) begin
rdAddr <= 2b0;
end
else begin
if (numLocEq2) begin
rdAddr <= rdAddr + 1;
end

5.6. Sincronizarea semnalelor la trecerea ntre dou


a domenii de ceas

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

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.34 Forme de und


a ale circuitului de sincronizare a datelor cu memorie FIFO
implementat
a cu registre.

181

5.7. Interfatarea cu CPU

a datelor implementat cu FIFO.

5.7

Interfatarea cu CPU

Acest paragraf prezinta proiectarea si modelul Verilog al unui bloc de interfatare a


unui controller de memorie (denumit n continuare sdramCntrl) cu un microcontroller
(denumit n continuare CPU). Se presupune ca sistemul (sdramCntrl) este vizibil n
spatiul de adrese al microcontrollerului (CPU).
Protocolul de accesare a registrelor de catre CPU este prezentat n figura 5.36.
Semnalul cpuRq_i informeaza un modul ca o noua tranzactie este ceruta de catre
CPU. Tipul tranzactiei este determinat de cpuRdWr_ni (0 semnifica scriere, 1 semnifica citire). Accesul este confirmat de catre sdramCntrl prin activarea semnalului
cpuAck_o pentru un tact.
Setul de registre de configurare si a accesului CPU la memorie este descris n
tabelul 5.2.
Registru
CONFIG_REG
RDWR_CMD
MSB_ADDR_REG
LSB_ADDR_REG
WRITE_DATA_REG
READ_DATA_REG

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

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.35 Circuitul de sincronizare a datelor cu FIFO - schem


a rezultat
a din sintez
a.

5.7. Interfatarea cu CPU

183

Figura 5.36 Operatii de citire/scriere ntre CPU si un registru intern al sdramCntrl.

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

CAPITOLUL 5. PROBLEME REZOLVATE

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

Porturile modulului de interfatare cu CPU.

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

5.7. Interfatarea cu CPU

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

Figura 5.37 Detalii de implementare a instantierii registrelor si a modului de scriere a


acestora. Toate scrierile se fac sincron pe cpuClk i.

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

CAPITOLUL 5. PROBLEME REZOLVATE

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

Figura 5.38 Detalii de implementare a citirii registrelor si de generare a confirm


arii.

187

5.7. Interfatarea cu CPU

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.

citire RDWR_REG, daca este egal cu 0x0000H, atunci operatia de citire se


considera ncheiata;
citire date din READ_DATA_REG.
Registrul READ_DATA_REG are un regim particular. Teoretic, CPU nu are motive
sa scrie acest registru. Din motive de depanare, s-a permis totusi scrierea acestuia
de catre CPU. Insa, READ_DATA_REG trebuie scris ca urmare a ncheierii operatiei
de citire din memorie cu datele provenite de la portul sysRdData_i. Apare o problema de sincronizare a unui bus de date: datele de intrare sysRdData_i sosesc pe
ceasul sysClk_i si trebuie citite din READ_DATA_REG pe ceasul cpuClk_i. Ideea de
sincronizare consta n nscrierea datelor ntr-un registru temporar n momentul confirmarii operatiei de citire (sysRdRq_o=1 si sysAck_i=1). Ulterior, conditia de citire
(de pe ceasul sysClk_i) este sincronizata pe ceasul cpuClk_i. Dupa sincronizarea
conditiei, datele din registrul temporar se ncarca n registrul READ_DATA_REG de unde
urmeaza a fi preluate de catre CPU. Figura 5.41 prezinta circuitul de sincronizare asociat registrului READ_DATA_REG. Se observa ca acest registru poate fi scris din doua
surse: CPU si restul sistemului.
Modelul Verilog are interfata descrisa n tabelul 5.3 si comportamentul prezentat
n figurile 5.37, 5.38, 5.39, 5.40 si 5.41.

n
V

include "cpuIntfAddr.h"
module cpuIntf(
// Interfata cpu
cpuClk_i,
cpuReset_ni,

// semnal de ceas al CPU


// semnal de reset al CPU, activ in 0

188

CAPITOLUL 5. PROBLEME REZOLVATE


pulseSync_f2s
ld4

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)

Figura 5.40 Sincronizarea RDWR REG.

cpuCs_ni,
cpuAddr_i,
cpuRdWr_ni,
cpuData_o,
cpuData_i,
cpuRq_i,
cpuAck_o,
// Interfata sys
sysClk_i,

//
//
//
//
//
//
//

selectare dispozitiv activ in 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)
sysReset_ni,
// semnal de reset activ in zero
sysCasLatency_o, // latenta CAS
sysSdramCntrlEn_o,// validare pornire sdramCntrl
sysBurstSize_o,
// dimensiune burst
sysFrecv_o,
// frecventa exprimata in MHz
sysAddr_o,
// adresa de acces la memorie
sysWrData_o,
// data ce urmeaza a fi scrisa in SDRAM
sysWrRq_o,
// comanda de scriere in memorie
sysRdData_i,
// data ce a fost citita din SDRAM
sysRdRq_o,
// comanda de citire din memorie
sysAck_i
// confirmare a comenzii de la sistem

);

189

5.7. Interfatarea cu CPU


pulseSync_f2s
cpuData_i

sysAck_i

16

ld30

sysRdRq_o
LD
sysRdData_i
ldCpu Dcpu

ldSys

16

Dsys

rdData

Figura 5.41 Sincronizarea READ DATA REG.

// 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

CAPITOLUL 5. PROBLEME REZOLVATE

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;

// semnal care valideaza o scriere


assign doWr = ~cpuCs_ni & ~cpuRdWr_ni & cpuRq_i;
// CONFIG_REG 0x00 ***************************************
// semnal de incarcare pentru registrii de la adresa CONFIG_REG
assign ld0 = (doWr & (cpuAddr_i == CONFIG_REG));
// registrul pe cpuClk_i
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
{frecv, burstSize, sdramCntrlEn, casLatency} <= 15b0;
end
else begin
if (ld0) begin

5.7. Interfatarea cu CPU

191

{frecv, burstSize, sdramCntrlEn, casLatency} <=


{cpuData_i[15:8], cpuData_i[6:0]};
end
end
end
// sincronizarea semnalului ld0 pe domeniul
// de ceas mai rapid (sysClk_i)
ldSync_s2f i_config_reg(
.clkS_i
(cpuClk_i
),
.resetS_ni (cpuReset_ni ),
.ldS_i
(ld0
),
.clkF_i
(sysClk_i
),
.resetF_ni (sysReset_ni ),
.ldF_o
(ld0Sys
)
);
// registrul CONFIG_REG sincronizat pe domeniul
// de ceas mai rapid (sysClk_i)
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
{sysFrecv_o, sysBurstSize_o, sysSdramCntrlEn_o, sysCasLatency_o}
<= 15b0;
end
else begin
if (ld0Sys) begin
{sysFrecv_o, sysBurstSize_o, sysSdramCntrlEn_o, sysCasLatency_o}
<= {frecv, burstSize, sdramCntrlEn, casLatency};
end
end
end
// RDWR_REG 0x04 ***************************************
// semnal de incarcare pentru registrii de la adresa RDWR_REG
assign ld4 = (doWr & (cpuAddr_i == RDWR_REG));
// registrul pe cpuClk_i
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
wrCmd <= 1b0;
rdCmd <= 1b0;
end
else begin
if (ld4) begin
rdCmd <= cpuData_i[8];
wrCmd <= cpuData_i[0];
end

192

CAPITOLUL 5. PROBLEME REZOLVATE

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};

5.7. Interfatarea cu CPU

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

CAPITOLUL 5. PROBLEME REZOLVATE

// LSB_ADDR_REG 0x10 ***************************************


// semnal de incarcare pentru registrii de la adresa LSB_ADDR_REG
assign ld10 = doWr & (cpuAddr_i == LSB_ADDR_REG);
// registrul care memoreaza adresa de acces la memorie (LSB)
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
lsbAddr <= 1b0;
end
else begin
if (ld10) begin
lsbAddr <= cpuData_i;
end
end
end
// registrul care memoreaza adresa de acces la memorie (MSB)
// pe domeniul de ceas mai rapid (sysClk_i)
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
sysAddr_o
<= 25b0;
sysWrData_o <= 16b0;
end
else begin
if (sysWrCmd_r[3] || sysRdCmd_r[3]) begin
sysAddr_o
<= {msbAddr, lsbAddr};
sysWrData_o <= wrData;
end
end
end
// WRITE_DATA_REG 0x20 ***************************************
// semnal de incarcare pentru registrii de la adresa WRITE_DATA_REG
assign ld20 = doWr & (cpuAddr_i == WRITE_DATA_REG);
// registrul care memoreaza datele ce urmeaza a fi scrise in memorie
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
wrData <= 1b0;
end
else begin
if (ld20) begin
wrData <= cpuData_i;
end
end
end

5.7. Interfatarea cu CPU

// READ_DATA_REG 0x30 ***************************************


// semnal de incarcare pentru registrii de la adresa READ_DATA_REG
assign ld30 = doWr & (cpuAddr_i == READ_DATA_REG);
// semnal de incarcare pentru registrul ce va contine
// datele citite de la memoria SDRAM
assign ldSys_f = sysAck_i & sysRdRq_o;
// registrul ce va contine
// datele citite de la memoria SDRAM
always @(posedge sysClk_i) begin
if (!sysReset_ni) begin
sysRdData_r <= 16b0;
end
else begin
if (ldSys_f) begin
sysRdData_r <= sysRdData_i;
end
end
end
// registrul care memoreaza datele care au fost citite din memorie
always @(posedge cpuClk_i) begin
if (!cpuReset_ni) begin
rdData <= 16b0;
end
else begin
if (ldSys_s) begin
rdData <= sysRdData_r;
end
else begin
if (ld30) begin
rdData <= cpuData_i;
end
end
end
end
// sincronizarea semnalului de incarcare ldSys_f
// pe domeniul de ceas mai lent (cpuClk_i)
pulseSync_f2s i_read_data_reg(
.clkF_i
(sysClk_i
),
.resetF_ni (sysReset_ni ),
.pulseF_i
(ldSys_f
),
.clkS_i
(cpuClk_i
),
.resetS_ni (cpuReset_ni ),

195

196
.pulseS_o

CAPITOLUL 5. PROBLEME REZOLVATE

(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

5.8. Multiplicator secvential

portamentul restului sistemului, sdramCntrl. Reprezentarea grafica a mediului de


testare este prezentata n figura 5.42 iar codul Verilog se afla n ntregime pe situl
cartii.

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

Figura 5.42 Mediu de testare pentru interfata CPU.

5.8

Multiplicator secvential

Un sistem digital complex poate fi structurat n doua componente principale:


cale de date si
cale de control.
Automatele constituie calea de control n cadrul circuitelor digitale asigurand semnale
de comanda si control caii de date.
Acest paragraf prezinta proiectarea unui multiplicator secvential, structurat n
cale de date si cale de control. In figura 5.43 este prezentata schema bloc a unui
multiplicator secvential ce foloseste metoda adunarilor repetate. Pentru simplificarea
schemei nu au fost reprezentate semnalele de ceas si reset prezente la intrarea tuturor
registrelor.
Modelul Verilog asociat multiplicatorului prezinta un model de nivel nalt, structural, care instantiaza alte doua module asociate caii de date si caii de control.

n
n
V
T

module mult (
ck,
reset_ni,
start_i,
opA_i,
opB_i,

198

CAPITOLUL 5. PROBLEME REZOLVATE

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

Figura 5.43 Schema bloc a multiplicatorului.

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;

// semnale intre calea de control si calea de date


wire
opBzero;
// operandul B a devenit 0
// (terminare multiplicare)
wire
ldRez;
// incarca rezultat
wire
ldOp;
// incarca operanzi
wire
decB;
// decrementeaza operand B
wire
ldAcc;
// incarca registru acumulator
multCaleControl umultCaleControl(
.ck
(ck
),
.reset_ni
(reset_ni
),
.start_i
(start_i
),
.rezValid_o (rezValid_o ),
.opBzero_i (opBzero
),

rezultat_o

199

5.8. Multiplicator secvential

.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;

// semnale intre calea de control si calea de date


output
opBzero_o;
// operandul B a devenit 0
// (terminare multiplicare)
input
ldRez_i;
// incarca rezultat

200
input
input
input

CAPITOLUL 5. PROBLEME REZOLVATE

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

5.8. Multiplicator secvential

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)

// semnale intre calea de control si calea de date


input
opBzero_i;
// operandul B a devenit 0
// (terminare multiplicare)
output
ldRez_o;
// incarca rezultat
output
ldOp_o;
// incarca operanzii
output
decB_o;
// decrementeaza operand B
output
ldAcc_o;
// incarca registru acumulator
//registru de stare al FSM
reg[2:0]
stare;
//modelarea tranzitilor FSM
always @(posedge ck) begin
if (~reset_ni) begin // reset sincron
stare <= INIT;
end
else begin
case (stare)
INIT: if (start_i)
stare <= DEC;
DEC:
if (opBzero_i)
stare <= FINAL;
else
stare <= ADD;
ADD:
if (opBzero_i)
stare <= FINAL;
else
stare <= DEC;
FINAL:
stare <= INIT;
default: stare <= INIT;
endcase

202

CAPITOLUL 5. PROBLEME REZOLVATE

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.

Figura 5.44 Schema multiplicatorului dup


a etapa de sintez
a.

5.9

Modelarea si testarea memoriilor

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.

5.9. Modelarea si testarea memoriilor

Figura 5.45 Schema multiplicatorului dup


a etapa de sintez
a - cale de control.

Figura 5.46 Schema multiplicatorului dup


a etapa de sintez
a - cale de date.

203

204

CAPITOLUL 5. PROBLEME REZOLVATE

Memoriile cu un singur port permit, la un moment dat, accesul la o singura locatie


de memorie fie pentru citire, fie pentru scriere. Structura si semnificatia porturilor
unei astfel de memorii este prezentata n tabelul 5.4. Operatiile de scriere si citire a
Port
clk
addr
di
ce
we
oe
dout

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:

Figura 5.47 Forme de und


a la citirea memoriei.

Figura 5.48 Forme de und


a la scrierea memoriei.

Modelul Verilog al unei memorii cu un port este prezentat n continuare:

n
V

module singlePortMem (
clk,
addr,
di,

5.9. Modelarea si testarea memoriilor

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 de 256 de locatii a cate 16 biti

// 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

CAPITOLUL 5. PROBLEME REZOLVATE

$readmemb ("memContent.dat", mem);


end
else begin
if (initLocation == "zero") begin
for (i=0; i<=255; i=i+1)
mem[i] = 0;
end
else begin
if (initLocation == "adresa") begin
for (i=0; i<=255; i=i+1)
mem[i] = i;
end
else
begin
if (initLocation == "x") begin
for (i=0; i<=255; i=i+1)
mem[i] = bx;
end
else begin
if (initLocation == "aleatoriu") begin
for (i=0; i<=255; i=i+1)
mem[i] = $random;
end
else begin
$display("%M EROARE: parametru incorect initLocation=%s",
initLocation);
$stop;
end
end
end
end
end
end
endmodule
Pentru testarea unei memorii cu un singur port se realizeaza un mediu de testare
n care se instantiaza memoria care se doreste a fi testata si se descriu task-urile care
implementeaz
a operatiile unei memorii.
Modul de initializare a memoriei este determinat de parametrul initLocation.
Dac
a initLocation="fisier", initializarea se face cu datele dintr-un fisier extern, cu comanda $readmemb. Formatul fisierului de intrare este prezentat n
continuare:
0000000000000000
0000000000000001
0000000000000010
0000000000000011

//
//
//
//

continutul
continutul
continutul
continutul

de
de
de
de

la
la
la
la

locatia
locatia
locatia
locatia

0
1
2
3

5.9. Modelarea si testarea memoriilor

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

CAPITOLUL 5. PROBLEME REZOLVATE

// Valoarea care se inscrie la locatia pointata de adresa


di <= di_task;
// Semnalele de control setate pentru operatia de scriere
we <= 1b1;
oe <= 1b1;
ce <= 1b1;
@(posedge clk);
end
endtask
Apelul task-ului de scriere este de forma:
Write(<adresa de scriere>, <data scrisa>);
Task-ul de citire a continutului ntregii memorii este prezentat n continuare:
task Dump;
input[0:100] file_name;
integer k;
integer file_id;
begin
file_id = $fopen(file_name);
$display("%M %t NOTA Citire/dump continut memorie", $time);
for (k=0; k<256; k = k + 1) begin
$fdisplay (file_id,"adresa=%d, data=%hH",
k, UsinglePortMem.mem[k]);
$display ("adresa=%d, data=%hH",
k, UsinglePortMem.mem[k]);
end
$fclose(file_id);
end
endtask
In urma apelului task-ului Dump rezulta un fisier care contine o copie a memoriei.
Formatul fisierului de iesire este prezentat n continuare:
#
#
#
#
#
#
#
#

tstSinglePortMem.Dump 5 NOTA Citire/dump continut memorie


adresa=
0, data=0000H
adresa=
1, data=0001H
adresa=
2, data=0002H
adresa=
3, data=0003H
adresa=
4, data=0004H
adresa=
5, data=0005H
adresa=
6, data=0006H

Un model Verilog care foloseste task-urile prezentate mai sus este prezentat n
continuare:

n
T

5.9. Modelarea si testarea memoriilor

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

CAPITOLUL 5. PROBLEME REZOLVATE

// instanta de memorie testata


defparam UsinglePortMem.initLocation = "adresa";
// "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
singlePortMem UsinglePortMem (
.clk
(clk ),
.addr
(addr ),
.di
(di
),
.ce
(ce
),
.we
(we
),
.oe
(oe
),
.dout
(dout )
);
endmodule

5.10

Modelarea multiplexoarelor

Multiplexoarele sunt circuite foarte frecvent utilizate. Ele implementeaza o functie de


selectie. Multiplexoarele se pot modela folosind operatorul ternar ?:.
assign y = sel ? i1 : i0;
Acest model este foarte folosit n majoritatea cazurilor. Paragrafele urmatoare
prezinta cateva limitari ale acestui model si propune solutii de mbunatatire a calitatii
modelului.

5.10.1

Multiplexor modelat cu valori neprecizate

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

5.10. Modelarea multiplexoarelor

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.

always @(sel or in0 or in1) begin


out1 <= sel ? in1 : in0;
if (sel) out2 <= in1; else
out2 <= in0;
if (sel) out3 <= in1; else
if (!sel) out3 <= in0; else
out3 <= 1bx;
out4 <= (sel & in1) | (~sel & in0);
end
out1 este modelat clasic. Daca sel=0, atunci out1=in0. Daca sel=1, atunci
out1=in1. Daca sel=1bx sau sel=1bz, atunci se evalueaza ambele expresii in0 si
in1. Daca sunt gasite egale, out1 primeste aceasta valoare (chiar daca sel=1bx).
Altfel spus, daca sel=1bx, in0=in1=1b0, atunci y=1b0. Acest lucru este corect
daca 1bx este interpretat ca valoare indiferenta dar egala (n realitate) cu 1b0 sau
1b1. Insa, acest lucru poate ascunde o conditie 1bx aparuta nedorit pe selectie.
out2 este modelat cu specificatie de decizie. In acest caz decizia if (sel) trebuie ntelesa ca if (sel==1b1), adica ntoarce adevarat daca sel=1b1 si fals n
celelalte cazuri. Ca efect, daca sel=1b1 atunci out2=in1, altfel out2=in0. Diferenta ntre out1 si out2 se manifesta cand sel=1bx si sel=1bz. In aceste cazuri,
out2=in0 dar out1 depinde de valorile ambelor intrari de date.
Desi mai neobisnuita la prima vedere, modelul de multiplexor out3 aduce un
avantaj: semnaleaza cu out3=1bx daca sel=1bx, indiferent de intrarile de date.
Acest lucru poate fi util n simularea comportamentala. Desi, la prima vedere,
conditia if (!sel) este gasita (n acea pozitie) tot timpul adevarata, acest lucru
nu este adevarat daca sel=1bx sau sel=1bz. In aceste ultime cazuri, se atribuite
out3=1bx.
A patra forma modeleaza multiplexorul pe baza ecuatiei sale logice. Se observa
ca iesirea nu poate avea valoarea 1bz. In plus, spre deosebire de out1, out4=1bx
daca in1=in0=1b1 dar sel=1bx.
Se demonstreaza astfel ca, desi modelele sunt echivalente pentru valorile logice
elementare 0 si 1, ele se comporta diferit imediat ce intrarile au alte valori (x si z).
Este interesat de studiat cum se comporta modelele de multiplexoare n cazul

212

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.49 Formele de und


a pentru circuitul multiplexor 2:1.

existentei unor conexiuni externe particulare. De exemplu, conectarea intrarii de


selectie la una din intrari (in0=sel) ar echivala functionarea multiplexorului cu cea
a unei porti logice out = sel & in1.
Multiplexorul instantiat n continuare are, conform algebrei Booleene, iesirea independenta de selectie (out=1b0 pentru orice valoare sel). Daca sel=1b0, atunci
out=in0=sel=1b0. Daca sel=1b0, atunci out=in1=1b0. Totusi, aparitia unei
valori sel=1bx sau sel=1bz produce out=1bx.
muxX UmuxX(
.sel
(sel ),
.in0
(sel ),
.in1
(1b0),
.out1 (out )
);

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

5.10. Modelarea multiplexoarelor

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

// reset global sincron

// set sincron

// reset sincron

In urma sintezei acestui cod si a implementarii circuitului n tehnologie eASIC


rezulta urmatorul netlist.
// Ver 1.0.2
Build Tue 01/11/05
// Technology //
E-cell netlist after mapping
//
***** Verplex FORMAT *****
module core_srFf (iesire_o, clk_i, reset_ni, rSync_i,
sSync1_i, sSync2_i);
output iesire_o;
input clk_i, reset_ni, rSync_i, sSync1_i, sSync2_i;
wire
n9, n8, n7, n6, n5, n4, n3;
supply1 N_VCC;
supply0 N_GND;
assign
assign
assign
assign
assign
assign

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

CAPITOLUL 5. PROBLEME REZOLVATE

.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

5.10. Modelarea multiplexoarelor

eCell-ul srFf_cell_17796 foloseste din resursele interne inv6xa, inv8xb, dffx,


muxy, lutx_7f, nand2x. eCell-ul srFf_cell_17780 foloseste din resursele interne
muxy, inv6xa, lutx_02, nand2x. Aceste resurse existente n eCell-uri au comportamentul descris n biblioteci specifice tehnologiei. Reprezentarea grafica a netlist-ului
este prezentata n figura 5.50.
reset_ni

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

Figura 5.50 Reprezentarea grafic


a a netlist-ului de bistabil RS la nivel de poart
a logic
a.

Componenta muxy este descrisa n biblioteca easic_TA.v prin instantierea unor


porti definite n limbaj si a apelarii unei primitive.
celldefine
// INVERTER
// mn = ms ? !m1 : !m0
module muxy (mn, m0, m1, ms);
output mn;
input m0;
input m1;
input ms;
protect
specify
// Pin-to-pin timing.
(m0 => mn) = (0.027:0.039:0.061,0.026:0.039:0.065);
(m1 => mn) = (0.025:0.036:0.058,0.028:0.042:0.071);
if(!m0&m1) (ms => mn) = (0.049:0.074:0.120,0.042:0.063:0.106);
if(m0&!m1) (ms => mn) = (0.036:0.051:0.080,0.047:0.072:0.118);
ifnone (ms => mn) = (0.049:0.074:0.120,0.042:0.063:0.106);
endspecify
// Gate-level description.
not _i0 (_n1,m1);

// poarta definita in Verilog

216

CAPITOLUL 5. PROBLEME REZOLVATE

not _i1 (_n2,m0);


p_mux21 _i2 (mn, _n1, _n2, ms);

// poarta definita in Verilog


// primitiva

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

De multe ori, multiplexoarele au ca date de intrare bus-uri. Un multiplexor 2:1 pe bus


de 32 biti este echivalent cu 32 de multiplexoare 2:1 pe bit. Modelarea acestora este
identica cu cea prezentata n paragraful precedent, cu deosebirea ca iesirea si intrarile
de date sunt de tip bus. Intrarea de selectie este de 1 bit si este conectata la toate
intrarile de selectie acele celor 32 de multiplexoare 2:1.
Un caz particular l constituie cazul n care se doreste implementarea unei operatii
de mascare pe bus. In acest caz, atat datele de intrare, cat si intrarea de selectie
sunt bus-uri. Desi circuitul hardware rezultat este acelasi (32 de multiplexoare 2:1),
faptul ca intr
arile de selectie sunt diferite necesita o modelare particulara. Modelarea
acestui circuit se poate face considerand operatori pe bus:
module muxBus(
data0,

5.11. Controller pentru memorie SDRAM

217

data1,
sel,
out
);
input[7:0]
input[7:0]
input[7:0]
output[7:0]

data0;
data1;
sel;
out;

assign out = (~sel & data0) | (sel & data1);


endmodule
Se observa ca operatorii ~, & si | sunt operatori pe vectori, rezultat fiind tot un
vector.

5.11

Controller pentru memorie SDRAM

Acest paragraf prezinta codul Verilog asociat controllerului SDRAM. Descrierea n


detaliu a controllerului SDRAM este prezentata n volumul ntai a acestei carti. Dupa
prezentarea modelului Verilog asociat si a structurilor hardware rezultate prin sinteza
se vor trata doua probleme specifice legate de testarea acestui modul:
verificarea corectitudini acceselor la memorie prin modelarea unei memorii de
referinta (oglinda);
modelarea unor generatoare de comenzi complexe.

5.11.1

Modelul Verilog al controllerului SDRAM

Secventierea activitatii controllerul SDRAM este asigurata de un automat sincron a


carui organigrama este reluata n figura 5.51.
Codul Verilog asociat este prezentat n continuare. Schema rezultata din sinteza
este prezentata n figura 5.52. Se observa ca datorita modului de codare one-hot
(specific cazurilor n care se doreste functionarea la frecvente nalte) automatul are
o prezentare grafica diferita de cea clasica. Registrul de stare este realizat din
bistabile individuale iar circuitul logic este mprastiat n jurul acestora.
// bistabile de stare (stari codificate "one-hot")
reg
initSt;
reg
nopSt;
reg
arfSt;
reg
idleArfSt;
reg
actSt;
reg
idleActSt;
reg
operSt;
reg
idle1St;

218

CAPITOLUL 5. PROBLEME REZOLVATE

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

Figura 5.51 Organigrama automatului controllerului SDRAM.

5.11. Controller pentru memorie SDRAM

reg
reg
reg
reg

idle2St;
idle3St;
idleWrSt;
prSt;

// automat de stare, codat "one-hot"


// (un bistabil asociat fiecarei stari)
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
initSt <= 1b1;
end
else begin
initSt <= (initSt & ~lmr);
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
nopSt <= 1b0;
end
else begin
nopSt <= (initSt & lmr) |
(nopSt & ~rfRq & ~rq_i) |
(idleArfSt & arTerm) |
prSt;
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
arfSt <= 1b0;
end
else begin
arfSt <= (nopSt & rfRq);
end
end
always @(posedge
if (~reset_ni)
idleArfSt <=
end
else begin
idleArfSt <=
end
end

clk_i or negedge reset_ni) begin


begin
1b0;

arfSt |
(idleArfSt & ~arTerm);

219

220

CAPITOLUL 5. PROBLEME REZOLVATE

always @(posedge clk_i or negedge reset_ni) begin


if (~reset_ni) begin
actSt <= 1b0;
end
else begin
actSt <= (nopSt & ~rfRq & rq_i);
end
end
always @(posedge
if (~reset_ni)
idleActSt <=
end
else begin
idleActSt <=
end
end

clk_i or negedge reset_ni) begin


begin
1b0;

actSt;

always @(posedge clk_i or negedge reset_ni) begin


if (~reset_ni) begin
operSt <= 1b0;
end
else begin
operSt <= idleActSt;
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
idle1St <= 1b0;
end
else begin
idle1St <= operSt;
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
idle2St <= 1b0;
end
else begin
idle2St <= idle1St;
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin

5.11. Controller pentru memorie SDRAM

221

idle3St <= 1b0;


end
else begin
idle3St <= idle2St;
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
idleWrSt <= 1b0;
end
else begin
idleWrSt <= idle3St & ~rwnCrt;
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
prSt <= 1b0;
end
else begin
prSt <= (idle3St & rwnCrt) |
idleWrSt;
end
end
Registrul de initializare este modelat ca un registru de 18 biti initializat la reset cu
valoarea 18b1 si deplasat spre stanga la fiecare tact dupa inactivarea semnalului de
reset. Pentru o mai buna ntelegere a codului, anumiti biti, ce corespund actiunilor
ce au loc la initializare au fost redenumiti cu nume sugestive. Figura 5.53 prezinta
schema rezultata din sinteza pentru registrul de initializare.
// denumire alternative pentru usurinta intelegerii codului
wire
lmr;
// "load mode register" la initializare
wire
ar1;
// primul auto-refresh la initializare
wire
ar2;
// al doilea auto-refresh la initializare
wire
pa;
// "precharge all" la initializare
/ *** registre de stare *************************************
// registru de deplasare utilizat pentru initializare
always @(posedge clk_i or negedge reset_ni) begin
if(~reset_ni) begin
// la reset, se activeaza bitul cel mai putin semnificativ
initShReg <= 18b1;
end
else begin
initShReg <= {initShReg[16:0], 1b0}; // deplasare stanga
end

222

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.52 Automatul controllerului SDRAM - schem


a sintetizat
a.

5.11. Controller pentru memorie SDRAM

223

end
// secventa de initializare SDRAM
assign lmr
= initShReg[17];
assign ar2
= initShReg[10];
assign ar1
= initShReg[3];
assign pa
= initShReg[1];

Figura 5.53 Registrul de initializare al controllerului SDRAM - schem


a sintetizat
a.

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;

// validarea emiterii datelor pe


// bus-ul de datetri-state

// *** iesiri de control spre SDRAM **************************


// adresa/banca SDRAM
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
addr_o <= 12b0;
ba_o
<= 2b00;
end
else begin
if (operSt) begin
addr_o <= {4b0, colCrt}; // coloana
ba_o
<= baCrt;
end
else begin
if (actSt) begin

224

CAPITOLUL 5. PROBLEME REZOLVATE

addr_o <= rowCrt;


// rand
ba_o
<= baCrt;
end
else begin
if (lmr) begin
addr_o <= 12b00_0_00_010_0_010;// registru de mod
ba_o
<= 2b00;
end
else begin
if (ar1 | ar2 | pa | prSt) begin
addr_o <= 12b0100_0000_0000; // autorefesh sau precharge all
ba_o
<= 2b00;
end
end
end
end
end
end
// semnalele de control
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
cs_no <= 1b1;
end
else begin
cs_no <= ~(lmr
| ar1
| ar2
| pa
|
arfSt | actSt | operSt | prSt);
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
ras_no <= 1b1;
end
else begin
ras_no <= ~(lmr
| ar1
| ar2 | pa
|
arfSt | actSt | prSt);
end
end
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
cas_no <= 1b1;
end
else begin
cas_no <= ~(lmr
| ar1
| ar2 |
arfSt | operSt);

5.11. Controller pentru memorie SDRAM

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]

rfCounter; // numaratorul perioadei de refresh


rfIdle;
// linie de intarziere pentru
// masurare latenta refresh

// *** circuite implicate in gestionarea refresh-ului *******


// registru de deplasare pentru masurarea latentei de refresh
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
rfIdle <= 7b0;
end
else begin
if (arfSt) begin
rfIdle <= 7b1;
end
else begin
rfIdle <= {rfIdle[5:0], 1b0};
end

226

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.54 Logica iesirilor controllerului SDRAM - schem


a sintetizat
a.

5.11. Controller pentru memorie SDRAM

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;

// intarziere confirmare pentru citire

// *** interfatarea cu clientul ********************************

228

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.55 Circuitul de refresh al controllerului SDRAM - schem


a sintetizat
a.

// memorarea comenzii curente


always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
rwnCrt <= 1b1;
baCrt <= 2b00;
rowCrt <= 12b0;
colCrt <= 8b0;
end
else begin
if (rq_i) begin // cat timp rq_i=1, clientul are obligatia
// sa tina comanda (tipul, adresa, datele)
// active.
// aceste informatii sunt necesare
// si ulterior
rwnCrt <= rw_ni;
baCrt <= addrClient_i[21:20];// decodificarea bancii SDRAM
rowCrt <= addrClient_i[19:8]; // decodificarea randului SDRAM
colCrt <= addrClient_i[7:0]; // decodificarea coloanei SDRAM
end
end
end
// intarziere confirmare (in cazul citiri, datorita latentei CAS)
always @(posedge clk_i or negedge reset_ni) begin
if (~reset_ni) begin
ackDel <= 4b0;
end
else begin
ackDel <= {ackDel[2:0],
((operSt | idle1St | idle2St | idle3St) & rwnCrt)};
end

5.11. Controller pentru memorie SDRAM

229

end
// confirmare spre client
assign ack_o
= rwnCrt ? ackDel[3] :
(operSt | idle1St | idle2St | idle3St);

Figura 5.56 Circuitul de interfata


cu clientul al controllerului SDRAM - schem
a sintetizat
a.

Legarea blocurilor functionale ntr-un modul este prezentata grafic n figura 5.57.

5.11.2

Mediul de testare al controllerului SDRAM

Mediul de testare propus instantiaza urmatoarele module:

n
T

sdramCntrl: modul de testat;


sdramClient: model al clientului SDRAM;
mt48lc4m32b2: model al memoriei SDRAM;
monitor: model de verificare.
Figura 5.58 prezinta grafic pozitia modulelor instantiate n mediul de testare.
Modelul clientului SDRAM este conceput cu task-uri asociate actiunilor acestuia: citire, scriere, lipsa cerere.

230

CAPITOLUL 5. PROBLEME REZOLVATE

Figura 5.57 Structura controllerului SDRAM - schem


a sintetizat
a.

231

5.11. Controller pentru memorie SDRAM

Mediu de testare
client

controller

memorie

SDRAM

SDRAM

SDRAM

monitor
protocol

Figura 5.58 Pozitia modulelor instantiate n mediul de testare.

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

CAPITOLUL 5. PROBLEME REZOLVATE

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,

5.11. Controller pentru memorie SDRAM

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

CAPITOLUL 5. PROBLEME REZOLVATE

$display("%M %t NOTA: Incepe o simulare infinita.", $time);


$stop;
end
else begin
$display("%M %t NOTA: Numar de vectori de test = %0d.", $time,
nrVectors_p);
$stop;
end
// testare intensiva
while ((nrVectors_p==0) || (crtVector<nrVectors_p)) begin
baTmp = $random;
rowTmp = {$random} % (1<<nrRows_p);
colTmp = {{$random}%64, 2b00};
adsTmp = {baTmp, rowTmp, colTmp};
if ($random%2) begin
/*
write(adsTmp, {16b0, adsTmp[15:0]},
{16b0, adsTmp[15:0]+16d1},
{16b0, adsTmp[15:0]+16d2},
{16b0, adsTmp[15:0]+16d3});
*/
write(adsTmp, $random, $random, $random, $random);
break({$random}%5+1);
end
else begin
/*
read(adsTmp, {16b0, adsTmp[15:0]},
{16b0, adsTmp[15:0]+16d1},
{16b0, adsTmp[15:0]+16d2},
{16b0, adsTmp[15:0]+16d3});
*/
read(adsTmp, 32bx, 32bx, 32bx, 32bx);
break({$random}%5+1);
end
if (nrVectors_p !== 0) begin
crtVector <= crtVector + 1;
end
end
$display("%M %t NOTA: Terminare simulare.", $time);
$stop;
end
O alternativa la corelarea datelor cu adresa la care se afla o constituie prezenta unui
modul de monitorizare si verificare a datelor vehiculate la interfata client-controller.
Modulul monitor are doar porturi de intrare si nu influenteaza functionarea celorlalte
module. Monitorul detine n interior o matrice de memorie echivalenta SDRAMului. Aceasta memorie este actualizata simultan cu scrierile ce sunt comandate la
interfata client-controller SDRAM. In cazul unei citiri, monitorul primeste data citita

5.11. Controller pentru memorie SDRAM

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
//
//
//
//
//
//

cerere catre sdramCntrl


confirmare de la sdramCntrl
1=citire, 0=scriere
adresa de la client
date citite de client
date scrise de client

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; //
//

semnal activ in momentul confirmarii


unei scrieri
semnal activ in momentul confirmarii
unei citiri

assign acceptWr = rq_i & ack_i & ~rw_ni;


always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) wrPend <= 3b0; else
wrPend <= {wrPend[1:0], acceptWr};

236

CAPITOLUL 5. PROBLEME REZOLVATE

// actualizare memorie de referinta la burst de scriere


always @(posedge clk_i)
if (acceptWr) begin
mirrorMem[addrClient_i] <= dataToSdram_i;
addrClientReg <= addrClient_i;
end
else begin
if (wrPend[0]) begin
mirrorMem[addrClientReg+1] <= dataToSdram_i;
end
else begin
if (wrPend[1]) begin
mirrorMem[addrClientReg+2] <= dataToSdram_i;
end
else begin
if (wrPend[2]) begin
mirrorMem[addrClientReg+3] <= dataToSdram_i;
end
end
end
end
assign acceptRd = rq_i & ack_i & rw_ni;
always @(posedge clk_i or negedge reset_ni)
if (~reset_ni) rdPend <= 3b0; else
rdPend <= {rdPend[1:0], acceptRd};
// verificare memorie de referinta la burst de citire
always @(posedge clk_i)
if (acceptRd) begin
if (mirrorMem[addrClient_i] !== dataFromSdram_i) begin
$display("%M %t EROARE adresa=%d, dataExp=%h, dataSdram=%h.",
$time, addrClient_i, mirrorMem[addrClient_i], dataFromSdram_i);
$stop;
end
else begin
$display("%M %t NOTA adresa=%d, dataExp=%h, dataSdram=%h.",
$time, addrClient_i, mirrorMem[addrClient_i], dataFromSdram_i);
end
addrClientReg <= addrClient_i;
end
else begin
if (rdPend[0]) begin
if (mirrorMem[addrClientReg+1] !== dataFromSdram_i) begin
$display("%M %t EROARE adresa=%d, dataExp=%h, dataSdram=%h.",
$time, (addrClientReg+1), mirrorMem[addrClientReg+1],

5.11. Controller pentru memorie SDRAM

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

Cu contributia lui Corneliu ZAHARIA.

A.1

Modelul SPICE al tranzistoarelor MOS

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

ANEXA A. MODELAREA SPICE A UNUI INVERSOR CMOS

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

Ridicarea caracteristicii de sarcin


a IDS (VDS )
pentru tranzistorul NMOS

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:

A.2. Ridicarea caracteristicii de sarcin


a IDS (VDS )
pentru tranzistorul NMOS

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

ANEXA A. MODELAREA SPICE A UNUI INVERSOR CMOS

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

grosimea stratului de oxid


coeficientul de dopare a
substratului
densitatea starii de suprafata
densitatea starii de suprafata
(rapida)
tipul materialului grilei:
+1 diferit de substrat
-1 acelasi ca la substrat
0 de Al
adancimea jonctiunii metalurgice
metalurgice
difuzia laterala
mobilitatea de suprafata
campul critic pentru degradarea
mobilitatii (doar la MOS2)
exponentul campului critic n
degradarea mobilitatii
(doar la MOS2)
coeficientul campului transversal
transversal pentru mobilitati
(eliminat la MOS2)
viteza maxima de drift
a purtatorilor
coeficientul de sarcina (fixa si
mobila) pe lungimea totala a
canalului (doar la MOS2)
coeficientul de zgomot aleatoriu
exponentul coeficientului de
zgomot aleatoriu
coeficientul pentru formula
capacitatii de saracire
la polarizare directa
efectul de largire pe tensiunea
de prag (MOS2 si MOS3)
modulatia mobilitatii
(doar la MOS3)
reactia n regim static
(doar la MOS3)
factorul pentru campul de
saturatie (doar la MOS3)
valoarea temperaturii

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).

A.2. Ridicarea caracteristicii de sarcin


a IDS (VDS )
pentru tranzistorul NMOS

243

Figura A.1 Schema electric


a pentru ridicarea caracteristicii de sarcin
a a tranzistorului
NMOS.

* Definirea modelului tranzistorului NMOS


* Numele modelului este CMOSN
.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
* Instantierea tranzistorului M1
* Drena este legata la nodul VDD
* Grila este legata la nodul IN
* Sursa este legata la nodul GND
* Substratul este legat la nodul GND
* Modelul de tranzistor este CNOMSN
* Lungimea portii este 4 um
* Latimea portii este 6 um
M1 VDD IN GND GND CMOSN L=4U W=6U
* Instantierea sursei de tensiune VDD
* Sursa de tensiune triunghiulara
* Perioada de 30 ms
vdd VDD GND pwl (0ns,0V 15000ns,5V 30000ns,0V r
* Instantierea sursei de tensiune VGS
* Sursa de tensiune constanta: 30 ms - 0V, 30 ms - 1V
* 30 ms - 2V, 30 ms - 3V, 30 ms - 4V, 30 ms - 5V
vi1 IN GND pwl (0ns,0V 30000ns,0V 30001ns,1V 60000ns,1V 60001ns,2V
+90000ns,2V 90001ns,3V 120000ns,3V 120001ns,4V 150000ns,4V 150001ns,5V
+180000ns,5V

244

ANEXA A. MODELAREA SPICE A UNUI INVERSOR CMOS

Caracteristica de sarcina a acestui tranzistor este prezentata n figura A.2.

Figura A.2 Caracteristica de sarcin


a a tranzistorului NMOS.

A.3

Modelul SPICE al inversorului CMOS

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

A.4. Determinarea caracteristicii de transfer si a parametrilor inversorului CMOS

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.

+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
* Tranzistorul NMOS legat in schema inversorului CMOS
M1 OUT IN GND GND CMOSN L=4U W=3U
* Tranzistorul PMOS legat in schema inversorului CMOS
M2 OUT IN VDD VDD CMOSP L=4U W=6U
* Sursa de tensiune de alimentare a circuitului inversor
vdd VDD GND 5V

A.4

Determinarea caracteristicii de transfer si a parametrilor inversorului CMOS

Urmatorii parametrii vor fi calculati pentru inversorul CMOS:


Nivelurile de tensiune;
Marginea de zgomot;
Timpul de propagare;
Consumul de putere;

246

ANEXA A. MODELAREA SPICE A UNUI INVERSOR CMOS

Figura A.4 Caracteristica de transfer a tranzistorului CMOS.

Factorul de merit.

A.4.1

Nivelurile de tensiune

Nivelurile de tensiune se pot determina folosind caracteristica statica a inversorului


MOS, folosind ca semnal de intrare o tensiune triunghiulara:
* Sursa de tensiune triunghiulara
* Cu perioada de 60 ms
vi1 IN gnd pwl (0ns,0V 30000ns,5V

60000ns,0V r

Se poate determina caracteristica statica Vout = f (Vin ) prezentata n figura A.4.


Rezulta parametrii statici:

A.4. Determinarea caracteristicii de transfer si a parametrilor inversorului CMOS

VIL
VIH
VOL
VOH

=
=
=
=

A.4.2

247

1.75 V
2.5 V
0.8 V
4.6 V

Marginea de zgomot

Marginea de zgomot se calculeaza ca:


MH = VOH-VIH
ML = VIL-VOL
Pentru inversorul studiat, acesta este:
MH = 4.6 V - 2.5 V = 2.1 V
ML = 1.75 V - 0.8V = 0.95 V

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

ANEXA A. MODELAREA SPICE A UNUI INVERSOR CMOS

Figura A.5 Diagramele de tensiune la intrare (a) si la iesire (b) ale inversorului CMOS.

* Sursa de tensiune de alimentare a circuitului inversor


vdd VDD GND 5V
* Tensiunea de intrare dreptunghiulara,
* cu timpul de tranzitie de 1 ns
* si perioada de 601 ns
vi1 IN GND pwl (0ns,0V 300ns,0V 301ns,5V

600ns,5V 601ns,0V r

Graficul tensiunii de intrare si de iesire este prezentat n figura A.5.


Masurarea pe grafic a timpului de propagare poate fi inexacta, de aceea se prefera masurarea automata a acestuia. In SPICE, aceasta masurare se face folosind
urmatoarele comenzi:
* Masurarea timpului tlh intre valoarea de
* 0.5 V si 4.5 V (10% - 90%) a tensiunii de iesire
* pe prima panta ascendenta a semnalului de iesire

A.4. Determinarea caracteristicii de transfer si a parametrilor inversorului CMOS

249

.measure tran tlh trig v(out) val=0.5 td=10n rise=1


+
targ v(out) val=4.5 td=10n rise=1
* Masurarea timpului thl intre valoarea de
* 4.5 V si 0.5 V (90% - 10%) a tensiunii de iesire
* pe prima panta descendenta a semnalului de iesire
.measure tran thl trig v(out) val=4.5 td=10n fall=1
+
targ v(out) val=0.5 td=10n fall=1
* Masurarea timpului tplh intre valoarea de
* 2.5 V a tensiunii de intrare si 2.5 V a
* tensiunii de iesire (50% - 50%)
* intre prima panta descendenta a semnalului de intrare
* si prima panta ascendenta a semnalului de iesire
.measure tran tplh trig v(in) val=2.5 td=10n fall=1
+
targ v(out) val=2.5 td=10n rise=1
* Masurarea timpului tphl intre valoarea de
* 2.5 V a tensiunii de intrare si 2.5 V a
* tensiunii de iesire (50% - 50%)
* intre prima panta ascendenta a semnalului de intrare
* si prima panta descendenta a semnalului de iesire
.measure tran tphl trig v(in) val=2.5 td=10n rise=1
+
targ v(out) val=2.5 td=10n fall=1
Rezultatele sunt afisate n raportul SPICE:
****** transient analysis tnom= 25.000 temp= 25.000 ******
tlh
= 3.4572E-09 targ= 6.4571E-08
trig= 6.1114E-08
thl
= 1.8614E-09 targ= 3.2904E-08
trig= 3.1043E-08
tplh
= 1.8225E-09 targ= 6.2323E-08
trig= 6.0500E-08
tphl
= 1.2219E-09 targ= 3.1722E-08
trig= 3.0500E-08
Rezulta:
Timpul
Timpul
Timpul
Timpul

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

Similar, daca timpul de tranzitie a semnalului de intrare este 1ns si capacitatea


de iesire de 0.4 pF, circuitul care masoara timpii de propagare se modifica astfel:
* Instantierea capacitatii de sarcina (0.4 pF)
C OUT GND 0.4p
Rezulta raportul SPICE:
tlh

1.0969E-08

targ=

7.2840E-08

trig=

6.1871E-08

250

ANEXA A. MODELAREA SPICE A UNUI INVERSOR CMOS

Figura A.6 Caracteristica de transfer si caracteristica curentului de dren


a pentru inversorul
CMOS.

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

Rezulta timpii de transfer si de propagare:


tlh = 10.96 ns
thl = 5.89 ns
tplh = 5.40 ns
tphl = 3.31 ns

A.4.4

Consumul de putere

Figura A.6 prezinta grafic dependenta curentului IDD , ca functie de tensiunea de


intrare.
Asa cum se observa pe grafic, consumul de curent are loc doar la tranzitia tensiunii
de intrare. Puterea maxima disipata de circuit este:
Pd= Vdd*Idd = 5V x 54uA = 270uW

A.4. Determinarea caracteristicii de transfer si a parametrilor inversorului CMOS

251

Curentul de intrare este foarte mic, deci puterea consumata la intrare este neglijabila.

A.4.5

Factorul de merit

Factorul de merit se calculeaza ca fiind:


PDP = Pd*tp
Pentru o sarcina de iesire de 0.1 pF:
tPLH = 1.82 ns, tPHL = 1.22 ns
Timpul de propagare mediu este:
tp = (1.82 ns + 1.22 ns)/2

= 1.52ns

Rezulta factorul de merit:


PDP = 270uW x 1.52ns = 410.4E-15 J

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 C. MEMENTO LIMBAJ VERILOG

Figura C.1 Memento limbaj Verilog.

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

S-ar putea să vă placă și