Układy cyfrowe i systemy wbudowane 1 – laboratorium mgr inż. Antoni Sterna Pt 1245 - 1500
SPRAWOZDANIE
Tym razem, w odróżnieniu od wszystkich poprzednich zajęć, nasze projekty mieliśmy zrealizować na układzie Spartan. Jest to o wiele bardziej rozbudowany i dający o większe możliwości układ, niż wcześniejszy XC9572XL. Na zajęciach mieliśmy za zadanie zbudować układ realizujący funkcję „echa” na porcie szeregowym dla wybranego zakresu znaków (znaki odebrane z komputera mieszczące się w zadanym przedziale miały zostać odesłane przez układ, inne pominięte). Drugie zadanie polegało na skonstruowaniu układu konwertującego wartości heksadecymalne przesyłane portem szeregowym z komputera na kod BCD i wyświetlić na wbudowanym wyświetlaczu LCD. Ćwiczenia zrealizowaliśmy w programie Xilnix ISE Project Navigator.
Układ realizujący funkcję „echa” na porcie szeregowym
Układ zbudowaliśmy wykorzystując gotowy moduł do obsługi portu szeregowego wbudowanego w Spartana. Do tego modułu podłączyliśmy napisany przez nas moduł filtrujący znaki odebrane z portu szeregowego, którego kod znajduje się poniżej. Po utworzeniu symbolu z napisanego modułu mogliśmy przystąpić do podłączenia wszystkiego w całość. Ostatecznie układ przedstawiał się następująco:
A oto kod filtra:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity filter is
port(
start_in : in std_logic;
filter_input : in std_logic_vector(7 downto 0);
start_out : out std_logic;
filter_output : out std_logic_vector(7 downto 0));
end filter;
architecture filter_arch of filter is
subtype byte is integer range 0 to 255;
constant zero : byte := character'pos('0');
constant nine : byte := character'pos('9');
constant lower_a : byte := character'pos('a');
constant lower_z : byte := character'pos('z');
constant upper_a : byte := character'pos('A');
constant upper_z : byte := character'pos('Z');
signal filter_input_value : byte;
begin
filter_input_value <= to_integer(unsigned(filter_input));
process(filter_input_value)
begin
if filter_input_value >= zero and filter_input_value <= nine then
filter_output <= std_logic_vector(to_unsigned(filter_input_value, filter_output'length));
elsif filter_input_value >= lower_a and filter_input_value <= lower_z then
filter_output <= std_logic_vector(to_unsigned(filter_input_value - 16#20#, filter_output'length));
elsif filter_input_value >= upper_a and filter_input_value <= upper_z then
filter_output <= std_logic_vector(to_unsigned(filter_input_value + 16#20#, filter_output'length));
else
filter_output <= (others => '0');
end if;
end process;
start_out <= start_in when ((filter_input_value >= zero and filter_input_value <= nine)
or (filter_input_value >= lower_a and filter_input_value <= lower_z)
or (filter_input_value >= upper_a and filter_input_value <= upper_z)) else '0';
end filter_arch;
Układ konwertujący wartości heksadecymalne przesyłane portem szeregowym z komputera na kod BCD i wyświetlający na wbudowanym wyświetlaczu LCD
Do realizacji układu, podobnie jak w poprzednim punkcie, skorzystaliśmy z gotowego modułu obsługi portu szeregowego, ponadto skorzystaliśmy jeszcze z modułu obsługującego wyświetlacz LCD. Do całości potrzebny był nam jeszcze moduł konwertera, który napisaliśmy w VHDL i którego kod znajduje się poniżej. Po podłączeniu wszystkiego razem układ prezentował się następująco:
A tak wygląda kod modułu konwertera, który na schemacie znajduje się w postaci symbolu bcd_impl:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity bcd_impl is
port(
hex_in : in std_logic_vector(7 downto 0);
bcd_out : out std_logic_vector(11 downto 0));
end bcd_impl;
architecture bcd_impl_arch of bcd_impl is
begin
process(hex_in)
variable temporary : unsigned(11 downto 0);
variable input_value : unsigned(7 downto 0);
begin
temporary := to_unsigned(0, bcd_out'length);
input_value := unsigned(hex_in);
for i in 0 to 7 loop
if temporary(3 downto 0) > 4 then
temporary(3 downto 0) := temporary(3 downto 0) + 3;
end if;
if temporary(7 downto 4) > 4 then
temporary(7 downto 4) := temporary(7 downto 4) + 3;
end if;
if temporary(11 downto 8) > 4 then
temporary(11 downto 8) := temporary(11 downto 8) + 3;
end if;
temporary := temporary sll 1;
temporary(0) := input_value(7);
input_value := input_value sll 1;
end loop;
bcd_out <= std_logic_vector(temporary);
end process;
end bcd_impl_arch;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity counter is
port(
CLR : in std_logic;
Clk_LF : in std_logic;
modulo : in std_logic_vector(1 downto 0);
count : out std_logic_vector(3 downto 0);
terminal_count : out std_logic);
end counter;
architecture counter_arch of counter is
signal count_internal : 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(3, 4);
when "01" => modulo_value <= to_unsigned(2, 4);
when "10" => modulo_value <= to_unsigned(8, 4);
when "11" => modulo_value <= to_unsigned(2, 4);
when others => modulo_value <= to_unsigned(0, 4);
end case;
end process;
process (CLR, Clk_LF) is
begin
if CLR = '1' then
count_internal <= to_unsigned(0, count_internal'length);
elsif rising_edge(Clk_LF) then
if count_internal < (modulo_value - to_unsigned(1, count_internal'length)) then
count_internal <= (count_internal + to_unsigned(1, count_internal'length));
else
count_internal <= to_unsigned(0, count_internal'length);
end if;
end if;
end process;
count <= not std_logic_vector(count_internal);
terminal_count <= '1' when (count_internal + to_unsigned(1, 3) = modulo_value) else '0';
end counter_arch;
Wnioski:
Dzięki tym zajęciom mieliśmy okazję doskonalić nasze umiejętności w zakresie programowania w języku VHDL. Podobnie jak na poprzednich zajęciach, korzystaliśmy zarówno z opisu modułów w języku VHDL, jak i budowy schematu układu za pomocą symboli. Pozwoliło to maksymalnie uprościć budowę układu przy wykorzystaniu wszystkich korzyści, jakie daje nam stosowanie języka VHDL. Ponadto zajęcia te pozwoliły nam zapoznać się z kolejnym produktem firmy Xilinx – układem Spartan. Zrobił on na nas duże wrażenie, bo w porównaniu z poprzednim układem oferuje o wiele więcej różnych przycisków i interfejsów, które z pewnością będziemy wykorzystywać w czasie kolejnych zajęć.