Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałAureliusz Krasuski Został zmieniony 11 lat temu
1
JĘZYK VHDL Geneza: komputerowa symulacja układu cyfrowego, Departament Obrony USA opis skomplikowanego systemu w postaci schematu jest nieczytelny, szybkie wprowadzanie zmian w opisie układu języki HDL: VHDL, Verilog, Abel zalety: więcej informacji niż w opisie schematowym, krótszy cykl projektowy złożonych układów, niezależność od technologii, opis na różnych poziomach abstrakcji, symulacja na różnych etapach zaawansowania projektu, standaryzacja wady: zmiana stylu projektowania, koszty narzędzi, szkoleń, problem syntezowalności, jakość syntezy, trudność oceny złożoności projektu VHDL- skrót: VHSIC (Very High Speed Integrated Circuit) Hardware Description Language, standard IEEE , IEEE r
2
Poziomy abstrakcji (style opisu układów):
behawioralny (algorytmiczny, systemowy) -opis działania układu bez szczegółów realizacyjnych (procesy, pętle) RTL (przesłań międzyrejestrowych, Dataflow) logiczny (wyrażeń boolowskich, bramek) strukturalny (podział na podukłady, wielokrotne wykorzystanie podukładów)
3
zasady opisu strukturalnego:
pełny układ można rozłożyć na komponenty, stopień złożoności komponentów jest dowolny brak ograniczeń co do liczby poziomów hierarchii najniższy poziom hierarchii musi mieć zdefiniowany model działania (styl behawioralny, RTL lub logiczny) elementy modelu działania: sygnały (odpowiedniki fizycznego połączenia, fizycznych wartości logicznych w układzie) procesy (operacje na wartościach logicznych w układzie) współbieżne wykonywanie operacji poszczególne części układu działają w sposób równoległy dwa rodzaje kodu VHDL: kod współbieżny kod sekwencyjny (procesy)
4
Elementy składni języka
* Przypisanie wartości sygnału: sample <= “0000” next_sample <= sample * Operatory relacyjne: =, /=, >, <, <=, >= * Operatory logiczne: and, xor, or, nand, nor, xnor, not * Operatory arytmetyczne: +, -, *, /, mod, rem * Operatory znaku: +, - * Operator sklejania: & *Wyrażenie “if -then -elsif -end if” (tylko procesy) *Wyrażenie “case -when..-when.. -end case” (tylko procesy) *Wyrażenie “for” (pętle w procesach, generacje) *Wyrażenia “when - else” oraz “with.. select” (odpowiednik case poza procesem) tzn. przypisanie warunkowe i selektywne *Konstrukcja “wait” *Przypisanie wartości zmiennej “:=“ *Pętla “while”
5
Zasady ogólne: * VHDL nie rozróżnia dużych i małych liter (ale należy mieć na uwadze tzw. dobry styl) * średnik kończy wyrażenie (zakończenie linii programu) * każda linia komentarza rozpoczyna się od “--” * identyfikatory muszą zaczynać się od litery i zawierać na następnych pozycjach znaki alfanumeryczne lub pokreślenie “_” * język silnie zorientowany na typ, automatyczna konwersja należy do rzadkości, możliwe jest przeciążanie operatorów, funkcji, procedur * syntezowalny jest jedynie podzbiór języka * żaden z systemów EDA nie gwarantuje prawidłowej syntezy modelowania algorytmicznego * wielkość układu po syntezie nie ma nic wspólnego z objętością kodu (należy zrezygnować z finezyjnego zapisu!!!)
6
Opis układu/podukładu składa się z deklaracji jednostki (ENTITY) i jednego lub więcej bloków ARCHITECTURE opisującego działanie. ENTITY zawiera listę zacisków wejściowych i wyjściowych (PORTS), jest ekwiwalentem symbolu na schemacie entity model_name is port ( list of inputs and outputs ); end model_name; architecture arch_name of model_name is begin ..... VHDL concurrent statements end arch_name;
7
when -else library IEEE; use IEEE.std_logic_1164.all;
entity mux2to1 is port ( signal s :in std_logic; signal x0,x1 :in std_logic_vector(7 downto 0); signal y :out std_logic_vector(7 downto 0) --brak średnika!!! ); end mux2to1; architecture a1 of mux2to1 is begin y <= x1 when (s=‘1’) else x0; end a1; ALTERA -nazwa pliku musi pokrywać się z nazwą entity (tutaj mux2to1.vhd)
8
* LIBRARY -biblioteka to zbiór zanalizowanych jednostek projektowych przechowywany w danym systemie operacyjnym (nazwa logiczna a nie katalog w systemie!) * aby można się było odwoływać do elementów biblioteki należy użyć klauzuli USE (specyfikuje które pakiety -package będą wybrane z biblioteki) use IEEE.std_logic_1164.all importuje procedury, funkcje i definicje pakietu std_logic_1164 * Pakiet std_logic_1164 definiuje system logiczny 9-wartościowy, 4 wartości są przydatne dla syntezy: ‘1’, ‘0’, ‘Z’ (high impedance), ‘-’ (don’t care), pozostałe wartości używane są dla celów symulacji: ‘U’ (uninitialized), ‘X’ (unknown-strong drive), ‘W’,’L’,’H’ (unknown, logic 0, logic 1 -weak drive). Dwa typy danych: std_ulogic oraz std_logic -z dodatkową funkcją rozstrzygającą konflikty połączeń (resolution function). Zalecane jest używanie typu std_logic! Przykład: sygnał y ma dwa sterowniki (driver’y) y<=a; y<=b;
9
* typ std_logic jest pojedynczym bitem, std_logic_vector jest używany do definiowania magistral
* VHDL posiada wbudowany typ bit 2-wartościowy ‘1’ i ‘0’; jest on niewystarczający do syntezy; istnieje też typ bit_vector * na liście portów podajemy końcówki zewnętrzne układu w konwencji: nazwa tryb typ dla celów syntezy używa się trybów in, out, inout słowo signal jest opcjonalne -najczęściej w deklaracji portów opuszczane * szerokość magistrali można definiować z indeksem rosnącym lub malejącym std_logic_vector (7 downto 0) lub std_logic_vector(0 to 7) skutek: różny wynik operacji przypisania np. y<=“ ” (wektory piszemy w podwójnym cudzysłowiu), jest równoważne operacjom: y(7)<=‘1’; ... ; y(0)<=‘0’; lub y(0)<=‘1’; ... ; y(7)<=‘0’; * indeks elementu magistrali może mieć dowolną wartość całkowitą * można użyć w opisie układu poszczególnych elementów magistali y(5 downto 2)<=“0110”; UWAGA: kierunek indeksowania musi być zgodny z deklaracją magistrali y(5 downto 3)<=x(0 to 2); oznacza przypisanie y(5)<=x(0); y(4)<=x(1); y(3)<=x(2); * jeżeli przypisujemy wartość całej magistrali wówczas nie trzeba specyfikować indeksów np. y<=x1; szerokość magistrali po obu stronach musi być identyczna!!!
10
* operator sklejania & (concatenation), np. dla deklaracji:
signal a :out std_logic_vector(7 downto 0); signal b : in std_logic_vector(3 downto 0); możliwe jest przypisanie a <= “100” & b & ‘1’; * ogólna postać warunkowego przypisania sygnału: signal_name <= value1 when condition1 else value2 when condition2 .... else valueN when conditionN else default_value; warunki są wyrażeniami przyjmującymi wartości true/false * wynik syntezy:
11
Przypisanie selektywne (selected signal assignment)
* Ogólna postać: with condition select signal_name<= value1 when cond_value1, value2 when cond_value2, .... valueN when cond_valueN, valueX when others; * warunki mogą być rozdzielone operatorem “or” w postaci | * przykład zastosowania: with sel select a<= d when “000” | “001”, e when “101”, ‘Z’ when others; * w niektórych przypadkach efekt działania identyczny z warunkowym przypisaniem sygnału * współbieżne przypisanie sygnału (concurrent signal assignment), warunkowe (conditional..) i selektywne (selected ...) są instrukcjami współbieżnymi, wykonywanymi jednocześnie i kolejność ich umieszczenia w bloku “architecture” nie ma znaczenia
12
Multiplekser 2/1 -metoda równań kombinacyjnych
library IEEE; use IEEE.std_logic_1164.all; entity mux2to1 is port ( s :in std_logic; x0,x1 :in std_logic_vector(7 downto 0); y :out std_logic_vector(7 downto 0) ); end mux2to1; architecture a2 of mux2to1 is signal temp: std_logic_vector(7 downto 0); begin temp<=(others=>s); y<=(temp and x1) or (not temp and x0); end a2;
13
* sygnał s (port wejściowy) nie może być bezpośrednio użyty w operacjach logicznych z sygnałami x0 i x1 ze względu na różny typ (std_logic, std_logic_vector) * zadeklarowano sygnał wewnętrzny -wektor/magistralę; deklaracje sygnałów umieszcza się zawsze przed słowem kluczowym begin * w deklaracji sygnału wewnętrznego nie określa się trybu (in, out, inout) * typ sygnału temp jest zgodny z x0 i x1 (ta sama szerokość wektora!!!) * każdemu bitowi wektora temp przypisano stan portu wejściowego s temp <= (others=>s); --najprostszy zapis (aggregate) temp<= (s,s,s,others=>s); temp<= (4=>s, 7=>s, 2=>s, 5=>s, 3=>s, 1=>s, 6=>s, 0=>s); temp<= s & s & s & s & s & s & s & s; temp(0)<=s; temp(1)<=s; ..... temp(7)<=s; temp(7 downto 4)<= (s,s,s,s); temp(2 downto 0)<= (others=>s); temp(3)<=s;
14
* zapis: y<=(temp and x1) or (not temp and x0);
jest równoważny z przypisaniem odpowiedniego wyrażenia każdemu elementowi wektora y y(7)<= (temp(7) and x1(7)) or (not temp(7) and x0(7)); y(6)<= (temp(6) and x1(6)) or (not temp(6) and x0(6)); ..... y(0)<= (temp(0) and x1(0)) or (not temp(0) and x0(0)); * ponieważ każdy element wektora temp jest równy s, to wykonywane jest działanie: y(7)<= (s and x1(7)) or (not s and x0(7)); ......
15
Multiplekser 2/1 -użycie procesu kombinacyjnego/niezegarowanego
architecture a3 of mux2to1 is begin comb: process (s, x0, x1) if (s=‘1’) then y<= x1; else y<=x0; end if; end process comb; end a3; * proces jest częścią kodu VHDL wykonywaną (analizowaną) sekwencyjnie; proces traktowany jako całość wykonywany jest współbieżnie z innymi procesami w architekturze oraz z innymi instrukacjami współbieżnymi; w obrębie procesu dozwolone jest stosowanie wyłącznie instrukcji sekwencyjnych * zmiana wartości któregokolwiek sygnału umieszczonego na liście czułości procesu powoduje analizę jego kodu przez symulator
16
* w procesach kombinacyjnych na liście czułości należy umieścić wszystkie (!!!) sygnały pobudzające blok logiki kombinacyjnej, który ma być efektem syntezy procesu s x0(7) x1(7) y(7) * w zależności od stanu sygnału s wyjście y powtarza zmiany na liniach x0 lub x1 * proces musi być analizowany gdy: (1) zachodzą zmiany wartości wektora x0 oraz s=0, (2) zachodzą zmiany wartości wektora x1 oraz s=1, (3) zmienia się wartość sygnału s.
17
* przypisanie nowej wartości do sygnału następuje w chwili wyjścia symulatora z procesu;
*w trakcie analizy kodu procesu rozpisywana jest tzw. transakcja; faktyczne przypisanie następuje z opóźnieniem delta, odpowiadającym najmniejszemu kwantowi czasu symulacyjnego (jeżeli nie wskazano inaczej!) np: czas a b c out1 out2 out3 process(a,b,c,out1,out2) t begin t > out1<=a and b; t2+d >0 1->0 out2<=out1 xor c; t2+2d >1 out3<=out1 xor out2; t2+3d end process * wniosek: pomimo że proces jest kodem sekwencyjnym, to kolejność umieszczenia przypisań do sygnałów jest dowolna
18
* w procesach których zamierzonym efektem ma być logika kombinacyjna konieczne jest zdefiniowanie sygnałów wyjściowych procesu dla wszystkich możliwych kombinacji wartości sygnałów wejściowych * często, aby uniknąć pomyłki na początku kodu procesu umieszcza się przypisanie wartości domyślnej comb: process(s, x0, x1) begin y<=x0; if (s=‘1’) then y<=x1; end if; end process comb; * w przypadku braku zdefiniowanego wyjścia dla pewnej grupy wartości wejściowych generowane są w procesie syntezy przerzutniki typu latch * proces opisuje reakcje części układu na pobudzenia (sygnały) bez wskazania sposobu realizacji
19
Enkoder priorytetowy entity en_prior is
port( x :in std_logic_vector(1 to 7); enc :out std_logic_vector(2 downto 0) ); end en_prior; architecture e1 of en_prior is begin process(x) -- każdy bit wektora x na liście czułości if (x(7)=‘1’) then enc<=“111”; elsif (x(6)=‘1’) then enc<=“110”; elsif (x(5)=‘1’) then enc<=“101”; elsif (x(4)=‘1’) then enc<=“100”; elsif (x(3)=‘1’) then enc<=“011”; elsif (x(2)=‘1’) then enc<=“010”; elsif (x(1)=‘1’) then enc<=“001”; else enc<=“000”; -- domyślna wartość wyjściowa end if; end process; end e1;
20
enc(2) enc(0) enc(1) x(6) x(4) x(5) x(7) x(2) x(1) x(3) * proces -kod sekwencyjny prowadzi do relizacji układowej czysto kombinacyjnej * kolejność sprawdzania warunków w łańcuchu wyrażeń if-elsif.... definiuje priorytet: najwyższy ma bit 7-my wektora x., bo jego warunek sprawdzany jest w procesie jako pierwszy
21
* w ramach procesu brane jest pod uwagę wyłącznie ostatnie napotkane podczas analizy kodu przypisanie wartości do sygnału; poniższy proces opisuje ten sam układ: process(x) begin enc<=“000”; --wartość domyślna if (x(1)=‘1’) then enc<=“001”; end if; if (x(2)=‘1’) then enc<=“010”; end if; if (x(3)=‘1’) then enc<=“011”; end if; if (x(4)=‘1’) then enc<=“100”; end if; if (x(5)=‘1’) then enc<=“101”; end if; if (x(6)=‘1’) then enc<=“110”; end if; if (x(7)=‘1’) then enc<=“111”; end if; end process; * bit 7-my ma najwyższy priorytet bo jest testowany jako ostatni (!!!) * ten sam efekt - przypisanie warunkowe, bez użycia procesu: enc <= “111” when x(7)=‘1’ else “110” when x(6)=‘1’ else “101” when x(5)=‘1’ else .... “001” when x(1)=‘1’ else “000”; --wartość domyślna
22
Przykład pętli -opis behawioralny enkodera priorytetowego
library IEEE; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity en_prior is port( x :in std_logic_vector(1 to 7); enc :out std_logic_vector(2 downto 0) ); end en_prior; architecture eloop of en_prior is begin process(x) variable i: integer; --definicja zmiennej i:=7; --przypisanie wartości do zmiennej while (i>0 and x(i)/=‘1’) loop i:=i-1; end loop; enc<=conv_std_logic_vector(i,3); --na drugim miejscu podana liczba pozycji end process; wektora wynikowego end eloop;
23
* zdefiniowano zmienną typu integer, przypisania do zmiennej dokonuje się przy pomocy operatora :=
* zmienne użyte w procesie są widoczne tylko w obrębie tego procesu; przechowują swoje wartości w trakcie “uśpienia” procesu * przypisanie nowej wartości do zmiennej następuje natychmiast -w momencie analizy linii przez symulator, np: process(a,b,c) czas a b c out1 out2 out3 variable out1,out2:std_logic; t begin t >0 out1:=a and b; t2+d out2:=out1 xor c; t out3<=(not out1) and out2; t >1 end process; t4+d * istotna jest kolejność wykonania przypisań, nowa wartość zmiennej jest uwzględniania w następnych liniach procesu * użyto funkcji konwersji integer -> std_logic_vector zdefiniowanej w pakiecie std_logic_arith * UWAGA: konstrukcje z pętlą while są często niesyntezowalne (Altera-Max+PlusII) Synplicity-wynik syntezy jest identyczny jak dla poprzednich architektur
24
Przykład pętli w układzie kombinacyjnym -opis syntezowalny
ENTITY proc IS PORT( d : IN BIT_VECTOR (2 DOWNTO 0); q : OUT INTEGER RANGE 0 TO 3 ); END proc; ARCHITECTURE maxpld OF proc IS BEGIN PROCESS (d) zliczanie jedynek logicznych w słowie wejściowym VARIABLE num_bits : INTEGER; num_bits := 0; FOR i IN d'RANGE LOOP --atrybut RANGE, zmienna i zdefiniow. automatycznie IF d(i) = '1' THEN num_bits := num_bits + 1; END IF; END LOOP; q <= num_bits; END PROCESS; END maxpld;
25
* użyto wbudowanego typu bit
* typ integer jest w układach cyfrowych interpretowany jako słowo binarne; może być wprost użyty w definicji portu bez potrzeby konwersji typu * długość słowa zależy od zakresu liczby integer - w przykładzie 2 bity * standardowo liczba integer zapisywana jest na 32 bitach * wskazówka: w kodzie przeznaczonym do syntezy należy używać jak najmniejszych liczb integer i zawsze ograniczać zakres
26
* typy pętli: prosta z określonym schematem iteracji L1:loop L2:for I in 1 to 3 loop do_something; A(I)<=B(I); end loop L1; end loop L2; L3:while condition loop do_something; end loop L3; * instrukcje używane w połączeniu z pętlami: next np: next L1 when I=J; next when (B<10); exit np: exit L2; exit Loop3 when a>b; *podstawowym warunkiem syntezowalności kodu z użyciem pętli jest ustalona na etapie syntezy liczba wykonań pętli * zaleca się stosowanie atrybutów do specyfikacji zakresu pętli
27
GENERATOR PARZYSTOŚCI
entity parity is generic (bus_size : integer := 8 ); port ( input_bus : in std_logic_vector (bus_size-1 downto 0); even_numbits, odd_numbits : out std_logic ) ; end parity ; architecture behave of parity is begin process (input_bus) variable temp: std_logic; temp := '0'; for i in input_bus'low to input_bus'high loop temp := temp xor input_bus( i ) ; end loop ; odd_numbits <= temp ; even_numbits <= not temp; end process; end behave;
28
* użyto parametru ogólnego generic; pozwala on na parametryzowanie podprojektów
* statyczny (!) przepływ informacji pomiędzy modułami * w szczególności zaleca się używanie tego typu stałej w definiowaniu wymiarów magistral, tablic, parametrów czasowych (w kodzie przeznaczonym do symulacji) * wartość parametru generic może być ustalona przy korzystaniu z danego komponentu na wyższym stopiniu hierarchii, łatwa rekonfigurowalność projektu KOMPARATOR entity compare is generic (size : integer := 16 ); port ( a,b :in std_logic_vector(size-1 downto 0); equal :out std_logic ); end compare; architecture c1 of compare is begin equal<= ‘1’ when a=b else ‘0’; end c1;
30
Dekoder 3 na 8 entity dec3to8 is port( sel :in std_logic_vector(2 downto 0); --wejścia ena :in std_logic; --output enable y :out std_logic_vector(7 downto 0) --wyjścia aktywne stanem niskim ); end dec3to8; architecture d1 of dec3to8 is begin procd:process(sel,ena) y<=“1111_1111”; --wartość domyślna if (ena=‘1’) then case sel is when “000”=> y(0)<=‘0’; when “001”=> y(1)<=‘0’; when “010”=> y(2)<=‘0’; when “011”=> y(3)<=‘0’; when “100”=> y(4)<=‘0’; when “101”=> y(5)<=‘0’; when “110”=> y(6)<=‘0’; when “111”=> y(7)<=‘0’; end case; end if; end process procd; end d1;
31
* wersja prawidłowa * wersja bez wartości domyślnej;
generowane są przerzutniki typu latch
32
* użyto wyrażenia sekwencyjnego case dozwolonego wyłącznie w procesach
* w wyrażeniu case można przypisać wartość domyślną używając konstrukcji when OTHERS => * wersja alternatywna z użyciem przypisania warunkowego osobno dla każdego bitu architecture d2 of dec3to8 is begin y(0)<=‘0’ when (ena=‘1’ and sel=“000”) else ‘1’; y(1)<=‘0’ when (ena=‘1’ and sel=“001”) else ‘1’; y(2)<=‘0’ when (ena=‘1’ and sel=“010”) else ‘1’; y(3)<=‘0’ when (ena=‘1’ and sel=“011”) else ‘1’; y(4)<=‘0’ when (ena=‘1’ and sel=“100”) else ‘1’; y(5)<=‘0’ when (ena=‘1’ and sel=“101”) else ‘1’; y(6)<=‘0’ when (ena=‘1’ and sel=“110”) else ‘1’; y(7)<=‘0’ when (ena=‘1’ and sel=“111”) else ‘1’; end d2; * indeksowanie przez sygnał-niezbędna funkcja konwersji znajduje się w pakiecie std_logic_unsigned; process (sel, ena) y<=“ ”; --wartość domyślna if (ena=‘1’) then y(conv_integer(sel))<=‘0’; end if; end process;
33
* wersja dekodera z pętlą w procesie
process(sel,ena) begin y<=“1111_1111”; for i in y’range loop if (ena=‘1’ and i=conv_integer(sel)) then y(i)<=‘0’; end if; end loop; end process; funkcja konwersji conv_integer jest dostępna po zadeklarowaniu use ieee.std_logic_unsigned.all; * wersja może być łatwo sparametryzowana (z użyciem generic), przypisanie wartości domyślnej należy wówczas zastąpić drugą pętla: for j in y’range loop y(j)<=‘1’;
34
Operatory przesunięcia (shift)
sll, srl, sla, sra, rol, ror -lewym argumentem jest bit_vector, prawym liczba całkowita sll, srl uzupełniają wektor wartością ‘0’ sla, sra powielają ostatni bit rol, ror wykonują rotację Uwaga: modelując rejestry przesuwne używa się operatora podstawienia z przesunięciem indeksów w wektorach i operatora sklejania &, zamiast operatorów przesunięcia * wersja dekodera 3 na 8 z operatorem przesunięcia architecture shift1 of dec3to8 is begin with ena select y<= to_stdlogicvector(“1111_1110” rol conv_integer(sel)) when ‘1’, “1111_1111” when others; end shift1;
35
Pół-sumator i pełny sumator 1 bitowy
entity halfadder is port( a,b :in std_logic; sum,cout :out std_logic); end halfadder; architecture a1 of halfadder is begin process(a,b) --OPIS BEHAWIORALNY if (a=‘1’ and b=‘1’) then cout<=‘1’; else cout<=‘0’; --cout<=a and b; end if; if ((a=‘1’ and b=‘0’) or (a=‘0’ and b=‘1’)) then sum<=‘1’; else sum<=‘0’; --sum<=a xor b; end process; end a1;
36
HALFADDER RTL -proces “Technology View”-Flex8000
RTL -równania logiczne
37
entity fulladder is port(
a,b,cin :in std_logic; sum,cout :out std_logic); end fulladder; architecture a1 of fulladder is -- OPIS DATAFLOW (poziom bramek) begin sum<=a xor b xor cin; cout<=(a and b) or (a and cin) or (b and cin); -- or (a and b and cin) end a1;
38
GENERACJA (generate) * jest odpowiednikiem pętli we współbieżnej części kodu * służy do automatycznej generacji struktur regularnych, tworzonych na bazie struktury wzorcowej (fizyczny efekt => powielenie podukładów wzorcowych) * wewnątrz generate może być powielana dowolna instrukcja współbieżna łącznie z samą instrukcją generate * dwa schematy generacji: generacja for dla układów w pełni regularnych, generacja if gdy istnieją nieregularności w układzie * wymagana jest etykieta (label) generacji * przykład: pełny sumator wielobitowy
39
entity fulladder_n is generic (size : integer := 4 ); port( a,b :in std_logic_vector(size-1 downto 0); sum :out std_logic_vector(size-1 downto 0); cin : in std_logic; cout :out std_logic); end fulladder_n; architecture a1 of fulladder_n is signal c :std_logic_vector(size downto 0); begin c(0)<=cin; G: for i in 0 to size-1 generate sum(i)<=a(i) xor b(i) xor c(i); c(i+1)<=(a(i) and b(i)) or (a(i) and c(i)) or (b(i) and c(i)); end generate; cout<=c(size); end a1; * parametr generacji nie musi być deklarowany (tutaj i)
42
entity adder_n is generic (size : integer := 4 ); port( a,b :in std_logic_vector(size-1 downto 0); sum :out std_logic_vector(size-1 downto 0); cout :out std_logic); end adder_n; architecture a1 of adder_n is signal c :std_logic_vector(size downto 1); begin G1: for i in 0 to size-1 generate G2:if i=0 generate sum(i)<=a(i) xor b(i); c(i+1)<=a(i) and b(i); end generate; --gałęzie else i elsif nie są dozwolone!!! G3: if i>0 generate sum(i)<=a(i) xor b(i) xor c(i); c(i+1)<=(a(i) and b(i)) or (a(i) and c(i)) or (b(i) and c(i)); end generate; cout<=c(size); end a1;
43
* ten sam efekt uzyskuje się stosując pętle w procesie
architecture a2 of fulladder_n is begin process(a,b,cin) variable c: std_logic; c:=cin; L: for i in 0 to size-1 loop sum(i)<=a(i) xor b(i) xor c; c:=(a(i) and b(i)) or (a(i) and c) or (b(i) and c); end loop L; cout<=c; end process; end a2; * istotna jest kolejność przypisań w pętli (c jest zmienną!!!) do obliczenia bieżącej wartości sum(i), oraz przeniesienia c brane jest pod uwagę przeniesienie z poprzedniej pozycji (c wyliczone w poprzednim wykonaniu pętli)
44
architecture a2 of adder_n is
begin process(a,b) variable c: std_logic; L: for i in 0 to size-1 loop if i=0 then sum(i)<=a(i) xor b(i); c:=a(i) and b(i); else sum(i)<=a(i) xor b(i) xor c; c:=(a(i) and b(i)) or (a(i) and c) or (b(i) and c); end if; end loop L; cout<=c; c:=‘0’; end process; L: for i in 0 to size-1 loop end a2; sum(i)<=a(i) xor b(i) xor c; cout<=c;
45
* wykorzystanie sumowania arytmetycznego zdefiniowanego w pakiecie std_logic_unsigned:
architecture a3 of adder_n is signal c :std_logic_vector(size downto 0); begin c<=(‘0’&a)+(‘0’&b); --przy zapisie c<=a+b; sum<=c(size-1 downto 0); --różna szerokość wektora, nie ma gwarancji cout<=c(size); --prawidłowej syntezy !!! end a3; * operacja na liczbach całkowitych: entity fulladder_int is port( a,b :in integer range 0 to 255; sum :out integer range 0 to 511; cin : in integer range 0 to 1); end fulladder_int; architecture a1 of fulladder_int is begin sum<=a+b+cin; end a1;
47
Projektowanie hierarchiczne (opis strukturalny)
* w opisie układu przywołujemy wcześniej zdefiniowane jednostki projektowe, dołączając sygnały do odpowiednich portów tych jednostek (tworzenie powiązań) * typy i zakresy sygnałów aktualnych i lokalnych (w przywoływanych jednostkach) muszą być zgodne * przy tworzeniu powiązań między portami obowiązuje zgodność kierunków (trybów) * przywołanie komponentu może również ustalać wartości parametrów ogólnych entity adder_4 is port( a,b :in std_logic_vector(3 downto 0); cin :in std_logic; sum :out std_logic_vector(3 downto 0); cout :out std_logic); end adder_4; architecture struct of adder_4 is begin component fulladder port( fa0: fulladder port map(a(0),b(0),cin,sum(0),c0); a,b,cin :in std_logic; fa1: fulladder port map(a(1),b(1),c0,sum(1),c1); sum,cout :out std_logic); fa2: fulladder port map(a(2),b(2),c1,sum(2),c2); end component; fa3: fulladder port map(a(3),b(3),c2,sum(3),cout); signal c0,c1,c2: std_logic; end struct;
48
* przyłączenia sygnałów do końcówek komponentu można dokonywać w dowolnej kolejności, ale z przywołaniem nazwy portu: fa2: fulladder port map(b=>b(2),a=>a(2),sum=>sum(2),cout=>c2,cin=>c1); * specyfikacja parametrów ogólnych -w deklaracji komponentu: component bufor generic (size:integer:=8); port( a:in std_logic_vector(size-1 downto 0); y:out std_logic_vector(size-1 downto 0) ); end component; -w podstawieniu komponentu buf1: bufor generic map(size=>8) port map(a=>port_in,y=>port_out); -w konfiguracji
49
Układy sekwencyjne Przerzutniki typu zatrzask (latch) aktywne poziomem
* zatrzask jest elementem pamiętającym latch: process(enable,data) process(enable,data) begin begin if (enable=‘1’) then if (enable=‘1’) then q<=data; q<=data; end if; else end process latch; q<=‘0’; end if; end process; -- q<=enable and data; enable data q
50
* na liście czułości procesu należy umieścić wejście zegarowe oraz wejście danych(!)
* układ jest transparentny jeżeli warunek enable=‘1’ jest spełniony; w przeciwnym wypadku proces nie zawiera żadnych instrukcji -na wyjściu q pamiętana jest ostatnia wartość wejścia data przy aktywnym zegarze * proces z określonym sterownikiem dla warunku enable/=‘1’ będzie syntezowany jako bramka AND * w technologiach w których przerzutniki typu latch nie są dostępne, synteza prowadzi do ekwiwalentu złożonego z bramek objętych sprzężeniem zwrotnym * zatrzaski mogą być również generowane poza procesem w części współbieżnej b1: block (enable=‘1’) warunek dozorujący bloku begin q<= GUARDED data; --sygnał dozorowany end block;
51
zatrzask (latch) z resetem asynchronicznym i synchronicznym
process(enable,data,rst) process(enable,data,rst) begin begin if (rst=‘1’) then if (enable=‘1’) then q1<=‘0’; if (rst=‘1’) then elsif (enable=‘1’) then q2<=‘0’; q1<=data; else end if; q2<=data; end process; end if; end if; end process; enable rst data q q1 q2
52
Przerzutniki aktywne zboczem (edge-sensitive flip-flop)
* proces sterowany zegarem (clocked process): zawiera instrukcję if uzależnioną od narastającego lub opadającego zbocza zegara, albo instrukcję oczekiwania na zmianę stanu sygnału wait until * w wyniku syntezy powstają przerzutniki aktywne zboczem * atrybuty ‘event oraz not ...’stable często są używane do wykrywania zbocza zegara, przy czym sygnał zegara musi być jednobitowy (typu bit lub std_logic) process begin wait until (clk’event and clk=‘1’ ) q<=data; end process; * proces w którym zastosowano instrukcję wait nie może posiadać listy czułości * instrukcja wait musi być pierwszą instrukcją procesu * proces startuje wyłącznie przy zmianach sygnału clk, w związku z tym warunek można skrócić do postaci: wait until clk=‘1’ wait until clk=‘0’ --opadające zbocze
53
process(clk) begin if (clk’event and clk=‘1’) then if (clk’event and clk=‘0’) then q<=data; if (not clk’stable and clk=‘1’) then end if; end process; * po warunku testującym zbocze zegara nie może wystąpić żadna gałąź else lub elsif * dla większości kompilatorów wykrywanie zbocza zegarowego musi być jedynym testowanym w danym wyrażeniu warunkiem -niedopuszczalne jest łączenie z testowaniem innego sygnału * jeżeli wykrywanie zbocza zegara następuje w wyrażeniu if... , to sygnał zegarowy musi(!!!) być umieszczony na liście wrażliwościowej procesu * proces może opisywać układ reagujący na zbocze tylko jednego sygnału (brak fizycznych elementów sterowanych zboczami wielu sygnałów) * możliwy jest opis w części współbieżnej kodu b2:block (clk’event and clk=‘1’) --warunek dozorujący q<= GUARDED data; end block;
54
przerzutniki z synchronicznym lub asynchronicznym zerowaniem/ustawianiem/ładowaniem
process(clk) process(clk,clear) begin begin if (clk’event and clk=‘1’) then if (clear=‘1’) then if (clear=‘1’) then q2<=‘0’ q1<=‘0’; elsif (clk’event and clk=‘1’) then else q2<=data; q1<=data; end if; end if; end process; end if; end process;
55
* w przypadku równoczesnej realizacji funkcji synchronicznej i asynchronicznej na liście wrażliwościowej należy umieścić wszystkie sygnały testowane i używane w procesie, przed warunkiem wykrywającym zbocze zegara * rozwiązanie alternatywne: b3:block (clk’event and clk=‘1’) begin q<= GUARDED ‘0’ when reset=‘1’ else data; --reset synchroniczny end block; * przerzutnik aktywny narastającym zboczem zegara, asynchroniczne zerowanie (wyższy priorytet) i ustawianie process(clk,reset,preset) begin if (reset=‘1’) then q<=‘0’; elsif (preset=‘1’) then q<=‘1’; elsif (clk’event and clk=‘1’) then q<=data; end if; end process; * przerzutnik aktywny opadającym zboczem zegara, asynchroniczne ustawianie (aktywne stanem niskim) process(clk,preset) begin if (preset=‘0’) then q<=‘1’ elsif (clk’event and clk=‘0’) then q<=data; end if; end process;
56
process(clk,load,data_lo)
begin if (load=‘1’) then --asynchroniczne ładowanie nowej zawartości data_lo q<=data_lo; elsif (clk’event and clk=‘1’) then --testowanie narastającego zbocza clk q<=data; end if; end process; process(clk,reset) if (reset=‘0’) then asynchroniczne zerowanie q<=‘0’; elsif (clk’event and clk=‘1’) then if (load=‘1’) then multiplekser przełączający wejścia data_lo i data else
57
* nie wszystkie kombinacje funkcji synchronicznych i asynchronicznych są syntezowalne w dowolnej technologii ALTERA: możliwy jest równocześnie asynchroniczny reset i preset przy czym reset ma priorytet, lub można wykorzystać asynchroniczne ładowanie wartości sygnału zewnętrznego XILINX: w układach FPGA przerzutniki mogą mieć tylko asynchroniczny reset lub preset * nie ma ograniczeń technologicznych co do części synchronicznej, złożony opis zostanie przekształcony w logikę kombinacyjną przed wejściem danych przerzutnika * wykorzystując pakiet std_logic_1164 można wykrywać zbocza przy pomocy funkcji if rising_edge(clk) then lub if falling_edge(clk) then ..... * wykorzystanie wejścia clock enable (wybrane technologie) oraz bramkowanie zegara (gated clock -uwaga, niebezpieczeństwo powstania szpilek na linii zegara) process(clk) process(clk,gate) begin begin if (clk’event and clk=‘1’) then if (gate=‘1’) then if (clk_enable=‘1’) then if (clk’event and clk=‘1’) then q<=data; q<=data; end if; end if; end if; end if; end process; end process;
58
Alternatywne opisy przerzutników
-w kodzie współbieżnym (przypisanie warunkowe) * przerzutnik typu latch -metoda opisu zalecana przez syntezer Synplify firmy Synplicity q <= data when (clk=‘1’) else q; * przerzutnik reagujący na zbocze (system projektowy Synario) q <= data when (clk’event and clk=‘1’) -w procesie wait until ((clk’event and clk=‘1’) or (reset=‘1’)) if (reset=‘1’) then q<=‘0’; else q<=data; end if; *konstrukcja if..then..elsif.. zapewnia większe możliwości opisu niż wyrażenie wait until *należy unikać mało czytelnych, nietypowych konstrukcji języka, generowany w ten sposób kod może okazać się niesyntezowalny przy pomocy innych narzędzi
59
przerzutnik z wyjściem trójstanowym
process(THREESTATE, CLK) begin if (THREESTATE=‘0’) then OUTPUT <= ‘Z’; elsif (CLK’event and CLK=‘1’) then if (CONDITION=‘1’) then OUTPUT <= INPUT; end if; end process; * opis nieprawidłowy: generowane są dwa przerzutniki
60
architecture EXAMPLE of reg_three is
signal TEMP: std_logic; begin process(CLK) if (CLK’event and CLK=‘1’) then if (CONDITION=‘1’) then TEMP<=INPUT; end if; end process; process (THREESTATE,TEMP) if (THREESTATE=‘0’) then OUTPUT<=‘Z’; else OUTPUT<=TEMP; end EXAMPLE;
61
wersja z nieprawidłowym opisem
62
procesy synchroniczne
* rozszerzenie zasad obowiązujących dla przerzutników na szerszą klasę układów * przykład: zatrzask magistrali z asynchronicznym zerowaniem/ładowaniem process(clk,reset) process(clk,load,data_lo) begin begin if reset=‘1’ then if load=‘1’ then data_out(7 downto 0)<=“ ”; data_out(0 to 7)<=data_lo(0 to 7); elsif (clk’event and clk=‘1’) then elsif (clk’event and clk=‘1’) then data_out(7 downto 0)<=data_in(7 downto 0); data_out(0 to 7)<=data_in(0 to 7); end if; end if; end process; end process; * nie należy opisywać w obrębie jednego procesu logiki posiadającej asynchroniczny reset/preset i nie posiadającej tej funkcji; może to prowadzić do błędnej syntezy * w procesie synchronicznym nie dopuszcza się przypisań poza instrukcją if, z wyjątkiem przypisania sygnałowi wartości zmiennej obliczonej wewnątrz instrukcji warunkowej if
63
* asynchroniczne zerowanie
ładowanie data_lo
64
liczniki synchroniczne
entity counter is port ( clk :in bit; clear, load, ena :in bit; --asynchr. zerowanie, synch. ładowanie, zezwol. na zliczanie up_ndown :in bit; --zliczanie w góre (1) lub w dół (0) data_in :in integer range 0 to 255; count :out integer range 0 to 255); end counter; architecture behavior of counter is begin process(clk, clear, up_ndown) variable cnt :integer range 0 to 255; variable dir :integer; if (up_ndown=‘1’) then dir:=1; else dir:=-1; end if; if (clear=‘1’) then cnt:=0; elsif (clk’event and clk=‘1’) then if (ena=‘1’) then if (load=‘1’) then cnt:=data_in; else cnt:=cnt+dir; end if; end if; count <= cnt; end process; end behavior;
65
* kierunek zliczania =>sumator wartości bieżącej rejestru z liczbą (+1) lub (-1), ena=‘1’, load=‘0’ => zwiększona lub zmniejszona wartość podana na wejścia D przerzutników * ena=‘0’ => przepisywana jest wartość bieżąca przerzutników (brak modyfikacji) * ena, load=‘1’ => na wejścia przerzutników podawana jest wartość data_in * asynchroniczne zerowanie - clear podane bezpośrednio do przerzutników
66
ograniczenie zakresu zliczania
entity counter is port( clk, preset :in std_logic; count :out std_logic_vector(7 downto 0) ); end counter; architecture behave of counter is signal count_int :std_logic_vector(7 downto 0); constant load_value :std_logic_vector(7 downto 0):=X”80”; constant high_value :integer:=220; begin process(clk,preset) if (preset=‘1’) then count_int<=load_value; elsif rising_edge(clk) then if (conv_integer(count_int)=high_value) then count_int<=X”00”; else count_int<=count_int+’1’; end if; end process; count<=count_int; end behave; * korzystanie z funkcji konwersji conv_integer oraz przeciążonego operatora dodawania wymaga użycia pakietu std_logic_unsigned * dodawanie wektorów: count_int + ” ”
67
dzielniki częstotliwości
dziel11bit:process(clk16M) begin if (clk16M’event and clk16M = '1') then counter<=unsigned(counter)- '1'; if (unsigned(counter)<=2 or unsigned(counter)=16#7FF#) then pfs<='1'; #...# -zapis w kodzie heksalnym else pfs<='0'; end if; if (unsigned(counter)<16#C# or unsigned(counter)>=16#7FE#) then syp<='1'; syp<='0'; end process; clk4M<=counter(1); clk2M<=counter(2); * clk16M-zegar wzorcowy-port wejściowy, clk4M, clk2M, pfs, syp -porty wyjściowe counter -sygnał wewnętrzny; wszystkie sygnały typu std_logic
68
początek ramki * w procesie, po warunku testującym zbocze zegara, następuje opis logiki kombinacyjnej sterującej wejścia D przerzutników TUTAJ: opis ten dotyczy następnego stanu przerzutników counter, pfs, syp (po reakcji układu na wykryte zbocze zegara), i uzależniony jest od bieżącego stanu przerzutników counter (przed reakcją na zbocze) * należy pamiętać, że sposób opisu układu zależy od wyboru “nośnika informacji”: sygnał czy zmienna * bity licznika są równocześnie wyjściami podzielnika częstotliwości
69
rejestry przesuwne * syntezowane jako łańcuch przerzutników
process(clk,reset) begin if (reset=‘1’) then a<=‘0’; b<=‘0’; c<=‘0’; shift_out<=‘0’; elsif (clk’event and clk=‘1’) then a<=shift_in; b<=a; c<=b; shift_out<=c; end if; end process;
70
* operacja na typie signal data_in, shiftreg :std_logic_vector(7 downto 0);
process(clk) begin if (clk’event and clk=‘1’) then if (load=‘1’) then shiftreg<=data_in; --wpis równoległy else shiftreg(0)<=shift_in; shiftreg(7 downto 1)<=shiftreg(6 downto 0); end if; --shiftreg(7)=shift_out jest wyjściem end if; end process;
71
entity shiftregister is
generic (size: integer:=8); port( shift_in :in std_logic; data_out :out std_logic_vector(size-1 downto 0); clear, enable :in std_logic; clock :in std_logic); end shiftregister; architecture a1 of shiftregister is signal reg :std_logic_vector(size-1 downto 0); begin process brak listy czułości!!! wait until clock=‘1’; if (clear=‘1’) then --zerowanie synchroniczne!!! reg<=conv_std_logic_vector(0,size); --use std_logic_arith elsif (enable=‘1’) then reg(0)<=shift_in; reg(size-1 downto 1)<=reg(size-2 downto 0); end if; --reg(size-1 downto 0)<=reg(size-2 downto 0) & shift_in; end process; data_out<=reg; end a1;
72
process --brak listy czułości!!!
begin wait until clock=‘1’; if (clear=‘1’) then L1: for i in size-1 downto 0 loop reg(i)<=‘0’; end loop L1; elsif (enable=‘1’) then reg(0)<=shift_in; L2: for j in size-1 downto 1 loop reg(j)<=reg(j-1); end loop L2; end if; end process;
73
entity shifter is port( data :inout std_logic_vector(7 downto 0); read :in std_logic; sl,sr :in std_logic; clock,reset :in std_logic; mode:in std_logic_vector(1 downto 0)); end shifter; architecture a1 of shifter is signal qout:std_logic_vector(7 downto 0); begin process(clock) if (clock’event and clock=‘1’) then if (reset=‘1’) then qout<=“ ”; else case mode is when “01”=>qout<=sr&qout(7 downto 1); when “10”=>qout<=qout(6 downto 0)&sl; when “11”=>qout<=data; when others=>null; end case; end if; end process; data<=qout when read=‘1’ else “ZZZZZZZZ”; end a1; * mode=01 -przesunięcie w prawo * mode=10 -przesunięcie w lewo * mode=11 -równoległy wpis nowych danych z magistrali * mode=00 -podtrzymanie poprzednich wartości rejestru przesuwnego * read=1 -zawartość rejestru przesuwnego wystawiana na magistralę
74
automaty/maszyny stanów (FSM -Finite State Machine)
* złożony układ cyfrowy, który na podstawie własnego stanu bieżącego oraz stanu wejść przechodzi do stanu następnego; przejście to jest reakcją na zbocze zegara * automat jawny => liczba stanów jest znana, każdy stan jest nazwany, rejestry przechowują zakodowaną reprezentację stanu * opis automatów zawiera sekcję kombinacyjną i sekcję synchroniczną * automat Moore’a: wyjścia automatu są jedynie funkcją stanu, logika kombinacyjna służy do generowania sygnałów wyjściowych na podstawie stanu automatu, oraz do określenia wejść przerzutników na podstawie stanu automatu i wejść do układu * automat Mealy’ego: zarówno następny stan jak i wektor wyjść są funkcjami bieżącego stanu automatu oraz wektora wejść; automat Mealy’ego synchroniczny wyposażony jest w przerzutniki wyjściowe, automat asynchroniczny natychmiast reaguje na zmianę sygnałów wejściowych * kodowanie stanów: -użycie typu wyliczeniowego type state is (st0, st1, st2, st3, st4); signal present_state, next_state: state; -użycie stałych subtype state is std_logic_vector(3 downto 0); constant st0: state:=“0010”; constant st1: state:=“1000”;
75
entity MOORE is port (X, clock :in bit; Z :out bit); end MOORE; architecture b1 of MOORE is type STATE_TYPE is (S0,S1,S2,S3); signal CURRENT, NEXTS: STATE_TYPE; begin SYNCH:process(clock) if (clock’event and clock=‘1’) then CURRENT<=NEXTS; end if; end process SYNCH; Current Next Output state state (Z) X=0 X=1 S S S S S S S S S S S S
76
COMB:process(CURRENT,X)
begin case CURRENT is when S0=> Z<=‘0’; if (X=‘0’) then NEXTS<=S0; else NEXTS<=S2; end if; when S1=> Z<=‘1’; when S2=> Z<=‘1’; if (X=‘0’) then NEXTS<=S2; else NEXTS<=S3; when S3=> Z<=‘0’; if (X=‘0’) then NEXTS<=S3; else NEXTS<=S1; end case; end process COMB; end b1; * przypisania do sygnału Z utworzą po syntezie logikę kombinacyjną zależną od wyjść przerzutników przechowujących aktualny stan automatu * przypisania do sygnału NEXTS opisują logikę kombinacyjną przygotowującą wejścia dla przerzutników przechowujących stan: następny stan (NEXTS) jest funkcją aktualnego stanu (CURRENT) i wejścia * proces SYNCH opisuje zespół przerzutników o wektorze wejściowym NEXTS i wyjściowym CURRENT * liczba przerzutników jest zależna od kodowania stanów; o sposobie kodowania decyduje narzędzie syntezy (sekwencyjne, gray, one-hot, one-cold)
77
architecture b2 of MOORE is
type STATE_TYPE is (S0,S1,S2,S3); signal CURRENT: STATE_TYPE; begin SYNCH:process(clock) if (clock’event and clock=‘1’) then case CURRENT is when S0=> if (X=‘1’) then CURRENT<=S2; end if; when S1=> if (X=‘0’) then CURRENT<=S0; else CURRENT<=S2; when S2=> if (X=‘1’) then CURRENT<=S3; when S3=> if (X=‘1’) then CURRENT<=S1; end case; end process SYNCH; COMB:process(CURRENT) begin case CURRENT is when S0=> Z<=‘0’; when S1=> Z<=‘1’; when S2=> Z<=‘1’; when S3=> Z<=‘0’; end case; end process COMB; end b2; * proces SYNCH opisuje tylko przejścia między stanami, jego rezultatem jest zespół przerzutników wraz z logiką sterującą ich wejściami * proces COMB opisuje logikę kombinacyjną sterującą wyjściem automatu
78
* wyjście Z jest synchronizowane zegarem, zrealizowane za pomocą logiki kombinacyjnej i przerzutnika
* cel zmiany: likwidacja stanów nieustalonych (w poprzednich rozwiązaniach możliwość powstania szpilek przy zmianie stanu automatu), uniezależnienie od sposobu kodowania stanów architecture b3 of MOORE is type STATE_TYPE is (S0,S1,S2,S3); signal CURRENT: STATE_TYPE; begin SYNCH:process(clock) if (clock’event and clock=‘1’) then case CURRENT is when S0=> if (X=‘1’) then CURRENT<=S2; Z<=‘1’; end if; when S1=> if (X=‘0’) then CURRENT<=S0; Z<=‘0’; else CURRENT<=S2; Z<=‘1’; when S2=> if (X=‘1’) then CURRENT<=S3; Z<=‘0’; when S3=> if (X=‘1’) then CURRENT<=S1; Z<=‘1’; end case; end process SYNCH; end b3;
79
entity MEALY is port (X, clock, reset :in bit; Z :out bit); end MEALY; architecture m1 of MEALY is type STATE is array(3 downto 0) of bit; signal CURRENT, NEXTS: STATE; -- one hot encoding constant S0: STATE:=“0001”; constant S1: STATE:=“0010”; constant S2: STATE:=“0100”; constant S3: STATE:=“1000”; signal Zint:bit; begin --Z<=Zint; --autom. Mealy’ego asynchron. SYNCH:process(clock,reset) if (reset=‘1’) then CURRENT<=S0;Z<=‘0’; elsif (clock’event and clock=‘1’) then CURRENT<=NEXTS; Z<=Zint; --autom. Mealy’ego synchr. end if; end process SYNCH; Current Next Output state state (Z) X=0 X=1 X=0 X=1 S S S S S S S S S S S S
80
COMB:process(CURRENT,X)
begin case CURRENT is when S0=> if (X=‘0’) then NEXTS<=S0; Zint<=‘0’; else NEXTS<=S2; Zint<=‘1’; end if; when S1=> if (X=‘0’) then NEXTS<=S0; Zint<=‘0’; else NEXTS<=S2; Zint<=‘0’; when S2=> if (X=‘0’) then NEXTS<=S2; Zint<=‘1’; else NEXTS<=S3; Zint<=‘0’; when others=> if (X=‘0’) then NEXTS<=S3; Zint<=‘0’; --others obejmuje S3 else NEXTS<=S1; Zint<=‘1’; --i stany nielegalne end case; end process COMB; end m1; * zalecanym sposobem opisu automatów jest rozdzielenie części kombinacyjnej i rejestrowej
81
MAGISTRALE entity mag3st is port( sel :in std_logic_vector(1 downto 0); nrd :in std_logic; data_out :out std_logic_vector(7 downto 0); data0,data1 :in std_logic_vector(3 downto 0); data2 :in std_logic_vector(6 downto 0); data3 :in std_logic ); end mag3st; architecture a1 of mag3st is begin data_out <= data0 & "0000" when (nrd='0' and sel="00") else "ZZZZZZZZ"; data_out <= "0000" & data1 when (nrd='0' and sel="01") data_out <= '0' & data2 when (nrd='0' and sel="10") data_out <= " " & data3 when (nrd='0' and sel="11") end a1;
82
* w architekturze opisano zestaw 4-ch bram trójstanowych
* linie trójstanowe są jedynym przypadkiem kodu syntezowalnego, kiedy sygnał może mieć kilka sterowników
83
* w układach PLD realizacja przy pomocy multipleksera i jednej bramy trójstanowej
* typowy opis z multiplekserem: architecture a2 of mag3st is begin data_out <= (data0 & "0000”) when (nrd='0' and sel="00") else ("0000" & data1) when (nrd='0' and sel="01") else ('0' & data2) when (nrd='0' and sel="10") else (" " & data3) when (nrd='0' and sel="11") else "ZZZZZZZZ"; end a2; * Altera Max+PlusII -preferowany jest opis, w którym najwyższy priorytet ma stan wysokiej impedancji architecture a3 of mag3st is data_out <= “ZZZZZZZZ” when nrd=‘1’ else (data0 & "0000”) when sel="00" else ("0000" & data1) when sel="01" else ('0' & data2) when sel="10" else (" " & data3); end a3;
85
efektywne używanie przerzutników
entity and_or_xor is port( clk,reset :in std_logic; and_bits,or_bits,xor_bits :out std_logic); end and_or_xor; architecture rtl1 of and_or_xor is begin process variable cnt: std_logic_vector(2 downto 0); wait until clk=‘1’; --wszystkie linie po tym wyrażeniu syntezowane są jako if (reset=‘1’) then --przerzutniki !!! cnt := “000”; else cnt := cnt+”001”; end if; and_bits<=cnt(2) and cnt(1) and cnt(0); --uwaga!!! cnt jest zmienną, do operacji or_bits<=cnt(2) or cnt(1) or cnt(0); --brane są nowe wartości bitów xor_bits<=cnt(2) xor cnt(1) xor cnt(0); --wyznaczone w danym przebiegu procesu end process; end rtl1;
86
architecture rtl2 of and_or_xor is
signal cnt:std_logic_vector(2 downto 0); begin REG:process wait until clk=‘1’; if (reset=‘1’) then cnt<=“000”; else cnt<=cnt+”001”; end if; end process; COMB:process(cnt) and_bits<=cnt(2) and cnt(1) and cnt(0); or_bits<=cnt(2) or cnt(1) or cnt(0); xor_bits<=cnt(2) xor cnt(1) xor cnt(0); end rtl2; * niezależne procesy: zegarowany i czysto kombinacyjny * możliwość powstawania “szpilek” na wyjściach, na zboczach sygnału zegarowego clk * poniższy przykład realizuje inną funkcję: architecture rtl3 of and_or_xor is signal cnt: std_logic_vector(2 downto 0); begin process wait until clk=‘1’; if (reset=‘1’) then cnt <= “000”; else cnt <= cnt+”001”; end if; and_bits<=cnt(2) and cnt(1) and cnt(0); or_bits<=cnt(2) or cnt(1) or cnt(0); xor_bits<=cnt(2) xor cnt(1) xor cnt(0); end process; --do operacji logicznych brana end rtl3; poprzednia wartość licznika cnt
87
rtl1
88
rtl2 rtl3 * w architekturze rtl3 wartości wyjść opóźnione są o jeden takt zegara w stosunku do stanu licznika, ze względu na zastosowanie sygnału cnt w miejsce zmiennej * CPLD/FPGA zawierają przerzutnik w każdej komórce; bezpieczniej jest projektować układy w pełni synchroniczne
89
JAKICH OPERACJI NIE NALEŻY WYKONYWAĆ ?
X<= A nand (not(not(not A))); * syntezer nie wygeneruje odwracającej linii opóźniającej i bramki nand, ALE potraktuje zapis jako opis układu X<=A nand (not A); tzn. X<=‘1’; entity COMP is port( a,b : in INTEGER range 0 to 7; z : out INTEGER range 0 to 7 ); end COMP; architecture a1 of COMP is begin process(a,b) if (a=b) then z<=a; end if; end process; end a1; * opis funkcjonalny jest prawidłowy, ALE układ nie będzie działać * powód: opóźnienie na bloku komparatora, generacja przez układ kombinacyjny szpilek “niszczących” prawidłową zawartość zatrzasku
90
TYPY OBIEKTÓW W VHDL -PODSUMOWANIE
* typy skalarne -typ całkowity -definiowany do wykonywania działań matematycznych, w standardzie zapisywany na 32 bitach: od -231 do +(231-1) przykłady literałów całkowitych o podstawie 10: 0, 100, 1e6, , 1_945_690 binarnych: 2#1111# , 2#1110_1111#, 2#1111#e2 (60) ósemkowych: 8# # heksalnych: 16#F0# , 16#1#E2 (256) prawidłowe są przypisania do zmiennych lub sygnałów: x:=1; y<=-7; d:=1e4 przypisanie nieprawidłowe: z<=10.0; -typ rzeczywisty - zakres zdefiniowany przez standard: -1.0e38 do 1.0e38 przykłady literałów rzeczywistych: 100.0, , 2.234_567_78, 2.71e-9 binarnych: 2#1.101#e3 (13.0), 2#11.00_01_11# heksalnych: 16#F.F#e1 (255.0) prawidłowe przypisania wartości: x:=2.34; y<= ; z<=1.9e21; przypisania nieprawidłowe: x:=2; y<=-1;
91
-typ wyliczeniowy: definiujemy go poprzez wymienienie wszystkich elementów, nazwa elementów jest dowolna type meal is (breakfast, dinner, lunch, midnight_snack); W systemie każdy z elementów typu wyliczeniowego otrzymuje wewnętrzny identyfikator w postaci liczby całkowitej począwszy od 0 dla skrajnego lewego elementu. Wyjątek: kodowanie stanów one hot lub one cold. -typ fizyczny -niesyntezowalny predefiniowanym w standardzie typem fizycznym jest TIME, jednostką bazową jest fs (można używać jednostek pochodnych ps, ns, us, ms, s) przykład użycia: t:=5 ns; przykład nowej definicji type weight is range 0 to 1e15 units ug; mg=1000 ug; g=1000 mg; kg=1000 g; t=1000 kg; end units;
92
* typy złożone -typy tablicowe: grupują obiekty tego samego typu (dowolnego) w jeden obiekt, w ogólności tablice mogą być wielowymiarowe wymiar tablicy: typu całkowitego lub wyliczeniowego, indeks rosnący (to) bądź malejący (downto) typ tablicowy ograniczony: dokładnie podany jest zakres indeksów typ nieograniczony: zakres nie jest podany, można definiować wiele podtypów na bazie jednej definicji typu type tab1 is array (0 to 7) of integer; type tab2dim is array (0 to 7, 15 downto 0) of std_logic; type std_logic_vector is array (NATURAL range<>) of std_logic; -użyty zakres musi być podany w oddzielnej definicji dostęp do tablicy poprzez indeks elementu: y<=x(6); możliwe przypisanie pełnej tablicy przy pomocy agregatu syntezowalne są wyłącznie tablice jednowymiarowe
93
-rekordy: grupują elementy różnych typów, mogą zawierać wewnątrz tablice i inne rekordy; do elementu rekordu odwołujemy się poprzez nazwę pola type rec_type is record val_int :integer; val_log :std_logic; end record; signal x: rec_type; x.val_int<=1; x.val_log<=‘0’; możliwe przypisanie przy pomocy agregatu: x<=(1,’0’); x<=(val_log=>’0’, val_int=> 1); *typ wskaźnikowy -niesyntezowalny!!!, przydatny przy modelowaniu kolejek, ograniczony wyłącznie do zmiennych type address is access memory;
94
* typ plikowy typ niesyntezowalny, przydatny przy symulacji (wypełnianie zawartości tablic, wektory testowe) definicja typu: type type_name is file of type; np: type TEST_VEC_FILE is file of STD_LOGIC_VECTOR(15 downto 0); automatycznie zdefiniowane są procedury: FILE_OPEN, FILE_CLOSE, READ, WRITE, ENDFILE elementy pliku nie mogą być typu wskaźnikowego, w przypadku tablic- tylko jednowymiarowymi PODTYPY * użytkownik definiuje ograniczenie typu bazowego subtype INTXX is integer range 0 to 1023; (liczba reprezentowana na 10-ciu bitach) subtype SLV8 is std_logic_vector(7 downto 0); ALIAS *nadanie nowej nazwy innemu obiektowi lub części innego obiektu-tutaj 8 najstarszych variable instr:bit_vector(31 downto 0); bitów alias op_code:bit_vector(7 downto 0) is instr(31 downto 24);
95
TYPY PREDEFINIOWANE -w pakietach STANDARD oraz TEXTIO
* BOOLEAN -wyliczeniowy, dwie wartości false i true (false<true) * BIT -wyliczeniowy, dwie wartości ‘0’ i ‘1’ * CHARACTER -wyliczeniowy, zawiera zbiór znaków ASCII, znaki w pojedynczym cudzysłowiu (‘a’, ‘Y’, ‘x’) * INTEGER -liczby całkowite * NATURAL -zbiór liczb nieujemnych, podtyp INTEGER * POSITIVE -zbiór liczb dodatnich, podtyp INTEGER * BIT_VECTOR -tablica wartości typu BIT łańcuchy bitów: “1110”, B”1111_1110”, X”FC0”, O”7677” * STRING -tablica wartości typu CHARACTER łańcuchy znaków: “ala ma kota”, “symulacja” * REAL -zbiór liczb rzeczywistych * TIME -typ fizyczny reprezentujący czas symulacji TYPY PAKIETU STD_LOGIC_1164 * STD_ULOGIC, STD_LOGIC (z dodatkową funkcją arbitrażową) type STD_ULOGIC is (‘U’, ‘X’, ‘0’, ‘1’, ‘Z’, ‘W’, ‘L’, ‘H’, ‘-’); * STD_ULOGIC_VECTOR, STD_LOGIC_VECTOR -typy tablicowe nieogr.
96
ATRYBUTY * atrybut jest dodatkową informacją związaną z obiektem * przykłady predefiniowanych atrybutów dla sygnałów: clk’event, clk’stable * przykłady atrybutów predefiniowanych dla typów tablicowych oraz sygnałów i zmiennych typu tablicowego: type ADDRESS_TYPE is std_logic_vector(31 downto 0); signal address : ADDRESS_TYPE; address’left ->31 -zwraca wartość lewego indeksu address’right ->0 -zwraca wartość prawego indeksu address’low ->0 -zwraca wartość najmniejszego indeksu address’high ->31 -zwraca wartość największego indeksu address’range ->zakres 0 do 31 -zwraca zakres zmian indeksu ADDRESS_TYPE’ascending - >false -zwraca true lub false w zależności od kierunku zmian indeksów * użytkownik może definiować własne atrybuty, które są stałymi
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.