1 / 96

JĘZYK VHDL

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

fareeda
Download Presentation

JĘZYK VHDL

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 IEEE1076 -1987, IEEE1164-1993r

  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 entitymodel_nameis port ( list of inputs and outputs ); endmodel_name; architecturearch_nameofmodel_nameis 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<=“11110000” (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 <=value1when condition1 elsevalue2 whencondition2 .... elsevalueN when conditionN elsedefault_value; warunki są wyrażeniami przyjmującymi wartości true/false * wynik syntezy:

  11. Przypisanie selektywne (selected signal assignment) * Ogólna postać: withconditionselect signal_name<= value1 whencond_value1, value2whencond_value2, .... valueNwhencond_valueN, valueXwhen 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) 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: czas a b c out1 out2 out3 process(a,b,c,out1,out2) t1 0 1 1 0 1 1 begin t2 1 1 1 0->1 1 1 out1<=a and b; t2+d 1 1 1 1 1->0 1->0 out2<=out1 xor c; t2+2d 1 1 1 1 0 0->1 out3<=out1 xor out2; t2+3d 1 1 1 1 0 1 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. 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 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) czas a b c out1 out2 out3 variable out1,out2:std_logic; t1 0 1 1 0 1 1 begin t2 1 1 1 1 0 1->0 out1:=a and b; t2+d 1 1 1 1 0 0 out2:=out1 xor c; t3 1 0 0 0 0 0 out3<=(not out1) and out2; t4 1 0 1 0 1 0->1 end process; t4+d 1 0 1 0 1 1 * 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: 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; 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. 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)<=‘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;

  30. * wersja prawidłowa * wersja bez wartości domyślnej; generowane są przerzutniki typu latch

  31. * 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<=“11111111”; --wartość domyślna if (ena=‘1’) then y(conv_integer(sel))<=‘0’; end if; end process;

  32. * 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’; end loop;

  33. 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;

  34. 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;

  35. HALFADDER RTL -proces “Technology View”-Flex8000 RTL -równania logiczne

  36. 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;

  37. 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

  38. 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)

  39. 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; end generate; cout<=c(size); end a1;

  40. * 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)

  41. 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;

  42. * 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;

  43. 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;

  44. * 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

  45. 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

  46. * 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;

More Related