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

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 wyjście 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 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