Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'VGA'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona


TempX

Znaleziono 4 wyniki

  1. Słowem wstępu, trzeba przyznać że tytuł artykułu sam w sobie jest dość kontrowersyjny. Dlaczego autorowi przyszło na myśl chwalić się najgorszą kartą graficzną na świecie, i to jeszcze drugą? Już spieszę z odpowiedzią: jest to moduł większego projektu, który jest dla mnie - autora - swego rodzaju wyzwaniem, dla czytelników - ciekawostką. A sprawa rozchodzi się o komputer ośmiobitowy. Jak zatem mogłaby wyglądać najgorsza karta graficzna? GeForce GT 210? Nie, pewnie jakiś radeon. Może zintegrowana grafika? W dobie XXI wieku już mało kto pamięta karty jeszcze starsze - stosowano niegdyś karty na szynach ISA, jak Trident TVGA-9000i (którego akurat posiadam). Karty te generowały obraz w rozdzielczości 640x480px, a przynajmniej przy trybie tekstowym. Przy trybie tekstowym, czyli karta generowała tylko i wyłącznie znaki, czasem tylko jednego koloru - lecz miała wtedy "fizycznie" największą rozdzielczość. Tryb graficzny umożliwiał kontrolę obrazu co do piksela i zmieniać nawet jego kolor, lecz wymagało to większej ilości zużycia RAMu - stąd tryby graficzne często były niższej rozdzielczości. Nie są to jednak karty najgorsze. Zainspirowany filmem Bena Eatera o jego "najgorszej karcie graficznej", postanowiłem samodzielnie zrobić takową kartę. Przyda się ona do zbudowania komputera ośmiobitowego, który już wcześniej zacząłem realizować, a że jeszcze przyszły mi płytki do rozlutu i były wakacje, był to całkiem dobry pomysł. Jak zatem prezentuje się karta? Źle. Na pewno teraz nasuwa się mnóstwo pytań czytelnikowi - więc już spieszę z opisem całości. Proces tworzenia karty zacząłem od postawienia założeń - na pewno nie chcę używać układów mocniejszych od Z80 (dla przykładu atmega 328p jest 16x mocniejsza od Z80), ponieważ nie ma to sensu - przerost formy nad treścią. Nie potrzebuję także trybu graficznego, chcę tylko terminal - więc tryb tekstowy mi wystarczy. Obraz chcę wyświetlać na monitorze kineskopowym (docelowo), więc chcę generować sygnał VGA. Kolor by się przydał, lecz priorytetem jest samo wyświetlanie znaków. Tak więc wiedziałem co chcę zrobić, musiałem się zastanowić jak. Najsampierw - zobaczyłem jaki sygnał należy generować. Tak więc, sygnał VGA to głównie 5 sygnałów - cyfrowa linia synchronizacji poziomej i pionowej, oraz 3 analogowe dla kolorów: czerwony, zielony i niebieski. Sygnał ten był opracowywany dla monitorów CRT, który obraz był generowany przez działko elektronowe, i sygnały cyfrowe tym działkiem sterują. Działko to pluje linię (display), po czym potrzebuje jeszcze chwili czasu (front porch), po czym - można powiedzieć - "synchronizuje się" z sygnałem (sync pulse), i wraca na początek linii (back porch). Całkiem podobnie jest dla linii synchronizacji pionowej. Kolory, jak już wcześniej wspomniałem, są sygnałem analogowym. Oznacza to, że im większe napięcie damy na ten sygnał, tym kolor będzie mocniejszy, a przy użyciu 3 sygnałów R, G i B - można te kolory łączyć. Jeżeli obraz nie jest wyświetlany, linie te powinny być podciągnięte do masy układu. I to w skrócie byłoby tyle - jeszcze rzut oka na czasy poszczególnych etapów sygnałów: Jak widać, aby uzyskać obraz 800x600 pikseli trzeba całość taktować aż czterdziestoma megahercami. Bramki logiczne, a i też niektóre mikrokontrolery nawet nie obsługują takich dużych częstotliwości - więc zdecydowałem się obniżyć ten zegar do 20MHz, co pozwoli uzyskać obraz 400x300 pikseli. Czasy zostają te same - lecz liczba pikseli się zmieni, co będzie bardzo ważną informacją w dalszej części artykułu. Wracając do układu Bena Eatera: on te czasy generował przy użyciu trzech liczników 4bit, potem porównywał konkretną liczbę z tych liczników, aby następnie sterować przerzutnikiem R/S dla linii synchronizacji. Ja uznałem "ale czemu tak komplikować sobie życie", zastosowałem jeden licznik binarny 12bit, a liczby porównywałem tylko logicznymi "jedynkami". Tak zatem wyglądają pierwsze dwa arkusze schematów: Pierwszy arkusz pokazuje kwestię zasilania, oraz złącz (karta będzie karmiona pięcioma woltami z zasilacza). Na złączu 40pin zaś znajdziemy ośmiobitową szynę danych, szesnastobitową szynę adresów, sygnały do wybierania jednego z 8 urządzeń, oraz piny WR i RD, odpowiadajace za operację zapisu i odczytu na wybranym urządzeniu. Złącze to łatwo można zdobyć z starych nagrywarek na szynie IDE, tasiemkę też - którą akurat kupiłem i skróciłem. Następny arkusz pokazuje licznik poziomy. Sam zegar na początku zrealizowałem przez układ 74HC14, z kwarcem 20MHz. Działał tylko po przyłożeniu palca (lub parówki) do styków kwarcu. Zamiast tego, generator sygnału 20MHz napędza licznik, który zlicza kolejno liczby w postaci binarnej. Liczby te sprawdzają bramki NAND, które interesują konkretnie 4 liczby: 400, 420, 484 i 528. Liczby te wziąłem z powyższej tabelki - a konkretnie po pierwszych 400 pikselach ustawiamy przerzutnik RS, dla wew. sygnału do wyświetlania pikseli. Sygnał HBLANK jest aktywny wtedy, kiedy nie powinny być wyświetlane żadne piksele. Następnie przy 420 pikselach ustawiamy kolejny przerzutnik, tym razem dla sygnału synchronizacji linii. Po 64 pikselach licznik ten jest resetowany, a przy 528 pikselu resetowany jest przerzutnik do wyświetlania pikseli, oraz resetowany sam licznik - następuje nowa linia, co jest też sygnałem taktującym dla zegara pionowego (sygnał jest przepuszczany przez bramkę NOT, ponieważ linia resetu i zegara jest aktywna w stanie wysokim). Tutaj też dość ważna informacja: na liczbę binarną składają się zarówno zera, jak i jedynki. Dlaczego zatem porównuję same jedynki? Każdy inny sygnał (który powinien być zerem) musiałbym podpiąć do bramki przez NOT, co by skutecznie powieliło ilość użytych układów. Porównywanie samych jedynek umożliwiło ominięcie tego, lecz "wybrana" liczba będzie występowała kilka razy. Nie ma to znaczenia i tak, ponieważ przerzutnik i tak został już ustawiony/zresetowany, a licznik jest potem resetowany. Tutaj jednak popełniłem kilka błędów. Do samej noty licznika (a nie samego pinoutu) zajrzałem duuużo później, gdzie przeczytałem, że liczniki te obsługują do 12MHz i to przy zasilaniu 15V (!) - tłumaczyło to wiele anomalii, lecz co ciekawe - zastosowanie liczników tych samych, lecz w wersji SMD zniwelowało wszelkie te anomalie. A że nie miałem pod ręką przejściówek z SO16 na DIP16, zrobiłem te śmieszne pajączki które widać na zdjęciu. Ważne że działa. Jest też jeszcze jeden błąd, który i ja popełniłem, i pan Eater popełnił: w informatyce zawsze się liczy od zera. Myślę że po wytłumaczeniu poprzedniego licznika, tutaj nie będzie niespodzianek. Jednak z racji tego, że na sygnał taktujący dostajemy 37.(87)kHz (zgodnie z tabelką), szukamy także pikseli podanych w tabelce: 600, 601, 605, 628. Technicznie rzecz biorąc pozwalałoby to na wyświetlanie obrazu 400x600px, lecz! Taka rozdzielczość byłaby troszkę niestandardowa, a litery byłyby mocno spłaszczone - przez co nieczytelne. Tak zaprojektowany i złożony układ prezentował się następująco: Generował on tylko i wyłącznie kolorowy ekran, lecz to już było coś. Problem zaczął w kwestii RAMu i ROMu. Zaczynając od RAMu, uznałem, że najlepiej będzie dodać licznik ósemkowy, który w połączeniu z bramkami AND, będzie po kolei sprawdzał każdy bit występujący na szynie danych pamięci ROM. W praktyce efekty okazały się co najmniej marne: Powinien się tutaj wyświetlać jeden znak, wykrzyknik, a dostałem... to. Potem spróbowałem czegoś podobnego lecz zamiast licznika ósemkowego - demultiplekser 74LS138. Bezskutecznie. Postanowiłem więc "wbudować" ten element karty do samej pamięci, marnując ją przy tym ogromnie: ponieważ obraz jest pobierany bezpośrednio z ROMu, wykorzystując przy tym jeden bit. A jest to pamięć ośmiobitowa. Tak więc zastosowany układ M27C1001, który jest pamięcią UV EPROM o pojemności 1Mbit, okazał się pomieścić "tylko" 4 tablice znaków po 255 znaków. A wygląda to tak: Linie adresu A0-A7 to wybór znaku, A8-A11 wybór linii, A12-A14 wybór kolumny, A15 - discord light theme, A16 - CP438, o którym mowa za chwilę. Pamięć samą w sobie zaprogramowałem wcześniej zrobionym i przerobionym programatorem, i mogę jeszcze powiedzieć, że mimo wersji o czasie odczytu do 100ns, wszystko działa sprawnie (a powinien być niższy od 50ns). Nawiązując jeszcze do samego wykonania płytki: przy projektowaniu schematu, nie wiedziałem do końca czy on zadziała. Dlatego nie trawiłem żadnych płytek, lecz całość wykonałem na płytkach prototypowych. Zasilanie doprowadzam górą, kynarami; sygnały zaś doprowadzam drutem 0.12mm z silniczka, który już się prawie skończył... Wracając: akurat się tak złożyło, że znak będzie duży na 8x16 (2³ x 2⁴) pikseli, co przy ekranie 400x300 pozwoli na wyświetlanie 50x18 znaków, nawet nieźle jak na gołe bramki logiczne. Po podpięciu pamięci RAM obraz wyglądał tak: Są to losowe znaki, co wynika z tego że pamięć RAM przy włączeniu zawiera losowe dane. A, nie powiedziałem jeszcze o samej tablicy znaków. Mocno inspirując się klasyczną, dosową czcionką, tak wygląda cała tablica znaków: Wykorzystując dodatkowy bit adresu pamięci EPROM, pozwoliłem sobie na zapis nowej tablicy znaków: CP438, gdzie standardowe znaki alfabetu są zastąpione przez Standardowy Alfabet Galaktyczny. Następnie w Processingu zrobiłem prosty program konwertujący piksele obrazu w tablicę zmiennych typu byte, jak docelowo miały być zapisywane znaki, a następnie tablicę tę skopiowałem do programatora. Niestety, nie opracowałem jeszcze zapisu z komputera, lecz na pewno będę musiał prędzej czy później zrobić - na chwilę obecną, programy muszą być mniejsze od pamięci samej atmegi. Więc skoro pamięć RAM i ROM już działała, to czego do szczęścia jeszcze trzeba? Ano, potrzebujemy coś zapisać do tej karty! I tutaj zaczęły się prawdziwe schody. Problem polega w tym, że pamięć RAM jest ciągle odczytywana przez timery. Przerwanie ich będzie skutkowało też przerwaniem wyświetlania obrazu. No i niestety, ale tak jest, ponieważ nie mam pomysłu jak inaczej wymyślić zapis. Tak więc, do odcinania timerów od RAMu służą tutaj bufory trójstanowe - 74HC245 i 244 (takie miałem pod ręką). Ale, zwykłe linie adresów i danych też trzeba było odciąć - więc musiałem zastosować tutaj 8 układów po 16 nóżek, więc lutownicą się namachałem. Na moje szczęście, powyższy schemat zadziałał za pierwszym razem. Jednak przez rozbieg, pomiędzy pamięć ROM i RAM dałem także bufor - jeżeli wstawiłbym tam zatrzask, to w najszczęśliwszym wypadku (zapis krótszy niż 0.4us) nie byłoby nic widać. Jednak zatrzask skutecznie by pozwolil zredukować liczbę anomalii, ale mimo wszystko tragedii nie ma przy zastosowaniu "zwykłego" bufora. Jak widać, proces zapisu jest aktywowany tylko, kiedy i linia zapisu i linia wyboru urządzenia są w stanie niskim - jest to realizowane bramką OR. Tak więc bufory są, wszystko jest, ale... kartę trzeba było jakoś sprawdzić. Jako, że płytkę z samym Z80 będę lutował później, na razie zapis przeprowadza Arduino MEGA (jeszcze raz: ono służy TYLKO do testowania karty, nie do generowania obrazu!), i karta działa zadziwiająco dobrze: Obraz jest monochromatyczny; zastosowanie palety kolorów byłoby ciekawym wyzwaniem. Kolor wybiera się przełącznikiem DIP przy złączu VGA. Ciekawa rzecz też była kiedy na początku źle zapisałem pamięć, na odwrót... Niestety, występuje także kilka anomalii. Lewy brzeg ekranu jest okupowany przez zgliczowane piksele, przez które najlepiej cały obraz jest przesunąć o znak w prawo. Pamięć ROM także wypaliłem w niezbyt komfortowych dla niej warunkach, więc piksele nie są do końca dobrze wypalone. Ciekawą anomalią są też te paski z tyłu, które występują tak trochę sinusoidalnie? Są stałe, rezystory pulldown i pullup nic nie dają... ale jeżeli sygnał koloru prześle przez płytkę stykową, linie magicznie znikają! Kiedy dostanę porządny oscyloskop (obecnie mam przystawkę hanteka, która mierzy tylko w kHz), głębiej to zbadam. Wiem też, że karta jest mocno wrażliwa na zakłócenia, np. z kabla USB czy oscyloskopu. Cały kod i obliczenia (dokumentację) udostępnię dopiero kiedy je sobie uporządkuję, bo kod arduino jest bardzo nieoptymalny, a obliczenia rozsiane po notesie... jak to pozbieram, wyślę na GitHuba, a całość opiszę po angielsku. EDIT: link do githuba Tak czy siak; karta jest gotowa, i może pracować razem z Z80, lub jako osobny moduł dla takiego Arduino (jak wiemy z poprzedniej konstrukcji, atmega nie do końca sobie radzi z VGA...) Wniosek: zostawić stare układy TTL, kupić płytkę z FPGA i się uczyć z forbotowego kursu. discord light theme
  2. Cześć, ponieważ, przy szukaniu kodu dla gry "Snake" natrafiłem na fajne repozytorium kodu dla płytki FPGA "Pepino" (Xilinx Spartan6), postanowiłem spróbować uruchomić jeszcze jedną "oldschool'ową" grę "Pacaman" na zestawie FPGA. W tym przypadku była wymaganą minimalna ilość pracy w kodzie projektu pobranego z repozytorium GIT(dla płytki Pepino): zamiana pliku "user constraints" "pacman.ucf". Tutaj prawidłowa postać tego pliku dla płytki Mimas V.2: # NUMATO Mimas V2 ucf file ## http://numato.com/ ## PACMAN UCF by Alex CONFIG VCCAUX = 3.3; ##Clock signal 100 MHz NET "SYS_CLK" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz; NET "SYS_CLK" TNM_NET = "sys_clk_pin"; TIMESPEC TS_sys_clk_pin = PERIOD "sys_clk_pin" 100 MHz HIGH 50 %; # LEDS NET "LED[3]" LOC = P15 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "LED[2]" LOC = U18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "LED[1]" LOC = T17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "LED[0]" LOC = T18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; # DIP Switches for one player, two player and credit #DP 8 NET "SW[0]" LOC = C17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; NET "SW[1]" LOC = C18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; NET "SW[2]" LOC = D17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; NET "SW[3]" LOC = D18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; # Push Buttons Switches For Joystick #SW6 - FIRE NET "JOYSTICK[4]" LOC = P1 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW1 RIGHT NET "JOYSTICK[3]" LOC = M18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW2 LEFT NET "JOYSTICK[2]" LOC = L18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW1 DOWN NET "JOYSTICK[1]" LOC = L17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW3 UP NET "JOYSTICK[0]" LOC = M16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; # Audio # # Audio Left NET "audio_l" LOC = B16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; # Audio Right NET "audio_r" LOC = A16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; # VGA Connections NET "VGA_HSYNC" LOC = B12 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_VSYNC" LOC = A12 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_RED[2]" LOC = C9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_RED[1]" LOC = B9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_RED[0]" LOC = A9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_GREEN[2]" LOC = C11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_GREEN[1]" LOC = A10 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_GREEN[0]" LOC = C10 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_BLUE[1]" LOC = A11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; NET "VGA_BLUE[0]" LOC = B11 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST; Poza tym trzeba było podmienić kawałek kodu w głównym entity projektu (związanego z głównym zegarem projektu) i dokonać zamiany typu układu FPGA Spartan6 (obudowa CSG324) we właściwościach projektu. No i dokonać syntezy i implementacji układu oraz generacji binarnego pliku konfiguracji układu FPGA ("pacman_top.bin" w katalogu "synth" projektu. Tutaj link do repozytorium kodu dla płytki FPGA Pepino (zawierającego miedzy innymi kod gry "Pacman"): https://github.com/Saanlima/Pepino/tree/master/Projects A tutaj link do tutoriala jakie zmiany trzeba wykonać, aby uruchomić grę "Pacman" na zestawie FPGA "Mimas V.2" (postępowałem dokladnie według tego tutorial'a): http://langster1980.blogspot.com/2016/04/pacman-running-on-mimas-v2-fpga.html Tak gra "Pacman prezentuje się na zestawie FPGA "Mimas V.2 (z małym monitorkiem 10 cali VGA): Myślę, że moim następnym krokiem będzie uruchomienie sprzętowego emulatora (na zestawie FPGA) komputera "Commodore C64" a w przyszłości "Amigi 600". No ale na to trzeba więcej czasu a i stopień skomplikowania projektu jest dużo większy. W archiwum zip spakowany projekt gry Pacman (dla Mimas V.2) dla "ISE 14.7" : Pepino-pacman.zip BTW: po namyśle, zdecydowałem, że "zabawę" z emulacją jakiejś prostej konsoli do gier rozpocznę od "NES" (Nintendo), bo w tym repozytorium dla płytki FPGA "Pepino" jest do jej emulacji fajny kod źródłowy: https://github.com/Saanlima/Pepino/tree/master/Projects/Pepino_NES_smb , tylko muszę najpierw kupić taki JoyPad (z oryginalnym złączem do konsoli NES) do tej konsoli (użyty w tym projekcie): https://allegro.pl/oferta/pad-do-konsoli-nintendo-entertainment-system-nes-11505068172 Pozdrawiam
  3. Cześć, ponieważ w ciągu tego roku byłem tak obciążony projektami elektronicznymi w pracy (i ich programowaniem), że nie mam w czasie wolnym ochoty na ambitne projekty. Ponieważ mam teraz kilka dni wolnych postanowiłem zająć się jakimś małym projektem, który da mi trochę rozrywki. Jak już kiedyś pisałem w latach 80-tych lubiłem grać w proste gry na "automatach", dlatego wybór padł znów na prostą grę "Snake"(wąż). Wybór padł na implementację tej gry na płytkę FPGA "Pepino" (także Spartan6) - niestety różni się sporo od Mimas V.2. Tutaj link do żródeł gry na Githgub'ie: https://github.com/Saanlima/Pepino/tree/master/Projects/Snake Przystępując do implementacji gry myślałem, że powinno udać się ją uruchomić na zestawie FPGA "Elbert V.2" (Spartan3) - niestety okazało się, iż liczba wymaganych zasobów jest ponad dwukrotnie większa od tej którą posiada ta płytka. Gra wymaga 1957 przerzutników (FF) i 1703 LUTs - patrz zrzut erranu z ISE: Tak, że mój wybór padł na zestaw FPGA "Mimas V.2", który posiadam od kilku lat. Tutaj linki do tego zestawu w Botland'zie oraz do producenta firmy "Numato Labs": https://botland.com.pl/moduly-i-zestawy-fpga/8603-mimas-v2-spartan-6-plytka-rozwojowa-fpga-5904422311964.html https://numato.com/product/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram/ https://numato.com/docs/mimas-v2-spartan-6-fpga-development-board-with-ddr-sdram/ Podstawową różnicą pomiędzy oryginalnym projektem na zestaw FPGA "Pepino" jest fakt, iż "Pepino" ma główny zegar 50 Mhz a Mimas v.2 100 Mhz. Poza tym ruch węża był realizowany poprzez klawiaturę PS2 podłączoną do plytki FPGA - ponieważ nie posiadam takiej klawiatury postanowiłem kontrolować ruch węża za pomocą przycisków na płytce Mimas. Z tego powodu można było usunąć dwa sygnały wejściowe: KB_clk i KB_data z głównego modułu aplikacji(Snake.v), i sam moduł obsługi klawiatury: kbInput(VGA_clk, KB_clk, KB_data, direction) Trzeba też było zmodyfikować plik "user constraints" (ucf) tak aby pasował do zestawu FPGA 'Mimas v.2". Oto lista wykonanych w projekcie zmian: 1) Zmodyfikowanie portów głównego modułu Snake.v: było: module Snake(start, master_clk, KB_clk, KB_data, VGA_R, VGA_G, VGA_B, VGA_hSync, VGA_vSync); input start; input master_clk, KB_clk, KB_data; output reg [2:0] VGA_R; output reg [2:0] VGA_G; output reg [1:0] VGA_B; output VGA_hSync, VGA_vSync; po modyfikacji: module Snake(start, clk100, VGA_R, VGA_G, VGA_B, VGA_hSync, VGA_vSync, btnUp, btnDown, btnLeft, btnRight); input start; input clk100; input btnUp, btnDown, btnLeft, btnRight; output reg [2:0] VGA_R; output reg [2:0] VGA_G; output reg [1:0] VGA_B; output VGA_hSync, VGA_vSync; 2) Usunięto moduł zegarowy w głównym module: // Use a CDM to generate VGA clock (25 MHz) from input clock (50 MHz) DCM #(.CLKIN_DIVIDE_BY_2("TRUE"), .CLKIN_PERIOD(20.000)) dcm(.CLKIN(master_clk), .CLKFB(VGA_clk), .RST(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .PSCLK(1'b0), .DSSEN(1'b0), .CLK0(VGA_clk)); a dodano DCM (IPCore PLL_Clock), który teraz z zegara Mimas'a 100 MHz generuje dwa zegary (50 Mhz i 25 Mhz do taktowania modułu VGA): // Instantiate the module PLL_Clock PLL1 (// Clock in ports .CLK_IN1(clk100), // IN 100Mhz // Clock out ports .CLK_OUT1(master_clk), // OUT 50Mhz .CLK_OUT2(VGA_clk)); // OUT 25MHz 3) Usunięte zostało wywołanie modułu: kbInput i kod samego modułu: VGA_gen gen1(VGA_clk, xCount, yCount, displayArea, VGA_hSync, VGA_vSync); randomGrid rand1(VGA_clk, rand_X, rand_Y); //kbInput kbIn(VGA_clk, KB_clk, KB_data, direction); updateClk UPDATE(VGA_clk, update); module kbInput(VGA_clk, KB_clk, KB_data, direction); input VGA_clk; input KB_clk; input KB_data; output reg [3:0] direction = 4'b0000; reg Q0, Q1; reg [10:0] shreg; reg [7:0] code; wire endbit; assign endbit = ~shreg[0]; assign shift = Q1 & ~Q0; always @ (posedge VGA_clk) begin Q0 <= KB_clk; Q1 <= Q0; shreg <= (endbit) ? 11'h7FF : shift ? {KB_data, shreg[10:1]} : shreg; if (endbit) code <= shreg[8:1]; if(code == 8'h1D) direction <= 4'b0001; else if(code == 8'h1C) direction <= 4'b0010; else if(code == 8'h1B) direction <= 4'b0100; else if(code == 8'h23) direction <= 4'b1000; end endmodule zamiast tego został dodany fragment kodu obsługujący przyciski z płytki Mimas w module głównym (linie od 79 do 87): end else if (~game_over) begin if (update) begin for(count = 1; count < 128; count = count + 1) begin if(size > count) begin snakeX[count] <= snakeX[count - 1]; snakeY[count] <= snakeY[count - 1]; end end //obsluga przycisow z Mimasa if(btnDown == 1'b0) direction <= 4'b0001; else if(btnLeft == 1'b0) direction <= 4'b0010; else if(btnUp == 1'b0) direction <= 4'b0100; else if(btnRight == 1'b0) direction <= 4'b1000; case(direction) 4'b0001: snakeY[0] <= (snakeY[0] - 1); 4'b0010: snakeX[0] <= (snakeX[0] - 1); 4'b0100: snakeY[0] <= (snakeY[0] + 1); 4'b1000: snakeX[0] <= (snakeX[0] + 1); endcase Poniżej rysunek z przyciskami z Mimas'a użytymi do kontrolowania ruchu węża i gry: Przycisk SW5 to start nowej gry a przyciski:SW!, SW2, SW3, SW4 kontrolują ruch węża. Poniżej zdjęcie z gry uruchomionej na zestawie Mimas v.2 i małym monitorku VGA: Bym zapomniał: był jeszcze błąd języka Verilog w tym fragmencie kodu: module randomGrid(VGA_clk, rand_X, rand_Y); input VGA_clk; output reg [6:0] rand_X; output reg [6:0] rand_Y; always @(posedge VGA_clk) begin //rand_X <= ((rand_X + 3) % 78) + 1; //rand_Y <= ((rand_Y + 5) % 58) + 1; rand_X <= ((rand_X + 3) % 64) + 1; rand_Y <= ((rand_Y + 5) % 32) + 1; end endmodule dwie linie zostały wykomentowane i dodane dwie poniżej (zmienione) - Verilog wymaga, aby drugi argument operatora modulo % był potęgą liczby dwa. Tutaj plik "Snake.ucf" (z user constraints) dla płytki Mimas v.2: NET "*" IOSTANDARD=LVCMOS33; CONFIG VCCAUX = "3.3" ; # Clock 100 MHz NET "clk100" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz ; NET "start" LOC = K17 | PULLUP; #SW5 # VGA port NET "VGA_hSync" LOC = B12; NET "VGA_vSync" LOC = A12; NET "VGA_R<0>" LOC = A9; NET "VGA_R<1>" LOC = B9; NET "VGA_R<2>" LOC = C9; NET "VGA_G<0>" LOC = C10; NET "VGA_G<1>" LOC = A10; NET "VGA_G<2>" LOC = C11; NET "VGA_B<0>" LOC = B11; NET "VGA_B<1>" LOC = A11; # Przyciski Mimas V.2 NET "btnLeft" LOC = M18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW1 NET "btnRight" LOC = L18 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW2 NET "btnDown" LOC = L17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW3 NET "btnUp" LOC = M16 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP; #SW4 Zamieszczam spakowany projekt gry dla "ISE 14.7 Webpack": SnakeGame.zip Plik binarny do wgrania konfiguracji FPGA to "snake.bin" (jeśli ktoś nie jest zainteresowany kodem źródłowym). Pozdrawiam
  4. Swego czasu, kiedy zaczynałem przygodę z elektroniką (6 klasa podstawówki, 2017 rok), zachciało mi się zrobić jakiś "większy" projekt. Padło na dość trudne wyzwanie, zrobienie mini pc z obsługą komend basicopodobnych. Z racji szkoły projektu nie dokończyłem, ale udało mi się zrobić płytkę z atmegą, z wyjściem VGA i wejściem na programator. Urządzenie nazwałem "iNap". Działanie Urządzenie jest podobne do Arduino Pro Mini: "goła" atmega 328 na 16Mhz, na płytce umieszczone zostały umieszczone peryferia takie jak: buzzer podpięty do pinu A0 przez tranzystor, generujący dźwięki diodę led przy pinie 13 (standard) stabilizator 7805 z filtrowaniem wyjście VGA gotowe pod bibliotekę VGAX 5 wyprowadzonych pinów (analogi + pin 2) Całość programujemy za pomocą usbasp z podłączonym zewnętrznym zasilaniem (błąd w pcb, masy są oddzielone). Płytka została zaprojektowana pod bilbiotekę VGAX, dzięki której na Arduino możemy wyświetlać obraz VGA w 4 kolorach (!), w rozdzielczości 120x60px. Na monitorze możemy napisać dowolny tekst, dowolną zmienną czy nawet wyświetlić zdjęcie. Na zdjęciu płytka pracuje z podpiętym zewnętrznym zasilaczem. Na monitorze (od razu przepraszam za bałagan na biurku) możemy zobaczyć przerobiony przykład z biblioteki, który wyświetla 1 kolorowe piksele w losowych miejscach. Samo generowanie VGA zużywa aż 3 timery naszej atmegi, przez co mamy ograniczoną swobodę wykonywania funkcji czasowych, a bufor danych (ramka) zużywa ponad 89% RAMu mikrokontrolera. Budowa Pierwszą płytkę (testową) wykonałem na płytce uniwersalnej (gdzieś ja schowałem, nie wiem gdzie), miała ona uboższe możliwości. Płytkę którą widzicie zaprojektowałem w Eaglu, jeszcze na starym pc, więc plików nie wyślę. Samo PCB wykonałem domowymi sposobami: ścieżki naniosłem metodą termotransferu na laminat, nastepnie wytrawiłem w B327. Nastepnie wiercenie, dopieszczanie i lutowanie. Na końcu zapomniałem pomalować spód lakierem, przez co 2 lata miałem wystawioną gołą miedź. Ale płytka jeszcze dobrze się trzyma 😉 Co do peryferiów, buzzer podpiąłem przez tranzystor 2N2222. Same sygnały VGA musiałem ograniczyć rezystorami do odpowiednich napięć (68ohm na vsync i hsync, ok. 220ohm na kolory). Układ stabilizatora wyposażyłem w podwójny przełącznik DIP Switch, który odcina zasilanie i wycisza buzzer. Podsumowanie Był to mój pierwszy tak duży projekt. Moje pierwsze trawienie, pierwsze PCB. Wszystko zadziałało za pierwszym razem, i gdyby nie szkoła, na pewno zrobiłbym coś więcej z tym. Poczułem się deczko zawiedziony, kiedy na instructablesach już ktoś napisał poradnik "jak zrobić mini pc na arduino diy" chyba parę miesięcy temu. Jeżeli ktoś by chciał zrobić podobny projekt, to przede wszystkim na ESP (autor tej biblioteki napisał podobną pod ESP), które oferuje prawdziwe, monochromatyczne 640x480px i dołożyć obsługę klawiatury na PS/2. Życzę szczęścia 😉 Pozdrawiam, Leoneq :3
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.