Core Generator (wersja 2)

 

Zadanie: Należy wykonać generator figur Lissajous o następujących właściwościach:

1.      Figury rysujemy w kwadratowym obszarze o wymiarach 384 x 384 pixeli.

2.      Obraz generujemy na analogowym monitorze VGA (możemy wykorzystać tryb 640x480).

3.      Generator obrazu ustawić tak, aby obraz był maksymalnie wycentrowany i kwadratowy.

4.      Generujemy obraz czarno-biały (wszystkie sygnały RGB sterujemy równocześnie z tego samego źródła). Figura ma być biała, tło czarne.

5.      Częstotliwość obu kanałów (X i Y) i fazę jednego (Y) ustawiamy za pomocą przełączników SW0-SW7 (zakres 0-255) i przycisków BTN0 (wpis częstotliwości X ustawionej na przełącznikach), BTN1 (wpis częstotliwości Y ustawionej na przełącznikach), BTN2 (wpis offsetu fazy Y ustawionej na przełącznikach).

6.      Przycisk BTN3 powinien służyć do wyczyszczenia ekranu i zresetowania generatora DDS (aby rozpoczął rysowanie figur od ustawionej fazy dla kanału Y i fazy 0 dla kanału X).

7.      Kanał X to Channel 0 (patrz opis komponentu DDS poniżej). Współrzędne ujemne są po lewej stronie ekranu dodatnie po prawej. Amplituda kanału powinna być tak dobrana aby krzywa w pełni wykorzystała dostępny ekran.

8.      Kanał Y to Channel 1 (patrz opis komponentu DDS poniżej). Współrzędne ujemne są na dole ekranu dodatnie na górze. Amplituda kanału powinna być tak dobrana aby krzywa w pełni wykorzystała dostępny ekran.

9.      Współrzędne (0,0) są w środku ekranu.

 

Informacje o figurach Lissajous:

http://en.wikipedia.org/wiki/Lissajous_curve


Wejścia i wyjścia układu:

clk_i  -  zegar 50MHz,

rgb_o – wyjście sygnału RGB do monitora,

hsync_o – wyjście sygnału synchronizacji poziomej do monitora,

vsync_o – wyjście sygnału synchronizacji pionowej do monitora,

sw_i – przełączniki do ustawiania częstotliwości i fazy kanałów,

btn_i – przyciski do wprowadzania częstotliwości i fazy kanałów ustawionych na przełącznikach.

Informacje o analogowym sygnale VGA:


http://www.ue.eti.pg.gda.pl/fpgalab/zadania.spartan3/zad_vga_generowanie_sygnalu_vga.html

Przy generacji sygnału wideo należy pamiętać o zerowaniu sygnałów RGB poza obszarem wyświetlania obrazu.

 

Do realizacji projektu potrzebne będą dwa moduły funkcjonalne wygenerowane przez Core Generator. Dwuportowa pamięć RAM posłuży jako pamięć obrazu, zaś Generator DDS (Direct Digital Synthesizer) wykorzystany zostanie do wytwarzania cyfrowych sygnałów sinusoidalnych dla kanału X (poziom) i Y (pion).



Generacja modułu pamięci video:

Wybieramy: Project -> New Source

Następnie otwiera się okienko Select Source Type w którym wybieramy:
IP (CORE Generator & Architecture Wizard).
Podajemy nazwę pliku dla nowego komponentu (generowanego przez Core Generator), np. video_mem i klikamy Next:

Następnie otwiera się okienko wyboru nowego komponentu Select IP:

W okienku tym wybieramy Block Memory Generator v2.8 oraz klikamy Next. Następnie wyświetla się okienko podsumowania: New Source Wizard – Summary. Należy potwierdzić naciskając Finish.

Następnie uruchamia się Core Generator i otwiera się okienko konfiguracji nowego komponentu:

W tym okienku (1/5) zmieniamy Memory Type na Simple Dual Port RAM. Pamięć dwuportowa będzie nam potrzebna, aby można było równocześnie pisać i czytać z dwóch różnych adresów (zapisujemy pixele wg kształtu krzywej, odczytujemy pixele sekwencyjnie do monitora).
Znajdujący się w lewym dolnym roku przycisk View Data Sheet otworzy szczegółową dokumentację projektowanego komponentu.

Następnie klikamy Next.

W tym okienku (2/5) zmieniamy Write Width na 1 (będziemy zapisywać zawsze jeden pixel – bit na określonej pozycji - adresie) oraz Write Depth na 147456 (jest 384*384 = 147456 pixeli).

Następnie klikamy Next.

W tym okienku (3/5) zmieniamy Read Width na 1 (będziemy odczytywać zawsze jeden pixel – bit na określonej pozycji – adresie) – możliwe jest ustawienie innej szerokości bitowej magistrali wyjściowej i wejściowej. Liczba adresów jest tym razem wyliczona automatycznie.

Następnie klikamy Next.

W tym okienku (4/5) nic nie zmieniamy. Początkowa zawartość pamięci – wszystkie bity zerowe.

Następnie klikamy Next.

W tym okienku (5/5) nic nie zmieniamy. Okienko pozwala na ustawienie opcji dotyczących modelu symulacyjnego pamięci – chodzi o wykrywanie kolizji (np. równoczesny zapis z dwóch portów do tej samej komórki pamięci), i wykrywanie przekroczenia zakresu (np. adresów).

Następnie klikamy Finish.

Spowoduje to rozpoczęcie generacji komponentu – należy trochę poczekać.

Wygenerowana pamięć posiada dwa wejścia zegarowe (po jednym dla każdego portu) co może być wykorzystane jeżeli w naszym systemie są dwie domeny zegarowe, jednak zazwyczaj mamy w projekcie jeden zegar i wtedy oba wejścia podłączamy do wspólnego zegara.

Należy zwrócić uwagę na definicję niektórych sygnałów (np. WEA) które są wektorami jednobitowymi – trzeba o tym pamiętać ponieważ jednobitowy wektor to nie jest to samo co pojedynczy sygnał.

Warto zapamiętać pomocnicze informacje zawierające podsumowanie właściwości projektowanego komponentu (pole Information) oraz blokowy schemat połączeń. Szczególnie istotna jest informacja:
Total Port B Read Latency (From Rising Edge of Read Clock): 1 Clock Cycle(s).

Oznacza to, że odczyt z pamięci odbywa się z opóźnieniem 1 cyklu zegara w stosunku do zbocza zegarowego zatrzaskującego odczytywany adres (w przeciwieństwie do zapisu, w którym zapisywana dana zatrzaskiwana jest równocześnie z adresem). W przypadku wątpliwości proszę zajrzeć do dokumentacji komponentu (klawisz View Data Sheet).

Po zakończeniu generacji komponent zostanie dołączony do listy plików projektu.

W celu ułatwienia dołączenia komponentu do hierarchii aktualnego projektu w katalogu projektu powstają pliki *.vho zawierające szkielet deklaracji komponentu oraz przykład jego użycia (tworzenia instancji). Możemy te elementy łatwo przenieść do naszego projektu – wtedy zaprojektowany komponent zajmie właściwe miejsce w hierarchii.

Przykładowy plik VHO:

--------------------------------------------------------------------------------

-- The following code must appear in the VHDL architecture header:

 

------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG

component video_mem

       port (

       clka: IN std_logic;

       dina: IN std_logic_VECTOR(0 downto 0);

       addra: IN std_logic_VECTOR(17 downto 0);

       wea: IN std_logic_VECTOR(0 downto 0);

       clkb: IN std_logic;

       addrb: IN std_logic_VECTOR(17 downto 0);

       doutb: OUT std_logic_VECTOR(0 downto 0));

end component;

 

-- Synplicity black box declaration

attribute syn_black_box : boolean;

attribute syn_black_box of video_mem: component is true;

 

-- COMP_TAG_END ------ End COMPONENT Declaration ------------

 

-- The following code must appear in the VHDL architecture

-- body. Substitute your own instance name and net names.

 

------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG

your_instance_name : video_mem

             port map (

                    clka => clka,

                    dina => dina,

                    addra => addra,

                    wea => wea,

                    clkb => clkb,

                    addrb => addrb,

                    doutb => doutb);

-- INST_TAG_END ------ End INSTANTIATION Template ------------

 

-- You must compile the wrapper file video_mem.vhd when simulating

-- the core, video_mem. When compiling the wrapper file, be sure to

-- reference the XilinxCoreLib VHDL simulation library. For detailed

-- instructions, please refer to the "CORE Generator Help".

 

 

Tekst zaznaczony na czerwono należy skopiować do obszaru definicji sygnałów lokalnych. Tekst zaznaczony na niebiesko (po ustaleniu nazwy instancji komponentu oraz sygnałów podłączonych) należy skopiować do obszaru opisu systemu. Po dokonaniu powyższych modyfikacji ikona komponentu powinna zająć właściwe miejsce w hierarchii plików projektu.

Modyfikacja parametrów komponentu i jego ponowna generacja są możliwe za pomocą ikonek Manage Cores i Regenerate Core zaznaczonych na poniższym rysunku.

 


Generacja modułu generatora DDS

W celu wygenerowania modułu generatora DDS postępujemy podobnie jak poprzednio.

Wybieramy: Project -> New Source

Następnie otwiera się okienko Select Source Type w którym wybieramy:
IP (CORE Generator & Architecture Wizard).
Podajemy nazwę pliku dla nowego komponentu (generowanego przez Core Generator), np. singen i klikamy Next:

Następnie otwiera się okienko wyboru nowego komponentu Select IP:

W okienku tym wybieramy Direct Digital Synthesizer v5.0 oraz klikamy Next. Następnie wyświetla się okienko podsumowania: New Source Wizard – Summary. Należy potwierdzić naciskając Finish.

Następnie uruchamia się Core Generator i otwiera się okienko konfiguracji nowego komponentu:

W tym okienku (1/6) wybieramy funkcję: Sine oraz liczbę kanałów: Channels: 2.
(będziemy potrzebować dwóch niezależnych generatorów funkcji sinus do kreślenia figur Lissajous). Oprócz tego musimy podać częstotliwość zegara systemowego którym dysponujemy – DDS Clock Rate: 50 MHz.
Konieczne jest także określenie jakości wytwarzanego sygnału (różnica pomiędzy amplitudą prążka pożądanego, a amplitudą największego spośród prążków niepożądanych w widmie sygnału podawana w dB) – od tego zależy liczba bitów użyta do opisu funkcji sinus, a więc także złożoność bloku generatora. Wybieramy – Spurious Free Dynamic Range: 65 dB
Pozostaje określenie rozdzielczości z którą będziemy ustawiać częstotliwość sygnału – Frequency Resolution: 500 Hz

Znajdujący się w lewym dolnym roku przycisk View Data Sheet otworzy szczegółową dokumentację projektowanego komponentu.

Następnie klikamy Next.

W tym okienku (2/6) ustawiamy początkowe częstotliwości kanałów generatora (częstotliwość podajemy w MHz). Proszę ustawić częstotliwość obu kanałów na: 0.1953125  MHz
Uwaga - podczas wprowadzania nie widać wprowadzanej wartości.
Phase Increment należy ustawić na: Programmable pozwoli to na późniejszą zmianę częstotliwości podczas pracy generatora. Częstotliwość będziemy podawać za pomocą przełączników, których stan możemy wprowadzać bezpośrednio do najmłodszych bitów wejścia programującego.

Następnie klikamy  Next.

W tym okienku (3/6) ustawiamy początkowe fazy kanałów generatora (fazy podajemy w radianach/2π – tj. np. wielkość 1.0 oznacza 2π radianów). Proszę ustawić fazę kanału 1 na: 0.0 a kanału 2 na: 0.25 (czyli π/2 radiana).
Uwaga - podczas wprowadzania nie widać wprowadzanej wartości.
Phase Offset należy ustawić na: Programmable pozwoli to na późniejszą zmianę fazy podczas pracy generatora. Fazę będziemy podawać za pomocą przełączników, których stan możemy wprowadzać bezpośrednio do najstarszych bitów wejścia programującego.

Następnie klikamy  Next.

W tym okienku (4/6) ustawiamy parametry pracy oraz dodatkowe opcje generatora DDS.

Proszę włączyć opcję: Clear Options – SCLR Pin (będzie ona potrzebna do resetowania generatora po wprowadzeniu zmian i wyczyszczeniu ekranu przyciskiem BTN3) – jest to reset synchroniczny.

Opcję Noise Shaping proszę pozostawić na None (opcja ta służy do modyfikacji właściwości generatora w kwestii jakości generowanego sygnału).

Opcję Memory Type proszę ustawić na Block ROM

W polu Handshaking Options proszę wyłączyć RFD Pin (jest niepotrzebny) oraz włączyć Channel Pin (informuje o tym z którego kanału jest wystawiana aktualna próbka).

Opcję Pipelined należy wyłączyć.

W polu Accumulator Latency należy ustawić One Cycle.

Następnie klikamy  Next.

Warto zapamiętać pomocnicze informacje zawierające posumowanie właściwości projektowanego komponentu (pole Summary) oraz blokowy schemat połączeń.

Następnie klikamy  Next.

Wyświetli się drugie okienko z informacjami podsumowującymi.

Należy uruchomić syntezę komponentu naciskając Generate.

Następnie należy trochę poczekać.

Podobnie jak w poprzednim przypadku należy teraz podłączyć wygenerowany komponent do projektu (można wykorzystać wygenerowany plik *.vho).


Weryfikacja układu

Należy zweryfikować układ praktycznie poprzez zaprogramowanie płytki testowej. W razie potrzeby należy wykonać symulację funkcjonalną. Weryfikacja praktyczna polega na sprawdzeniu działania systemu poprzez wyświetlenie kilku figur Lissajous dla różnych częstotliwości i faz. W tym celu należy do wyjścia VGA podłączyć kabelek od małego monitora znajdującego się na stanowisku laboratoryjnym. Działanie zademonstrować prowadzącemu. Wyjaśnić kiedy i dlaczego widzimy dyskretną strukturę figur (figura złożona z pojedynczych kropek).


Informacje dodatkowe o zasadach działania generatorów DDS:
http://en.wikipedia.org/wiki/Direct_digital_synthesizer
http://www.ieee.li/pdf/essay/dds.pdf

 


Plik ucf do zadania, płytka Digilent Spartan-3, układ Spartan-3 3S200 FT256-4:

# Clock:

NET "clk_i" LOC = "T9" ; # 50 MHz clock

# VGA display:

NET "rgb_o<1>" LOC = "R12" ; # R

NET "rgb_o<2>" LOC = "T12" ; # G

NET "rgb_o<0>" LOC = "R11" ; # B

NET "hsync_o" LOC = "R9";

NET "vsync_o" LOC = "T10";

# Slide switches:

NET "sw_i<0>" LOC = "F12" ; # active high when in UP position

NET "sw_i<1>" LOC = "G12" ; # active high when in UP position

NET "sw_i<2>" LOC = "H14" ; # active high when in UP position

NET "sw_i<3>" LOC = "H13" ; # active high when in UP position

NET "sw_i<4>" LOC = "J14" ; # active high when in UP position

NET "sw_i<5>" LOC = "J13" ; # active high when in UP position

NET "sw_i<6>" LOC = "K14" ; # active high when in UP position

NET "sw_i<7>" LOC = "K13" ; # active high when in UP position

# Push-buttons:

NET "btn_i<0>" LOC = "M13" ; # active high

NET "btn_i<1>" LOC = "M14" ; # active high

NET "btn_i<2>" LOC = "L13" ; # active high

NET "btn_i<3>" LOC = "L14" ; # active high

#