Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[vhdl] Zegar na płytce nexys2

jaitylkoja 14 Kwi 2012 14:20 1209 3
  • #1 14 Kwi 2012 14:20
    jaitylkoja
    Poziom 6  

    Dzień dobry.

    Na wstępie napomnę, że moja znajomość vhdl'a jest słaba. Chciałem zaprojektować zegar czasu rzeczywistego, który byłby wyświetlany na wyświetlaczu 7-segmentowym w konwencji (G G . M M). Do ustawienia godzin/minut wykorzystywałbym przyciski BTNx. Zaprojektowałem poprawnie komponent display&decoder, komponent debouncer do wyeliminowania drgań zestyków. I to wszystko działa. Jednak mam problem w top module, aby w jednym procesie (albo może być też w innych) dochodziło do ustawiania godzin (dynamiczne wyświetlanie na segmencie) i jednoczesnej pracy zegar 1Hz, który po 60 okresach zmienia mi pierwszą cyfrę minuty (którego generuję w innym procesie). Z powodów niemożliwości wykorzystania dwóch dyrektyw np. rising_edge w jednym procesie i niemożności przypisywania wartości do tych samych wektorów w innych procesach - mam problem. Przyciski powinny mieć działanie asynchroniczne of course. Gdy ustawiam coś takiego w jednym procesie wraz zegarem herzowym:
    if min1_1 = '1' wtedy cyfry na wyświetlaczu zmieniają się bardzo szybko i ciężko ustawić jest konkretną godzinę.

    Próbowałem również coś takiego wrzucić, ale wtedy przy jednym przycisku, cyfra zmienia się dwa razy:

    if min2_1 = '1' then

    if przyc = true then
    minuta2 <= minuta2 + 1;

    if minuta2 = 5 then

    minuta2 <= 0;

    end if;

    end if;
    przyc := false;
    end if;




    if min2_1 = '0' then
    if przyc = false then
    przyc := true;
    end if;
    (dalsza część instrukcji dla godz1_1 itd.).

    Może ktoś wspomóc pomysłem, literaturą, kodem? Z góry dziękuję,
    jaitylkoja.

    0 3
  • #2 14 Kwi 2012 23:25
    tymon_x
    Poziom 30  

    jaitylkoja napisał:
    Przyciski powinny mieć działanie asynchroniczne of course.

    Nie of course, wszytko ma mieć działanie synchroniczne względem głównego zegara.

    Zegar główny (powiedzmy 50 MHz) podajesz do wszystkich przerzutników bez wyjątku, czyli do funkcji rising_edge. Teraz za pomocą preskalera uzyskujesz 1Hz i tak podajesz do procesu liczącego pojedyncze sekundy na wejście clock_enable, kiedy dojdzie do '9' wystawiasz w tym cyklu stroba trwającego jeden takt zegara głównego do następnego procesu (jako clock_enable) liczącego dziesiętne sekundy, który jest taktowany głównym zegarem (50 MHz). Jeden zegar w systemie ! I tak powtarzasz proces. Taki kod BCD wystawiasz do Swojego dekodera na obsługę wyświetlacza segmentowego bezpośrednio.

    Do obsługi button oraz trybu pracy zegara, najlepiej zaprojektować skończoną maszynę stanów FSM. W jednym stanie będzie Sobie liczyć, w innym (np. po przetrzymaniu BTN) zmieniać czas. FSM wystawia odpowiednie sygnały do tych procesów, które odpowiednie zmienią zawartość przypadających im rejestrów stanów zegara.

    Pseudokod idei:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    0
  • #3 14 Kwi 2012 23:33
    gaskoin
    Poziom 38  

    Kiedy się procesów (czy pojedynczych encji) nie synchronizuje zegarem, to kiedy właściwie zmienia się ich stan ? Dodawanie wszędzie takiej synchronizacji z kolei wydaje się być uciążliwe (pchanie w każdy blok CLK), choć z drugiej strony umożliwia synchronizację na takty z różnych zegarów. Nie da się tego jakoś sensownie użyć ? Na przykład encji użyć w jakimś większym bloku zbiorczym i tam wszystko synchronizować ?

    0
  • #4 15 Kwi 2012 00:29
    tymon_x
    Poziom 30  

    gaskoin napisał:
    Kiedy się procesów (czy pojedynczych encji) nie synchronizuje zegarem, to kiedy właściwie zmienia się ich stan ? Dodawanie wszędzie takiej synchronizacji z kolei wydaje się być uciążliwe (pchanie w każdy blok CLK), choć z drugiej strony umożliwia synchronizację na takty z różnych zegarów. Nie da się tego jakoś sensownie użyć ? Na przykład encji użyć w jakimś większym bloku zbiorczym i tam wszystko synchronizować ?

    Po kolei. Załóżmy, że mamy duży system, który działa synchronicznie, ale między tymi procesami są jakieś działania asynchroniczne, jak np. dodawanie, zmiana adresu multipleksera i inne cuda. Teraz syntezer na podstawie układu (czasy opóźnień prymitywnych jednostek) musi wyliczyć max freq., a ona jest ustalana na podstawie stabilnej i znanej zmianie stanu (jakiś sygnał) między jednym procesem synchronicznym, a drugim. Im większe opóźnienie między nimi (czyli powiedzmy z grubsza suma działań asynchronicznych czy buforów) to spada nam maksymalna częstotliwość układu. W dodatku wszystkie działania asynchroniczne, są z reguły nieprzewidywalne.

    Jeśli proces (VHDL) nie jest synchroniczny (nie zawiera rising/falling_edge, 'event czy czegoś podobnego co syntezer zinterpretuje) to będzie asynchroniczny i jego czas "reakcji" zależy od czasów prymitywów. Czyli normalna logika asyn..

    Nie jestem zwolennikiem procesów, gdzie się pcha dużo funkcji (if, case etc) względem jednego zegara. Utrudnia to przede wszystkim czytelność opisu, proces powinień być zwarty, a większe działanie powinno zostać ukryte w architekturze/module jako BlackBox, a w środku małe procesiki, które między Sobą współpracują razem z kodem który działa współbieżnie do procesów (ex. sig <= '0' when sig_a = '1' else '1';). Raz się przejechałem na takim procesie... trzeba pamiętać, że ulubione zagnieżdżanie if-elsif-else-end zwiększa czas propagacji, po stawia co rusz nową bramkę do warunku, to spada f_clk oraz istnieje ryzyko, że może nie działać tak jak chcemy, wystąpi hazard. Łatwiej też przewidzieć jak zasoby można zużyć etc... na dużo rzeczy można zwrócić uwagę.

    Moja dewiza to im prościej, tym lepiej :)

    Tutaj widać, że można zaprojektować jeden uniwersalny proces do osobnej architektury, który będzie konfigurowalny za pomocą generic. Teraz wystarczy powołać taki unit jako komponent i umieścić go do architektury obsługi zegara za pomocą nowych instancji (UNIT : KOMPONENT i przypisanie portów port map oraz konfiguracji generic map). To jest normalny tok myślenia, stworzyć coś uniwersalnego i później wielokrotnie tego używać. Za pomocą generic możesz przekazać max zliczenie, a reszta sygnałów będzie taka sama (zegar, reset, clock_eneble, sygnały sterujące, wynik rejestru). Dla pro-moców, jeszcze można uprościć powielanie za pomocą generate.

    0