Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

JĘZYK VHDL Geneza: komputerowa symulacja układu cyfrowego, Departament Obrony USA opis skomplikowanego systemu w postaci schematu jest nieczytelny, szybkie.

Podobne prezentacje


Prezentacja na temat: "JĘZYK VHDL Geneza: komputerowa symulacja układu cyfrowego, Departament Obrony USA opis skomplikowanego systemu w postaci schematu jest nieczytelny, szybkie."— Zapis prezentacji:

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 ( signals:instd_logic; signalx0,x1:instd_logic_vector(7 downto 0); signaly:outstd_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), - (dont 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 (drivery) 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: nazwatrybtyp 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: signala:outstd_logic_vector(7 downto 0); signalb: instd_logic_vector(3 downto 0); możliwe jest przypisanie a <= 100 & b & 1; * ogólna postać warunkowego przypisania sygnału: signal_name <=value1when 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:instd_logic; x0,x1:instd_logic_vector(7 downto 0); y:outstd_logic_vector(7 downto 0) ); end mux2to1; architecture a2 of mux2to1 is signal temp:std_logic_vector(7 downto 0); begin temp 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 s);--najprostszy zapis (aggregate) temp s); temp 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) 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) begin 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: czasa bc out1 out2 out3 process(a,b,c,out1,out2) t begin t >1 1 1 out1 0 1->0 out2 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 begin 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 * 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 x(6) x(4) x(5) x(7) x(2) x(1) x(3) enc(2) enc(0) enc(1)

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 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 begin 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) czasa bc out1 out2out3 variable out1,out2:std_logic; t begin t >0 out1:=a and b; t2+d out2:=out1 xor c; t out3 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; BEGIN 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: prostaz określonym schematem iteracji L1:loopL2: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: nextnp: next L1 when I=J; next when (B<10); exitnp: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; begin 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;

29

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) begin y<=1111_1111;--wartość domyślna if (ena=1) then case sel is when 000=> y(0) y(1)<=0; when 010=> y(2) y(3)<=0; when 100=> y(4) y(5)<=0; when 110=> y(6) 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) begin 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 yrange 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 yrange loop y(j)<=1; end loop;

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 begin 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 if; 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 signalc: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)

40

41

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 signalc: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; begin 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; begin 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; c:=(a(i) and b(i)) or (a(i) and c) or (b(i) and c); end loop L; cout<=c;

45 * wykorzystanie sumowania arytmetycznego zdefiniowanego w pakiecie std_logic_unsigned: architecture a3 of adder_n is signalc: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;

46

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 isbegin 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: buforgeneric 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 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 synchronicznymprocess(enable,data,rst)begin if (rst=1) thenif (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 (clkevent 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 (clkevent and clk=1) then if (clkevent and clk=0) then q<=data; if (not clkstable 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 (clkevent and clk=1)--warunek dozorujący begin q<= GUARDED data; end block;

54 przerzutniki z synchronicznym lub asynchronicznym zerowaniem/ustawianiem/ładowaniem process(clk)process(clk,clear)begin if (clkevent and clk=1) thenif (clear=1) then if (clear=1) then q2<=0 q1<=0; elsif (clkevent 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 (clkevent and clk=1) begin q<= GUARDED 0 when reset=1 else data; --reset synchroniczny end block; * przerzutnik aktywny opadającym zboczem zegara, asynchroniczne ustawianie (aktywne stanem niskim) process(clk,preset) begin if (preset=0) then q<=1 elsif (clkevent and clk=0) then q<=data; end if; end process; * 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 (clkevent and clk=1) 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 (clkevent and clk=1) then --testowanie narastającego zbocza clk q<=data; end if; end process; process(clk,reset) begin if (reset=0) then --asynchroniczne zerowanie q<=0; elsif (clkevent and clk=1) then if (load=1) then --multiplekser przełączający wejścia data_lo i data q<=data_lo; else q<=data; end if; end process;

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 if (clkevent and clk=1) thenif (gate=1) then if (clk_enable=1) then if (clkevent and clk=1) then q<=data; q<=data; end if; end if; 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 (clkevent and clk=1) else q; -w procesie wait until ((clkevent 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 (CLKevent 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) begin if (CLKevent and CLK=1) then if (CONDITION=1) then TEMP<=INPUT; end if; end process; process (THREESTATE,TEMP) begin if (THREESTATE=0) then OUTPUT<=Z; else OUTPUT<=TEMP; end if; end process; 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 if reset=1 thenif load=1 then data_out(7 downto 0)<= ; data_out(0 to 7)<=data_lo(0 to 7); elsif (clkevent and clk=1) then elsif (clkevent 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; * 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 * asynchroniczne ł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; begin if (up_ndown=1) then dir:=1; else dir:=-1; end if; if (clear=1) then cnt:=0; elsif (clkevent and clk=1) then if (ena=1) then if (load=1) then cnt:=data_in; else cnt:=cnt+dir; 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):=X80; constant high_value:integer:=220; begin process(clk,preset) begin if (preset=1) then count_int<=load_value; elsif rising_edge(clk) then if (conv_integer(count_int)=high_value) then count_int<=X00; 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 (clk16Mevent and clk16M = '1') then counter<=unsigned(counter)- '1'; if (unsigned(counter)<=2 or unsigned(counter)=16#7FF#) then pfs<='1';-- 16#...# -zapis w kodzie heksalnym else pfs<='0'; end if; if (unsigned(counter) =16#7FE#) then syp<='1'; else syp<='0'; end if; 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 (clkevent 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 (clkevent 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 signalreg:std_logic_vector(size-1 downto 0); begin process--brak listy czułości!!! begin 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) begin if (clockevent 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 Moorea: 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 Mealyego: zarówno następny stan jak i wektor wyjść są funkcjami bieżącego stanu automatu oraz wektora wejść; automat Mealyego synchroniczny wyposażony jest w przerzutniki wyjściowe, automat asynchroniczny natychmiast reaguje na zmianę sygnałów wejściowych * kodowanie stanów: -użycie typu wyliczeniowegotype 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 Current Next Output state state (Z) X=0 X=1 S0 S0 S2 0 S1 S0 S2 1 S2 S2 S3 1 S3 S3 S1 0 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) begin if (clockevent and clock=1) then CURRENT<=NEXTS; end if; end process SYNCH;

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; if (X=0) then NEXTS<=S0; else NEXTS<=S2; end if; when S2=> Z<=1; if (X=0) then NEXTS<=S2; else NEXTS<=S3; end if; when S3=> Z<=0; if (X=0) then NEXTS<=S3; else NEXTS<=S1; end if; 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) begin if (clockevent 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; end if; when S2=> if (X=1) then CURRENT<=S3; end if; when S3=> if (X=1) then CURRENT<=S1; end if; end case; end if; 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 architecture b3 of MOORE is type STATE_TYPE is (S0,S1,S2,S3); signal CURRENT: STATE_TYPE; begin SYNCH:process(clock) begin if (clockevent 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; end if; when S2=> if (X=1) then CURRENT<=S3; Z<=0; end if; when S3=> if (X=1) then CURRENT<=S1; Z<=1; end if; end case; end if; end process SYNCH; end b3; * 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

79 Current Next Output state state (Z) X=0 X=1 X=0 X=1 S0 S0 S2 0 1 S1 S0 S2 0 0 S2 S2 S3 1 0 S3 S3 S1 0 1 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. Mealyego asynchron. SYNCH:process(clock,reset) begin if (reset=1) then CURRENT<=S0;Z<=0; elsif (clockevent and clock=1) then CURRENT<=NEXTS; Z<=Zint; --autom. Mealyego synchr. end if; end process SYNCH;

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; end if; when S2=> if (X=0) then NEXTS<=S2; Zint<=1; else NEXTS<=S3; Zint<=0; end if; when others=> if (X=0) then NEXTS<=S3; Zint<=0; --others obejmuje S3 else NEXTS<=S1; Zint<=1; --i stany nielegalne end if; 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") else "ZZZZZZZZ"; data_out <= '0' & data2 when (nrd='0' and sel="10") else "ZZZZZZZZ"; data_out <= " " & data3 when (nrd='0' and sel="11") else "ZZZZZZZZ"; 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 begin 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;

84

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); begin 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 begin wait until clk=1; if (reset=1) then cnt<=000; else cnt<=cnt+001; end if; end process; COMB:process(cnt) begin 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; 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 begin 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) begin 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 do +( ) 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 definicjitype 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 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

96 ATRYBUTY * atrybut jest dodatkową informacją związaną z obiektem * przykłady predefiniowanych atrybutów dla sygnałów: clkevent, clkstable * 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; addressleft->31-zwraca wartość lewego indeksu addressright->0-zwraca wartość prawego indeksu addresslow->0-zwraca wartość najmniejszego indeksu addresshigh->31-zwraca wartość największego indeksu addressrange->zakres 0 do 31-zwraca zakres zmian indeksu ADDRESS_TYPEascending - >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


Pobierz ppt "JĘZYK VHDL Geneza: komputerowa symulacja układu cyfrowego, Departament Obrony USA opis skomplikowanego systemu w postaci schematu jest nieczytelny, szybkie."

Podobne prezentacje


Reklamy Google