Sprawozdanie 4
Układy cyfrowe i systemy wbudowane
Prow.: dr inż. Dariusz Caban
Założenia
Celem laboratorium było stworzenie układu odczytującego wartości heksadecymalne klawisza numerycznego z klawiatury i wyświetlającego je w wartościach binarnych na ekranie komputera za pomocą terminala puty.
Wykonanie
Wykorzystaliśmy gotowe już podukłady dostępne na stronie laboratorium - obsługujący port RS232 - podukład RS232_RX i RS232_TX służące do obustronnej komunikacji płytki z komputerem. Po połączeniu się programem puty na ekranie powinna pojawiać się binarna wartość klawisza, po której powinny nastąpić znaki ASCII CR i LN.
Program wykonano jako maszynę stanów, gdzie wartość naciśniętego klawisza powodowała przejście do odpowiedniego ciągu ośmiu stanów, gdzie każdy z nich przechowywał jedną cyfrę (0 lub 1), którą miał przesłać po porcie RS232 do komputera.
Powyższy program wymagał dużej pojemności pamięci płytki. Mimo częściowej optymalizacji o prawie połowę stanów, nie udało się zmieścić wszystkiego na płytce. Założona optymalizacja zakładała, że dla każdej cyfry pierwsze cztery bity są identyczne, różnią się dopiero następnymi czterema. Tak więc, maszyna zawsze wykonywała jeden ciąg czterech stanów, po którym dopiero wybierany był drugi ciąg odpowiadającego klawisza. Na końcu następowało wyświetlenie wartości ASCII symboli CR i LN.
Dlatego w efekcie program skrócono do możliwości odczytu cyfr: 0,1,2 i 3. Reszta cyfr byłaby wykonana analogicznie.
Wykonano językiem VHDL, korzystając ze schematu.
Schemat układu:
Objaśnienia:
Uwzględniono trzy wejścia (klawisz reset, zegar i wejście RS232) i trzy wyjścia (wyjście RS232 i dwie kontrolne diody LED. Podukład VHDL2 to podukład napisany kodem VHDL przedstawionym poniżej. Wejściami do VHDL2 są: zegar, reset, przesyłany sygnał i sygnał gotowości z RS232_RX, wyjściami natomiast: sygnał gotowości do przesłania sygnału i sam sygnał do RS232_TX.
Kod VHDL:
Powyższy kod to przypisanie sygnałów, deklaracja stanów maszyny oraz funkcji reset. Stany maszyny podzielono na dwie grupy: te posiadające w nazwie s[numer] to stany odpowiadające za same cyfry 0 i 1, które zostaną wyświetlone. Stany o nazwie sWait[numer] to stany odpowiadające oczekiwaniu na skończenie nadawania cyfry ze stanu poprzedniego. Numery:1, 2, 3 i 4 to numery pierwszego ciągu czterech bitów, który jest identyczny dla wartości każdej cyfry. I odpowiednio cyfry: 5, 6, 7 i 8 oznaczają drugi ciąg bitów cyfry „0”, 15,16,17,18 oznaczają „1”, 25,26,27,28 oznaczają cyfrę „2”, 35, 36, 37, 38 oznaczają cyfrę „3”. Sygnał „state” oznacza aktualny stan, „nextstate” stan następny.
Na powyższy kod składa się opis stanu Reset, po którym maszyna ma przejść do stanu Ready , który oczekuje wprowadzenia cyfry na klawiaturze. Jeśli RS_RX nie jest zajęty (DIRdy) może nastąpić transmisja. Później następują przejścia ze stanów Wait do stanów s z zachowaniem odpowiednich numerów.
Powyższy kod to rozpoczęcie wyszukiwania kolejnego ciągu czterech bitów. Jeśli na RS_RX przesłano „0” (X30), maszyna ma przejść do ciągu stanów, który rozpoczyna sWait[cyfra], jeśli na RS_RX przesłano „1” (X31), maszyna ma przejść do ciągu stanów, który rozpoczyna sWait[1_cyfra] oraz analogicznie dla pozostałych wartości.
Powyższy kod to przykładowy kod po wybraniu cyfry „0”, który reprezentuje przejście ze stanu 4 do Wait5, potem do stanu 5, aż wreszcie do stanu 6. Stan 5 przechowuje wartość piątego bitu, szósty szóstego itd. Pozostałe przejścia między stanami dla wszystkich cyfr są identyczne, zmieniają się jedynie indeksy poszczególnych stanów.
Powyższy kod zostaje wykonany po przejściu ze stanu 8, reprezentującego ósmy bit. Są to stany odpowiadające za kody ASCII oznaczające CR i LN, czyli zakończenie linii i przejście do nowej. Tak samo jak wyżej dzielą się na dwie grupy - stany oczekiwania i stany przechowujące wartości. Podany kod zostaje wywołany zawsze po zakończeniu odczytywania ósmego bitu cyfry.
Powyższy kod to przypisanie odpowiednim stanom odpowiednich wartości na wyjściu. Inaczej, jeśli pojawia się dany stan, na wyjście RS_TX ma zostać wysłana odpowiednia wartość. Pierwsze osiem stanów to deklaracja cyfry „0”, ponieważ przy pozostałych cyfrach, pierwsze cztery bity są identyczne, ponowna ich deklaracja i użycie nie ma sensu, dlatego potem występuje jedynie deklarowanie ostatnich czterech bitów każdej cyfry. Ostatnie dwa stany to kod znaków CR i LN.
Powyższy kod odpowiada za sygnał gotowości układy RS_TX odpowiadającego za wyjście i wyświetlenie cyfry na ekran. W założeniu sygnał ma aktywować się tylko dla niektórych stanów, faktycznie odpowiadających za przechowywanie wartości numerycznych. Przy stanach sWait nic nie musi być wyświetlane, więc wtedy RS_TX nie musi być gotowy do odczytu magistrali i wyświetlenia na ekran znaków.
Wyniki końcowe:
Jak już wspomniano, przy próbie realizacji wszystkich cyfr, układ odmówił współpracy z powodu zbyt małej pamięci. Świadczą o tym komunikaty o błędach:
Mimo to, dla czterech cyfr, układ działał poprawnie.
str. 7
Elżbieta Tchorowska 08-12-2010
Konrad Kukulski
str. 1
entity vhdl2 is
Port ( RS_RX : in STD_LOGIC_VECTOR (7 downto 0);
Clk_XT : in STD_LOGIC;
reset : in STD_LOGIC;
DIRdy : in STD_LOGIC;
TXBusy : in STD_LOGIC;
DORdy : out STD_LOGIC;
Busy : out STD_LOGIC;
RS_TX : out BIT_VECTOR (7 downto 0));
end vhdl2;
architecture RTL of vhdl2 is
type state_type is (sReset,sReady,sWait1,sWait2,sWait3,sWait4,sWait5,sWait6,sWait7,sWait8,s1,s2,s3,s4,s5,s6,s7,s8,scr,sln,waitcr,waitln,
sWait15,sWait16,sWait17,sWait18,s15,s16,s17,s18,
sWait25,sWait26,sWait27,sWait28,s25,s26,s27,s28,
sWait35,sWait36,sWait37,sWait38,s35,s36,s37,s38);
signal State, NextState : state_type;
signal HalfByte : STD_LOGIC_VECTOR (7 downto 0);
begin
process (Clk_XT, Reset)
Begin
if Reset = '1' then
State <= SReset;
elsif rising_edge(Clk_XT) then
State <= NextState;
end if;
end process;
process ( State,DIRdy,TxBusy)
begin
process ( State,DIRdy,TxBusy)
begin
NextState <= State;
case State is
when SReset =>
NExtState <=sReady;
when sReady =>
if DIRdy = '1' then
NextState <= sWait1;
end if;
when sWait1 =>
if TxBusy = '0' then
NextState <= s1;
end if;
when s1 => nextstate <= sWait2;
when sWait2 =>
if TxBusy = '0' then
NextState <= s2;
end if;
when s2 =>nextstate <= sWait3;
when sWait3 =>
if TxBusy = '0' then
NextState <= s3;
end if;
when s3 =>nextstate <= sWait4;
when sWait4 =>
if TxBusy = '0' then
NextState <= s4;
end if;
when s4 =>if RS_RX = X"30" then nextstate <= sWait5;
elsif RS_RX = X"31" then nextstate <= sWait15;
elsif RS_RX = X"32" then nextstate <= sWait25;
elsif RS_RX = X"33" then nextstate <= sWait35;
end if;
when sWait5 =>
if TxBusy = '0' then
NextState <= s5;
end if;
when s5 =>nextstate <= sWait6;
when s8 =>nextstate <= waitcr;
when waitcr =>
if TxBusy = '0' then
NextState <= scr;
end if;
when scr =>nextstate <= waitln;
when waitln =>
if TxBusy = '0' then
NextState <= sln;
end if;
when sln =>nextstate <= sReady;
process (State)
begin
case State is
when s1 => RS_TX <=X"30";
when s2 => RS_TX <=X"30";
when s3 => RS_TX <=X"31";
when s4 => RS_TX <=X"31";
when s5 => RS_TX <=X"30";
when s6 => RS_TX <=X"30";
when s7 => RS_TX <=X"30";
when s8 => RS_TX <=X"30";
when s15 => RS_TX <=X"30";
when s16 => RS_TX <=X"30";
when s17 => RS_TX <=X"30";
when s18 => RS_TX <=X"31";
when s25 => RS_TX <=X"30";
when s26 => RS_TX <=X"30";
when s27 => RS_TX <=X"31";
when s28 => RS_TX <=X"30";
when s35 => RS_TX <=X"30";
when s36 => RS_TX <=X"30";
when s37 => RS_TX <=X"31";
when s38 => RS_TX <=X"31";
when scr => RS_TX <=X"0D";
when sln => RS_TX <=X"0A";
when others => RS_TX <= X"39";
end case;
end process;
DORdy <= '1' when State = s1 or State = s2 or State = s3 or State = s4 or State = s5 or State = s6 or State = s7 or State = s8 or State = scr or State = sln
or State = s15 or State = s16 or State = s17 or State = s18
or State = s25 or State = s26 or State = s27 or State = s28
or State = s35 or State = s36 or State = s37 or State = s38
else '0';
ERROR:Cpld:837 - Insufficient number of macrocells. The design needs at least
129 but only 72 left after allocating other resources.
ERROR:Cpld:868 - Cannot fit the design into any of the specified devices with
the selected implementation options.