Spisu treści:

VHDL Basys3: Connect 4 Gra: 5 kroków
VHDL Basys3: Connect 4 Gra: 5 kroków

Wideo: VHDL Basys3: Connect 4 Gra: 5 kroków

Wideo: VHDL Basys3: Connect 4 Gra: 5 kroków
Wideo: Getting started with Vivado and Basys3 2024, Listopad
Anonim
VHDL Basys3: gra Connect 4
VHDL Basys3: gra Connect 4

Wstęp:

Jest to cyfrowa gra logiczna Connect 4 zaprojektowana w VHDL przy użyciu oprogramowania Vivado i zaprogramowana na płycie Basys3. Konstrukcja i projekt tego projektu są pośrednie, ale nowicjusze mogą skopiować kroki i zbudować grę cyfrową.

Gra działa jak gra Connect 4. Gracze mogą przesuwać kursor po ekranie za pomocą lewego i prawego przycisku znajdującego się na planszy. Naciśnięcie środkowego przycisku na planszy spowoduje, że gracz umieści swój znacznik na tej kolumnie, a następnie rozpocznie się kolejka następnego gracza. Gdy gracz wygra, grę można zresetować, naciskając przycisk w górę na planszy.

Krok 1: Szybkie szczegóły i materiały

Szybkie szczegóły techniczne:

  • Wykorzystuje trzy zestawy połączeń PMOD na płycie (JA, JB, JC)

    • 8 pinów (z wyłączeniem pinów Vcc i GND) używanych dla każdego złącza PMOD
    • JA - Kontrola rzędów
    • JB - Kontrola zielonych kolumn
    • JC - Kontrola czerwonych kolumn
  • Zegar ekranowy działa z częstotliwością 960 Hz

    Jednocześnie świeci tylko 8 diod LED. Ekran odświeża się z wystarczająco dużą szybkością zegara, aby można było złudzić, że w danym momencie świeci ponad 8 diod LED

  • Zegar guzikowy działa z częstotliwością 5 Hz; Opcjonalnie można dostroić, edytując kod VHDL.
  • Wewnętrzna rezystancja matryc Darlington Array jest wystarczająca, aby zapobiec przepaleniu diod LED

Gra jest skonstruowana przy użyciu następujących komponentów i narzędzi:

  • (1) Płytka Basys3
  • (2) Matryca LED dwukolorowa 8x5:
  • (2) ULN2803 - Tablice tranzystorowe Darlington - Arkusz danych
  • Szpule drutu
  • Przewody połączeniowe
  • Narzędzie do ściągania izolacji
  • Deski do krojenia chleba (duży kwadrat powinien wystarczyć)
  • Multimetr i zasilacz (rozwiązywanie problemów)

Krok 2: Podłączanie sprzętu

Podłączanie sprzętu
Podłączanie sprzętu
Podłączanie sprzętu
Podłączanie sprzętu

Wytyczne:

Okablowanie projektu może być bardzo zawiłe, proszę nie spiesz się i sprawdź, czy wszystkie połączenia są prawidłowe, jeden zestaw na raz.

W projekcie wykorzystano dwa ekrany LED, które zostały połączone w jeden duży ekran. Można to osiągnąć, łącząc wszystkie rzędy z tym samym punktem. Ponieważ każdy ekran jest dwukolorowy, czerwone i zielone rzędy jednego ekranu muszą być również powiązane z czerwonym i zielonym rzędem drugiego ekranu. W ten sposób możemy kontrolować wszystkie rzędy za pomocą zaledwie 8 pinów. Pozostałe 16 pinów służy do sterowania kolumnami wyświetlacza. 8 pinów do złącza można podłączyć bezpośrednio za pomocą kabli połączeniowych do złączy pmod. Połączenia Pmod najpierw trafiają do wejścia ULN2083A, a wyjście ULN2083A jest podłączone bezpośrednio do kolumny na ekranie. Ponieważ projekt to 8x8, niektóre kolumny nie będą fizycznie połączone.

  • JA: Połączenia rzędowe: Wiersz 1 do JA:1 do Wiersza 8 dla JA:10.
  • JA: Połączenia czerwonej kolumny:
  • JC: Połączenia zielonej kolumny

Proszę zapoznać się z zamieszczonymi obrazami, aby dowiedzieć się, które piny odpowiadają którym rzędom/kolumnom.

Uwaga: Tranzystory mają wbudowane rezystancje, dzięki czemu diody LED nie wymagają dodatkowego rezystancji, aby połączyć je szeregowo.

Krok 3: Wyjaśnienie techniczne: Ekran

Ekran operuje na trwałości widzenia. Ekran odświeża się tak szybko, że ludzkie oko nie jest w stanie dostrzec, że niektóre diody LED szybko się wyłączają i włączają. W rzeczywistości, spowalniając zegar wyświetlacza, można zauważyć miganie.

Wyświetlacz włącza wszystkie osiem wierszy zgodnie z danymi przechowywanymi dla tych wierszy, a wyświetlacz włącza jedną kolumnę. Następnie szybko przechodzi do następnego wpisu danych dla ośmiu wierszy i włącza następną kolumnę – przy wyłączonych wszystkich pozostałych kolumnach. Proces ten jest kontynuowany z wystarczająco dużą szybkością zegara, aby migotanie diody LED stało się niezauważalne.

Przechowywanie danych dla wyświetlacza jest inicjowane natychmiast po architekturze w pliku VHDL w następujący sposób:

sygnał RedA, RedB, RedC, RedD, RedE, RedF, RedG, RedH: std_logic_vector (7 do 0):= "00000000";

sygnał GreenA, GreenB, GreenC, GreenD, GreenE, GreenF, GreenG, GreenH: std_logic_vector (7 do 0):= "00000000"; -- Dane wiersza w zależności od kolumny: ZIELONY

Poniżej mały fragment procesu sterującego matrycą wyświetlacza LED.

-- Proces kontrolujący wyświetlanie matrycy wyświetlacza LED: proces (ColCLK) -- 0-16 do odświeżenia zarówno zmiennej matrycy 8X8 RED, jak i 8x8 GREEn RowCount: zakres liczb całkowitych od 0 do 16:= 0; rozpocznij jeśli (rising_edge(ColCLK)) then if (RowCount = 0) then DOROW <= RedA; -- Dane wiersza dla odpowiedniej kolumny DOCol <= "1000000000000000"; -- Wyzwalacz kolumny -- Powtórz ten kod aż do „0000000000000001” -- Zmień na czerwonyB, czerwonyC…zielonyA, zielonyB…zielonyH

Na końcu GreenH, tuż przed zakończeniem procesu, ten fragment kodu jest dołączany, aby zresetować RowCount z powrotem do zera.

if (RowCount = 15) then -- Uruchom ponownie odświeżanie z kolumny A RowCount:= 0; w przeciwnym razie Licznik Wierszy:= Licznik Wierszy + 1; -- Przechodzenie między kolumnami kończy się jeśli;

Teraz wyjaśnijmy zegar, który znajduje się na liście czułości procesu wyświetlania. Płyta Basys3 posiada wewnętrzny zegar pracujący na 100MHz. Dla naszych celów jest to zbyt szybki zegar, więc będziemy musieli podzielić ten zegar na zegar 960 Hz, korzystając z następującego procesu.

-- Proces zegara pracujący przy 960HzCLKDivider: zmienna procesu (CLK) clkcount: zakres liczb całkowitych od 0 do 52083:= 0; rozpocznij jeśli (rising_edge(CLK)) then clkcount:= clkcount + 1; if (clkcount = 52083) to ColCLK <= not(ColCLK); licznik:= 0; koniec jeśli; koniec jeśli; koniec procesu;

Krok 4: Wyjaśnienie techniczne: Zmiana wyświetlanych informacji

Wyjaśnienie techniczne: Zmiana wyświetlanych informacji
Wyjaśnienie techniczne: Zmiana wyświetlanych informacji

W kodzie VHDL informacje lub dane, które będą wyświetlane na ekranie, są kontrolowane przez proces kursora, który na liście czułości ma inny zegar. Ten kod nazywał się BtnCLK, zegar zaprojektowany w celu zminimalizowania wypychania przycisków po ich naciśnięciu. Jest to uwzględnione, aby po naciśnięciu przycisku kursor w górnym rzędzie nie poruszał się bardzo szybko po kolumnach.

-- Proces zegara pracujący z częstotliwością 5 Hz. ButtonCLK: zmienna procesu (CLK) btnclkcount: zakres liczb całkowitych od 0 do 10000001:= 0; rozpocznij jeśli (rising_edge(CLK)) then if (btnclkcount = 10000000) then btnclkcount:= 0; BtnCLK <= nie(BtnCLK); w przeciwnym razie licznik btnclk:= licznik btnclk + 1; koniec jeśli; koniec jeśli; koniec procesu;

Dzięki wyjściu sygnału BtnCLK tego procesu możemy teraz wyjaśnić proces kursora. Proces kursora ma tylko BtnCLK na liście czułości, ale w bloku kodu sprawdzany jest stan przycisków, co spowoduje zmianę danych dla RedA, RedB…GreenH. Oto fragment kodu kursora, który zawiera blok resetowania i blok dla pierwszej kolumny.

kursor: proces (BtnCLK) zmienna OCursorCol: STD_LOGIC_VECTOR (2 do 0):= "000"; -- OCursorCol śledzi poprzednią zmienną kolumny NCursorCol: STD_LOGIC_VECTOR (2 do 0):= "000"; -- NCursorCol ustawia nową kolumnę kursora begin --RESET warunek (przycisk W GÓRĘ) --Płyta jest czyszczona, aby gra mogła zostać zrestartowana if (rising_edge(BtnCLK)) then if (RST = '1') then RedA <= "00000000"; CzerwonyB <= "00000000"; CzerwonyC <= "00000000"; CzerwonyD <= "00000000"; CzerwonyE <= "00000000"; CzerwonyF <= "00000000"; CzerwonyG <= "00000000"; CzerwonyH <= "00000000"; ZielonyA <= "00000000"; ZielonyB <= "00000000"; ZielonyC <= "00000000"; ZielonyD <= "00000000"; ZielonyE <= "00000000"; ZielonyF <= "00000000"; ZielonyG <= "00000000"; GreenH if (Lbtn = '1') then NCursorCol:= "111"; -- Kolumna H elsif (Rbtn = '1') then NCursorCol:= "001"; -- Kolumna B elsif (Cbtn = '1') then NCursorCol:= OCursorCol; -- Kolumna pozostaje taka sama NTurnState <= not(TurnState); -- Wyzwala kolejkę następnego gracza -- Sprawdza bieżącą kolumnę od dołu do góry i włącza pierwszą diodę LED, która nie jest włączona. Kolor zależy od koloru kursora aktualnego gracza. dla ck w pętli 7 do 1, jeśli (RedA(0) = '1') i (RedA(ck) = '0') and (GreenA(ck) = '0') to RedA(Ck) <= '1'; CzerwonyA(0) <= '0'; WYJŚCIE; koniec jeśli;

jeśli (ZielonyA(0) = '1') i (CzerwonyA(ck) = '0') i (ZielonyA(ck) = '0') to

ZielonyA(Ck) <= '1'; ZielonyA(0) -- Czerwony gracz ZielonyA(0) <= '0'; if (NCursorCol = OCursorCol) then -- Jeśli nic nie zostało naciśnięte RedA(0) <= '1'; elsif (NCursorCol = "111") then -- Jeśli naciśnięto Lbtn RedH(0) <= '1'; CzerwonyA(0) <= '0'; elsif (NCursorCol = "001") then -- Jeśli naciśnięto Rbtn RedB(0) <= '1'; RedA(0) -- Zielony gracz RedA(0) <= '0'; if (NCursorCol = OCursorCol) then GreenA(0) <= '1'; elsif (NCursorCol = "111"), a następnie GreenH(0) <= '1'; ZielonyA(0) <= '0'; elsif (NCursorCol = "001"), a następnie GreenB(0) <= '1'; ZielonyA(0) <= '0'; koniec jeśli; sprawa końcowa;

Zauważ, że pierwsza instrukcja case o nazwie: OCursorCol (co oznacza Old Cursor Column) jest początkiem maszyny skończonych stanów. Każda kolumna wyświetlacza jest traktowana jako własny stan w FSM. Istnieje 8 kolumn, więc do identyfikacji każdej kolumny jako stanu użyto 3-bitowego zestawu liczb binarnych. Sposób, w jaki FSM porusza się między stanami, zależy od wciśniętego przycisku. W powyższym fragmencie, jeśli lewy przycisk zostanie naciśnięty, FSM przejdzie do „111”, która byłaby ostatnią kolumną wyświetlacza. Jeśli prawy przycisk zostanie naciśnięty, FSM przejdzie do „001”, która będzie drugą kolumną wyświetlacza.

Jeśli środkowy przycisk zostanie naciśnięty, FSM NIE przejdzie do nowego stanu, ale zamiast tego wyzwoli zmianę w sygnale TurnState, który jest jednobitowym sygnałem informującym o tym, który jest ruch gracza. Dodatkowo środkowy przycisk uruchomi blok kodu, który sprawdza, czy na samym dole jest pusty wiersz aż do samej góry. Będzie próbował umieścić znacznik w najniższym, niewypełnionym rzędzie. Pamiętaj, to jest gra typu „połącz cztery”.

W zagnieżdżonej instrukcji case o nazwie: TurnState zmieniamy kolor kursora i kolumnę w pierwszym wierszu, dla której chcemy zmienić dane, aby proces wyświetlania mógł odzwierciedlać zmianę.

Powtarzamy ten podstawowy kod dla pozostałych siedmiu przypadków. Diagram FSM może być pomocny w zrozumieniu, jak zmieniają się stany.

Krok 5: Kod

Kod
Kod

Jest to kod funkcjonalny Connect 4, który można skompilować w VHDL za pomocą oprogramowania Vivado.

Dostępne jest również ograniczenie umożliwiające uruchomienie gry.

Dostarczyliśmy schemat blokowy, który wyjaśnia, w jaki sposób wejścia i wyjścia każdego procesu są ze sobą połączone.

Zalecana: