background image

Język opisu sprzętu VHDL

Materiały pomocnicze dla przedmiotu

"Technika cyfrowa i mikroprocesorowa" II/III RA

Krzysztof Kołek

Katedra Automatyki, Akademia Górniczo-Hutnicza

Al. Mickiewicza 30, 30-059 Kraków

tel. (0-12) 617-20-97

kko@ia.agh.edu.pl

background image

- 2 -

Język opisu sprzętu VHDL

background image

Spis treści

1. WSTĘP.................................................................................................................................................................5

2. PODSTAWOWE POJĘCIA JĘZYKA VHDL.................................................................................................6

2.1. P

REDEFINIOWANE

 

TYPY

........................................................................................................................................7

2.2. L

OGIKA

 

WIELOWARTOŚCIOWA

................................................................................................................................7

2.3. K

OMPONENTY

....................................................................................................................................................8

2.4. P

AKIETY

............................................................................................................................................................9

2.5. P

ODPROGRAMY

...................................................................................................................................................9

2.6. O

PERATORY

.....................................................................................................................................................10

2.7. S

YGNAŁY

ZMIENNE

STAŁE

................................................................................................................................11

2.8. D

EFINICJA

 

I

 

UŻYCIE

 

TYPÓW

.................................................................................................................................14

2.9. R

ÓWNOLEGŁE

 

ORAZ

 

SZEREGOWE

 

WYKONANIE

 

INSTRUKCJI

. K

ONCEPCJA

 

PROCESU

.........................................................15

2.10. Z

AWIESZANIE

 

WYKONANIA

 

PROCESU

...................................................................................................................17

2.11. I

NSTRUKCJE

 

WYKONYWANE

 

SZEREGOWO

.............................................................................................................19

2.12. C

YKL

 "

DELTA

"...............................................................................................................................................21

2.13. A

TRYBUTY

....................................................................................................................................................22

2.14. P

OZOSTAŁE

 

CECHY

 

JĘZYKA

...............................................................................................................................23

2.15. P

RZEŁADOWANIE

 

OPERATORÓW

.........................................................................................................................23

3. STRUKTURALNY OPIS SPRZĘTU..............................................................................................................24

3.1. S

UMATOR

 4-

BITOWY

. O

PIS

 

STRUKTURALNY

..........................................................................................................24

3.2. G

ENERATOR

 

NUMERÓW

 

GÓRNIKÓW

. P

ROJEKT

 

W

 

POSTACI

 

SCHEMATU

 

ELEKTRYCZNEGO

.................................................30

4. BEHAWIORALNY OPIS SPRZĘTU.............................................................................................................34

4.1. W

IELOKROTNE

 

WYWOŁANIE

 

PROCESU

...................................................................................................................34

4.2. D

EFINIOWANIE

 

REJESTRÓW

.................................................................................................................................35

4.3. C

ZTEROBITOWY

 

REJESTR

 

Z

 

RÓWNOLEGŁYM

 

ŁADOWANIEM

 

I

 

ASYNCHRONICZNYM

 

ZEROWANIEM

........................................37

4.4. C

ZTEROBITOWY

 

BINARNY

 

LICZNIK

 

ASYNCHRONICZNY

..............................................................................................38

4.5. K

ONWERTER

 

KODU

 BCD 

NA

 

KOD

 

WYŚWIETLACZA

 

SIEDMIOSEGMENTOWEGO

..............................................................39

4.6. M

ULTIPLEKSER

 4 

NA

 1......................................................................................................................................39

4.7. C

ZTEROBITOWY

 

REJESTR

 

PRZESUWAJĄCY

..............................................................................................................40

4.8. C

ZTEROBITOWY

 

LICZNIK

 

SYNCHRONICZNY

 

Z

 

WEJŚCIEM

 

ZEZWALAJĄCYM

 

NA

 

ZLICZANIE

ASYNCHRONICZNYM

 

ZEROWANIEM

 

I

 

SYNCHRONICZNYM

 

ŁADOWANIEM

................................................................................................................................40

4.9. B

UFOR

 

TRÓJSTANOWY

........................................................................................................................................41

4.10. F

UNKCJA

 

KONWERSJI

 

TYPU

 

BIT

_

VECTOR

 

DO

 

TYPU

 

INTEGER

....................................................................................41

4.11. A

UTOMAT

 

O

 

SKOŃCZONEJ

 

LICZBIE

 

STANÓW

..........................................................................................................42

4.12. I

MPLEMENTACJA

 

UKŁADÓW

 

Z

 

RODZINY

 TTL.......................................................................................................44

4.12.1. Implementacja układu 7400................................................................................................................44
4.12.2. Implementacja układu 74138..............................................................................................................44

5. WYKAZ FUNKCJI JĘZYKA VHDL.............................................................................................................46

5.1. A

TRYBUTY

.......................................................................................................................................................46

5.2. D

EFINICJA

 

TABLIC

.............................................................................................................................................47

5.3. I

NSTRUKCJA

 

CASE

.............................................................................................................................................48

5.4. S

CALANIE

 

WARTOŚCI

 (

ANG

AGGREGATE

)..............................................................................................................49

5.5. T

YP

 B

IT

..........................................................................................................................................................50

5.6. T

YP

 B

IT

_V

ECTOR

............................................................................................................................................50

5.7. T

YP

 B

OOLEAN

.................................................................................................................................................51

5.8. T

YP

 C

HARACTER

..............................................................................................................................................51

5.9. P

AKIET

............................................................................................................................................................51

6. PRZYKŁADY....................................................................................................................................................52

6.1. K

ONWERTER

 

LICZBY

 

BINARNEJ

 

NA

 

KOD

 BCD. W

YŚWIETLENIE

 

LICZBY

 BCD 

NA

 

WYŚWIETLACZU

 7-

SEGMENTOWYM

........54

6.2. C

ZĘSTOTLIWOŚCIOMIERZ

....................................................................................................................................58

Język opisu sprzętu VHDL

- 3 -

background image

6.3. G

ENERATOR

 

NUMERÓW

 

GÓRNIKÓW

......................................................................................................................62

6.4. G

ENERATOR

 

SYGNAŁU

 

WIZYJNEGO

 

DLA

 

MONITORA

 

MONOCHROMATYCZNEGO

..............................................................68

- 4 -

Język opisu sprzętu VHDL

background image

1.

Wstęp

Język VHDL (skrót pochodzi od dwóch innych skrótów: V - Very High Speed Integrated 

Circuit oraz HDL - Hardware Description Language) rozwijany był na początku lat 80-tych do 
opisu niezależnych metod opisywania układów elektronicznych przez  American Department 
of Defence (ang. DoD). Po raz pierwszy został zestandaryzowany w roku 1983, a następnie 
standaryzację powtórzono w latach 1987 oraz 1993. 

Główne cechy języka VHDL to:

równoległość   przejawiająca   się   w   możliwości   zdefiniowania   potrzeby   oraz 
wykonywania równoległego (jednoczesnego w czasie) przetwarzania różnych porcji 
informacji,

strukturalność oznaczająca możliwość hierarchicznego opisywania projektów. W 
opisie hierarchicznym projekt zbudowany jest z połączonych bloków o mniejszym 
stopniu   złożoności,   które   z   kolei   zbudowane   są   z   prostszych   bloków,   które 
zawierają w sobie jeszcze  prostsze  bloki i tak dalej aż dochodzimy do bloków 
podstawowych, którymi np. w przypadku układów cyfrowych są bramki logiczne. 
Strukturalność oznacza możliwość opisu sprzętu od poziomu systemu do poziomu 
bramki,

"redesign" - typowy projekt cyfrowego układu elektronicznego zawiera w sobie do 
80%   fragmentów   z   innych   projektów.   Nowe   projekty   nie   powstają   w   pustce. 
Projektanci   wykorzystują   poprzednio   zdobyte   doświadczenia   przenosząc 
opracowane i poznane uprzednio rozwiązania do nowych projektów. Proces ten 
określa się pochodzącym z języka angielskiego słowem redesign,

możliwość wykonywania instrukcji sekwencyjnie (czyli w sposób przeciwstawny 
do   wykonywania   równoległego)   oznaczająca   możliwość   definiowania   czynności 
wykonywanych   jedna   po   drugiej,   w   sposób   analogiczny   jak   w   tradycyjnych 
językach programowania. ,

zdolność do jednolitego opisywania struktury układów zbudowanych w oparciu o 
różne   technologie   stwarzająca   możliwość   przenoszenia   projektów   pomiędzy 
różnymi platformami sprzętowymi,

możliwość symulowania projektowanych układów; możliwość tworzenia sekwencji 
sygnałów   testujących.   Istnieje   możliwość   wbudowania   sygnałów   testowych   w 
projekt,

"samodokumentowanie" osiągnięte dzięki prostej i przejrzystej strukturze,

modelowanie układów z uwzględnieniem upływającego czasu.

Programowanie w języku VHDL może odbywać się na różnych poziomach abstrakcji. Są 

to:

warstwa  topograficzna  (ang.  layout) specyfikująca połączenia z uwzględnieniem 
również   zależności   czasowych   i   efektów   analogowych.   Przykładowo   realizuje 
opóźnienia   propagacji   sygnału   oraz   blokowanie   sygnałów   poniżej   minimalnej 
zadanej szerokości,

warstwa  logiki  zawierająca   informację   o   funkcjach,   architekturze,   technologii   i 
szczegóły zależności czasowych. Podstawowo opisuje zależności logiczne między 
blokami,

Język opisu sprzętu VHDL

- 5 -

background image

warstwa RTL (ang. Register Transfer Level) - zawiera opis każdego rejestru oraz 
logiki   między   nimi.   Zawiera   informacje   o   architekturze   ale   nie   o   technologii. 
Zależności czasowe nie są specyfikowane. Istotna jest tylko informacja o zegarach 
taktujących,

warstwa behawioralna (ang. behavioural) opisująca funkcje projektu. Zawiera tak 
dużo   informacji   o   zależnościach   czasowych,   jak   jest   to   niezbędne   do   opisaniu 
funkcji projektu. 

Każdy element opisywany w języku VHDL może posiadać dowolną liczbę definicji w 

każdej z omówionych warstw. Umożliwia to skupienie się w różnych fazach projektu na 
różnych jego aspektach.

Język przypomina języki programowania typu C lub Pascal jednak jego podstawowym 

celem   nie   jest   wykonywanie   obliczeń.   Zadaniem   języka   jest   wspieranie   całości   procesu 
projektowania   układów   cyfrowych   poczynając   od   symulacji   poprzez   modelowanie, 
testowanie, implementacje oraz tworzenie dokumentacji. Podstawowym celem języka VHDL 
jest "zaprogramowanie" programowalnego układu logicznego
 niezależnie od technologii 
w jakiej ten układ został wytworzony (ASIC, FPGA, PLD, itp.). Dotyczy to również układów 
opracowywanych w przyszłości, których parametry nie są jeszcze aktualnie znane.

Podstawowym   ograniczeniem   języka   VHDL   jest,   iż   pierwotnie   był   projektowany 

wyłącznie   do   systemów   cyfrowych.   Aktualnie   trwają   prace   nad   standaryzacją   wersji   dla 
układów   analogowych   oraz   nad   opracowaniem   analogowych   programowalnych   i 
konfigurowalnych   układów   scalonych   o   podobnym   stopniu   elastyczności   jaki   osiągnęły 
układy FPGA w technice cyfrowej.

Dostępne   oprogramowanie   wspomagające   użytkowanie   języka   zwykle   automatycznie 

tworzy   i   optymalizuje   struktura   komórek   i   połączeń   podczas   programowanie 
programowalnych układów logicznych. Język VHDL wydaje się być szczególnie użyteczny 
dla układów FPGA o 10-20 tysiącach komórek. Narzędzia języka HVDL dla układów FPGA 
kosztują od 1 do 20 tysięcy USD (w porównaniu z cenami 50-100 tysięcy USD dla układów 
ASIC).

Niniejsze opracowanie przedstawia skrótowy opis struktur języka VHDL ukierunkowany 

na wykorzystanie do programowania programowalnych układów logicznych firmy XILINX z 
wykorzystanie   firmowego   oprogramowania   wspomagany   przez   pakiet   oprogramowanie 
ORCAD   w   wersji   7.11.   Należy   zwrócić   uwagę   na   występujące   różnice   między   opisem 
standardu   języka   VHDL   oraz   jego   implementacją   w   programie   ORCAD.   Praktyczna 
implementacja   zawiera   bowiem   istotne   ograniczenia   w   stosunku   do   ogólnej   specyfikacji 
języka podyktowane kłopotami w realizacji niektórych cech w oparciu o aktualną technologię. 
Specyfikacja języka, będąc bardzo elastyczną, uwzględnia cechy, które aktualnie mogą być 
wyłącznie symulowane w sposób programowy (nie jest możliwa ich praktyczna realizacja z 
zastosowaniem   okładów   firmy   XILINX)   nie   należy   jednak   wykluczyć   ich   praktycznej 
realizacji w oparciu o nowe rozwiązania technologiczne.

2.

Podstawowe pojęcia języka VHDL

- 6 -

Język opisu sprzętu VHDL

background image

Poniżej przedstawiono podstawowe pojęcia występujące w opisie języka VHDL. Należy 

pamiętać, iż język VHDL został zaprojektowany jako język opisu sprzętu. Powoduje to istotne 
różnice   w   stosunku   do   języków   programowania   ogólnego   przeznaczenia.   Język   VHDL 
wykazuje duże podobieństwa składniowe do języków typu Pascal lub C niemniej  podobnie 
wyglądające   instrukcje   mogą   charakteryzować   się   dramatycznie   odmiennym 
zachowaniem
. W szczególności dotyczy to zasad określania zależności czasowych oraz pracy 
równoległej.

2.1.

Predefiniowane typy

Język VHDL posiada następujące predefiniowane typy danych:

BOOLEAN przyjmuje jedną z dwóch wartości: FALSE lub TRUE,

BIT jest równe '1' lub '0',

BIT_VECTOR ciąg wartości typu BIT np. "000000", "01101". Można użyć do 
modelowania magistral,

CHARACTER umożliwia używanie znaków alfanumerycznych np. 'a', 'X',

STRING definiuje ciągi znaków np. "ABCD", "012ws"

INTEGER reprezentuje liczby całkowite,

REAL umożliwia zapis liczb zmiennopozycyjnych.

Powyższe typy powinny być zdefiniowane w pakiecie  STANDARD  wchodzącym w 

skład   języka.   Definicja   pewnych   typów   może   być   zależna   od   implementacji   lub   nie 
występować.   Dotyczy   to   na   przykład   typu  REAL,   który   ze   względu   na   problemy 
implementacyjne nie zawsze jest dostępny.

2.2.

Logika wielowartościowa

Logika wielowartościowa posiada więcej typów niż  tylko  zero i  jedynka logiczna. 

Pakiet Std_Logic_1164 wchodzący w skład języka VHDL zawiera definicję typów std_logic 
(typ   "resolved")   oraz  std_ulogic  (typ   "unresolved")   o   następujących   wartościach   wraz   z 
operującymi na nich funkcjami:

'U'

- wartość nigdy dotychczas nie została określona,

'X'

- wartość była znana ale aktualnie nie można podać jej konkretnej wartości; 
sygnał "strong drive",

'0'

- sygnał logicznego 0 typu "strong drive",

'1'

- sygnał logicznej 1 typu "strong drive",

'Z'

- stan wysokiej impedancji; sygnał nie posiada "driver"-a,

'W'

- wartość była znana ale aktualnie nie można podać jej konkretnej wartości; 
sygnał "weak drive"; rzadko używany,

'L'

- sygnał logicznego 0 typu "weak drive",

'H'

- sygnał logicznej 1 typu "weak drive",

'-'

- wartość sygnału nie ma znaczenia.

Pakiet zawiera również definicje typów Std_logic_vector oraz Std_ulogic_vector.

Język opisu sprzętu VHDL

- 7 -

background image

Pakiet Std_logic zawarty jest w bibliotece IEEE. Poniższe instrukcje czynią elementy 

zdefiniowane w pakiecie Std_logic dostępnymi w projekcie:

library IEEE;    

-- Uczyń bibliotekę dostępną

use IEEE.Std_Logic_1164.all; -- Całość biblioteki dostępna

Jest możliwe podstawianie elementów typu std_ulogic do std_logic i vice-versa.

2.3.

Komponenty

Opis   komponentów   składowych   projektu   wykonywany   jest   za   pomocą   dyrektywy 

ENTITY  opisującej sprzęg w strukturze  hierarchicznej,  bez definiowania  zachowania. Jest 
odpowiednikiem symbolu na schemacie. Przykładowy opis komponenty przedstawiony jest 
poniżej. 

ENTITY halfadd IS
PORT
 ( a,b : IN BIT;
      sum, carry : OUT BIT);
END halfadd;

Blok  ENTITY  zawiera   definicje   sygnałów   wejściowych   i   wyjściowych   komponentu. 

Może   również   zawierać   definicje   parametrów   i   stałych.   Opisany  blok   o   nazwie  halfadd 
posiada dwa wejścia (a  oraz  b) oraz  dwa wyjścia (sum  oraz  carry). Wszystkie wejścia i 
wyjścia są typu BIT. Przedstawiony powyżej przykład odpowiada następującemu blokowi:

halfadd

sum

a

b

carry

Zachowanie komponentu opisane jest w bloku ARCHITEKTURE

ARCHITECTURE behave OF halfadd IS 
BEGIN
    sum <= a XOR b;
    carry <= a AND b;
END behave;

Po słowie  ARCHTECTURE  znajduje się zdefiniowana przez użytkownika nazwa. Blok 

ARCHTECTURE  jest   zawsze   związany   z   blokiem  ENTITY.   Znaki   '<='   są   symbolami 
przypisania   nowych   wartości   do   sygnałów.   Każdy   blok  ENTITY  może   posiadać   kilka, 
różniących   się   nazwami,   bloków  ARCHTECTURE.   Umożliwia   to   opisanie   projektu   na 
różnych poziomach abstrakcji.

- 8 -

Język opisu sprzętu VHDL

background image

2.4.

Pakiety

W   języku   VHDL   można   pogrupować   komponenty   oraz   ich   właściwości   w   postaci 

pakietów. Pakiet jest zbiorem definicji, które mogą być dostępne przez wiele projektów w tym 
samym   czasie.   Jest   odrębną   jednostką   projektową   w   VHDL.   Występuje   na   zewnątrz 
rozważanych dotychczas jednostek (ENTITY  i  ARCHITECTURE). Może zawierać definicje 
stałych, typy definiowane przez  użytkownika, deklaracje komponentów  oraz podprogramy 
VHDL, które są dzielone pomiędzy różne projekty.

Pakiety definiuje się za pomocą dyrektywy PACKAGE.

Przykładowym   pakietem   jest  Std_Logic_1164  zawierający   między   innymi   definicje 

podstawowych typów.

2.5.

Podprogramy

Język VHDL umożliwia definicję zarówno funkcji jak i procedur, które ogólnie zwane są 

podprogramami.   Przykładem   działania   funkcji   jest   transkodowanie,   czyli   zmiana   zapisu 
liczby w jednym kodzie na inny (patrz przykład poniżej). Taka sama operacja może zostać 
zrealizowana   za   pomocą   procedury   (patrz   drugi   przykład).   Różnica   polega   na   zwracane 
wartości: procedura nie zwraca żadnej wartości i w związku z tym nie może zostać użyta np. 
w   instrukcjach   przypisania   podczas   gdy   funkcja   zwraca   wartość   określonego   typu. 
Ewentualne wartości modyfikowane przez procedurę muszą zostać zadeklarowane na jej liście 
argumentów jako wyjściowe lub wejściowo/wyjściowe (out lub inout).

function Transcod(Value: in bit_vector(0 to 7)) return bit_vector is
begin
  case Value is
    when "00000000" => return "01010101";
    when "01010101" => return "00000000";
    when others =>     return "11111111";
  end case;    
end Transcod;

procedure Transcoder_1 (variable Value: inout bit_vector (0 to 7)) is
begin
  case Value is
    when "00000000" => Value:="01010101";
    when "01010101" => Value:="00000000";
    when others     => Value:="11111111";
  end case;    
end procedure Transcoder_1;

Język opisu sprzętu VHDL

- 9 -

background image

2.6.

Operatory

Operatory   dostępne   w   języku   VHDL   przedstawia   poniższa   tabela.   Przedstawione 

operatory działają na standardowych typach wbudowanych w język. Mogą zostać niezależnie 
zdefiniowane dla typów definiowanych przez użytkownika. 

Operator

Typy operandów

Typ wyniku

Logiczne

AND, OR, NAND, 
NOR,

 

XOR, 

XNOR, NOT

BIT lub BOOLEAN

(BIT_VECTOR,   STD_LOGIC, 
STD_LOGIC_VECTOR, 
STD_ULOGIC, 
STD_ULOGIC_VECTOR)

BIT lub BOOLEAN

(BIT_VECTOR, 
STD_LOGIC, 
STD_LOGIC_VECTOR, 
STD_ULOGIC, 
STD_ULOGIC_VECTOR)

Porównań

=, /=, <, <=, >, >= Wszystkie typu

BOOLEAN

Przesunięć

SLL,   SRL,   SLA, 
SRA, ROL, ROR

Lewostronny:   BIT   lub 
wektor

 

BOOLEAN; 

prawostronny: INTEGER

BOOLEAN

Dodawania

+, -, &

Tablica   numeryczna   lub 
element tablicy

Tego   samego   typu   jak 
operandy

Znak

+, -

Numeryczny

Tego   samego   typu   jak 
operandy

Mnożenia

*, /

INTEGER, REAL

Tego   samego   typu   jak 
operandy

MOD,

 

REM 

(reszta z dzielenia, 
różnie   działają   w 
zależności

 

od 

znaku operandu)

INTEGER

Tego   samego   typu   jak 
operandy

Inne

ABS 

Numeryczny

Tego   samego   typu   jak 
operandy

**  (potęgowanie) Lewostronny:   numeryczny; 

prawostronny: INTEGER

Tego   samego   typu   jak 
lewostronny operand

Spośród operatorów logicznych wszystkie oprócz  NOT  posiadają identyczny priorytet. 

Operator NOT posiada priorytet wyższy od pozostałych operatorów logicznych.

Dla argumentów typu tablicowego argumenty są wyrównywane w lewo i porównywane. 

Powoduje to, że '111' jest większe od '1011'. Oznacza to, że z wektorem nie jest związana 
żadna wartość numeryczne. To tylko zbiór elementów tego samego typu.

Podstawowo operatory arytmetyczne zdefiniowane są dla typów integerreal oraz time

Wykonywanie   operacji   arytmetycznych   dla   typów   takich   jak   np.  std_logic  wymaga 

- 10 -

Język opisu sprzętu VHDL

background image

zdefiniowania funkcji definiujących operatory dla takich typów. Jest to możliwe ponieważ 
język VHDL umożliwia definiowanie znaczenia operatorów. 

Dla operatorów arytmetycznych można wyspecyfikować zakres argumentów i wyniku:

entity ADD is
port(A, B : in integer range 0 to 7;
     Z : out integer range 0 to 15);
end ADD;
architecture ARITHMETIC of ADD is
begin
   Z <= A + B;
end ARITHMETIC;

Zmienne typu time można mnożyć i dzielić zarówno przez integer jak i real:

signal CLK : std_ulogic;
constant PERIOD : time := 50 ns;
wait for 5 * PERIOD;
wait for PERIOD * 1.5;
CLK <= not CLK after PERIOD/2;

2.7.

Sygnały, zmienne, stałe

Właściwe rozumienie cech oraz zasad użycia sygnałów oraz 
zmiennych jest najbardziej istotną cechą języka VHDL.

Sygnały   w   języku   VHDL   służą   do   reprezentacji   rzeczywistych   połączeń   między 

elementami   projektu.   Odpowiadają   więc   połączeniom   pojedynczym   lub   magistralom.   Z 
sygnałami związane są opóźnienie w związku z propagacją sygnału oraz zdolność tłumienia 
sygnałów o czasie trwania krótszym od zadanego. Operatorem przypisania w stosunku do 
sygnałów jest '<='. Przykładowo instrukcja:

z <= a;

powoduje przypisanie do sygnały z wartości sygnału a.

Każdy   sygnał   ma   z   sobą   związany   wzmacniacz   będący   źródłem   wartości   sygnału. 

Przedstawione powyżej podstawienie odpowiada sytuacji:

z

a

Język opisu sprzętu VHDL

- 11 -

background image

Podstawienie   wartości   do   sygnału   oznacza   w   rzeczywistości   ustawienie   wartości 

wyjściowej   ze   wzmacniacza.   Jeżeli   występuje   więcej   niż   jedno   podstawienie   do   sygnału 
wówczas   odpowiada   to   sytuacji   gdy   pojedynczy   sygnał   ma   kilka   związanych   z   nim 
wzmacniaczy. Pamiętając iż instrukcje mogą wykonywać się w sposób równoległy poniższy 
ciąg podstawień:

z <= a;
z <= b;

odpowiada sytuacji

z

a

b

Takie   rozwiązanie   jest   zwykle   niedopuszczalne.   Wielokrotne   podstawienie   wartości   do 
sygnału   powoduje   utworzenie   wielu   wzmacniaczy   będących   źródłem   wartości   sygnału. 
Jedynym przypadkiem dopuszczalności, a nawet dużej użyteczności takiego rozwiązania, jest 
zdefiniowanie sygnału  z  jako typu  resolved. Oznacza to związanie z sygnałem  z  specjalnej 
funkcji, która określa jaka jest wartość sygnału w przypadku gdy jest on sterowany z dwóch 
wzmacniaczy.

W   przypadku   wielokrotnego   podstawiania   wartości   do   tego   samego   sygnału 

wykonywanego   sekwencyjnie   wykona   się   wyłącznie   ostatnie   podstawienie.   Każde 
sekwencyjnie   podstawienie   wartości   do   sygnału   "anuluje"   poprzednie   sekwencyjne 
podstawienia. Wszystkie takie podstawienia wpływają na wyjście tego samego wzmacniacza 
sygnału. 

Podstawienia do sygnału w różnych sekwencyjnych fragmentach programu wykonywane 

jest równolegle i produkuje wielokrotne wzmacniacze dla podstawianego sygnału. W takim 
przypadku niezbędnym jest zdefiniowanie funkcji określającej wartość sygnału.

Przypisując wartość do sygnału można określić uzależnienia czasowe związane z taką 

operacją.  Przypisania   sygnałów  mogą  posiadać  zdefiniowane  opóźnienia  typu  inertial  lub 
transport. Dodatkowo opóźnienie  typu  inertial  może  posiadac wyspecyfikowany parametr 
reject

Podstawienie do zmiennej wykonywane jest za pomocą operatora <=. Instrukcja:

z <= a AFTER 5 NS;

powoduje  przypisanie   wartości   sygnału  a  do  sygnału  z  po  5   nanosekundach.  Dodatkowo 
impulsy o długości poniżej 5 nanosekund pojawiające się w sygnale  a  nie powodują zmian 
wartości sygnału z

Podstawienie

z <= REJECT 3 NS INERTIAL a AFTER 5 NS;

- 12 -

Język opisu sprzętu VHDL

background image

wprowadza opóźnienie 5 nanosekund i wycina impulsy o długości poniżej 3 nanosekund. 
Odpowiada to linii sygnałowej o zadanym opóźnieniu i ograniczonym paśmie.

Podstawienie

z <= TRANSPORT a AFTER 5 NS;

powoduje opóźnienie sygnału o 5 nanosekund. Dowolnie krótki  impuls  jest przenoszony. 
Odpowiada   to   linii   o   nieskończonym   widmie   i   może   np.   posłużyć   do   modelowania   linii 
opóźniających.

Podstawienie

z <= '1' AFTER 3 NS, '0' AFTER 7 NS, '1' AFTER 17 NS;

tworzy falę 1->0->1 zmieniającą wartości w chwilach czasu 3 ns, 7 ns  oraz 17 ns.

Wszystkie   podstawienia   sygnałów   wewnątrz   bloku 
ARCHITECTURE
 wykonywane są w sposób równoległy

Zmienne służą do zapamiętywania wartości chwilowych i w odróżnieniu od sygnałów nie 

mają bezpośredniego odniesienia w sprzęcie. Zmienne języka VHDL mogą być używane w 
sposób podobny do zmiennych klasycznych języków programowania. 

Operatorem przypisania dla zmiennych jest ':='. Przykładowo:

z := a;

Stałe służą do deklaracji wartości określonych typów. 

Zasady deklarowania, przypisywania i używania sygnałów, zmiennych oraz stałych zależą 

od tego czy wykonywane są w sekwencyjnej czy w równoległej części programu VHDL. 
Odpowiednie zasady przedstawia poniższa tabela.

Instrukcje wykonywane równolegle

Instrukcje wykonywane szeregowo

Deklaracja Przypisanie

Użycie

Deklaracja Przypisanie

Użycie

Sygnał

TAK

TAK

TAK

NIE

TAK

TAK

Zmienna

NIE

NIE

TAK

TAK

TAK

TAK

Stała

TAK

---

TAK

TAK

---

TAK

Zmienne zachowują swoją wartość między wywołaniami procesu.

Język opisu sprzętu VHDL

- 13 -

background image

Jest   możliwe   podstawianie   sygnałów   do   zmiennych   i   odwrotnie   choć   ciągle 

obowiązuje zasada zgodności typów.

Zakresem ważności zmiennych jest TYLKO proces wewnątrz którego są zdefiniowane. 

Aby ich wartości wysłać na zewnątrz procesu należy je przypisać do sygnałów.

Obiekty typu  variable  są zmieniane natychmiast, są więc używane do przechowywania 

zmiennych tymczasowych posiadających wpływ na wykonanie procesu. Typowo, wejściowe 
sygnały przypisujemy do zmiennych (variable
), wykonujemy są wszelkie obliczenia, a ich 
wyniki przypisujemy do sygnałów wyjściowych
.

2.8.

Definicja i użycie typów

W języku VHDL występują typy definiowane przez użytkownika. Mają one charakter 

typu wyliczeniowego. Typy definiuje się wewnątrz bloków typu  package,  architecture  lub 
process.

Przykładowa definicja typu wygląda w sposób następujący:

type MY_STATE is (RESET, IDLE, RW_CYCLE, INT_CYCLE);
...
signal STATE : MY_STATE;
...
   STATE <= RESET; 

Do sygnału danego typu można przypisać tylko wartość tego typu.

Zwykle elementy typów kodowane są na najmniejszej licznie bitów niezbędnych do 

zakodowania wszystkich elementów typu choć sposób kodowania zależy od implementacji 
języka.

Obiekty można przypisywać jeżeli są tego samego typu i tego samego rozmiaru:

signal Z_BUS:bit_vector(3 downto 0);
signal C_BUS:bit_vector(1 to 4);

Z_BUS <= C_BUS;

Z_BUS(3 downto 2) <= "00";
C_BUS(2 to 4) <= Z_BUS(3 downto 1);

Konkatenacja   sygnałów   w   magistrale   wykonywana   jest   za   pomocą   operatora   &. 

Agregacja   sygnałów   również   tworzy  magistrale,   ale   jest   przeprowadzana   poprzez   objęcie 
nawiasami oddzielonych przecinkiem elementów składowych:

signal Z_BUS : bit_vector(3 downto 0);
signal A, B, C, D : bit;
signal BYTE : bit_vector(7 downto 0);

- 14 -

Język opisu sprzętu VHDL

background image

Z_BUS <= A & B & C & D;

BYTE <= Z_BUS & Z_BUS;

Z_BUS <= (A, B, C, D);
-- equivalent to:
Z_BUS(3) <= A;
Z_BUS(2) <= B;
Z_BUS(1) <= C;
Z_BUS(0) <= D;

Specyfikacja   pozycji   może   nastąpić   przez   wpis   wartości   na   odpowiedniej   pozycji 

pozycję lub poprzez podanie indeksu:

X <= (3=>'1', 1 downto 0=>'1', 2 => B);

Operator others umożliwia przypisanie wartości do niezdefiniowanych elementów:

X <= (3=>'1', 1=>'0', others => B);

Każdy sygnał, zmienna i stała muszą mieć określony typ.

2.9.

Równoległe oraz szeregowe wykonanie instrukcji. Koncepcja  
procesu

Równoległe (ang. conrurrent) wykonywane instrukcji odbywa się wewnątrz architektury, 

jednak na zewnątrz zdefiniowanych wewnątrz architektury procesów. Instrukcje wykonują się 
równolegle   w   tym   samym   czasie.   Zachowanie   instrukcji   wykonywanych   równolegle   nie 
zależy od kolejności w jakiej są zapisane. Np. instrukcje:

X <= A + B;
Z <= C + X;

oraz instrukcje:

Z <= C + X;
X <= A + B;

dają TEN SAM REZULTAT. Rezultat obu operacji służy do policzenia wartości sygnału Z
Najlepiej widać to na poniższym schemacie przedstawiającym przepływ danych:

Język opisu sprzętu VHDL

- 15 -

background image

+

+

Z

C

X

B

A

Pewne instrukcje mogą nie mieć sensu wówczas gdy wykonywane są szeregowo. Np. 
X <= X + A;

opisuje sumator bez dodatkowego rejestru. Jest to więc logika kombinacyjna i jej realizacja 
sprzętowa wymagałaby następującej struktury:

+

X

X

A

Utworzona pętla algebraiczna uniemożliwia obliczenie wartości sygnału X.

Podczas pisanie programu w języku VHDL należy myśleć w 
sposób "zorientowany na sprzęt"
.

Instrukcje   wykonują   się   sekwencyjnie   wówczas   gdy   zostaną   umieszczone   wewnątrz 

procesu. Przykładowy proces przedstawiono poniżej:

MUX: process (A, B, SEL)
begin
   if SEL = '1' then
      Z <= A;
   else
      Z <= B;
   end if;
end process MUX;

Ciało   procesu   zdefiniowane   jest   między  słowami   kluczowymi  process  oraz  end   process
MUX  jest opcjonalną nazwą procesu. Po słowie  process  znajduje się lista  inicjalizacyjna. 
Umieszczenie   sygnału   w   liście   inicjalizacyjnej   powoduje,   że   proces   będzie   podlegał 
wykonaniu gdy zmieni się stan dowolnego sygnału z listy. W przeciwnym przypadku ciało 
procesu nie jest wykonywane. Typowo wewnątrz procesu zmieniane są wartości sygnałów. 
Jeżeli takie sygnały znajdują się na listach inicjalizacyjnych innych procesów jest to sposobem 
na "wywoływanie" jednych procesów przez inne.

Rozważmy   przykład   procesu   realizującego   funkcję   multipleksera   przedstawiony 

powyżej. Jeżeli sygnał SEL zostanie usunięty z listy inicjalizacyjnej wówczas zmiana sygnału 

- 16 -

Język opisu sprzętu VHDL

background image

SEL nie spowoduje zmiany wartości sygnału Z. Tylko zmiany A i B są w stanie wpłynąć na Z
Nie   pracuje   to   wówczas   jako   poprawny   multiplekser.  Lista   inicjalizacyjna   powinna 
ZAWSZE być KOMPLETNA

Instrukcje wewnątrz procesu wykonywane są sekwencyjnie - "jedna po drugiej"

Definicja procesu musi znajdować się w ciele architektury. Wewnątrz architektury może 

znajdować się dowolna liczba procesów:

architecture A of E is
begin
   -- concurrent statements
   P1 : process
   begin
      -- sequential statements
   end process P1;
   -- concurrent statements
   P2 : process
   begin
      -- sequential statements
   end process P2;
   -- concurrent statements
end A;

Instrukcje wewnątrz procesów wykonywane są sekwencyjnie, ale procesy wykonują się w 
sposób   równoległy.   Oprócz   procesów   architektura   może   zawierać   inne   wykonywane 
równolegle instrukcje.

Sygnały   zmieniane   wewnątrz   procesu   uzyskują   nową   wartość   dopiero   po 

zakończeniu   procesu.   Zapobiega   to   podstawianiu   wartości   tymczasowych   podczas 
wykorzystywania   sygnałów   po   lewej   stronie   znaku   przypisania.   Jeżeli   zachodzi   potrzeba 
wykorzystania wartości tymczasowych należy używać zmiennych. Zmienne, w odróżnieniu od 
sygnałów, zmieniają swoje wartości natychmiast, bez oczekiwania na zakończenie procesu.

Te   same  instrukcje   mogą  posiadać   różne   znaczenie   w   zależności   od   tego   czy   są 

wykonywane wewnątrz czy na zewnątrz procesu.

2.10. Zawieszanie wykonania procesu

Zawieszanie wykonania procesu oznacza wstrzymanie jego wykonania na określony 

czas lub do czasu zmiany wartości określonych sygnałów.

Występują   dwa   style   zawieszania   wykonania   procesu   w   oczekiwaniu   na   zmiany 

sygnałów. Pierwszy wykorzystuje listę inicjalizacyjną:

process (A,B)
begin
   if (A='1' or B='1') then

Język opisu sprzętu VHDL

- 17 -

background image

      Z <= '1';
   else
      Z <= '0';
   end if;
end process;

Proces podlega wykonaniu tylko wówczas gdy zmianie  ulegnie któryś z sygnałów z listy 
inicjalizacyjnej   po   czym   zatrzymuje   się   na   końcu.   Przedstawiony   powyżej   przykład   jest 
równoważny:

process
begin
   if (A='1' or B='1') then
      Z <= '1';
   else
      Z <= '0';
   end if;
   wait on A, B;
end process;

Zdefiniowany proces nie ma listy inicjalizacyjnej. Instrukcja wait on w sposób jawny 

specyfikuje   sygnały,   których   zmiana   "odwiesi"   proces.   Proces   zatrzymuje   się   na   końcu   i 
wznawia wykonanie gdy sygnał  A  lub  B  zmienią  swoją wartość. Proces posiadający listę 
aktywacyjną nie może posiadać instrukcji wait. 

Występuje   kilka   odmian   instrukcji  wait.   Pierwsza   z   nich   wstrzymuje   wykonanie 

procesu na pewien okres czasu:

STIMULUS: process
begin
   SEL <= '0';
   BUS_B <= "0000";
   BUS_A <= "1111";
   wait for 10 ns;
   SEL <= '1';
   wait for 10 ns;
   -- etc, etc
end process STIMULUS;

proces wznawia wykonanie po określonym w instrukcji wait for czasie.

Instrukcja  wait   on  wstrzymuje   wykonanie   w   oczekiwaniu   na   zmianę   wartości 

sygnałów (zdarzenie zachodzące na sygnałach) wyspecyfikowanych w liście.

W poniższym przykładzie 

process
begin
   wait until CLK='1';
   Q <= D;

- 18 -

Język opisu sprzętu VHDL

background image

end process;

instrukcja wait until czeka na zdarzenie na sygnale na moment gdy warunek jest prawdziwy. 
Gdy sygnał zmieni swoją wartość i dodatkowo spełniony jest warunek wykonanie procesu jest 
wznawiane.

Instrukcja  wait  wstrzymuje proces na zawsze. W przedstawionym poniżej przykładzie 

proces wykona się wyłącznie raz. Po wykonaniu instrukcji  wait  proces nie zostanie nigdy 
wznowiony:

STIMULUS: process
begin
   SEL <= '0';
   BUS_B <= "0000";
   BUS_A <= "1111";
   wait for 10 ns;
   SEL <= '1';
   wait;
end process STIMULUS;

2.11. Instrukcje wykonywane szeregowo

Instrukcje  for  (instrukcja pętli z licznikiem),  case  (instrukcja wyboru jednej z kilku 

możliwości)  oraz  if  (instrukcja   rozgałęzienia)   mogą   być   wykonywane  WYŁĄCZNIE 
SEKWENCYJNIE. 
Oznacza to, że muszą znajdować się wewnątrz procesu.

Najprostsza forma instrukcji if umożliwiająca warunkowe wykonanie grupy instrukcji 

ma następującą postać:

if CONDITION then
   -- sequential statements
end if;

W celu wykonania jednej z dwóch grup instrukcji należy wykorzystać instrukcję if w postaci:

if CONDITION then
   -- sequential statements
else
   -- sequential statements
end if;

Wykonanie jednej z kilku grup instrukcji możliwe jest dzięki instrukcji if w postaci:

if CONDITION1 then
   -- sequential statements
elsif CONDITION2 then
    -- sequential statements

Język opisu sprzętu VHDL

- 19 -

background image

elsif CONDITION3 then
   -- sequential statements
else
   -- sequential statements
end if;

Tylko pierwszy z warunków posiadający wartość logiczną prawdy służy do wyboru instrukcji 
podlegającej   wykonaniu   (w  if  może   być   więcej   niż   jeden   prawdziwy   warunek   jak   w 
przykładzie   poniżej).   Oznacza   to   występowanie   wbudowanego   priorytetu   występującego 
dzięki wyborowi kolejności warunków instrukcji if.

process (A, B, C, X)
begin
   if (X = "0000") then
      Z <= A;
   elsif (X <= "0101") then
      Z <= B;
   else
       Z <= C;
   end if;
end process;

Instrukcja  case  testuje wartość obiektu a następnie wykonuje jedną z grup instrukcji 

zależnie   od   aktualnej   wartości   obiektu.   Ogólny   format   instrukcji   wygląda   w   sposób 
następujący:

case OBJECT is
   when VALUE_1 =>
      -- statements
   when VALUE_2 =>
      -- statements
   when VALUE_3 =>
      --statements

   --etc...
end case;

W instrukcji case każda możliwa wartość obiektu MUSI ZOSTAĆ WYSPECYFIOWANA 
i musi być wyspecyfikowana TYLKO JEDEN RAZ. Przykład instrukcji case przedstawiono 
poniżej:

process (A, B, C, X)
begin
   case X is
      when 0 to 4 =>
         Z <= B;
      when 5 =>

- 20 -

Język opisu sprzętu VHDL

background image

         Z <= C;
      when 7 | 9 =>
         Z <= A;
      when others =>
         Z <= 0;
   end case;
end process;

Ogólny format pętli z licznikiem for ma postać:

for I in 0 to 3 loop
    -- statements
end loop

Powoduje iteracyjne wykonanie ciała pętli dla wyspecyfikowanej wartości licznika pętli. Nie 
ma potrzeby oddzielnego definiowania licznika pętli. Przykład użycia pętli for przedstawiono 
poniżej:

entity EX is
port
 (A : in std_ulogic_vector(0 to 15);
      SEL : in integer range 0 to 15;
      Z   : out std_ulogic);
end EX;

architecture RTL of EX is
begin
   WHAT: process (A, SEL)
   begin
      for I in to 15 loop
         if SEL = I then
            Z <= A(I);
         end if;
      end loop;
   end process WHAT;
end RTL;

2.12. Cykl "delta"

W każdej chwili czasu podczas wykonywania programu w języku VHDL występują 

dwie kolejki:

sygnałów do zmiany oraz 

procesów do wykonania

Język opisu sprzętu VHDL

- 21 -

background image

Pierwsza zawiera listę sygnałów, do których przypisano nowe wartości w procesie i 

które czekają na aktualizacje po zakończeniu procesu. Druga zawiera listę procesów, które 
czekają na wykonanie w związku ze zmianą wartości sygnałów na ich listach aktywacyjnych.

Jeżeli   sygnał   jest   zmieniany   to   wszystkie   procesy,   które   posiadają   go   w   liście 

aktywacyjnej umieszczane są w kolejce procesów do wykonania. Z kolei każdy proces jest 
wykonywany,   a   uaktualniane   sygnały   nie   są   zmieniane   natychmiast   lecz   umieszczane   w 
kolejce sygnałów do zmiany. Po wykonaniu wszystkich procesów sygnały są uaktualniane. 
Jako wynik zmian sygnałów inne procesy mogą zostać umieszczone w kolejce procesów. 
Takie cykle przeplatają się wzajemnie

Jeden taki cykl jest zwany cyklem delta.

Wiele   cykli   delta   może   być   wykonywanych   w   tym   samym   czasie   symulacji 

(wykonania).   Wykonanie   w  danym   czasie   kończy  się   wówczas   gdy  kolejki   sygnałów   do 
zmiany i procesów do wykonania są puste. Następnie przechodzi się do następnego kroku 
symulacji/wykonania.

2.13. Atrybuty

Zmienne, funkcje, typy, sygnały oraz stałe posiadają związane z nimi atrybuty, które 

ułatwiają programowanie. W rozdziale xxxx zawarto opis wybranych atrybutów. Do atrybutu 
odwołuje się zapisując po nazwie obiektu apostrof i podając nazwę atrybutu. Przykładowo, 
zapis A'Event oznacza atrybut, który staje się prawdą wówczas gdy nastąpiła zmiana wartości 
sygnału A (zdarzenie na sygnale A). Poniżej przedstawiono przykład wykorzystania atrybutów 
do liczenia parzystości sygnału o dowolnym rozmiarze.

process (A)
   variable TMP : std_ulogic;
begin
   TMP := '0';
   for I in A'low to A'high loop
      TMP := TMP xor A(I);
   end loop;
   ODD <= TMP;
end process;

- 22 -

Język opisu sprzętu VHDL

background image

Atrybuty  A'low  oraz  A'high  oznaczają   odpowiednio   najniższy   i   najwyższy   indeks 

sygnału A.

2.14. Pozostałe cechy języka

Język   VHDL   nie   interpretuje   wielkości   liter.   Elementy   języka   posiadają   takie   samo 

znaczenie niezależnie od tego czy pisane są małymi czy dużymi literami. 

Znakiem komentarze jest podwójny ciąg znaków minus: '--'. Pojawienie się tego ciągu w 

programie powoduje, że pozostała część linii programu traktowana jest jako komentarz.

Typowym   rozszerzeniem   plików   zawierających   programy   w   języku   VHDL   jest  vhd

Kompilatory języka na podstawie plików źródłowych tworzą pliki binarne, które mogą służyć 
do   symulacji   lub   programowania   układów   programowalnych.   Najmniejsza   kompilowalna 
jednostka nosi nazwę projektu.

VHDL traktuje wektor jako zbiór elementów tego samego typu, zgrupowanych razem dla 

wygody.   Wektor   (np.   bitów)   nie   jest   równoważny   żadnej   liczbie.   Dlatego   nie   można 
wykonywać na wektorze bitów operacji arytmetycznych, a operacje relacyjne mają sens tylko 
wówczas gdy wektory są tej samej długości. 

2.15. Przeładowanie operatorów

Przeładowanie operatorów oznacza możliwość zdefiniowania kilku funkcji o tej samej 

nazwie   ale   różnych   typach   wejść   i   wyjść.   W   szczególności   oznacza   to   możliwość 
wielokrotnego   definiowania   operatorów.   Zwykle   dostawcy   oprogramowania   dostarczają 
pakiety   zawierające   definicje   typowych   operatorów   dla   popularnych   typów   zmiennych. 
Poniżej przedstawiony przykład takiego pakietu.

package P_ARITHMETIC is
subtype
 slv is std_logic_vector;
function "+"(L:slv; R:slv) return integer;
function "+"(L:slv; R:slv) return slv;
function "+"(L:slv; R:integer) return slv;
function "+"(L:integer; R:slv) return slv;
end P_ARITHMETIC;

use work.P_ARITHMETIC.all;
entity OVERLOADED is
port (A_BUS,B_BUS: in  slv (0 to 3);
      A_INT,B_INT: in  integer;
      Y_BUS,Z_BUS: out slv (0 to 3);
      Y_INT,Z_INT: out integer);
end OVERLOADED;

Język opisu sprzętu VHDL

- 23 -

background image

3.

Strukturalny opis sprzętu

Strukturalny  opis   układu   cyfrowego   polega   na   opisaniu   w   języku   VHDL  elementów 

składowych   oraz   połączeń   między   nimi.   Zwykle   definiuje   się   pewną   liczbę   elementów 
podstawowych (np. podstawowe bramki logiczne) i w oparciu o nie buduje struktury bardziej 
złożone. Zachowania funkcjonalne wynikają ze sposobu połączeń elementów składowych. Ich 
funkcje   nie   są   nigdzie   zapisane   w   sposób   jawny   co   odróżnia   ten   sposób   zapisu   od 
behawioralnego opisu sprzętu.

Strukturalny   opis   sprzętu   jest   użyteczny   np.   w   sytuacji   gdy   niezbędne   jest   oddanie 

struktury istniejącego już rozwiązania (układu elektronicznego lub układu scalonego) i znany 
jest   jego   schemat   elektroniczny.   Wówczas   nie   wnikając   w   jego   funkcje   oraz   zależności 
czasowe   między   elementami   można   za   pomocą   opisu   strukturalnego   odzwierciedlić   jego 
zachowanie w języku VHDL.

Strukturalny sposób opisu sprzętu jest używany głównie przez programy komputerowe do 

automatycznej generacji programów w języku VHDL na podstawie np. schematów układów 
(np.   pochodzących   z   programu   ORCAD).   Umieszczenie   na   wyjściowym   schemacie   np. 
układów średniej skali integracji powoduje, iż program "rozpisuje" je na elementy składowe 
(zwykle bramki logiczne) tworząc kompletny strukturalny opis sprzętu umożliwiający jego 
praktyczną implementację.

Strukturalny opis sprzętu nie wydaje się być szczególnie efektywny przy opisie układu 

wykonywanym przez człowieka. W takim przypadku odpowiedniejszym sposobem wydaje się 
być   behawioralny   opis   zachowań.   Niemniej   podkreślić   należy,   iż   oba   sposoby   opisu   są 
zupełne i za pomocą każdego z nich można opisać każdą strukturę logiczną.

3.1.

Sumator 4-bitowy. Opis strukturalny

Jako przykład realizacji funkcji logicznej opisanej w języku VHDL w sposób strukturalny 

przedstawimy 4-bitowy sumator binarny. Sumator 4-bitowy składa się z bloków sumatorów 
jednobitowych o strukturze przedstawionej na Rys.3.1. Wejścia do sumatora stanowią dwie 
dodawane liczby A

i

  i B

i

  oraz przeniesienie z poprzedniej pozycji C

i-1

. Wyjściem jest wynik 

dodawania S

i

 oraz przeniesienie na następną pozycję C

i

.

Si

Ci-

1

Ci

Bi

Ai

A

B
C

C S

i

i

i

i

i

1

Rys.3.1. Jednobitowy sumator binarny.

- 24 -

Język opisu sprzętu VHDL

background image

Tablice Karnouhg oraz funkcje logiczne dla wyjść przedstawiono poniżej. Odpowiednio 

dla wyjścia sumy S

i

 jest to:

A

i

 B

i

C

i

C

i-1

00

01

11

10

0

0

0

1

0

1

0

1

1

1

Si = A

i

 and B

i

  or  C

i-1

 

and A

i

  or  C

i-1

 

and B

i

 = 

       (A

i

 nand B

i

)  nand  (C

i-1

 

nand A

i

)  nand  (C

i-1

 

nand B

i

)

oraz dla wyjścia przeniesienia na następną pozycję C

i

:

A

i

 B

i

S

i

C

i-1`

00

01

11

10

0

0

1

0

1

1

1

0

1

0

C

i

 = A

i

 xor B

i

 xor C

i-1

Sumator   4-bitowy   realizowany   jest   jako   kaskadowe   połączenie   czterech   sumatorów 

jednobitowych (Rys.3.2).

C2

C3

C4

C0

S4

B4

A4

C1

S3

B3

A3

S2

B2

A2

S1

B1

A1

Rys.3.2. Kaskadowy sumator 4-bitowy.

Realizacja   omawianej   struktury   sumatora   4-bitowego   w   programie   ORCAD 

przedstawiona została na Rys.3.3. Strukturalny opis sumatora w języku VHDL realizowany 
jest w bloku SumLogic. Porty wejściowe SW3_1 do SW3_8 oraz osiem buforów wejściowych 
IBUF służą do zadania wartości dwóch 4-bitowych składników. Porty oraz bufory wyjściowe 
służą do wyprowadzenia wyniku. 

Język opisu sprzętu VHDL

- 25 -

background image

SumLogic

SumLogic

S[4..0]

A[3..0]

B[3..0]

A[3..0]

B[3..0]

S[4..0]

RD

RT

A3

B1

A1

B2

A0

A2

B3

B0

S4

S1

S0

S2

S3

U14

OBUF

U1

IBUF

U17

IBUF

MD0

U16

MD0

MD1

U15

MD1

CLK

TRIG

DATA

RIP

U13

READBACK

U2

IBUF

U3

IBUF

U4

IBUF

U6

IBUF

U8

IBUF

U10

IBUF

U5

IBUF

U12

OBUF

U18

OBUF

U7

OBUF

U11

OBUF

U9

OBUF

SW3_1

SW3_2

SW3_3

SW3_4

SW3_5

SW3_6

SW3_7

SW3_8

LOWER2_PIN

LOWER1_PIN

UPPER0_PIN

LOWER0_PIN

LOWER3_PIN

P19

P20

P23

P24

P25

P26

P27

P28

P57

P62

P61

P65

P66

Rys.3.3. Realizacja 4-bitowego sumatora binarnego w programie ORCAD.

- 26 -

Język opisu sprzętu VHDL

background image

Omawiany przykład zrealizowany został na układzie programowalnym firmy XILINX o 

numerze   4008.   Etykiety   nadane   sygnałom   za   portami   wejściowymi   oraz   przed   portami 
wyjściowymi o postaci Pxx definiują numery wyprowadzeń układu 4008. Np. P28 definiuje 
wyprowadzenie układu o numerze 28. 

Blok READBACK wraz z elementami wejściowymi oraz wyjściowymi dodany został w 

celu weryfikacji poprawności zapisu danych do układu 4008. Jego obecność jest opcjonalna.

Program w języku VHDL związany z blokiem SumLogic przedstawiono poniżej. Zawiera 

on deklarację trójwejściowej bramki XOR  xor3, dwuwejściowej bramki NAND nand2  oraz 
trójwejściowej   bramki   NAND  nand3.   Na   ich   podstawie   zdefiniowano   blok   sumatora 
jednobitowego  Sum1Bit.   Z   kolei   ten   sumator   jednobitowy   służy   do   definicji   sumatora 
czterobitowego SumLogic

Strukturalny   opis   elementu   rozpoczyna   się   od   wyspecyfikowania   części   składowych 

deklarowanych za pomocą komendy  COMPONENT. Po słowie kluczowym  COMPONENT 
następuje nazwa komponentu, a po słowie kluczowym PORT specyfikacja wejść oraz wyjść 
komponentu wraz z podaniem ich typów. Dyrektywy postaci:

   FOR ALL : xor3gate USE ENTITY xor3;

określają jaki blok ENTITY związany jest z deklarowanymi komponentami. Dyrektywy PORT 
MAP
  przypisują odpowiednie sygnały do odpowiednich wejść oraz wyjść poszczególnych 
komponentów. Przykładowo dla deklaracji bloku ENTITY:

ENTITY xor3 is

PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

I3

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ;

END xor3;

komendy:

  COMPONENT xor3gate PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

I3

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ; END COMPONENT;

   FOR ALL : xor3gate USE ENTITY xor3;
--
--
  st1 : xor3gate PORT MAP ( A,  B,  Ci, Co );     -- Co

przyporządkowują  komponent  xor3gate  do  bloku  ENTITY  xor3  oraz   wiążą  z  bramką  st1 
sygnały ABCi oraz Co w taki sposób, że sygnały Aoraz Ci są wejściami i odpowiadają 

Język opisu sprzętu VHDL

- 27 -

background image

sygnałom  I1,  I2  oraz  I3  oraz  sygnał  Co  jest  wyjściem odpowiadającym wyjściu  O  bloku 
ENTITY o nazwie xor3.

Kompletna implementacja bloku SumLogic przedstawiona została poniżej.

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY xor3 is

PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

I3

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ;

END xor3;

ARCHITECTURE behavior_xor3 OF xor3 IS
BEGIN
  O <= I1 xor I2 xor I3;
END behavior_xor3;

Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY nand2 is

PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ;

END nand2;

ARCHITECTURE behavior_nand2 OF nand2 IS
BEGIN
  O <= not (I1 and I2);
END behavior_nand2;

Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY nand3 is

PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

I3

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ;

END nand3;

ARCHITECTURE behavior_nand3 OF nand3 IS
BEGIN
  O <= not (I1 and I2 and I3);
END behavior_nand3;

Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY Sum1Bit is

- 28 -

Język opisu sprzętu VHDL

background image

PORT (

A

: IN STD_LOGIC;

B

: IN STD_LOGIC;

Ci

: IN STD_LOGIC;

S

: OUT STD_LOGIC;

               Co

: OUT STD_LOGIC ) ;

END Sum1Bit;

ARCHITECTURE behavior_Sum1Bit OF Sum1Bit IS
  COMPONENT xor3gate PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

I3

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ; END COMPONENT;

  COMPONENT nand2gate PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ; END COMPONENT;

  COMPONENT nand3gate PORT (

I1

: IN STD_LOGIC;

I2

: IN STD_LOGIC;

I3

: IN STD_LOGIC;

O

: OUT STD_LOGIC ) ; END COMPONENT;

   FOR ALL : xor3gate USE ENTITY xor3;
   FOR ALL : nand2gate USE ENTITY nand2;
   FOR ALL : nand3gate USE ENTITY nand3;
   SIGNAL t1, t2, t3 : STD_LOGIC;
BEGIN
  st1 : xor3gate PORT MAP ( A,  B,  Ci, Co );     -- Co
  st2 : nand2gate PORT MAP ( A,  B,  t1 );
  st3 : nand2gate PORT MAP ( A,  Ci,  t2 );
  st4 : nand2gate PORT MAP ( B,  Ci,  t3 );
  st5 : nand3gate PORT MAP ( t1, t2, t3, S );     -- S
END behavior_Sum1Bit;

Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY SumLogic is

PORT (

S

: OUT STD_LOGIC_VECTOR (4 DOWNTO 0);

A

: IN STD_LOGIC_VECTOR (3 DOWNTO 0);

B

: IN STD_LOGIC_VECTOR (3 DOWNTO 0));

END SumLogic;

ARCHITECTURE behavior OF SumLogic IS

  COMPONENT S1B 

PORT (

A

: IN STD_LOGIC;

B

: IN STD_LOGIC;

Ci

: IN STD_LOGIC;

S

: OUT STD_LOGIC;

               Co

: OUT STD_LOGIC ) ;  END COMPONENT;

   FOR ALL : S1B USE ENTITY Sum1Bit;

   SIGNAL C0, C1, C2, C3, C4 : STD_LOGIC;

Język opisu sprzętu VHDL

- 29 -

background image

BEGIN
  C0 <= '0';

  st1 : S1B PORT MAP ( A(0),  B(0), C0, S(0),C1 );
  st2 : S1B PORT MAP ( A(1),  B(1), C1, S(1),C2 );
  st3 : S1B PORT MAP ( A(2),  B(2), C2, S(2),C3 );
  st4 : S1B PORT MAP ( A(3),  B(3), C3, S(3),C4 );

  S(4) <= C4;
END behavior;

Ze względu na niską efektywność tworzenia układów logicznych opisywanych w sposób 

strukturalny ten sposób opisu nie będzie omawiany w dalszej części niniejszej publikacji. 
Niemniej należy mieć świadomość, że wobec faktu automatycznej generacji przez program 
ORCAD   opisów   w   języku   VHDL   wprowadzonych   schematów   znajomość   zasad 
strukturalnego opisu logiki może okazać się niezbędna.

3.2.

Generator numerów górników. Projekt w postaci schematu  
elektrycznego

Jednym   ze   sposobów   zaprogramowanie   programowalnych   układów   logicznych   jest 

narysowanie schematu elektronicznego projektowanego układu. W sposobie tym pośrednio 
wykorzystywany jest strukturalny opis sprzętu bowiem program ORCAD z wprowadzonego 
schematu   w   sposób   automatyczny  generuje   program   w   języku   VHDL,  który  z   kolei   jest 
podstawą do wygenerowania ciągu bitowego programującego programowalny układ logiczny.

Poniżej   omówiono   aplikację,   której   celem   była   lokalizacja   położenia   górników   w 

kopalni. System lokalizacji składa się z nadajników rozmieszczonych w chodnikach kopalni 
oraz   z   odbiorników   przenoszonych   przez   każdego   górnika.   Każdy   z   nadajników   nadaje 
kolejno wszystkie kombinacje 13-bitowych numerów w formacie przedstawionym na Rys.3.4. 
Każdy z odbiorników jednoznacznie związany z określonym górnikiem posiada "zaszyty" w 
sobie   unikalny  numer   13-bitowy.   Jeżeli   odbiornik   znajdzie   się   w  strefie   pracy  nadajnika 
wysyła   potwierdzenie   umożliwiające   lokalizacje   konkretnego   górnika.   Schematy   ideowe 
układu nadajnika oraz odbiornika przedstawiono na Rys.3.5, Rys.3.6 oraz Rys.3.7.

Realizacja   poprzez   wprowadzenie   schematu   elektronicznego   układu   była   w   tym 

przypadku   szczególnie   efektywna   bowiem   znany   był   schemat   elektroniczny   poprawnie 
pracującego układu. W dalszej części opracowania przedstawiony zostanie układu nadajnika 
oraz odbiornika zrealizowany poprzez behawioralny opis funkcji w języku VHDL. 

- 30 -

Język opisu sprzętu VHDL

background image

Bity przerwy

7 bitów numeru

6 bitów numeru

Bity o wartości '0'

Rys.3.4. Format numeru.

Warto zauważyć, iż pierwotna realizacja układu wykonana w oparciu o układy TTL oraz 

CMOS średniej skali integracji wymagała wykorzystania po kilkanaście układów zarówno po 
stronie   odbiornika   jak   i   nadajnika.   Wykorzystując   układy  programowalne   firmy  XILINX 
można do układu 4003 "wpisać" zarówno nadajnik jak i odbiornik wykorzystując tylko około 
50%   pojemności   układu.   Dodatkowymi   zaletami   są   niezwykła   elastyczność 
przeprogramowania   układu   oraz   redukcja   zużycia   mocy  szczególnie   istotna   w  przypadku 
zasilania bateryjnego.

Nadajnik1

Nadajnik

Reset

Numer

Nad_Clock

Odbior

Odbior

Odb_reset

Odb_Numer

Jest_nr

Odb_Clock

U24

INV

D

Q

C

U25

FD_1

U26

INV

SW5

Numer

Out70

JEST

Clock

P18

P14

P70

P68

P67

Rys.3.5. Blokowy schemat układu nadajnika oraz odbiornika.

Język opisu sprzętu VHDL

- 31 -

background image

INT_RESET

NUMER

INPUT

U7

AND4

U22

OR2

U19

VCC

Q

J

K

CLR

C

U16

FJKC

U20
INV

Q

J

K

CLR

C

U4

FJKC

U9
INV

U5
INV

U18

VCC

U21

OR2

U3
X74_150

E0E1E2E3E4E5E6E7E8E9E10

E11

E12

E13

E14

E15

A B C

D G

W

U1

NAND2

U14
CB4CE

CEC CLR

Q0Q1Q2Q3

CEO

TC

U13
CB4CE

CEC CLR

Q0Q1Q2Q3

CEO

TC

U12
CB4CE

CEC CLR

Q0Q1Q2Q3

CEO

TC

U15
CB4CE

CEC CLR

Q0Q1Q2Q3

CEO

TC

U11
CB4CE

CEC CLR

Q0Q1Q2Q3

CEO

TC

Q

J K

CLR

C

U6
FJKC

U8

VCC

U17
AND4

D

Q

C

U2

FD_1

U10
OSC4

F8M

F500K

F16K

F490

F15

U23

INV

Reset

Numer

Nad_Clock

Rys.3.6. Schemat ideowy nadajnika numerów.

- 32 -

Język opisu sprzętu VHDL

background image

CLOCK

NUMER_OK

U44

NAND2

U46

NAND2

U57

AND2

U56

NAND2

U63
X74_164

A B CK

CLR

QA

QB

QC

QD

QE

QF

QG

QH

U60

NAND2

U55

AND2

U45

AND2

U42

NAND2

U48
INV

U39

AND2

U49

AND2

U34

NAND2

U36

NAND2

U31
NAND8

U51

AND2

U33

AND2

U62

AND2

U61

AND2

U54

NAND2

U52

NAND2

Q

J

K

CLR

C

U27

FJKC

U28
NOR2

U35

AND2

U38

NAND2

U53

AND2

U50

NAND2

U37

AND2

U32
NAND8

U40

NAND2

U59

AND2

U65

INV

U43

AND2

U47

AND2

U64
X74_164

A B CK

CLR

QA

QB

QC

QD

QE

QF

QG

QH

U41

AND2

U58

NAND2

U29
OR2

D

Q

CLRC

U30

FDC_1

Odb_reset

Odb_Numer

Jest_nr

Odb_Clock

Rys.3.7. Schemat ideowy odbiornika numerów umożliwiający detekcje konkretnego numeru.

Język opisu sprzętu VHDL

- 33 -

background image

4.

Behawioralny opis sprzętu

Behawioralny  opis   sprzętu   polega   na   opisie   w   języku   VHDL   funkcji   układu,   a   nie 

struktury  połączeń   elementów.   Zamiast   używać   instrukcji   definiujących   komponenty  oraz 
połączenia między nimi używa się operatorów, instrukcji podstawienia, definicji procesów, 
instrukcji  pętli,   rozgałęzień  itp.  Opis behawioralny  przypomina  zapis  algorytmu  w  takich 
językach programowania jak C lub Pascal. 

Poniżej przedstawiono opis behawioralny funkcji sumatora jednobitowego omawianego 

w poprzednim rozdziale. Warto zwrócić uwagę na znacznie bardziej zwarty i czytelny zapis 
wewnątrz bloku ARCHITEKTURE w porównaniu z opisem strukturalnym.

ENTITY Sum1Bit is

PORT (

A

: IN STD_LOGIC;

B

: IN STD_LOGIC;

Ci

: IN STD_LOGIC;

S

: OUT STD_LOGIC;

               Co

: OUT STD_LOGIC ) ;

END Sum1Bit;

ARCHITECTURE behavior_Sum1Bit OF Sum1Bit IS
BEGIN
  S <= ( A and B ) or ( A and Ci ) or ( B and Ci );
  Co <= A xor B xor Ci;
END behavior_Sum1Bit;

Poniżej   przedstawiono   wybrane   techniki   programowania   używane   podczas 

behawioralnego opisu zachowania układów cyfrowych. 

4.1.

Wielokrotne wywołanie procesu

Rozważmy przykład:

EXAMPLE: process (A, B, M)
begin
   Y <= A;
   M <= B;
   Z <= M;
end process EXAMPLE;

- 34 -

Język opisu sprzętu VHDL

background image

Występuje tutaj przypisanie do sygnału M oraz sygnał M znajduje się jednocześnie na 

liście aktywacyjnej procesu. W instrukcji M <= B; sygnał M nie zmienia się ponieważ zmiany 
następują dopiero po zakończeniu procesu. W związku z tym nie nastąpi zmiana wartości 
sygnału  Z  (ściśle mówiąc nowa wartość sygnału  Z  będzie równa wartości sygnału  B). Gdy 
proces się zakończy  M  jest zmieniane na wartość  B, ale  Z  zmienia wartość na poprzednią 
wartość  M. Ale  M  się zmieniło i  M  jest na liście aktywacyjnej więc proces jest powtórnie 
wywoływany. To spowoduje zmianę wartości sygnału ZJest to więc sposób na wielokrotne 
wywołanie procesu
.

4.2.

Definiowanie rejestrów

Poniższy program opisuje przerzutnik typu D wyzwalany narastającym zboczem:

entity FLOP is
port
 (D, CLK : in std_ulogic;
      Q     : out std_ulogic);
end FLOP;

architecture A of FLOP is
begin
  process
  begin
    wait until CLK'event and CLK='1';
    Q <= D;
  end process;
end A;

Wyjście  Q  jest  uaktualniane  tylko wówczas gdy CLK się zmieniło  i gdy jest '1' czyli  w 
odpowiedzi na narastające zbocze. Proces jest taktowany sygnałem zegarowym CLK.

Narastającego zbocze może zostać również wykryte za pomocą następującej sekwencji 

instrukcji:

process (CLK)
begin
   if (CLK'event and CLK='1') then
      Q <= D;
   end if;
end process;

lub za pomocą:

library IEEE;
use IEEE.Std_Logic_1164.all
...
process
begin

Język opisu sprzętu VHDL

- 35 -

background image

   wait until RISING_EDGE(CLK);
   Q <= D;
end process;

Ostatni sposób nie zawsze jest dostępny.

Przerzutnik przezroczysty typu "latch" może zostać zaimplementowany w następujący 

sposób:

process (EN, D)
   begin
      if (EN = '1') then
         Q <= D;
      end if;
   end process;

Gdy  EN=1  to   przerzutnik   jest   przezroczysty,   gdy  nie   to   podtrzymuje   poprzednią 

wartość.   Jest   to   tzw.   "incomplete   assigment"   występujący   wówczas   gdy   wartość   jest 
przypisana do zmiennej w jednej części instrukcji if, a w innej nie.

Poniżej przedstawiono implementacje wybranych typów przerzutników. Są to kolejno:

przerzutnik typu D z asynchronicznym wejściem zerującym,

przerzutnik typu D z synchronicznym wejściem zerującym,

przerzutnik typu D wyzwalany zboczem narastającym,

przerzutnik D typu latch,

przerzutnik D typu latch z asynchronicznym wejściem zerującym.

-- D F/F with asynchronous Reset
--   CLK: in STD_LOGIC;
--   RESET: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

process (CLK, RESET)
begin
   if RESET='1' then --asynchronous RESET active High
      DOUT <= '0';
   elsif (CLK'event and CLK='1') then  --CLK rising edge
      DOUT <= DIN;
   end if;
end process;

-- D F/F with synchronous Reset
--   CLK: in STD_LOGIC;
--   RESET: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

process (CLK)
begin
   if CLK'event and CLK='1' then  --CLK rising edge
      if RESET='1' then

--synchronous RESET active High

- 36 -

Język opisu sprzętu VHDL

background image

         DOUT <= '0';
      else
         DOUT <= DIN;
      end if;
   end if;
end process;

-- D Flip-Flop
--   CLK: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

process (CLK)
begin
   if CLK'event and CLK='1' then  --CLK rising edge
      DOUT <= DIN;
   end if;
end process;

-- D Latch 
--   GATE: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

process (GATE, DIN)
begin
   if GATE='1' then  --GATE active High
      DOUT <= DIN;
   end if;
end process;

-- D Latch with Reset
--   GATE: in STD_LOGIC;
--   RESET: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

process (GATE, DIN, RESET)
begin
   if RESET='1' then --RESET active High
      DOUT <= '0';
   elsif GATE='1' then  --GATE active High
      DOUT <= DIN;
   end if;
end process;

4.3.

Czterobitowy rejestr z równoległym ładowaniem i  
asynchronicznym zerowaniem

Przykład   rejestru   czterobitowego   z   równoległym   ładowaniem   i   asynchronicznym 

zerowaniem przedstawiono poniżej.

-- 4-bit parallel load register with asynchronous reset

Język opisu sprzętu VHDL

- 37 -

background image

--   CLK: in STD_LOGIC;
--   ASYNC: in STD_LOGIC;
--   LOAD: in STD_LOGIC;
--   DIN: in STD_LOGIC_VECTOR(3 downto 0);
--   DOUT: out STD_LOGIC_VECTOR(3 downto 0);

process (CLK, ASYNC)
begin
   if ASYNC='1' then
      DOUT <= "0000";
   elsif CLK='1' and CLK'event then
      if LOAD='1' then
         DOUT <= DIN;
      end if;
   end if;
end process;

4.4.

Czterobitowy binarny licznik asynchroniczny

Poniżej   przedstawiono   implementację   czterobitowego   binarnego   licznika 

asynchronicznego.

-- 4-bit asynchronous binary counter
--   CLK: in STD_LOGIC;
--   RESET: in STD_LOGIC;
--   COUNT: out STD_LOGIC_VECTOR(3 downto 0);

-- The declaration of the auxiliary signal COUNTER must be inserted in
-- the architecture declarative part.
-- The output port "COUNT" cannot appear on the right side of assignment
-- statements.

signal COUNTER: STD_LOGIC_VECTOR(3 downto 0);

process (CLK, COUNTER, RESET)

begin
   if RESET='1' then  
      COUNTER <= "0000"; 
   else
      if CLK'event and CLK='1' then
         COUNTER(0) <= not COUNTER(0);
      end if;
      if COUNTER(0)'event and COUNTER(0)='0' then
         COUNTER(1) <= not COUNTER(1);
      end if;
      if COUNTER(1)'event and COUNTER(1)='0' then
         COUNTER(2) <= not COUNTER(2);
      end if;
      if COUNTER(2)'event and COUNTER(2)='0' then
         COUNTER(3) <= not COUNTER(3);

- 38 -

Język opisu sprzętu VHDL

background image

      end if;
   end if;
end process;   
COUNT <= COUNTER;

4.5.

Konwerter kodu BCD na kod wyświetlacza siedmiosegmentowego

W   przypadku   układów   wykorzystujących   wyświetlacze   siedmiosegmentowe   LED 

częstym problemem jest przekodowanie liczby w zakresie od 0 do 9 zapisanej w kodzie BCD 
na kod wyświetlacza. Poniżej przedstawione zostało rozwiązanie tego problemu. Ciągi bitowe 
zwracane   w   zmiennej  LED  sterują   poprawnie   poszczególnymi   segmentami   wyświetlacza 
jeżeli zostały one podłączone do kolejnych bitów w sposób objaśniony w komentarzu.

--HEX-to-seven-segment decoder
-- HEX:

in 

STD_LOGIC_VECTOR (3 downto 0);

-- LED:

out

STD_LOGIC_VECTOR (6 downto 0);

--
-- podlaczenie segmentow wyswietlacza
-- do kolejnych bitow zmiennej LED
--      0
--     ---  
--  5 |   | 1
--     ---   <- 6
--  4 |   | 2
--     ---
--      3

    with HEX select

LED<= "1111001" when "0001", --1

"0100100" when "0010", --2
"0110000" when "0011", --3
"0011001" when "0100", --4
"0010010" when "0101", --5
"0000010" when "0110", --6
"1111000" when "0111", --7
"0000000" when "1000", --8
"0010000" when "1001", --9
"0001000" when "1010", --A
"0000011" when "1011", --b
"1000110" when "1100", --C
"0100001" when "1101", --d
"0000110" when "1110", --E
"0001110" when "1111", --F
"1000000" when others; --0

4.6.

Multiplekser 4 na 1

Poniższy przykład realizuje multiplekser o czterech wejściach  A,  B,  C,  D  oraz jednym 

wyjściu MUX_OUT. Sygnał SEL pełni rolę wejścia adresowego.

Język opisu sprzętu VHDL

- 39 -

background image

-- 4 to 1 multiplexer design with case construct
--   SEL: in STD_LOGIC_VECTOR(0 to 1);
--   A, B, C, D:in STD_LOGIC;
--   MUX_OUT: out STD_LOGIC;

process (SEL, A, B, C, D)
begin
   case SEL is
      when "00" => MUX_OUT <= A;
      when "01" => MUX_OUT <= B;
      when "10" => MUX_OUT <= C;
      when "11" => MUX_OUT <= D;
      when others => MUX_OUT <= 'X';
   end case;
end process;

4.7.

Czterobitowy rejestr przesuwający

Poniżej   przedstawiono   realizację   czterobitowego   rejestru   przesuwnego   o   szeregowym 

wejściu oraz o szeregowym wyjściu.

-- 4-bit serial-in and serial-out shift register
--   CLK: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

process (CLK)
   variable REG: STD_LOGIC_VECTOR(3 downto 0);
begin
   if CLK'event and CLK='1' then  
      REG := DIN & REG(3 downto 1);
   end if;
   DOUT <= REG(0);
end process;   

4.8.

Czterobitowy licznik synchroniczny z wejściem zezwalającym na  
zliczanie, asynchronicznym zerowaniem i synchronicznym  
ładowaniem

Poniżej   widoczna   jest   implementacja   czterobitowego   licznika   synchronicznego   z 

wejściem   zezwalającym   na   zliczanie,   asynchronicznym   zerowaniem   i   synchronicznym 
wpisem równoległym.

-- 4-bit synchronous counter with count enable, asynchronous reset and synchronous load
--   CLK: in STD_LOGIC;
--   RESET: in STD_LOGIC;
--   CE, LOAD, DIR: in STD_LOGIC;

- 40 -

Język opisu sprzętu VHDL

background image

--   DIN: in INTEGER range 0 to 15;
--   COUNT: out INTEGER range 0 to 15;

process (CLK, RESET)

--auxiliary variable COUNTER declaration
--the output port "COUNT" cannot appear on the right side of assignment
-- statements
variable COUNTER: INTEGER range 0 to 15;
begin
   if RESET='1' then
      COUNTER := 0;
   elsif CLK='1' and CLK'event then
      if LOAD='1' then
         COUNTER := DIN;
      else
         if CE='1' then
            if DIR='1' then   
               if COUNTER = 15 then
                  COUNTER := 0;
               else
                  COUNTER := COUNTER + 1;
               end if;
            else
               if COUNTER = 0 then
                  COUNTER := 15;
               else
                  COUNTER := COUNTER - 1;
               end if;
            end if;
         end if;
      end if;
   end if;
   COUNT <= COUNTER;
end process;

4.9.

Bufor trójstanowy

Poniżej przedstawiono przykład realizacji bufora trójstanowego.

-- Tristate Buffer
--   ENABLE: in STD_LOGIC;
--   DIN: in STD_LOGIC;
--   DOUT: out STD_LOGIC;

DOUT <= DIN when ENABLE='1' else 'Z';

4.10. Funkcja konwersji typu bit_vector do typu integer

Język opisu sprzętu VHDL

- 41 -

background image

W   języku   VHDL   ciągi   bitów   nie   reprezentują   sobą   żadnej   wartości.   Poniżej 

przedstawiono   przykład   funkcji,   która   przyjmuje   jako   argument   wektor   bitowy  i   zwraca 
odpowiadającą mu w kodzie binarnym liczbę całkowitą.

function bit_vec2int(A : BIT_VECTOR) return integer is
variable RESULT: integer:=0;
variable TMP: integer:=1;
begin
  if A'length = 0 
    then return RESULT; 
  end if;
  for i in A'reverse_range loop
    if a(i)='1' 
      then RESULT:=RESULT+TMP; 
    end if;
    TMP:=TMP*2;
  end loop;
  return RESULT;
end;

4.11. Automat o skończonej liczbie stanów

Automat o skończonej liczbie stanów( FSM - ang. Finite State Machine) składa się ze 

skończonej, określonej liczby stanów oraz operacji definiujących przejścia miedzy stanami. 
Ogólna struktura maszyny stanowej przedstawiona jest na rysunku poniżej:

Rejestr

Stanu

Wyjście

Następny

Stan

Zegar

Rys.4.1. Struktura automatu FSM.

Zdefiniujmy FSM posiadającą cztery stany typu definiowanego przez użytkownika:

architecture RTL of FSM is
  type T_STATE is (IDLE, RW_CYCLE, INT_CYCLE, DMA_CYCLE);
  signal NEXT_STATE, STATE : T_STATE;
begin
  ...

- 42 -

Język opisu sprzętu VHDL

background image

Zdefiniowane   są   trzy  sygnały  wejściowe:  RW,INT_REQ  oraz  DMA_REQ.   Ogólny  format 
maszyny FSM wygląda w sposób następujący:

NS: process(STATE,RW,INT_REQ,DMA_REQ)
  begin
    case STATE is
      when IDLE =>
        -- statements
      when RW_CYCLE =>
        -- statements
      when INT_CYCLE =>
        -- statements
      when DMA_CYCLE =>
        -- statements
   end case
end process NS;

Szczegółowa implementacja może posiadać postać:

NS: process(STATE,RW,INT_REQ,DMA_REQ)
begin
  NEXT_STATE <= STATE;
  case STATE is
    when IDLE =>
      if (INT_REQ = '1') then
        NEXT_STATE <= INT_CYCLE;
      elsif (DMA_REQ = '1') then
        NEXT_STATE <= DMA_CYCLE;
      end if;
    when RW_CYCLE =>
      -- statements
    ...
end process NS;

Proces NS jest czuły na wejścia oraz sygnał stanu. Każda gałąź case definiuje nową wartość 
stanu.

Implementacja rejestru stanu może przybrać postać:

REG : process (CLK, RST)
begin
  if RST = '1' then
    STATE <= IDLE;
  elsif CLK'event and CLK ='1' then
    STATE <= NEXT_STATE;
  end if;
end process REG;

Język opisu sprzętu VHDL

- 43 -

background image

4.12. Implementacja układów z rodziny TTL

Poniżej  przedstawiono dwa przykłady realizacji  w języku VHDL układów rodziny 

TTL. Zwykle każda implementacja języka zawiera odpowiednią bibliotekę definiującą funkcje 
najbardziej popularnych układów scalonych z rodzin TTL oraz CMOS.

4.12.1.

Implementacja układu 7400

LIBRARY ieee;
USE ieee.std_logic_1164.all;

USE work.orcad_prims.all;

ENTITY \74S00\ IS PORT(
I0_A : IN  std_logic;
I0_B : IN  std_logic;
I0_C : IN  std_logic;
I0_D : IN  std_logic;
I1_A : IN  std_logic;
I1_B : IN  std_logic;
I1_C : IN  std_logic;
I1_D : IN  std_logic;
O_A : OUT  std_logic;
O_B : OUT  std_logic;
O_C : OUT  std_logic;
O_D : OUT  std_logic;
VCC : IN  std_logic;
GND : IN  std_logic);
END \74S00\;

ARCHITECTURE model OF \74S00\ IS

    BEGIN
    O_A <= NOT ( I0_A AND I1_A ) AFTER 5 ns;
    O_B <= NOT ( I0_B AND I1_B ) AFTER 5 ns;
    O_C <= NOT ( I1_C AND I0_C ) AFTER 5 ns;
    O_D <= NOT ( I1_D AND I0_D ) AFTER 5 ns;
END model;

4.12.2.

Implementacja układu 74138

LIBRARY ieee;
USE ieee.std_logic_1164.all;

USE work.orcad_prims.all;

ENTITY \74S138\ IS PORT(
A : IN  std_logic;
B : IN  std_logic;
C : IN  std_logic;
G1 : IN  std_logic;
G2A : IN  std_logic;

- 44 -

Język opisu sprzętu VHDL

background image

G2B : IN  std_logic;
Y0 : OUT  std_logic;
Y1 : OUT  std_logic;
Y2 : OUT  std_logic;
Y3 : OUT  std_logic;
Y4 : OUT  std_logic;
Y5 : OUT  std_logic;
Y6 : OUT  std_logic;
Y7 : OUT  std_logic;
VCC : IN  std_logic;
GND : IN  std_logic);
END \74S138\;

ARCHITECTURE model OF \74S138\ IS
    SIGNAL L1 : std_logic;
    SIGNAL N1 : std_logic;
    SIGNAL N2 : std_logic;
    SIGNAL N3 : std_logic;
    SIGNAL N4 : std_logic;
    SIGNAL N5 : std_logic;
    SIGNAL N6 : std_logic;
    SIGNAL N7 : std_logic;
    SIGNAL N8 : std_logic;

    BEGIN
    N1 <=  ( A ) AFTER 7 ns;
    N2 <=  ( B ) AFTER 7 ns;
    N3 <=  ( C ) AFTER 7 ns;
    N4 <= NOT ( A ) AFTER 6 ns;
    N5 <= NOT ( B ) AFTER 6 ns;
    N6 <= NOT ( C ) AFTER 6 ns;
    N7 <=  ( G1 ) AFTER 6 ns;
    N8 <= NOT ( G2A OR G2B ) AFTER 6 ns;
    L1 <=  ( N7 AND N8 );
    Y0 <= NOT ( N4 AND N5 AND N6 AND L1 ) AFTER 5 ns;
    Y1 <= NOT ( N1 AND N5 AND N6 AND L1 ) AFTER 5 ns;
    Y2 <= NOT ( N4 AND N2 AND N6 AND L1 ) AFTER 5 ns;
    Y3 <= NOT ( N1 AND N2 AND N6 AND L1 ) AFTER 5 ns;
    Y4 <= NOT ( N4 AND N5 AND N3 AND L1 ) AFTER 5 ns;
    Y5 <= NOT ( N1 AND N5 AND N3 AND L1 ) AFTER 5 ns;
    Y6 <= NOT ( N4 AND N2 AND N3 AND L1 ) AFTER 5 ns;
    Y7 <= NOT ( N1 AND N2 AND N3 AND L1 ) AFTER 5 ns;
END model;

Język opisu sprzętu VHDL

- 45 -

background image

5.

Wykaz funkcji języka VHDL

5.1.

Atrybuty

Zmienne,   funkcje,   typy,   sygnały   oraz   stałe   posiadają   związane   z   nimi   atrybuty. 

Dodatkowo   programista   ma   możliwość   definiowania   własnych   nowych   atrybutów.   Typy 
predefiniowane przedstawiono w poniższej tabeli.

Atrybut

Typ wyniku

Wynik

Atrybuty typów

T'Base

typ basowy typu T; wówczas gdy typ T jest podtypem

Atrybuty skalarów

T'Left

jak T

najbardziej lewostronna wartość T

T'Right

jak T

najbardziej prawostronna wartość T

T'Low

jak T

najmniejsza wartość T

T'Right

jak T

największa wartość T

T'Ascending

boolean

true jeżeli T jest uporządkowane rosnąco; jeżeli nie to 
false

T'Image(x)

string

tekstowa reprezentacja wartości x typu T

T'Value(s)

typ bazowy T wartość w T reprezentowana przez string s

Atrybuty dyskretnych lub fizycznych typów lub podtypów

T'Pos(s)

integer

numer pozycji występowania s w T

T'Val(x)

typ bazowy T wartość na pozycji x w T

T'Succ(s)

typ bazowy T wartość na pozycji o jeden większej niż s w T

T'Pred(s)

typ bazowy T wartość na pozycji o jeden mniejszej niż s w T

T'Leftof(s)

typ bazowy T wartość na pozycji o jeden w lewo niż s w T

T'Rightof(s)

typ bazowy T wartość na pozycji o jeden w prawo niż s w T

Atrybuty tablic

A'Left(n)

lewy zakres indeksu o numerze n

A'Right(n)

prawy zakres indeksu o numerze n

A'Low(n)

dolna granica indeksu o numerze n

A'High(n)

górna granica indeksu o numerze n

- 46 -

Język opisu sprzętu VHDL

background image

A'Range(n)

zakres indeksu o numerze n

A'Reverse_range(n)

odwrócony zakres indeksu o numerze n

A'Length(n)

liczba wartości w indeksie o numerze n

A'Ascending(n)

boolean

thue jeżeli wartości o numerze n nawastają; false jeżeli 
opadają

Atrybuty sygnałów

S'Delayed(t)

równy sygnałowi S ale opóźniony o t

S'Stable(t)

boolean

true jeżeli sygnał nie zmienił się przez okres czasu t; w 
przeciwnym przypadku false

S'Quiet(t)

boolean

true jeżeli sygnał nie miał transakcji przez okres czasu 
t; w przeciwnym przypadku false

S'Transaction

boolean

wartość zmieniająca się w każdym cyklu symulacji w 
którym nastąpiła transakcja na sygnale S

S'Event

boolean

true   jeżeli   sygnał   się   zmienił;   w   przeciwnym 
przypadku false

S'Active

true jeżeli sygnał miał transakcję w aktualnym cyklu 
symulacji; w przeciwnym przypadku false

S'Last_event

czas   od   ostatniego   zdarzenia,   które   wystąpiło   na 
sygnale S

S'Last_active

czas od ostatniej transakcji, która wystąpiła na sygnale 
S

S'Last_value

wartość sygnału S poprzedzająca ostatnie zdarzenie

S'Driving

true   jeżeli   proces   steruje   sygnałem   S;   false   w 
przeciwnym przypadku

S'Driving_value

aktualna   wartość   dla   sterownika   związanego   z 
sygnałem S

Atrybuty nazw

E'Simple_name

string

string pojawiający się w deklaracji E

E'Path_name

string

string poprzez hierarchiczną ścieżkę opisujący E

5.2.

Definicja tablic

Tablica jest zmienną  złożoną  z elementów  tej  samej  wartości. Do elementów  tablicy 

dostajemy się poprzez  podanie indeksu (dla tablic  jednowymiarowych) lub indeksów (dla 
tablic wielowymiarowych). 

type BYTE is array ( 0 to 7 ) of BIT;   -- definicja typu tablicy

Język opisu sprzętu VHDL

- 47 -

background image

type L4Vect is array ( 1 to 8, 1 to 2 ) of L4;   -- dwuwymiarowa tablica

type X is ( LOW, HIGH );

type X1 is array ( 0 to 7, X ) of BIT;   -- dwuwymiarowa tablica

5.3.

Instrukcja case

Instrukcja  case  służy   do   wyboru   do   wykonania   jednej   z   kilku   sekwencji   instrukcji. 

Ogólny format instrukcji wygląda w sposób następujący:

case wyrażenie is

when wybów1 => sekwencja 1;
when wybów2 => sekwencja 2;
......
end case;

Każda możliwa wartość wyrażenia musi posiadać odpowiedni jeden i tylko jeden wybór 

związany z odpowiednim wyborem. 

P1:process 
variable x: Integer range 1 to 3;
variable y: BIT_VECTOR (0 to 1);
begin 
  C1: case x is 
        when 1 => Out_1 <= 0; 
        when 2 => Out_1 <= 1; 
        when 3 => Out_1 <= 2; 
  end case C1; 

  C2: case y is 
        when "00" => Out_2 <= 0; 
        when "01" => Out_2 <= 1; 
        when "10" => Out_2 <= 2; 

        when "11" => Out_2 <= 3; 
  end case C2; 
end process; 

P2:process
type Codes_Of_Operation is (ADD,SUB,MULT,DIV);
variable Code_Variable: Codes_Of_Operation;
begin 

- 48 -

Język opisu sprzętu VHDL

background image

  C3: case Code_Variable is 

       when ADD | SUB  => Operation := 0;
       when MULT | DIV => Operation := 1; 

  end case C3; 
end process; 

P3:process 
type Some_Characters is ('a','b','c','d','e');
variable Some_Characters_Variable: Some_Characters;
begin 
  C4: case Some_Characters_Variable is 
        when 'a' to 'c' => Operation := 0;

      when 'd' to 'e' => Operation := 1; 
 end case C4; 

end process; 

P5:process 
variable Code_of_Operation : INTEGER range 0 to 2;
constant Variable_1 : INTEGER := 0;
begin 
  C6: case Code_of_Operation is 

     when Variable_1 | Variable_1 + 1 =>  

             Operation := 0;
       

when Variable_1 + 2 => 

 Operation := 1; 

  end case C6;
end process; 

P6:process 
type Some_Characters is ('a','b','c','d','e');
variable Code_of_Address : Some_Characters;
begin 
  C7:case Code_of_Address is 
       when 'a' | 'c' => Operation := 0;
       when others => Operation := 1;
  end case C7; 
end process; 

Sekwencja when others może wystąpić tylko jako ostatnia.

5.4.

Scalanie wartości (ang. aggregate)

Scalanie wartości oznacza łączenie kilku wartości w rekord lub tablicę. Łączone elementy 

specyfikuje się w nawiasach rozdzielając przecinkiem. Wyspecyfikowane elementy składają 
się z określenia pozycji oraz wartości wpisywanej w wyspecyfikowaną pozycję. 

Język opisu sprzętu VHDL

- 49 -

background image

Słowo kluczowe other może być tylko ostatnie w specyfikowanej liście. Każda pozycja 

podczas określania wartości tablicy lub rekordu musi zostać wyspecyfikowana raz i tylko raz.

variable v1 : bit_vector ( 0 to 3 ) := ( '1', '1', '0', '1' );   -- "1011"
variable v2 : bit_vector ( 3 downto 0 ) := ( '1', '1', '0', '1' );   -- "1101"
variable v3 : bit_vector ( 1 to 4 ) := ( 1=>'0', 3=>'0', 4=>'0', 2=>'1' );
       -- "0010"
sugnal s1 : std_logic_vector ( 7 downto 0 );
  s1 <= ( 7 downto 4 => '1', 3 downto 0 => '0' );   -- "11110000"
  s1 <= ( 6 downto 5 => '1', others => 'Z' );  -- "Z11ZZZZZ"
  s1 <= ( others => 'Z' ); -- "ZZZZZZZZ"; niezależnie od długości s1
  s1 <= ( 6 | 3 => '1', others => '0' );  -- "01001000"
type R1Def is record
    f1 : integer;
    f2 : std_logic_vector ( 3 downto 0 )
end record;
variable r1 : R1Def := ( f1 => 33, f2 => "0110" );

5.5.

Typ Bit

Typ bit jest predefiniowany w pakiecie Standard i zawiera dwie wartości: '0' oraz '1'. Typ 

posiada tylko dwie wartości i nie jest możliwe użycie go np. do reprezentacji stanu wysokiej 
impedancji.   Sygnały  typu  bit  nie   są   typu  resolved  i   w  związku   z   tym   sygnał   taki   może 
posiadać tylko jeden sterownik. Wartości typu bit zapisywane są w apostrofach.

signal b1, b2 : bit;
b1 <= '1';
b2 <= not b1;

5.6.

Typ Bit_Vector

Typ  Bit_Vector  jest zdefiniowany w pakiecie  Standard  i reprezentuje jednowymiarową 

tablicę elementów typu  bit. Rozmiar wektora typu  Bit_Vector  jest specyfikowany podczas 
definiowania wektora. Wartości typu Bit_Vector zapisywane są w podwójnych apostrofach w 
odróżnieniu od elementów wektora, które zapisywane są w pojedynczych apostrofach.

signal bv : bit_vector( 7 downto 0 );
signal b : bit;
bv( 0 ) <= '1';
bv <= '0' & "011011" & b;

- 50 -

Język opisu sprzętu VHDL

background image

5.7.

Typ Boolean

Typ Boolean jest zdefiniowany w pakiecie Standard i posiada dwie wartości: false oraz 

true. Typowo jest wynikiem wykonania operacji relacyjnych. W odróżnieniu od niektórych 
klasycznych języków programowania wartości typu  boolean  nie są identyczne z logicznymi 
wartościami '0' oraz '1'.

5.8.

Typ Character

Typ  character  jest typem wyliczeniowym zawierającym wszystkie akceptowalne znaki. 

Jego specyfikacja znajduje się w pakiecie Standard

5.9.

Pakiet

Pakiet   grupuje   definicje   stałych,   typów   definiowanych   przez   użytkownika,   deklaracje 

komponentów (sygnałów i zmiennych) oraz definicje funkcji i procedur (wliczając definicje 
funkcji operatorów). Celem definicji pakietu jest zdefiniowanie zasobów współużywalnych w 
celu wykorzystywania ich przez różne projekty. Zwyczajowo pakiety zapisywane są w postaci 
bibliotek. 

Pakiet składa się z deklaracji pakietu oraz z ciała pakietu. Deklaracja pakietu zawiera 

definicje stałych, typów oraz nagłówki funkcji i procedur. Ciało pakietu zawiera definicje 
deklarowanych w deklaracji pakietu procedur i funkcji. Definicja pakietu posiada następującą 
składnię:

-- Deklaracja pakietu
package nazwa_pakietu is
    deklaracja_pakietu
end nazwa_pakietu;
-- Definicja ciała pakietu
package body nazwa_pakietu is
    definicja_pakietu
end package body nazwa_pakietu;

Jednostki zdefiniowane w pakiecie są dostępne w projekcie po użyciu dyrektywy use

Standard języka VHDL wymaga obecności co najmniej dwóch pakietów:  STANDARD 

oraz  TEXTIO.   Pierwszy   zawiera   definicje   typów,   stałych   i   operatorów.   Drugi   zawiera 
definicje operacji współpracujących z plikami tekstowymi. Kolejnym często występującym 
pakietem jest STD_LOGIC_1164 zawierający rozszerzenia języka.

Język opisu sprzętu VHDL

- 51 -

background image

6.

Przykłady

Poniżej  przedstawiono przykłady realizacji  projektów układów logicznych za  pomocą 

programu ORCAD z przeznaczeniem do zaprojektowania układów logicznych firmy XILINX. 
Działanie wszystkich projektów zostało praktycznie sprawdzone na układach 4003 oraz 4008. 
Wykorzystano układy elektroniczne oraz peryferia znajdujące się na  XILINX FPGA Demo 
Board.  
W szczególności wykorzystano znajdujące się na płytce przełączniki do zadawania 
wartości sygnałów, zestaw 16 diod LED oraz dwa siedmiosegmentowe wyświetlacze LED do 
wyświetlania informacji.

Przepływ informacji między programowalnym układem logicznym a jego zewnętrzem 

odbywa się za pomocą wyprowadzeń układu. To, które z wyprowadzeń jest wejściem lub 
wyjściem oraz jaki sygnał zewnętrzny jest z nim stowarzyszony określane jest za pomocą 
portów wejściowych oraz  wyjściowych wraz z  wejściowymi  oraz  wyjściowymi  buforami. 
Sposób doprowadzania sygnału do układu przedstawia Rys.7.1. Wyprowadzanie sygnału z 
układu przedstawiono na Rys.7.2.

U14

IBUF

SW3_8

P28

Rys.7.1. Doprowadzanie sygnału do układu.

U1

OBUF

BasicClock

P41

Rys.7.2. Wyprowadzanie sygnału z układu.

Przedstawiony   na   Rys.7.1   sposób   doprowadzenia   sygnału   zewnętrznego   do   układu 

programowalnego składa się z portu wejściowego  SW3_8  oraz bufora wejściowego  IBUF
Wyjście   z   bufora   stanowi   wejście   dla   logiki   wewnątrz   programowanego   układu.   Numer 
wyprowadzenia programowalnego układu logicznego, z którym związany jest dany sygnał 
określony jest poprzez atrybut linii między portem a buforem wejściowym. Atrybut ten nosi 
nazwę LOC i jego wartość jest w postaci Pxx, gdzie xx jest numerem wyprowadzenia układu 
scalonego. Oznaczenie P28 wiąże sygnał z 28 wyprowadzeniem układu.

Wyprowadzanie sygnałów z układu na zewnątrz realizowane jest w analogiczny sposób. 

Sygnał z wnętrza układu podawany jest na wejście bufora wyjściowego OBUF, a następnie na 
wejście portu wyjściowego. Wartość atrybutu  LOC  określa numer wyprowadzenia  układu 
scalonego związanego z danym sygnałem wyjściowym.

- 52 -

Język opisu sprzętu VHDL

background image

Programy w języku VHDL stanowią fragmenty bloków odpowiednich hierarchicznych. 

Takie  bloki  biorą  udział  zarówno  w  symulacji   pracy układu   jak  i   podczas  syntezy ciągu 
bitowego programującego programowalny układ logiczny.

Występujące na schematach bloki  READBACK są opcjonalne i ich przeznaczeniem jest 

weryfikacja ciągu bitowego programującego układ.

Język opisu sprzętu VHDL

- 53 -

background image

6.1.

Konwerter liczby binarnej na kod BCD. Wyświetlenie liczby BCD  
na wyświetlaczu 7-segmentowym

Jedną z typowych aplikacji programowalnych układów logicznych jest wykorzystanie ich 

w  roli   układów   sterujących   miernikami   cyfrowymi.   W   takiej   roli   mogą   stanowić   "serce" 
woltomierza  lub częstotliwościomierza. W takich zastosowaniach użyteczną  rolę spełniają 
konwertery kodu binarnego na kod wyświetlaczy 7-segmentowych. Pośredniczą one między 
wewnętrznymi funkcjami miernika, pracującymi zwykle w kodzie binarnym, a wyjściem z 
układu realizowanym wielokrotnie za  pomocą wyświetlania  informacji  na wyświetlaczach 
7-segmentowych LED.

Przedstawiony   na   Rys.7.3   schemat   realizuje   konwersję   kodu   binarnego   na   kod 

wyświetlacza   7-segmentowego.   Konwersja   realizowana   jest   przez   hierarchiczny   blok 
VHDL_Blk. Ciało programu w języku VHDL związanego z tym blokiem przedstawiono w 
ramce   poniżej.   Liczba   binarna   doprowadzana   jest   do   układu   za   pomocą   zestawu 
przełączników dołączonych do wejść układu o numerach 19, 20, 23, 24, 25, 26 oraz 27. Stany 
przełączników potwierdzane są na diodach dołączonych do wyjść układu o numerach 59, 58, 
57,   66,   65,   62   oraz   61.   Zdekodowana   liczba   wyświetlana   jest   na   dwóch   wyświetlaczach 
7-segmentowych dołączonych do wyjść 39, 38, 36, 35, 29, 40 i 44 oraz 49, 48, 47, 46, 45, 50 i 
51.

W   celu   wykonania   konwersji   zdefiniowano   proces,   na   którego   liście   inicjalizacyjnej 

znajduje się wejściowa liczba binarna:

  process( Bin )  -- bin-2-BCD converter

Proces ten wykonywany jest tylko wówczas gdy wejściowa zmienna  Bin  ulegnie zmianie. 
Przekodowanie liczby z kodu binarnego na kod wyświetlacza odbywa się w dwóch etapach. 
Wpierw liczba binarna zamieniana jest na liczbę w kodzie BCD. Zamiana wykonywana jest 
na   zasadzie   testowania   kolejnych   bitów   liczby   binarnej   (poczynając   od   najmłodszego)   i 
dodawaniu do wyniku odpowiednich wag. Następnie dla dwóch cyfr liczby w kodzie BCD 
wywoływana   jest   funkcja   wyliczająca   wzór   danej   cyfry,   który   wyświetlany   jest   na 
wyświetlaczu.

W celu wyświetlenia zdekodowanej liczby zdefiniowano oddzielny proces wzbudzany 

sygnałem digit:

  process( digit )    -- BCD-2-7 segment LED converter
  begin
     LdLED <= BCD2LED( digit( 3 downto 0 ) );
     UpLED <= BCD2LED( digit( 7 downto 4 ) );

  end process;

Sygnał digit ustawiany jest przez proces wykonujący konwersje.

- 54 -

Język opisu sprzętu VHDL

background image

VHDL_Blk

VHDL_Blk

Bin[6..0]

UpLED[6..0]

LdLED[6..0]

B6

B5

B4

RD

RT

B2

B1

B0

B3

B[6..0]

UPLED[6..0]

UPLED0

UPLED1

UPLED2

UPLED3

UPLED4

UPLED5

UPLED6

LDLED0

LDLED1

LDLED2

LDLED3

LDLED4

LDLED5

LDLED6

LDLED[6..0]

B0

B1

B2

B3

B4

B5

B6

U29

OBUF

U31

OBUF

U27

OBUF

U25

OBUF

U22

OBUF

U19

OBUF

U16

OBUF

U13

OBUF

U1

IBUF

U33

IBUF

MD0

U32

MD0

MD1

U30

MD1

CLK

TRIG

DATA

RIP

U28

READBACK

U2

OBUF

U4

OBUF

U5

OBUF

U7

OBUF

U9

OBUF

U10

OBUF

U12

OBUF

U17

OBUF

U18

OBUF

U20

OBUF

U21

OBUF

U23

OBUF

U24

OBUF

U26

OBUF

U3

IBUF

U6

IBUF

U8

IBUF

U11

IBUF

U14

IBUF

U15

IBUF

SW3_1

UPPER2_PIN

UPPER1_PIN

UPPER0_PIN

LOWER3_PIN

LOWER2_PIN

LOWER1_PIN

LOWER0_PIN

UPPERa

UPPERb

UPPERc

UPPERd

UPPERe

UPPERf

UPPERg

LOVERa

LOVERb

LOVERc

LOVERd

LOVERe

LOVERf

LOVERg

SW3_2

SW3_3

SW3_4

SW3_5

SW3_6

SW3_7

LOC=P59

LOC=P58

LOC=P57

LOC=P65

LOC=P66

LOC=P62

LOC=P61

LOC=P19

LOC=P39

LOC=P38

LOC=P36

LOC=P35

LOC=P29

LOC=P40

LOC=P44

LOC=P49

LOC=P48

LOC=P47

LOC=P46

LOC=P45

LOC=P50

LOC=P51

LOC=P20

LOC=P23

LOC=P24

LOC=P25

LOC=P26

LOC=P27

Rys.7.3. Schemat logiczny konwertera kodu binarnego na kod wyświetlacza 7-sermentowego.

Język opisu sprzętu VHDL

- 55 -

background image

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY VHDL_Blk is

PORT (

Bin    

: IN    STD_LOGIC_VECTOR (6 DOWNTO 0);

UpLED : OUT STD_LOGIC_VECTOR (6 DOWNTO 0);
LdLED : OUT STD_LOGIC_VECTOR (6 DOWNTO 0));

END VHDL_Blk;

ARCHITECTURE behavior OF VHDL_Blk IS
  shared VARIABLE TMP   : std_logic_vector ( 7 downto 0 );
  shared VARIABLE TMP1 : std_logic_vector ( 3 downto 0 );
             SIGNAL     digit   :  std_logic_vector ( 7 downto 0 );

--
-- Konwersja liczby w kodzie BCD na kod wyswietlacza 7-segmentowego
-- zrealizowana w postaci funkcji
--
FUNCTION BCD2LED( BCD : std_logic_vector( 3 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 6 downto 0 );
begin
      if        BCD = "0000" then TMP := "1000000";    -- 0
        elsif  BCD = "0001" then TMP := "1111001";    -- 1
        elsif  BCD = "0010" then TMP := "0100100";    -- 2
        elsif  BCD = "0011" then TMP := "0110000";    -- 3
        elsif  BCD = "0100" then TMP := "0011001";    -- 4
        elsif  BCD = "0101" then TMP := "0010010";    -- 5
        elsif  BCD = "0110" then TMP := "0000010";    -- 6
        elsif  BCD = "0111" then TMP := "1111000";    -- 7
        elsif  BCD = "1000" then TMP := "0000000";    -- 8
        elsif  BCD = "1001" then TMP := "0010000";    -- 9
     else
        TMP := "0111111";
     end if;  
  return TMP;
end  BCD2LED;

BEGIN

  process( Bin )  -- bin-2-BCD converter
  begin
    TMP :=  ( '0' &  Bin ) and "00001111";

    if  TMP > "00001001" then
      TMP := std_logic_vector( unsigned(TMP) + 6 );
    end if;

    if Bin(4) = '1' then
      TMP := std_logic_vector( unsigned(TMP) + x"16" );
       if  TMP(3 downto 0) > "1001" then
         TMP := std_logic_vector( unsigned(TMP) + 6 );
       end if;
    end if;

- 56 -

Język opisu sprzętu VHDL

background image

    if Bin(5) = '1' then
      TMP := std_logic_vector( unsigned(TMP) + x"32" );
       if  TMP(3 downto 0) > "1001" then
         TMP := std_logic_vector( unsigned(TMP) + 6 );
       end if;
    end if;

    if Bin(6) = '1' then
      TMP := std_logic_vector( unsigned(TMP) + x"64" );
       if  TMP(3 downto 0) > x"9" then
         TMP := std_logic_vector( unsigned(TMP) + 6 );
       end if;
       if  TMP(7 downto 4) > x"9" then
         TMP := std_logic_vector( unsigned(TMP) + x"60" );
       end if;
    end if;

    digit <= TMP;
  end process;

  process( digit )    -- BCD-2-7 segment LED converter
  begin
     LdLED <= BCD2LED( digit( 3 downto 0 ) );
     UpLED <= BCD2LED( digit( 7 downto 4 ) );

  end process;

END behavior;

Język opisu sprzętu VHDL

- 57 -

background image

6.2.

Częstotliwościomierz

Zasada   działania   miernika   częstotliwości   polega   na   zliczaniu   liczby   impulsów   w 

określonej jednostce czasu. W przypadku sygnałów cyfrowych zlicza się liczbę narastających 
lub   opadających   zboczy   sygnału   badanego.   Jeżeli   przykładowo   czas   zliczania   wynosi   1 
milisekundę   wówczas   zliczona   liczba   impulsów   podaje   częstotliwość   badanego   sygnału 
wyrażoną w [kHz]. 

Rysunek   7.4   przedstawia   schemat   częstotliwościomierza   wykonany   w   programie 

ORCAD w formacie umożliwiającym za jego pomocą zaprogramowanie programowalnego 
układu   logicznego.   Mierzony   sygnał   dołączony   jest   do   portu  SW3_1.   Wynik   pracy 
częstotliwościomierza   wyświetlany   jest   na   dwóch   7-segmentowych   wyświetlaczach   LED 
(patrz poprzedni przykład).

Na   schemacie   zawarte   są   dwa   bloki   opisane   w   języku   VHDL:  VHDL_Div  oraz 

VHDL_Blk. Wejściem dla pierwszego bloku jest wyjście wbudowanego w programowalny 
układ oscylatora o częstotliwości 8MHz. Blok VHDL_Div dzieli częstotliwość wejściową w 
celu uzyskania sygnału taktującego zliczanie liczby impulsów w bloku VHDL_Blk (patrz ciało 

ARCHITECTURE behavior OF VHDL_Div IS

 w ramce poniżej). Zależnie od częstotliwości sygnału 

mierzonego częstotliwość sygnału wyjściowego z bloku VHDL_Div musi ulegać zmianie tak 
aby w trakcie jednego zliczenia zarejestrować od 1 do maksymalnie 99 impulsów (tylko taki 
zakres można wyświetlić na dwóch polach wyświetlacza).

Blok  VHDL_Blk  zlicza liczbę narastających zboczy sygnału mierzonego. Realizowane 

jest to dzięki instrukcji (patrz ciało 

ARCHITECTURE behavior OF VHDL_Blk IS

 poniżej):

  elsif ( InpSignal = '1' and InpSignal'Event ) then

Zliczanie odbywa się w kodzie BCD. Jednocześnie jeżeli sygnał Reset osiągnie wartość zero 
wówczas licznik przyjmuje wartość zerową:

  if Reset ='0' then 
    count <= "00000000";

W   celu   wyświetlenia   zliczonej   wartości   zdefiniowano   proces,   na   którego   liście 
inicjalizacyjnej znajduje się sygnał Reset:

process( Reset )
begin
  if Reset = '0' and Reset'Event then
    LdLED <= BCD2LED( count( 3 downto 0 ) );
    UpLED <= BCD2LED( count( 7 downto 4 ) );
  end if;
end process;

Pojawienie się opadającego zbocza sygnału Reset powoduje podstawienie za zmienne LdLED 
oraz UpLED wzorców obu cyfr zliczonej liczby. Stanowią one wyjście z bloku VHDL_Blk i 
są bezpośrednio połączone z 7-segmentowymi wyświetlaczami LED.

- 58 -

Język opisu sprzętu VHDL

background image

VHDL_Blk

VHDL_Blk

UpLED[6..0]

LdLED[6..0]

InpSignal

Reset

VHDL_Div

VHDL_Div

InpClk

OutClk

RD

RT

UPLED[6..0]

UPLED0

UPLED1

UPLED2

UPLED3

UPLED4

UPLED5

UPLED6

LDLED0

LDLED1

LDLED2

LDLED3

LDLED4

LDLED5

LDLED6

LDLED[6..0]

U21

OBUF

U2

IBUF

U24

IBUF

MD0

U23

MD0

MD1

U22

MD1

CLK

TRIG

DATA

RIP

U20

READBACK

U3

OBUF

U5

OBUF

U6

OBUF

U7

OBUF

U8

OBUF

U9

OBUF

U10

OBUF

U13

OBUF

U14

OBUF

U15

OBUF

U16

OBUF

U17

OBUF

U18

OBUF

U19

OBUF

OSC1

OSC4

F8M

F500K

F16K

F490

F15

U4

BUFGS

U12
OBUF

U11
OBUF

U1

OBUF

SW3_1

UPPERa

UPPERb

UPPERc

UPPERd

UPPERe

UPPERf

UPPERg

LOVERa

LOVERb

LOVERc

LOVERd

LOVERe

LOVERf

LOVERg

Aux2

Aux1

InpFreq

LOC=P19

LOC=P39

LOC=P38

LOC=P36

LOC=P35

LOC=P29

LOC=P40

LOC=P44

LOC=P49

LOC=P48

LOC=P47

LOC=P46

LOC=P45

LOC=P50

LOC=P51

LOC=P62

LOC=P61

LOC=P65

Rys.7.4. Schemat ideowy częstotliwościomierza.

Język opisu sprzętu VHDL

- 59 -

background image

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY VHDL_Div is

PORT (

InpClk : IN STD_LOGIC;
OutClk : OUT STD_LOGIC);

END VHDL_Div;

ARCHITECTURE behavior OF VHDL_Div IS
             SIGNAL     TMPCLK : std_logic_vector ( 7 downto 0 )  := x"00";
  shared VARIABLE TMP       : std_logic_vector ( 7 downto 0 );
BEGIN

  process
  begin
    wait until InpClk = '1' and InpClk'Event;
      TMP := TMPCLK;
      TMP := std_logic_vector( unsigned(TMP) + 1 );
      if  TMP > "01000110" then
        OutClk <= '0';
        TMP := 0;
      else
        OutClk <= '1';
      end if;
      TMPCLK <= TMP;
 end process;

END behavior;

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY VHDL_Blk is

PORT (

InpSignal 

: IN    STD_LOGIC;

Reset    : IN    STD_LOGIC;
UpLED : OUT STD_LOGIC_VECTOR (6 DOWNTO 0);
LdLED : OUT STD_LOGIC_VECTOR (6 DOWNTO 0));

END VHDL_Blk;

ARCHITECTURE behavior OF VHDL_Blk IS
             SIGNAL TMPCLK  : std_logic_vector ( 3 downto 0 )  := "1110";
             SIGNAL count       : std_logic_vector ( 7 downto 0 )  := x"00";
             SIGNAL TMPRES  : std_logic := '0';
  shared VARIABLE TMP   : std_logic_vector ( 3 downto 0 );
  shared VARIABLE TMP8 : std_logic_vector ( 7 downto 0 );

- 60 -

Język opisu sprzętu VHDL

background image

FUNCTION BCD2LED( BCD : std_logic_vector( 3 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 6 downto 0 );
begin
      if        BCD = "0000" then TMP := "1000000";    -- 0
        elsif  BCD = "0001" then TMP := "1111001";    -- 1
        elsif  BCD = "0010" then TMP := "0100100";    -- 2
        elsif  BCD = "0011" then TMP := "0110000";    -- 3
        elsif  BCD = "0100" then TMP := "0011001";    -- 4
        elsif  BCD = "0101" then TMP := "0010010";    -- 5
        elsif  BCD = "0110" then TMP := "0000010";    -- 6
        elsif  BCD = "0111" then TMP := "1111000";    -- 7
        elsif  BCD = "1000" then TMP := "0000000";    -- 8
        elsif  BCD = "1001" then TMP := "0010000";    -- 9
     else
        TMP := "0111111";
     end if;  
  return TMP;
end  BCD2LED;

BEGIN

process( Reset )
begin
  if Reset = '0' and Reset'Event then
    LdLED <= BCD2LED( count( 3 downto 0 ) );
    UpLED <= BCD2LED( count( 7 downto 4 ) );
--    TMPRES <= '1';
  end if;
end process;

process( Reset, InpSignal, count ) -- ( Clk , InpSignal, count )
begin 
  if Reset ='0' then -- and Reset'Event then
    count <= "00000000";
  elsif ( InpSignal = '1' and InpSignal'Event ) then
     TMP8 := count;
     TMP8 := std_logic_vector( unsigned(TMP8) + 1 );
     if TMP8( 3 downto 0 ) > "1001" then     -- decimal adjustment of the lower digit
       TMP8 := std_logic_vector( unsigned(TMP8) + 6 );
     end if;
     if TMP8( 7 downto 4 ) > "1001" then     -- decimal adjustment of the upper digit
       TMP8 := std_logic_vector( unsigned(TMP8) + x"60" );
     end if;
     count <= TMP8;
  end if;
end process;

Język opisu sprzętu VHDL

- 61 -

background image

6.3.

Generator numerów górników

Szczegóły   pracy   systemu   kontroli   przemieszczania   się   górników   w   chodnikach   pod 

ziemią   przedstawiono   w   rozdziale   3.2.   Poniżej   przedstawiono   projekt   nadajnika   oraz 
odbiornika (detektora) numerów, w których główne bloki funkcjonalne zostały opisane w 
języku VHDL w sposób behawioralny.

Na schemacie widoczne są cztery bloki hierarchiczne opisane w języku VHDL: Divider

GenNumReadNum oraz VHDL_Blk. 

Blok  Divider  (patrz   pierwsza   ramka   poniżej)   odpowiada   za   podział   częstotliwości   z 

wbudowanego generatora w celu uzyskania częstotliwości taktującej prace bloków GenNum 
oraz  ReadNum.   Zawarto   w   nim   dwa   procesy,   z   których   pierwszy  odpowiada   za   podział 
częstotliwości   wejściowej   przez   16,   a   drugi   ustala   współczynnik   wypełnienia   sygnału 
wyjściowego.

Blok  GenNum  powoduje   wygenerowanie   numerów   w   odpowiednim   formacie   dla 

wszystkich kombinacji 13-bitowych numerów. Pobudzany jest narastającym zboczem sygnału 
wyjściowego z bloku  Divider. Posiada wbudowany licznik  tmp_clk, którego różne wartości 
powodują   wysłanie   na   wyjście  Numer  kolejnych   fragmentów   generowanego   sygnału. 
Dodatkowy 13-bitowy licznik nbr zawiera aktualnie wysyłany numer górnika.

Blok  ReadNum  odbiera wysyłany przez blok  GenNum  numer i wpisuje go ro rejestru 

szeregowego. Realizowane jest to przez wydzielony proces:

  process ( In_clk, In_num )
  begin
      if ( In_clk'Event and In_clk = '0') then
        dtk_nbr <= dtk_nbr( 14 downto 0 ) &  In_num;
      end if;
  end process;

Następnie numer przypisany do sygnału dtk_nbr z sekwencją "01111110" oraz z sekwencją 7 
bitów zadaną przez dołączone go układu przełączniki (wejście DIP bloku ReadNum):

  process ( dtk_nbr, DIP )
  begin
    if dtk_nbr = "01111110" & DIP( 6 downto 0 ) & '0' then
      aux <= '1';

Jeżeli   numer   zostanie   wykryty   ustawiana   jest   zmienna  aux,   która   w   kolejnym   procesie 
powoduje ustawienie sygnału wyjściowego Num_OK.

Blok  VHDL_Blk  używany   jest   do   wyświetlenia   na   dwóch   polach   wyświetlacza 

7-segmentowego   zadawanego   za   pomocą   przełączników   fragmentu   numeru.   Ułatwia   to 
weryfikację poprawności pracy układu.

Warto zauważyć, że w celu ułatwienia testowania pracy układu zarówno nadajnik jak i 

odbiornik   zaprojektowano   w   pojedynczym   układzie   FPGA.   W   rzeczywistości   są   to   dwa 
niezależne układy, a połączenie między nimi realizowane jest na drodze radiowej.

- 62 -

Język opisu sprzętu VHDL

background image

Divider

Divider

Inp

Outp

GenNum

GenNum

ClkInp

Numer

ReadNum

ReadNum

In_clk

In_num

Num_OK

DIP[7..0]

Numer[6..0]

VHDL_Blk

VHDL_Blk

Bin[6..0]

UpLED[6..0]

LdLED[6..0]

CLOCK

RD

RT

outp

DIP[7..0]

DIP0

DIP1

DIP2

DIP3

DIP4

DIP5

DIP6

DIP7

UPLED[6..0]

LDLED[6..0]

UPLED0

UPLED1

UPLED2

UPLED3

UPLED4

UPLED5

UPLED6

LDLED0

LDLED1

LDLED2

LDLED3

LDLED4

LDLED5

LDLED6

Numer[6..0]

U20

OBUF

U6

BUFGS

U23

IBUF

MD0

U22

MD0

MD1

U21

MD1

U1

OBUF

CLK

TRIG

DATA

RIP

U19

READBACK

U2

OBUF

U5

OSC4

F8M

F500K

F16K

F490

F15

U3

OBUF

U9

IBUF

U11

IBUF

U14

IBUF

U16

IBUF

U18

IBUF

U24

IBUF

U27

IBUF

U29

IBUF

U4

OBUF

U7

OBUF

U8

OBUF

U10

OBUF

U12

OBUF

U13

OBUF

U15

OBUF

U17

OBUF

U25

OBUF

U26

OBUF

U28

OBUF

U30

OBUF

U31

OBUF

U32

OBUF

U33

OBUF

Pin_61

Pin_62

Pin_65

SW3_1

SW3_2

SW3_3

SW3_4

SW3_5

SW3_6

SW3_7

SW3_8

Pin_66

UPPERa

UPPERb

UPPERc

UPPERd

UPPERe

UPPERf

UPPERg

LOVERa

LOVERb

LOVERc

LOVERd

LOVERe

LOVERf

LOVERg

P61

P62

P65

P19

P20

P23

P24

P25

P26

P27

P28

P66

P39

P38

P36

P35

P29

P40

P44

P49

P48

P47

P46

P45

P50

P51

Rys.7.5. Schemat ideowy nadajnika oraz detektora numerów.

Język opisu sprzętu VHDL

- 63 -

background image

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY Divider is

PORT (

Inp

: IN STD_LOGIC;

Outp

: OUT STD_LOGIC);

END Divider;

ARCHITECTURE behavior OF Divider IS
--  signal count, new_count : std_logic_vector (3 downto 0 ) := "0000";
  signal count : std_logic_vector (3 downto 0 ) := "0000";
  BEGIN

  process ( Inp )
    begin
    if (Inp'Event and Inp = '1') then
       if count = "1111" then
         count <= "0000";
       else
         count <=  std_logic_vector(unsigned(count) + "1"); 
       end if;
    end if;
  end process;

  process ( count )
    begin
       if count >= "0111" then
         Outp <= '1';
       else
         Outp <= '0';
       end if;
    end process;

END behavior;

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY GenNum is

PORT (

ClkInp : IN STD_LOGIC;
Numer : OUT STD_LOGIC);

END GenNum;

ARCHITECTURE behavior OF GenNum IS
  signal nbr        : std_logic_vector (12 downto 0) := "0000000000000";
  signal tmp_clk : std_logic_vector (4 downto 0) := "00000";

BEGIN

  process ( ClkInp )

- 64 -

Język opisu sprzętu VHDL

background image

    begin
    if ( ClkInp'Event and ClkInp = '1') then
      if tmp_clk( 4 ) = '0' then
        case tmp_clk(3 downto 0) is
           when "0000"  => Numer <= '0';
           when "0001"  => Numer <= nbr( 0 );
           when "0010"  => Numer <= nbr( 1 );
           when "0011"  => Numer <= nbr( 2 );
           when "0100"  => Numer <= nbr( 3 );
           when "0101"  => Numer <= nbr( 4 );
           when "0110"  => Numer <= nbr( 5 );
           when "0111"  => Numer <= '0';
           when "1000"  => Numer <= nbr( 6 );
           when "1001"  => Numer <= nbr( 7 );
           when "1010"  => Numer <= nbr( 8 );
           when "1011"  => Numer <= nbr( 9 );
           when "1100"  => Numer <= nbr( 10 );
           when "1101"  => Numer <= nbr( 11 );
           when "1110"  => Numer <= nbr( 12 );
           when "1111"  =>
                                    Numer <= '0';
                                    nbr <=  std_logic_vector(unsigned(nbr) + "1"); 
           when others => Numer <= '1';
        end case;
      else
         Numer <= '1';
      end if;
      if tmp_clk > "11000" then
        tmp_clk <= "00000";
      else
        tmp_clk <=  std_logic_vector(unsigned(tmp_clk) + "1"); 
      end if;
    end if;
  end process;

END behavior;

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY ReadNum is

PORT (

In_clk : IN STD_LOGIC;
In_num : IN STD_LOGIC;
Num_OK

: OUT STD_LOGIC;

               Numer     : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);

DIP

: IN STD_LOGIC_VECTOR (7 DOWNTO 0) );

END ReadNum;

ARCHITECTURE behavior OF ReadNum IS
  signal dtk_nbr  : std_logic_vector (15 downto 0) := "0000000000000000";
  signal aux       : std_logic := '0';
--  signal aux_nbr  : std_logic_vector (6 downto 0) := "0000000";
BEGIN

  process ( In_clk, In_num )

Język opisu sprzętu VHDL

- 65 -

background image

  begin
      if ( In_clk'Event and In_clk = '0') then
        dtk_nbr <= dtk_nbr( 14 downto 0 ) &  In_num;
      end if;
  end process;

  process ( dtk_nbr, DIP )
  begin
    if dtk_nbr = "01111110" & DIP( 6 downto 0 ) & '0' then
      aux <= '1';
    else
      aux <= '0';
    end if;
  end process;

  process ( aux )
  begin
    if aux'Event and aux = '1' then
      Numer <= dtk_nbr( 7 downto 1 );
      if Num_OK = '0' then
        Num_OK <= '1';
      else
        Num_OK <= '0';
      end if;
    end if;
  end process;
  
END behavior;

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY VHDL_Blk is

PORT (

Bin    

: IN    STD_LOGIC_VECTOR (6 DOWNTO 0);

UpLED : OUT STD_LOGIC_VECTOR (6 DOWNTO 0);
LdLED : OUT STD_LOGIC_VECTOR (6 DOWNTO 0));

END VHDL_Blk;

ARCHITECTURE behavior OF VHDL_Blk IS
  shared VARIABLE TMP   : std_logic_vector ( 7 downto 0 );
  shared VARIABLE TMP1 : std_logic_vector ( 3 downto 0 );
             SIGNAL     digit   :  std_logic_vector ( 7 downto 0 );

FUNCTION BCD2LED( BCD : std_logic_vector( 3 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 6 downto 0 );
begin
      if        BCD = "0000" then TMP := "1000000";    -- 0
        elsif  BCD = "0001" then TMP := "1111001";    -- 1
        elsif  BCD = "0010" then TMP := "0100100";    -- 2
        elsif  BCD = "0011" then TMP := "0110000";    -- 3
        elsif  BCD = "0100" then TMP := "0011001";    -- 4
        elsif  BCD = "0101" then TMP := "0010010";    -- 5
        elsif  BCD = "0110" then TMP := "0000010";    -- 6
        elsif  BCD = "0111" then TMP := "1111000";    -- 7
        elsif  BCD = "1000" then TMP := "0000000";    -- 8

- 66 -

Język opisu sprzętu VHDL

background image

        elsif  BCD = "1001" then TMP := "0010000";    -- 9
     else
        TMP := "0111111";
     end if;  
  return TMP;
end  BCD2LED;

BEGIN

  process( Bin )  -- bin-2-BCD converter
  begin
    TMP :=  ( '0' &  Bin ) and "00001111";

    if  TMP > "00001001" then
      TMP := std_logic_vector( unsigned(TMP) + 6 );
    end if;

    if Bin(4) = '1' then
      TMP := std_logic_vector( unsigned(TMP) + x"16" );
       if  TMP(3 downto 0) > "1001" then
         TMP := std_logic_vector( unsigned(TMP) + 6 );
       end if;
    end if;

    if Bin(5) = '1' then
      TMP := std_logic_vector( unsigned(TMP) + x"32" );
       if  TMP(3 downto 0) > "1001" then
         TMP := std_logic_vector( unsigned(TMP) + 6 );
       end if;
    end if;

    if Bin(6) = '1' then
      TMP := std_logic_vector( unsigned(TMP) + x"64" );
       if  TMP(3 downto 0) > x"9" then
         TMP := std_logic_vector( unsigned(TMP) + 6 );
       end if;
       if  TMP(7 downto 4) > x"9" then
         TMP := std_logic_vector( unsigned(TMP) + x"60" );
       end if;
    end if;

    digit <= TMP;
  end process;

  process( digit )    -- BCD-2-7 segment LED converter
  begin

     LdLED <= BCD2LED( digit( 3 downto 0 ) );
     UpLED <= BCD2LED( digit( 7 downto 4 ) );

 end process;

END behavior;

Język opisu sprzętu VHDL

- 67 -

background image

6.4.

Generator sygnału wizyjnego dla monitora monochromatycznego

Programowalne układy logiczne firmy XILINX mogą zostać użyte do generacji sygnałów 

dla   monitorów   komputerowych.   W   tej   roli   pracują   podobnie   do   generatorów   obrazu 
wchodzących w skład kart graficznych. Poniżej przedstawiono aplikację, której celem jest 
generacja ramki obrazowej dla monitora monochromatycznego. Kompletny sygnał wizyjny 
składa   się   z   trzech   sygnałów:   sygnały   synchronizacji   poziomej,   sygnały   synchronizacji 
pionowej   oraz   sygnału   luminancji.   W   przypadku   monitorów   komputerowych   poziomy 
wszystkich   sygnałów   mieszczą   się   w   standardzie   TTL.   Wygląd   sygnałów   synchronizacji 
poziomej i pionowej przedstawia rysunek 7.6. Sygnał luminancji jest równy jedynce logicznej 
gdy  odpowiadający  mu   punk   na   ekranie   jest   jasny  lub   jest   równy  zeru   logicznemu   gdy 
odpowiedni punkt jest wygaszony.

8.4us

55us

Sygnał synchronizacji poziomej

880us

20.4ms

Sygnał synchronizacji pionowej

Rys.7.6. Kształt impulsów synchronizacji poziomej oraz pionowej.

Schemat   generatora   sygnału   wizyjnego   wykonany  w   programie   ORCAD   przedstawia 

rysunek 7.7. Zawiera on trzy bloki, których logika jest opisana za pomocą języka VHDL. Są 
to: DivV2H oraz Video.

Blok  Div  służy   do   generacji   impulsu   synchronizacji   poziomej   (wyjście  H_Sync). 

Wykonuje   on   podział   częstotliwości   z   generatora   (wejście  M8)   w   celu   uzyskania 
odpowiednich   reżimów   czasowych   generowanego   sygnału   synchronizacji.   Dodatkowo 
wyjściem z bloku jest licznik kolumn (punktów w linii) generowanego obrazu. Jest to 9-
bitowy   sygnał   stanowiący   wejście   do   bloku   generacji   sygnału   wizyjnego.   Szczegóły 
implementacyjne bloku znajdują się w ramce poniżej wewnątrz ciała 

ARCHITECTURE behavior 

OF Div IS

.

Blok V2H służy do generacji impulsu synchronizacji pionowej. Wejściem taktującym jest 

sygnał synchronizacji poziomej, bowiem wygodnie jest podawać parametry czasowe sygnału 
synchronizacji   pionowej   w   jednostkach   równych   okresowi   synchronizacji   poziomej. 

- 68 -

Język opisu sprzętu VHDL

background image

Wyjściem   z   układu   jest   sygnał  V_Sync.   Dodatkowo   9-bitowe   wyjście  Count  umożliwia 
blokowi  Video  zliczanie   linii   generowanego   obrazu.   Szczegóły   implementacyjne 
przedstawiono w ramce poniżej w ciele 

ARCHITECTURE behavior OF V2H IS

.

Div

Div

M8

H_Sync

Count[8..0]

V2H

V2H

H_Sync

V_Sync

Count[8..0]

Video

Video

NoCol[8..0]

NoRow[8..0]

Video

Intensity

Mode[7..0]

Clk

NoCol[8..0]

NoRow[8..0]

Mode[7..0]

Mode0

Mode1

Mode2

Mode3

Mode4

Mode5

Mode6

Mode7

U4

OSC4

F8M

F500K

F16K

F490

F15

U1

OBUF

U2

OBUF

U3

OBUF

U5

OBUF

U6

OBUF

U7

IBUF

U8

IBUF

U9

IBUF

U10

IBUF

U11

IBUF

U12

IBUF

U13

IBUF

U14

IBUF

BasicClock

H_Sync

V_Sync

VideoOut

Intensity

SW3_1

SW3_2

SW3_3

SW3_4

SW3_5

SW3_6

SW3_7

SW3_8

P41

P36

P35

P38

P37

P19

P20

P23

P24

P25

P26

P27

P28

Rys.7.7. Schemat ideowy generatora sygnału wizyjnego.

Blok Video służy do generacji sygnału luminancji (wyjście Video). Dodatkowo niektóre 

monitory   potrafią   reagować   na   sygnał   podniesionej   jasności   obrazu,   który   może   zostać 
wygenerowany na wyjściu Intensity. Zadaniem omawianej aplikacji będzie generacji różnego 
typu obrazów testowych. Będą to np.: pasy poziome, pasy pionowe, krata, szachownica, itp. 
Typ generowanego aktualnie obrazu wybierany jest za pomocą przełączników dołączonych do 
wejścia  Mode  bloku  Video. Szczegóły implementacyjne programu w języku VHDL bloku 
Video przedstawiono poniżej. Zasada pracy bloku Video polega na ustawianiu w stan wysoki 
lub   niski   wyjścia   luminancji  Video  zależnie   od  aktualnego  stanu   licznika   kolumn   i   linii. 
Zależnie   od   stanu   czterech   młodszych   linii   sygnału  Mode  wywoływana   jest   odpowiednia 
funkcja ustalająca stan sygnały luminancji:

       case Mode( 3 downto 0 ) is
         when "0000" =>  AUX <= Video0( NoCol, NoRow, Mode );
         when "0001" =>  AUX <= Video1( NoCol, NoRow, Mode );
         when "0010" =>  AUX <= Video2( NoCol, NoRow, Mode );
         when "0011" =>  AUX <= Video3( NoCol, NoRow, Mode );
         when "0100" =>  AUX <= Video4( NoCol, NoRow, Mode );
         when "0101" =>  AUX <= Video5( NoCol, NoRow, Mode );
         when "0110" =>  AUX <= Video6( NoCol, NoRow, Mode );
         when "0111" =>  AUX <= Video7( NoCol, NoRow, Mode );

Język opisu sprzętu VHDL

- 69 -

background image

         when "1000" =>  AUX <= Video8( NoCol, NoRow, Mode );
         when "1001" =>  AUX <= Video9( NoCol, NoRow, Mode );
         when "1010" =>  AUX <= Video10( NoCol, NoRow, Mode );
         when others =>
            AUX <= "00";
       end case;

Wywoływane w instrukcji  case  funkcje generują pasy pionowe, poziome lub kratę (ramka 
poniżej nie zawiera implementacji wszystkich funkcji). Przykładowo generacja poziomych 
pasów wymaga odczytywania stanu licznika linii i w zależności od jego wartości ustawienia 
lub gaszenia sygnału luminancji.

Warto zauważyć, że przedstawiona aplikacja w istotny sposób różni się od typowych kart 

graficznych   mimo,   iż   ich   zachowanie   wydaje   się   być   bardzo   podobne.   Wszystkie   karty 
graficzne posiadają własną pamięć, w której przechowywana jest informacja o luminancji (lub 
chrominancji w przypadku obrazów kolorowych). Zawartość tej pamięci jest modyfikowana 
przez główny procesor systemu komputerowego. Omawiana aplikacja nie posiada lokalnej 
pamięci i dlatego jest w stanie generować tylko stały nie zmieniający się zestaw statycznych 
obrazów.

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY Div is

PORT (

M8

: IN STD_LOGIC;

H_Sync : OUT STD_LOGIC;
Count : OUT STD_LOGIC_VECTOR (8 DOWNTO 0));

END Div;

ARCHITECTURE behavior OF Div IS
                  SIGNAL      TMPCLK : std_logic_vector ( 8 downto 0 )  := "000000000";
    SHARED VARIABLE  AUX       : std_logic_vector ( 8 downto 0 );
BEGIN
  
  PROCESS( M8, TMPCLK )
  BEGIN
    IF M8 = '1' AND M8'Event THEN
        AUX := TMPCLK;
        AUX := std_logic_vector( unsigned(AUX) + 1 );
        IF AUX > "110010000"  THEN    -- 110010000 = 400 = 55.1us
            AUX := "000000000";
        END IF;
        IF AUX < "001000000" THEN    --  1000000 = 64 = 8.4us
           H_Sync <= '1';
        ELSE        
           H_Sync <= '0';
        END IF;
        TMPCLK <= AUX;
    END IF;
    Count <= TMPCLK;
END PROCESS;

- 70 -

Język opisu sprzętu VHDL

background image

END behavior;

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY V2H is

PORT (

H_Sync : IN STD_LOGIC;
V_Sync : OUT STD_LOGIC;
Count : OUT STD_LOGIC_VECTOR (8 DOWNTO 0) );

END V2H;

ARCHITECTURE behavior OF V2H IS
                  SIGNAL      TMPCLK : std_logic_vector ( 8 downto 0 )  := "000000000";
    SHARED VARIABLE  AUX       : std_logic_vector ( 8 downto 0 );
BEGIN

  PROCESS( H_Sync, TMPCLK )
  BEGIN
    IF H_Sync = '1' AND H_Sync'Event THEN
        AUX := TMPCLK;
        AUX := std_logic_vector( unsigned(AUX) + 1 );
        IF AUX > "101010010"  THEN    --  = 370 = 20.4ms  .
            AUX := "000000000";
        END IF;
        IF AUX < "000010000" THEN    --   = 16 = 880us
           V_Sync <= '0';
        ELSE        
           V_Sync <= '1';
        END IF;
        TMPCLK <= AUX;
    END IF;
    Count <= TMPCLK;
END PROCESS;

END behavior;

Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;

ENTITY Video is

PORT (

NoCol : IN STD_LOGIC_VECTOR (8 DOWNTO 0);
NoRow : IN STD_LOGIC_VECTOR (8 DOWNTO 0);
Mode

: IN STD_LOGIC_VECTOR (7 DOWNTO 0);

Clk

: IN STD_LOGIC;
Video

: OUT STD_LOGIC;

Intensity: OUT STD_LOGIC);

END Video;

ARCHITECTURE behavior OF Video IS

Język opisu sprzętu VHDL

- 71 -

background image

--
-- Pionowe pasy
--
FUNCTION Video1(  NoCol : std_logic_vector( 8 downto 0 ); 
                                 NoRow : std_logic_vector( 8 downto 0 ); 
                              Mode  : std_logic_vector( 7 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 1 downto 0 );
begin
     TMP( 0 ) := '0';    TMP( 1 ) := NoCol( 1 );
  return TMP;
end  Video1;

--
-- Poziome pasy
--
FUNCTION Video8(  NoCol : std_logic_vector( 8 downto 0 ); 
                                 NoRow : std_logic_vector( 8 downto 0 ); 
                              Mode  : std_logic_vector( 7 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 1 downto 0 );
begin
     TMP( 0 ) := '0';    TMP( 1 ) := NoRow( 4 );
  return TMP;
end  Video8;

--
-- Krata
--
FUNCTION Video9(  NoCol : std_logic_vector( 8 downto 0 ); 
                                 NoRow : std_logic_vector( 8 downto 0 ); 
                              Mode  : std_logic_vector( 7 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 1 downto 0 );
  VARIABLE AUXC, AUXR : std_logic_vector ( 8 downto 0 ); 
begin
     TMP( 0 ) := '0';  
        AUXC := std_logic_vector( unsigned(NoCol) - 96 );
        if ( AUXC < "100000000" ) AND ( AUXC(3 downto 0) = "0000" ) then
           TMP( 1 ) := '1';
        else
           TMP( 1 ) := '0';
        end if;

        AUXR:= std_logic_vector( unsigned(NoRow) - 64 );
        if ( AUXR < "100000000" ) AND ( AUXR(3 downto 0) = "0000" ) then
           TMP( 1 ) := '1';
        end if;

     if NoRow < "001000000" then TMP( 1 ) := '0'; end if;
     if NoCol < "001100000" then TMP( 1 ) := '0'; end if;
  return TMP;
end  Video9;

--
-- Szachownica
--
FUNCTION Video10(  NoCol : std_logic_vector( 8 downto 0 ); 
                                   NoRow : std_logic_vector( 8 downto 0 ); 
                              Mode  : std_logic_vector( 7 downto 0 ) ) return std_logic_vector is
  VARIABLE TMP : std_logic_vector ( 1 downto 0 );
  VARIABLE AUXC, AUXR : std_logic_vector ( 8 downto 0 ); 

- 72 -

Język opisu sprzętu VHDL

background image

begin
     TMP( 0 ) := '0';  
        AUXC := std_logic_vector( unsigned(NoCol) - 96 );
        if ( AUXC < "100000000" ) AND ( AUXC(3 downto 0) = "0000" ) then
           TMP( 1 ) := '1';
        else
           TMP( 1 ) := '0';
        end if;

        AUXR:= std_logic_vector( unsigned(NoRow) - 64 );
        if ( AUXR < "100000000" ) AND ( AUXR(3 downto 0) = "0000" ) then
           TMP( 1 ) := '1';
        end if;

        if TMP( 1 ) = '0' then
          TMP( 1 ) := AUXR( 4 ) XOR AUXC( 4 );
        end if;

     if NoRow < "001000000" then TMP( 1 ) := '0'; end if;
     if NoCol < "001100000" then TMP( 1 ) := '0'; end if;
  
  return TMP;
end  Video10;

SIGNAL AUX : std_logic_vector ( 1 downto 0 );
BEGIN

  PROCESS( Clk )
  BEGIN
     if Clk'Event and Clk = '0' then
       case Mode( 3 downto 0 ) is
         when "0000" =>  AUX <= Video0( NoCol, NoRow, Mode );
         when "0001" =>  AUX <= Video1( NoCol, NoRow, Mode );
         when "0010" =>  AUX <= Video2( NoCol, NoRow, Mode );
         when "0011" =>  AUX <= Video3( NoCol, NoRow, Mode );
         when "0100" =>  AUX <= Video4( NoCol, NoRow, Mode );
         when "0101" =>  AUX <= Video5( NoCol, NoRow, Mode );
         when "0110" =>  AUX <= Video6( NoCol, NoRow, Mode );
         when "0111" =>  AUX <= Video7( NoCol, NoRow, Mode );
         when "1000" =>  AUX <= Video8( NoCol, NoRow, Mode );
         when "1001" =>  AUX <= Video9( NoCol, NoRow, Mode );
         when "1010" =>  AUX <= Video10( NoCol, NoRow, Mode );
         when others =>
            AUX <= "00";
       end case;

       Video <= AUX( 1 );
       Intensity <= AUX( 0 );
     end if;
  END PROCESS;

END behavior;

Język opisu sprzętu VHDL

- 73 -

background image

Literatura

 

[1]

IEEE Standard VHDL Language Reference Manual, IEEE Std. 1076-1987, Institute of 
Electrical and Elecronic Engineers, 1988.

[2]

 IEEE Standard VHDL Language Reference Manual, ANSI/IEEE Std. 1076-1993, Institute 
of Electrical and Elecronic Engineers, 1984.

[3] XILINX - opis programu XACT

[4] XILINX - katalogi firmowe

[5]

 Esperan MasterClass. The multimedia VHDL Tutorial, A Windows-based tutorial for 
FPGA and PLD design, OrCAD, oprogramowanie na płytce CD.

[6]

 Navabi Z.: VHDL. Analysis and Modeling of Digital Systems, McGraw-Hill, New York, 
1998.

[7]

 Ashenden P.J.: The VHDL Cookbook. First Edition, Dept. Computer Science, University 
of Adelaide, South Australia, 1990, materiały dostępne w sieci Internet.

- 74 -

Język opisu sprzętu VHDL