PUCY 08 VHDL Uklady sekwencyjne


VHDL - Projektowanie bloków sekwencyjnych.
Główne tematy wykładu:
1. Projektowanie rejestrów i liczników.
2. Projektowanie pamięci o dostępie swobodnym (RAM).
3. Projektowanie automatów stanów synchronicznych.
4. Uwagi praktyczne.
Literatura:
1. Zw1  Mark Zwoliński  Projektowanie układów cyfrowych z wykorzystaniem języka VHDL -
WKA 2002
2. Sk1  Kevin Skahill  Język VHDL - Projektowanie programowalnych układów logicznych -
NT 2001
3. LZ1 - Tadeusz Auba, Bogdan Zbierzchowski  Komputerowe projektowanie układów
cyfrowych - WKA 2000
Wprowadzenie
Podstawowym problemem w projektowaniu układów synchronicznych jest uzależnienie działania
układu od sygnału taktującego, zegara. Najczęściej układy synchroniczne reagują na narastające
zbocze sygnału zegara. W języku VHDL istnieje wiele sposobów wykrywania zbocza zegara z
których kilka zostanie omówionych na przykładzie przerzutnika D.
W pierwszym przykładzie użyta zostanie instrukcja wait...until. Pozwala ona oczekiwać na
zdarzenie zapisane wyrażeniem warunkowym po słowie until. Ponieważ jest to instrukcja
sekwencyjna musi być użyta w bloku procesu. Proces może mieć listę czułości lub instrukcje wait.
1. library ieee; -- projekt P1_D_wait
2. use ieee.std_logic_1164.all;
3.
4. entity D_FF is
5. port (D, CK : in std_logic;
6. Q : out std_logic);
7. end entity D_FF;
8.
9. architecture D_wait of D_FF is
10. begin
11. p0: process is
12. begin
13. wait until (CK = '1');
14. Q<=D;
15. end process p0;
16. end architecture D_wait;
Rys. 1  Symulacja projektu D_wait.
W omawianym przykładzie lista czułości procesu jest pusta. Wykrycie zmiany sygnału taktującego
CK z 0 na 1 umożliwia instrukcja wait until zatrzymująca działanie procesu aż do wystąpienia
tego zdarzenia. Dopiero po nim nastąpi przypisanie zmiennej wyjściowej D do wyjściowej Q.
1
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Projekt ten zajmuje jedną makrocelę a maksymalny czas propagacji zegara CK do wyjścia Q
wynosi 11 ns (dla układu EP1K30T144-30). Symulację tego projektu pokazuje rysunek 6.1.
Analizując przebieg symulacji warto zauważyć, że zmiana sygnału wejściowego D w tym samym
momencie co sygnału zegara CK nie zostanie zauważona przez przerzutnik. Nie spełniony został
czas t .
SET_UP
W kolejnym przykładzie użyta zostanie instrukcja if...then. Oczekując na spełnienie warunku
również trzeba użyć tej instrukcji sekwencyjnie a więc w bloku procesu. Na liście czułości procesu
znalazł się sygnał zegara CK. Jego zmiana spowoduje ponowne uruchomienie procesu, a więc
dopiero po wykryciu zbocza zegara zostaje sprawdzone czy było to zbocze narastające, wtedy
CK= 1 , czy opadające.
1. architecture D_if of D_FF is -- projekt P1_D_if
2. begin
3. p0: process (CK) is
4. begin
5. if (CK = '1') then Q<=D;
6. end if;
7. end process p0;
8. end architecture D_if;
W obu omówionych przypadkach instrukcja podstawienia zostanie wykonana dopiero po spełnieniu
warunku zmiany sygnału zegara z 0 na 1.
Układy działają identycznie i zgodnie z raportem są dokładnie tak samo zrealizowane:
-- Node name is 'Q'
-- Equation name is 'Q', type is output
Q = _LC2_C14;
-- Node name is ':3'
-- Equation name is '_LC2_C14', type is buried
_LC2_C14 = DFFE( D, GLOBAL( CK), VCC, VCC, VCC);
Przerzutnik wbudowany w makrocelę ma następującą definicję w AHDL, która to jest używana w
raportach programu MaxPlusII:
FUNCTION DFFE (D, CLK, CLRN, PRN, ENA)
RETURNS (Q);
Działanie tej funkcji opisuje tabela:
wejścia wyjścia
CLRN PRN ENA D CLK Q
L H X X X L
H L X X X H
L L X X X nielegalne
H H L X X Q
H H H L ę! L
H H H H ę! H
H H X X L Q
Powyższy opis projektu można zmodyfikować do następującej postaci (nie działa to w MaxPlusII):
1. architecture D_if of D_FF is -- projekt P1_D_if_wait
2. begin
3. p0: process is
4. begin
5. if (CK = '1') then Q<=D; end if;
6. wait on CK;
7. end process p0;
8. end architecture D_if;
2
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Instrukcja wait on zawiesza wykonanie procesu aż do zmiany sygnału CK. W tym przypadku
podstawienie zostanie wykonane przed zawieszeniem wykonania procesu w oczekiwaniu na zmianę
sygnału taktującego CK.
O ile pierwsze przykłady jednoznacznie opisują działanie przerzutnika czułego na narastające zbocze
sygnału zegara to trzeci przykład może być różnie interpretowany przez narzędzia syntezy. Wydawać by się
mogło, że opisuje on przerzutnik typu latch, aktywny poziomem wysokim ale należy pamiętać, że opisywane
zmienne realizowane są sprzętowo a więc  działają bez przerwy. Po wykonaniu procesu, w którym
oczekując na zmianę sygnału CK wykryto zbocze 0->1 następuje ponowne jego wykonanie, a więc
podstawienie Q<=D i ponowne jego zawieszenie z oczekiwaniem na zmianę CK dla zbocza 1->0.
Zwykle zmienne wejściowe i wyjściowe deklarowane są jako std_ulog a jak pamiętamy mogą
wtedy przyjmować jeden z dziewięciu stanów. Zaproponowany wyżej sposób chociaż poprawny
dla syntezy w FPLD to jego symulacja może mieć problemy z tak zdefiniowanym projektem.
Problem polega na tym, że wykrywany jest stan  1 po zmianie sygnału taktującego CK. Lepiej jest
się jednak upewnić, że przed pojawieniem się stanu  1 był stan  0 co można uczynić w
następujący sposób (CK event jest prawdą gdy zmiana sygnału CK nastąpiła w aktualnym czasie):
1. architecture D_if of D_FF is
2. begin
3. p0: process is
4. begin
5. if (CK = '1' and CK last_value= 0 and CK event) then
6. Q<=D;
7. end if;
8. end process p0;
9. end architecture D_if;
Jednak taka forma nie jest rozpoznawana przez wszystkie narzędzia syntezy min. przez MaxPlusII.
Nie rozpoznawane są atrybuty sygnałów pomimo ich deklarowanej dostępności. Dostępne są
natomiast funkcje rising_edge i falling_edge w pakiecie standardowym. Pierwsza z nich
pozwala wykryć narastające zbocze sygnału będącego parametrem tej funkcji a druga jego
opadające zbocze. Odpowiednia definicja architektury przerzutnika D ma postać:
1. architecture D_if of D_FF is -- projekt P1_D_if_ris
2. begin
3. p0: process (CK) is
4. begin
5. if rising_edge(CK) then
6. Q<=D;
7. end if;
8. end process p0;
9. end architecture D_if;
Dotychczas prezentowany opis przerzutnika abstrahował od jego fizycznej realizacji. Ponieważ
układy FPLD są wyposażone w przerzutniki można, gdy zachodzi tego potrzeba, bezpośrednio
wskazać sygnały podane na wyprowadzenia przerzutnika. Odpowiednia definicja projektu
przerzutnika D ma postać (wynik symulacji tego projektu pokazuje rys.7.2):
1. entity D_FF is -- projekt P1_D_ff
2. port (D,CK,RES,PR : in std_logic; Q : out std_logic);
3. end entity D_FF;
4. architecture D_FF of D_FF is
5. component DFF
6. port (d : in std_logic; -- wejście danych
7. clk : in std_logic; -- wejście taktujące
8. clrn : in std_logic; -- wejście zerujące
9. prn : in std_logic; -- wejście ustawiające
10. q : out std_logic); -- wyjście danych
11. end component DFF;
12. begin
13. przerzutnik: DFF port map(D,CK,RES,PR,Q);
14. end architecture D_FF;
3
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Rys. 2  Symulacja projektu D_FF.
Projektowanie rejestrów i liczników
" Rejestr RR - Rejestr równoległo-równoległy jest szczególnym przypadkiem rejestru typu D.
Wprowadzimy do jego definicji dodatkowy sygnał zerujący CLR. Opis projektu dla takiego rejestru
jest następujący:
1. library ieee; -- projekt P2_rej_rr
2. use ieee.std_logic_1164.all;
3.
4. entity rej_RR is
5. generic (n : natural := 16);
6. port (WE : in std_ulogic_vector (n-1 downto 0);
7. CK, CLR : in std_ulogic;
8. WY : out std_ulogic_vector (n-1 downto 0));
9. end entity rej_RR;
10.
11. architecture rejestr_RR of rej_RR is
12. begin
13. e0: process (CK, CLR) is
14. begin
15. if (CLR = '0') then
16. WY <= (others => '0');
17. elsif rising_edge (CK) then
18. WY <= WE;
19. end if;
20. end process e0;
21. end architecture rejestr_RR;
Wynik symulacji projektu rej_RR pokazuje rysunek 3.
Rys. 3  Symulacja projektu rej_RR.
Układ działa zgodnie z oczekiwaniami tzn. na jego wyjściu WY pojawia się stan z wejścia WE pod
wpływem narastającego zbocza sygnału CK po maksimum 11 ns (dla układu EP1K30T144-30).
Niestety program MaxPlusII nie informuje o szybkości reakcji układu na sygnał zerujący CLR.
4
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
W układzie FPLD i-ta pozycja rejestru opisanego powyższym projektem została zrealizowana w
następujący sposób:
-- Node name is 'WY0'
-- Equation name is 'WY0', type is output
WY0 = _LC2_C16;
-- Node name is ':49'
-- Equation name is '_LC2_C16', type is buried
_LC2_C16 = DFFE( WE0, GLOBAL( CK), GLOBAL( CLR), VCC, VCC);
Jak widać realizacja rejestru jest identyczna z pokazaną poprzednio realizacją przerzutnika D.
Wykorzystano dwa sygnały globalne: taktujący CK i zerujący CLR. Przesłanie tych sygnałów po
liniach globalnych pozwala na zminimalizowanie czasu ich propagacji a także dostarczenie ich w
tym samym czasie do wszystkich przerzutników.
" Rejestr przesuwający - Rejestr równoległo-równoległy z operacjami przesuwania w lewo i
w prawo o jedną pozycję.
W projekcie nie można użyć operacji przesuwania np. sll, której parametrem jest liczba pozycji
przesuwania dlatego użyjemy konkatenacji wektorów. Projekt ma postać:
1. library ieee; -- projekt P2_rej_shift
2. use ieee.std_logic_1164.all;
3.
4. entity rej_SHIFT is
5. generic (n : natural := 8);
6. port (WE : in std_ulogic_vector (n-1 downto 0);
7. S : in std_ulogic_vector (1 downto 0);
8. CK,CLR,SR,SL : in std_ulogic;
9. WY : inout std_ulogic_vector (n-1 downto 0));
10. end entity rej_SHIFT;
11.
12. architecture rejestr_SHIFT of rej_SHIFT is
13. signal rej : std_ulogic_vector(n-1 downto 0);
14. begin
15. rej <= WE when S="00" else
16. (WY(n-2 downto 0) & SL) when S="01" else
17. (SR & WY(n-1 downto 1)) when S="10" else
18. WY when S="11";
19. e0: process (CK, CLR) is
20. begin
21. if (CLR = '0') then WY <= (others => '0');
22. elsif rising_edge (CK) then WY <= rej; end if;
23. end process e0;
24. end architecture rejestr_SHIFT;
W projekcie tym wprowadzony został dodatkowy sygnał rej pozwalający na przygotowanie danej
zapisywanej do rejestru przed narastającym zboczem zegara. Instrukcja podstawienia danej do rej
wykonywana jest równolegle do procesu e0 dlatego na wyjściu WY rejestru pojawi się dana z rej
ustalona bezpośrednio przed narastającego zbocza zegara.
Realizacja w FPLD zerowej pozycji rejestru ma postać:
-- Node name is 'WY0'
-- Equation name is 'WY0', type is bidir
WY0 = TRI(_LC8_B9, VCC);
_LC8_B9 = DFFE( _EQ008, GLOBAL( CK), GLOBAL( CLR), VCC, VCC);
_EQ008 = _LC3_B16 & S1
# _LC3_B16 & S0
# !S0 & !S1 & WE0;
_LC3_B16 = LCELL( _EQ023);
_EQ023 = _LC4_B16
# SL & S0 & !S1;
5
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
_LC4_B16 = LCELL( _EQ024);
_EQ024 = !S0 & S1 & WY1
# S0 & S1 & WY0;
Na wejściu przerzutnika _LC8_B9 zrealizowany jest multiplekser wybierający w zależności od
wartości sterowania S[1..0]:
gdy  00 daną wejściową WE0,
gdy  01 daną z wejścia SL  przesunięcie w lewo,
gdy  10 zawartość rejestru WY1  przesunięcie w prawo,
gdy  11 stan wyjścia WY0 (operacja nic nie rób).
" Licznik rewersyjny  Licznik z zerowaniem i ładowaniem synchronicznym
zwiększający/zmniejszający swoją zawartość o 1.
Projekt licznika różni się od projektu rejestru przesuwającego chociaż można oba przedstawić
podobnym schematem blokowym, w którym blok przerzutników poprzedza blok kombinacyjny
przygotowujący wartość wpisywaną do przerzutników. W przypadku licznika w pełni
synchronicznego najpierw trzeba wykryć zbocze zegara a następnie wykonać operację uzależnioną
od sterowania.
1. library ieee; -- projekt P3_licz_rev
2. use ieee.std_logic_1164.all;
3. use ieee.std_logic_arith.all;
4.
5. entity licz_rev is
6. generic (n : natural := 8);
7. port (WE : in std_ulogic_vector (n-1 downto 0);
8. CK,CLR,UD,LD : in std_ulogic;
9. WY : out std_ulogic_vector (n-1 downto 0));
10. end entity licz_rev;
11.
12. architecture licznik of licz_rev is
13. begin
14. e0: process (CK) is
15. variable licz : unsigned (n-1 downto 0);
16. begin
17. if rising_edge (CK) then
18. if (CLR = '0') then licz := (others => '0');
19. elsif ( LD = '0') then licz := unsigned (WE);
20. elsif ( UD = '0') then licz := licz-1;
21. else licz := licz+1; end if; end if;
22. WY <= std_ulogic_vector(licz);
23. end process e0;
24. end architecture licznik;
Ponieważ użyto typu unsigned oraz operacji arytmetycznych: dodawania i odejmowania,
konieczne było dołączenie biblioteki arytmetycznej ieee.std_logic_arith. Zmienna
pomocnicza licz ma inny typ od zmiennej wejściowej WE i wyjściowej WY dlatego konieczna
jest konwersja typów zrealizowana w wierszu 19 i 22. Symulacja projektu wskazuje maksymalny
czas propagacji równy 11 ns (dla układu EP1K30T144-30).
Uwaga. W wierszach 18-21 użyto znaku podstawienia  := gdyż po lewej stronie
znaku podstawienia  <= nie może wystąpić zmienna zadeklarowana jako variable.
Porównując projekt licznika o podobnej skali złożoności rejestrem przesuwnym okazuje się, że
8-bitowy licznik wymaga 25 makroceli a 8-bitowy rejestr 24 makroceli a więc mają identyczną
złożoność. Oczywiście gdyby funkcje wzbudzeń dla przerzutników licznika trzeba było zrealizować
z bramek to ze względu na operacje arytmetyczne wymagałby on zdecydowanie większej liczby
składników niż rejestr ale do realizacji projektów został wybrany układ FPLD w którym matrycę
AND zastępuje tablica LUT czyli pamięć, dla której złożoność funkcji kombinacyjnej nie ma
istotnego znaczenia.
6
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Projektowanie pamięci o dostępie swobodnym (RAM).
Do zaprojektowania pamięci RAM wykorzystana zostanie tablica dwuwymiarowa.
1. library ieee; -- projekt P4_ram_16x8
2. use ieee.std_logic_1164.all;
3. entity ram_16x8 is
4. port (DIN : in std_ulogic_vector (7 downto 0);
5. DOU : out std_ulogic_vector (7 downto 0);
6. ADR : in integer range 0 to 15;
7. CS,WR,RD : in std_ulogic);
8. end entity ram_16x8;
9. architecture pamiec_RAM of ram_16x8 is
10. begin
11. e0: process (ADR,DIN,CS,WR,RD) is
12. type ram_array is array (0 to 15) of
13. std_ulogic_vector (7 downto 0);
14. variable mem : ram_array;
15. begin
16. DOU <= (others => 'Z');
17. if (CS = '0') then
18. if (RD = '0') then DOU <= mem(ADR);
19. elsif (WR = '0') then mem(ADR) := DIN; end if; end if;
20. end process e0;
21. end architecture pamiec_RAM;
Rozdzielono dane wejściowe DIN od wyjściowych DOU gdyż podczas symulacji nie udaje się, bez
problemów dla sygnału dwukierunkowego, wymusić stan wejścia a następnie odczytać stan wyjścia
dla tej samej zmiennej. Wynik symulacji tego projektu pokazuje rysunek 4.
Rys. 4  Symulacja projektu ram_16x8.
Z raportu syntezy projektu wynika zapotrzebowanie na 243 makrokomórek z maksymalnym
czasem dostępu 32,9 ns, prawie dwa razy więcej niż liczba przerzutników koniecznych do
zapamiętania w niej danych odpowiadających zapamiętywanym bitom danych. Trzeba jednak
pamiętać o konieczności wyboru komórek pamięci zarówno dla zapisu jak i odczytu.
Lepszym rozwiązaniem projektu RAM jest wykorzystanie elementu bibliotecznego lpm_ram_dq 
pamięci z rozdzielonymi danymi wejściowymi i wyjściowymi, która wykorzystuje wbudowany
blok pamięci EAB układu ACEX1K. Ale niestety nie uda się przy jej pomocy zaprojektować
pamięć RAM asynchronicznie sterowaną niezależnymi strobami odczytu i zapisu. Asynchroniczną
wersję RAM można zbudować z jednym sygnałem sterującym WE. Gdy WE= 1 następuje zapis
do pamięci a gdy WE= 0 odczyt. Projekt takiej pamięci ma następującą postać:
1.
library ieee; -- projekt P4_ram_lpm
2.
use ieee.std_logic_1164.all;
3.
library lpm;
4.
use lpm.lpm_components.lpm_ram_dq;
7
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
5. entity ram_16x8_lpm is
6. port (DIN : in std_logic_vector (7 downto 0);
7. DOU : out std_logic_vector (7 downto 0);
8. ADR : in std_logic_vector (3 downto 0);
9. WE : in std_logic);
10. end entity ram_16x8_lpm;
11. architecture pamiec_RAM of ram_16x8_lpm is
12. begin
13. e0: lpm_ram_dq
14. generic map (LPM_WIDTH=>8, LPM_WIDTHAD=>4, LPM_NUMWORDS=>16,
15. LPM_INDATA=>"UNREGISTERED", LPM_OUTDATA=>"UNREGISTERED",
16. LPM_ADDRESS_CONTROL=>"UNREGISTERED")
17. port map (data=>DIN, address=>ADR, we=>WE, q=>DOU);
18. end architecture pamiec_RAM;
Maksymalny czas propagacji dla tego rozwiązania wynosi 26,2 ns a realizacja tego projektu
wymagała jednego bloku EAB i osiem wbudowanych komórek ale żadnej makrokomórki. Sposób
działania takiej pamięci pokazuje wynik symulacji zaprezentowany na rysunku 5.
Rys. 5  Symulacja projektu ram_16x8_lpm
Z listy parametrów lpm_ram_dq wynika, że zarówno dane wejściowe i wyjściowe jak i adres mogą
być synchronizowane zegarem.
Projektowanie automatów stanów
Projekty automatów zarówno synchronicznych jak asynchronicznych zostaną pokazane na
przykładzie czterostanowego układu arbitrażu udostępniającego hipoteczny zasób. Żądanie dostępu
zgłaszane jest za pośrednictwem sygnałów RQi=0 a zgoda na dostęp udzielana jest sygnałami
Gri=0.
Aby nie dopuścić do przejęcia zasobu przez jednego z żądających, w automacie zostanie
zastosowany priorytet kołowy, tzn. po przyznaniu zasobu na żądanie RQ0=0 następny przydział
będzie odpowiedzią na żądanie RQ1=0 bez względu na ponowne zgłoszenie RQ0, tzn. gdy takie
żądanie zostanie zgłoszone przed lub równocześnie z żądaniem RQ0=0.
Zasadę działania automatu przedstawia rysunek 7.6. Krawędzie grafu opisane są wartościami
odpowiadającymi zmiennym wejściowym RQ0 i RQ1. Ponieważ projektowany jest automat
Moore a stan wyjść zależny jest wyłącznie od aktualnego stanu, dlatego jest on wymieniony w
węzłach opisujących stany automatu.
Rys. 6  Graf przejść automatu arbitrażu.
8
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Różnica pomiędzy automatem synchronicznym a asynchronicznym będzie polegała na tym, że ten
pierwszy będzie analizował stan wejść RQi w momentach wyznaczonych zegarem a automat
asynchroniczny będzie reagował natychmiast na zmianę sygnałów wejściowych. Jak można
zauważyć, pomiędzy dwoma zezwoleniami na dostęp do współdzielonego zasobu musi upłynąć co
najmniej jeden takt zegara. Ma to pozwolić na bezpieczne zwolnienie zasobu przez układ, któremu
go przydzielono.
" Automat synchroniczny
W każdym automacie można wyróżnić funkcję przejść i funkcję wyjść. Funkcja przejść opisuje
warunki przechodzenia pomiędzy stanami wewnętrznymi automatu, które należy nazwać.
Zrealizowane jest to w wierszu 12, który definiuje typ zawierający nazwy stanów. Funkcja wyjść
ustala stan wyjść automatu w zależności od stanu (automat Moora, który został właśnie
zaprojektowany) lub od stanu wewnętrznego i stanu wejść (automat Mealego). Projekt automatu
synchronicznego realizującego arbitraż pokazano poniżej.
1.
library ieee; -- projekt P5_aut_synch
2.
use ieee.std_logic_1164.all;
3.
4.
entity aut_synch is
5.
port (RQ0,RQ1,CK : in std_ulogic;
6.
GR0,GR1 : out std_ulogic);
7.
end entity aut_synch;
8.
9.
architecture arbitraz of aut_synch is
10.
begin
11.
e0: process (CK) is
12.
type state_type is (ST0,ST1,ST2,ST3);
13.
variable stan : state_type;
14.
begin
15.
if rising_edge(CK) then
16.
case stan is
17.
when ST0 =>
18.
GR0<='1'; GR1<='1';
19.
if RQ0='0' then stan:=ST1;
20.
elsif RQ1='0' then stan:=ST3;
21.
else stan:=ST0; end if;
22.
when ST1 =>
23.
GR0<='0'; GR1<='1';
24.
if RQ0='0' then stan:=ST1;
25.
else stan:=ST2; end if;
26.
when ST2 =>
27.
GR0<='1'; GR1<='1';
28.
if RQ1='0' then stan:=ST3;
29.
elsif RQ0='0' then stan:=ST1;
30.
else stan:=ST2; end if;
31.
when ST3 =>
32.
GR0<='1'; GR1<='0';
33.
if RQ1='0' then stan:=ST3;
34.
else stan:=ST0; end if;
35.
end case;
36.
end if;
37.
end process e0;
38.
end architecture arbitraz;
Działanie automatu uzależniono od narastającego zbocza sygnału zegara CK. Zmianę stanu
uzyskuje się przez operację podstawienia nazwy nowego stanu pod zmienną stan. Ponieważ
zmienna stan jest zadeklarowana jako variable konieczne jest użycie znaków  := w operacji
podstawienia. Wynik symulacji tego projektu pokazuje rysunek 7.
9
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Rys. 7  Symulacja projektu aut_synch.
Z symulacji wynika, że stan wyjść zmienia się nie na początku stanu, w którym są one określone ale
dopiero po zakończeniu cyklu zegarowego w danym stanie. Maksymalna zwłoka w reakcji na
zmianę stanu wejścia RQi nie przekracza dwóch taktów zegara przy zgłoszeniu żądania tylko na
jednym wejściu RQi.
Sprawdzenie stanu sygnału zegara na końcu stanu pozwala przyspieszyć wystawienie
odpowiedniego sygnału wyjściowego. Zmianę to wprowadzono w projekcie aut_synch_v1, którego
opis pokazano poniżej.
1.
library ieee; -- projekt P5_aut_synch_v1
2.
use ieee.std_logic_1164.all;
3.
entity aut_synch_v1 is
4.
port (RQ0,RQ1,CK : in std_ulogic;
5.
GR0,GR1 : out std_ulogic);
6.
end entity aut_synch_v1;
7.
architecture arbitraz of aut_synch_v1 is
8.
begin
9.
e0: process (CK) is
10.
type state_type is (ST0,ST1,ST2,ST3);
11.
variable stan, stan_akt : state_type;
12.
begin
13.
case stan_akt is
14.
when ST0 =>
15.
GR0<='1'; GR1<='1';
16.
if RQ0='0' then stan:=ST1;
17.
elsif RQ1='0' then stan:=ST3;
18.
else stan:=ST0; end if;
19.
when ST1 =>
20.
GR0<='0'; GR1<='1';
21.
if RQ0='0' then stan:=ST1;
22.
else stan:=ST2; end if;
23.
when ST2 =>
24.
GR0<='1'; GR1<='1';
25.
if RQ1='0' then stan:=ST3;
26.
elsif RQ0='0' then stan:=ST1;
27.
else stan:=ST2; end if;
28.
when ST3 =>
29.
GR0<='1'; GR1<='0';
30.
if RQ1='0' then stan:=ST3;
31.
else stan:=ST0; end if;
32.
end case;
33.
if rising_edge(CK) then stan_akt:=stan; end if;
34.
end process e0;
35.
end architecture arbitraz;
Wprowadzono drugą zmienną stan_akt reprezentujący aktualny stan automatu. Zmienna stan
przechowuje następny stan automatu, który zostaje wpisany do zmiennej stan_akt po wykryciu
narastającego zbocza zegara CK. Wynik symulacji pokazuje rysunek 8.
10
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
Rys. 8  Symulacja projektu aut_synch_v1.
Jak widać automat szybciej reaguje na zmianę sygnałów żądania dostępu ale pojawiły się szpilki o
czasie trwania 0,2ns. Teoretycznie żaden z układów synchronicznych i asynchronicznych nie
powinien zareagować na tą szpilkę ale nie jest to  czyste rozwiązanie, chyba że współpracuje on z
układami synchronizowanymi tym samym sygnałem zegara, które nie zauważą tych  zakłóceń .
Pierwsze przedstawione rozwiązanie wymaga 5 makroceli a drugie 6.
Projekt aut_synch_v1 można  lekko zmodyfikować uruchamiając dwa zamiast jednego procesu.
Pierwszy z nich stan_nastepny przygotowuje stan następny automatu i generuje stan wyjść GR0
i GR1. Proces stan_taktowanie obsługuje narastające zbocze zegara CK. Ponieważ zmienne
dotychczas zdefiniowane w procesie e0 mają obowiązywać w obu nowych procesach trzeba było
przenieść ich definicje na poziom architektury i zamiast deklaracji stanu jako zmiennej trzeba było
zadeklarować go jako sygnał. Konsekwencją zmiany deklaracji jest zastąpienie postawienia
stan:=..... podstawieniem stan<=.....
1. architecture arbitraz of aut_synch_v2 is -- projekt P5_aut_synch_v2
2. type state_type is (ST0,ST1,ST2,ST3);
3. signal stan, stan_akt : state_type;
4. begin
5. stan_nastepny:
6. process is
7. begin
--------------- wiersze 15-34 z projektu aut_synch_v1 --------
28. end process stan_nastepny;
29. stan_taktowanie:
30. process (CK) is
31. begin
32. if rising_edge(CK) then stan_akt<=stan; end if;
33. end process stan_taktowanie;
34. end architecture arbitraz;
Efekt jest identyczny jak dla projektu aut_sym_v1, tzn. układ zachowuje się identycznie i wymaga
tych samych zasobów.
W niektórych przypadkach projektant chciałby narzucić sposób kodowania stanów wewnętrznych
automatu. Należy wtedy zmienić sposób deklarowania stanu automatu. W miejsce typu
state_type i sygnały stan i stan_akt definiowane są jako wektory binarne. Przy takiej
definicji można określić stałe opisujące poszczególne stany jak pokazano poniżej. Pozostała część
pliku opisującego projekt pozostaje bez zmian jak również wyniki otrzymane z syntezy tego
projektu są identyczne jak poprzednie.
1. architecture arbitraz of aut_synch_v4 is
2. signal stan, stan_akt : std_logic_vector (1 downto 0);
3. constant ST0 : std_logic_vector (1 downto 0) := "11";
4. constant ST1 : std_logic_vector (1 downto 0) := "10";
5. constant ST2 : std_logic_vector (1 downto 0) := "01";
6. constant ST3 : std_logic_vector (1 downto 0) := "00";
11
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.
" Automat asynchroniczny
Niestety nie można zaprojektować asynchronicznego automatu stanów realizowanego w układach
FPLD firmy Altera. Nie oznacza to, że jest to niemożliwe. Trzeba po prostu zaprojektować automat
samodzielnie i projekt opisać na poziomie funkcji logicznych.
-- projekt P5_aut_asynch
Uwagi praktyczne
1. Synchronizację działania układu zboczem sygnału taktującego ułatwiają standardowe funkcje:
rising_edge(zegar)  wykrywająca narastające zbocze sygnału taktującego i
falling_edge(zegar)  dla zbocza opadającego. Samodzielne wykrycie zbocza dla std_ulogic
naprawdę nie jest proste zwłaszcza, że MaxPlussII nie pozwala użyć odpowiednich atrybutów.
2. Ze względu na konieczność użycia instrukcji sekwencyjnych opis układów sekwencyjnych trzeba
zawrzeć w strukturze process.
12
2007-07-19
MPW  PUCY  VHDL  projektowanie układów sekwencyjnych.


Wyszukiwarka

Podobne podstrony:
PRZERZUTNIKI I UKŁADY SEKWENCYJNE
15 Język Instruction List Układy sekwencyjne Działania na liczbach materiały wykładowe
10 Cyfrowe Układy Sekwencyjne
zadania na układy sekwencyjne
Cyfrowe uklady sekwencyjne
Czesc3, układy sekwencyjne
08 Podstawowe Uklady Sekwencyjne (6)
UKŁADY SEKWENCYJNE
W2 Układy sekwencyjne AiSD 2012

więcej podobnych podstron