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

[VHDL] stuck at "1" po zaprogramowaniu pytki, prosty kod

11 Maj 2012 13:40 2434 17
  • Poziom 9  
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    Wydaje sie prosty automat stanu, jak chce go przetestowac i wrzucam na plytke DE0 to zmienna START i RS2round non stop wisi w stanie '1' za to RS1round wisi jako '0'. wraz z kolejnymi kliknieciami zegara nic sie nie zmienia
  • Zasilacze UPS
  • Poziom 14  
    Po pierwsze przydałby się jakiś reset, gdzie na początku ustalasz wartość 'current_state'.
    Po drugie zamiast clk'event and clk = '1' lepiej używać rising_edge(clk).
    Po trzecie przydałby się "when others".
  • Poziom 9  
    Dziękuje.

    Ale to są drobne zmiany które niczego nie naprawiają.
  • Zasilacze UPS
  • Poziom 30  
    adeptofvoltron napisał:
    Ale to są drobne zmiany które niczego nie naprawiają.

    Uwielbiam takie stwierdzenia, zamiast pisać od początku do końca czytelnie i zgodnie z sztuką, to przesłaniasz faktyczny problem takim "brzydkim" opisem HDL. Po co reset albo tcq ? I tak dalej, przyciemnia to sprawę...

    variable licznik :integer; - integer domyślnie to jest 32 bitowy rejestr, marnujesz niepotrzebnie zasoby logiki programowalnej. Mądry syntezer zoptymalizuje ten babol, ale następnym razem ograniczaj zakres za pomocą range x to y, albo najlepiej korzystaj tylko z std_logic_vector.

    signal tmp :std_logic; - inicjalizuj takie sygnały, bo w symulacji wyjdą Ci same X, a to świadczy że na pewno nie zrobiłeś symulacji, to byś wiedział co masz źle. Domyślnie większość narzędzi inicjalizuje w FPGA wartością '0'.

    clk'event and clk = '1' - używaj rising_edge, to robi różnicę w symulacji, zwiększa czytelność.

    tmp <= not tmp; - wiesz co właśnie stworzyłeś ? Generator ! Czyli jak będzie w tym stanie, to wartość tmp będzie się zmieniała z jego maksymalnym opóźnieniem. Czyli jak czas propagacji bramki NOT (inwerter) wyniesie pojedyncze ns, to otrzymasz jakieś kilkanaście MHz ! Raczej nie zobaczysz tego na LED. Tu leży główna przyczyna Twojego problemu

    (licznik<StartTime) - typowe myślenie programisty, marnujesz znowu zasoby. Wystarczy samo =.

    when others - wstaw

    adeptofvoltron napisał:
    Wydaje sie prosty automat stanu, jak chce go przetestowac ...

    Najpierw piszemy testbench, uruchamiamy symulator, a później wrzucamy bitsream do FPGA, a nie pomijamy tego etapu...
  • Poziom 9  
    dzięki. Dokładnie o takie porady mi chodziło, cóż widać, że dotychczas zajmowałem się raczej projektami z wysokiego poziomu.
  • Poziom 38  
    Czy jest jakiś sposób na pozbycie się tak paskudnego zapisu maszyny stanów, żeby nie ciągnąć litanii whenów? :)
  • Poziom 30  
    gaskoin napisał:
    Czy jest jakiś sposób na pozbycie się tak paskudnego zapisu maszyny stanów, żeby nie ciągnąć litanii whenów? :)

    Stworzyć opis pamięci ROM :P Adresować można za pomocą type, czyli nazwami (po C-naszemu enum), a bity w pamięci, a dokładnie wektor zastąpić type strukturą z polami (po C-naszemu, typedef struct).

    Case to klasyka, bo łatwo dobrać wtedy sposób optymalizacji. Czy to ma być multiplekser czy pamięć, czy kodować binarnie czy Gray oraz wszystkie syntezery optymalizują maszynę stanów względem opisu za pomocą case, bo taki szablon jest analizowany.
  • Poziom 14  
    Tymon możesz coś więcej wyjaśnić, bo coś nie mogę załapać :)

    Co do FSM'a to jest inne wyjście poza case'm. Można skorzystać również z "Implicit State Machine" gdzie używa się z konstrukcji 'wait'.
  • Poziom 30  
    Dave_PL napisał:
    Tymon możesz coś więcej wyjaśnić, bo coś nie mogę załapać :)

    Myślałem o czymś takim:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Problem jest ze słówkiem others oraz record i jego różnymi typami. Trzeba konkretniej podawać, gdzie chcemy zrobić agregację. Wyjściem z tej sytuacji, jest stworzenie wspólnego rekordu z jednym typem (std_logic) i rozdzielenie funkcjonalności za pomocą nazw: uart0_send, timer0_up. Wtedy można za pomocą others zmienić wartości globalnie, ale to mi się nie podoba. Brakuje mi w agregacji wyboru zakresu rekordu (timer0 to timer2 nie działa). Jak dodasz do rekordu inny typ, to wywali błąd że others nie pokryje tego zakresu i trzeba uzupełniać w reszcie stanów. Dlatego tam jest wszędzie UART0. Można by było coś z tablicą też pokombinować i umieścić TIMERn lub UARTn do array, to by trochę ułatwiło sprawę i nie trzeba by było klepać UARTn tylko dać others do indeksów. Druga myśl jaka mi przyszła, to zrobić do tego funkcję, która już by samo uzupełniała, a stringami inicjalizować rekordy, trochę może przekombinowane, ale wykonywalne. Już coś podobnego robiłem w assert i wskaźnikami access. Wybór i powiązania między opcjami opierał się na tablicy z stringami.

    Użycie w dowolnym procesie jest banalne, wystarczy użyć.
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Później należy według własnego uznania zaprojektować stany przejściowe na podstawie sygnałów wejściowych. Można stosując tą samą metodę wyżej, można adresować tej inny blok pamięci o adresach zawierających w wspólne sygnały obecnego stanu fsm oraz sygnałów wejściowych (za pomocą aggregate), a na wyjściu mieć następny stan fsm.

    To całość sprowadza się do modyfikacji pamięci oraz użycie sygnałów wyjściowych z takiej maszyny do naszych procesów.

    Można pójść dalej i wykorzystać RAM do tego i przeprogramować taką maszynę stanów :P
  • Poziom 9  
    Ja pozostanę chwilowo jeszcze przy konstrukcji z case'm póki jej jeszcze w pełni nie zrozumiałem.

    napisałem do tego samego obiektu zupełnie inną architekturę. Wybacz, że integer jest bez zasięgu jeszcze podany. Ale jeszcze nie jestem pewien wartości stałych.

    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    gdzie leży problem? current_state po pierwszym kliknięciu zegara spada do undef...wynika to pewnie z tego iż "next_state" jest niezdefiniowane. Jednakże kompilator nie przełknie sytuacji gdzie bym po resecie nadawał jakąś wartość next_state (swoją drogą, dlaczego? jakie to ma odwzorowanie w fizycznej konstrukcji?)
  • Poziom 14  
    Wartość do sygnału można przypisać tylko w jednym procesie. Z tego co pamiętam to vsim i riviera (nie wiem jak vcs) chyba to ignorują i przy ewentualnym konflikcie wywalają 'X' aczkolwiek przez syntezę to na 100% nie przejdzie.

    Czy Ty w ogóle to resetujesz w TB ? Czy tylko dopisałeś reset?
  • Poziom 9  
    tak resetuje niemalże na początku
  • Poziom 9  
    szczerze użyłem starego Wave-forma dodawanego do starych quatrusów.

    na wejściu clk zapodałem zegar o okresie 20ns, reset krótki stan wysoki trwający jakieś 3ns jeszcze przed pierwszym impulsem zegara.

    teraz piszę z innego komputera to screena nie wrzucę. (później dziś dodam). Symulacja funkcjonalna!
  • Poziom 14  
    Swoją drogą to jestem ciekaw jak ten quartus puszcza symulację skoro proces kombinacyjny blokuje całą symulację ze względu na to, że w każdym stanie zmieniasz licznik, który jest w liście czułości. Teoretycznie powoduje to nieskończoną pętle kombinacyjną, a to z kolei powinno powodować to, że symulator nie powinien ruszyć z czasu 0ns - w tym momencie powinien skakać z delty na delte...
  • Poziom 9  
    aj...przez błąd wkleiłem złą wersję. to była chwilowa modyfikacja żeby sprawdzić efekt.
    edit:
    już wykasowałem. o ile się nie myle to jest orginalna wersja kodu teraz
  • Poziom 14  
    Chyba tego nie rozumiesz.

    0ns:
    current_state = RS1turnUP;
    next_state = RS1turnUP;

    1 delta:
    current_state = IdleAfterRS2;
    next_state = RS1turnUP;

    2 delta:
    current_state = IdleAfterRS2;
    next_state = IdleAfterRS2;

    I spowoduje to, że proces kombinacyjny się już nie uruchomi, bo current_state się nie zmieni. Dobrze, że tam był licznik - problemem była tylko pętla kombinacyjna na liczniku (w każdej kolejnej delcie zmieniał się licznik przez co symulator stanął w czasie 0ns bo non stop wywoływany został ten proces).

    http:// esd.cs. ucr. edu/ labs/ tutorial/ fsm.vhd - tu jest przykład jak to mniej więcej powinno wyglądać. Sygnał 'a' jest na liście czułości, ale zmieniany jest jakby zewnętrznie - niezaleznie od stanów. W Twoim przypadku stan jest zależny od licznika, a licznik od konkretnego stanu i powstaje problem.
  • Poziom 9  
    dziwne, bo wykorzystywałem to w innych modułach i działało. Znam ten przykład...ale dopiero jutro jak będe przy domowym PC, zastosuje się do Twoich wskazówek...napisze jaki był tego efekt.