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

FPGA/CPLD Rozbieżność między symulacją a pracującym układem

reinhold 20 Mar 2020 12:51 960 18
  • #1
    reinhold
    Level 11  
    Witam serdecznie,
    Jestem dość początkujący jeśli chodzi o układy programowalne i mam problem polegający na różnicy wyników działania symulacji oraz zaprogramowanego urządzenia. Zaczęło się od tego, że zmontowałem sobie płytkę z cpld xc9572xl, podłączyłem oscylator 40Mhz i zrobiłem dzielnik częstotliwości przez dwa. Układ działa prawidłowo, ale sygnał wyjściowy zmienia się nie na tym zboczu na którym robi to w symulacji. Z obawy, że układ CPLD może być uszkodzony (wymontowałem go ze starego Mikrotika), zrobiłem dokładnie to samo na FPGA (cyclone ii ep2c5t) no i działa to dokładnie tak samo jak na CPLD. Oto mój kod VHLD:

    Code: vhdl
    Log in, to see the code


    Symulację robiłem w ISE Webpack oraz za pomocą GHDL. W każdym przypadku wynik był taki sam. Patrząc na wykresy z symulacji rozumiem to tak, że przy narastającym zboczu 'in1' zmienia się aktualna wartość sygnału 'tmp', a sygnał wyjściowy 'out1' przejmuje starą wartość 'tmp' (jeszcze przed zmianą). Przy opadającym zboczu 'in1' do sygnału 'out1' zapisywana jest aktualna wartość 'tmp'. Z tego powodu sygnał wyjściowy zmienia się zawsze przy narastającym zboczu 'in1'.

    Jednak w zaprogramowanym urządzeniu działa to tak, że sygnał wyjściowy zmienia się przy narastającym zboczu sygnału wejściowego.
    Czy ktoś mógłby mi to wytłumaczyć? Czytałem, że procesy nie mogą modyfikować wartości sygnału na podstawie dwóch rodzajów zmian wartości sygnału który jest w liście czułości procesu. Tj. zmieniać wartości sygnału w procesie w odpowiedzi zarówno na zbocze narastające jak i opadające. Tylko to wytłumaczenie przychodzi mi do głowy, tj. że sygnał 'out1' dostaje wartość 'tmp' dopiero przy kolejnym narastającym zboczu ponieważ zmiana przy opadającym zboczu jest pomijana.

    Czy ktoś mógłby mi wytłumaczyć czy mój tok rozumowania jest poprawny? a jeśli nie, to dlaczego działa to w ten sposób?
    Z góry dziękuję za pomoc.

    symulacja:
    FPGA/CPLD Rozbieżność między symulacją a pracującym układem

    działanie urządzenia:
    FPGA/CPLD Rozbieżność między symulacją a pracującym układem
  • #2
    JarekC
    Level 32  
    1. Dlaczego przypisanie tmp do sygnału wyjściowego dałeś wewnątrz procesu a nie poza nim?

    2. Czy symulację w programie robiłeś po syntezie (Behavioral Simulation) czy po Fit (Post-Fit Simulation)

    3. Czy w raporcie z syntezy masz jakieś ostrzeżenia?

    JarekC
  • #3
    reinhold
    Level 11  
    Przypisanie do tmp jest wewnątrz procesu bo tak było w tutorialu który czytałem. Jak wyrzucę to poza proces to wszystko jest w porządku tj. symulacja pokrywa się z pracą układu.

    Co do symulacji to raczej jest behavioral. Nie jestem pewien, bo wczoraj pierwszy raz instalowałem ISE Webpack Xilinxa, dodałem testbench i po prostu kliknąłem 'run simulation'. Nie za bardzo jeszcze umiem obsługiwać ten symulator (ModelSim od altery z resztą też nie). Czym różnią się te dwa rodzaje symulacji? Ten drugi bardziej odzwierciedla pracę "w urządzeniu"?

    Podczas syntezy nie ma żadnych ostrzeżeń, ani w ISE Webpack, ani w Quartus II.

    Testowo zrobiłem proces który próbuje modyfikować sygnał tmp przy opadającym oraz rosnącym zboczu sygnału in1. Nie udało się go syntezować. Szukałem dalej informacji o tym i wyczytałem że mało który fpga posiada dual-edge flip flop i dlatego takie coś jest niemożliwe, ale kompilator przy syntezie nie zawsze to wykryje i dlatego czasem tworzy się coś co do końca nie działa. To by pasowało do mojej teorii, szukam tylko kogoś kto to potwierdzi, albo wyprowadzi mnie z błędu :)

    EDIT: zrobiłem tę symulację post-fit w ModelSim, na podstawie netlisty wygenerowanej przy syntezowaniu i jest teraz tak jak na urządzeniu. Czyli chyba mam rację z tym flip-flopem który działa tylko przy narastającym zboczu.. ale i tak fajnie, gdyby ktoś bardziej obeznany to potwierdził :)
  • #4
    yakuza_2000
    Level 21  
    Rejestr może reagować na jeden typ zbocza - narastające albo opadające. U ciebie out1 reaguje na oba, więc jest to konstrukcja niesyntezowalna. Jeśli chcesz otrzymać przebieg taki jak na symulacji to out1 możesz dać do osobnego procesu reagującego na zbocze opadające.
  • #5
    J.A
    Level 28  
    reinhold wrote:

    /.../ mam problem polegający na różnicy wyników działania symulacji oraz zaprogramowanego urządzenia /.../



    problem w out <= not tmp; a konkretnie w miejcu napisania
    tej linijki;

    symulacja pokazuje dokladnie napisana funkcje,
    a fizyczny uklad to, co na podstawie kodu da sie zsyntetyzowac;


    jesli jest rising_edge(in1) to
    linia: tmp <= not tmp nie zmienia natychmiast wartosci tmp,
    ale wpisuje nowa wartosc do, powiedzmy, kolejki;
    nastepnie linia: out1 <= tmp przepisuje do out1 wartosc
    aktualna tmp, (czyli jeszcze 'stara');
    symulator dochodzi do konca procesu i dopiero teraz uaktualnia
    zmienne, czyli teraz tmp ma nowa (zakolejkowana) wartosc;

    nastepnie jest falling_edge(in1),
    proces startuje na nowo, bo jest czuly na kazda zmiane sygnalu in1;
    linia: if rising_edge nie wykonuje sie
    ale out1 <= tmp tak, z tym ze tmp ma juz nowa wartosc, ktora byla
    wczesniej zakolejkowana, wiec w symulacji wyglada to tak,
    jakby przepisanie do out bylo na opadajacym zboczu;

    poprawnie byloby przeniesc przepisanie
    out1 <= tmp poza process;

    J.
  • #6
    abant
    Level 11  
    Oczywiście można poprawić program zmieniając go.
    Ale autor powinien wiedzieć co robi źle.

    A złe jest to, że wewnątrz procesu uzależniamy sygnał out1 od zmiennej tmp, której nie ma na liście czułości procesu.

    Dopisanie jej tam automagicznie naprawi wszystkie błędy symulacji.
  • #7
    J.A
    Level 28  
    abant wrote:

    /.../
    A złe jest to, że wewnątrz procesu uzależniamy sygnał out1 od zmiennej tmp, której nie ma na liście czułości procesu.
    Dopisanie jej tam automagicznie naprawi wszystkie błędy symulacji.



    to zdecydowanie nie jest dobry pomysł :)
    a zmiana listy czułości to też jest zmiana programu;

    jeśli zamysłem autora był dzielnik częstotliwości, to jedynym
    błędem jest umieszczenie przypisania: out1 <= tmp;
    w procesie

    J.
  • #8
    trol.six
    Level 31  
    J.A wrote:
    symulacja pokazuje dokladnie napisana funkcje,

    J.A wrote:
    linia: tmp <= not tmp nie zmienia natychmiast wartosci tmp,
    ale wpisuje nowa wartosc do, powiedzmy, kolejki;

    A mnie się zdawało że wewnątrz procesu wszystko wykonuje się sekwencyjnie, a nie w jakiś kolejkach. Skoro "tmp" jest modyfikowana przed przypisaniem do "out1" to "out1" powinien od razu posiadać te wartość.
  • #9
    reinhold
    Level 11  
    dziękuję wszystkim za fachową pomoc, wszystko jest teraz dla mnie całkowicie zrozumiałe :)

    Dodano po 4 [minuty]:

    trol.six wrote:
    mnie się zdawało że wewnątrz procesu wszystko wykonuje się sekwencyjnie, a nie w jakiś kolejkach


    a to nie jest tak że tylko działania na zmiennych działają sekwencyjnie, a na sygnałach tak jak poza procesem, tj. w owych kolejkach?
  • #11
    reinhold
    Level 11  
    poza procesem sygnał przyjmuje wartość od razu (logika kombinacyjna) a w procesie
    sygnał przyjmuje nową wartość po zakończeniu procesu, a zmienna od razu po przypisaniu w procesie.
  • #12
    abant
    Level 11  
    J.A wrote:

    to zdecydowanie nie jest dobry pomysł :)
    J.

    Post byłby wartościowszy, gdybyś napisał czemu tak uważasz.

    Oczywiście, że to zmiana programu. Złego programu nie da się naprawić nie zmieniwszy go.

    Ale błędna symulacja nie jest skutkiem tego, że jakieś przypisanie jest wewnątrz, a nie poza procesem.
    Jest skutkiem nieodpowiedniej listy czułości do zawartości procesu.

    Pozdr.
  • #13
    trol.six
    Level 31  
    No więc proces się zakończył a jak widać na symulacji zmienna dalej nie ma odpowiedniej wartości. Ale podejżewam że wiem w czym może jest "problem", w tym jak traktowane jest rising_edge. Dla symulacji czas rising edge trwa tyle ile trwa stan 1 na wejściu in1.

    Dodano po 1 [godziny] 8 [minuty]:

    http://www.vhdl.renerta.com/source/vhd00062.htm , z tego wynika że proces się kończy gdy mamy zdarzenie na liście czułości, a nie jak to widać zaczyna się, dlatego sygnały czekają na zmiane zegara in1.
  • #14
    J.A
    Level 28  
    trol.six wrote:

    A mnie się zdawało że wewnątrz procesu wszystko wykonuje się sekwencyjnie,
    a nie w jakiś kolejkach


    w ten sposob symulator nasladuje dzialanie rzeczywistej logiki,
    a konkretnie przerzutnika

    jesli sygnaly x i y maja poczatkowo wartosc '0'
    to kod jak ponizej w hardware wykona sie:
    Code: vhdl
    Log in, to see the code


    po pierwszym zboczu zegara x przyjmie wartosc '1', ale y wciaz '0',
    bo ustalanie jedynki na x zajmuje czas, pikosekundy, ale nie zero sekund,
    dlatego na wejsciu y przy pierwszym zboczu zegara bedzie wciaz '0', nie '1';
    ten efekt nazwalem w tym watku kolejka, ale nie jest to poprawny termin
    uzywany w literaturze fachowej;
    dlatego - w symulacji obiekt x bedzie mial wartosc '1' dopiero jak symulator
    dotrze do linii: "end process";
    y przyjmie wartosc '1' dopiero po drugim cyklu zegara;
    =============================

    reinhold wrote:

    a to nie jest tak że tylko działania na zmiennych działają sekwencyjnie,
    a na sygnałach tak jak poza procesem, tj. w owych kolejkach?


    nie, operacje wykonuja sie w sekwencyjnie w procesie,
    procesy i przypisania poza procesem (continous assignment)
    wykonuja sie wspolbieznie, rownolegle;

    jesli w procesie sa zadeklarowane zmienne (variable),
    to one przyjmuja nowa wartosc natychmiast, bez owego opoznienia
    nazwanego przeze mnie kolejkowaniem
    wiec kod:
    Code: vhdl
    Log in, to see the code

    po jednym cyklu zegara zapisalby do x i y wartosc '1';
    (inaczej niz w pierwszym przykladzie)
    variable sa czesto bardzo pomocne, ale trzeba sobie zdawac sprawe
    z tego, ze nie maja odpowiednika w ukladzie logicznym, bez odpowiedniej
    wprawy lepiej ich nie uzywac, by nie zastanawiac sie czemu symulacja
    dziala inaczej niz uklad na plytce;

    reinhold wrote:

    poza procesem sygnał przyjmuje wartość od razu (logika kombinacyjna) a w procesie sygnał
    przyjmuje nową wartość po zakończeniu procesu, a zmienna od razu po przypisaniu w procesie.


    dokladnie tak;
    =============================

    abant wrote:

    Post byłby wartościowszy, gdybyś napisał czemu tak uważasz.


    bo w ukladzie CPLD czy FPGA mamy albo bramki logiczne, albo przerzutniki FF;
    (+ oczywiscie mnostwo innych rzeczy, ale rozmawiamy o samej logice)
    bramki reaguja na zmiane dowolnego wejscia 'natychmiast', tzn z opoznieniem
    czasu propagacji, FF dzialaja na zbocze zegara przepisujac stan wejscia D
    na wyjscie Q;
    nie ma w FPGA struktury, ktora zalezna bylaby od zbocza zegara i poziomu
    jakiegos sygnalu (pomijamy reset w przerzutnikach, to nie ten przypadek)
    jesli nawet dopisanie do listy czulosci sygnalu tmp naprawiloby symulacje,
    to wprawiloby w konfuzje kompilator;
    byc moze, nie wiem i wydaje mi sie to nie warte jakiejs glebokiej analizy,
    ze wynik syntezy moglby zalezec od kompilatora, moze nawet od jego wersji,
    od wybranej FPGA...
    krotko mowiac kod RTL powinien mozliwie scisle opisywac dostepne w ukladzie
    struktury, a nie tylko dzialac poprawnie w symulacji;

    pozdrowienia dla wszystkich uczestnikow watku :)

    J.
  • #15
    abant
    Level 11  
    Nie wiem dlaczego sądzisz, że czym innym jest w tym wypadku uznanie za zegar sygnału tmp niż sygnału in1?

    Kompilatory radzą sobie z tym bez problemu produkując ten sam wynik (sprawdzone dla synplify i lse)

    Co więcej LSE dla orginalnego kodu produkuje:
    35921251 WARNING - top.vhd: tmp should be on the sensitivity list of the process. VHDL-1251

    EDIT:
    Dla nieprzekonanych dodaję do poczytania rozważania na ten temat:
    https://electronics.stackexchange.com/questio...uestion-about-sensitivity-list-in-vhdl/333307
    https://vhdlwhiz.com/sensitivity-list/
  • #16
    J.A
    Level 28  
    abant wrote:
    Nie wiem dlaczego sądzisz, że czym innym jest
    w tym wypadku uznanie za zegar sygnału tmp niż sygnału in1?


    nie wiem, czy dokladnie rozumiem pytanie;
    sygnal tmp tym rozni sie od in1, ze in1 jest w linii:
    if rising_edge(in1) then
    a tmp nie;
    ---------------------------------

    abant wrote:

    Kompilatory radzą sobie z tym bez problemu produkując ten sam wynik
    (sprawdzone dla synplify i lse)


    owszem, co oznacza tyle, ze kompilator (a wlasciwie jego tworcy)
    'wiedza lepiej, co uzytkownik mial na mysli',
    to nie jest dobra praktyka, by zdawac sie na to, ze narzedzie poprawi nasze
    'niedokladnosci' w opisie;


    FPGA/CPLD Rozbieżność między symulacją a pracującym układemtop_rt..jpg Download (28.46 kB)

    tu jest rtl view (quartus) dla 3 wersji kodu, oryginalna, z tmp2 w sensivity list
    i z przypisaniem tmp3 <= not(tmp3); poza procesem;
    kompiler za kazdym razem produkuje ta sama logike nie dlatego, ze kazdy kod jest
    funkcjonalnie taki sam, ale dlatego, ze program 'domyslil' sie poprawnie
    intencji autora;

    jak ty zapisalbys w vhdl przedstawiony powyzej schemat?

    abant wrote:

    Co więcej LSE dla orginalnego kodu produkuje:
    35921251 WARNING - top.vhd: tmp should be on the sensitivity list of the process. VHDL-1251


    to jest automat, wszystko co jest po prawej stronie przypisan w process,
    a jest poza if (rising_edge(...)) then ... end if;
    ma byc w sensivity list;

    przyklad podany przez autora watku jest skrajnie prosty, wiec kompilator nie
    ma problemu z rozpoznaniem o jaka funkcje chodzi, proponowane przez ciebie
    dodanie tmp do listy czulosci nic nie zmieni w syntezie (na szczescie)
    a zmieni wynik symulacji na zgodny z przebiegami na fizycznej plytce;

    jednakze podobny zabieg przy bardziej skomplikowanym projekcie moglby
    doprowadzic do trudno wykrywalnych bledow, dlatego protestuje przeciwko
    takiemu 'leczeniu', choc skutecznemu w tym konkretnym przypadku;

    jeszcze raz - zastanow sie i napisz sobie poprawny wg. ciebie opis
    logiki dolaczonych schematow, a wlasciwie schematu, bo wszystkie sa
    identyczne;

    J.
  • #17
    abant
    Level 11  
    Cóż, oczywiście myślę, że poprawna jest moja wersja. I potwierdzają to podesłane później linki.
    Wydaje mi się także, że Twój sposób rozumowania wynika z utożsamiania listy czułości procesu i bloku always z verilog'a.
    Więc chyba każdy z nas pozostanie przy swoim.
    A głupi automat rozumie nas obu ;-)

    FPGA/CPLD Rozbieżność między symulacją a pracującym układem
    Moja logika jest prosta:
    1. 3 sygnały w kodzie -> 3 sygnały w schemacie
    2. Przypisanie na zboczu -> rejestr, poza -> przewód
    3. Po co przenosić operacje z sygnałem poza proces, skoro ten sygnał nie występuje poza nim. -> Enkapsulacja
    4. Autor ma błędy w symulacji, nie w syntezie -> lista czułości.
    5. Nasza wymiana poglądów jest tematem ubocznym w stosunku do pytania autora,
    niezależnie kto ma rację co do poprawności kodu.
  • #18
    trol.six
    Level 31  
    Wasze niuanse wynikają z tego że vhdl który jak nazwa mówi stanowi opis sprzętu, wcale takim nie jest. Gdyby tak było:
    1. nie byłoby rozbieżności pomiędzy symulacją a realnym układem
    2. kod byłby syntezowalny zawsze

    VHDL sie rozdmuchał, i każdy ma swoją wersje zdarzeń. Ja pisząc w VHDL czasem dochodze do absurdów ale zwyczajnie nie mam czasu tego na forum prezentować.

    J.A wrote:

    po pierwszym zboczu zegara x przyjmie wartosc '1', ale y wciaz '0',
    bo ustalanie jedynki na x zajmuje czas, pikosekundy, ale nie zero sekund,
    dlatego na wejsciu y przy pierwszym zboczy zegara bedzie wciaz '0', nie '1';
    ten efekt nazwalem w tym watku kolejka, ale nie jest to poprawny termin
    uzywany w literaturze fachowej;
    dlatego - w symulacji obiekt x bedzie mial wartosc '1' dopiero jak symulator
    dotrze do linii: "end process";
    =============================


    Twoje wyjaśnienie jest pokręcone jak cały VHDL ;)

    Myśle że chodzi po prostu o to że sygnały czekają na koniec procesu z listy czułości.
    Jakby ktoś nie widział linka:
    http://www.vhdl.renerta.com/source/vhd00062.htm

    Myśle że zrobienie symulacji kodu poniżej co nie co wyjaśni.
    Mamy jedno przypisanie wewnątrz procesu a drugie na zewnątrz.
    I które będzie pierwsze?

    Code: vhdl
    Log in, to see the code
  • #19
    abant
    Level 11  
    Niestety nie wyjaśni nic
    Symulacja może być niepoprawna ze względu na brak tmp na liście czułości ;-(