Sunteți pe pagina 1din 112

UNIVERSITATEA TEHNICĂ "GHEORGHE ASACHI" IAŞI

FACULTATEA DE ELECTRONICĂ SI TELECOMUNICAŢII

LUCRARE DE DIPLOMĂ

Coordonator ştiinţific: Student Ieremie Ionuţ


Dr.Ing. Dănuţ Burdia grupa 5507
VHDL pentru SINTEZĂ
CUPRINS

Secţiunea I
Introducere..................................................................................................................................3
ASIC............................................................................................................................................4
Introducere............................................................................................................................4
ASIC - tipuri..........................................................................................................................5
Full-Custom ASICs...............................................................................................................6
Standard-Cell-Based ASICs..................................................................................................6
Gate-Array-Based ASICs......................................................................................................9
Structured Gate Array.........................................................................................................10
Dispozitive logice programabile.........................................................................................11
Limbajul VHDL....................................................................................................................14
Design Compiler...................................................................................................................15
Modelsim şi Leonardo Spectrum..............................................................................................16
Secţiunea II
CY7C910
Descriere funcţională...........................................................................................................17
Proiectare
Introducere..................................................................................................................19
Package-ul..................................................................................................................21
Instruction Decoder....................................................................................................23
Register-Counter........................................................................................................32
Stack...........................................................................................................................35
MicroProgram Counter...............................................................................................40
Interfaţa sursă.............................................................................................................43
Multiplexer.................................................................................................................44
Zero Detector..............................................................................................................44
TS Buffer....................................................................................................................44
CY7C910....................................................................................................................45
Sinteza circuitului CY7C910...........................................................................47
Testarea circuitului CY7C910.........................................................................52
CY7C901
Descriere funcţională...........................................................................................................67
Proiectare
Package-ul..................................................................................................................71
ALU............................................................................................................................72
Q Register...................................................................................................................76
Q Shift........................................................................................................................80
Ram Addressable Registers........................................................................................83
Ram Shift....................................................................................................................86
ALU Data Source Selector.........................................................................................88
Output Data Selector..................................................................................................91
CY7C901....................................................................................................................93
Sinteza circuitului CY7C901...........................................................................94
Testarea circuitului CY7C901.........................................................................96
Concluzii.................................................................................................................................110
CD-ul anexă............................................................................................................................111
Bibliografie
Introducere

La nivelul anului 2003, circuitele integrate digitale (CID) conţinând peste 10 milioane de
tranzistoare sunt deja banale (procesoarele Intel Pentium4 conţin peste 40 milioane tranzistoare), iar în
cazul anumitor procesoare grafice, numărul tranzistoarelor depăşeşte 100 de milioane. Este evident că
proiectarea unor astfel de circuite nu mai poate fi realizată manual. De fapt, la proiectarea manuală a CID s-
a renunţat începând de la sfârşitul anilor 1970. O dată cu apariţia primelor instrumente soft pentru
proiectarea CID, s-a intrat într-un fel de reacţie pozitivă care a făcut posibilă complexitatea CID actuale :
prin apariţia unor procesoare mai puternice, acestea puteau rula aplicaţii mai complexe - deci şi programe
de proiectare mai complexe -, iar aceste programe de proiectare au permis realizarea unor procesoare şi mai
puternice, şi aşa mai departe.
Prin renunţarea la proiectarea manuală, la nivel de schemă, şi trecerea la proiectarea asistată de
calculator a apărut un nou tip de abordare a proiectării CID. Astfel, principala sarcină a proiectantului este
aceea de a descrie, într-un limbaj HDL (VHDL sau Verilog), funcţionarea dorită de la circuit. După această
operaţiune preponderent manuală, celelalte etape de proiectare sunt aproape complet automatizate. Astfel,
după realizarea descrierii funcţionării circuitului într-un limbaj HDL, un soft va transforma această
descriere în format RTL (register transfer logic), care reprezintă o implementare cu operatori logici a
circuitului descris. Apoi alt soft realizează maparea fişierului RTL pe o anumită tehnologie, adică
implementarea circuitului descris folosind componente (porţi logice, bistabili, mux-uri, etc) dintr-o
bibliotecă de componente, ţinând cont de constrângerile de arie, viteză sau consum de putere impuse de
proiectant. În final alt soft preia fişierul de mapare şi realizează layout-ul circuitului (dispunerea pe chip a
componentelor folosite la implementarea circuitului), ţinând cont de anumite constrângeri.
Prin această lucrare mi-am propus să realizez descrierea, sinteza şi simularea a două circuite
integrate digitale : CY7C910 şi CY7C901. Scopul principal a fost acela de a căpăta experientă în
programarea VHDL pentru sinteză, în vederea unei viitoare cariere în acest domeniu. M-am limitat doar la
această etapă deoarece cunoaşterea fiecărei etape presupune o perioadă destul de mare de studiu, iar într-o
firmă, un proiectant lucrează doar la una dintre etapele proiectului. În plus, în timp ce limbajul VHDL este
standardizat şi a suferi foarte puţine modificări de la apariţia sa la începutul anilor 1980, programele de
sinteză suferă modificări permanent, apărând altele noi, astel că în scurt timp s-ar putea ca această lucrare
să nu mai prezinte interes. Mai trebuie precizat că, cu cât ne apropiem de siliciu, cu atât programele sunt tot
mai greu de găsit şi de instalat pe PC-uri.
Lucrarea are 2 secţiuni : o secţiune introductivă în care sunt prezentate circuitele ASIC, limbajul
VHDL şi instrumentele soft folosite la realizarea proiectului şi secţiunea principală, în care sunt prezentate
descrierile VHDL, programele de test, sinteza şi simularea circuitelor pe care le-am proiectat.
3
ASIC
Introducere

Un ASIC (application specific integrated circuit) este un circuit integrat dedicat unei aplicaţii
specifice (cel putin aceasta este semnificatia acronimului) . Înainte de a vedea ce inseamnă in realitate
ASIC, vom arunca o privire asupra evoluţiei circuitelor integrate (CI) .
Figura 1(a) arată capsula unui CI (în acest caz este vorba despre un PGA (pin-grid array)
prezentat răsturnat : pinii vor intra prin găurile unei plăci cu cablaj imprimat) . Capsula este denumită adesea
(impropriu) chip, dar, după cum se vede în figura 1(b), chiar chip-ul de siliciu (numit die) este montat iîn
cavitatea de sub stratul de protecţie. O capsulă PGA este confecţionată, în mod obişnuit, din material
ceramic, dar si capsulele din plastic sunt destul de răspândite.

Figura 1. Un circuit integrat

Dimensiunile fizice ale unui chip de siliciu variază de la câţiva milimetri (latura unui
dreptunghi) , la peste 3 centimetri, insă adesea dimensiunea unui CI este exprimată prin numărul porţilor
logice echivalente sau al tranzistoarelor conţinute de acel CI. Ca unitate de măsură, o poartă echivalentă
corespunde unei porţi NAND cu două intrări.
Apărută o dată cu primul CI la începutul anilor 1970, industria semiconductorilor s-a maturizat
şi a evoluat rapid. Primele CI integrate pe scară mică conţineau câteva(1 → 10) porţi logice (NAND, NOR)
ce însumau câteva zeci de tranzistoare. Perioada CI integrate pe scară medie a crescut capacitatea logică a
acestora, făcând posibilă realizarea primelor numărătoare integrate. Era CI integrate pe sacră mare a făcut
posibilă apariţia primelor procesoare realizate pe un singur chip. În zilele noastre, CI integrate pe scară
foarte mare (VLSI) oferă procesoare pe 128 de biţi, cu memorie cache şi unităţi de calcul în virgulă mobilă
– mult peste 10 milioane de tranzistoare – toate acestea pe un singur chip de siliciu.
Primele CI foloseau tehnologia bipolară, iar majoritatea circuitelor digitale foloseau familiile
logice TTL sau ECL. Deşi inventat înaintea tranzistorului bipolar, tranzistorul MOS (metal-oxide-silicon)
era iniţial dificil de fabricat. Pe măsură ce problemele de realizare a tranzistorului MOS au fost rezolvate, s-
a dezvoltat tehnologia nMOS (metal-gate n-channel MOS) . La acea vreme tehnologia MOS necesita mai
puţine măşti, era mai densă şi consuma mai puţină putere decât tehnologia bipolară echivalentă. Asta
însemna că, pentru o anume performanţă, un integrat MOS era mai ieftin decât unul bipolar echivalent, ceea
ce a dus la investiţii şi la creşterea pieţei circuitelor integrate MOS.
La începutul anilor 1980 grilele din aluminiu ale tranzistoarelor au fost înlocuite cu grile din
polisiliciu, însă numele MOS a rămas. Introducerea polisiliciului ca material pentru grilă a constituit o
îmbunătăţire majoră a tehnologiei MOS, făcând mai uşoară realizarea celor două tipuri de tranzistoare MOS
(NMOS şi PMOS) pe acelaşi CI, ceea ce a dus la apariţia tehnologiei CMOS (complementar MOS) .
Principalul avantaj al tehnologiei CMOS faţă de tehnologia nMOS este reducerea puterii consumate. Alt
avantaj, urmare a introducerii grilei din polisiliciu, este simplificarea procesului de fabricare care, în plus,
permite micşorarea dimensiunilor tranzistoarelor.

4
O poartă NAND cu două intrări este realizată din 4 tranzistoare CMOS, deci, pentru a exprima
dimensiunea unui CI ca număr de tranzistoare, se multiplică cu 4 dimensiunea acelui CI exprimată ca număr
de porţi echivalente.
Procesul de fabricare a unui CI poate fi caracterizat şi de cea mai mică dimensiune rezolvabilă
(cam jumătate din dimensiunea minimă permisă de fabricant pentru lungimea unui tranzistor) . În prezent se
folosesc procese de 0.13µm şi chiar 0.09µm, ceea ce înseamnă că cel mai mic tranzistor are aproximativ
0.13µm(0.09µm) în lungime. Cea mai mică dimensiune rezolvabilă, pe care o vom nota λ, va avea
dimensiunile λ = 0.065µm şi 0.045µm pentru procesele de 0.13µm, respectiv 0.09µm.
Un proces CMOS submicronic modern este acum la fel de complicat ca şi un proces
submicronic bipolar sau BiCMOS. Totuşi CI CMOS au o poziţie dominantă, fiind fabricate în volum mult
mai mare decât circuitele bipolare şi BiCMOS (din considerentele prezentate mai sus) . Tehnologiile
bipolare şi BiCMOS sunt în continuare utilizate pentru aplicaţii speciale. De exemplu, tehnologia bipolară
este capabilă să lucreze cu tensiuni mai mari decât permite tehnologia CMOS. Astfel CI bipolare şi
BiCMOS rămân în continuare foarte utile în electronica de putere, electronica auto, circuite telefonice, etc .
Unele CI sunt componente standard. Se poate alege un CI standard dintr-un catalog şi cumpăra
de la distribuitori. Fabricanţii de sisteme şi proiectanţii pot utiliza acelaşi CI standard într-o mare varietate
de sisteme microelectronice.
O dată cu apariţia circuitelor VLSI, inginerii au început să realizeze avantajele proiectării unui
CI pentru o aplicaţie specifică, decât utilizarea CI standard. Proiectarea sistemelor microelectronice a
devenit o problemă de definire a funcţiilor care se pot implementa folosind CI standard, şi apoi de a
implementa funcţiile logice rămase (numite “glue logic”) cu unul sau mai multe CI dedicate (care trebuie
proiectate) . Se poate realiza un sistem dintr-un număr mai mic de componente, combinând multe CI
standard cu câteva CI dedicate. Construirea unui sistem microelectronic cu mai puţine CI dedicate permite
reducerea costului şi îmbunătăţeşte fiabilitatea.
Desigur, există multe situaţii în care nu este adecvată utilizarea CI configurabile pentru fiecare
parte a unui sistem microelectronic. Dacă, de exemplu, o aplicaţie necesită o memorie de dimensiuni mari,
este indicat utilizarea unui CI de memorie standard, DRAM sau SRAM.
Deoarece este dificil de definit cu exactitate termenul ASIC, vom încerca să clarificăm ce
înseamnă acest termen apelând la unele exemple. Exemple de circuite integrate care nu sunt ASIC-uri :
microprocesoarele, memoriile destinate PC-urilor (SDRAM, DDRAM) . Exemple de CI ASIC : un CI
pentru o păpuşă “vorbitoare”, un CI pentru un satelit, un CI care conţine un microprocesor ca celulă,
împreună cu altă logică. Ca o regulă generală, dacă un CI poate fi găsit într-un catalog atunci este foarte
probabil să nu fie ASIC.

ASIC – tipuri

Circuitele integrate sunt fabricate pe wafere circulare subţiri (câteva sute de microni) din
siliciu, fiecare wafer conţinând sute de chip-uri. Tranzistoarele şi conexiunile sunt realizate în mai multe
straturi (de obicei între 10 şi 15) suprapuse. Fiecare strat are o configuraţie definită cu ajutorul unei măşti.
Straturile inferioare definesc tranzistoarele, iar straturile superioare conexiunile dintre tranzistoare.
Un CI full-custom include câteva (sau toate) celule logice proiectate special şi măştile, care
sunt toate proiectate special. Un microprocesor este un exemplu de CI full-custom. Proiectanţii au cheltuit
foarte mult timp insistând asupra fiecărui µm² de pe chip. Proiectând astfel toate resursele circuitului
integrat, este posibilă includerea pe chip a unor circuite analogice sau a unor celule de memorie optimizate.
CI full-custom sunt cele mai scump de proiectat şi de fabricat. Aceste CI full-custom sunt adesea destinate
unei aplicaţii specifice, deci am putea numi unele dintre acestea CI ASIC full-custom.
Ceea ce ne interesează pe noi sunt însă CI ASIC semicustom, pentru care toate celulele logice
sunt deja proiectate şi unele măşti (probabil toate) sunt configurabile. Folosind celule logice predefinite
(dintr-o librărie de celule) viaţa proiectanţilor devine mult mai uşoară. Sunt două tipuri de CI ASIC
5
semicustom despre care vom vorbi : CI ASIC bazate pe celule standard (“standard cell based ASICs “) şi
CI ASIC bazate pe arii de porţi logice (“gate-array-based ASICs”) . Apoi vor fi descrise CI ASIC
programabile.

Full-Custom ASICs

Într-un CI ASIC full-custom un inginer configurează parţial (sau în totalitate) celulele logice,
circuitele şi layout-ul într-un mod specific. Aceasta înseamnă că proiectantul abandonează abordarea de a
utiliza celule pretestate pentru realizarea întregului circuit. Această abordare full-custom are sens doar dacă
nu există librării de celule care să permită realizarea întregului design. Aceasta se poate întâmpla deoarece
celulele din librăriile de celule existente nu sunt suficient de rapide, sau nu sunt suficient de mici, sau
consumă prea multă putere.; sau dacă tehnologia ASIC este nouă sau atât de specializată încât nu există
librării de celule ; sau dacă circuitul este atât de specializat încât unele blocuri trebuie proiectate special. Din
ce în ce mai puţine CI ASIC full-custom sunt realizate (există şi o excepţie :circuitele mixte analog/digital) .
Tehnologia bipolară a fost utilizată dintotdeauna pentru funcţii analogice de precizie. Există
câteva motive fundamentale pentru aceasta. În toate CI împerecherea caracteristicilor componentelor de pe
chip-uri diferite este foarte slabă, dar foarte bună pentru componentele aflate pe acelaşi chip. Să presupunem
că avem tranzistoarele T1, T2, T3 într-un CI ASIC analog/digital. Cele trei tranzistoare au dimensiuni
identice şi sunt construite în acelaşi mod. Tranzistoarele T1 şi T2 sunt plasate foarte aproape unul de celălalt
şi au aceeaşi orientare, în timp ce tranzistorul T3 este plasat pe chip pe partea opusă şi are o orientare
diferită. Circuitele integrate sunt fabricate în loturi, numite “wafer lots”. Un “wafer lot” este un grup de
wafer-e de siliciu (intre 5 şi 30) care sunt procesate împreună. Fiecare wafer poate conţine zeci sau sute de
chip-uri, în funcţie de dimensiunile CI şi ale wafer-ului. Dacă facem măsurători asupra caracteristicilor
tranzistoarelor T1, T2, T3 vom desprinde următoarele concluzii :
- Tranzistoarele T1 şi T2 de pe acelaşi chip vor avea caracteristici aproape identice ;
- Tranzistorul T3 se împerechează foarte bine cu tranzistoarele T1 şi T2 de pe acelaşi chip, dar nu atât de
strâns ca împerecherea dintre T1 şi T2 ;
- Tranzistoarele T1, T2 şi T3 se vor împerechea destul de bine cu tranzistoarele T1, T2, T3 de pe alt chip de
pe acelaşi wafer ; împerecherea depinde de cât de depărtate sunt cele două chip-uri unul de celălalt ;
- Tranzistoarele de pe chip-uri aflate pe afer-e diferite nu se vor împerechea foarte bine ;
- Tranzistoarele de pe chip-uri din loturi de wafer-e diferite se vor împerechea foarte slab ;
La proiectarea circuitelor analogice împerecherea tranzistoarelor este crucială pentru funcţionarea
circuitului. Pentru aceste circuite sunt folosite perechi de tranzistoare situate adiacent pe chip. Fizica
dispozitivului dictează că o pereche de tranzistoare bipolare se vor împerechea întotdeauna mult mai precis
decât o pereche de tranzistoare CMOS de dimensiuni comparabile. Tehnologia bipolară a fost utilizată pe
larg pentru circuite analogice full-custom datorită preciziei sporite. În ciuda slabelor sale carcteristici
analogice, utilizarea tehnologiei CMOS pentru funcţii analogice este în creştere, şi aceasta din două motive:
primul motiv este acela că în prezent tehnologia CMOS este cea mai larg disponibilă tehnologie de realizare
a CI ; al doilea motiv este acela că nivelul crescut de integrare necesită realizarea de funcţii analogice şi
digitale pe acelaşi chip, ceea ce a obligat proiectanţii să folosească tehnologia CMOS pentru implementarea
funcţiilor analogice.

Standard-Cell-Based ASICs

Un CBIC (cell-based IC) foloseşte celule logice (porţi NAND, NOR, multiplexoare, bistabili)
predefinite, numite celule standard. Un CBIC este construit din rânduri de celule standard - la fel cum zidul
este construit din cărămizi. Ariile de celule standard pot fi utilizate în combinaţie cu celule predefinite mai
mari, microcontrollere sau chiar microprocesoare, numite megacelule.

6
Proiectantul ASIC defineşte doar plasarea celulelor standard şi interconexiunile într-un CBIC.
Celulele standard pot fi plasate oriunde pe chip, ceea ce înseamnă că toate măştile unui CBIC sunt
configurabile. Avantajul circuitelor CBIC este acela că proiectanţii economisesc timp, bani şi reduc riscul
prin utilizarea unei librării de celule standard gata proiectate, pretestate şi precaracterizate. Pe de altă parte,
fiecare celulă standard poate fi optimizată individual. În timpul proiectării unei librării de celule fiecare
tranzistor din fiecare celulă standard poate fi ales astfel încât să maximizeze viteza sau să minimizeze aria,
de exemplu. Dezavantajul în acest caz este timpul şi banii cheltuiţi pentru proiectarea unei librării de celule.
Figura 2 arată un CBIC. Caracteristicile principale ale acestui tip de ASIC sunt următoarele :
- toate măştile sunt proiectate special – tranzistoarele şi interconexiunile ;
- pot fi incluse blocuri custom
- timpul de fabricare este în jur de 8 săptămâni .

Figura 2. Un CBIC die

Fiecare celulă standard dintr-o librărie este construită folosind metode de proiectare full-custom,
însă aceste celule standard gata proiectate se pot utiliza la realizarea circuitelor digitale fără a fi deloc
necesară proiectarea full-custom. Acest stil de proiectare duce la obţinerea aceloraşi avantaje de performanţă
şi flexibilitate ca în cazul ASIC full-custom, dar reduce riscul şi timpul de proiectare.
Celulele standard sunt proiectate să se potrivească asemeni cărămizilor într-un zid. Figura 3
arată exemplul unei celule standard simple (simplu în sensul că nu este optimizată pentru densitate, dar este
ideală pentru a arăta construcţia internă). Liniile de putere şi de masă (VDD şi GND sau VSS) traversează
orizontal celulele.

Figura 3. Layout-ul unei celule standard (privire de sus)

Proiectarea standard cell permite automatizarea procesului de asamblare. Grupuri de celule standard
sunt aranjate împreună pe orizontală pentru a forma rânduri. Rândurile sunt stivuite pe verticală pentru a
7
forma blocuri rectangulare flexibile (forma acestoara poate fi modificată pe durata proiectării) . Apoi un
bloc flexibil construit din câteva rânduri de celule standard poate fi conectat la alt bloc de celule standard
sau la alt bloc logic full-custom. De exemplu, să presupunem că vrem să includem pe acelaşi chip un circuit
de interfaţă (proiectat de noi) pentru un microcontroller gata proiectat (megacelulă) , împreună cu o
anumită cantitate de memorie. Blocul microcontrollerului este o megacelulă de dimensiuni fixe, memoria
poate fi generată folosind un compilator de memorie, iar circuitul de interfată va fi construit din blocuri
flexibile de celule standard a căror formă se poate modifică astfel încât să se potrivească în spaţiile rămase
libere pe chip.
Circuitele integrate ASIC, atât cele “cell-based”, cât şi cele “gate-array”, utilizează celule
predefinite, însă există o diferenţă: putem modifica dimensiunile tranzistoarelor într-o celulă standard
(pentru a optimiza viteza sau aria) , însă în cazul ariilor de porţi logice dimensiunile tranzistoarelor sunt
fixe. Aceasta determină o interdependenţă între arie şi viteză la nivel de siliciu în cazul “gate-array”, pe
când, în cazul “standard-cell”, această interdependenţă se manifestă la nivelul librăriei de celule standard.
Circuitele ASIC CMOS moderne utilizează două, trei sau mai multe straturi (layer–e) de metal
pentru interconexiuni. Aceasta permite traseelor de interconexiune să traverseze diferite straturi, la fel ca în
cazul traseelor de cupru de pe o placă cu cablaj împrimat. Într-o tehnologie CMOS cu 2 nivele de metal,
conexiunile la intrările şi ieşirile celulelor standard se realizează pe nivelul metal2 (nivelul superior de
metal) , la extremităţile superioară şi inferioară ale celulelor. Într-o tehnologie cu 3 nivele de metal,
conexiunile pot fi interne celulei standard (ca în Figura 3) , ceea ce permite programelor de rutare să
folosească nivelul de metal în plus pentru a ruta interconexiunile pe deasupra celulelor standard.
O conexiune care trebuie să treacă pe deaupra unui rând de celule standard foloseşte un
“feedthrough” (fie o porţiune de metal folosită pentru a trece un semnal printr-o celulă, fie un spaţiu lăsat
liber în interiorul celulei, spaţiu ce va fi ocupat de un traseu metalic) . Figura 4 prezintă două astfel de
“feedtrough”-uri: unul în celula A.14 şi unul în celula A.23.
Atât în tehnologia cu 2 nivele de metal, cât şi în cea cu 3 nivele de metal, bus-urile de putere
(“power buses” – VDD şi GND) în interiorul celulelor utilizează în mod normal cel mai de jos (cel mai
apropiat de tranzistoare) nivel de metal – metal1.Lăţimea fiecărui rând de celule standard este ajustată astfel
încât acesea să poată fi aliniate prin intermediul celulelor de spaţiere (“spacer cells”) . Traseele “power
buses” se conectează apoi la linii de power adiţionale verticale prin intermediul celulelor speciale de sfârşit
de rând (“row-end cells”) la capetele aliniate ale fiecărui bloc de celule standard. Dacă rândurile de celule
standard sunt lungi, liniile de power verticale pot fi realizate pe nivelul metal2 şi vor parcurge rândurile de
celule standard prin intermediul unor celule speciale, numite “power cells”, care realizează doar conectarea
la VDD şi GND. În mod normal, proiectantul controlează manual numărul şi lăţimea liniilor de power
verticale conectate la un bloc de celule standard în timpul proiectării la nivel fizic (layout) . O imagine a
schemei de distribuţie a traseelor de power pentru un CBIC este arătată în Fig 4.

Figura 4. Rutarea CBIC-ului din fig2

8
Toate măştile pentru un CBIC sunt configurabile. Aceasta permite plasarea unor megacelule
(SRAM, controller SCSI, decodor MPEG, etc) alături de celule standard pe acelaşi chip. Megacelulele sunt
furnizate de un fabricant de ASIC-uri sau de librării, împreună cu modele comportamentale şi anumite
strategeii de test pentru aceste megacelule. Companiile furnizoare de librării ASIC pot furniza, de asemenea,
compilatoare pentru generarea flexibilă a blocurilor de memorie (DRAM, SRAM, ROM) . Întrucât în cazul
unui design “standard cell” toate măştile sunt configurabile, proiectarea blocurilor de memorie este mult mai
eficientă şi mai densă decât in cazul designului “gate arrays”.
Librăriile “standard cell” şi “gate array” conţin sute de celule logice diferite, incluzând funcţii
combinaţionale (porţi NAND, NOR cu 2 sau mai multe intrări) , precum şi latch-uri şî bistabili (cu diverse
combinaţii de reset, preset şi opţiuni pentru semanlul de ceas) . Producătorul librăriilor furnizează
documentaţia (descriere funcţională şi informaţii de timing) pentru fiecare element al librăriei.

Gate-Array-Based ASICs

Într-un ASIC de tip “gate-array” (prescurtat GA) tranzistoarele sunt predefinite pe wafer.
Configuraţia predefinită a tranzistoarelor pe o arie de porţi reprezintă aria de bază (“base array”) , iar cel
mai mic element care este replicat pentru a forma aria de bază reprezintă celula de bază (“base cell”, numită
şi “primitive cell”) . Doar câteva din straturile superioare de metal, care definesc conexiunile dintre
tranzistoare, sunt definite de proiectant folosind măşti configurabile. Pentru a fi deosebit de alte tipuri de
“gate array”, acest tip este numit “masked gate array” (MGA) . Proiectantul alege dintr-o librărie “gate-
array” celule logice predefinite. Celulele logice dintr-o librărie “gate-array” sunt numite adesea macrouri
(“macros” – de la asemănarea cu macrourile software ) deoarece layout-ul pentru o “base-cell” este acelaşi
pentru fiecare celulă logică, şi doar conexiunile (în interiorul celulelor logice şi între acestea) sunt
configurabile.
Putem realiza etapele de difuzie până la definirea tranzistoarelor, după care waferele pot fi
depozitate în vederea utilizării ulterioare. Deoarece doar interconexiunile metalice sunt unice pentru un
MGA, putem utiliza waferele din depozit pentru diferite aplicaţii, după necesităţi. Folosind wafere
prefabricate până la nivelul de metalizare, se reduce timpul necesar fabricării unui MGA (între 2 zile şi 2
săptămâni) .
Există 3 tipuri de MGA :
- Channeled gate arrays
- Chanelless gate arrays
- Structured gate arrays
Să explicăm pe scurt termenii “channeled”, “channelless” şi “structured”. Există două modalităţi
uzuale de a aranja tranzistoarele într- un MGA : în cazul “channeled gate arrays”, între rândurile de
tranzistoare se lasă un spaţiu liber destinat rutării ; rutarea în cazul dispozitivelor “channelless gate arrays”
utilizează rânduri de tranzistorare neutilizate. Tipul “structured gate arrays” poate fi atât “channeled”, cât şi
“channelless”, însă include şi un bloc configurabil.
Channeled Gate Array
Figura 5 prezintă un chip “channeled gate array”. Principalele caracteristici ale acestui tip de MGA sunt :
- Doar interconexiunile sunt “custom”
- Interconexiunile utilizează spaţiile predefinite dintre rândurile de “base cells”

9
- Fabricarea durează între 2 zile şi 2 săptămâni

Figura 5. Channeled gate array die

Un chip “channeled gate array” este asemănător cu un CBIC – ambele utilizează rânduri de
celule separate de canale pentru interconexiuni. Diferenţa este dată de faptul că, în cazul “channeled gate
array” canalele de rutare au dimensiuni fixe.
Channelless Gate Array
Figura 6 prezintă un chip “channelless gate array”. Principalele caracteristici ale acestui tip de MGA sunt :
- Doar câteva din layerele superioare sunt “custom” – interconexiunile
- Fabricarea durează între 2 zile şi 2 săptămâni
Principala deosebire faţă de “channeled gate array” este absenţa spaţiilor de rutare predefinite.
În acest caz rutarea se realizează pe deasupra tranzistoarelor. Aceasta se poate realiza deoarece proiectantul
configurează stratul “contact layer” care defineşte conexiunile dintre nivelul metal1 şi tranzistoare. Când se
utilizează o arie de tranzistoare pentru rutare, nu se realizează nici un contact către tranzistoarele de
dedesubt; tranzistoarele sunt lăsate pur şi simplu neutilizate.

Figura 6. Channelless gate array die

Densitatea de integrare pentru “channelless gate arrays” este mai mare decât în cazul
“channeled gate arrays”. Aceasta se datorează faptului că masca de contact este configurabilă în cazul
“channelless gate arrays”. Prin configurarea stratului de contact se permite creşterea densităţii celulelor
deoarece se poate realiza rutarea şi pe deasupra contactelor neutilizate.

Structured Gate Array

Un chip “structured gate array” combină câteva dintre caracteristicile CBIC – urilor şi MGA –
urilor. Unul dintre dezavantajele MGA este celula de bază neconfigurabilă, ceea ce face ca implementarea
memoriei, de exemplu, să fie dificilă şi ineficientă. În cazul “structured gate array”, o parte din aria chipului
este dedictă funcţiilor speciale (această arie poate conţine celule de bază mai adecvate pentru implementarea
memoriei, sau poate conţine un bloc complet – un microcontroller de exemplu) .
Figura 7 prezintă un chip “structured gate array”. Principalele caracteristici ale acestui tip de
MGA sunt următoarele :
10
- doar interconexiunile sunt configurabile
- pot fi incluse macrocelule
- fabricarea durează între 2 zile şi 2 săptămâni

Figura 7. Structured Gate Array die

Tipul “structured gate array” combină densitatea şi performanţa superioare ale unui CBIC cu
costurile scăzute şi timpul de fabricare redus ale unui MGA. Unul din principalele dezavantaje provine
tocmai de la blocul special (macrocelula) integrat care nu este configurabil. Dacă “strucured gate array”
conţine o arie destinată implementării a 32 Kb de memorie, iar pentru o aplicaţie sunt necesari doar 16 Kb,
înseamnă că jumătate din această arie de memorie rămâne nefolosită şi inutilizabilă în alt scop; însă, chiar şi
aşa, tot este mai eficient şi mai ieftin decât implementarea celor 16 Kb de memorie utilizând macrouri.

Dispozitive logice programabile

Dispozitivele logice programabile, (Programmable Logic Devices - PLD) sunt circuite integrate care
au proprietatea că pot fi configurate (programate) de către utilizator, oferind astfel posibilitatea acestuia de a
implementa diverse sisteme digitale.
Dispozitivele logice programabile oferă un set de resurse logice care pot fi configurate, prin
intermediul unor biţide configurare. Resursele logice sunt dispuse sub forma unei arhitecturi fixe, de tip
modular.Prin arhitectură de tip modular se înţelege o arhitectură compusă dintr-un număr de blocuri identice
care sunt inteconectate. Conexiunile dintre aceste blocuri sunt realizate pe baza unorcomutatoare
programabile.
Programarea unui PLD constă în setarea biţilor de configurare, care controlează starea
comutatoarelor programabile şi configuraţia resurselor logice, pe baza unei descrieri a sistemului digital care
se doreşte a fi implementat. În funcţie de starea biţilor de configurare se pot genera diverse configuraţii ale
resurselor logice şi interconexiuni între blocurile din componenţa PLD-ului, în final obţinându-se arhitectura
sistemului digital dorit. Programarea acestor dispozitive este realizată pe baza unor instrumente software
complexe şi implică inserarea circuitului în unitaţi speciale de programare. Un pas înainte în proiectarea
sistemelor digitale pe baza PLD-urilor a fost realizat recent prin posibilitatea configurarării PLD-ului ”in-
sistem” (fără a fi necesară extragerea lor din sistem). PLD-urile sunt utilizate în special în segmentul de
piaţă ce cuprinde producerea desisteme digitale la un volum redus de producţie, fiind ideale pentru
realizarea prototipurilor.
Principalele avantaje pe care le oferă PLD-urile sunt: cost iniţial redus pentru realizarea
proiectului (în faza de prototip), risc financiar redus în faza de realizare a prototipului, posibilitatea
parcurgerii tuturor fazelor implicate în proiectarea unui produs chiar din faza de prototip, începând de la
stabilirea cerinţelor de proiectare şi terminând cu implementarea finală a produsului şi nu în ultimul rând
uşurinţa cu care se pot realiza modificările în proiect.digitale.
Întrucât pot fi programate pentru a se obţine circuite pentru o aplicaţie specifică, PLD-urile
pot fi incluse în familia ASIC-urilor.
Primul PLD a fost realizat în anii ’70 şi a fost denumit ProgrammableLogic Array, pe scurt
PLA. Dispozitivul PLA este un PLD de capacitate logică redusă.
11
Dispozitivele PLA sunt alcătuite din 2 nivele (plane) logice: un nivel logic alcătuit din porţi logice
AND - planul AND, la care sunt conectate intrările dispozitivului şi un nivel logic alcătuit din porţi logice
OR - planul OR, la care sunt conectate ieşirile dispozitivului. Cele două plane sunt conectate între ele astfel
încât, ieşirile din porţile AND reprezintă intrările în porţile OR. Distinctiv pentru acest tip de dispozitiv este
faptul că ambele planuri logice pot fi programate. Cele 2 planuri logice mai poartă şi denumirea de arii
logice programabile.
Programarea acestor arii logice este realizată la nivelul conexiunilor (firelor), prin intermediul
comutatoarelor (switch-uri) programabile, realizate în diverse tehnologii: fuzibil, antifuzibil, EPROM,
EEPROM, Flash, SRAM. La nivelul planului AND, pot fi conectate oricare dintre intrările dispozitivului, la
ieşirea acestuia rezultând un set de termeni produs. La nivelul planului OR, pot fi conectate oricare dintre
termenii produs, la ieşirea acestuia rezultând sume de termeni produs, deci funcþii logice care pot descrie un
sistem digital. Versatilitatea dispozitivului, ca o consecinţă a faptului că ambele planuri logice din
componenţa sa pot fi programate, oferă posibilitatea realizării unei game extinse de sisteme
Dipozitivele PLA prezintă 2 dezavantaje importante: cost mare de fabricare (cost raportat la nivelul
tehnologic al anilor ’70) şi viteză de lucru redusă. Ambele dezavantaje sunt determinate de
programabilitatea ambelor plane logice: planele logice programabile sunt dificil de realizat şi introduc
întârzieri în propagarea semnalului. Pentru eliminarea (parţială) a acestor dezavantaje s-a încercat
eliminarea problemei care a cauzat-o: programabilitatea planelor logice. Cum eliminarea conexiunilor
programabile din cele 2 plane logice ar fi condus practic la dispariţia circuitului PLD, s-au eliminat numai
conexiunile programabile din planul OR (conexiunile din acest plan au devenit fixe) şi astfel dezavantajele
prezentate de dispozitivul PAL au fost diminuate. Noul dispozitiv creat a fost patentat de către firma AMD
(Advanced Micro Device) şi poartă denumirea de Programmable Array Logic, pe scurt PAL.
Dispozitivele PAL au un plan AND programabil şi un plan OR fix. Structura unui dispozitiv PAL
este prezentată în Figura.8, în care se remarcă o nouă deosebire faţă de dispozitivele PLA: ieşirile di. porţile
OR pot fi conectate fie la un set de bistabile de tip D (ca in figură), fie la un set de macrocelule logice.

Figura 8. Structura unui dispozitiv PAL

Dispozitivele de tip PLA şi PAL sunt referite deseori în literatura de specialitate sub
denumirea de Simple Programmable Logic Devices - SPLD. Aceste dispozitive au o densitate logică redusă.
Astfel, dispozitivele SPLD au o capacitate logică de maxim 600 porţi echivalente.
Pe măsură ce sistemele digitale au devenit mai complexe, a apărut nevoia unor dispozitive PLD
de mare densitate logică. Pe măsură ce tehnologia de fabricare a circuitelor integrate a avansat, s-au
dezvoltat în timp două mari categorii de dispozitive PLD.
Prima categorie o reprezintă dispozitivele de tip Complex Programmable Logic Devices -
CPLD, a căror capacitate logică se situează, în mod uzual în jurul ordinului miilor de porţi logice (deşi sunt
câteva firme care produc dispozitive CPLD cu capacitate logică de câteva sute de mii de porţi logice),
arhitectura acestora fiind dezvoltată pe baza dispozitivelor SPLD. Alte denumiri sub care se pot referi aceste
dispozitive sunt: Enhanced PLD, abreviat EPLD, Super PAL, Mega PAL, etc.
Dispozitivele CPLD sunt destinate în special implementării sistemelor digitale cu un pronunţat caracter
combinaţional, principalele domenii de aplicaţii ale acestora fiind: controlere LAN, sisteme UART, sisteme
12
de interfaţă cu bus-uri, comparatoare, respectiv decodoare complexe de viteză mare, automate secvenţiale
complexe, controlere video, etc.
A doua categorie de dispozitive PLD este reprezentată de circuitele Field Programmable
Gate Array, abreviate FPGA, a căror arhitectură, remarcabilă prin numărul foarte mare de bistabile incluse,
este diferită de precedentele tipuri de dispozitive PLD din punct de vedere al concepţiei, ceea ce permite
atingerea unei capacităţi logice de până la 1 milion de porţi logice. Dispozitivele FPGA sunt destinate în
special implementării sistemelor digitale cu un pronunţat caracter secvenţial (datorită numărului mare de
bistabile incluse în structură), principalele domenii de aplicaţii fiind: emularea sistemelor hardware,
dispozitive de codare şi filtrare în comunicaţii, circuite aritmetice de dimensiuni mari, controlere utilizate în
prelucrarea imaginilor, etc.
Arhitectura dispozitivelor FPGA (field programmable gate array) este compusă dintr-un set de
celule logice (logic cells – LC) dispuse matricial, care comunică între ele şi/sau cu celulele I/O prin
intermediul unor canale de rutare orizontale şi verticale. Canalele de rutare conţin un număr de fire de
interconexiune. Acestea pot fi conectate între ele prin intermediul unor comutatoare programabile.
Arhitectura celulelor logice precum şi modul în care este implementată schema de rutare variază în funcţie
de producător. În general, celulele logice oferă o funcţionalitate mai redusă decât combinaţia termeni produs
– macrocelule, oferită de dispozitivele CPLD, dar, în cazul dispozitivelor FPGA, implementarea unor funcţii
logice complexe poate fi realizată prin conectarea în cascadă a celulelor logice. În figura9 este prezentată
arhitectura generică a unui dispozitiv FPGA. Ţinând cont de specificul arhitecturii unui dispozitiv FPGA, în
general, acestea sunt utilizate pentru implementarea sistemelor digitale cu un predominant caracter
secvenţial, unităţi de calcul, sau diferite tipuri de interfeţe în sisteme de comunicaţie.

Figura 9. Arhitectura generică a unui dispozitiv FPGA

Pentru a fi un produs competitiv pe piaţă, un dispozitiv FPGA trebuie să satisfacă anumite


cerinţe. Între acestea, cele mai importante sunt:
1. performanţa – capacitatea de a implementa sisteme digitale care să poată funcţiona la frecvenţe ridicate
2. densitatea şi capacitatea logică – capacitatea de a majora nivelul de integrare, de a implementa sisteme
digitale tot mai complexe într-un singur cip, prin utilizarea tuturor resurselor logice disponibile şi obţinerea
astfel a unor soluţii ieftine de proiectare.
3. proiectare facilă – capacitatea de a realiza un proiect într-un interval de timp minim, fapt care depinde de
instrumentul software de proiectare şi de posibilitatea de a fi efectuate modificări ulterioare în proiect fără a
fi afectate pricipalele caracteristici legate de viteza de lucru şi alocarea pinilor dispozitivului.
4. programarea “in-system” şi reprogramarea “in-circuit” – capacitatea de a programa şi reprograma un
dispozitiv conectat într-un sistem.
Satisfacerea acestor cerinţe de către dispozitivele FPGA depinde în mare măsură de tehnologia
utilizată pentru proiectarea elementelor programabile. În prezent sunt utilizate două tehnologii: tehnologia
SRAM şi antifuzibil (antifuse).

13
Limbajul VHDL
Limbajul VHDL a apărut la începutul anilor 1980 şi este acceptat în prezent ca unul dintre cele mai
importante limbaje standard pentru descrierea, verificarea şi proiectarea circuitelor electronice.
VHDL eliberează proiectantul de constrângerea de a folosi structuri von Neumann şi îi permite să
lucreze cu evenimente concurente în locul maşinilor secvenţiale. Aceasta a dus la apariţia unor posibilităţi
complet noi pentru proiectant.
Două din motivele importante pentru care se utilizează VHDL în locul proiectării tradiţionale la
nivel de schemă sunt : timpul mai scurt pentru dezvoltarea proiectelor electronice şi întreţinerea mai simplă.
VHDL a apărut ca un limbaj pentru descriere şi verificare, primele simulatoare fiind dezvoltate la
sfârşitul anilor 1980. Proiectarea cu VHDL a apărut câţiva ani mai târziu. În prezent, toţi marii producători
de instrumente soft de proiectare electronică suportă standardul VHDL. În prezent VHDL este un limbaj
standardizat, cu avantajul că un cod VHDL poate fi uşor mutat pe diferite instrumente (platforme)
comerciale. Aceasta înseamnă că un cod VHDL scris pentru un simulator al unui producător anume poate fi
mutat pe simulatoarele altor producători fără a trebui să fie modificat.
O nouă posibilitate, care a schimbat lumea proiectanţilor de circuite electronice, este modalitatea
prin care câteva mii (sute de mii şi chiar milioane în prezent) de porţi şi bistabili pot fi programate sub
forma unui circuit integrat în doar câteva minute pe un singur PC şi fără a fi nevoie de echipamente
costisitoare. Aceasta înseamnă că, plecând de la un cod VHDL, se poate genera automat un fişier pentru
programarea circuitelor ; această metodă se numeşte “rapid prototyping”.
Scrierea de cod VHDL în locul utilizării componentelor schematice (ex : porţi logice) , reprezintă o
nouă cale de proiectare. Lucrul cu VHDL nu inseamnă doar scrierea de cod, existând facilităţi pentru
construirea de ierarhii şi proiectarea cu o librărie de componente. VHDL se pretează, de asemenea, la
scrierea de cod pentru circuite standard (ex: Motorola 680020) . Există companii care vând coduri VHDL
pentru simularea circuitelor standard. Aceasta înseamnă că o întreagă placă ce conţine componente standard
poate fi verificată printr-o simulare pe computer.
Proiectarea cu VHDL presupune ca proiectantul să scrie cod VHDL şi să verifice funcţionarea
acestuia într-un simulator, după care codul este sintetizat într-un netlist. Sinteza poate fi comparată cu
procesul prin care un compilator transformă un cod scris într-un limbaj de programare în cod maşină. În
hardware, codul VHDL este transpus într-o schemă cu porţi şi bistabili.
VHDL suportă diferite metode de proiectare : top-down (de la vârf spre bază) , bottop-up (de la bază
spre vârf) şi orice combinaţie a acestora.
Multe din produsele electronice de astăzi au o durată de viaţă mai mare de 10 ani şi, ca urmare,
trebuie să fie reproiectate de câteva ori pentru a exploata avantajele noilor tehnologii. Cea mai simplă
metodă pentru a face asta este proiectarea VHDL independentă de tehnologie, ceea ce permite modificarea
tehnologiei folosind instrumente automate.
Limbajul VHDL suportă ierarhii (diagrame bloc) , componente reutilizabile, managementul erorilor
şi verificare. Ierarhiile sunt descrise folosind VHDL structural, proceduri şi funcţii. VHDL structural poate
fi comparat cu o diagramă bloc. Multe sisteme suportă intrări grafice care pot fi transferate automat în
VHDL structural.

14
Design Compiler
Design Compiler sintetizează o descriere HDL (VHDL sau Verilog) într-un design la nivel de poartă (gate-
level) dependent de tehnologie. Folosind Design Compiler putem defini condiţiile de mediu, constrângerile,
metodologia de compilare, regulile de proiectare şi librăriile “ţintă” (target) pentru a îndeplini sarcinile de
proiectare.
Design Compiler este “inima” suitei de produse software pentru sinteză Synopsys.
Design Compiler realizează optimizarea, bazată pe constrângeri, a logicii secvenţiale şi suportă o mare
diversitate de stiluri de proiectare.
În continuare sunt prezentate succint câteva aspecte de bază ale Design Compiler care permit
formarea unei imagini despre posibilităţile acestuia.
Procesul de sinteză
Design Compiler optimizează designul logic pentru viteză, arie şi rutabilitate. Această optimizare este
realizată pentru descrieri ierarhice ale circuitelor logice combinaţionale şi secvenţiale. Pornind de la
cerinţele impuse asupra caracteristicilor măsurabile ale circuitului, Design Compiler sintetizează un circuit
pe care îl transferă într-o tehnologie indicată. Aceasta permite generarea de fişiere schematics şi netlists
compatibile cu instrumentele CAE (computer-aided engineering) .
Procesul de sinteză, prezentat în figura de mai jos, urmează această schemă generală :
- încărcarea proiectului şi a subproiectelor (blocurilor componente) acestuia ;
- specificarea caracteristicilor de proiectare pentru proiectul “top-level” ;
- impunerea de performanţe de viteză şi arie realistice ;
- analiza “check_design” pentru verificarea proiectului ; identificarea şi corectarea tuturor erorilor ;
- optimizarea proiectului cu Design Compiler ;
- analiza fişierelor de raport privind constrângerile de arie şi viteză, pentru a se determina dacă sarcinile de
proiectare au fost îndeplinite ;
- reoptimizarea, după modificarea atributelor sau constrângerilor, în cazul în care sarcinile de proiectare nu
au fost îndeplinite ;
- generarea de rapoarte şi scheme suplimentare, pentru analiza aprofundată a rezultatelor

15
Stiluri de proiectare
Proiectele pot fi ierarhice sau plane (flat) , secvenţiale sau combinaţionale.
Formate de intrare
Design Compiler suportă descrieri VHDL şi Verilog ca formate de intrare pentru descrierea proiectului. De
asemenea, Design Compiler suportă formatele PLA şi EDIF 200.
Formate de ieşire
Alături de formatul Synopsys binar (.db) , Design Compiler suportă formatele de ieşire VHDL, Verilog şi
EDIF 200. De asemenea Design Compiler suportă şi formatele : ecuaţii. LSI, Mentor Graphics, PLA, state-
table şi Tegas.

Modelsim

Modelsim, produs de Mentor Graphics, este la ora actuală cel mai popular simulator HDL de pe piaţă. Prin
intermediul acestuia se pot simula atât fişiere VHDL, cât şi fişiere Verilog. Toate fişierele din acest proiect
au fost simulate cu Modelsim versiunea 5.6, formele de undă prezentate fiind generate de acesta.

Leonardo Spectrum
Leonardo Spectrum, din cadrul pachetului FPGA Advanced, este un soft de sinteză semiprofesional, destinat
în principal aplicaţiilor FPGA. Deşi are rezultate foarte slabe la sinteza standard cells, şi deşi nu generează
fişiere SDF (generează fişîere EDIF, care însă nu pot fi simulate cu Modelsim), acest soft mi-a fost de mare
ajutor pentru a testa dacă codurile VHDL scrise de mine erau sintetizabile.

16
CY7C910 Microprogram Controller
Descriere funcţională
CY7C910 este un microprogram controller de sine stătător care selectează, testează, stochează, reface,
manipulează şi testează adresele care controlează secvenţa de execuţie a instrucţiunilor stocate într-o
memorie externă. Toate adresele sunt valori pe 12 biţi care desemnează o locaţie absolută de memorie.
După cum se vede din diagrama bloc, CY7C910 constă dintr-o stivă LIFO (last in first out) de 17 locaţii a
câte 12 biţi împreună cu un indicator de stivă (stack pointer – SP) , un registru/numărător (Register/Counter)
pe 12 biţi, un numărător de program (Microprogram Counter – MPC) , un multiplexor de 4 intări de câte 12
biţi şi logica necesară pentru manipularea şi controlul datelor.
Operaţia executată este determinată de 4 linii de instrucţiuni de intrare (I3 – I0) care selectează sursa
(internă) următoarei microinstrucţiuni ce urmează a fi executată. Această adresă este scoasă la ieşirile Y11 –
Y0. Două intrări suplimentare (\CC şi \CCEN) sunt destinate pentru a fi examinate în timpul executării
anumitor instrucţiuni, ceea ce permite utilizatorului să facă execuţia unei instrucţiuni fie necondiţionată, fie
condiţionată de un test extern.

CY7C910 - diagrama bloc

Descrierea pinilor
Nume I/O Descriere
D0 – D11 I Intrări directe către RC (Register/Counter) şi multiplexor.
D0 este LSB, iar D11 este MSB
\RLD I Intrare de control a RC care, atunci când este pe nivelul
LOW, incarcă data de pe pinii de intrare D11 – D0 în RC, pe
frontul crescător al semnalului de ceas (CP)

I3 – I0 I Intrările de instrucţiune care selectează una din cele 16


instrucţiuni pentru a fi executată de CY7C910
\CC I Intrare de control care, atunci când se află pe nivelul LOW,
inseamnă că un test a fost trecut
\CCEN I Intrare de activare a semnalului \CC. Dacă este pe nivel HIGH,
\CC este ignorat şi este forţată trecerea testului. Dacă este pe nivel LOW,
starea semnalului \CC este examinată
CP I Intrarea pentru semnalul de ceas. Toate stările interne se
17
modifică pe frontul crescător al semnalului de ceas
CI I Intrare de carry pentru LSB-ul incrementorului pentru MPC
\OE I Intrare de control pentru ieşirile Y11 – Y0. LOW pentru activarea,
HIGH pentru dezactivarea buferelor threee-state de pe ieşiri.
Y11 – Y0 O Ieşirile de adresă către memoria program. Y0 este LSB, iar
Y11 este MSB
\FULL O Când este pe nivel LOW indică faptul că stiva este plină
\PL O Când este pe nivel LOW selectează registrul pipeline ca sursă
pentruintrările directe D
\MAP O Când este pe nivel LOW selectează PROM-ul mapat (sau
PLA-ul) ca sursă pentru intrările directe D
\VECT O Când este pe nivel LOW selectează vectorul de întrerupere ca
sursă pentru intrările directe D

Arhitectura CY7C910
CY7C910 este un microprogram controller care generează o secvenţă de adrese de 12 biţi care controlează
execuţia unui microprogram. Adresele sunt selectate din una din cele 4 surse posibile, în funcţie de
instrucţiunea în execuţie (I3 – I0) şi de alte semnale externe. Cele 4 surse sunt :
1.intrările D11 – D0 ;
2.RC (register/counter) ;
3.stiva
4.MPC (microprogram counter)
Câte 12 linii de un bit de la fiecare din aceste 4 surse reprezintă intrările într-un multiplexor (după cum se
vede în diagrama bloc) ale cărui ieşiri sunt aplicate intrărilor driverelor three-state de ieşire Y11 – Y0 .

Semnalele de intrare externe : D11 – D0


Semnalele de intrare externe sunt folosite ca sursă pentru adresele destinaţie în cazul instrucţiunilor de salt
(jump) şi ramificare (branch) . O a doua utilizare a acestor intrări este la încărcarea RC-ului.

RC (register/counter)
Registrul/numărător RC este realizat din 12 bistabili de tip D activi pe frontul crescător al semnalului de
ceas. Datele de pe intrările D sunt încărcate sincron în RC atunci când semnalul de intrare pentru controlul
încărcării, \RLD, este pe nivel LOW. Ieşirea RC este disponibilă ca intrarea R a multiplexorului şî poate fi
transferată la ieşirile Y în timpul execuţiei anumitor instrucţiuni, după cum este indicat de R în tabela de
instrucţiuni.
RC operează ca un numărător pe 12 biţi, conţinutul său fiind decrementat şi testat dacă este zero în timpul
instrucţiunilor 8, 9 şi 15. Aceasta permite repetarea de până la 4096 de ori a unor microinstrucţiuni. RC este
conceput astfel încât, dacă este încărcat cu un număr N, secvenţa va fi executată de exact N+1 ori.

Stiva şi indicatorul de stivă (SP)


Stiva din 17 locaţii de 12 biţi este utilizată pentru furnizarea adreselor de revenire din subrutine sau cicluri.
SP-ul indică (adresează) ultima dată salvată în stivă, ceea ce permite referirea la această dată fără a fi
nevoie de extragerea acesteia din stivă (execuţia unei instrucţiuni POP) .
SP-ul funcţionează ca un numărător bidirecţional care este incrementat cănd se execută o operaţiune de tip
PUSH (instrucţiunile 8, 10, 11, 13 sau 15) . Operaţia PUSH scrie in stivă adresa de revenire, iar operaţiunea
POP o şterge efectiv de pe stivă. Operaţia propriuzisă este executată pe frontul crescător al semnalului de
ceas care urmează instrucţiunea.
Stiva este iniţializată prin execuţia instrucţiunii 0 (“salt la locaţia zero” sau “reset”) . De fiecare dată când se
execută o instrucţiune “salt la subrutină”(1, 5) sau de ciclare (4) , adresa de revenire este depusă pe stivă, şi
de fiecare dată când se execută o instrucţiune de revenire din subrutină sau din ciclu, adresa de revenire este
retrasă de pe stivă.
18
Când o subrutină apelează o altă subrutină sau un ciclu apare în interiorul altui ciclu (cicluri imbricate)
adâncimea logică a stvei creşte. Adâncimea fizică a stivei este de 17 locaţii. Când această adâncime este
atinsă, semnalul \FULL trece în starea LOW la următorul front crescător al semnalului de ceas. Orice altă
operaţie PUSH asupra unei stive pline va determina ca data din vârful stivei să fie suprascrisă, dar nu va
incrementa SP-ul.Similar, executând o operaţie POP asupra unei stive goale nu va decrementa SP-ul şi ar
putea determina apariţia unor date fără sens la ieşirile Y.

MPC (Microprogram counter ) :


MPC-ul constă dintr-un incrementor pe 12 biţi, urmat de un registru de 12 biţi. În mod obişnuit, registrul
reţine adresa instrucţiunii în curs de execuţie. Când instrucţiunile sunt executate secvenţial (succesiv, una
după alta după cum se află în memorie) , intrarea de carry (CI) către incrementor este pe nivel HIGH şi, ca
urmare, se adună 1 la ieşirile Y ale multiplexorului, care sunt încărcate în MPC la următorul front crescător
al semnalului de ceas.
Când intrarea CI este pe nivel LOW, ieşirile Y ale multiplexorului sunt Incărcate direct în MPC, astfel încât
aceeaşi instrucţiune este extrasă şi executată.

Tabela de instrucţiuni
RESULT
RC Fail Pass RC Enable
I3-I0 Mnemonic Name con- \CCEN=L \CCEN=H
tents \CC=H \CC=L
Y Stack Y Stack
0 JZ Jump Zero X 0 Clear 0 Clear Hold PL
1 CJS Cond JSB PL X PC Hold D Push Hold PL
2 JMAP Jump Map X D Hold D Hold Hold Map
3 CJP Cond Jump PL X PC Hold D Hold Hold PL
4 PUSH Push/Cond LD CNTR X PC Push PC Push Note PL
5 JSRP Cond JSB R/PL X R Push D Push Hold PL
6 CJV Cond Jump Vector X PC Hold D Hold Hold Vect
7 JRP Cond Jump R/PL X R Hold D Hold Hold PL
8 RFCT Repeat Loop, ≠0 F Hold F Hold Dec PL
CNTR ≠ 0 =0 PC Pop PC Pop Hold PL
9 RPCT Repeat PL, ≠0 D Hold D Hold Dec PL
CNTR ≠ 0 =0 PC Hold PC Hold Hold PL
10 CRTN Cond Return X PC Hold F Pop Hold PL
11 CJPP Cond Jump PL & Pop X PC Hold D Pop Hold PL
12 LDCT LD Cntr & Continue X PC Hold PC Hold Load PL
13 LOOP Test end Loop X F Hold PC Pop Hold PL
14 CONT Continue X PC Hold PC Hold Hold PL
15 TWB Three-Way Branch ≠0 F Hold PC Pop Dec PL
=0 D Pop PC Pop Hold PL

Introducere

Proiectarea unui circuit integrat digital (şi nu numai) presupune în primul rând înţelegerea
deplină a funcţionării circuitului (a ceea ce doreşte beneficiarul proiectului) .

19
Presupunând că din datele de catalog s-a înţeles foarte bine funcţionarea circuitului, următoarea
etapă este reprezentată de descompunerea circuitului în blocuri funcţionale. Această descompunere a
circuitului are, în principal, următoarele motivaţii :
- fiecare bloc component al circuitului poate fi încredinţat câte unui proiectant, ceea ce duce la scăderea
timpului de proiectare faţă de situaţia în care întreg proiectul ar fi încredinţat unui singur proiectant ;
- detecţia, localizarea şi corectarea erorilor de proiectare sunt mult mai facile în cazul descompunerii
circuitului în subcircuite ;
În cazul circuitului CY7C910, pentru descompunerea acestuia în subblocuri am pornit de la diagrama bloc
prezentată în catalog. Faţă de această diagramă bloc am făcut următoarele modificări :
- blocurile “Microprogram Counter-Register” şi “Incrementer” au fost unite într-un singur bloc, numit MPC
(Microprogram Counter) , deoarece :
- se reduce aria consumată : un numărător pe 12 biţi (Incrementer) şi un registru de 12 biţi (Microprogram
Counter-Register) sunt înlocuiţi cu un numărător pe 12 biţi (Microprogram Counter) .
- se rezolvă unele probleme de timing : datele de la intrarea blocului Incrementer modifică ieşîrea acestuia
după primul front activ al semnalului de ceas, iar încărcarea datelor de la ieşirea Incrementer-ului în
Microprogram Counter-Register se face pe următorul front activ al semnalului de ceas (apare astfel o
întârziere suplimentară de o perioadă de ceas între aplicarea datelor pe intrarea Incrementer-ului şi apariţia
datelor la ieşirile blocului Microprogram Counter-Register, ceea ce ar da complet peste cap funcţionarea
circuitului CY7C910) ; s-ar mai putea imagina o soluţie în care Incrementer-ul ar fi activ pe frontul negativ
al semnalului de ceas, iar Microprogram-Counter-Register-ul aer fi activ pe frontul crescător al semnalului
de ceas, însă şi această soluţie ar ridica anumite probleme de timing şi ar determina o scădere a frecvenţei
maxime de funcţionare a circuitului CY7C910.
- blocurile Stack Pointer şi 17 Word x 12 Bit Stack au fost înlocuite cu un singur bloc, numit STACK ;
Iniţial am încercat să descriu separat cele două blocuri dar, în urma simulării post-sinteză a ansamblului
format cu cele 2 blocuri, am constatat funcţionarea defectoasă a ansamblului. După mai mult de 10 descrieri
VHDL încercate (trebuie spus că simulările pre-sinteză arătau funcţionarea corectă pentru fiecare din aceste
descrieri), codul care a determinat funcţionarea corectă post-sinteză corespundea cazului de stivă monobloc.
- apare, în plus faţă de diagrama bloc prezentată în catalog, blocul INTERFATA_SURSA care, deşi nu
aduce circuitului îmbunătăţiri din punct de vedere al ariei sau vitezei (dar nici nu le influenţează negativ) ,
uşurează scrierea codului VHDL pentru blocul INSTRUCTION DECODER.

Diagrama bloc obţinută în urma modificărilor de mai sus

Blocurile componente pot fi la rândul lor descompuse în alte blocuri mai mici şi aşa mai departe,
până când se obţin blocuri suficient de mici pentru a putea fi descrise cu uşurinţă în VHDL. În cazul
circuitului CY7C910 nu am considerat necesară descompunerea suplimentară a blocurilor componente, dar
am apelat la această metodă în cazul unor blocuri ale circuitului CY7C901.
După descompunerea circuitului în blocuri funcţionale, se poate trece la proiectarea fiecărui bloc în
parte. Pentru fiecare bloc trebuie parcurse următoarele etape :

20
1.scrierea unui program de test (test_bench) în VHDL, în care se precizează semnalele de intrare ce vor fi
aplicate blocului testat şi semnalele de ieşire care ar trebui să fie determinate de semnalele de intrare.
2.scrierea unui cod VHDL care să descrie funcţionarea dorită pentru blocul proiectat ; la realizarea descrierii
VHDL trebuie avut în grijă ca această descriere să fie sintetizabilă (aceasta presupune utilizarea unei sintaxe
acceptate de instrumentul de sinteză) .
3.compilarea codului VHDL obţinut în etapa a 2-a şi corectarea eventualelor erori de sintaxă (erorile de
funcţionare sau logice nu pot fi evidenţiate în urma compilării) ; în urma compilării este generată o entitate
(entity) VHDL cu numele blocului descris ;
4. entitatea generată în etapa a 3-a este simulată cu programul de test realizat în etapa 1; dacă în urma
simulării se constată o funcţionare incorectă a entităţii, trebuie să revenim la etapa a 2-a ;
5.dacă simularea cu programul de test a dovedit funcţionarea corectă a entităţii, se poate trece la sinteza
descrierii VHDL obţinută în etapa a 2-a. În urma sintezei (realizate cu Design Compiler) sunt generate un
fisier VHDL şi un fişier SDF (Standard Delay Format) .
6.se compilează fişierul VHDL obţinut în urma sintezei, iar entitatea generată în urma compilării este
simulată (cu fişierul SDF aplicat) cu programul de test de la etapa 1. Dacă simularea arată o funcţionare
corectă, îneamnă că proiectarea blocului respectiv este încheiată şi că descrierea VHDL de la etapa a 2-a
poate fi folosită la realizarea circuitului CY7C910; în cazul în care simularea arată o funcţionare incorectă
trebuie să ne dăm seama de cauză şi să revenim la etapa a 2-a ; această revenire la etapa de rescriere a
codului VHDL poate părea ciudată întrucât simularea presinteză a dovedit corectitudinea descrierii realizate
în etapa a 2-a, însă chiar eu m-am lovit de o asemenea situaţie în cazul proiectării stivei – amănunte vor fi
prezentate când voi analiza proiectarea acestui bloc.
După proiectarea tuturor blocurilor componente, acestea trebuie interconectate pentru a realiza
împreună funcţionarea circuitului CY7C910. Această abordare corespunde metodei de proiectare “bottom-
up”.

Package-ul
În cazul proiectelor de dimensiuni mari, întâlnim adesea funcţii, proceduri, tipuri de date sau
constante care sunt folosite în mai multe componente ale proiectului sau/şi de mai mulţi proiectanţi. Dacă pe
parcursul proiectării se modifică una din aceste funcţii, proceduri sau tipuri de date, este preferabil ca
proiectul să fie modificat într-un singur loc, nu peste tot unde acestea au fost utilizate. Acest lucru este
posibil prin utilizarea package-urilor.
Package-urile sunt foarte utile şi din alt motiv: posibilitatea reutilizării codului VHDL pentru
implementări ulterioare ale aceluiaşi circuit. De exemplu, în cazul circuitului CY7C910, stiva conţine 17
locaţii a 12 biţi ; este posibil ca in viitor să se dorească implementarea unei variante a acestui circuit dar care
să dispună, de exemplu, de o stivă cu 24 de locaţii (de fapt, CY7C910 reprezintă o variantă îmbunătăţită a
circuitelor din familia AM2910 ; astfel AM2910 dispune de o stivă cu 5 locaţii, iar AM2910A dispune de o
stivă cu 9 locaţii) sau de un bus de adrese cu lăţimea de 16 biţi (în loc de 12 biţi) .
Pentru acest proiect am conceput un package care să realizeze 2 funcţii :
- posibilitatea reutilizării codului VHDL pentru implementări de variante ale circuitului CY7C910 cu
dimensiuni diferite pentru stivă sau pentru bus-ul de adrese ;
- facilitarea scrierii unui cod mai uşor de urmărit.
packageCY7C910.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
package packageCY7C910 is

-- seciunea destinata reutilizarii codului si tipurilor de date care sunt


-- folosite in mai multe blocuri ale proiectului
constant address_bus_width : integer := 12 ;
constant stack_depth : integer := 17 ;
constant zero12 : std_logic_vector(address_bus_width - 1 downto 0) := "000000000000" ;
subtype mem_width is std_logic_vector (address_bus_width - 1 downto 0) ;
type mem is array (stack_depth - 1 downto 0) of mem_width ;

-- sectiunea destinata scrierii unui cod usor de urmarit


21
-- sunt definite (botezate) toate tipurile de date necesare in proiect

-- instructiunile de selectie a MULTILPEXER


constant ZEROmux : std_logic_vector (2 downto 0) := "000" ;
constant MPCmux : std_logic_vector (2 downto 0) := "001" ;
constant Dmux : std_logic_vector (2 downto 0) := "010" ;
constant Rmux : std_logic_vector (2 downto 0) := "011" ;
constant Fmux : std_logic_vector (2 downto 0) := "100" ;

-- instructiunile de comanda a stivei (STACK)


constant Clear_s : std_logic_vector (1 downto 0) := "00" ;
constant Hold_s : std_logic_vector (1 downto 0) := "01" ;
constant Push_s : std_logic_vector (1 downto 0) := "10" ;
constant Pop_s : std_logic_vector (1 downto 0) := "11" ;

-- instructiunile de comanda a Register/Counter


constant Hold : std_logic_vector (1 downto 0) := "00" ;
constant DEC : std_logic_vector (1 downto 0) := "01" ;
constant Load : std_logic_vector (1 downto 0) := "10" ;

-- insructiunile de comanda ale MPC (MicroProgram Counter)


constant Clear : std_logic := '0' ;
constant Count : std_logic := '1' ;

-- instructiunile de comanda pentru INTERFATA_SURSA


constant PL : std_logic_vector (1 downto 0) := "00" ;
constant Mapp : std_logic_vector (1 downto 0) := "01" ;
constant Vect : std_logic_vector (1 downto 0) := "10" ;

-- instructiunile de comanda ale CY7C910 (I3 - I0)


constant JZ : std_logic_vector (3 downto 0) := "0000" ;
constant CJS : std_logic_vector (3 downto 0) := "0001" ;
constant JMAP : std_logic_vector (3 downto 0) := "0010" ;
constant CJP : std_logic_vector (3 downto 0) := "0011" ;
constant PUSH : std_logic_vector (3 downto 0) := "0100" ;
constant JSRP : std_logic_vector (3 downto 0) := "0101" ;
constant CJV : std_logic_vector (3 downto 0) := "0110" ;
constant JRP : std_logic_vector (3 downto 0) := "0111" ;
constant RFCT : std_logic_vector (3 downto 0) := "1000" ;
constant RPCT : std_logic_vector (3 downto 0) := "1001" ;
constant CRTN : std_logic_vector (3 downto 0) := "1010" ;
constant CJPP : std_logic_vector (3 downto 0) := "1011" ;
constant LDCT : std_logic_vector (3 downto 0) := "1100" ;
constant LOP : std_logic_vector (3 downto 0) := "1101" ;
constant CONT : std_logic_vector (3 downto 0) := "1110" ;
constant TWB : std_logic_vector (3 downto 0) := "1111" ;

-- definire de tipuri de date pt vizualizarea mai usoara a semnalelor


type INSTR_type is (JZ_v, CJS_v, JMAP_v, CJP_v, PUSH_v, JSRP_v, CJV_v, JRP_v, RFCT_v,
RPCT_v, CRTN_v, CJPP_v, LDCT_v, LOP_v, CONT_v, TWB_v, XXXX) ;
type MUX_type is (ZEROmux_v, MPCmux_v, Dmux_v, Rmux_v, Fmux_v, XXX) ;
type STACK_type is (Clear_v, Hold_v, Push_v, Pop_v, XXX) ;
type RC_type is (Hold_v, Dec_v, Load_v, XXX) ;
type MPC_type is (Clear_v, Count_v, XXX) ;
type INT_S_type is (PL_v, Mapp_v, Vect_v, XXX) ;

end packageCY7C910 ;

Acest package, numit “packageCY7C910” este salvat în fişierul “packageCY7C910.vhd”.


Referitor la acest package trebuie să fac următoarea observaţie: dacă în cazul celor 16 instrucţiuni ale
CY7C910 lucrurile sunt destul de clare, întrucât echivalentul binar al acestora este specificat în tabela de
instrucţiuni, în cazul instrucţiunilor pentru blocurile componente ale circuitului apar unele probleme.; astfel,
în mod normal, ar fi trebuit ca eu doar să definesc, pentru un anume set de instrucţiuni, tipul şi denumirea
acestora (de exemplu ‘ type instr_stiva is Clear_s, Hold_s, Push_s, Pop_s ; ‘) , iar programul de sinteză, în
urma optimizării, să atribuie echivalenţii binari pentru instrucţiuni ; din motive care mie îmi scapă, doar
Leonardo Spectrum acceptă această sintaxă, pe când Desing Compiler generează erori ; întrucât principalul
instrument de sinteză utilizat la realizarea proiectului este Design Compiler, am preferat să folosesc
package-ul de mai sus (care funcţionează şi cu Leonardo Spectrum) , în care am atribuit valori arbitrare
pentru echivalenţii binari ai semnalelor interne circuitului CY7C910.

22
INSTRUCTION_DECODER
Programul de test şi descrierea VHDL pentru acest bloc sunt prezentate în continuare :
test_INSTRUCTION_DECODER.vhd
library IEEE, STD ;
use IEEE.std_logic_1164.all ;
use IEEE.numeric_std.all ;
use IEEE.std_logic_unsigned.all ;
use IEEE.std_logic_arith.all ;
use work.std_logic_arith.all ;
use std.textio.all ;
use work.packageCY7C910.all ;
entity test_INSTRUCTION_DECODER is end ;

architecture test of test_INSTRUCTION_DECODER is


signal I : std_logic_vector (3 downto 0) := "0000" ;
signal nCC, nCCEN, ZERO_DET : std_logic ;
signal MUX_SEL : std_logic_vector (2 downto 0) ;
signal STACK_CNTL : std_logic_vector (1 downto 0) ;
signal REG_CNTR_CNTL : std_logic_vector (1 downto 0) ;
signal MPC_CNTL : std_logic ;
signal ENABLE_CNTL : std_logic_vector (1 downto 0) ;
signal test_OK : boolean := TRUE ;
constant DELAY : time := 1 ns ; --DELAY_TIME ;
constant T_CK : time := 10 ns ; --CK period ;
component INSTRUCTION_DECODER
port (I : in std_logic_vector (3 downto 0) ; nCC, nCCEN, ZERO_DET : in std_logic; MUX_SEL : out std_logic_vector (2 downto 0) ;
STACK_CNTL : out std_logic_vector (1 downto 0) ; REG_CNTR_CNTL : out std_logic_vector (1 downto 0) ;
MPC_CNTL : out std_logic ; ENABLE_CNTL : out std_logic_vector (1 downto 0) ) ;
end component ;

-- definire de tipuri de date pt vizualizarea mai usoara a semnalelor


type INSTR_type is (JZ_v, CJS_v, JMAP_v, CJP_v, PUSH_v, JSRP_v, CJV_v, JRP_v, RFCT_v, RPCT_v, CRTN_v, CJPP_v, LDCT_v, LOP_v, CONT_v, TWB_v,
XXXX) ;
type MUX_type is (ZEROmux_v, MPCmux_v, Dmux_v, Rmux_v, Fmux_v, XXX) ;
type STACK_type is (Clear_v, Hold_v, Push_v, Pop_v, XXX) ;
type RC_type is (Hold_v, Dec_v, Load_v, XXX) ;
type MPC_type is (Clear_v, Count_v, XXX) ;
type INT_S_type is (PL_v, Mapp_v, Vect_v, XXX) ;
-- definirea semnalelor pentru vizualizarea mai usoara
signal INSTRUCTION : INSTR_type ;
signal MUX_SEL_v : MUX_type ;
signal STACK_CNTL_v : STACK_type ;
signal REG_CNTR_CNTL_v : RC_type ;
signal MPC_CNTL_v : MPC_type ;
signal ENABLE_CNTL_v : INT_S_type ;

begin
DUT : INSTRUCTION_DECODER port map (I, nCC, nCCEN, ZERO_DET, MUX_SEL, STACK_CNTL, REG_CNTR_CNTL, MPC_CNTL, ENABLE_CNTL) ;

process
begin
wait for T_CK ;
I <= I + 1 ;
end process ;
nCC <= '1', '0' after 16 * T_CK, 'X' after 32 * T_CK, '1' after 48 * T_CK, '0' after 64 * T_CK, 'X' after 80 * T_CK ;
nCCEN <= '0', 'X' after 16 * T_CK, '1' after 32 * T_CK, '0' after 48 * T_CK, 'X' after 64 * T_CK, '1' after 80 * T_CK ;
ZERO_DET <= 'X', '1' after 8 * T_CK, 'X' after 10 * T_CK, '1' after 15 * T_CK, 'X' after 16 * T_CK, '1' after 24 * T_CK, 'X' after 26 * T_CK, '1'
after 31 * T_CK,
'X' after 32*T_CK, '0' after 40*T_CK, 'X' after 42*T_CK, '0' after 47*T_CK, 'X' after 48*T_CK, '0' after 56*T_CK, 'X' after 58*T_CK, '0' after
63 * T_CK ;

process
begin
wait until i'event ;
wait for DELAY ;
case I is
when JZ =>
if (nCC = '1' and nCCEN = '0') then
if (MUX_SEL = ZEROmux and STACK_CNTL = Clear_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Clear and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = ZEROmux and STACK_CNTL = Clear_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Clear and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when CJS =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Push_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when JMAP =>

23
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = Mapp) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = Mapp) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when CJP =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when PUSH =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Push_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Push_s and REG_CNTR_CNTL = Load and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when JSRP =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Rmux and STACK_CNTL = Push_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Push_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when CJV =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = Vect) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = Vect) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when JRP =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Rmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when RFCT =>


case ZERO_DET is
when '1' =>

24
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;
when others =>
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Fmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Dec and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Fmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Dec and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;
end case ;

when RPCT =>


case ZERO_DET is
when '1' =>
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;
when others =>
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Dec and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Dec and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;
end case ;

when CRTN =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Fmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when CJPP =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = Dmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

25
when LDCT=>
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Load and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Load and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when LOP =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Fmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when CONT =>


if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;

when others => -- TWB


case ZERO_DET is
when '1' =>
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Dmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Hold and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;
when others =>
if (nCCEN = '0' and nCC = '1') then
if (MUX_SEL = Fmux and STACK_CNTL = Hold_s and REG_CNTR_CNTL = Dec and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
else
if (MUX_SEL = MPCmux and STACK_CNTL = Pop_s and REG_CNTR_CNTL = Dec and MPC_CNTL = Count and ENABLE_CNTL = PL) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;

end if ;
end if ;
end case ;

end case ;

end process ;

OK : process (test_ok)
begin
if (test_OK'event and test_OK = FALSE) then
report " EROARE "
severity warning ;
end if ;
end process ;

-- atribuirea de valori semnalelor destinate vizualizarii

26
process (I)
begin
if (I'event) then
case I is
when JZ => INSTRUCTION <= JZ_v ;
when CJS => INSTRUCTION <= CJS_v;
when JMAP => INSTRUCTION <= JMAP_v ;
when CJP => INSTRUCTION <= CJP_v ;
when PUSH => INSTRUCTION <= PUSH_v ;
when JSRP => INSTRUCTION <= JSRP_v ;
when CJV => INSTRUCTION <= CJV_v ;
when JRP => INSTRUCTION <= JRP_v ;
when RFCT => INSTRUCTION <= RFCT_v ;
when RPCT => INSTRUCTION <= RPCT_v ;
when CRTN => INSTRUCTION <= CRTN_v ;
when CJPP => INSTRUCTION <= CJPP_v ;
when LDCT => INSTRUCTION <= LDCT_v ;
when LOP => INSTRUCTION <= LOP_v ;
when CONT => INSTRUCTION <= CONT_v ;
when TWB => INSTRUCTION <= TWB_v ;
when others => INSTRUCTION <= XXXX ;
end case ;
end if ;
end process ;
process (MUX_SEL)
begin
if (MUX_SEL'event) then
case MUX_SEL is
when ZEROmux => MUX_SEL_v <= ZEROmux_v ;
when MPCmux => MUX_SEL_v <= MPCmux_v ;
when Dmux => MUX_SEL_v <= Dmux_v ;
when Rmux => MUX_SEL_v <= Rmux_v ;
when Fmux => MUX_SEL_v <= Fmux_v ;
when others => MUX_SEL_v <= XXX ;
end case ;
end if ;
end process ;

process (STACK_CNTL)
begin
if (STACK_CNTL'event) then
case STACK_CNTL is
when Clear_s => STACK_CNTL_v <= Clear_v ;
when Hold_s => STACK_CNTL_v <= Hold_v ;
when Push_s => STACK_CNTL_v <= Push_v ;
when Pop_s => STACK_CNTL_v <= Pop_v ;
when others => STACK_CNTL_v <= XXX ;
end case ;
end if ;
end process ;

process (REG_CNTR_CNTL)
begin
if (REG_CNTR_CNTL'event) then
case REG_CNTR_CNTL is
when Hold => REG_CNTR_CNTL_v <= Hold_v ;
when Dec => REG_CNTR_CNTL_v <= Dec_v ;
when Load => REG_CNTR_CNTL_v <= Load_v ;
when others => REG_CNTR_CNTL_v <= XXX ;
end case ;
end if ;
end process ;

process (MPC_CNTL)
begin
if (MPC_CNTL'event) then
case MPC_CNTL is
when Clear => MPC_CNTL_v <= Clear_v ;
when Count => MPC_CNTL_v <= Count_v ;
when others => MPC_CNTL_v <= XXX ;
end case ;
end if ;
end process ;

process (ENABLE_CNTL)
begin
if (ENABLE_CNTL'event) then
case ENABLE_CNTL is
when PL => ENABLE_CNTL_v <= PL_v ;
when Mapp => ENABLE_CNTL_v <= Mapp_v ;
when Vect => ENABLE_CNTL_v <= Vect_v ;
when others => ENABLE_CNTL_v <= XXX ;
end case ;
end if ;
end process ;
end test ;

INSTRUCTION_DECODER.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity INSTRUCTION_DECODER is
port (I : in std_logic_vector (3 downto 0) ;
nCC, nCCEN, ZERO_DET : in std_logic;
MUX_SEL : out std_logic_vector (2 downto 0) ;
STACK_CNTL : out std_logic_vector (1 downto 0) ;

27
REG_CNTR_CNTL : out std_logic_vector (1 downto 0) ;
MPC_CNTL : out std_logic ;
ENABLE_CNTL : out std_logic_vector (1 downto 0) ) ;
end INSTRUCTION_DECODER ;
architecture RTL of INSTRUCTION_DECODER is
begin
process (I, nCC, nCCEN, ZERO_DET)
begin
if (nCCEN = '0' and nCC = '1') then
case I is
when JZ => MUX_SEL <= ZEROmux ;
STACK_CNTL <= Clear_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Clear ;
when CJS => MUX_SEL <= MPCmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
when JMAP => MUX_SEL <= Dmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= Mapp ;
MPC_CNTL <= Count ;
when CJP => MUX_SEL <= MPCmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
when PUSH => MUX_SEL <= MPCmux ;
STACK_CNTL <= Push_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
when JSRP => MUX_SEL <= Rmux ;
STACK_CNTL <= Push_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
when CJV => MUX_SEL <= MPCmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= Vect ;
MPC_CNTL <= Count ;
when JRP => MUX_SEL <= Rmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when RFCT =>


if ( ZERO_DET = '1') then
MUX_SEL <= MPCmux ;
STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
else
MUX_SEL <= Fmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Dec ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
end if ;

when RPCT =>


if ( ZERO_DET = '1') then
MUX_SEL <= MPCmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

else
MUX_SEL <= Dmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Dec ;
28
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
end if ;

when CRTN => MUX_SEL <= MPCmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when CJPP => MUX_SEL <= MPCmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when LDCT => MUX_SEL <= MPCmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Load ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when LOP => MUX_SEL <= Fmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when CONT => MUX_SEL <= MPCmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when others => -- TWB


if (ZERO_DET = '1') then
MUX_SEL <= Dmux ;
STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
else
MUX_SEL <= Fmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= DEC ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
end if ;

end case ;
else
case I is
when JZ => MUX_SEL <= ZEROmux ;
STACK_CNTL <= Clear_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Clear ;

when CJS => MUX_SEL <= Dmux ;


STACK_CNTL <= Push_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when JMAP => MUX_SEL <= Dmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= Mapp ;
MPC_CNTL <= Count ;

when CJP => MUX_SEL <= Dmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when PUSH => MUX_SEL <= MPCmux ;


STACK_CNTL <= Push_s ;
29
REG_CNTR_CNTL <= Load ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when JSRP => MUX_SEL <= Dmux ;


STACK_CNTL <= Push_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when CJV => MUX_SEL <= Dmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= Vect ;
MPC_CNTL <= Count ;

when JRP => MUX_SEL <= Dmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when RFCT =>


if ( ZERO_DET = '1') then
MUX_SEL <= MPCmux ;
STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

else
MUX_SEL <= Fmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Dec ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

end if ;

when RPCT =>


if ( ZERO_DET = '1') then
MUX_SEL <= MPCmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
else
MUX_SEL <= Dmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Dec ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
end if ;

when CRTN => MUX_SEL <= Fmux ;


STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when CJPP => MUX_SEL <= Dmux ;


STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when LDCT => MUX_SEL <= MPCmux ;


STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Load ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when LOP => MUX_SEL <= MPCmux ;


STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

30
when CONT => MUX_SEL <= MPCmux ;
STACK_CNTL <= Hold_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;

when others => --TWB


if (ZERO_DET = '1') then
MUX_SEL <= MPCmux ;
STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= Hold ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
else
MUX_SEL <= MPCmux ;
STACK_CNTL <= Pop_s ;
REG_CNTR_CNTL <= DEC ;
ENABLE_CNTL <= PL ;
MPC_CNTL <= Count ;
end if ;

end case ;
end if ;
end process ;
end RTL ;

Descrierea VHDL pentru acest bloc nu reprezintă altceva decât transpunerea în limbaj VHDL a tabelei de
instrucţiuni de la prezentarea circuitului CY7C910. Acest bloc nu a ridicat probleme deosebite de
programare, însă au apărut unele probleme din cauza neatenţiei la citirea datelor din tabel, probleme care au
fost evidenţiate în urma testării, fiind apoi corectate cu uşurinţă. Ar mai trebui precizat faptul că, pe cât
posibil, am folosit instrucţiunea case în locul instrucţiunii if, aceasta fiind una dintre cele mai importante
recomandări de proiectare.

INSTRUCTION_DECODER – (RTL)

31
Register/Counter
Programul de test şi descrierea VHDL pentru acest bloc sunt prezentate în continuare :
test_RC.vhd
library IEEE, STD ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.packageCY7C910.all ;
entity test_REGISTER_COUNTER is end ;

architecture test of test_REGISTER_COUNTER is


signal CK, nRLD : std_logic := '0' ;
signal CNTL : std_logic_vector (1 downto 0) ;
signal CNTL_v : RC_type ; -- pt vizualizare
signal DATAIN, DATAOUT : std_logic_vector(address_bus_width - 1 downto 0) := "111000111000" ;
signal DATAIN_v, DATAOUT_v : integer ; -- pentru vizualizare
signal test_OK : BOOLEAN := TRUE ;
signal last_DATAIN, last_DATAOUT : std_logic_vector(address_bus_width - 1 downto 0) ;
constant CK_SPER : time := 5 ns ; --semiperioada semnalului de ceas
constant DELAY : time := 3 ns ;
component REGISTER_COUNTER
port( CK, nRLD : in std_logic ; CNTL : in std_logic_vector (1 downto 0) ;
32
DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
DATAOUT : buffer std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

begin
DUT : REGISTER_COUNTER port map (CK, nRLD, CNTL, DATAIN, DATAOUT) ;
CK <= not CK after CK_SPER ;
nRLD <= '0', '1' after 11 * CK_SPER ;
CNTL <= Load, Dec after 4* CK_SPER, Hold after 8 * CK_SPER, Load after 14 * CK_SPER, Dec after 18 *
CK_SPER, Hold after 28*CK_SPER, Load after 32*CK_SPER, Dec after 38*CK_SPER ;
DATAIN <= ( (DATAIN - 5) nor (shl (DATAIN, "10") ) ) after 4 * CK_SPER ;
-- generare pseudo_aleatoare a datelor de intrare
DATAIN_v <= conv_integer (DATAIN) ;
DATAOUT_v <= conv_integer (DATAOUT) ;

process
begin
wait until CK = '1' ;
wait for DELAY ;
case nRLD is
when '0' =>
if (DATAOUT = DATAIN) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity warning ;
end if ;
when others =>
case CNTL is
when Load =>
if (DATAOUT = last_DATAIN) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity warning ;

end if ;
when Dec =>
if (DATAOUT = last_DATAOUT - 1) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity warning ;
end if ;

when others =>


if (DATAOUT = last_DATAOUT ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity warning ;
end if ;
end case ;

end case ;

wait until CK = '0' ;


last_DATAIN <= DATAIN ;
last_DATAOUT <= DATAOUT ;
end process ;

process (CNTL)
begin
if (CNTL'event) then
case CNTL is
when Load => CNTL_v <= Load_v ;
when Hold => CNTL_v <= Hold_v ;
when Dec => CNTL_v <= Dec_v ;
when others => CNTL_v <= XXX ;
end case ;
end if ;
end process ;

end test ;
33
REGISTER_COUNTER.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.packageCY7C910.all ;
entity REGISTER_COUNTER is
port( CK, nRLD : in std_logic ; CNTL : in std_logic_vector (1 downto 0) ;
DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
DATAOUT : buffer std_logic_vector (address_bus_width - 1 downto 0) ) ;
end REGISTER_COUNTER ;

architecture RTL of REGISTER_COUNTER is


begin
process (CK)
begin
if (CK'event and CK = '1') then
case nRLD is
when '0' =>
DATAOUT <= DATAIN ;
when others =>
case CNTL is
when Load =>
DATAOUT <= DATAIN ;
when Dec =>
DATAOUT <= DATAOUT - 1 ;
when others =>
null ;
end case ;
end case ;
end if ;
end process ;
end RTL ;

REGEISTER_COUNTER – (RTL)

REGISTER_COUNTER – (RTL)
34
În cazul acestui bloc, se observă (prima figură) că programul de sinteză a recunoscut, din codul VHDL,
structurile a 2 dintre macrocelule din biblioteca sa de componente şi anume : decoder_2 şi
counter_dn_sload_clock_clk_en_12. În a doua figură sunt prezentate şi arhitecturile interne ale celor două
macrocelule.

STACK
Programul de test şi descrierea VHDL ale acestui bloc sunt prezentate mai jos:
test_STACK.vhd
library IEEE, STD ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.std_logic_arith.all ;
use work.packageCY7C910.all ;

entity test_STACK is end ;

architecture test of test_STACK is

signal CK : std_logic := '0' ;


signal nFULL : std_logic ;
signal CNTL : std_logic_vector (1 downto 0) := "00" ;
signal CNTL_v : STACK_type ; -- pentru vizualizare
signal DATAIN, DATAIN_pre : std_logic_vector (address_bus_width - 1 downto 0) ;
signal DATAOUT : std_logic_vector (address_bus_width - 1 downto 0) ;
signal test_OK : BOOLEAN := TRUE ;
constant CK_HPER : time := 5 ns ;
constant DELAY : time := 3 ns ;
subtype vec12 is std_logic_vector (11 downto 0) ;
type mem20 is array (19 downto 0) of vec12 ;
signal MEMORIE : mem20 ;
signal DATAOUT_pre : std_logic_vector (address_bus_width - 1 downto 0) ;
signal nFULL_PRE : std_logic ;
signal DATAIN_v, DATAOUT_v : integer ; -- pentru vizualizare

component STACK
port( CK : in std_logic ;
DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
CNTL : in std_logic_vector (1 downto 0) ;
nFULL : out std_logic ;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

begin
DUT : STACK port map (CK, DATAIN, CNTL, nFULL, DATAOUT) ;

process (CK)
begin
MEMORIE (0) <= "111000111000" ;
if (CK'event) then
for k in 1 to 19 loop
MEMORIE (k) <= (MEMORIE (k-1) - 57) xor
(shl (MEMORIE (k-1) , "11") ) after 1 ns ;
end loop ;
end if ;
end process ;
CK <= not CK after CK_HPER ;
CNTL <= Clear_s, Push_s after 4*CK_HPER, Hold_s after 44*CK_HPER, Pop_s after 48*CK_HPER ;
process
variable n : integer := 0 ;

35
begin
wait until (CK'event and CK = '0') ;
DATAIN_pre <= MEMORIE (n) ;
if (n < 19) then
n := n + 1 ;
else
n := n ;
end if ;
end process ;
DATAIN <= DATAIN_pre after 2*CK_HPER ;

process
variable n : integer := 0 ;
variable EMPTY : bit ;
begin
wait until (CK'event and CK = '1') ;
wait for DELAY ;
case CNTL is
when Clear_s =>
EMPTY := '1' ;
if (DATAOUT = zero12 and nFULL = '1' ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " Eroare la Clear"
severity Warning ;
end if ;
when Push_s =>
case EMPTY is
when '1' =>
EMPTY := '0' ;
n := n ;
when others =>
if (n = 16) then
n := n ;
else
n := n + 1 ;
end if ;
end case ;
if( (DATAOUT /= DATAIN) or (n = 16 and nFULL /= '0')) then
test_OK <= FALSE ;
report " EROARE la PUSH"
severity Warning ;
else
test_OK <= TRUE ;
end if ;
when Pop_s =>
if (n = 16) then
if (DATAOUT = MEMORIE (15) and nFULL = '1') then
n := n - 2 ;
test_OK <= TRUE ;
else
n := n - 1 ;
test_OK <= FALSE ;
report " Eroare la Pop "
severity Warning ;
end if ;
else
if (DATAOUT = MEMORIE (n) and nFULL = '1') then
if (n = 0) then
n := n ;
EMPTY := '1' ;
else
n := n - 1 ;
end if ;
test_OK <= TRUE ;
else
if (n = 0) then
n := n ;
EMPTY := '1' ;
else
n := n - 1 ;
end if ;
test_OK <= FALSE ;
report " Eroare la Pop "
severity Warning ;
end if ;
end if ;
36
when others => -- Hold
if (DATAOUT = DATAOUT_pre and nFULL = nFULL_pre) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " Eroare la Hold"
severity Warning ;
end if ;
end case ;
end process ;

process -- se memoreaza starea anterioara a iesirii in DATAOUT_pre si nFULL_pre


begin
wait until (CK'event and CK = '0') ;
DATAOUT_pre <= DATAOUT ;
nFULL_pre <= nFULL ;
end process ;

DATAIN_v <= conv_integer (DATAIN) ;


DATAOUT_v <= conv_integer (DATAOUT) ;
process (CNTL)
begin
if (CNTL'event) then
case CNTL is
when Clear_s => CNTL_v <= Clear_v ;
when Hold_s => CNTL_v <= Hold_v ;
when Push_s => CNTL_v <= Push_v ;
when Pop_s => CNTL_v <= Pop_v ;
when others => CNTL_v <= XXX ;
end case ;
end if ;
end process ;
end test ;

STACK.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use IEEE.std_logic_unsigned.all ;
use work.NUMERIC_STD.all ;
use work.packageCY7C910.all ;
entity STACK is
port( CK : in std_logic ;
DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
CNTL : in std_logic_vector (1 downto 0) ;
nFULL : out std_logic ;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end STACK ;

architecture RTL of STACK is


signal ram : mem ; -- registrii stivei
signal S_EMPTY : std_logic ;
signal COUNT : std_logic_vector (4 downto 0) ;

begin
process (CK)
begin
if (CK'event and CK = '1') then
case CNTL is
when Clear_s =>
COUNT <= "00000" ;
ram(0) <= zero12 ;
S_EMPTY <= '1' ;
nFULL <= '1' ;
DATAOUT <= zero12 ;
when Push_s =>
if (COUNT = "01111" ) then
nFULL <= '0' ;
S_EMPTY <= '0' ;
ram(TO_INTEGER(UNSIGNED(COUNT + 1)))<=DATAIN;
COUNT <= COUNT + 1 ;
DATAOUT <= DATAIN ;
else
if (S_EMPTY = '1' or COUNT = "10000") then
ram(TO_INTEGER(UNSIGNED(COUNT)))<=DATAIN;
S_EMPTY <= '0' ;
DATAOUT <= DATAIN ;
else

37
ram(TO_INTEGER(UNSIGNED(COUNT + 1)))<=DATAIN;
COUNT <= COUNT + 1 ;
DATAOUT <= DATAIN ;
end if ;
end if ;
when Pop_s =>
if (COUNT = "00000") then
DATAOUT <=ram(TO_INTEGER(UNSIGNED(COUNT))) ;
nFULL <= '1' ;
S_EMPTY <= '1' ;
else
DATAOUT<=ram(TO_INTEGER(UNSIGNED(COUNT)+ 31));
COUNT <= COUNT + 31 ; -- <=> COUNT <= COUNT - 1
nFULL <= '1' ;
end if ;
when others => -- Hold_s
DATAOUT <= ram(TO_INTEGER(UNSIGNED(COUNT))) ;
end case ;
end if ;
end process ;
end RTL ;

Deşi forma finală a descrierii VHDL pentru acest bloc este destul de simplă, trebuie să spun că pentru a
ajunge la această formă am rescris codul de mai mult de zece ori pe parcursul câtorva zile.
Pentru implementarea regiştrilor stivei am folosit semnalul ram, pe care l-am declarat de tip mem, tip
descris în packageCY7C910.vhd. Întrucât în cazul stivei memoria este desul de mică (17 x 12 = 208 biţi ~
26 octeţi) , este ermisă descrierea memoriei sub forma unei matrici. Pentru memorii de dimensiuni mai mari,
această metodă este total neindicată, în aceste cazuri utilizându-se compilatoare de memorie. Chiar şi în
cazul acestei memorii de dimensiuni reduse, aria ocupată de aceasta reprezintă aproximativ 85% din aria
totală a circuitului.
Semnalul COUNT joacă rolul STACK_POINTER-ului, indicând locaţia din vârful stivei. Întrucât stiva are
17 regiştri, semnalul COUNT a fost definit ca vector std_logic de dimensiune 5. (2^4 < 17 < 2^5) .
Am introdus un semnal intern, S_EMPTY, care semnalează dacă stiva este goală. Necesitatea acestui
semnal rezultă din următoarea situaţie :
- presupunem că, la un moment dat, COUNT = 1, ram(1) = N1, ram(0) = N0 deci DATAOUT = N1 ;
- se execută o instrucţiune Pop_s => COUNT = 0, ram(0) = N0, DATAOUT = N0 ;
- din acest moment considerăm următoarele 2 situaţii :
1. se execută Push_s N => COUNT = 1, ram(1) = N, ram(0) = N0, DATAOUT = N ;
2. se execută Pop_s urmat de Push_s N ;
- după Pop_s => COUNT = 0, ram(0) = N0, DATAOUT = N0, deci practic nu se modifică nimic ;
- deci succesiunea POP_s, Push_s N ar avea acelaşi efect cu înstrucţiunea Push_s N de la situaţia 1. De fapt,
se doreşte ca în urma situaţiei 2 să rezulte COUNT = 0, ram(0) = N, DATAOUT = N.
Pentru aceasta, avem nevoie de un flag suplimentar, S_EMPTY, S_EMPTY devine activ atunci când
COUNT = 0 şi se execută o instrucţiune Pop_s. S_EMPTY este dezactivat atunci când COUNT = 0,
S_EMPTY = 1 şi se execută o instrucţiune Push_s.
În această descriere am folosit funcţia TO_INTEGER() din package-ul std_logic_unsigned, funcţie
care realizează conversia din vector std_logic în întreg.
Dintre toate blocurile circuitului CY7C910, stiva mi-a creat cele mai multe probleme. Primele
probleme au apărut chiar de la simularea presinteză. Iniţial, pentru instrucţiunea Push_s de exemplu, codul
arăta cam aşa :
if (CK’event and CK = ‘1’) then
case CNTL is
..........................................
when Push_s =>
..................................
COUNT <= COUNT + 1 ;
ram(TO_INTEGER (UNSIGNED (COUNT) ) ) <= DATAIN ;
DATAOUT <= ram(TO_INTEGER (UNSIGNED (COUNT) ) ) ;
...................................................
38
O asemenea descriere ar da rezultatele scontate într-un limbaj de programare precum C –ul. În cazul VHDL
situaţia este cu totul alta. Astfel, semnalul COUNT este incrementat corect, însă în instrucţiunea
ram(TO_INTEGER (UNSIGNED (COUNT) ) ) <= DATAIN ; semnalul COUNT nu are valoarea
incrementată (obţinută în urma executării instrucţiunii anterioare) , ci valoarea anterioară frontului pozitiv al
semnalului de ceas.
Ca urmare, am modificat descrierea VHDL astfel :
.............................................................
when Push_s =>
..........................................
ram(TO_INTEGER (UNSIGNED (COUNT + 1) ) ) <= DATAIN ;
COUNT <= COUNT + 1 ;
DATAOUT <= DATAIN ;
.........................................................................
when Pop_s =>
....................................................
DATAOUT <= ram(TO_INTEGER (UNSIGNED (COUNT - 1) ) ) ;
COUNT <= COUNT – 1 ;
.............................................................................
Această descriere a dat rezultatele aşteptate la simularea presinteză, însă au apărut probleme la simularea
postsinteză. În cazul instrucţiunilor Push_s, circuitul funcţiona corect, însă în cazul instrucţiunilor Pop_s
execuţia acestora era întârziată cu o perioadă de ceas. Acest fapt mi s-a părut ciudat, mai ales că, după
părerea mea, execuţia instrucţiunii Pop_s este mult mai simplă decât execuţia instrucţiunii Push_s, întrucât
data care trebuie scoasă la ieşirile DATAOUT se află deja în unul din regiştrii stivei.
După mai multe modificări ale codului VHDL care nu au eliminat această problemă, mi-am dat seama că
problema ar putea fi cauzată tocmai de folosirea operaţiei de scădere în cazul instrucţiunii Pop_s. Prin
urmare, am încercat să elimin operaţia de scădere din codul VHDL, ceea ce am reuşit prin înlocuirea
COUNT – 1 cu COUNT + 31 (31 = 11111B) În urma acestei modificări simulările presinteză şi postsinteză
au arătat o funcţionare corectă a circuitului.

STACK – (RTL) STACK – (RTL) – vedere parţială

39
MPC (MicroProgram Counter)
Programul de testare şi descrierea VHDL pentru acest bloc sunt prezentate în continuare :
test_MPC.vhd
library IEEE, STD ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.std_logic_arith.all ;
use work.packageCY7C910.all ;
entity test_MPC is end ;
architecture test of test_MPC is
signal CK, CI : std_logic := '0' ;
40
signal MPC_CNTL : std_logic ;
signal MPC_CNTL_v : MPC_type ; -- pentru vizualizare
signal DATAIN : std_logic_vector (address_bus_width - 1 downto 0) := "111000111000" ;
signal DATAOUT : std_logic_vector ( address_bus_width - 1 downto 0) ;
constant CK_HPER : time := 5 ns ; -- semiperioada semnalului de ceas
constant DELAY : time := 3 ns ;
signal test_OK : boolean := TRUE ;
signal DATAIN_v, DATAOUT_v : integer ; -- pentru vizualizare
component MPC
port (CK, CI : in std_logic ;
DATAIN : in std_logic_vector ( address_bus_width - 1 downto 0) ;
MPC_CNTL : in std_logic ;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

begin
DUT : MPC port map (CK, CI, DATAIN, MPC_CNTL, DATAOUT) ;
CLOCK : CK <= not CK after CK_HPER ;
process -- generare pseudo-aleatoare a DATAIN
begin
wait until (CK’event and CK = ‘0’) ;
DATAIN_gen : DATAIN <= (DATAIN - 57) xor (shl (DATAIN, "11") ) ;
end process ;
CI <= DATAIN(5) ; -- generare pseudo aleatoare a semnalului CARRY
MPC_CNTL <= Clear, Count after 6*CK_HPER, Clear after 12*CK_HPER, Count after 16*CK_HPER ;
DATAIN_v <= conv_integer (DATAIN) ;
DATAOUT_v <= conv_integer (DATAOUT) ;
process
variable DATAOUT_var : std_logic_vector (address_bus_width - 1 downto 0);
begin
wait until CK = '1' ;
DATAOUT_var := DATAIN ;
wait for DELAY ;
case MPC_CNTL is
when Clear =>
if (DATAOUT = zero12) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "Eroare la Clear"
severity Warning ;
end if ;

when others => -- Count


case CI is
when '1' =>
if (DATAOUT = DATAOUT_var + 1) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "Eroare la numarare cu CI = 1"
severity Warning ;
end if ;
when others =>
if (DATAOUT = DATAOUT_var) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "Eroare la numarare cu CI = 0"
severity Warning ;
end if ;
end case ;
end case ;
end process ;

process (MPC_CNTL)
begin
if (MPC_CNTL'event) then
case MPC_CNTL is
when Clear => MPC_CNTL_v <= Clear_v ;
when Count => MPC_CNTL_v <= Count_v ;
when others => MPC_CNTL_v <= XXX ;
end case ;
end if ;
end process ;
end test ;

41
MPC.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.packageCY7C910.all ;
entity MPC is
port (CK, CI : in std_logic ;
DATAIN : in std_logic_vector ( address_bus_width - 1 downto 0) ;
MPC_CNTL : in std_logic ;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end MPC ;
architecture RTL of MPC is
begin
process (CK)
begin
if (CK'event and CK = '1') then
if (MPC_CNTL = Clear) then
DATAOUT <= zero12 ;
else
DATAOUT <= DATAIN + CI ;
end if ;
end if ;
end process ;
end RTL ;

Se poate observa cu uşurinţă că în cazul acestui bloc programul de test este mult mai lung decât
descrierea propriuzisă. În plus, realizarea unui program de test implică găsirea unei soluţii optime prin care,
cu un număr suficient de mic de vectori de test, circuitul să poată fi adus în toate situaţiile de interes. După
realizarea descrierilor VHDL şi a programelor de test pentru circuitele CY7C910 şi CY7C901, pot să spun
că timpul consumat pentru realizarea programelor de test a fost de 5-6 ori mai mare decât pentru realizarea
descrierilor.

MPC – (RTL)

42
interfaţa_sursă
Am introdus acest bloc pentru uşurarea scrierii codului VHDL pentru blocul Instruction Decoder. Acest
bloc are o intrare pe 2 biţi care provine de la Instruction Decoder şi, în funcţie de valorile de pe intrare,
activează (pune pe nivel LOW) un singur semanal din cele 3 semnale de ieşire (nPL, nVECT, nMAP) ,
celelalte două fiind dezactivate. Întrucât acest bloc este foarte simplu, voi include aici doar descrierea
VHDL, programul de test putând fi găsit pe CD-ul anexat la proiect.
interfata_sursa.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity interfata_sursa is
port (DATAIN : in std_logic_vector (1 downto 0) ;
nPL, nMAP, nVECT : out std_logic) ;
end interfata_sursa ;
architecture RTL of interfata_sursa is
begin
process (DATAIN)
begin
case DATAIN is
when PL =>
nPL <= '0' ;
nMAP <= '1' ;
nVECT <= '1' ;
when Mapp =>
nPL <= '1' ;
nMAP <= '0' ;
nVECT <= '1' ;
when others => -- Vect
nPL <= '1' ;
nMAP <= '1' ;
nVECT <= '0' ;
end case ;
end process ;
end RTL ;

interfata_sursa – (RTL)
43
Blocurile MULTIPLEXER, ZERO_DETECTOR şi TS_BUFFER sunt simple şi nu ridică probleme
deosebite. Prin urmare, voi prezenta doar descrierile VHDL corespunzătoare acestor blocuri, programele de
test putând fi găsite pe CD-ul anexat proiectului.
MULTIPLEXER.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity MULTIPLEXER is
port (D, R, F, MPC : in std_logic_vector (address_bus_width - 1 downto 0) ; MUX_SEL : in
std_logic_vector (2 downto 0) ;
MUXOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end MULTIPLEXER ;
architecture RTL of MULTIPLEXER is
begin
process (D, R, F, MPC, MUX_SEL)
begin
case MUX_SEL is
when Dmux => MUXOUT <= D ;
when Rmux => MUXOUT <= R ;
when Fmux => MUXOUT <= F ;
when ZEROmux => MUXOUT <= zero12 ;
when others => MUXOUT <= MPC ;
end case ;
end process ;
end RTL ;

ZERO_DETECTOR.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity ZERO_DETECTOR is
port (DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
DATAOUT : out std_logic) ;
end ZERO_DETECTOR ;
architecture RTL of ZERO_DETECTOR is
begin
process (DATAIN)
begin
if (DATAIN = zero12) then
DATAOUT <= '1' ;
else
DATAOUT <= '0' ;
end if ;
end process ;
end RTL ;

TS_BUFFER.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity TS_BUFFER is
port (DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
nOE : in std_logic ;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end TS_BUFFER ;
architecture RTL of TS_BUFFER is
begin
process (nOE, DATAIN)
begin
if (nOE = '0') then
DATAOUT <= DATAIN ;
else
DATAOUT <= "ZZZZZZZZZZZZ" ;
end if ;
end process ;
end RTL ;

ZERO_DETECTOR – (RTL)
44
MULTIPLEXER – (RTL) TS_BUFFER – (RTL)

MULTIPLEXER – forme de undă

CY7C910
Blocurile funcţionale descrise anterior trebuie asamblate astfel încât împreună să aibă funcţionalitatea
circuitului CY7C910. Codul VHDL care ralizează această asamblare este prezentat în continuare :
CY7C910.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity CY7C910 is
port (
D : in std_logic_vector (address_bus_width - 1 downto 0) ;
nRLD : in std_logic ;
I : in std_logic_vector (3 downto 0) ;
nCC :in std_logic ;
nCCEN : in std_logic ;
CP : in std_logic ;
CI : in std_logic ;
nOE : in std_logic ;
Y : out std_logic_vector (address_bus_width - 1 downto 0) ;
nFULL : out std_logic ;
nPL : out std_logic ;
nMAP : out std_logic ;
nVECT : out std_logic) ;

end CY7C910 ;
architecture structural of CY7C910 is
signal Y_BUS, MPC_BUS, F_BUS, R_BUS : std_logic_vector(address_bus_width - 1 downto 0);
signal STACK_CNTL : std_logic_vector (1 downto 0) ;

45
signal MPC_CNTL : std_logic ;
signal MUX_CNTL : std_logic_vector (2 downto 0) ;
signal RC_CNTL : std_logic_vector (1 downto 0) ;
signal ZERO_DET : std_logic ;
signal SURSA_DET : std_logic_vector (1 downto 0) ;

-- declararea blocurilor componente


component INSTRUCTION_DECODER
port (I : in std_logic_vector(3 downto 0) ; nCC, nCCEN, ZERO_DET : in std_logic;
MUX_SEL : out std_logic_vector(2 downto 0) ; STACK_CNTL : out std_logic_vector(1 downto 0);
REG_CNTR_CNTL : out std_logic_vector (1 downto 0) ; MPC_CNTL : out std_logic ;
ENABLE_CNTL : out std_logic_vector (1 downto 0) ) ;
end component ;

component MPC
port (CK, CI : in std_logic ; DATAIN : in std_logic_vector ( address_bus_width - 1 downto 0) ;
MPC_CNTL : in std_logic ; DATAOUT : out std_logic_vector(address_bus_width - 1 downto 0) );
end component ;

component MULTIPLEXER
port (D, R, F, MPC : in std_logic_vector (address_bus_width - 1 downto 0) ;
MUX_SEL : in std_logic_vector (2 downto 0) ;
MUXOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

component REGISTER_COUNTER
port (CK, nRLD : in std_logic ; CNTL : in std_logic_vector (1 downto 0) ;
DATAIN : in std_logic_vector (address_bus_width - 1 downto 0) ;
DATAOUT : buffer std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

component STACK
port(CK : in std_logic ; DATAIN : in std_logic_vector(address_bus_width - 1 downto 0);
CNTL : in std_logic_vector (1 downto 0) ;nFULL : out std_logic ;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

component TS_BUFFER
port (DATAIN : in std_logic_vector(address_bus_width - 1 downto 0); nOE : in std_logic;
DATAOUT : out std_logic_vector (address_bus_width - 1 downto 0) ) ;
end component ;

component interfata_sursa
port(DATAIN : in std_logic_vector(1 downto 0) ; nPL, nMAP, nVECT : out std_logic); end component ;

component ZERO_DETECTOR
port(DATAIN : in std_logic_vector(address_bus_width - 1 downto 0) ; DATAOUT : out std_logic);
end component ;

begin
-- Instanţierea blocurilor componente

INSTR_DEC : INSTRUCTION_DECODER port map (I, nCC, nCCEN, ZERO_DET, MUX_CNTL, STACK_CNTL, RC_CNTL,
MPC_CNTL, SURSA_DET) ;
MPC_i : MPC port map (CP, CI, Y_BUS, MPC_CNTL, MPC_BUS) ;
MUX_i : MULTIPLEXER port map (D, R_BUS, F_BUS, MPC_BUS, MUX_CNTL, Y_BUS) ;
RC_i : REGISTER_COUNTER port map (CP, nRLD, RC_CNTL, D, R_BUS) ;
ZERO_i : ZERO_DETECTOR port map (R_BUS, ZERO_DET) ;
STACK_i : STACK port map (CP, MPC_BUS, STACK_CNTL, nFULL, F_BUS) ;
TSB_i : TS_BUFFER port map (Y_BUS, nOE, Y) ;
INTF_SURSA : interfata_sursa port map (SURSA_DET, nPL, nMAP, NVECT) ;

end structural ;

46
Sinteza circuitului CY7C910
După ce am realizat descrierea VHDL pentru circuitul CY7C910 şi, în urma simulărilor, m-am
convins de corectitudinea acesteia, trebuie realizată sinteza acestei descrieri VHDL.
Trebuie să precizez că în această lucrare nu mi-am propus să aprofundez metodele de optimizare a
procesului de sinteză, întrucât sinteza este un domeniu cu totul diferit de scrierea de cod VHDL pentru
sinteză. Învăţarea temeinică a tehnicilor de sinteză necesită o perioadă de timp îndelungată, iar, în cadrul
firmelor din domeniu, scrierea codului VHDL şi sinteza acestui cod sunt activităţi separate, realizate de
persoane diferite.
Ceea ce am dorit eu, prin sinteza codului VHDL, a fost să mă conving că acest cod VHDL este într-
adevăr sintetizabil şi că circuitul generat de programul de sinteză se comportă conform aşteptărilor.
Sinteza circuitului CY7C910 am realizat-o cu programul Design Compiler din cadrul pachetului de
programe Synopsys.
Pentru realizarea sintezei este nevoie, în primul rând, de fişiere tehnologice. Sinteza circuitului
CY7C910 am realizat-o într-o tehnologie de 0.35 µm, fişierele tehnologice folosite fiin :
- “tcb773pwc.db” – biblioteca de celule de CORE (standard cells) ;
- “tcb773p.sdb” – biblioteca de simboluri pentru componentele din biblioteca de celule standard ;
- “tcb773p.v” – fişier Verilog care conţine descrierile Verilog ale componentelor din biblioteca de celule
standard ; acest fişier nu este folosit la sinteză, ci la simularea postsinteză ;
Apoi, în fişierul “.synopsys_dc.setup” de configurare a programului de sinteză trebuie indicate căile
către fişierele tehnologice, precum şi alte reguli care trebuie respectate la sinteză.
.synopsys_dc.setup
/* Setari pentru tehnologia TSMC035 - tcb773p - Worst Case */
/* tcb773pwc.db este biblioteca de celule de CORE (standard-cells) */
designer = "Ieremie Ionut"
company = "ETC"

search_path = { ., synopsys_root + /libraries/syn}


search_path = {scripts} + search_path

hdlin_translate_off_skip_text = TRUE

link_library = {"*" tcb773pwc.db}


target_library = {tcb773pwc.db}
symbol_library = {tcb773p.sdb}
default_schematic_options = "-size infinite"
define_design_lib work -path work

/* CACHE directory settings */


cache_write = ./cache
cache_read = ./cache
cache_write_info = "false"
cache_read_info = "false"

/* Site Specific Variables */


synthetic_library = {C:/Synopsys/libraries/syn/standard.sldb}
command_log_file = "./command.log"
view_command_log_file = "./view_command.log"
plot_command = "lpr -Plw"
text_print_command = "lpr -Plw"

/* enable Text Viewer feature */


hdlin_source_to_gates_mode = "off"
hdlin_report_inferred_modules = "verbose"

/* Synopsys to Compass EDIF interface */


edifin_ground_name = "VSS"
edifin_ground_net_name = "VSS"
edifin_ground_net_property_name = "global"
edifin_ground_net_property_value = "VSS"
edifin_ground_pin_name = "VSS"
edifin_ground_port_name = "VSS"
edifin_netlist_only = "true"
edifin_power_name = "VDD"
edifin_power_net_name = "VDD"
edifin_power_net_property_name = "global"

47
edifin_power_net_property_value = "VDD"
edifin_power_pin_name = "VDD"
edifin_power_port_name = "VDD"
edifin_power_and_ground_representation = "net"
edifout_ground_name = "VSS"
edifout_ground_net_name = "VSS"
edifout_ground_net_property_name = "global"
edifout_ground_net_property_value = "VSS"
edifout_ground_pin_name = "VSS"
edifout_ground_port_name = "VSS"
edifout_netlist_only = "true"
edifout_no_array = "true"
edifout_power_name = "VDD"
edifout_power_net_name = "VDD"
edifout_power_net_property_name = "global"
edifout_power_net_property_value = "VDD"
edifout_power_pin_name = "VDD"
edifout_power_port_name = "VDD"
edifout_power_and_ground_representation = "net"
write_name_nets_same_as_ports = "true"
compile_fix_multiple_port_nets = "true"
verilogout_no_tri = "true"

include TSMC_naming_rule.script

/* change_names -rules asic_core_rules -verbose -hierarchy */

Apoi, pentru realizarea sintezei, se realizează un script, “compile.scr”, în care sunt grupate
directivele de sinteză.
compile.scr
design = CY7C910

analyze -library work -format vhdl sources/packageCY7C910.vhd


analyze -library work -format vhdl sources/INSTRUCTION_DECODER.vhd
analyze -library work -format vhdl sources/interfata_sursa.vhd
analyze -library work -format vhdl sources/MPC.vhd
analyze -library work -format vhdl sources/MULTIPLEXER.vhd
analyze -library work -format vhdl sources/REGISTER_COUNTER.vhd
analyze -library work -format vhdl sources/Stack.vhd
analyze -library work -format vhdl sources/TS_BUFFER.vhd
analyze -library work -format vhdl sources/ZERO_DETECTOR.vhd
analyze -library work -format vhdl sources/ + design + ".vhd"
elaborate -library work design

set_wire_load_model -library tcb773pwc -name TSMC16K_Conservative


set_wire_load_mode enclosed

create_clock -name CLK -period 20 -waveform { 0 5 } { CP }

set_output_delay 12 -clock CLK all_outputs()


set_dont_touch_network { CLK }
group_path -name fromI -from { I }
group_path -name fromnCC -from { nCC }
group_path -name fromnCCEN -from { nCCEN }
group_path -name fromCI -from { CI }

compile -map_effort high


create_schematic -all

report -area > "reports/" + design + "_area_report.txt"


report -timing > "reports/" + design + "_timing_report.txt"

check_design
check_timing

write -f db -hier -o "db/" + design + "_mapped.db"


write_sdf "netlist/" + design + "_mapped.sdf"
write -format vhdl -hierarchy -output "netlist/" + design + "_mapped.vhd"
write -format verilog -hierarchy -output "netlist/" + design + "_mapped.v"

În urma sintezei sunt generate următoarele fişiere :


- “CY7C910_mapped.vhd” – descrierea VHDL a circuitului implementat cu celule standard generat de
programul de sinteză ;

48
- “CY7C910_mapped.v” - descrierea Verilog a circuitului implementat cu celule standard generat de
programul de sinteză ;
- “CY7C901_mapped.sdf” - conţine informaţiile despre întârzierile pe căile de semnal interne circuitului
- “CY7C910_timing_report.txt” – fişier text în care se raportează modul în care au fost respectae
constrângerile de timing ;
- “CY7C910_area_report.txt” – fişier text în care se raporteză modul în care au fost respectate
constrângerile de arie ;
- “CY7C910_mapped.db” – fişier în format Synopsys ;
Dintre aceste fişiere, voi reda în continuare doar fişierele de raport de timing şi arie, aceste fiind
singurele atât scurte, cât şi relevante.
CY7C910_timing_report.txt
****************************************
Report : timing
-path full
-delay max
-max_paths 1
Design : CY7C910
Version: 2000.05
Date : Tue May 13 10:49:02 2003
****************************************

Operating Conditions: WCCOM Library: tcb773pwc


Wire Load Model Mode: enclosed

Startpoint: RC_i/DATAOUT_reg[3]
(rising edge-triggered flip-flop clocked by CLK)
Endpoint: Y[11] (output port clocked by CLK)
Path Group: CLK
Path Type: max

Des/Clust/Port Wire Load Model Library


------------------------------------------------
CY7C910 TSMC16K_Conservative tcb773pwc
ZERO_DETECTOR TSMC16K_Conservative tcb773pwc
INSTRUCTION_DECODER TSMC8K_Conservative tcb773pwc
TS_BUFFER TSMC8K_Conservative tcb773pwc
MULTIPLEXER TSMC8K_Conservative tcb773pwc

Point Incr Path


--------------------------------------------------------------------------
clock CLK (rise edge) 0.00 0.00
clock network delay (ideal) 0.00 0.00
RC_i/DATAOUT_reg[3]/CP (DFCNS1Q) 0.00 0.00 r
RC_i/DATAOUT_reg[3]/Q (DFCNS1Q) 1.11 1.11 r
RC_i/DATAOUT[3] (REGISTER_COUNTER) 0.00 1.11 r
ZERO_i/DATAIN[3] (ZERO_DETECTOR) 0.00 1.11 r
ZERO_i/U9/Z (OR3D1) 0.78 1.90 r
ZERO_i/U11/ZN (NR8D3) 1.34 3.24 f
ZERO_i/DATAOUT (ZERO_DETECTOR) 0.00 3.24 f
INSTR_DEC/ZERO_DET (INSTRUCTION_DECODER) 0.00 3.24 f
INSTR_DEC/U100/ZN (ND2D1) 0.23 3.47 r
INSTR_DEC/U103/ZN (NR2D1) 0.21 3.68 f
INSTR_DEC/U104/Z (MUX2D2) 0.59 4.27 f
INSTR_DEC/U115/ZN (OAI21D0) 0.33 4.60 r
INSTR_DEC/U87/ZN (IND2D1) 0.46 5.07 f
INSTR_DEC/MUX_SEL[1] (INSTRUCTION_DECODER) 0.00 5.07 f
MUX_i/MUX_SEL[1] (MULTIPLEXER) 0.00 5.07 f
MUX_i/U9/Z (MUX2D1) 0.64 5.71 f
MUX_i/U51/ZN (INV1) 0.52 6.23 r
MUX_i/U48/ZN (MOAI22D0) 0.52 6.75 r
MUX_i/U35/ZN (IOA221D0D) 0.77 7.52 r
MUX_i/MUXOUT[11] (MULTIPLEXER) 0.00 7.52 r
TSB_i/DATAIN[11] (TS_BUFFER) 0.00 7.52 r
TSB_i/U14/ZN (INV1) 0.23 7.75 f
TSB_i/DATAOUT_tri[11]/ZN (INVTN1) 0.22 7.97 r
TSB_i/DATAOUT[11] (TS_BUFFER) 0.00 7.97 r
Y[11] (out) 0.00 7.97 r
data arrival time 7.97

clock CLK (rise edge) 20.00 20.00


clock network delay (ideal) 0.00 20.00
output external delay -12.00 8.00
data required time 8.00
--------------------------------------------------------------------------
data required time 8.00
data arrival time -7.97
--------------------------------------------------------------------------
slack (MET) 0.03

49
Startpoint: CI (input port)
Endpoint: MPC_i/DATAOUT_reg[11]
(rising edge-triggered flip-flop clocked by CLK)
Path Group: fromCI
Path Type: max

Des/Clust/Port Wire Load Model Library


------------------------------------------------
CY7C910 TSMC16K_Conservative tcb773pwc
MPC TSMC8K_Conservative tcb773pwc

Point Incr Path


--------------------------------------------------------------------------
clock (input port clock) (rise edge) 0.00 0.00
input external delay 0.00 0.00 r
CI (in) 0.00 0.00 r
MPC_i/CI (MPC) 0.00 0.00 r
MPC_i/add_17/plus/plus/U1_0/CO (FA1D1) 0.95 0.95 r
MPC_i/add_17/plus/plus/U1_1/CO (FA1D1) 0.60 1.54 r
MPC_i/add_17/plus/plus/U1_2/CO (FA1D1) 0.59 2.13 r
MPC_i/add_17/plus/plus/U1_3/CO (FA1D1) 0.59 2.73 r
MPC_i/add_17/plus/plus/U1_4/CO (FA1D1) 0.59 3.32 r
MPC_i/add_17/plus/plus/U1_5/CO (FA1D1) 0.59 3.92 r
MPC_i/add_17/plus/plus/U1_6/CO (FA1D1) 0.59 4.51 r
MPC_i/add_17/plus/plus/U1_7/CO (FA1D1) 0.59 5.11 r
MPC_i/add_17/plus/plus/U1_8/CO (FA1D1) 0.59 5.70 r
MPC_i/add_17/plus/plus/U1_9/CO (FA1D1) 0.59 6.29 r
MPC_i/add_17/plus/plus/U1_10/CO (FA1D1) 0.57 6.87 r
MPC_i/U27/Z (XOR2D1) 0.61 7.48 f
MPC_i/DATAOUT_reg[11]/EN (DFCNE2Q) 0.00 7.48 f
data arrival time 7.48

clock CLK (rise edge) 20.00 20.00


clock network delay (ideal) 0.00 20.00
MPC_i/DATAOUT_reg[11]/CP (DFCNE2Q) 0.00 20.00 r
library setup time -0.52 19.48
data required time 19.48
--------------------------------------------------------------------------
data required time 19.48
data arrival time -7.48
--------------------------------------------------------------------------
slack (MET) 12.00

Startpoint: I[0] (input port)


Endpoint: Y[11] (output port clocked by CLK)
Path Group: fromI
Path Type: max

Des/Clust/Port Wire Load Model Library


------------------------------------------------
CY7C910 TSMC16K_Conservative tcb773pwc
INSTRUCTION_DECODER TSMC8K_Conservative tcb773pwc
TS_BUFFER TSMC8K_Conservative tcb773pwc
MULTIPLEXER TSMC8K_Conservative tcb773pwc

Point Incr Path


--------------------------------------------------------------------------
clock (input port clock) (rise edge) 0.00 0.00
input external delay 0.00 0.00 r
I[0] (in) 0.00 0.00 r
INSTR_DEC/I[0] (INSTRUCTION_DECODER) 0.00 0.00 r
INSTR_DEC/U83/ZN (INV0) 0.48 0.48 f
INSTR_DEC/U109/ZN (OAI21D0) 0.42 0.90 r
INSTR_DEC/U95/ZN (IAO21D0A) 0.43 1.33 f
INSTR_DEC/U65/Z (MUX2D1) 0.68 2.01 f
INSTR_DEC/U86/ZN (OAI21D0) 0.44 2.45 r
INSTR_DEC/MUX_SEL[0] (INSTRUCTION_DECODER) 0.00 2.45 r
MUX_i/MUX_SEL[0] (MULTIPLEXER) 0.00 2.45 r
MUX_i/U11/ZN (INV0) 0.48 2.94 f
MUX_i/U9/Z (MUX2D1) 0.69 3.63 f
MUX_i/U51/ZN (INV1) 0.52 4.15 r
MUX_i/U48/ZN (MOAI22D0) 0.52 4.67 r
MUX_i/U35/ZN (IOA221D0D) 0.77 5.44 r
MUX_i/MUXOUT[11] (MULTIPLEXER) 0.00 5.44 r
TSB_i/DATAIN[11] (TS_BUFFER) 0.00 5.44 r
TSB_i/U14/ZN (INV1) 0.23 5.67 f
TSB_i/DATAOUT_tri[11]/ZN (INVTN1) 0.22 5.89 r
TSB_i/DATAOUT[11] (TS_BUFFER) 0.00 5.89 r
Y[11] (out) 0.00 5.89 r
data arrival time 5.89

clock CLK (rise edge) 20.00 20.00


clock network delay (ideal) 0.00 20.00
output external delay -12.00 8.00
data required time 8.00
--------------------------------------------------------------------------
data required time 8.00
data arrival time -5.89
50
--------------------------------------------------------------------------
slack (MET) 2.11

Startpoint: nCC (input port)


Endpoint: Y[11] (output port clocked by CLK)
Path Group: fromnCC
Path Type: max

Des/Clust/Port Wire Load Model Library


------------------------------------------------
CY7C910 TSMC16K_Conservative tcb773pwc
INSTRUCTION_DECODER TSMC8K_Conservative tcb773pwc
TS_BUFFER TSMC8K_Conservative tcb773pwc
MULTIPLEXER TSMC8K_Conservative tcb773pwc

Point Incr Path


--------------------------------------------------------------------------
clock (input port clock) (rise edge) 0.00 0.00
input external delay 0.00 0.00 f
nCC (in) 0.00 0.00 f
INSTR_DEC/nCC (INSTRUCTION_DECODER) 0.00 0.00 f
INSTR_DEC/U97/ZN (IND2D1) 0.36 0.36 r
INSTR_DEC/U71/ZN (ND2D0) 0.54 0.90 f
INSTR_DEC/U94/ZN (IAO21D0B) 0.77 1.66 f
INSTR_DEC/U88/ZN (OAI32D0) 0.84 2.50 r
INSTR_DEC/MUX_SEL[2] (INSTRUCTION_DECODER) 0.00 2.50 r
MUX_i/MUX_SEL[2] (MULTIPLEXER) 0.00 2.50 r
MUX_i/U10/ZN (INV0) 0.33 2.83 f
MUX_i/U9/Z (MUX2D1) 0.67 3.51 f
MUX_i/U51/ZN (INV1) 0.52 4.03 r
MUX_i/U48/ZN (MOAI22D0) 0.52 4.55 r
MUX_i/U35/ZN (IOA221D0D) 0.77 5.32 r
MUX_i/MUXOUT[11] (MULTIPLEXER) 0.00 5.32 r
TSB_i/DATAIN[11] (TS_BUFFER) 0.00 5.32 r
TSB_i/U14/ZN (INV1) 0.23 5.55 f
TSB_i/DATAOUT_tri[11]/ZN (INVTN1) 0.22 5.77 r
TSB_i/DATAOUT[11] (TS_BUFFER) 0.00 5.77 r
Y[11] (out) 0.00 5.77 r
data arrival time 5.77

clock CLK (rise edge) 20.00 20.00


clock network delay (ideal) 0.00 20.00
output external delay -12.00 8.00
data required time 8.00
--------------------------------------------------------------------------
data required time 8.00
data arrival time -5.77
--------------------------------------------------------------------------
slack (MET) 2.23

Startpoint: nCCEN (input port)


Endpoint: Y[11] (output port clocked by CLK)
Path Group: fromnCCEN
Path Type: max

Des/Clust/Port Wire Load Model Library


------------------------------------------------
CY7C910 TSMC16K_Conservative tcb773pwc
INSTRUCTION_DECODER TSMC8K_Conservative tcb773pwc
TS_BUFFER TSMC8K_Conservative tcb773pwc
MULTIPLEXER TSMC8K_Conservative tcb773pwc

Point Incr Path


--------------------------------------------------------------------------
clock (input port clock) (rise edge) 0.00 0.00
input external delay 0.00 0.00 r
nCCEN (in) 0.00 0.00 r
INSTR_DEC/nCCEN (INSTRUCTION_DECODER) 0.00 0.00 r
INSTR_DEC/U97/ZN (IND2D1) 0.57 0.57 r
INSTR_DEC/U71/ZN (ND2D0) 0.54 1.11 f
INSTR_DEC/U94/ZN (IAO21D0B) 0.77 1.88 f
INSTR_DEC/U88/ZN (OAI32D0) 0.84 2.71 r
INSTR_DEC/MUX_SEL[2] (INSTRUCTION_DECODER) 0.00 2.71 r
MUX_i/MUX_SEL[2] (MULTIPLEXER) 0.00 2.71 r
MUX_i/U10/ZN (INV0) 0.33 3.05 f
MUX_i/U9/Z (MUX2D1) 0.67 3.72 f
MUX_i/U51/ZN (INV1) 0.52 4.24 r
MUX_i/U48/ZN (MOAI22D0) 0.52 4.76 r
MUX_i/U35/ZN (IOA221D0D) 0.77 5.53 r
MUX_i/MUXOUT[11] (MULTIPLEXER) 0.00 5.53 r
TSB_i/DATAIN[11] (TS_BUFFER) 0.00 5.53 r
TSB_i/U14/ZN (INV1) 0.23 5.76 f
TSB_i/DATAOUT_tri[11]/ZN (INVTN1) 0.22 5.98 r
TSB_i/DATAOUT[11] (TS_BUFFER) 0.00 5.98 r
Y[11] (out) 0.00 5.98 r
data arrival time 5.98

51
clock CLK (rise edge) 20.00 20.00
clock network delay (ideal) 0.00 20.00
output external delay -12.00 8.00
data required time 8.00
--------------------------------------------------------------------------
data required time 8.00
data arrival time -5.98
--------------------------------------------------------------------------
slack (MET) 2.02

CY7C910_area_report.txt
report_area
Information: Updating design information... (UID-85)

****************************************
Report : area
Design : CY7C910
Version: 2000.05
Date : Tue May 13 10:49:02 2003
****************************************

Library(s) Used:

tcb773pwc (File: C:/Synopsys/libraries/syn/tcb773pwc.db)

Number of ports: 38
Number of nets: 97
Number of cells: 8
Number of references: 8

Combinational area: 91385.000000


Noncombinational area: 106802.500000
Net Interconnect area: undefined (Wire load has zero net area)

Total cell area: 198187.500000


Total area: undefined

Testarea circuitului CY7C910

Pentru testarea întregului circuit CY7C910, nu am realizat un program de test original, ci am folosit
programul de test pentru circuitul AM2910 (echivalent cu CY7C910) prezentat în [2]. Deşi acest testbench
nu realizează o testare funcţională completă a circuitului CY7C910, am decis să-l utilizez astfel încât, prin
compararea formelor de undă prezentate în [2] cu cele obţinute în urma simulării circuitului proiectat de
mine, să pot stabili, cu destulă siguranţă, dacă circuitul meu funcţionează corect. Trebuie să precizez aici că
formele de undă prezentate în [2] sunt obţinute în urma testării presinteză.
Testarea lui CY7C910 se va realiza cu un circuit de test, în locul unui program de test. Arhitectura
circuitului de test este prezentată în continuare :

CY7C910

ROM

PIPELINE

52
Ieşirile Y ale circuitului CY7C910 sunt folosite pentru a adresa o memorie ROM. Registrul pipeline are
rolul de a elimina stările tranzitorii de pe intrările lui CY7C910 (stări tranzitorii ce ar apărea în absenţa
registrului pipeline din cauza întărzierilor diferite pe căile combinaţionale între intrările lui CY7C910 şi
ieşirile Y ale acestuia) .
ROM-ul conţine un microprogram. Microprogramul următor a fost realizat pentru a verifica toate
instrucţiunile lui CY7C910 :
Program.txt
1 1100 e 001 -- locatia 0(hexa) ; nRLD = 1, CI = 1, nCCEN = 0, nCC = 0 ; I =
CONT(hexa) ; D = 001(hexa)
2 1100 4 002 -- 1 ; PUSH
3 0100 4 003 -- 2 ; PUSH
4 1100 4 004 -- 3 ; PUSH
5 1101 4 005 -- 4 ; PUSH
6 1100 4 006 -- 5 ; PUSH
7 1110 4 007 -- 6 ; PUSH
8 0100 4 008 -- 7 ; PUSH
9 1100 4 009 -- 8 ; PUSH
10 1111 4 00a -- 9 ; PUSH
11 1100 4 00b -- a ; PUSH
12 1100 4 00c -- b ; PUSH
13 1100 4 00d -- c ; PUSH
14 1100 4 00e -- d ; PUSH
15 1100 4 00f -- e ; PUSH
16 1100 4 010 -- f ; PUSH
17 1100 4 011 -- 10 ; PUSH
18 1100 4 012 -- 11 ; PUSH
19 1100 4 013 -- 12 ; PUSH
20 1110 d 014 -- 13 ; LOP(pop)
21 1100 d 015 -- 14 ; LOP(pop)
22 1100 d 016 -- 15 ; LOP(pop)
23 1100 d 017 -- 16 ; LOP(pop)
24 1110 d 018 -- 17 ; LOP(pop)
25 1100 d 019 -- 18 ; LOP(pop)
26 1110 d 01a -- 19 ; LOP(pop)
27 1100 d 01b -- 1a ; LOP(pop)
28 1111 d 01c -- 1b ; LOP(pop)
29 1100 d 01d -- 1c ; LOP(pop)
30 0100 d 01e -- 1d ; LOP(pop)
31 1111 d 01f -- 1e ; LOP(pop)
32 1110 d 020 -- 1f ; LOP(pop)
33 1100 d 021 -- 20 ; LOP(pop)
34 0111 d 022 -- 21 ; LOP(pop)
35 1110 d 023 -- 22 ; LOP(pop)
36 1100 d 024 -- 23 ; LOP(pop)
37 1100 d 025 -- 24 ; LOP(pop)
38 1100 e 026 -- 25 ; CONT
39 1100 e 027 -- 26 ; CONT
40 1100 0 035 -- 27 ; CJS la adresa 035(hexa)
41 1100 0 000 -- 28 ;de fapt nu conteaza ce se afla la adresele 028 - 034(hexa)
deoarece se realizeaza un salt peste aceste adrese
42 1100 0 000 -- 29 ;
43 1100 0 000 -- 2a ;
44 1100 0 000 -- 2b ;
45 1100 0 000 -- 2c ;
46 1100 0 000 -- 2d ;
47 1100 0 000 -- 2e ;
48 1100 0 000 -- 2f ;
49 1100 0 000 -- 30 ;
50 1100 0 000 -- 31 ;
51 1100 0 000 -- 32 ;
52 1100 0 000 -- 33 ;
53 1100 0 000 -- 34 ;
54 1100 2 038 -- 35 ; JMAP a adresa 38(hexa)
55 1100 0 000 -- 36 ; nu conteaza
56 1100 0 000 -- 37 ; nu conteaza
57 1101 3 0ff -- 38 ; CJP, no jump
58 1100 3 03c -- 39 ; CJP, salt la 3c
59 1100 0 000 -- 3a ; nu conteaza
60 1100 0 000 -- 3b ; nu conteaza
61 1100 1 040 -- 3c ; CJS la 40(hexa)
62 1100 0 000 -- 3d ; nu conteaza
63 1100 0 000 -- 3e ; nu conteaza
64 1100 0 000 -- 3f ; nu conteaza
65 1100 4 003 -- 40 ; PUSH, load counter 3
53
66 1100 e 040 -- 41 ; CONT
67 1100 8 041 -- 42 ; RFCT, repeat
68 1101 a 043 -- 43 ; Condition return, no return
69 1100 a 044 -- 44 ; return
70 1100 4 fff -- 45 ; load counter with fff
71 1100 d 046 -- 46 ; pop
72 1100 c 002 -- 47 ; LDCT, load counter and continue
73 1100 9 048 -- 48 ; RFCT, repeat this instruction
74 1101 6 000 -- 49 ; CJV, conditional jump, no jump
75 1100 6 04c -- 4a ; CJV, salt la 04c
76 1100 0 000 -- 4b ; nu conteaza
77 1100 c 04f -- 4c ; LDCT, load counter 4f
78 1101 7 000 -- 4d ; JRP, jump to counter address 4f
79 1100 0 000 -- 4e ; nu conteaza
80 1100 7 051 -- 4f ; JRP, jump to D
81 1100 0 000 -- 50 ; nu conteaza
82 1100 c 054 -- 51 ; LDCT 54
83 1101 5 000 -- 52 ; JSRP, jump to counter
84 1100 0 000 -- 53 ; nu conteaza
85 1100 5 056 -- 54 ; JSRP, jump to counter
86 1100 0 000 -- 55 ; nu conteaza
87 1100 4 003 -- 56 ; PUSH and load counter with 60
88 1100 e aaa -- 57 ; CONT
89 1101 f 05a -- 58 ; TWB, three way branch to 5a when done
90 1100 e bad -- 59 ; CONT
91 1100 e d0e -- 5a ; CONT
92 1100 e d0e -- 5b ; CONT
93 1100 e d0e -- 5c ; CONT
94 1000 e doe –- 5d ; CONT

Fiecare locaţie a memoriei ROM are 20 de biţi. Primii 4 biţi de la stânga reprezintă nRLD, CI, nCC,
nCCEN ; următorii 4 sunt pentru intrările de instrucţiuni I ; următorii 12 sunt pentru intrările D.
Liniile 2 – 19 testează instrucţiunea Push_s. Sunt 18 operaţii Push_s, astfel încât se poate testa
comportamentul circuitului la umplerea stivei.
Liniiile 20 – 37 testează operaţia Pop_s.
Explicaţii detaliate despre microprogram vor fi date când vor fi prezentate formele de undă obţinute
în urma simulării.
În continuare trebuie descrise blocurile ROM şi PIPELINE utilizate la testare.
ROM.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
use work.std_logic_arith.all ;
use IEEE.std_logic_textio.all ;
use STD.TEXTIO.all ;
entity ROM is
generic (SIZE : integer := 20 ; WORDS : integer := 94 ; ADSIZE : integer := 7 ; CODEFILE : string :=
"Program.txt") ;
port (A : in std_logic_vector (ADSIZE - 1 downto 0) ; DOUT : out std_logic_vector (SIZE - 1 downto
0) ) ;
end ROM ;
architecture BEH of ROM is
constant DELAYMIN : time := 0.01 ns ;
type memorie is array (255 downto 0) of std_logic_vector (SIZE - 1 downto 0) ;
signal mem_ROM : memorie ;
begin
process -- se încarcă ROM-ul cu datele din fişierul “Program.txt”
file my_file : text open read_mode is CODEFILE ;
variable INLINE : line ;
variable i : integer := 0 ;
variable N : integer ;
variable bits4, OPCODE : std_logic_vector (3 downto 0) ;
variable DATA : std_logic_vector (address_bus_width - 1 downto 0) ;
begin
while not endfile(my_file) loop
readline(my_file, INLINE ) ;
-- se Incarcă o linie din “Program.txt” în variabila INLINE de tip LINE
read (INLINE, N) ;
-- se încarcă în variabila N primul întreg din linia INLINE
read (INLINE, bits4) ;
-- se încarcă în variabila bits4 următorii 4 biţi din INLINE
hread (INLINE, OPCODE) ;
--se tratează următoarea secvenţă de caractere din INLINE ca număr
54
--hexazecimal şi se ribuie variabilei OPCODE
hread (INLINE, DATA) ;
--se tratează următoarea secvenţă de caractere din INLINE ca număr
--hexazecimal şi se ribuie variabilei DATA
mem_ROM (i) <= bits4 & OPCODE & DATA ;
--concatenarea celor 20 de biţi citiţi anterior şi înscrierea
--acestora într-o locaţie a memoriei ROM
i := i + 1 ;
wait for DELAYMIN ;
end loop ;
wait for 10 ns ;
wait ;
end process ;

process (A) -- se descrie funcţionarea ROM-ului


begin
DOUT <= mem_ROM (CONV_INTEGER (unsigned (A) ) ) ;
end process ;
end BEH ;

PIPELINE.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
entity pipeline is
port (CP, R : in std_logic ; I : in std_logic_vector (19 downto 0) ; Q : out std_logic_vector (19
downto 0) ) ;
end pipeline ;
architecture RTL of pipeline is
constant DELAY : time := 5 ns ;
begin
process
begin
wait until (CP'event and CP = '1') ;
case R is
when '1' =>
Q <= "00000000000000000000" after DELAY ;
when others =>
Q <= I after DELAY ;
end case ;
end process ;
end RTL ;

Circuitul de test se obţine prin asamblarea blocurilor CY7C910, ROM şi PIPELINE.


test_CY7C910.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C910.all ;
use work.std_logic_arith.all ;
use work.std_logic_unsigned.all ;
use IEEE.std_logic_textio.all ;
use STD.TEXTIO.all ;
entity test_CY7C910 is end ;
architecture test of test_CY7C910 is
component CY7C910
port (
D : in std_logic_vector (address_bus_width - 1 downto 0) ;
nRLD : in std_logic ;
I : in std_logic_vector (3 downto 0) ;
nCC :in std_logic ;
nCCEN : in std_logic ;
CP : in std_logic ;
CI : in std_logic ;
nOE : in std_logic ;
Y : out std_logic_vector (address_bus_width - 1 downto 0) ;
nFULL : out std_logic ;
nPL : out std_logic ;
nMAP : out std_logic ;
nVECT : out std_logic) ;
end component ;

component pipeline
port (CP, R : in std_logic ; I : in std_logic_vector (19 downto 0) ;
Q : out std_logic_vector (19 downto 0) ) ;
55
end component ;

component ROM
generic (SIZE : integer := 20 ; WORDS : integer := 94 ; ADSIZE : integer := 7 ;
CODEFILE : string := "Program.txt") ;
port (A : in std_logic_vector (ADSIZE - 1 downto 0) ;
DOUT : out std_logic_vector (SIZE - 1 downto 0) ) ;
end component ;

signal D, Y : std_logic_vector (address_bus_width - 1 downto 0) ;


signal nRLD, nCC, nCCEN, CP, CI, nOE, nFULL, nPL, nMAP, nVECT, R : std_logic ;
signal I : std_logic_vector (3 downto 0) ;
signal A : std_logic_vector (6 downto 0) ;
signal DOUT, Q : std_logic_vector (19 downto 0) ;
constant TPER : time := 50 ns ; -- 50 se înlocuieşte cu 14 pentru a doua simulare

-- semnale ajutatoare pt analiza formelor de unda


signal S1 : std_logic_vector (3 downto 0) ; -- nRLD CI nCC nCCEN
signal D_v, Y_v : integer ;
signal INSTRUCTION : INSTR_type ;
signal Source_v : INT_S_type ;
signal Source_v2 : std_logic_vector (2 downto 0) ;

begin
DUT : CY7C910 port map (D, nRLD, I, nCC, nCCEN, CP, CI, nOE, Y, nFULL, nPL, nMAP, nVECT) ;
pipeline_i : pipeline port map (CP, R, DOUT, Q) ;
ROM_i : ROM generic map (SIZE => 20, WORDS => 93, ADSIZE => 7, CODEFILE => "Program.txt")
port map (A, DOUT) ;
process
begin
CP <= '0' ;
wait for TPER / 2 ;
CP <= '1' ;
wait for TPER / 2 ;
end process ;
R <= '1', '0' after 3 * TPER ;
nRLD <= Q (19) ;
CI <= Q (18) ;
nCCEN <= Q (17) ;
nCC <= Q (16) ;
I <= Q (15 downto 12) ;
D <= Q (11 downto 0) ;
A <= Y (6 downto 0) ;

S1(3) <= nRLD ;


S1(2) <= CI ;
S1(1) <= nCCEN ;
S1(0) <= nCC ;
D_v <= conv_integer (D) ;
Y_v <= conv_integer (Y) ;
Source_v2(2) <= nPL ;
Source_v2(1) <= nMAP ;
Source_v2(0) <= nVECT ;
nOE <= '0' ;
process (I)
begin
if (I'event) then
case I is
when JZ => INSTRUCTION <= JZ_v ;
when CJS => INSTRUCTION <= CJS_v;
when JMAP => INSTRUCTION <= JMAP_v ;
when CJP => INSTRUCTION <= CJP_v ;
when PUSH => INSTRUCTION <= PUSH_v ;
when JSRP => INSTRUCTION <= JSRP_v ;
when CJV => INSTRUCTION <= CJV_v ;
when JRP => INSTRUCTION <= JRP_v ;
when RFCT => INSTRUCTION <= RFCT_v ;
when RPCT => INSTRUCTION <= RPCT_v ;
when CRTN => INSTRUCTION <= CRTN_v ;
when CJPP => INSTRUCTION <= CJPP_v ;
when LDCT => INSTRUCTION <= LDCT_v ;
when LOP => INSTRUCTION <= LOP_v ;
when CONT => INSTRUCTION <= CONT_v ;
when TWB => INSTRUCTION <= TWB_v ;
when others => INSTRUCTION <= XXXX ;
end case ;
end if ;
end process ;
56
process (Source_v2)
begin
if (Source_v2'event) then
case Source_v2 is
when "011" => Source_v <= PL_v ;
when "101" => Source_v <= Mapp_v ;
when "110" => Source_v <= Vect_v ;
when others => Source_v <= XXX ;
end case ;
end if ;
end process ;
end test ;

În continuare voi reproduce formele de undă prezentate în [2], împreună cu comentariile referitoare
la acestea.
Figura 1 arată formele de undă începând cu momentul anterior dezactivări semnalului de reset (rstn
în figură) al registrului pipeline. Sunt prezentate formele de undă corespunzătoare multor semanle
importante din design (Trebuie preciat că denumirile semnalelor şi a tipurilor corespunzătoare acestor
semnale sunt diferite de cele din proiectul meu, dar destul de asemănătoare pentru ca formele de undă să
poată fi analizate cu uşurinţă) . După cum se observă din figura 1, stiva şi MPC-ul sunt şterse (resetate) .
MUX_CNTL este setat pe SEL_ZERO astfel încât Y va fi Zero. Register?Counter-ul este, de asemenea,
încărcat cu Zero. După ce semnalul de reset (RSTn) este dezactivat, instrucţiunile din microprogramul
stocat în memoria ROM sunt executate. Prima instrucţiune este o instrucţiune CONT (Continue) . MPC-ul
este incrementat cu 1. MUX_CNTL este setat pe SEL_UPC. Următoarea instrucţiune, PUSH, este
executată. Prima instrucţiune PUSH nu modifică SP-ul. Flagul EMPTYn este dezactivat. După aceasta, SP-
ul va fi incrementat.

Figura 1

Figura 2 prezintă următoarele forme de undă, pentru situaţia în care stiva este plină. Ieşirea FULLn este
activată după ce se scrie ultima locaţie liberă a stivei. Următoarea instrucţiune PUSH suprascrie valoarea
din vârful stivei, 12 (hexa) , cu 13 (hexa) . Apoi asupra stivei se execută operaţia POP. De notat că ieşirea
stivei indică valoarea 11 (hexa) , care reprezintă valoarea înscrisă în penultima locaţie a stivei. Ieşirea
FULLn este dezactivată.

57
Figura 2

Figura 3 prezintă formele de undă corespunzătoare golirii stivei. Flagul EMPTYn este activat. Stack
Pointer-ul rămâne zero. Ieşirea stivei rămâne la valoarea 2, care reprezintă prima valoare înscrisă în stivă.

Figura 3

58
Figura 4 reproduce formele de undă corespunzătoare încărcării Register/Counter-ului cu valoarea 3.
Instrucţiunile CONT şi RFCT sunt executate de 4 ori. De notat că Register?counter-ul este decrementat la
fiecare instrucţiune RFCT.

Figura 4

Formele de undă din figura 5 prezintă testarea instrucţiunilor CRTN, CJS, LDCT, RPCT, CJV, JRP şi
JSRP.

Figura 5

59
Figura 6 reproduce ultimele forme de undă ale simulării. Se testează instrucţiunea de ramificare TWB. În
final, CI este setat pe 0. Se observă că ieşirea MPC-ului rămâne la aceeaşi valoare.

Figura 6

Există, bineînţeles, multe funcţii şi combinaţii de instrucţiuni care nu sunt verificate de acest program de
test. Eu mi-am permis să consider că, dacă circuitul proiectat de mine funcţionează corect pentru acest test
incomplet, este foarte probabil ca să funcţioneze corect şi pentru un test mult mai complet (Bineînţeles, n-
am nici o dovadă cu care să susţin aceasta) .

După ce, în prealabil, s-a realizat sinteza circuitului CY7C910, testarea postsinteză se realizează
astfel :
- se compilează, cu ModelSim, fişierul “TCB773P.v” ; în acest fişier se află descrierile Verilog pentru
componentele din biblioteca tehnologică “tcb773pwc.lib”, componente cu care programul de sinteză a
implementat circuitul CY7C910 ;
- se compilează fişierul “CY7C910_mapped.vhd” generat de Design Compiler în urma procesului de
sinteză a designului CY7C910 ;
- se compilează programul de test “test_CY7C910.vhd” ; în prealabil trebuiau compilate fişierele
“ROM.vhd” şi “pipeline.vhd” ;
- se încarcă arhitectura test din cadrul designului test_CY7C910, având grijă să ataşăm fişierul
“CY7C910_mapped.sdf” (generat de programul de sinteză) instanţei DUT (instanţierea circuitului
CY7C910) din cadrul circuitului de test ; în plus, rezoluţia de simulare trebuie setată pe ps (picosecunde) .
Acestea fiind făcute, se poate trece la vizualizarea formelor de undă. Trebuie să spun că am simulat
circuitul CY7C910 pentru diverse perioade (frecvenţe) ale semnalului de ceas. Am pornit de la o valoare
de 100 ns a perioadei semnalului de ceas şi am coborât treptat această valoare, până când simularea a arătat
o funcţionare incorectă a circuitului. Cea mai mică perioadă a semnalului de ceas pentru care circuitul a
mai funcţionat corect a fost de 14 ns, ceea ce corespunde unei frecvenţe de funcţionare de aproximativ 70
MHz (mai mult ca sigur că, în urma realizării layout-ului , simularea postlayout va arăta o frecvenţă
maximă de funcţionare mai mică) .
Am hotărât să prezint formele de undă obţinute în urma simulării postsinteză în două cazuri :
perioada semnalului de ceas de 50 ns şi perioada semnalului de ceas de 14 ns. Am ales cazul simulării cu
60
perioada semnalului de ceas de 50 ns întrucât simularea presinteză prezentată în [2] a fost realizată cu un
semnal de ceas de aceeaşi perioadă, asfel putându-se pbserva mai uşor diferenţele dintre simularea
postsinteză şi simularea presinteză. Am ales prezentarea simulării cu semnalul de ceas cu perioada de 14 ns
întrucât aceasta corespunde frecvenţei maxime de funcţionare a circuitului, reprezentând cazul cel mai
interesant din punct de vedere practic.
Prezentarea simulării cu perioada semnalului de ceas de 50 ns este foarte importantă şi pentru a evidenţia
funcţionarea corectă a circuitului în cazul semnaluli de ceas cu perioada de 14 ns, prin compararea formelor
de undă obţinute în cele două cazuri (ar fi fost foarte greu de comparat rezultatele testării postsinteză cu
perioada semanalului de ceas de 14 ns cu rezultatele testării presinteze prezentate în [2])
În continuare voi reproduce, în paralel, formele de undă obţinute în urma simulării postsinteze a
circuitului CY7C910 pentru cele două cazuri.

61
62
63
64
65
66
CY7C901

Descriere funcţională
CY7C901 este o unitate aritmetico-logică (ALU) pe 4 biţi, rapidă, expandabilă, care poate fi
utilizată pentru implementarea componentei aritmetice a unui CPU, controller periferic sau controller
programabil. Setul de instrucţiuni al CY7C901 este simplu însă foarte versatil, ceea ce permite emularea
unităţii ALU a aproape oricărui calculator.
După cum se observă din diagrama bloc, CY7C901 constă dintr-o memorie RAM (16 x 4 biţi) dual-
port, un ALU pe 4 biţi şi logica necesară pentru manipularea datelor şi control.

CY7C901 - diagrama bloc

Operaţia realizată este determinată de 9 linii de intrare de control (I0 – I9) , valorile aplicate pe
acestea provenind de obicei de la un registru de microinstrucţiuni.
Cy7C901 este expandabil în incrementări a câte 4 biţi, are ieşiri “three-states”, flag-uri, iar semnalul
de carry poate fi folosit pentru implementarea fie a unui “look-ahead carry”, fie a unui “ripple carry”.
Tabel 1.Descrierea pinilor
Nume I/O Descriere
A0 – A3 I aceste 4 linii de adresa selecteaza unul din registrii din stiva
si pune continutul acestuia pe portul (intern) A
B0 – B3 I aceste 4 linii de adresa selecteaza unul din registrii din stiva si
pune continutul acestuia pe portul (intern) B ; aceste linii pot,
de asemenea, sa reprezinte adresa destinatie atunci cand data
este scrisa in registri
I0 – I8 I Aceste 9 linii de insructiune selecteaza sursa de date pentru
ALU (I(2), I(1) , I(0)) , operatia care trebuie realizata
(I(5), I(4), I(3)) si ce data trebuie sa fie inscrisa in
Registrul Q sau in registrii de memorie (I(8), I(7), I(6))
D0 – D3 I Reprezinta 4 linii de intrare de date care pot fi selectate
de I(2)I(1)I(0) ca intrari ale ALU
Y0 – Y3 O liinii three state de iesire date care pot fi selectate ca intrari
67
ale ALU de catre I(2) I(1) I(0)
\OE I OUTPUT ENABLE ; intrare activa pe LOW care
controleaza iesirile Y ; cand este LOW, iesirile Y sunt
activate, cand este HIGH iesireil Y sunt in inalta impedanta
CP I Intrarea semnalului de ceas ; Nivelul LOW al ceasului inscrie
data in memoria RAM ; Nivelul HIGH al ceasului inscrie data
din RAM in latch-urile port A si port B
Functionarea registrului QQ este similara ; Data intra in
latch-ul master pe palierul LOW al ceasului si este transferata
din master in slave pe palierul HIGH al ceasului
Q3 I/O linii bidirectionale controlate de intrarile I(8) I(7) I(6)
RAM3 IESIRI : Cand codul destinatie pe liniile I(8) I(7) I(6)
indica o operatie de deplasare la stanga(UP), Iesirile
three state sunt activate si MSB_ul registrului Q este scos la
pinul Q3 iar MSB_ul iesiri ALU (F3) este scos la pinul RAM3
INTRARI : Cand codul destinatie pe liniile I(8) I(7) I(6)
indica o operatie de deplasare la dreapta(DOWN), pinul
Q3 reprezinta intrarea de date catre MSB-ul registrului Q
iar RAM3 reprezinta intrarea de date catre MSB-ul RAM-ului
Q0 I/O linii bidirectionale care functioneaza similar cu Q3 si RAM3,
RAM0 doar ca reprezinta LSB_ul registrului Q respectiv al RAM-ului
Cn I carry-in catre ALU-ul intern
Cn+4 O carry-out de la ALU-ul intern
\G O iesiri pentru carry generat si carry propagat ale ALU ; pot
\P fi utilizate pentru a realiza o operatie "carry look-ahead"
asupra celor 4 biti ai ALU
OVR O OVERFLOW ; Acest semnal este dpdv logic rezultatul
operatiei XOR intre carry-in si carry-out ale MSB al ALU ;
indica daca rezultatul operatiei realizate de ALU a
depasit capacitatea masinii ; valid doar pentru bitul de semn si
se asuma codarea numerelor negative in complement fata de 2 ;
F=0 O iesire "open drain" care trece in HIGH dacă data de pe
iesirea ALU are toti bitii in LOW <=> F = 0000 ; indica faptul
ca rezultatul unei operatii a ALU este zero

F3 O MSB al iesirii ALU

Descriere arhitecturală

RAM
RAM-ul este adresat de două intrări de adresă de câte 4 biţi (A0 – A3 şi B0 – B3) care determină ca datele de
la adresele selectate să apară la porturile interne A şi B. Dacă adresele A şi B sunt identice, atunci datele la
porturile interne A şi B vor fi identice.
Datele noi se înscriu în RAM la locaţia specificată de intrările de adresă B, atunci când semnalul de scriere a
RAM-ului (WR_EN) este activ, iar semanlul de ceas se află pe nivelul LOW.
Fiecare din cele 4 intrări de date ale RAM-ului este comandată de câte un multiplexor, ceea ce permite
ieşirii ALU (F0 – F3) să poată fi deplasată cu un bit la stânga sau la dreapta (sau să nu fie deplasată). În
cazul unei deplasări la stânga, MSB-ul este scos pe pinul RAM3, iar LSB-ul este preluat de pe pinul RAM0.
În cazul deplasării la dreapta, LSB-ul este scos la pinul RAM0, iar MSB-ul este preluat de la pinul RAM3.

68
Data care trebuie înscrisă în RAM se aplică pe intrările de date D şi se trece nemodificată prin ALU, până
la locaţia de adresă indicată de intrările de adresă B.
Ieşirile RAM-ului, porturile interne A şi B, sunt conectate la câte un latch pe 4 biţi, care devin active atunci
când semnalul de ceas se află pe nivel HIGH. Ieşirile latch-urilor sunt conectate. prin intermediul unor
multiplexoare, la cele două intrări ale ALU (R3 – R0 şi S3 – S0) şi la ieşirile Y3 – Y0.

ALU
ALU poate executa 3 operaţii aritmetice şi 5 operaţii logice cu 2 operanzi pe câte 4 biţi : R şi S. Intrările R
provin de la 4 multiplexoare de două intrări, ale căror intrări provin fie de la portul A intern, fie de la
intrările externe de date D. Intrările S provin de la 4 multiplexoare de trei intrări conectate la porturile
interne A şi B şi la registrul Q. Ambele grupuri de multiplexoare sunt comandate de intrările I2 – I0.
Configuraţia multiplexoarelor de pe intrările R şi S ale ALU permit utilizatorului să selecteze 8 perechi de
combinaţii între A, B, D, Q şi “0000”(neselectat) ca operanzi ai ALU.
Tabel 2. Selecţia operanzilor ALU
Mnemonic Micro Code Operanzii ALU
I2 I1 I0 Octal R S
AQ L L L 0 A Q
AB L L H 1 A B
ZQ L H L 2 0 Q
ZB L H H 3 0 B
ZA H L L 4 0 A
DA H L H 5 D A
DQ H H L 6 D Q
DZ H H H 7 D 0

Operaţia executată de ALU este selectată de intrările I5 – I3. Cele 8 operaţii aritmetice şi logice între
operanzii R şi S sunt prezentate în tabelul de mai jos.
Tabel 3.Operaţiile ALU
Mnemonic Micro Code ALU Symbol
I5 I4 I3 Octal Function
ADD L L L 0 R plus S R+S
SUBR L L H 1 S minus R S−R
SUBS L H L 2 R minus S R−S
OR L H H 3 R OR S R∨S
AND H L L 4 R AND S R∧S
NOTRS H L H 5 R AND S R∧S
EXOR H H L 6 R XOR S R∀S
EXNOR H H H 7 R XNOR S R∀S

ALU are intrare de carry-in (Cn) , ieşire carry-out (Cn+4) , ieşire carry-propagate (\P) , ieşire carry-generate
(\G) şi ieşire pentru overflow (OVR) , ceea ce permite utilizatorului :
1.creşterea vitezei de execuţie a operaţiilor aritmetice prin implementarea transportului “carry-look-ahead”
2.să determine dacă a apărut o depăşire logică
Ieşirile ALU-lui (F3 – F0) sunt rutate către intrările RAM-lui şi ale registrului Qşi către ieşirile Y în funcţie
de semnalele de intrare de control I8 – I6. după cum se arată în tabelul următor :

69
Tabel 4. Setul de instrucţiuni
Mnemonic Micro Code RAM Q-Reg Y RAM Q
function function out shifter shifter
I8 I7 I6 oct shift load shift load RAM0 RAM3 Q0 Q3
QREG L L L 0 X none none F→Q F X X X X
NOP L L H 1 X none X none F X X X X
RAMA L H L 2 none F→B X none A X X X X
RAMF L H H 3 none F→B X none F X X X X
RAMQD H L L 4 DOWN F/2→B DOWN Q/2→Q F F0 IN3 Q0 IN3
RAMD H L H 5 DOWN F/2→B X none F F0 IN3 Q0 X
RAMQU H H L 6 UP 2F→B UP 2Q→Q F IN 0 F3 IN 0 Q3
RAMU H H H 7 UP 2f→B X none F IN0 F3 X Q3
În plus, bitul cel mai semnificativ al ieşirii ALU este scos la pinul F3, astfel încât utilizatorul poate examina
bitul de semn fără a activa buferele three-state de pe ieşire. Pinul F=0, folosit pentru detecţie de zero, este o
ieşire open-drain, ceea ce permite implementarea unei funcţii SAU-cablat între semnalele F=0 de la mai
multe circuite CY7C901 în cazul unei arhitecturi slice multiprocesor.

Registrul Q
Registrul Q funcţionează ca un acumalator sau registru de stocare temporară. Fizic reprezintă un registru de
4 biţi implementat cu latch-uri master-slave. Intrările registrului Q provin de la ieşirile a 4 multiplexoare cu
3 intrări comandate de semnalele de intrare de control I8 – I8. Pinii Q3 şi Q0 funcţionează într-o manieră
similară cu pinii RAM3 şi RAM0. Multiplexoarele permit deplasarea la stânga sau la dreapta a conţinutului
registrului Q, sau încărcarea latch-urilor master cu valoarea din ieşirea ALU. Datele sunt încărcate în latch-
urile master când nivelul semnalului de ceas este LOW şi sunt transferate în latch-urile slave (pe ieşiri)
când semnalul de ceas trece din LOW în HIGH.

Sursele de operanzi şi funcţiile ALU


Semnalele I2 – I0 selectează una din cele 8 perechi de surse de operanzi, iar semnalele I5 – I3 selectează
operaţia care trebuie executată.Semnalul carry-in (Cn) afectează doar rezultatul operaţiilor aritmetice şi
flag-urile interne, neintervenind în operaţiile logice.

Funcţiile logice pentru \G, \P, Cn+4 şi OVR


Semnalele G, P, Cn şi OVR indică condiţiile de transport şi depăşire atunci când CY7C901 se află în unul
din modurile adunare sau scădere. Tabelul următor indică ecuaţiile logice pentru aceste 4 semnale pentru
fiecare din cele 8 funcţii ale ALU. R şi S reprezintă cele două intrări selectate conform tabelul 4.
Definiţii (+ inseamnă OR) :
P0 = R0 + S0 ; G0 = R0S0 ;
P1 = R1 + S1 ; G1 = R1S1 ;
P2 = R2 + S2 ; G2 = R2S2 ;
P3 = R3 + S3 ; G3 = R3S3 ;
C4 = G3 + P3G2 + P3P2G1 + P3P2G0 + P3P2P1P0Cn ;
C3 = G2 + P2G1 + P2P1G0 + P2P1P0Cn ;
Tabel 5. Funcţiile logice pentru semnalele \P, \G, Cn+4 şi OVR
I543 Function \P \G Cn + 4 OVR
0 R÷S P3 P2 P1P0 G3 + P3G2 + P3 P2G1 + P3 P2 P1G0 C4 C3∀C4
1 S−R La fel ca la R+S, dar se inlocuieşte Ri cu Ri în definiţii
2 R−S La fel ca la R+S, dar se inlocuieşte S cu Si în definiţii
i

3 R∨S LOW P3 P2 P1P0 P3 P2 P1P0 + Cn P3 P2 P1P0 + Cn

70
4 R∧S LOW G3 + G2 + G1 + G0 G3 + G2 + G1 + G0 + Cn G3 + G2 + G1 + G0 + Cn

5 R∧S LOW La fel ca la R ∧ S , dar se inlocuieşte Ri cu Ri în definiţii


6 R∀S La fel ca la R∀S , dar se inlocuieşte Ri cu Ri în definiţii
7 R∀S G3 + G2 + G3 + P3G2 + P3 P2G1 + P3 P2 P1P0 Nota 1 Nota 2
G1 + G0

(
Nota 1 : G3 + P3G2 + P3 P2G1 + P3 P2 P1P0 G0 + Cn )
[[ ]] [
Nota 2 : P2 + G2 P1 + G2 G1 P0 + G2 G1 G0Cn ∀ P3 + G3 P2 + G3 G2 P1 + G3 G2 G1 P0 + G3 G2 G1 G0Cn ]
Package - ul

În acest package am definit câteva tipuri de date şi seturi de constante pentru a-mi uşura scrierea codului.
PackageCY7C901.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
package packageCY7C901 is

subtype vec2 is std_logic_vector (1 downto 0) ;


subtype vec3 is std_logic_vector (2 downto 0) ;
subtype vec4 is std_logic_vector (3 downto 0) ;
-- ALU Source Operand Control' s Mnemonic
constant AQ : vec3 := "000" ;
constant AB : vec3 := "001" ;
constant ZQ : vec3 := "010" ;
constant ZB : vec3 := "011" ;
constant ZA : vec3 := "100" ;
constant DA : vec3 := "101" ;
constant DQ : vec3 := "110" ;
constant DZ : vec3 := "111" ;

-- ALU Function Control's Mnemonics ;


--s-a folosit sufixul _i fiindca unele mnemonice sunt cuvinte rezervate in VHDL
constant ADD_i : vec3 := "000" ;
constant SUBR_i : vec3 := "001" ;
constant SUBS_i : vec3 := "010" ;
constant OR_i : vec3 := "011" ;
constant AND_i : vec3 := "100" ;
constant NOTRS_i: vec3 := "101" ;
constant EXOR_i : vec3 := "110" ;
constant EXNOR_i : vec3 := "111" ;

-- ALU Destination Control's Mnemonics


constant QREG : vec3 := "000" ;
constant NOP : vec3 := "001" ;
constant RAMA : vec3 := "010" ;
constant RAMF : vec3 := "011" ;
constant RAMQD : vec3 := "100" ;
constant RAMD : vec3 := "101" ;
constant RAMQU : vec3 := "110" ;
constant RAMU : vec3 := "111" ;

-- Semnale folosite pentru vizualizare in test_bench-uri


type ALU_source is (AQv, ABv, ZQv, ZBv, zAv, DAv, DQv, DZv, XXX) ;
type ALU_instruction is (ADDv, SUBRv, SUBSv, ORv, ANDv, NOTRSv, EXORv, EXNORv, XXX) ;
type ALU_destination is (QREGv, NOPv, RAMAv, RAMFv, RAMQDv, RAMDv, RAMQUv, RAMUv, XXX) ;

end packageCY7C901 ;

71
ALU
Pentru acest bloc am decis să folosesc o metodă de testare completă. Astfel, pentru fiecare pereche de
valori ale intrărilor R şi S (în total 16 x 16 = 256) , am aplicat pe intrarea de control, succesiv, fiecare din
cele 8 instrucţiuni şi, pentru fiecare instrucţiune, am atribuit intrării Cn atât nivelul LOW, cât şi nivelul
HIGH. Astfel, pentru testarea completă a acestui bloc se generează 16 x 16 x 8 x 2 = 4096 de vectori de
test. Simularea circuitului pentru aceşti 4096 de vectori de test presupune un efort de calcul nesemnificativ.
Testarea completă a fost posibilă în acest caz datorită caracterului pur combinaţional şi numărului
foarte mic de intrări (12) ale acestui bloc.
test_ALU.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use IEEE.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity test_ALU is end ;
architecture test of test_ALU is
signal R, S, F : vec4 ;
signal Rv, Sv, Fv : integer ; -- pentru vizualizare ;
signal CNTL : vec3 ;
signal CNTLv : ALU_instruction ; -- pentru vizualizare
signal Cn, nG, nP, Cn4, OVR : std_logic ;
component ALU
port (R, S : in vec4 ; CNTL : in vec3 ; Cn : in std_logic ; F : out vec4 ; nG, nP, Cn4, OVR : out
std_logic) ;
end component ;
constant TPER : time := 30 ns ;
constant DELAY : time := 10 ns ;
signal nG_t, nP_t, Cn4_t, OVR_t : std_logic ;
signal F_t : vec4 ;
signal P, G : vec4 ;
signal C4, C3 : std_logic ;
signal test_OK : BOOLEAN := TRUE ;
signal vec12 : std_logic_vector (11 downto 0) := "000000000000" ;
begin
vec12 <= vec12 + 1 after TPER ;
R <= vec12 (11 downto 8) ;
S <= vec12 (7 downto 4) ;
CNTL <= vec12 (3 downto 1) ;
Cn <= vec12 (0) ;

DUT : ALU port map (R, S, CNTL, Cn, F, nG, nP, Cn4, OVR) ;
process
begin
wait until (R'event or S'event or CNTL'event or Cn'event) ;
case CNTL is
when ADD_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when SUBR_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when SUBS_i =>
for k in 0 to 3 loop
P(k) <= R(k) or (not S(k)) ;
G(k) <= R(k) and (not S(k)) ;
end loop ;
when OR_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when AND_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when NOTRS_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;

72
end loop ;
when EXOR_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when others => -- EXNOR_i
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;

end case ;

end process ;

C4 <= G(3) or (P(3) and G(3)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and G(0)) or (P(3) and P(2) and P(1) and P(0) and Cn);
C3 <= G(2) or (P(2) and G(1)) or (P(2) and P(1) and G(0)) or (P(2) and P(1) and P(0) and Cn) ;

process
begin
wait until (R'event or S'event or CNTL'event or Cn' event or C4'event or C3'event or P'event or G'event);
case CNTL is
when ADD_i =>
F_t <= R + S + Cn;
nP_t <= not (P(3) and P(2) and P(1) and P(0)) ;
nG_t <= not(G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0)));
Cn4_t <= C4 ;
OVR_t <= C3 xor C4 ;
when SUBR_i =>
F_t <= S - R - (not Cn) ;
nP_t <= not (P(3) and P(2) and P(1) and P(0)) ;
nG_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0)) ) ;
Cn4_t <= C4 ;
OVR_t <= C3 xor C4 ;
when SUBS_i =>
F_t <= R - S - (not Cn) ;
nP_t <= not (P(3) and P(2) and P(1) and P(0)) ;
nG_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0)) ) ;
Cn4_t <= C4 ;
OVR_t <= C3 xor C4 ;
when OR_i =>
F_t <= R or S ;
nP_t <= '0' ;
nG_t <= P(3) and P(2) and P(1) and P(0) ;
Cn4_t <= (not (P(3) and P(2) and P(1) and P(0)) ) or Cn ;
OVR_t <= (not (P(3) and P(2) and P(1) and P(0)) ) or Cn ;
when AND_i =>
F_t <= R and S ;
nP_t <= '0' ;
nG_t <= not (G(3) or G(2) or G(1) or G(0) ) ;
Cn4_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
OVR_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
when NOTRS_i =>
F_t <= (not R) and S ;
nP_t <= '0' ;
nG_t <= not (G(3) or G(2) or G(1) or G(0) ) ;
Cn4_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
OVR_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
when EXOR_i =>
F_t <= R xor S ;
nP_t <= G(3) or G(2) or G(1) or G(0) ;
nG_t <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and P(0)) ;
Cn4_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2)
and P(1) and P(0) and (G(0) or (not Cn)) ) ) ;
OVR_t <= (P(2) or (G(2) and P(1)) or ((not G(2)) and (not G(1)) and (not P(0)))) xor ((not P(3)) or ((not
G(3)) and (not P(2))) or ((not G(3)) and (not G(2)) and (not P(1))) or ((not G(3)) and (not G(2))
and (not G(1)) and (not P(0))) or ((not G(3)) and (not G(2)) and (not G(1)) and (not G(0)) and Cn));

when others => -- EXNOR_i


F_t <= R xnor S ;
nP_t <= G(3) or G(2) or G(1) or G(0) ;
nG_t <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and P(0));
Cn4_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2)
and P(1) and P(0) and (G(0) or (not Cn)) )) ;
OVR_t <= (P(2) or (G(2) and P(1)) or ((not G(2)) and (not G(1)) and (not P(0)))) xor((not P(3)) or
((not G(3)) and (not P(2))) or ((not G(3)) and (not G(2)) and (not P(1)) or ((not G(3)) and (not G(2))
and (not G(1)) and (not P(0))) or ((not G(3)) and (not G(2)) and (not G(1)) and (not G(0)) and Cn)) ;

73
end case ;
end process ;

process
begin
wait until (R'event or S'event or CNTL'event or Cn'event) ;
wait for DELAY ;
if((F_t = F) and (Cn4_t = Cn4) and (OVR_t = OVR) and (nG_t = nG) and (nP_t = nP) )
then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity Warning ;
end if ;
end process ;

-- Semnalele pentru vizualizare


Rv <= conv_integer (R) ;
Sv <= conv_integer (S) ;
Fv <= conv_integer (F) ;
process (CNTL)
begin
case CNTL is
when ADD_i => CNTLv <= ADDv ;
when SUBR_i => CNTLv <= SUBRv ;
when SUBS_i => CNTLv <= SUBSv ;
when OR_i => CNTLv <= ORv ;
when AND_i => CNTLv <= ANDv ;
when NOTRS_i => CNTLv <= NOTRSv ;
when EXOR_i => CNTLv <= EXORv ;
when EXNOR_i => CNTLv <= EXNORv ;
when others => CNTLv <= XXX ;
end case ;
end process ;
end test ;

Descrierea VHDL a blocului ALU reprezintă transpunerea în cod VHDL a informaţiilor conţinute în
tabelele 2 şi 5, solicitând mai mult atenţia decât inventivitatea.
ALU.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
use IEEE.std_logic_unsigned.all ;
entity ALU is
port (R, S : in vec4 ; CNTL : in vec3 ; Cn : in std_logic ; F : out vec4 ; nG, nP, Cn4, OVR : out
std_logic) ;
end ALU ;
architecture RTL of ALU is
signal P, G : vec4 ;
signal C3, C4 : std_logic ;
begin
process (R, S, CNTL, Cn)
begin
case CNTL is
when ADD_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when SUBR_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when SUBS_i =>
for k in 0 to 3 loop
P(k) <= R(k) or (not S(k)) ;
G(k) <= R(k) and (not S(k)) ;
end loop ;
when OR_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when AND_i =>

74
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when NOTRS_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when EXOR_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when others => -- EXNOR_i
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;

end case ;
end process ;

process (P, G, Cn)


begin
C4 <= G(3) or (P(3) and G(3)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and G(0)) or (P(3) and P(2)
and P(1) and P(0) and Cn) ;
C3 <= G(2) or (P(2) and G(1)) or (P(2) and P(1) and G(0)) or (P(2) and P(1) and P(0) and Cn) ;
end process ;

process (R, S, CNTL, P, G, Cn, C4, C3)


begin
case CNTL is
when ADD_i =>
F <= R + S + Cn;
nP <= not (P(3) and P(2) and P(1) and P(0)) ;
nG <= not(G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0))) ;
Cn4 <= C4 ;
OVR <= C3 xor C4 ;
when SUBR_i =>
F <= S - R - (not Cn) ;
nP <= not (P(3) and P(2) and P(1) and P(0)) ;
nG <= not(G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0))) ;
Cn4 <= C4 ;
OVR <= C3 xor C4 ;
when SUBS_i =>
F <= R - S - (not Cn) ;
nP <= not (P(3) and P(2) and P(1) and P(0)) ;
nG <= not(G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and G(0))) ;
Cn4 <= C4 ;
OVR <= C3 xor C4 ;
when OR_i =>
F <= R or S ;
nP <= '0' ;
nG <= P(3) and P(2) and P(1) and P(0) ;
Cn4 <= (not (P(3) and P(2) and P(1) and P(0)) ) or Cn ;
OVR <= (not (P(3) and P(2) and P(1) and P(0)) ) or Cn ;
when AND_i =>
F <= R and S ;
nP <= '0' ;
nG <= not (G(3) or G(2) or G(1) or G(0) ) ;
Cn4 <= G(3) or G(2) or G(1) or G(0) or Cn ;
OVR <= G(3) or G(2) or G(1) or G(0) or Cn ;
when NOTRS_i =>
F <= (not R) and S ;
nP <= '0' ;
nG <= not (G(3) or G(2) or G(1) or G(0) ) ;
Cn4 <= G(3) or G(2) or G(1) or G(0) or Cn ;
OVR <= G(3) or G(2) or G(1) or G(0) or Cn
when EXOR_i =>
F <= R xor S ;
nP <= G(3) or G(2) or G(1) or G(0) ;
nG <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and P(0)) ;
Cn4 <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1))
or (P(3) and P(2) and P(1) and P(0) and (G(0) or (not Cn)) ) ) ;
OVR <= (P(2) or (G(2) and P(1)) or ((not G(2)) and (not G(1)) and (not P(0)))) xor ((not P(3)) or ((not G(3))
and (not P(2))) or ((not G(3)) and (not G(2)) and (not P(1))) or ((not G(3)) and (not G(2)) and

75
(not G(1))and (not P(0))) or ((not G(3)) and (not G(2)) and (not G(1)) and (not G(0)) and Cn)) ;

when others => -- EXNOR_i


F <= R xnor S ;
nP <= G(3) or G(2) or G(1) or G(0) ;
nG <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1) and P(0)) ;
Cn4 <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and P(1)
and P(0) and (G(0) or (not Cn)) ) ) ;
OVR <= (P(2) or (G(2) and P(1)) or ((not G(2)) and (not G(1)) and (not P(0)))) xor ((not P(3)) or ((not
G(3)) and (not P(2))) or ((not G(3)) and (not G(2)) and (not P(1))) or ((not G(3)) and (not G(2))
and (not G(1)) and (not P(0))) or ((not G(3)) and (not G(2)) and (not G(1)) and (not G(0)) and Cn)) ;
end case ;
end process ;

end RTL ;

Întrucât am realizat testarea completă a acestui bloc, prezentarea unor forme de undă obţinute în urma
simulării ar fi irelevantă sau ar ocupa foarte mult spaţiu. Urmărirea funcţionării acestui bloc se poate realiza
cu fişierele de pe CD-ul anexă.

ALU – RTL

Q_REGISTER
test_Q_REGISTER.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity test_Q_REGISTER is end ;
architecture test of test_Q_REGISTER is
component Q_REGISTER
port(CP : in std_logic ; F, Q : in vec4 ; CNTL : in vec3 ; Q_out : out vec4) ;
end component ;
signal CP : std_logic := '0' ;
signal F : vec4 := "0001" ;
signal Q : vec4 := "1001" ;
signal Q_out : vec4 ;
signal CNTL : vec3 := "000" ;
signal CNTLv : ALU_destination ; -- pentru vizualizare
constant TPER : time := 20 ns ;
constant DELAY : time := 3 ns ;
signal test_OK : BOOLEAN := TRUE ;
begin
DUT : Q_REGISTER port map (CP, F, Q, CNTL, Q_out) ;
CP <= not CP after TPER / 2 ;
process
begin

76
wait until (CP'event and CP = '1') ;
wait for TPER/4 ;
CNTL <= CNTL + 1 ;
F <= F + 7 ;
Q <= Q + 9 ;
end process ;

process
variable F_var, Q_var, Q_out_var : vec4 ;
begin
wait until (CP'event and CP = '0') ;
F_var := F ;
Q_var := Q ;
Q_out_var := Q_out ;
wait until (CP'event and CP = '1') ;
wait for DELAY ;
case CNTL is
when QREG =>
if (Q_out = F_var) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
when RAMQD =>
if (Q_out = Q_var) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
when RAMQU =>
if (Q_out = Q_var) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
when others =>
if (Q_out = Q_out_var) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
end case ;
end process ;
-- pentru vizualizare
process (CNTL)
begin
case CNTL is
when QREG => CNTLv <= QREGv ;
when NOP => CNTLv <= NOPv ;
when RAMA => CNTLv <= RAMAv ;
when RAMF => CNTLv <= RAMFv ;
when RAMQD => CNTLv <= RAMQDv ;
when RAMD => CNTLv <= RAMDv ;
when RAMQU => CNTLv <= RAMQUv ;
when RAMU => CNTLv <= RAMUv ;
when others => CNTLv <= XXX ;
end case ;
end process ;

end test ;

Întrucât de pe diagrama bloc a circuitului CY7C901 se observă că blocul Q_REGISTER realizează o dublă
funcţie (registru master-slave + selecţia uneia dintre cele două intrări) , am hotărât să-l descompun în două
sub-blocuri : Q_REGISTER_SOURCE_SEL (realizează selecţia uneia dintre cele 2 intrări, F şi Q, în
funcţie de intrarea de control, CNTL) şi REG_MASTER_SLAVE. Blocul REG_MASTER_SLAVE are o
intrare de activare, LD_EN, care se conectează la ieşirea cu acelaşi nume a blocului
77
Q_REGISTER_SOURCE_SEL. Semnalul LD_EN este activat sau dezactivat conform informaţiilor din
tabelul 4.
Şi în cazul acestui bloc am trecut peste specificaţiile circuitului (din aceleaşi motive ca şi în cazul
memoriei RAM) , încărcarea datelor în registru şi transferarea acestora pe ieşiri făcându-se pe front, nu pe
palier.
Descrierile VHDL pentru blocul Q_REGISTER şi pentru cele 2 sub-blocuri ale sale sunt date în continuare.
Q_REGISTER_SOURCE_SEL.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity Q_REGISTER_SOURCE_SEL is
port (F, Q : in vec4 ; CNTL : in vec3 ; Q_in : out vec4 ; LD_EN : out std_logic) ;
end Q_REGISTER_SOURCE_SEL ;
architecture RTL of Q_REGISTER_SOURCE_SEL is
begin
process (CNTL, F, Q)
begin
case CNTL is
when QREG =>
Q_in <= F ;
LD_EN <= '1' ;
when RAMQD =>
Q_in <= Q ;
LD_EN <= '1' ;
when RAMQU =>
Q_in <= Q ;
LD_EN <= '1' ;
when others =>
Q_in <= "----" ;
LD_EN <= '0' ;
end case ;
end process ;
end RTL ;

REG_MASTER_SLAVE.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity REG_MASTER_SLAVE is
port (CP : in std_logic ; Q_in : in vec4 ; LD_EN : in std_logic ;
Q_out : out vec4) ;
end REG_MASTER_SLAVE ;
architecture RTL of REG_MASTER_SLAVE is
signal Q_master : vec4 ;

begin

process (CP)
begin
if (CP'event and CP = '0') then
if (LD_EN = '1') then
Q_master <= Q_in ;
end if ;
end if ;
end process ;

process (CP)
begin
if (CP'event and CP = '1') then
Q_out <= Q_master ;
end if ;
end process ;

end RTL ;

Q_REGISTER
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity Q_REGISTER is
port (CP : in std_logic ; F, Q : in vec4 ; CNTL : in vec3 ; Q_out : out vec4) ;
end Q_REGISTER ;
architecture RTL of Q_REGISTER is

78
signal Q_in : vec4 ; -- F sau Q in functie de CNTL
signal LD_EN : std_logic ;
component Q_REGISTER_SOURCE_SEL
port (F, Q : in vec4 ; CNTL : in vec3 ; Q_in : out vec4 ; LD_EN : out std_logic) ;
end component ;
component REG_MASTER_SLAVE
port(CP : in std_logic ; Q_in : in vec4 ; LD_EN : in std_logic ; Q_out : out vec4);
end component ;

begin
SOURCE_SELECT_i : Q_REGISTER_SOURCE_SEL port map (F, Q, CNTL, Q_in, LD_EN) ;
MASTER_SLAVE_i : REG_MASTER_SLAVE port map (CP, Q_in, LD_EN, Q_out) ;
end RTL ;

Q_REGISTER (RTL)

Q_REGISTER_SOURCE_SELECTOR (RTL) REG_MASTER_SLAVE (RTL)

Q_REGISTER (RTL)

79
Q_SHIFT
Deşi aparent simplu (de fapt chiar aşa şi este) , blocul Q_SHIFT mi-a creat cele mai mari probleme
dintre toate blocurile lui CY7C901. Cauzele acestor probleme sunt cele două porturi bidirecţionale, Q3 şi Q0,
ale acestui bloc.
Problemele au apărut pentru că, pe parcursul codului, un port bidirecţional devenea, pe rând, în
funcţie de anumite condiţii, fie port de intrare, fie port de ieşire. Deşi codul iniţial părea corect, nici
simularea presinteză, nici sinteza nu au dat rezultate satisfăcătoare. Trebuie să precizez aici că în nici una
din cele 6 cărţi (indicate în bibliografie) care tratează limbajul VHDL, studiate de mine, nu am găsit măcar
un exemplu care să trateze un circuit cu porturi bidirecţionale.
Soluţia pentru rezolvarea acestor probleme am găsit-o după ce am studiat structura fizică a unui port
bidirecţional. Pentru a transpune această structură fizică într-un cod VHDL, am apelat la un mic truc : am
implementat mai întâi un bloc, pe care l-am numit Q_SHIFT_INTERN, care avea acelaşi aspect şi
funcţionalitate cu blocul Q_SHIFT, cu singura diferenţă, dar esenţială, că fiecare din cele două porturi
bidirecţonale, Q3 şi Q0, au fost înlocuite cu câte două porturi (unul de intrare şi unul de ieşire) şi anume Q3 IN
şi Q3 OUT , respectiv Q0 IN şi Q0 OUT . De fiecare dată când unul din porturile bidirecţionale, de exemplu Q3,
este folosit ca pin de intrare este necesar ca pinul de ieşire asociat, Q3 OUT în acest caz, să fie trecut în starea
de înaltă impedanţă. Apoi blocul Q_SHIFT_INTERN este inclus în blocul Q_SHIFT, având pinii Q3 IN şi
Q3 OUT conectaţi intern la pinul Q3 al lui Q_SHIFT, iar Q0 IN şi Q0 OUT fiind conectaţi la pinul Q0 .
Q_SHIFT_INTERN.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity Q_SHIFT_INTERN is
port ( F : in vec4 ; Q3_in, Q0_in : in std_logic ; Q3_out, Q0_out : out
std_logic ; CNTL : in vec3 ; D : out vec4) ;
end Q_SHIFT_INTERN ;
architecture RTL of Q_SHIFT_INTERN is
begin
process (CNTL, F, Q3_in, Q0_in)
begin
case CNTL is
when RAMQD =>
Q3_out <= 'Z' ;
Q0_out <= F(0) ;
D(2 downto 0) <= F (3 downto 1) ;
D (3) <= Q3_in ;
when RAMQU =>
Q3_out <= F(3) ;
Q0_out <= 'Z' ;
D (3 downto 1) <= F (2 downto 0) ;
D(0) <= Q0_in ;
when others => -- QREG,NOP, RAMA, RAMF, RAMD, RAMU
Q3_out <= '-' ;
Q0_out <= '-' ;
D <= "----" ;
end case ;
end process ;
end RTL ;

80
Q_SHIFT.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use IEEE.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity Q_SHIFT is
port(Q_in : in vec4 ; CNTL : in vec3 ; Q3, Q0 : inout std_logic ; Q_out : out vec4);
end Q_SHIFT ;
architecture RTL of Q_SHIFT is
component Q_SHIFT_INTERN
port (F : in vec4 ; Q3_in, Q0_in : in std_logic ;
Q3_out, Q0_out : out std_logic ; CNTL : in vec3 ; D : out vec4) ;
end component ;
begin
INT_i : Q_SHIFT_INTERN port map (Q_in, Q3, Q0, Q3, Q0, CNTL, Q_out) ;
end RTL ;

Probleme deosebite au apărut şi la realizarea test_bench-ului pentru Q_SHIFT. Astfel, pentru


fiecare caz în care unul din porturile bidirecţionale avea rol de pin de ieşire, a fost necesară aplicarea
nivelului HZ, din exterior, pe acel pin. (se înţelege mai bine de pe formele de undă) .
test_Q_SHIFT.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_arith.all ;
use work.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity test_Q_SHIFT is end ;
architecture test of test_Q_SHIFT is
component Q_SHIFT
port(Q_in : in vec4 ; CNTL : in vec3 ; Q3, Q0 : inout std_logic ; Q_out : out vec4);
end component ;
signal Q_in, Q_out : vec4 ;
signal CNTL : vec3 := "000" ;
signal CNTLv : ALU_destination ; -- pentru vizualizare
signal Q3, Q0 : std_logic ;
signal DATAIN : std_logic_vector (5 downto 0) := "001101" ;
constant TPER : time := 10 ns ;
constant DELAY : time := 5 ns ;
signal test_OK : BOOLEAN := TRUE ;
begin
DUT : Q_SHIFT port map (Q_in, CNTL, Q3, Q0, Q_out) ;
--generare pseudo aleatoare a semnalului DATAIN si, dece, a semnalelor Q_in, Q3, Q0
DATAIN <= DATAIN + 37 after TPER ;
Q_in <= DATAIN (4 downto 1) ;
CNTL <= CNTL + 1 after TPER ;
process (DATAIN, CNTL)
begin
case CNTL is
when RAMQD =>
Q3 <= DATAIN(5) ;
Q0 <= 'Z' ;
when RAMQU =>
Q3 <= 'Z' ;
Q0 <= DATAIN(0) ;
when others => -- QREG,NOP, RAMA, RAMF, RAMD, RAMU
Q3 <= '-' ;
Q0 <= '-' ;
end case ;
end process ;

process
variable DATAIN_var : std_logic_vector (5 downto 0) ;
begin
wait until (DATAIN'event or CNTL'event) ;
DATAIN_var := DATAIN ;
wait for DELAY ;
case CNTL is
when RAMQD =>
if (Q_out = DATAIN_var (5 downto 2) and Q0 = DATAIN_var(1)) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;

81
end if ;
when RAMQU =>
if(Q_out = DATAIN_var(3 downto 0) and Q3 = DATAIN_var (4) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when others =>
test_OK <= TRUE ;
end case ;
end process ;

-- pentru vizualizare
process (CNTL)
begin
case CNTL is
when QREG => CNTLv <= QREGv ;
when NOP => CNTLv <= NOPv ;
when RAMA => CNTLv <= RAMAv ;
when RAMF => CNTLv <= RAMFv ;
when RAMQD => CNTLv <= RAMQDv ;
when RAMD => CNTLv <= RAMDv ;
when RAMQU => CNTLv <= RAMQUv ;
when RAMU => CNTLv <= RAMUv ;
when others => CNTLv <= XXX ;
end case ;
end process ;
end test ;

Q_SHIFT

Q_SHIFT (RTL)

82
RAM_ADDRESSABLE_REGISTERS
Programul de test pentru acest bloc realizează următoarele : Se încarcă pe rând câte o dată (aplicată pe
intrarea B_DATAIN) într-un registru al memoriei (selectat de B_ADDRESS) , ceea ce presupune ca
WR_EN = ‘1’ ; Pentru fiecare dată înscrisă în RAM, scrierea având loc efectiv pe frontul pozitiv al
ceasului, se testează funcţionarea corectă a blocului prin compararea datei de la ieşirea RAMB_DATAOUT
după frontul negativ imediat următor al ceasului cu data aplicată anterior pe intrarea B_DATAIN.
După scrierea cu date a tuturor celor 16 locaţii de memorie, semnalul WR_EN este dezactivat şi în
continuare se testează corectitudinea funcţionării memoriei, prin compararea ieşirilor RAMA_DATAOUT
şi RAMB_DATAOUT cu valorile la care ne aşteptam cunoscând conţinutul memoriei la momentul
respectiv.
test_RAM_ADDRESSABLE_REGISTERS.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.NUMERIC_STD.all ;
use work.packageCY7C901.all ;
entity test_RAM_ADDRESSABLE_REGISTERS is end ;
architecture test of test_RAM_ADDRESSABLE_REGISTERS is
type mem is array (15 downto 0) of vec4 ;
signal ram, buf : mem ;
component RAM_ADDRESSABLE_REGISTERS
port ( CP : in std_logic ; A_ADDRESS, B_ADDRESS, B_DATAIN : in vec4 ;
WR_EN : in std_logic ; RAMA_DATAOUT, RAMB_DATAOUT : out vec4) ;
end component ;
signal CP : std_logic := '1' ;
signal WR_EN : std_logic := '1' ;
signal A, B, B_in : vec4 := "1111" ;
signal A_out, B_out : vec4 ;
constant TPER : time := 50 ns ; -- perioada semnalului de ceas
constant DELAY : time := TPER/16 ;
constant DELAY2 : time := 2 ns ;
signal test_OK : BOOLEAN := TRUE ;
signal TRUC : vec4 ;

begin

DUT : RAM_ADDRESSABLE_REGISTERS port map (CP, A, B, B_in, WR_EN, A_out, B_out) ;


CP <= not CP after TPER / 2 ;
WR_EN <= '1' , '0' after 17.5 * TPER ;
process
begin
buf(0) <= "0101" ;
for k in 1 to 15 loop
wait for 0.01 ns ; -- intarziere minima ; in absenta acesteia ar rezulta o eroare
buf(k) <= buf(k - 1) + 7 ;
end loop ;
end process ;

process
variable B_in_var : vec4 ;
begin
for k in 0 to 15 loop
wait until (CP'event and CP = '0') ;
wait for TPER/8 ;
B_in <= buf(k) ;
wait for 0.1 ns ;
B_in_var := B_in ;
TRUC <= B_in_var ;
end loop ;
end process ;

process
begin
wait until (CP'event and CP = '0') ;
wait for TPER/4 ;
A <= A + 3 ;
B <= B + 1 ;
end process ;

process
begin
wait until (CP'event and CP = '0') ;

83
wait for DELAY ;
case WR_EN is
when '1' =>
if (B_out = TRUC) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when others =>
if (A_out = buf(TO_INTEGER(UNSIGNED(A))) and B_out = buf(TO_INTEGER(UNSIGNED(B)))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
end case ;
end process ;
end test ;

Realizarea descrierii VHDL pentru acest bloc a fost destul de dificilă. Iniţial am înercat să respect
specificaţiile din documentaţie, conform cărora o dată se înscrie în RAM pe palierul LOW al semnalului de
ceas, iar datele apar pe ieşiri pe palierul HIGH al semnalului de ceas. Problemele au apărut pe durata
procesului de sinteză, când au fost generate avertismente de tipul “time loop detected”. Apoi, la simularea
postsinteză, am fost bombardat cu mesaje de eroare ce sesizau violări de timing (setup şi hold) .
Cautând să înţeleg sursa acestor erori, am descoperit că descrierea VHDL a determinat programul
de sinteză să implementeze memoria RAM utilizând latch-uri. Am aflat că aceste latch-uri creează cele mai
mari probleme într-un proiect şi că descrierea VHDL a unui circuit trebuie realizată astfel încât programul
de sinteză să folosească numai bistabili (în locul latch-urilor) la implementarea circuitului respectiv.
Ca urmare, am trcut peste specificaţii şi am modificat descrierea VHDL în sensul că înscrierea
datelor în RAM se face pe frontul pozitiv al semnalului de ceas, iar transferarea datelor pe ieşirile memoriei
RAM se face pe frontul negativ al semnalului de ceas.
În urma acestor modificări au dispărut atât erorile de la sinteză, cât şi cele de la simularea
postsinteză. Trebuie, totuşi, să precizez că, prin înlocuirea latch-urilor cu bistabili, aria circuitului creşte
semnificativ.
RAM_ADDRESSABLE_REGISTERS.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_unsigned.all ;
use work.NUMERIC_STD.all ;
use work.packageCY7C901.all ;
entity RAM_ADDRESSABLE_REGISTERS is
port ( CP : in std_logic ; A_ADDRESS, B_ADDRESS, B_DATAIN : in vec4 ;
WR_EN : in std_logic ; RAMA_DATAOUT, RAMB_DATAOUT : out vec4) ;
end RAM_ADDRESSABLE_REGISTERS ;
architecture RTL of RAM_ADDRESSABLE_REGISTERS is
type mem is array (15 downto 0) of vec4 ;
signal memo : mem ;
begin
process (CP)
begin
if (CP'event and CP = '0') then
RAMA_DATAOUT <= memo(to_integer (unsigned(A_ADDRESS))) ;
RAMB_DATAOUT <= memo(to_integer (unsigned(B_ADDRESS))) ;

end if ;
end process ;

process (CP)
begin

if (CP'event and CP = '1') then


if WR_EN = '1' then
memo(to_integer (unsigned(B_ADDRESS))) <= B_DATAIN ;
end if ;
end if ;
end process ;
end RTL ;
84
RAM_ADDRESSABLE_REGISTERS (RTL) : a) complet ; b) vedere parţială

Operaţiunea de scriere a datelor în RAM (iniţial conţinutul RAM-ului este nedeterminat)

Opearaţiunea de citire a datelor din RAM.

85
RAM_SHIFT
Acest bloc este aproape identic cu Q_SHIFT, observaţiile de la Q_SHIFT fiind deci valabile şi pentru acest
bloc.
test_RAM_SHIFT.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.std_logic_arith.all ;
use work.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity test_RAM_SHIFT is end ;
architecture test of test_RAM_SHIFT is
component RAM_SHIFT is
port(F : in vec4 ; CNTL : in vec3 ; RAM3, RAM0 : inout std_logic ; B : out vec4);
end component ;
signal F, B : vec4 ;
signal CNTL : vec3 := "000" ;
signal CNTLv : ALU_destination ; -- pentru vizualizare
signal RAM3, RAM0 : std_logic ;
signal DATAIN : std_logic_vector (5 downto 0) := "001101" ;
constant TPER : time := 10 ns ;
constant DELAY : time := 5 ns ;
signal test_OK : BOOLEAN := TRUE ;
begin
DUT : RAM_SHIFT port map (F, CNTL, RAM3, RAM0, B) ;
--generare pseudo aleatoare a semnalului DATAIN si, dece, a semnalelor F, RAM3, RAM0
DATAIN <= DATAIN + 37 after TPER ;
F <= DATAIN (4 downto 1) ;
CNTL <= CNTL + 1 after TPER ;
process (DATAIN, CNTL)
begin
case CNTL is
when RAMQD =>
RAM3 <= DATAIN(5) ;
RAM0 <= 'Z' ;
when RAMD =>
RAM3 <= DATAIN(5) ;
RAM0 <= 'Z' ;
when RAMQU =>
RAM3 <= 'Z' ;
RAM0 <= DATAIN(0) ;
when RAMU =>
RAM3 <= 'Z' ;
RAM0 <= DATAIN(0) ;
when others => -- QREG,NOP, RAMA, RAMF, RAMD, RAMU
RAM3 <= '-' ;
RAM0 <= '-' ;
end case ;
end process ;

process
variable DATAIN_var : std_logic_vector (5 downto 0) ;
begin
wait until (DATAIN'event or CNTL'event) ;
DATAIN_var := DATAIN ;
wait for DELAY ;
case CNTL is
when RAMA =>
if (B = DATAIN (4 downto 1) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when RAMF =>
if (B = DATAIN (4 downto 1) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when RAMQD =>
if (B = DATAIN_var (5 downto 2) and RAM0 = DATAIN_var(1)) then
test_OK <= TRUE ;
86
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when RAMD =>
if (B = DATAIN_var (5 downto 2) and RAM0 = DATAIN_var(1)) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when RAMQU =>
if (B = DATAIN_var (3 downto 0) and RAM3 = DATAIN_var (4) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when RAMU =>
if (B = DATAIN_var (3 downto 0) and RAM3 = DATAIN_var (4) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
when others =>
test_OK <= TRUE ;
end case ;
end process ;

-- pentru vizualizare
process (CNTL)
begin
case CNTL is
when QREG => CNTLv <= QREGv ;
when NOP => CNTLv <= NOPv ;
when RAMA => CNTLv <= RAMAv ;
when RAMF => CNTLv <= RAMFv ;
when RAMQD => CNTLv <= RAMQDv ;
when RAMD => CNTLv <= RAMDv ;
when RAMQU => CNTLv <= RAMQUv ;
when RAMU => CNTLv <= RAMUv ;
when others => CNTLv <= XXX ;
end case ;
end process ;

end test ;

RAM_SHIFT_INTERN.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity RAM_SHIFT_INTERN is
port ( F : in vec4 ; RAM3_in, RAM0_in : in std_logic ;
RAM3_out, RAM0_out : out std_logic ; CNTL : in vec3 ; D : out vec4) ;
end RAM_SHIFT_INTERN ;
architecture RTL of RAM_SHIFT_INTERN is
begin
process (CNTL, F, RAM3_in, RAM0_in)
begin
case CNTL is
when RAMA =>
D <= F ;
RAM3_out <= '-' ;
RAM0_out <= '-' ;
when RAMF =>
D <= F ;
RAM3_out <= '-' ;
RAM0_out <= '-' ;
when RAMQD =>
RAM3_out <= 'Z' ;
RAM0_out <= F(0) ;
D(2 downto 0) <= F (3 downto 1) ;

87
D (3) <= RAM3_in ;
when RAMD =>
RAM3_out <= 'Z' ;
RAM0_out <= F(0) ;
D(2 downto 0) <= F (3 downto 1) ;
D (3) <= RAM3_in ;
when RAMQU =>
RAM3_out <= F(3) ;
RAM0_out <= 'Z' ;
D (3 downto 1) <= F (2 downto 0) ;
D(0) <= RAM0_in ;
when RAMU =>
RAM3_out <= F(3) ;
RAM0_out <= 'Z' ;
D (3 downto 1) <= F (2 downto 0) ;
D(0) <= RAM0_in ;
when others => -- QREG si NOP
RAM3_out <= '-' ;
RAM0_out <= '-' ;
D <= "----" ;
end case ;
end process ;
end RTL ;

RAM_SHIFT.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity RAM_SHIFT is
port(F : in vec4 ; CNTL : in vec3 ; RAM3, RAM0 : inout std_logic ; B : out vec4);
end RAM_SHIFT ;
architecture RTL of RAM_SHIFT is
component RAM_SHIFT_INTERN
port ( F : in vec4 ; RAM3_in, RAM0_in : in std_logic ;
RAM3_out, RAM0_out : out std_logic ; CNTL : in vec3 ; D : out vec4) ;
end component ;
begin
INT_i : RAM_SHIFT_INTERN port map (F, RAM3, RAM0, RAM3, RAM0, CNTL, B) ;
end RTL ;

RAM_SHIFT (RTL)

ALU_DATA_SOURCE_SELECTOR
Acest bloc nu a ridicat probleme deosebite, descrierea VHDL a acestuia reprezentând transpunerea în cod
VHDL a tabelului 2.
test_ALU_DATA_SOURCE_SELECTOR.vhd
library IEEE, arithmetic ;
use IEEE.std_logic_1164.all ;
use IEEE.std_logic_unsigned.all ;
use arithmetic.std_logic_arith.all ;
use work.packageCY7C901.all ;
entity test_ALU_DATA_SOURCE_SELECTOR is end ;
88
architecture test of test_ALU_DATA_SOURCE_SELECTOR is
component ALU_DATA_SOURCE_SELECTOR
port (D, A, B, Q : in vec4 ; CNTL : in vec3 ;R, S : out vec4) ;
end component ;
signal D : vec4 := "1010" ;
signal A : vec4 := "1100" ;
signal B : vec4 := "1001" ;
signal Q : vec4 := "0011" ;
signal R, S : vec4 ;
signal R_t, S_t : vec4 ;
signal CNTL : vec3 := "000";
signal CNTLv : ALU_source ; -- pentru vizualizare
constant TPER : time := 20 ns ;
constant DELAY : time := 5 ns ;
signal test_OK : BOOLEAN := TRUE ;
begin

DUT : ALU_DATA_SOURCE_SELECTOR port map (D, A, B, Q, CNTL, R, S) ;


-- generare pseudo aleatoare a semnalelor D, A, B, Q
D <= (D + 4) xnor (D rol 1) after TPER ;
A <= (D + 8) xnor (A rol 1) after TPER ;
B <= (D + 6) xor (B rol 1) after TPER ;
Q <= (Q + 9) xnor (Q rol 1) after TPER ;

-- generarea semnalului CNTL


CNTL <= CNTL + 1 after TPER ;

process
begin
wait until (D'event or A'event or B'event or Q'event or CNTL'event) ;
case CNTL is
when AQ =>
R_t <= A ;
S_t <= Q ;
when AB =>
R_t <= A ;
S_t <= B ;
when ZQ =>
R_t <= "0000" ;
S_t <= Q ;
when ZB =>
R_t <= "0000" ;
S_t <= B ;
when ZA =>
R_t <= "0000" ;
S_t <= A ;
when DA =>
R_t <= D ;
S_t <= A ;
when DQ =>
R_t <= D ;
S_t <= Q ;
when others => -- DZ
R_t <= D ;
S_t <= "0000" ;
end case ;
end process ;

process
begin
wait until (D'event or A'event or B'event or Q'event or CNTL'event) ;
wait for DELAY ;
if (R_t = R and S_t = S) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
end process ;
-- pentru vizualizare
process (CNTL)
begin
case CNTL is
when AQ => CNTLv <= AQv ;
when AB => CNTLv <= ABv ;
when ZQ => CNTLv <= ZQv ;
when ZB => CNTLv <= ZBv ;
89
when ZA => CNTLv <= ZAv ;
when DA => CNTLv <= DAv ;
when DQ => CNTLv <= DQv ;
when DZ => CNTLv <= DZv ;
when others => CNTLv <= XXX ;
end case ;
end process ;
end test ;

ALU_DATA_SOURCE_SELECTOR.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity ALU_DATA_SOURCE_SELECTOR is
port (D, A, B, Q : in vec4 ; CNTL : in vec3 ;R, S : out vec4) ;
end ALU_DATA_SOURCE_SELECTOR ;
architecture RTL of ALU_DATA_SOURCE_SELECTOR is
begin
process (D, A, B, Q, CNTL)
begin
case CNTL is
when AQ =>
R <= A ;
S <= Q ;
when AB =>
R <= A ;
S <= B ;
when ZQ =>
R <= "0000" ;
S <= Q ;
when ZB =>
R <= "0000" ;
S <= B ;
when ZA =>
R <= "0000" ;
S <= A ;
when DA =>
R <= D ;
S <= A ;
when DQ =>
R <= D ;
S <= Q ;
when others => -- DZ
R <= D ;
S <= "0000" ;
end case ;
end process ;
end RTL ;

ALU_DATA_SOURCE_SELECTOR (RTL)

90
OUTPUT_DATA_SELECTOR
Nici acest bloc nu a ridicat probleme deosebite, reprezentând 4 multiplexoare de 2 intrări având pe ieşiri
bufere three-states.
test_OUTPUT_DATA_CONTROL.vhd
library IEEE, arithmetic ;
use IEEE.std_logic_1164.all ;
use arithmetic.std_logic_arith.all ;
use IEEE.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity test_OUTPUT_DATA_SELECTOR is end ;
architecture test of test_OUTPUT_DATA_SELECTOR is
component OUTPUT_DATA_SELECTOR
port (A, F : in vec4 ; nOE : in std_logic ; CNTL : in vec3 ; Y : out vec4) ;
end component ;
signal A, F : vec4 := "1010" ;
signal Y, Y_t : vec4 ;
signal nOE : std_logic := '0' ;
signal CNTL : vec3 := "000" ;
signal CNTLv : ALU_destination ; -- pentru vizualizare
constant TPER : time := 20 ns ;
constant DELAY : time := 5 ns ;
signal test_OK : BOOLEAN := TRUE ;
begin
DUT : OUTPUT_DATA_SELECTOR port map (A, F, nOE, CNTL, Y) ;

-- generare pseudo aleatoare a semanlelor A si F


A <= (A + 9) xnor (A rol 2) after TPER ;
F <= (F +3) xnor (F rol 3) after TPER ;
nOE <= not nOE after 9 * TPER ;
CNTL <= CNTL + 1 after TPER ;
process (A, F, nOE, CNTL)
begin
case nOE is
when '0' =>
case CNTL is
when RAMA =>
Y_t <= A ;
when others =>
Y_t <= F ;
end case ;
when others =>
Y_t <= "ZZZZ" ;
end case ;
end process ;

process
begin
wait until (A'event or F'event or nOE'event or CNTL'event) ;
wait for DELAY ;
if (Y_t = Y) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
end process ;

91
-- pentru vizualizare
process (CNTL)
begin
case CNTL is
when QREG => CNTLv <= QREGv ;
when NOP => CNTLv <= NOPv ;
when RAMA => CNTLv <= RAMAv ;
when RAMF => CNTLv <= RAMFv ;
when RAMQD => CNTLv <= RAMQDv ;
when RAMD => CNTLv <= RAMDv ;
when RAMQU => CNTLv <= RAMQUv ;
when RAMU => CNTLv <= RAMUv ;
when others => CNTLv <= XXX ;
end case ;
end process ;
end test ;

OUTPUT_DATA_SELECTOR.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity OUTPUT_DATA_SELECTOR is
port (A, F : in vec4 ; nOE : in std_logic ; CNTL : in vec3 ; Y : out vec4) ;
end OUTPUT_DATA_SELECTOR ;
architecture RTL of OUTPUT_DATA_SELECTOR is
begin
process (A, F, nOE, CNTL)
begin
case nOE is
when '0' =>
case CNTL is
when RAMA =>
Y <= A ;
when others =>
Y <= F ;
end case ;
when others =>
Y <= "ZZZZ" ;
end case ;
end process ;
end RTL ;

OUTPUT_DATA_SELECTOR (RTL)

92
CY7C901
După descrierea tuturor blocurilor componente, acestea trebuie asamblate astfel încât, împreună, să
realizeze funcţionalitatea circuitului CY7C901.
Pe lângă blocurile descrise anterior, mai este necesară logica pentru semnalul intern WR_EN şi
pentru ieşirile F3 (flagul de semn) şi F_eq_0 (flagul de zero) .
CY7C901.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use work.packageCY7C901.all ;
entity CY7C901 is
port(
A : in vec4 ;
B : in vec4 ;
I : in std_logic_vector (8 downto 0) ;
D : in vec4 ;
Y : out vec4 ;
nOE : in std_logic ;
CP : in std_logic ;
Q3, RAM3 : inout std_logic ;
Q0, RAM0 : inout std_logic ;
Cn : in std_logic ;
Cn4 : out std_logic ;
nG, nP : out std_logic ;
OVR : out std_logic ;
F_eq_0 : out std_logic ;
F3 : out std_logic
) ;
end CY7C901 ;
architecture STRUCTURAL of CY7C901 is
signal I_210, I_543, I_876 : vec3 ;
signal A_BUS, B_BUS, F_BUS, R_BUS, S_BUS, Q_BUS, B_DATAIN, Q_SHIFT_OUT : vec4 ;
signal WR_EN : std_logic ;
component ALU
port (R, S : in vec4 ; CNTL : in vec3 ; Cn : in std_logic ; F : out vec4 ;
nG, nP, Cn4, OVR : out std_logic) ;
end component ;

component ALU_DATA_SOURCE_SELECTOR
port (D, A, B, Q : in vec4 ; CNTL : in vec3 ;R, S : out vec4) ;
end component ;

component OUTPUT_DATA_SELECTOR
port (A, F : in vec4 ; nOE : in std_logic ; CNTL : in vec3 ; Y : out vec4) ;
end component ;

component RAM_SHIFT
port(F : in vec4 ; CNTL : in vec3 ; RAM3, RAM0 : inout std_logic ; B : out vec4);
end component ;

component RAM_ADDRESSABLE_REGISTERS
port ( CP : in std_logic ; A_ADDRESS, B_ADDRESS, B_DATAIN : in vec4 ;
WR_EN : in std_logic ; RAMA_DATAOUT, RAMB_DATAOUT : out vec4) ;
end component ;

component Q_SHIFT
port(Q_in : in vec4 ; CNTL : in vec3 ; Q3, Q0 : inout std_logic ; Q_out : out vec4);
end component ;

component Q_REGISTER
port (CP : in std_logic ; F, Q : in vec4 ; CNTL : in vec3 ; Q_out : out vec4) ;
end component ;

begin
I_210 <= I (2 downto 0) ;
I_543 <= I (5 downto 3) ;
I_876 <= I (8 downto 6) ;
process (I_876)
begin
case I_876 is
when QREG =>
WR_EN <= '0' ;
when NOP =>
WR_EN <= '0' ;
when others =>
WR_EN <= '1' ;
93
end case ;
end process ;
ALU_i : ALU port map (R_BUS, S_BUS, I_543, Cn, F_bus, nG, nP, Cn4,OVR) ;
ALU_D_S_SEL_i : ALU_DATA_SOURCE_SELECTOR port map (D, A_BUS, B_BUS, Q_BUS, I_210, R_BUS, S_BUS) ;
OUT_D_SEL_i : OUTPUT_DATA_SELECTOR port map (A_BUS, F_BUS, nOE, I_876, Y) ;
RAM_SHIFT_i : RAM_SHIFT port map (F_BUS, I_876, RAM3, RAM0, B_DATAIN) ;
RAM_REG_i : RAM_ADDRESSABLE_REGISTERS port map (CP, A, B, B_DATAIN, WR_EN, A_BUS, B_BUS) ;
Q_SHIFT_i : Q_SHIFT port map (Q_BUS, I_876, Q3, Q0, Q_SHIFT_OUT) ;
Q_REG_i : Q_REGISTER port map (CP, F_BUS, Q_SHIFT_OUT, I_876, Q_BUS) ;
F_eq_0 <= not (F_BUS(3) or F_BUS(2) or F_BUS(1) or F_BUS(0)) ;
F3 <= F_BUS(3) ;
end STRUCTURAL ;

CY7C901 – diagrama bloc obţinută în urma asamblării blocurilor componente

Sinteza CY7C901
Pentru sinteza circuitului CY7C901, rămân valabile cele spuse la sinteza circuitului CY7C910. Voi
reda aici doar fişierele “compile.scr”, “CY7C901_timing_report.txt” şi “CY7C901_area_report.txt”.
compile.scr
design = CY7C901
analyze -library work -format vhdl sources/packageCY7C901.vhd
analyze -library work -format vhdl sources/ALU.vhd
analyze -library work -format vhdl sources/ALU_DATA_SOURCE_SELECTOR.vhd
analyze -library work -format vhdl sources/OUTPUT_DATA_SELECTOR.vhd
analyze -library work -format vhdl sources/REG_MASTER_SLAVE.vhd
analyze -library work -format vhdl sources/Q_REGISTER_SOURCE_SEL.vhd
analyze -library work -format vhdl sources/Q_REGISTER.vhd
analyze -library work -format vhdl sources/Q_SHIFT_INTERN.vhd
analyze -library work -format vhdl sources/Q_SHIFT.vhd
analyze -library work -format vhdl sources/RAM_ADDRESSABLE_REGISTERS.vhd
analyze -library work -format vhdl sources/RAM_SHIFT_INTERN.vhd
analyze -library work -format vhdl sources/RAM_SHIFT.vhd
analyze -library work -format vhdl sources/ + design + ".vhd"
elaborate -library work design

set_wire_load_model -library tcb773pwc -name TSMC16K_Conservative


set_wire_load_mode enclosed

create_clock -name CLK -period 24 -waveform { 0 12 } { CP }


set_output_delay 5 -clock CLK all_outputs()
set_dont_touch_network { CLK }

compile -map_effort high


create_schematic -all

report -area > "reports/" + design + "_area_report.txt"


report -timing > "reports/" + design + "_timing_report.txt"
94
check_design
check_timing

change_names -rules asic_core_rules -verbose -hierarchy

write -f db -hier -o "db/" + design + "_mapped.db"


write_sdf "netlist/" + design + "_mapped.sdf"
write -format vhdl -hierarchy -output "netlist/" + design + "_mapped.vhd"
write -format verilog -hierarchy -output "netlist/" + design + "_mapped.v"

CY7C901_timing_report.txt

****************************************
Report : timing
-path full
-delay max
-max_paths 1
Design : CY7C901
Version: 2000.05
Date : Mon May 19 23:57:40 2003
****************************************

Operating Conditions: WCCOM Library: tcb773pwc


Wire Load Model Mode: enclosed

Startpoint: RAM_REG_i/RAMB_DATAOUT_reg[0]
(rising edge-triggered flip-flop clocked by CLK')
Endpoint: Y[3] (output port clocked by CLK)
Path Group: CLK
Path Type: max

Des/Clust/Port Wire Load Model Library


------------------------------------------------
RAM_ADDRESSABLE_REGISTERS
TSMC8K_Conservative tcb773pwc
CY7C901 TSMC16K_Conservative tcb773pwc
ALU_DATA_SOURCE_SELECTOR
TSMC8K_Conservative tcb773pwc
ALU TSMC8K_Conservative tcb773pwc
OUTPUT_DATA_SELECTOR
TSMC8K_Conservative tcb773pwc

Point Incr Path


--------------------------------------------------------------------------
clock CLK' (rise edge) 12.00 12.00
clock network delay (ideal) 0.00 12.00
RAM_REG_i/RAMB_DATAOUT_reg[0]/CP (DFF1) 0.00 12.00 r
RAM_REG_i/RAMB_DATAOUT_reg[0]/Q (DFF1) 0.77 12.77 r
RAM_REG_i/RAMB_DATAOUT[0] (RAM_ADDRESSABLE_REGISTERS)
0.00 12.77 r
ALU_D_S_SEL_i/B[0] (ALU_DATA_SOURCE_SELECTOR) 0.00 12.77 r
ALU_D_S_SEL_i/U82/ZN (MAOI22D2) 0.74 13.51 f
ALU_D_S_SEL_i/U83/ZN (OAI21D1H) 0.22 13.73 r
ALU_D_S_SEL_i/S[0] (ALU_DATA_SOURCE_SELECTOR) 0.00 13.73 r
ALU_i/S[0] (ALU) 0.00 13.73 r
ALU_i/U472/ZN (INV3) 0.21 13.94 f
ALU_i/U471/ZN (INV1) 0.29 14.23 r
ALU_i/U587/ZN (ND2D1H) 0.26 14.50 f
ALU_i/U593/ZN (OAI21D1H) 0.39 14.89 r
ALU_i/U480/ZN (OAI21D1H) 0.35 15.24 f
ALU_i/U479/ZN (OAI21D1H) 0.20 15.45 r
ALU_i/U574/ZN (INV1) 0.28 15.73 f
ALU_i/U483/ZN (OAI32D1H) 0.40 16.13 r
ALU_i/U482/ZN (IND3D0) 0.30 16.43 f
ALU_i/U584/Z (MUX2D2) 0.68 17.11 f
ALU_i/U469/ZN (ND3D1H) 0.19 17.30 r
ALU_i/U488/ZN (OAI21D1H) 0.24 17.54 f
ALU_i/U485/ZN (AOI21D1H) 0.33 17.87 r
ALU_i/U486/ZN (INV3) 0.19 18.06 f
ALU_i/F[3] (ALU) 0.00 18.06 f
OUT_D_SEL_i/F[3] (OUTPUT_DATA_SELECTOR) 0.00 18.06 f
OUT_D_SEL_i/U30/Z (MUX2D2) 0.56 18.62 f
OUT_D_SEL_i/U31/ZN (INV1) 0.18 18.81 r
OUT_D_SEL_i/Y_tri[3]/ZN (INVTN1) 0.19 19.00 f
OUT_D_SEL_i/Y[3] (OUTPUT_DATA_SELECTOR) 0.00 19.00 f
Y[3] (out) 0.00 19.00 f

95
data arrival time 19.00

clock CLK (rise edge) 24.00 24.00


clock network delay (ideal) 0.00 24.00
output external delay -5.00 19.00
data required time 19.00
--------------------------------------------------------------------------
data required time 19.00
data arrival time -19.00
--------------------------------------------------------------------------
slack (MET) 0.00

CY7C901_area_report.txt
report_area
Information: Updating design information... (UID-85)

****************************************
Report : area
Design : CY7C901
Version: 2000.05
Date : Mon May 19 23:57:40 2003
****************************************

Library(s) Used:

tcb773pwc (File: C:/Synopsys/libraries/syn/tcb773pwc.db)

Number of ports: 38
Number of nets: 70
Number of cells: 9
Number of references: 9

Combinational area: 47932.500000


Noncombinational area: 33180.000000
Net Interconnect area: undefined (Wire load has zero net area)

Total cell area: 81112.500000


Total area: undefined

Testarea circuitului CY7C901


După cum era de aşteptat, realizarea programului de test pentru circuitul CY7C901 a constituit una din cele
mai dificile sarcini ale proiectului. În primul rând, o testare completă a circuitului nu ar fi fost posibilă, atât
din cauza numărului destul de mare de intrări, cât, mai ales, din cauza caracterului secvenţial al circuitului.
Ca urmare, a trebuit să găsesc o soluţie de testare a circuitului care, printr-un număr relativ mic de vectori
de test, să pună circuitul în aproape toate tipurile de situaţii posibile.Prima etapă a testării este verificarea
RAM-ului. Mai întâi se încarcă un set de 16 date în RAM ; fiecare dată care se încarcă în RAM trebuie să
fie aplicată pe intrarea de date D şi trebuie să ajungă nemodificată la intrarea blocului RAM_SHIFT, ceea
ce presupune ca instrucţiunea aplicată circuitului să determine: a) cele 2 ieşiri ale
ALU_DATA_SOURCE_SELECTOR să fie D şi ZERO ; b) operaţia executată de ALU să fie adunarea
(ADD ; în plus, trebuie ca Cn să fie LOW) ; c) instrucţiunea de control al destinaţiei ieşirii ALU să fie :
RAMA, RAMF, RAMQD, RAMD, RAMQU sau RAMU. Pe durata acestei prime etape se testează, prin
intermediul ieşirii F a lui CY7C901, dacă datele introduse din exterior au ajuns corect (nemodifiate) la
ieşirea ALU (ceea ce presupune, în plus, ca semnalul nOE să fie pe nivel LOW) . Am testat încărcarea
memoriei pentru fiecare din instrucţiunile de încărcare ; aceasta a necesitat calcularea manuală a
conţinutului memoriei după fiecare operaţiune de încărcare, în scopul comparării rezultatelor teoretice cu
cele experimentale.
Testarea ALU-lui s-a realizat astfel : cu datele aflate la un moment dat în memorie se execută cele 8
operaţii ale ALU, fiecare operaţie executându-se pentru 16 perechi de date din memorie.
Testarea blocurilor Q_REGISTER şi Q_SHIFT a condus la modificarea conţinutului memoriei RAM, ceea
ce a necesitat alte calcule manuale.
În acest test_bench am folosit o variabilă, N_CK (în program N_CK este declarat ca semnal, întrucât o
variabilă poate fi declarată doar în interiorul unui proces, fiind vizibilă doar în acel proces) , care reprezintă
numărul de ordine al ciclului de ceas curent.
Pentru evaluarea corectitudinii funcţionării circuitului, am folosit două variabile (declarate, de asemenea, ca
96
semnale) : test_OK şi test_OK1. Cu test_OK se testează dacă operaţiunile de scriere/citire a memoriei se
execută corect. Valoarea lui test_OK1 depinde atât de valoarea lui test_OK, cât şi de corectitudinea
executării operaţiilor aritmetice şi logice.
test_CY7C901.vhd
library IEEE ;
use IEEE.std_logic_1164.all ;
use IEEE.std_logic_unsigned.all ;
use work.packageCY7C901.all ;
entity test_CY7C901 is end ;

architecture test of test_CY7C901 is


component CY7C901
port(
A : in vec4 ;
B : in vec4 ;
I : in std_logic_vector (8 downto 0) ;
D : in vec4 ;
Y : out vec4 ;
nOE : in std_logic ;
CP : in std_logic ;
Q3, RAM3 : inout std_logic ;
Q0, RAM0 : inout std_logic ;
Cn : in std_logic ;
Cn4 : out std_logic ;
nG, nP : out std_logic ;
OVR : out std_logic ;
F_eq_0 : out std_logic ;
F3 : out std_logic
) ;
end component ;

signal N_CK : integer := 0 ; -- indica perioada de ceas curenta


signal A, B : vec4 := "0000" ;
signal D : vec4 := "0101" ;
signal Y : vec4 ;
signal I : std_logic_vector (8 downto 0) ;
signal Cn4, nG, nP, OVR, F_eq_0, F3 : std_logic ;
signal test_OK, test_OK1 : BOOLEAN := TRUE ;
signal Q3, Q0, RAM3, RAM0 : std_logic := '0' ;
signal nOE, Cn : std_logic := '0' ;
signal CP : std_logic := '1' ;
signal R : vec4 := "0101" ;
signal S : vec4 := "0000" ;
signal P, G : vec4 ;

signal F_eq_0_t : std_logic ;


signal nG_t : std_logic := '1' ;
signal nP_t : std_logic := '1' ;
signal OVR_t : std_logic := '0' ;
signal Cn4_t : std_logic := '0' ;
signal F3_t : std_logic := '0' ;
signal F_t : vec4 := "0101" ;
signal Y_t : vec4 := "0101" ;
signal C4, C3 : std_logic ;
constant TPER : time :=40 ns ;
constant HOLD : time := 10 ns ;
constant DELAY : time := 15 ns ;
constant DELAYMIN : time := 0.1 ns ;
type mem is array (0 to 15) of vec4 ;
signal ram_var : mem := ("0101", "0011", "1011", "0000", "1001", "1000", "0001",
"1111", "0100", "1011", "0010", "0110", "1110", "1100", "0011", "1011") ;
-- in ram_var sunt stocate datele ce vor fi aplicate pe intrarile D si inscrise in
-- registri in prima faza
signal ram_var2 : mem := ("0010", "0001", "0101", "1000", "1100", "1100", "0000",
"0111", "1000", "0110", "0101", "1101", "1101", "1000", "0110", "0110") ;
-- in ram_var2 sunt stocate datele ce ar trebui sa fie inscrise in registri in urma
-- operatiilor de extragere, deplasare si rescriere a datelor din registri
signal Q_var : mem := ("0001", "1000", "1100", "1110", "1111", "0111", "0011",
"0001", "0010", "0100", "1000", "0000", "0001", "0011", "0111", "1111") ;
signal ram_var3 : mem := ("0010", "0000", "0100", "0110", "0111", "1111", "1011",
"1001", "0011", "0101", "1001", "0001", "0000", "0010", "0110", "1110") ;
-- Q_var i ram_var3 sunt folosite la testarea blocului Q_REGISTER
-- semnalele pentru vizualizare
signal ALU_DESTINATIONv : ALU_destination ;
signal ALU_SOURCEv : ALU_source ;
signal ALU_INSTRUCTIONv : ALU_instruction ;
97
begin
process
begin
wait until (CP'event and CP = '1') ;
N_CK <= N_CK + 1 ;
end process ;
DUT : CY7C901 port map (A, B, I, D, Y, nOE, CP,Q3, RAM3, Q0, RAM0, Cn, Cn4, nG, nP,
OVR, F_eq_0, F3) ;
-- in primele 16 perioade de ceas se incarca cei 16 registri RAM cu date introduse de
-- la intrarile D
CP <= not CP after TPER / 2 ;
process
begin
wait until (CP'event and CP = '1') ;
wait for HOLD ;
B <= B + 1 ;
A <= A + 3 ;
end process ;
RAM3 <= 'Z', '0' after (16 * TPER + HOLD) , '1' after (19 * TPER + HOLD) , '0' after
(22 * TPER + HOLD) , 'Z' after (24 * TPER + HOLD) , '0' after (177 * TPER +
HOLD) , '1' after (181 * TPER + HOLD) , 'Z' after (184 * TPER + HOLD) ;
RAM0 <= 'Z', '0' after (24 * TPER + HOLD) , '1' after (26 * TPER + HOLD) , '0' after
(29 * TPER + HOLD) , 'Z' after (32 * TPER + HOLD) , '1' after (184 * TPER +
HOLD) , '0' after (188 * TPER + HOLD) , 'Z' after (192 * TPER + HOLD) ;
Q3 <= 'Z', '1' after (177 * TPER + HOLD) , '0' after (181 * TPER + HOLD) , 'Z' after
(184 * TPER + HOLD) ;
Q0 <= 'Z', '0' after (184 * TPER + HOLD) , '1' after (188 * TPER + HOLD) , 'Z' after
(192 * TPER + HOLD) ;

process
begin
wait until (CP'event and CP = '1') ;
wait for HOLD ;
if (N_CK <= 47) then
Cn <= '0' ;
elsif (N_CK <= 175) then
Cn <= B(1) ;
else
Cn <= '0' ;
end if ;
end process ;
process
begin
wait until (CP'event and CP = '1') ;
wait for HOLD ;
wait for DELAYMIN ;
if (N_CK <= 15) then
D <= ram_var (N_CK) ;
elsif (N_CK <= 31) then
D <= ram_var (N_CK - 16) ;
else
D <= "0001" ;
end if ;
end process ;

I <= "011000111" ,
-- RAMF ADD DZ <=> datele aplicate pe intrarea D sunt scoase pe iesirea Y si memorate
-- in registri la adresa selectata de intrarea B
"100000111" after (16 * TPER + HOLD) ,
-- RAMQD ADD DZ <=> datele aplicate pe intrarea D sunt scoase pe iesirea Y si memorate
-- in registri deplasate spre dreapta cu un bit
"101000111" after (20 * TPER + HOLD) ,
-- RAMD ADD DZ <=> datele aplicate pe intrarea D sunt scoase pe iesirea Y si memorate
-- in registri deplasate spre dreapta cu un bit
"110000111" after (24 * TPER + HOLD) ,
-- RAMQU ADD DZ <=> datele aplicate pe intrarea D sunt scoase pe iesirea Y si memorate
-- in registri deplasate spre stanga cu un bit
"111000111" after (28 * TPER + HOLD) ,
-- RAMU ADD DZ <=> datele aplicate pe intrarea D sunt scoase pe iesirea Y si memorate
-- in registri deplasate spre stanga cu un bit
"001000011" after (32 * TPER + HOLD) ,
-- NOP ADD ZB <=> datele memorate in registri sunt scoase la iesirea Y
"001000001" after (48 * TPER + HOLD) ,
-- NOP ADD AB <=> se executa operatia ADD intre continuturile a cate doi registri
-- selectati de datele aplicate pe intrarile A si D
"001001001" after (64 * TPER + HOLD) ,
-- NOP SUBR AB <=> se executa operatia SUBR intre continutul registrului adresat de B
-- si continutul registrului adresat de A
98
"001010001" after (80 * TPER + HOLD) ,
-- NOP SUBS AB <=> se executa operatia SUBS intre continutul registrului adresat de A
--si continutul registrului adresat de B
"001011001" after (96 * TPER + HOLD) ,
-- NOP OR AB <=> se executa operatia OR intre continutul registrului adresat de A si
-- continutul registrului adresat de B
"001100001" after (112 * TPER + HOLD) ,
-- NOP AND AB <=> se executa operatia AND intre continutul registrului adresat de A si
-- continutul registrului adresat de B
"001101001" after (128 * TPER + HOLD) ,
-- NOP NOTRS AB <=> se executa operatia AND intre continutul negat al registrului
-- adresat de A si continutul registrului adresat de B
"001110001" after (144 * TPER + HOLD) ,
-- NOP EXOR AB <=> se executa operatia XOR intre continutul registrului adresat de A –
-- si continutul registrului adresat de B
"001111001" after (160 * TPER + HOLD) ,
-- NOP EXNOR AB <=> se executa operatia XNOR intre continutul registrului adresat de A
--si continutul registrului adresat de B
"000000111" after (176 * TPER + HOLD) ,
-- QREG ADD DZ <=> se incarca Q_REGISTER cu valoarea lui D si apoi aceasta este scoasa la iesirea Y
"100000010" after (177 * TPER + HOLD) ,
-- RAMQD ADD ZQ <=> Q <= F/2 si se scoate la iesirea Y
"110000010" after (184* TPER + HOLD) ,
-- RAMQU ADD ZQ <=> Q <= 2F si se scoate la iesirea Y
"001000001" after (192 * TPER + HOLD)
-- NOP ADD AB <=> se executa operatia ADD intre continuturile a cate doi registri
-- selectati de datele aplicate pe intrarile A si D
;

process
begin
wait until (CP'event and CP = '0') ;
wait for DELAY ;
if (N_CK <= 15) then
if (Y = ram_var (N_CK) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 31) then
if (Y = ram_var (N_CK - 16) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 47) then
if (Y = ram_var2 (N_CK - 32) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 63) then
if (Y = (ram_var2(CONV_INTEGER(A)) + ram_var2(CONV_INTEGER(B)) + Cn)) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 79) then
if (Y = (ram_var2(CONV_INTEGER(B)) - ram_var2(CONV_INTEGER(A)) - (not Cn)) ) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 95) then
if (Y = (ram_var2(CONV_INTEGER(A)) - ram_var2(CONV_INTEGER(B)) - (not Cn))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
99
report " EROARE"
severity ERROR ;
end if ;

elsif (N_CK <= 111) then


if (Y = (ram_var2(CONV_INTEGER(A)) or ram_var2(CONV_INTEGER(B)))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 127) then
if (Y = (ram_var2(CONV_INTEGER(A)) and ram_var2(CONV_INTEGER(B)))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 143) then
if (Y = ((not(ram_var2(CONV_INTEGER (A)))) and ram_var2(CONV_INTEGER(B)))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 159) then
if (Y = (ram_var2(CONV_INTEGER(A)) xor ram_var2(CONV_INTEGER(B)))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 175) then
if (Y = (ram_var2(CONV_INTEGER(A)) xnor ram_var2(CONV_INTEGER(B)))) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 177) then
if (Y = Q_var (0) ) then
test_OK <= test_OK ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 183) then
if ( (Y = Q_var (N_CK - 177) ) and (Q0 = Q_var (N_CK - 177)(0)) ) then
test_OK <= test_OK ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK <= 191) then
if ( (Y = Q_var (N_CK - 177) ) and (Q3 = Q_var (N_CK - 177)(3)) ) then
test_OK <= test_OK ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
elsif (N_CK >= 192) then
if (Y = (ram_var3(CONV_INTEGER(A)) + ram_var3(CONV_INTEGER(B)) + Cn)) then
test_OK <= TRUE ;
else
test_OK <= FALSE ;
report " EROARE"
severity ERROR ;
end if ;
end if ;
end process ;
100
process
begin
wait until (CP'event and CP = '1') ;
wait for HOLD ;
wait for DELAYMIN/2 ;
if (N_CK <= 31) then
S <= "0000" ;
R <= ram_var (CONV_INTEGER (B) ) ;
elsif (N_CK <= 47) then
R <= "0000" ;
S <= ram_var2 (CONV_INTEGER (B)) ;
elsif (N_CK <= 175) then
R <= ram_var2 (CONV_INTEGER (A) ) ;
S <= ram_var2 (CONV_INTEGER (B) ) ;
elsif (N_CK <= 177) then
R <= "0000" ;
S <= Q_var (0) ;
elsif (N_CK <= 191) then
R <= "0000";
S <= Q_var (N_CK - 177) ;
elsif (N_CK >= 192) then
R <= ram_var3 (CONV_INTEGER (A) ) ;
S <= ram_var3 (CONV_INTEGER (B) ) ;
end if ;
end process ;

process
begin
wait until (CP'event and CP = '1') ;
wait for HOLD ;
wait for DELAYMIN ; -- altfel nu s-ar folosi noile valori ale R si S
case I (5 downto 3) is
when ADD_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when SUBR_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when SUBS_i =>
for k in 0 to 3 loop
P(k) <= R(k) or (not S(k)) ;
G(k) <= R(k) and (not S(k)) ;
end loop ;
when OR_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when AND_i =>
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;
when NOTRS_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when EXOR_i =>
for k in 0 to 3 loop
P(k) <= (not R(k)) or S(k) ;
G(k) <= (not R(k)) and S(k) ;
end loop ;
when others => -- EXNOR_i
for k in 0 to 3 loop
P(k) <= R(k) or S(k) ;
G(k) <= R(k) and S(k) ;
end loop ;

end case ;
end process ;

101
C4 <= G(3) or (P(3) and G(3)) or (P(3) and P(2) and G(1)) or (P(3) and P(2) and G(0))
or (P(3) and P(2) and P(1) and P(0) and Cn) ;
C3 <= G(2) or (P(2) and G(1)) or (P(2) and P(1) and G(0)) or (P(2) and P(1) and P(0) and Cn);

process
begin
wait until (CP'event and CP = '1') ;
wait for HOLD ;
wait for 2 * DELAYMIN ;
case I (5 downto 3) is
when ADD_i =>
F_t <= R + S + Cn;
nP_t <= not (P(3) and P(2) and P(1) and P(0)) ;
nG_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3)
and P(2) and P(1) and G(0)) ) ;
Cn4_t <= C4 ;
OVR_t <= C3 xor C4 ;
when SUBR_i =>
F_t <= S - R - (not Cn) ;
nP_t <= not (P(3) and P(2) and P(1) and P(0)) ;
nG_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3)
and P(2) and P(1) and G(0)) ) ;
Cn4_t <= C4 ;
OVR_t <= C3 xor C4 ;
when SUBS_i =>
F_t <= R - S - (not Cn) ;
nP_t <= not (P(3) and P(2) and P(1) and P(0)) ;
nG_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3)
and P(2) and P(1) and G(0)) ) ;
Cn4_t <= C4 ;
OVR_t <= C3 xor C4 ;
when OR_i =>
F_t <= R or S ;
nP_t <= '0' ;
nG_t <= P(3) and P(2) and P(1) and P(0) ;
Cn4_t <= (not (P(3) and P(2) and P(1) and P(0)) ) or Cn ;
OVR_t <= (not (P(3) and P(2) and P(1) and P(0)) ) or Cn ;
when AND_i =>
F_t <= R and S ;
nP_t <= '0' ;
nG_t <= not (G(3) or G(2) or G(1) or G(0) ) ;
Cn4_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
OVR_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
when NOTRS_i =>
F_t <= (not R) and S ;
nP_t <= '0' ;
nG_t <= not (G(3) or G(2) or G(1) or G(0) ) ;
Cn4_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
OVR_t <= G(3) or G(2) or G(1) or G(0) or Cn ;
when EXOR_i =>
F_t <= R xor S ;
nP_t <= G(3) or G(2) or G(1) or G(0) ;
nG_t <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and
P(2) and P(1) and P(0)) ;
Cn4_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3)
and P(2) and P(1) and P(0) and (G(0) or (not Cn)) ) ) ;
OVR_t <= (P(2) or (G(2) and P(1)) or ((not G(2)) and (not G(1)) and (not P(0)))) xor ((not
P(3)) or ((not G(3)) and (not P(2))) or ((not G(3)) and (not G(2)) and (not P(1)))
or ((not G(3)) and (not G(2)) and (not G(1)) and (not P(0))) or ((not G(3)) and (not
G(2)) and (not G(1)) and (not G(0)) and Cn)) ;

when others => -- EXNOR_i


F_t <= R xnor S ;
nP_t <= G(3) or G(2) or G(1) or G(0) ;
nG_t <= G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3) and
P(2) and P(1) and P(0)) ;
Cn4_t <= not (G(3) or (P(3) and G(2)) or (P(3) and P(2) and G(1)) or (P(3)
and P(2) and P(1) and P(0) and (G(0) or (not Cn)) ) ) ;
OVR_t <= (P(2) or (G(2) and P(1)) or ((not G(2)) and (not G(1)) and (not P(0)))) xor ((not P(3))
or ((not G(3)) and (not P(2))) or ((not G(3)) and (not G(2)) and (not P(1))) or ((not G(3))
and (not G(2)) and (not G(1)) and (not P(0))) or ((not G(3)) and (not G(2)) and (not G(1))
and (not G(0)) and Cn)) ;
end case ;
end process ;

process
begin
wait until (CP'event and CP = '1') ;
102
wait for HOLD ;
wait for 3 * DELAYMIN ;
case nOE is
when '0' =>
case I (8 downto 6) is
when RAMA =>
Y_t <= ram_var (CONV_INTEGER (A)) ;
when others =>
Y_t <= F_t ;
end case ;
when others =>
Y_t <= "ZZZZ" ;
end case ;
end process ;
process (F_t)
begin
case F_t is
when "0000" =>
F_eq_0_t <= '1' ;
when others =>
F_eq_0_t <= '0' ;
end case ;
end process ;

F3_t <= F_t (3) ;

process
begin
wait until (CP'event and CP = '0') ;
wait for DELAY ;
if((test_OK = TRUE) and (Y = Y_t) and (nP = nP_t) and (nG = nG_t) and (Cn4 =
Cn4_t) and (OVR = OVR_t) and (F_eq_0_t = F_eq_0) and (F3_t = F3)) then
test_OK1 <= TRUE ;
else
test_OK1 <= FALSE ;
report "EROARE"
severity ERROR ;
end if ;
end process ;

-- pentru vizualizare
process (I(2 downto 0))
begin
case I(2 downto 0) is
when AQ => ALU_SOURCEv <= AQv ;
when AB => ALU_SOURCEv <= ABv ;
when ZQ => ALU_SOURCEv <= ZQv ;
when ZB => ALU_SOURCEv <= ZBv ;
when ZA => ALU_SOURCEv <= ZAv ;
when DA => ALU_SOURCEv <= DAv ;
when DQ => ALU_SOURCEv <= DQv ;
when DZ => ALU_SOURCEv <= DZv ;
when others => ALU_SOURCEv <= XXX ;
end case ;
end process ;
process (I(5 downto 3))
begin
case I(5 downto 3) is
when ADD_i => ALU_INSTRUCTIONv <= ADDv ;
when SUBR_i => ALU_INSTRUCTIONv <= SUBRv ;
when SUBS_i => ALU_INSTRUCTIONv <= SUBSv ;
when OR_i => ALU_INSTRUCTIONv <= ORv ;
when AND_i => ALU_INSTRUCTIONv <= ANDv ;
when NOTRS_i => ALU_INSTRUCTIONv <= NOTRSv ;
when EXOR_i => ALU_INSTRUCTIONv <= EXORv ;
when EXNOR_i => ALU_INSTRUCTIONv <= EXNORv ;
when others => ALU_INSTRUCTIONv <= XXX ;
end case ;
end process ;
process (I(8 downto 6))
begin
case I(8 downto 6) is
when QREG => ALU_DESTINATIONv <= QREGv ;
when NOP => ALU_DESTINATIONv <= NOPv ;
when RAMA => ALU_DESTINATIONv <= RAMAv ;
when RAMF => ALU_DESTINATIONv <= RAMFv ;
when RAMQD => ALU_DESTINATIONv <= RAMQDv ;
when RAMD => ALU_DESTINATIONv <= RAMDv ;
103
when RAMQU => ALU_DESTINATIONv <= RAMQUv ;
when RAMU => ALU_DESTINATIONv <= RAMUv ;
when others => ALU_DESTINATIONv <= XXX ;
end case ;
end process ;
end test ;

Metodologia de testare este identică cu cea de la testarea ui CY7C910: se compilează fişierul


“tcb773p.v”, apoi se compilează “CY7C910_mapped.vhd” (generat de programul de sinteză) , iar apoi se
compilează fişierul “test_CY7C901.vhd”. Apoi se încarcă arhitectura test din cadrul designului
test_CY7C901 având grijă să ataşăm fişîerul “CY7C901_mapped.sdf” instanţei DUT din cadrul
arhitecturii test şi se setează rezoluţia de simulare pe picosecunde.
În continuare voi prezenta formele de undă obţinute în urma simulării postsinteză.

Figura 1

În figura 1 sunt prezentate formele de undă rezultate în urma operaţiei de încărcare a memoriei cu datele
aplicate pe intrarea D. Nu se poate vizualiza conţinutul locaţiilor de memorie întrucât aceasta ar presupune
identificarea bistabililor care alcătuiesc fiecare locaţie de memorie şi afişarea ieşirilor acesto bistabili, ceea
ce ar necesita redarea unui număr foarte mare de forme de undă. Ceea ce se poate observa cu uşurinţă este
faptul că datele aplicate pe intrarea D ajung nemodificate la ieşirea Y.

Figura 2

104
În figura 2 (16 < N <= 31) este vizualizată operaţia de încărcare a memoriei RAM cu datele aplicate pe
intrarea D, deplasate la stânga sau la dreapta în funcţie de instrucţiunea de control a destinaţiei ieşirii ALU
aplicate (RAMQD, RAMD, RAMQU, RAMU) . Şi în această figură se poate observa că datele aplicate pe
intrarea D ajung nemodificate la ieşirea Y. Ţinând cont de datele aplicate pe intrarea D, de locaţia de
memorie selectată de data aplicată pe intrarea B, de tipul de deplasare (la stânga sau la dreapta) indicat de
instrucţiunea de control a destinaţiei ieşirii ALU şi de semnalele aplicate pe pinii bidirecţionali RAM3 şi
RAM0, se poate calcula conţinutul memoriei în urma operaţiilor de încărcare. Conform calculelor, la
momentul N = 32, în locaţiile memoriei RAM ar trebui să se afle următoarele date :
RAM[ 0 : 15 ] = ("0001", "1000", "1100", "1110", "1111", "0111", "0011", "0001", "0010",
"0100", "1000", "0000", "0001", "0011", "0111", "1111") ;
În continuare (31 < N <= 47) se testează dacă, într-adevăr, datele scrise în RAM sunt cele calculate. Pentru
aceasta, se selectează (prin intermediul intrării B) o locaţie de memorie, conţinutul acesteia fiind scos pe
ieşirea Y în urma operaţiei de adunare cu zero (Figura 3) .

Figura 3

În continuare (47 < N <= 175) se verifică funcţionarea ALU, executând, pe rând, fiecare din cele 8
instrucţiuni asupra a câte 16 perechi de date din memorie.

Figura 4 – testarea operaţiei ADD

105
Figura 5 – testarea operaţiei SUBR

Figura 6 – testarea oparaţiei SUBS

Figura 7 – testarea operaţiei OR

106
Figura 8 – testarea operaţiei AND

Figura 9 – testarea operaţiei NOTRS

Figura 10 – testarea operaţiei EXOR

107
Figura 11 – testarea operaţiei EXNOR

În continuare (175 < N <= 191) am testat funcţionarea ansamblului Q_REGISTER – Q_SHIFT. Mai întâi ,
prin execuţia instrucţiunii QREG de control a destinaţiei ieşirii ALU, am încărcat Q_REGISTER cu data
aplicată pe intrarea D. Apoi am testat execuţia instrucţiunilor RAMQU şi RAMQD asupra Q_REGISTER.
Întrucât RAMQU şi RAMQD acţionează şi asupra RAM-ului, nu numai asura Q_REGISTER, execuţia
acestora va determina şi modificarea conţinutului memoriei RAM. În figura 12 am prezentat şi formele de
undă a mai multor semnale interne circuitului CY7C901 pentru a se putea observa mai uşor funcţionarea
Q_REGISTER-lui, dar şi a celor două blocuri de deplasare : Q_SHIFT şi RAM_SHIFT.

Figura 12 – testarea blocurilor Q_REGISTER, Q_SHIFT şi RAM_SHIFT

În urma testării blocului Q_REGISTER, conţinutul memoriei RAM s-a modificat, la momentul N = 192
acesta trebuind să fie , după calcule, următorul :
RAM[ 0 : 15 ] = ("0010", "0000", "0100", "0110", "0111", "1111", "1011", "1001", "0011", "0101", "1001", "0001", "0000", "0010", "0110", "1110") ;

108
În final, se verifică corectitudinea rescrierii anterioare a memoriei RAM prin executarea operaţiei de
adunare între diferite perechi de date din RAM. Analizând formele de undă din figura 13 se poate observa
cu uşurinţă că datele de pe intrările R şi S ale ALU, reprezentând datele de la locaţiile de memorie indicate
de A, respectiv B, sunt aceleaşi cu datele calculate anterior.

Figura 13

Această simulare postsinteză dovedeşte funcţionarea corectă a circuitului CY7C901. Din păcate, frecvenţa
maximă de funcţionare este destul de mică, aproximativ 25 MHz, însă acestă frecvenţă ar putea fi crescută
destul de mult dacă sinteza circuitului ar fi realizată de un specialist în acest domeniu.

109
CONCLUZII

După cum am spus şi în introducere, scopul acestei lucrări a fost aprofundarea problemelor ridicate
de proiectarea VHDL pentru sinteză a circuitelor integrate digitale. Acum, după terminarea proiectului, pot
spune că, în mare măsură, scopul a fost atins, având ca principal argument faptul că cele două circuite,
CY7C910 şi CY7C901, au putut fi sintetizate şi că rezultatele simulărilor postsinteză au fost corecte. În
afară de aprofundarea limbajului VHDL, în special VHDL pentru sinteză, am deprins cunoştinţele de bază
despre instrumentele soft pentru simulare (ModelSim) şi sinteză (Design Compiler şi Leonardo Spectrum).
De asemenea, consider deosebit de importantă deprinderea strategiei de abordare a unui proiect :
descompunerea circuitului în subcircuite mai simple, tratarea independentă a acestor subcircuite (descriere,
testare, sinteză, testare postsinteză), îmbinarea subcircuitelor şi testarea circuitului astfel obţinut.
Puse cap la cap, descrierile VHDL şi programele de test pentru aceste descrieri însumează peste
3000 de linii de cod. Proiectarea propriuzisă (descrierile VHDL, programele de test, sinteza descrierilor
VHDL, simulările) s-a întins pe o perioadă de aproximativ 6 săptămâni, perioada de proiectare efectivă
fiind, după calculele mele, de aproximativ 300 de ore. Pe parcursul realizării proiectului am fost nevoit să
refac de mai multe ori descrierile anumitor blocuri, iar găsirea unor soluţii pentru realizarea programelor de
test a fost de cele mai multe ori mult mai lentă decât transpunerea acestor soluţii în cod VHDL.
Realizarea acestui proiect a presupus descrierea pentru sinteză a multor blocuri foarte des întâlnite
în activitatea de proiectant/programator VHDL : unitate aritmetico-logică, stivă, memorie RAM dual-port,
numărător, multiplexor, buffer three-states, registru master-slave, registru de deplasare cu porturi
bidirecţionale.
Prin numărul şi diversitatea blocurilor descrise, prin programele de test realizate pentru aceste
blocuri, prin prezentarea amănunţită a problemelor deosebite întâlnite la descrierea anumitor blocuri, prin
garanţia că toate descrierile VHDL sunt sintetizabile şi prin prezentarea simulărilor postsinteză (care
dovedesc funcţionarea corectă a circuitelor sintetizate) , consider că acest material poate constitui cu succes
îndrumătorul de laborator pentru o disciplină precum PAC2 sau VLSIR.
În final vreau să le mulţumesc domnului dr.ing Dănuţ Burdia şi domnului doctorand Silviu Isarie
pentru ajutorul dat la instalarea pachetului Synopsys, pentru furnizarea fişierelor tehnologice şi pentru
sfaturile deosebit de utile pentru proiectare.

110
BIBLIOGRAFIE

1. Michael John Sebastian Smith – “Application-Specific Integrated Circuits”, 1997


2. K.C.Chang – “Digital Systems Design with VHDL and Synthesis : An Integrated Approach”, 1999
3. D.Burdia şi G.Ş.Popescu -"Proiectarea asistată de calculator a circuitelor electronice -
SPICE - VHDL", 1999
4. Stefan Sjoholm – “VHDL for Designers”, 1997
5. Douglas Smith – “HDL Chip Design”
6. Ţigăeru Liviu – cursul de Structuri VLSI Reconfigurabile
7. J.Bhashker – “A VHDL Primer. Revised Edition”, 1995