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
- 2 -
Język opisu sprzętu VHDL
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 -
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
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 -
•
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
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 -
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
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 -
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 integer, real oraz time.
Wykonywanie operacji arytmetycznych dla typów takich jak np. std_logic wymaga
- 10 -
Język opisu sprzętu VHDL
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 -
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
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 -
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
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 -
+
+
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
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 -
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
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 -
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
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 0 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 -
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
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 -
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
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 -
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
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 A, B, Ci oraz Co w taki sposób, że sygnały A, B oraz Ci są wejściami i odpowiadają
Język opisu sprzętu VHDL
- 27 -
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
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 -
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
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 -
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
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 -
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
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 Z. Jest 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 -
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
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 -
-- 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
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 -
-- 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
-- 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 -
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
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 -
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
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 -
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
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 -
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
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 -
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
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 -
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
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 -
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
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 -
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
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 -
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
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 -
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
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 -
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,
GenNum, ReadNum 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
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 -
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
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 -
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
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 -
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: Div, V2H 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
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 -
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
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 -
--
-- 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
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 -
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