Aby wąż giętki robił to co wymyśli głowa, czyli słów kilka o analizie leksyk...
Cw1 ir dod2
1. Układy Cyfrowe – Laboratorium
Ćwiczenie 1
Język VHDL w projektowaniu układów kombinacyjnych
Przykładowe zadania
1
2. Zadania przykładowe
Zadanie 1
Zaprojektować układ kombinacyjny o wejściach A[7..0], B[7..0] i C[7..0] oraz wyjściu S[7..0],
który otrzymuje na wejściach liczby w kodzie BCD i daje na wyjściu największą spośród liczb A, B, C,
które dzielą się bez reszty przez 3. Jeśli Ŝadna z danych A, B, C nie dzieli się przez 3, to na wyjście
S naleŜy wyprowadzić liczbę 0.
Projekt ma być stanowić 1 jednostkę projektową w języku VHDL. Wejścia i wyjścia mają być sygna-
łami typu std_logic_vector.
1.1. Metoda rozwiązania
Kryterium podzielności przez 3 jest, aby suma cyfr liczby w postaci dziesiętnej dzieliła się przez 3.
Dane A, B i C są 2-cyfrowymi liczbami dziesiętnymi. Suma cyfr kaŜdej z liczb A, B lub C moŜe wyno-
sić maksymalnie 18.
Zsumujemy zatem cyfry np. Sa[7..0] <= A[7..4] + A[3..0]. Wystarczy sumowanie binarne;
A[7..4] oraz A[3..0]są liczbami binarnymi z zakresu od 0 do 9; suma Sa będzie liczbą 5-bitową
od 0 do 18.
Następnie zbadamy wartość Sa. Jeśli wynosi ona 3, 6, 9, 12, 15 lub 18, to wejściowa liczba A jest
podzielna przez 3.
Sa = 0 tylko wtedy, gdy A = 0. W tym przypadku formalnie występuje podzielność przez 3, ponie-
waŜ liczba zero dzieli się bez reszty przez kaŜdą liczbę. W przypadku danego zadania uznanie licz-
by 0 za podzielną lub za niepodzielną przez 3 nie zmieni rozwiązania.
Dla pozostałych wartości Sa liczba A jest róŜna od 0 i niepodzielna przez 3.
Podobnie musimy zbadać liczby B i C, uzyskując sumy cyfr Sb i Sc.
Na koniec spośród liczb As, Bs i Cs, gdzie np. As = A jeśli A jest podzielne przez 3 oraz As = 0 w
pozostałych przypadkach i analogicznie Bs i Cs zaleŜą odpowiednio od B i C, znajdziemy liczbę naj-
większą.
Projekt wykonamy etapami, zaczynając od 4-bitowego sumatora binarnego i uzupełniając kolejne
wersje jednostki projektowej o kolejne funkcje.
1.2. Sumator binarny
1.2.1. Układ podstawowy
Sumator jest podstawowym układem arytmetycznym. Do rozwiązania przedstawionych zadań będą
nam potrzebne sumatory binarne tak bezpośrednio, jak i w zastosowaniu do budowy sumatorów
danych w kodzie BCD.
Sumator binarny moŜe słuŜyć do dodawania liczb w naturalnym kodzie binarnym (liczb bez znaku)
lub liczb w kodzie uzupełnień do 2 (liczb ze znakiem). Układ sumatora dla obu przypadków jest taki
sam, róŜni się tylko interpretacja danych wejściowych oraz wyniku i sposób badania poprawności
wyniku.
Zacznijmy od zaprojektowania w języku VHDL 4-bitowego sumatora liczb binarnych bez znaku o
wejściach A[3..0] i B[3..0] oraz wyjściu S[3..0], bez wejścia przeniesienia i bez wyjścia prze-
niesienia.
2
3. Przy zastosowaniu pakietów std_logic_1164 oraz numeric_std projekt taki moŜna zapisać w
sposób przedstawiony poniŜej.
-- --------------------------------------------
-- Projekt 4-bitowego sumatora binarnego
-- bez przeniesienia wejściowego i wyjściowego
-- --------------------------------------------
-- Korzystamy z pakietów std_logic_1164 oraz numeric_std:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- Deklarujemy wymagane wejścia i wyjścia typów std_logic i std_logic_vector:
entity Zadanie_1_01 is
port (A, B: in std_logic_vector(3 downto 0);
S: out std_logic_vector(3 downto 0)
);
end Zadanie_1_01;
architecture Dataflow of Zadanie_1_01 is
begin
-- Tworzymy 4-bitową sumę dwu 4-bitowych danych:
S <= std_logic_vector( unsigned( A ) + unsigned( B ) );
end Dataflow;
PowyŜszy projekt zrealizowany w środowisku projektowym Quartus II firmy Altera zajmuje 4 ele-
menty logiczne w układzie FPGA serii Cyclone II.
1.2.2. Wyjście przeniesienia
JeŜeli A + B > 15, to na wyjściu układu według powyŜszego projektu uzyskamy nieprawidłowy
wynik i błąd ten nie zostanie zasygnalizowany. Aby uzyskać poprawne działanie sumatora w takiej
sytuacji, musimy uwzględnić wyjście przeniesienia.
Projekt sumatora binarnego o wejściach A[3..0] i B[3..0] oraz wyjściu S[3..0], z wyjściem
przeniesienia Cout i bez wejścia przeniesienia, moŜna zapisać w sposób przedstawiony poniŜej.
Sumowanie wykonujemy na słowie o 1 bit dłuŜszym od danych wejściowych, a najbardziej znaczący
bit wyniku wyprowadzamy jako wyjście przeniesienia.
-- --------------------------------------
-- Projekt 4-bitowego sumatora binarnego
-- z wyjściem przeniesienia
-- --------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Zadanie_1_02 is
port (A, B: in std_logic_vector(3 downto 0);
S: out std_logic_vector(3 downto 0);
Cout: out std_logic
);
end Zadanie_1_02;
3
4. architecture Dataflow of Zadanie_1_02 is
-- Dla sumowania z wyjściem przeniesienia deklarujemy słowa 5-bitowe:
signal Ax, Bx, Sx: std_logic_vector( 4 downto 0 );
begin
-- Za pomocą operatora konkatenacji definiujemy 2 składniki 5-bitowe:
Ax <= '0' & A;
Bx <= '0' & B;
-- Tworzymy 5-bitową sumę 5-bitowych danych:
Sx <= std_logic_vector( unsigned( Ax ) + unsigned( Bx ) );
-- Rozdzielamy 5-bitową sumę na 4-bitowy wynik oraz bit przeniesienia:
S <= Sx( 3 downto 0 );
Cout <= Sx( 4 );
end Dataflow;
PowyŜszy projekt zrealizowany w środowisku projektowym Quartus II firmy Altera zajmuje 5 ele-
mentów logicznych w układzie FPGA serii Cyclone II.
1.2.3. Wejście przeniesienia
Dla umoŜliwienia łączenia zaprojektowanych sumatorów w zespoły o większej długości słowa suma-
tor powinien mieć takŜe wejście przeniesienia.
Projekt sumatora binarnego o wejściach A[3..0] i B[3..0] oraz wyjściu S[3..0], z wejściem
przeniesienia Cin i wyjściem przeniesienia Cout, moŜna zapisać w sposób przedstawiony poniŜej.
Podobnie jak poprzednio, sumowanie wykonujemy na słowie o 1 bit dłuŜszym od danych wejścio-
wych, a najbardziej znaczący bit wyniku wyprowadzamy jako wyjście przeniesienia. Sumujemy jed-
nak juŜ 3 składniki – trzecim jest wejściowy bit przeniesienia, który rozszerzamy do słowa o takiej
samej długości jak suma.
-- ----------------------------------------
-- Projekt 4-bitowego sumatora binarnego
-- z wejściem i wyjściem przeniesienia
-- ---------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Zadanie_1_03 is
port (A, B: in std_logic_vector(3 downto 0);
Cin: in std_logic;
S: out std_logic_vector(3 downto 0);
Cout: out std_logic
);
end Zadanie_1_03;
architecture Dataflow of Zadanie_1_03 is
-- Deklarujemy 3 składniki i sumę jako słowa 5-bitowe:
signal Ax, Bx, Cx, Sx: std_logic_vector( 4 downto 0 );
4
5. begin
-- Za pomocą operatora konkatenacji definiujemy 3 składniki 5-bitowe:
Ax <= '0' & A;
Bx <= '0' & B;
Cx <= "0000" & Cin;
-- Tworzymy 5-bitową sumę trzech 5-bitowych danych:
Sx <= std_logic_vector( unsigned( Ax ) + unsigned( Bx ) + unsigned( Cx ) );
-- Rozdzielamy 5-bitową sumę na 4-bitowy wynik oraz bit przeniesienia:
S <= Sx( 3 downto 0 );
Cout <= Sx( 4 );
end Dataflow;
PowyŜszy projekt zrealizowany w środowisku projektowym Quartus II firmy Altera zajmuje 6 ele-
mentów logicznych w układzie FPGA serii Cyclone II.
1.3. Badanie podzielności liczby przez 3
Napiszemy teraz projekt, w którym badana będzie podzielność przez 3 wejściowej danej A[7..0] w
kodzie BCD. Na wyjście będzie wyprowadzana będzie dana As[7..0], równa A, jeśli A jest podziel-
ne przez 3 i równa 0 w pozostałych przypadkach.
-- -----------------------------------------
-- Badanie podzielności przez 3
-- 2-cyfrowej liczby w kodzie BCD
-- -----------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Zadanie_1_03 is
port (A: in std_logic_vector(7 downto 0);
As: out std_logic_vector(7 downto 0)
);
end Zadanie_1_04;
architecture Dataflow of Zadanie_1_04 is
-- Dla sumowania z bitem przeniesienia deklarujemy słowa 5-bitowe:
signal Ah, Al: std_logic_vector( 4 downto 0 );
signal Sa: unsigned( 4 downto 0 );
-- Deklarujemy bit kryterium podzielności:
signal Ka: std_logic;
begin
-- Wykonujemy 5-bitowe sumowanie binarne:
Ah <= '0' & A( 7 downto 4 );
Al <= '0' & A( 3 downto 0 );
Sa <= unsigned( Ah ) + unsigned( Al );
5
6. -- Badamy podzielność przez 3:
Ka <= '1' when Sa = 3 or Sa = 6 or Sa = 9
or Sa = 12 or Sa = 15 or Sa = 18 else
'0';
-- Generujemy wynik:
As <= A when Ka = '1' else
"00000000";
end Dataflow;
PowyŜszy projekt zrealizowany w środowisku projektowym Quartus II firmy Altera zajmuje 15 ele-
mentów logicznych w układzie FPGA serii Cyclone II.
1.4 Znajdowanie liczby największej spośród trzech 8- bitowych liczb BCD
Wykorzystamy operator porównania '>=' do porównania wartości sygnałów wektorowych typu
std_logic_vector, interpretowanych jako liczby w kodzie binarnym. Takie porównanie daje właściwy
wynik równieŜ dla liczb wyraŜonych w kodzie BCD. Operatory porównań - >, <, >=, <=, /=, = -, w
odniesieniu do typów wektorowych (bit_vector, std_logic_vector, unsigned, signed), powinny być
stosowane dla wektorówo takiej samej liczbie bitów. JeŜeli porównywane będą argumenty do typu
signed, to będą one interpretowane jako liczby w kodzie U2.
----------------------------
-- Porównanie 3 liczb BCD w celu znalezienia liczby
-- największej
----------------------------
library ieee;
use ieee.std_logic_1164.all;
entity Zadanie_1_05 is
port (A, B, C: in std_logic_vector(7 downto 0);
Max_o: out std_logic_vector(7 downto 0)
);
end Zadanie_1_05;
architecture arch of Zadanie_1_05 is
signal max_ab : std_logic_vector(7 downto 0);
begin
max_ab <= A when A >= B else
B;
Max_o <= max_ab when max_ab >= C else
C;
end arch;
6
7. 1.5 Całość rozwiązania – wersja ze schematem graficznym
1.6. Całość rozwiązania – wersja VHDL
-- -----------------------------------------
-- Największa liczba w kodzie BCD spośród
-- liczb podzielnych przez 3
-- -----------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity Przyklad1 is
port
(
A : in std_logic_vector (7 downto 0);
B : in std_logic_vector (7 downto 0);
C : in std_logic_vector (7 downto 0);
Max : out std_logic_vector (7 downto 0)
);
end Przyklad1;
architecture Arch of Przyklad1 is
component Zadanie_1_04
port( A : in std_logic_vector (7 downto 0);
As : out std_logic_vector (7 downto 0)
);
end component;
7
8. component Zadanie_1_05
port ( A : in std_logic_vector (7 downto 0);
B : in std_logic_vector (7 downto 0);
C : in std_logic_vector (7 downto 0);
Max_o : out std_logic_vector (7 downto 0)
);
end component;
signal sig_0, sig_1, sig_2 : std_logic_vector (7 downto 0);
begin
b2v_inst : Zadanie_1_04
port map (A => A,
As => sig_0);
b2v_inst1 : Zadanie_1_04
port map (A => B,
As => sig_1);
b2v_inst2 : Zadanie_1_04
port map (A => C,
As => sig_2);
b2v_inst3 : Zadanie_1_05
port map (A => sig_0,
B => sig_1,
C => sig_2,
Max_o => Max);
end Arch;
8