Układy cyfrowe i systemy wbudowane 1 – laboratorium mgr inż. Antoni Sterna Pt 1245 - 1500
SPRAWOZDANIE
Tym razem, w odróżnieniu od poprzednich zajęć, nasze układy opisywaliśmy przy pomocy języka VHDL, a nie jak dotychczas – z gotowych modułów. Pierwsze do wykonania ćwiczenie polegało na przerobieniu na język VHDL układu detektora, który realizowaliśmy na pierwszych zajęciach (w naszym przypadku detektor wykrywa sekwencję 000) – należało przygotować 4 różne warianty realizacji. Następne ćwiczenie również bazowało na pierwszych zajęciach – naszym zadaniem było napisanie pełnego subtraktora 1-bitowego. Kolejne zadanie to licznik synchroniczny z programowalnym modulo 4-bitowym z możliwością resetu. Ostatnie do zrealizowania ćwiczenie polegało na zbudowaniu licznika o sekwencji zadawanej za pomocą tablicy (array). Ćwiczenia zrealizowaliśmy w programie Xilnix ISE Project Navigator i zaprogramowaliśmy je w układzie XC9572XL.
Detektor wykrywający sekwencję 000
Zadanie to należało wykonać na 4 sposoby: za pomocą przypisania selektywnego, warunkowego oraz w 2 wariantach procesu. Udało nam się napisać kod w taki sposób, że wszystkie cztery warianty działały równolegle i mogliśmy porównać ich działanie – oczywiście wszystkie działały prawidłowo, w ten sam sposób. Poniżej zamieszczony jest kod VHDL:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity detector is
port(
A : in std_logic_vector(3 downto 0);
LED : out std_logic_vector(3 downto 0));
end detector;
architecture detector_arch of detector is
signal o : std_logic_vector(3 downto 0);
begin
o(0) <= ((not A(3)) and A(2))
or ((not A(2)) and A(1))
or (A(3) and (not A(2)) and A(0))
or ((not A(2)) and (A(1) or (A(3) and A(0))));
o(1) <= '1' when (unsigned(A) >= 2 and unsigned(A) <= 7) or (unsigned(A) >= 9 and unsigned(A) <= 11) else '0';
process(A) is
begin
if unsigned(A) >= 2 and unsigned(A) <= 7 then
o(2) <= '1';
elsif unsigned(A) >= 9 and unsigned(A) <= 11 then
o(2) <= '1';
else
o(2) <= '0';
end if;
end process;
process(A) is
begin
case A is
when "0010" => o(3) <= '1';
when "0011" => o(3) <= '1';
when "0100" => o(3) <= '1';
when "0101" => o(3) <= '1';
when "0110" => o(3) <= '1';
when "0111" => o(3) <= '1';
when "1001" => o(3) <= '1';
when "1010" => o(3) <= '1';
when "1011" => o(3) <= '1';
when others => o(3) <= '0';
end case;
end process;
LED <= not o;
end detector_arch;
Zbudować pełny subtraktor 1-bitowy, a następnie układ dwóch połączonych subtraktorów.
Napisanie subtraktora nie przysporzyło nam większych problemów, natomiast połączenie dwóch subtraktorów było dla nas nieco problematyczne. Do poprawnego działania należało zastosować funkcje component oraz port map. Ostatecznie jednak układ udało się zrealizować, a poniżej przedstawiony jest jego kod:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity sub1 is
port(
a, b, c : in std_logic;
s, cout : out std_logic);
end sub1;
architecture sub1_arch of sub1 is
begin
s <= a xor b xor c;
cout <= (((not a) and b) or (b and c) or (c and (not a)));
end sub1_arch;
--------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity sub is
port(
A : in std_logic_vector(1 downto 0);
B : in std_logic_vector(1 downto 0);
C : in std_logic;
S_real : out std_logic_vector(1 downto 0);
Cout_real : out std_logic);
end sub;
architecture sub_arch of sub is
component sub1 is
port(
a, b, c : in std_logic;
s, cout : out std_logic);
end component;
signal cint : std_logic;
signal Cout : std_logic;
signal S : std_logic_vector(1 downto 0);
begin
first : sub1
port map(A(0), B(0), C, S(0), cint);
second : sub1
port map(A(1), B(1), cint, S(1), Cout);
S_real <= not S;
Cout_real <= not Cout;
end sub_arch;
Licznik synchroniczny z programowalnym modulo 4-bitowym z możliwością resetu.
Licznik zbudowaliśmy w ten sposób, że zliczał on sygnały zegara LF, a za pomocą wciśnięcia odpowiednich klawiszy można było ustalić żądaną wartość modulo (do wyboru 0, 2, 4, 8, 15). Ponadto zaimplementowaliśmy także klawisz do resetowania. Domyślna wartość modulo to 0. Do przesyłania wartości konieczne okazało się zastosowanie funkcji to_unsigned. Poniżej zamieszczony jest kod układu:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity counter is
port(
CLR : in std_logic;
Clk_LF : in std_logic;
modulo : in std_logic_vector(1 downto 0);
LED : out std_logic_vector(3 downto 0));
end counter;
architecture counter_arch of counter is
signal count : unsigned(3 downto 0);
signal modulo_value : unsigned(3 downto 0);
begin
process (modulo) is
begin
case modulo is
when "00" => modulo_value <= to_unsigned(2, 4);
when "01" => modulo_value <= to_unsigned(4, 4);
when "10" => modulo_value <= to_unsigned(8, 4);
when "11" => modulo_value <= to_unsigned(15, 4);
when others => modulo_value <= to_unsigned(0, 4);
end case;
end process;
process (CLR, Clk_LF) is
begin
if CLR = '1' then
count <= to_unsigned(0, count'length);
elsif rising_edge(Clk_LF) then
if count < (modulo_value - to_unsigned(1, count'length)) then
count <= (count + to_unsigned(1, count'length));
else
count <= to_unsigned(0, count'length);
end if;
end if;
end process;
LED <= not std_logic_vector(count);
end counter_arch;
Wnioski:
Dzięki tym zajęciom mieliśmy okazję wypróbować w praktyce język VHDL i poznać niektóre z jego funkcji. Początkowo sprawiło nam trochę trudności zrozumienie, w jaki sposób pracuje się z językiem VHDL w środowisku Xilinx ISE Project Navigator, a rozwiązywanie powstających po drodze problemów zajęło nam nieco czasu. Niestety, udało nam się zrealizować 3 z 4 zaplanowanych zadań, jednak doświadczenie, które zdobyliśmy na tych zajęciach na pewno sprawi, że wykonanie kolejnych zadań do realizacji w VHDL zajmie nam dużo mniej czasu. Ponadto zrozumieliśmy kilka istotnych faktów, o których należy pamiętać przy opisywaniu układów w VHDL (m. in. używanie funkcji to_unsigned), które z pewnością przydadzą się w przyszłości.