Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[FPGA][ALTERA/INTEL] Simulation Waveform - nieoczekiwane stany Unknown Forcing

matti0010 23 Apr 2019 20:59 378 11
  • #1
    matti0010
    Level 11  
    Witam,

    Mam problem z symulacją w Quartus pamięci RAM, która jest komponentem IP (megafunkcja). Wszystko jest dobrze jeżeli wykonuję symulację samej pamięci RAM. Problem pojawia się gdy symuluję większą część układu, w skład której wchodzi pamieć RAM. Próbowałem różnych ustawień megafunkcji i samego Quartusa. W efekcie widziałem różnego rodzaju zmiany ale nadal pojawiało się sporo Unknown Forcing (X). Można to zobaczyć na poniższej grafice (jest to wyjście pamięci RAM):
    [FPGA][ALTERA/INTEL] Simulation Waveform - nieoczekiwane stany Unknown Forcing

    Mam taki problem tylko z pamięciami RAM.
    Pamięć RAM jest zainicjalizowana, tak samo wszystkie "zmienne" w kodzie.
    Co więcej, układ ten po wgraniu na rzeczywisty układ FPGA (płytki DE0-Nano i DE10-Nano) działa bez zarzutu. Problemem jest tylko sama symulacja.

    Czy ktoś spotkał się z takim problemem i wie jak go rozwiązać?
    Nie znalazłem niczego użytecznego w google. Widziałem, że inni mieli podobny problemy ale nie znalazłem odpowiedzi, która w moim przypadku okazałaby się pomocna.
  • Helpful post
    #2
    yakuza_2000
    Level 21  
    RAM wygenerowany w Quartusie jest inicjalizowany plikiem *.hex. Jeśli w folderze z symulacja nie ma tego pliku(albo nie pokazałeś narzędziu gdzie może szukać), w pamięci zostaną wartości X.
  • #3
    matti0010
    Level 11  
    RAM mam zainicjalizowany. Testowałem to zarówno plikiem *.mif jak i *.hex.
    Pliki wskazałem (raczej) dobrze. W pamięci ROM, którą podobno inicjalizuję mam takie wartości jakich oczekuję.

    Czy jest możliwe, że mam coś źle ustawione w samym Quartusie? Może trzeba przestawić jakieś parametry symulacji?
  • Helpful post
    #4
    yakuza_2000
    Level 21  
    No to jest jeszcze opcja ze sam wpisujesz te X do pamięci :wink: . Pokaż co się dzieje na interfejsie do zapisu RAM. Najlepiej to pokaż przebiegi ze wszystkich wejść/wyjść ramu.
  • Helpful post
    #5
    User removed account
    Level 1  
  • Helpful post
    #6
    yakuza_2000
    Level 21  
    atari_robbo wrote:
    Niezainicjowana pamięć to zazwyczaj 'U'


    W Verilogu niezainicjowana pamięć będzie mieć X. Ale fakt, najbardziej prawdopodobne jest to że autor zrobił zwarcie ;p
  • #7
    matti0010
    Level 11  
    Jeżeli chodzi o sam kod, to wygląda on tak (przepraszam, za bałagan w kodzie ale ciągle go zmieniam szukając problemu więc nie jest posprzątany...):

    Plik MAIN:
    Code: verilog
    Log in, to see the code


    PLLR_RAM:
    Code: verilog
    Log in, to see the code


    PLLR_GENERATOR:
    Code: verilog
    Log in, to see the code


    Plik *.mif do inicjalizacji:
    Code: verilog
    Log in, to see the code


    I drugi alternatywny plik *.hex do inicjalizacji:
    Code: verilog
    Log in, to see the code


    Według mnie plik *.mif jest bardziej czytelny.

    Generator jest zwykłym licznikiem, który ma się "przekręcić" po osiągnięciu maksymalnej wartości (16 cykli) i tym samym jest on generatorem adresu dla pamięci RAM.
    Najpierw zapisuję dane do pamięci RAM (wejście "in_UKOM" w pliku MAIN) a później chcę odczytywać dane z tej pamięci.
    Wiem, że to fizycznie działa bo podpiąłem analizator stanów logicznych, wgrałem kod na płytki DE0-Nano i DE10-Nano a następnie widziałem, że mam na wejściu i wyjściu pamięci RAM to co chcę. Problem więc leży tylko w symulacji a nie działaniu.

    Mam kilka różnych pamięci RAM w całym układzie i każda w pewnym momencie zaczyna bez powodu wyrzucać stany "X"...

    Symulację pokazującą wejścia i wyjścia wrzucę jak ją ponownie wygeneruję. Niestety trochę to to trwa dla całego układu.

    Nie wiedziałem o opcji "Trace X". Spróbuję znaleźć o tym jakieś informacje i wskazówki jak można odpalić to śledzenie w Quartus. Chyba, że tutaj ktoś napisze mi krótki "idiotoodporny" poradnik :)
  • #8
    yakuza_2000
    Level 21  
    Po pobieżnym przeglądnięciu kodu nie widzę żeby to w tym module powstały X, musiały raczej "przyjść" z zewnątrz. Robisz symulacje samego modułu PLLR_MAIN? Czy ten moduł jest gdzieś użyty?

    Plus parę uwag:
    1) Ogólnie ten kod nie jest napisany w stylu "FPGA" :wink:
    Na przykład:
    Code: verilog
    Log in, to see the code


    Ten licznik jest taktowny zegarem 'triger', który jest generowany przez bramkę XOR. Normalnie chcemy tak zaprojektować układ, żeby licznik był taktowany globalnym zegarem np clk, a jego inkrementacja następowała w odpowiednim warunku np:

    Code: verilog
    Log in, to see the code


    Oczywiście ten kod nie zastępuję twojego kodu, bo trzeba tak wygenerować sygnał 'triger', żeby pojawiał się tam stan niski na jeden cykl zegara, gdy (triger_UKOM xor triger_KPI) zmieni stan z 1 na 0.
    Przy okazji, poczytaj o blocking/non-blocking assignments.

    2) Dlaczego masz pamięć dual clock? I co robi moduł BUFOR_1BIT?
    3) Zamiast
    Code: verilog
    Log in, to see the code

    możesz napisać
    Code: verilog
    Log in, to see the code

    co jest bardziej czytelne. Analogicznie jest z nand.
    4)Tak z ciekawości, robisz ten projekt na uczelnie/do pracy/hobbystycznie?
  • #9
    matti0010
    Level 11  
    Jest użyty w większym układzie (znacznie większym). Robiłem jednak symulacje tego układu od strony wejść PLLR_MAIN i tam nie było ani jednego "X". Postaram się jutro wieczorem wrzucić symulację, dziś już nie dam rady.

    Wszelkie uwagi mile widziane :) jestem głównie samoukiem więc pewnie robię sporo błędów.

    Specjalnie chciałem dać bramkę XOR bo próbuję odseparować się od globalnego CLK. Teraz jeszcze nie do końca mnie się to udało ale w kolejnej wersji tego układu planuję "wyrzucić" jak najwięcej linii globalnego CLK a te co zostaną chcę "bramkować". Niemniej jednak rozumie o co chodzi i dziękuję za uwagę :)

    BUFOR_1BIT opóźnia sygnał o jeden cykl zegara. Przedrostek 1BIT mówi mi, że to bufor 1-bitowy. Mam jeszcze kilka innych buforów. Dałem go teraz tylko na czas testów.
    Mam dual clock tylko z powodu testów i prób odpalenia tego ustrojstwa. Wcześniej miałem single clock bez rejestru na wyjściu pamięci (jest mi zbędne "bramkowanie czy raczej rejestrowanie :) " wyjścia).

    Jestem elektronikiem, dla mnie bardziej intuicyjne są opisy XOR, NAND, AND, OR, NOR itd. bo odzwierciedlają jak najbardziej architekturę, którą sobie zaprojektowałem przed rozpoczęciem pisania kodu. Gdybym pisał kod na mikrokontroler czy PC to na pewno używałbym "^".


    Pośrednio na uczelnie i hobbystycznie. Chcę się douczyć jak najwięcej i zrobić dekoder LDPC (kodowanie LDPC wykorzystywane jest w np. telewizji cyfrowej (WiMax, DVB-T2, DVB-S2, itd.) czy 5G więc temat jest całkiem ciekawy). Robię to w ramach projektu kilkuletniego na uczelnię, ale sam temat stał się moim hobby i w sumie najbardziej zależy mi na nauczeniu się jak najwięcej :) I na uruchomieniu tej wrednej symulacji... potrzebuję jej do uruchomienia analizy poboru energii (Power Analyzer).
  • #10
    matti0010
    Level 11  
    Wrzucam grafiki z symulacji:
    [FPGA][ALTERA/INTEL] Simulation Waveform - nieoczekiwane stany Unknown Forcing [FPGA][ALTERA/INTEL] Simulation Waveform - nieoczekiwane stany Unknown Forcing

    Linie sygnałowe z przedrostkiem PLLR pokazują sygnały wejściowe i wyjściowe modułu PLLR_MAIN. Reszta to pozostałe sygnały całego układu, które obecnie nie są istotne.

    Jeżeli chodzi o nazewnictwo pomiędzy symulacją a modułem PLLR_MAIN to:
    Code: verilog
    Log in, to see the code


    Tak się zastanawiam, chyba to bramka NAND wszystko psuje w PLLR_MAIN.
    Muszę się nad tym zastanowić.
  • #11
    yakuza_2000
    Level 21  
    Z tych przebiegów wynika że te X przychodzą z zewnątrz - widać je na wejściu in_UKOM[4:0]. Do tego wygląda że wszystko się popsuło gdy sygnał "in_sterowanie" zmienił stan na '0'.

    Dlaczego chcesz się odseparować od globalnego CLK? FPGA są tak zaprojektowane żeby używać kilku, kilkudziesięciu globalnych/regionalnych zegarów. Wtedy osiągniesz największą wydajność. Zegary które są generowane przez logikę kombinacyjną są złą praktyka - takie zegary mogą mieć hazardy (jeśli nie zrobisz odpowiedniego bramkowania), do tego trudniej jest spełnić wymagania czasowe.


    Ogólnie myślę że dekoder LDPC to trochę za gruba sprawa dla początkującego, lepiej zacząć od czegoś prostszego :wink:.
  • #12
    matti0010
    Level 11  
    "in_sterowanie" informuje dekoder, że skończono transmitować dane z zewnątrz do układu.

    Chcę spróbować zrobić częściowo asynchroniczny dekoder. Poza tym chcę odciąć się od zegarów w pewnym stopniu aby osiągnąć tę asynchroniczność.

    Co do LDPC. Mam już kilka wersji tego dekodera i wszystkie działają ;) Oczywiście wszystkie sam zrobiłem od zera.
    Jasne, mają kilka bolączek ale to dopiero etap developerski. Czasem wychodzą małe "smaczki", które przeoczyłem. Niestety ale LDPC są dość wymagające pod kątem architektury i nie zawsze wszystko wyłapię od razu. Tym bardziej, że testuję różne podejścia w trakcie robienia tego.
    Mam nawet skrypt, w którym wpisuję sobie żądane parametry dekodera i całość jest generowana (skrypt mojego autorstwa).
    Ogólnie fajna zabawa jest z tym.

    Poprawiłem sygnał wren, dodałem parę drobnych rzeczy, kilka odjąłem i teraz działa:
    [FPGA][ALTERA/INTEL] Simulation Waveform - nieoczekiwane stany Unknown Forcing

    Od 2 tygodni sprawdzałem wszystko tylko nie sygnał wren... Ale jestem teraz zły sam na siebie :D

    Jeszcze sporo pracy mnie czeka ale problem jest rozwiązany. Muszę uważać na sygnał "wren".

    BARDZO DZIĘKUJĘ ZA POMOC. WSZYSTKIE UWAGI I PYTANIA DOPROWADZIŁY DO ZNALEZIENIA ROZWIĄZANIA :D