vhdl wyk

background image

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

background image

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)

background image

•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)

background image

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”

background image

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!!!)

background image

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;

background image

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)

background image

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

background image

* 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!!!

background image

* 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:

background image

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

background image

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;

background image

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

background image

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

background image

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

background image

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

background image

* 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

background image

* 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

background image

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;

background image

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

background image

* 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

background image

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;

background image

* 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

background image

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;

background image

* 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

background image

*

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

background image

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;

background image

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

background image

background image

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;

background image

* wersja prawidłowa

* wersja bez wartości domyślnej;
generowane są przerzutniki typu latch

background image

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

background image

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

background image

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;

background image

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;

background image

HALFADDER

RTL -proces

“Technology View”-Flex8000

RTL -równania logiczne

background image

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;

background image

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

background image

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)

background image

background image

background image

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;

background image

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

background image

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;

background image

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

background image

background image

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;

background image

* 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

background image

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

background image

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

background image

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

background image

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

background image

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

begin

q<= GUARDED data;

end block;

background image

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;

background image

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

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

background image

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)
begin
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
q<=data_lo;
else
q<=data;
end if;
end if;
end process;

background image

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

background image

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’)

else q;
-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

background image

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 if;
end process;

* opis nieprawidłowy: generowane są
dwa przerzutniki

background image

architecture EXAMPLE of reg_three is
signal TEMP: std_logic;
begin
process(CLK)
begin
if (CLK’event and CLK=‘1’) then
if (CONDITION=‘1’) then
TEMP<=INPUT;
end if;
end if;
end process;

process (THREESTATE,TEMP)
begin
if (THREESTATE=‘0’) then
OUTPUT<=‘Z’;
else
OUTPUT<=TEMP;
end if;
end process;
end EXAMPLE;

background image

wersja z nieprawidłowym opisem

background image

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)<=“00000000”;

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

background image

* asynchroniczne zerowanie

* asynchroniczne
ładowanie data_lo

background image

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 (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;
end if;
count <= cnt;
end process;
end behavior;

background image

* kierunek zliczania =>sumator wartości bieżącej rejestru z liczbą
00000001 (+1) lub 11111111 (-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

background image

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)
begin
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 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 + ”00000001”

background image

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';

-- 16#...# -zapis w kodzie heksalnym

else
pfs<='0';
end if;
if (unsigned(counter)<16#C# or unsigned(counter)>=16#7FE#) then
syp<='1';
else
syp<='0';
end if;
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

background image

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

background image

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;

background image

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

background image

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!!!

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;

background image

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;

background image

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 (clock’event and clock=‘1’) then
if (reset=‘1’) then
qout<=“00000000”;
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 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ę

background image

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”;

background image

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 (clock’event and clock=‘1’) then
CURRENT<=NEXTS;
end if;
end process SYNCH;

background image

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)

background image

architecture b2 of MOORE is
type STATE_TYPE is (S0,S1,S2,S3);
signal CURRENT: STATE_TYPE;
begin

SYNCH:process(clock)
begin
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;
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

background image

architecture b3 of MOORE is
type STATE_TYPE is (S0,S1,S2,S3);
signal CURRENT: STATE_TYPE;
begin

SYNCH:process(clock)
begin
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’;
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

background image

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. Mealy’ego asynchron.
SYNCH:process(clock,reset)
begin
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;

background image

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

background image

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 <= "0000000" & data3 when (nrd='0' and sel="11")

else "ZZZZZZZZ";

end a1;

background image

* 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

background image

* 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 ("0000000" & 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 ("0000000" & data3);
end a3;

background image

background image

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;

background image

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

background image

rtl1

background image

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

background image

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

background image

TYPY OBIEKTÓW W VHDL -PODSUMOWANIE

* typy skalarne

-typ całkowity -definiowany do wykonywania działań
matematycznych, w standardzie zapisywany na 32 bitach: od -2

31

do

+(2

31

-1)

przykłady literałów całkowitych o podstawie 10: 0, 100, 1e6,
-700000, 1_945_690

binarnych: 2#1111# , 2#1110_1111#,

2#1111#e2 (60)

ósemkowych: 8#1234567#
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, -1.765, 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<=3.14159;

z<=1.9e21;
przypisania nieprawidłowe:

x:=2; y<=-1;

background image

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

background image

* 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

background image

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

background image

* 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);

background image

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.

background image

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


Document Outline


Wyszukiwarka

Podobne podstrony:
EDI wyk
Wyk ad 5 6(1)
Introduction to VHDL
zaaw wyk ad5a 11 12
Wyk 02 Pneumatyczne elementy
Automatyka (wyk 3i4) Przel zawory reg
Wyk ECiUL#1 2013
wyk II
Wyk 07 Osprz t Koparki
budownictwo stany skupenia wyk 3
6 wykˆad WiĄzania chemiczne[F]
Wyk ECiUL#9S 2013
Wyk ad II

więcej podobnych podstron