logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Dlaczego układ w ISE nie działa mimo poprawnej analizy czasowej?

pndemon 07 Wrz 2007 22:00 1727 16
REKLAMA
  • #1 4261024
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    Witam, dotarłem do etapu pracy, w której przeprowadziłem analizę czasową. Niestety jak to zwykle bywa układ nie działa tak jak powinien. Ustawiłem ograniczenie globalne dla linii zegarowej, po wielu zmianach układ udało mi się tak dopasować aby ISE nie zwracało błędu 'time constrain validation'. W moim mniemaniu oznacza to, że opóźnienie na wszystkich ścieżkach pomiędzy elementami synchronicznymi jest nie większe niż długość jednego cyklu zegarowego, co powinno skutkować tym że układ dział tak jak chcę, no ale z jakiegoś powodu tak się nie dzieje.
    Układ projektowałem tak, że nie zawiera żadnych resetów asynchronicznych. Niestety nie wiem co może być powodem błędów podczas symulacji post-place-and-route, a analiza tysięcy sygnałów które pojawiły się w opisie jest chyba niemożliwa, przynajmniej ja nie wiem jak się w tym połapać.
    Może macie jakieś sugestie co może powodować te różnice, albo na co warto zwrócić uwagę.
    Zastanawiałem się jeszcze nad tym, że wg mnie błędy mogą powstawać tylko sytuacje w których sygnał zegarowy dociera do dwóch rejestrów w różnym czasie. Może dodanie DCMa coś zmieni, wiem że te komponenty jakoś tam polepszają zegar.
    I na koniec jeszcze jedno pytane. Wydaje mi się, że syntezer powinien rozpoznać linię zegarową (a jest tylko jeden zegar) i umieścić ten sygnał w liniach dydykowanych , a może się myle.
    A i jeszcze jedno, niestety nie mogę wgrać układu na matryce, bo jest to tylko komponent systemu i nie jest samodzielny, a ponieważ muszę udowodnić że to co napisałem działa, chciałem przeprowadzić symulację czasową.
  • REKLAMA
  • #2 4261517
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    Cytat:
    Witam, dotarłem do etapu pracy, w której przeprowadziłem analizę czasową.
    Niestety jak to zwykle bywa układ nie działa tak jak powinien...

    ise znam bardzo slabo, musialem pracowac z tym programem przez pol roku
    po czym, z ulga, wrocilem do quartusa, ale sadze, ze opisany tu problem nie zalezy
    za bardzo od srodowiska;
    piszesz, ze cos jest zle, ale nie podajesz zadnych informacji co, wiec by ci cokolwiek
    doradzic czy zasugerowac trzeba by chyba miec krysztalowa kule;

    Cytat:
    Ustawiłem ograniczenie globalne dla linii zegarowej, po wielu zmianach układ udało mi się
    tak dopasować, aby ISE nie zwracało błędu 'time constrain validation'.
    W moim mniemaniu oznacza to, że opóźnienie na wszystkich ścieżkach pomiędzy elementami
    synchronicznymi jest nie większe niż długość jednego cyklu zegarowego,

    tez tak to rozumiem
    Cytat:
    co powinno skutkować tym że układ dział tak jak chcę, no ale z jakiegoś powodu tak się nie dzieje.

    pod warunkiem, ze twoj algorytm jest poprawny;
    Cytat:
    Układ projektowałem tak, że nie zawiera żadnych resetów asynchronicznych.

    slusznie;
    Cytat:
    Niestety nie wiem co może być powodem błędów podczas symulacji post-place-and-route,

    obawiam sie, ze nikt ci nic nie podpowie, jesli nie opiszesz owych bledow
    Cytat:
    I na koniec jeszcze jedno pytane. Wydaje mi się, że syntezer powinien rozpoznać linię zegarową
    (a jest tylko jeden zegar) i umieścić ten sygnał w liniach dydykowanych , a może się myle.

    quartus tak robi i jestem swiecie przekonany, ze ise nie jest w tym punkcie gorszy;
    Cytat:
    A i jeszcze jedno, niestety nie mogę wgrać układu na matryce, bo jest to tylko komponent
    systemu i nie jest samodzielny, a ponieważ muszę udowodnić że to co napisałem działa,
    chciałem przeprowadzić symulację czasową.

    nie widze wiekszych problemow z przetestowaniem w fpga modulu, ktory jest fragmentem
    wiekszej calosci;
    w koncu kazdy modul moze byc samodzielnym projektem, a kazda wieksza calosc moze byc
    modulem super-calosci;

    J.A
  • #3 4261937
    sepher
    Poziom 19  
    Posty: 301
    Pomógł: 21
    Ocena: 4
    Jeśli analizowałeś pracę układu przy jakiejś wyższej częstotliwości (np. zbliżonej do tej, z którą ma działać na płytce), to spróbuj obniżyć dla celów testów częstotliwość zegara i zobacz czy w tym przypadku wszystko zadziała. Jeśli nie, to znaczy, że błąd raczej nie jest spowodowany opóźnieniami wprowadzanymi przez logikę. Jeśli tak, to w raportach generowanych przez ISE możesz podejrzeć która ścieżka między wejściem i wyjściem wprowadza największe opóźnienie, łącznie z podziałem na etapy, a także zobaczyć, które sygnały naruszają wprowadzone przez Ciebie ograniczenia (constraints). To jest dobre miejsce, aby zacząć szukanie rzeczy, które można w projekcie poprawić.
  • REKLAMA
  • #4 4261939
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    Błędem jest to ze nie działa tak jak powinien :), tzn. uznałem ze opisywanie to co nie działa jest nieistotne, po prostu układ przetwarza ale nie tak jak powinien, pojawiają się błędne dane, których nie powinno być, inaczej mówiąc zmienia się funkcjonalność.

    Co do testowania z osobna modułów programu, to jakoś tak sceptycznie podchodzę. Nie robiłem nigdy tak, a wydaje mi się, ze jak zmapuję tylko pojedynczy moduł to przeciez jego struktura będzie zupełnie inna nić w połączeniu z resztą układów, chyba zeby zmusić router do umieszczenia tego dokładnie tak samo na matrycy, ale nie bardzo nawet wiem jak.

    Mimo wszystko dzięki za rady i spróbuję tak jak pisałeś, bo i tak nic innego mi nie przychodzi, do głowy. Jedna tylko pozostaje rzecz, otóz gdybym wiedział co moze powodować zmianę zachowania układu, moze udało by mi się zawęzyć krąg poszukiwań.


    Cytat:
    Jeśli analizowałeś pracę układu przy jakiejś wyższej częstotliwości

    Jedyne ograniczenia jakie wprowadzałem to częstotliwość pracy układu, dałem 100 MHz i raport z TRACE'a wygląda tak:
    Timing constraint: TS_clk = PERIOD TIMEGRP "clk" 100 MHz HIGH 50%;
    
     54973 items analyzed, 0 timing errors detected. (0 setup errors, 0 hold errors)
     Minimum period is   9.974ns.


    No nie jest za dobrze, błąd nie zależy od częstotliwości pracy, a co mnie bardziej martwi, to że układ zwraca kod błędu i z tego wnioskuję, że automat nie znajduje się w tym stanie co powinien. Błędy zależą jedynie od rodzaju danych jakie wchodzą do układu. tzn część danych określa sposób przetwarzania układu, jeśli one ulegają zmianie to błędy pojawiają się w innych miejscach, ale w obrębie jedne rodzaju danych, częstotliwość nie ma znaczenia, tzn. testowałem dla 50 MHz i dla 10 MHz, wynik jest taki sam.

    Największy problem, to to że ISE przestawia mi nazwy wszystkich sygnałów, i nie bardzo wiem, jak je później odłowić z tych tysięcy w pliku do symulacji post_place_and_route. Może istnieje jakaś metoda na to?
  • #5 4268430
    griva
    Poziom 17  
    Posty: 203
    Pomógł: 12
    Ocena: 1
    masz jedna domene zgarowa? masz internalne clocki? automaty sa zrobione z opcja safe?

    nie mozesz podgladnac stanu automatu? sciagnij sobie evalucayjna wersje chipscopa i bedzie wszystko jasne.
  • #6 4268657
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    pndemon napisał:
    Błędem jest to ze nie działa tak jak powinien :), tzn. uznałem,
    ze opisywanie tego co nie działa jest nieistotne


    innymi slowy oczekujesz od dobrych dusz usilujacych pomoc wrozenia z fusow;

    pndemon napisał:

    Co do testowania z osobna modułów programu, to jakoś tak sceptycznie podchodzę. Nie robiłem nigdy tak,
    a wydaje mi się, ze jak zmapuję tylko pojedynczy moduł to przeciez jego struktura będzie zupełnie inna niz
    w połączeniu z resztą układów, chyba zeby zmusić router do umieszczenia tego dokładnie tak samo
    na matrycy, ale nie bardzo nawet wiem jak.


    blad moze byc wynikiem wynikiem blednie zakodowanego algorytmu, problemow
    czasowych, przyjeciem niewlasciwych zalozen co do sekwencji wejsc;
    jesli projekt jest bardziej skomplikowany niz prosty automat czy licznik, to masz
    najprawdopodobniej do czynienia z polaczonym efektem kilku bledow na raz;
    im wiecej tych bledow, tym trudniejszy proces odpluskwiania;
    dlatego najpierw weryfikuje sie kazdy modul z osobna i nie ma znaczenia, jak pozniej
    zostanie rozmieszczona logika, przeciez ten twoj uklad nie moze dzialac tylko i wylacznie
    w jednym konkretnym rozlozeniu bramek i rejestrow;

    pndemon napisał:

    Jedna tylko pozostaje rzecz, otóz gdybym wiedział co moze powodować
    zmianę zachowania układu, moze udało by mi się zawęzyć krąg poszukiwań..


    no coz,
    /fusy_mode ON

    pndemon napisał:

    co mnie bardziej martwi, to że układ zwraca kod błędu i z tego wnioskuję, że automat
    nie znajduje się w tym stanie co powinien.


    no to skompiluj sam automat i testuj go mozliwymi stanami wejsc;
    jedna z przyczyn opisanego przez ciebie zachowania moze byc takie zakodowanie FSM:
    jesli A to FSM = X1
    jesli B to FSM = X2
    tymczasem na wejsciu pojawia sie i A i B, wiec FSM idzie do jakiegos nieprzewidzianego
    stanu X1&X2 a potem juz calkiem w maliny;

    pndemon napisał:

    Błędy zależą jedynie od rodzaju danych jakie wchodzą do układu. tzn część danych określa
    sposób przetwarzania układu


    moze RTL nie jest przygotowany na zmiane sposobu przetwazania danych w dowolnym
    momencie, a jedynie gdy jest w konkretnym stanie ?

    /fusy_mode OFF

    powodzenia w debuggowaniu :)

    J.A
  • #7 4269997
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    Cytat:
    pndemon napisał:
    Cytat:
    Błędem jest to ze nie działa tak jak powinien Smile, tzn. uznałem,
    ze opisywanie tego co nie działa jest nieistotne



    innymi slowy oczekujesz od dobrych dusz usilujacych pomoc wrozenia z fusow;


    no nie zupełnie, po prostu stanąłem, przed faktem, że opis funkcjonalny działa dobrze, najdłuższa ścieżka ma poniżej 10 ns, stąd wnioskowałem że jeśli odpalę symulację na częstotliwości mniejszej niż 100 MHz to powinno działać, a ponieważ tak się nie dzieje, to uważam że ISE zrobił z mojego opisu nie to co sądziłem, że zrobi. Największy jednak problem jaki mnie gnębi to, fakt że nie wiem jak analizować symulację modeli, które zostały wygenerowane po place-and-route. Z każdego mojego sygnału robi się 200 innych i nawet nie wiem, za co one odpowiadają, myślałem, że może jest jakiś sposób na odnalezienie się w tym gąszczu.



    Cytat:
    blad moze byc wynikiem wynikiem blednie zakodowanego algorytmu, problemow
    czasowych,

    nie bardzo jestem w stanie sobie wyobrazić jakie to problemy czasowe mogą się pojawić, skoro timing analizer uznał że pomiędzy dwoma sąsiednimi rejestrami najdłuższa ścieżka nie przekracza 10 ns


    no w każdym razie będe jak już mówiłem, próbować posymulować wszystko oddzielnie.

    dzięki za wytrwałość :)
  • #8 4271575
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    Cytat:

    nie bardzo jestem w stanie sobie wyobrazić jakie to problemy czasowe mogą
    się pojawić, skoro timing analizer uznał że pomiędzy dwoma sąsiednimi rejestrami
    najdłuższa ścieżka nie przekracza 10 ns


    to byla uwaga uzasadniajaca, dlaczego warto przetestowac mniejsze kawalki,
    zanim sie zabierzesz za sprawdzanie calosci;
    walczysz wtedy z mniejsza iloscia wrogow na raz;

    Cytat:

    po prostu stanąłem, przed faktem, że opis funkcjonalny działa dobrze


    cos mi umknelo, skad wiesz, ze opis funkcjonalny dziala dobrze ?
    sama symulacja - twoja znajomosc ise jest chyba niewiele wieksza
    niz moja :)
    musisz poswiecic godzine na przeczytanie manuala, nie wierze, ze
    w symulatorze nie ma jakiegos filtra pozwalajacego latwo wybrac
    do wyswietlenia interesujace cie sygnaly;
    inna sprawa, ze w trakcie kompilacji sygnaly moga zmieniac nazwy,
    ale to zwykle oznacza dodanie do nazwy z rtl jakiejs koncowki i dotyczy
    logiki kombinacyjnej, rejestry powinny zostac nieruszone;
    jesli ktores linie sa dla ciebie wazne, a nie mozesz ich znalezc
    [bo optymalizacja je usunela] mozesz takie sygnaly polaczyc do
    top level pinow, nie zostania usuniete i latwo bedzie je znalezc;

    J.A
  • #9 4271871
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    Cytat:
    cos mi umknelo, skad wiesz, ze opis funkcjonalny dziala dobrze ?

    no z tego co ja wiem to w ISE najpierw testuje się opis behawioralny, oczywiście taki, który da się zsyntetyzować, a dopiero potem tzw. post-place-and-route, czyli model zależności czasowych.

    z tego co udało mi się na razie ustalić, to raczej chodzi o problemy wynikające z tego, że myślałem, iż syntezer się domyśli czegoś z mojego opisu, ale tak się nie stało, przykładowo miałem tablicę, do której mają prawo odczytu dwa procesy, myślałem, że zostanie ona stworzona jako pamięć dwuportowa, albo po prostu syntezer zdubluje tą tablicę dla każdego procesu oddzielnie, teraz wiem że coś tu nie działa, więc przebudowuje tego typu konstrukcje
  • REKLAMA
  • #10 4272014
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    co to znaczy: " w ISE najpierw testuje się opis behawioralny"
    zakladasz, ze ise samo cos testuje ?
    zrobiles symulacje funkcjonalna RTL i bylo ok ?
    jesli symulacja funkcjonalna jest w porzadku,
    post-place&route nie, to faktycznie masz problem z timingiem,
    ale wtedy chyba dosc latwo jest porownac wynik obu symulacji
    z znalezc przynajmniej miejsce w ktorym cos szwankuje;

    pndemon:
    > przykładowo miałem tablicę, do której mają prawo odczytu dwa procesy

    wczesniej programowales procesorki, prawda ? :)

    pndemon:
    > myślałem, że zostanie ona stworzona jako pamięć dwuportowa

    jesli ja napiszesz tak jak trzeba, to kompilator sie domysli,
    ze chodzi o dual-port memory;
    jesli sie nie domyslil - zle napisane;
    w ise mozesz uzyc core generator ktory stworzy dla ciebie
    dual-port memory o zadanych parametrach [glebokosc i dlugosc slowa]

    pndemon:
    > albo po prostu syntezer zdubluje tą tablicę dla każdego procesu
    > oddzielnie

    tego nie rozumiem :(
    nijak nie potrafie wymyslic przykladu, w ktorym 2-portowa
    pamiec mozna zastapic 2 pamieciami;
    chyba ze zle pojalem od poczatku, nie chodzi o 2-port RAM,
    przez ktory procesy wymieniaja dane, a o ROM z jakimis stalymi,
    tylko ze w takim przypadku mowienie o dual-port nie ma sensu...
    a moze mam zacmienie :(

    J.A
  • #11 4272070
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    no dobra może nie w ISE, bo używam ModelSim'a :)

    Cytat:
    zrobiles symulacje funkcjonalna RTL i bylo ok ?
    jesli symulacja funkcjonalna jest w porzadku,


    zrobiłem dokładnie tak:
    - napisałem kod w vhdlu
    - syntezator w ISE znał że jest OK
    - wrzuciłem opis behawioralny do ModelSim'a i było ok (oczywiście nie od razu)
    - zrobiłem translacje, mapowanie i routing
    - zacząłem testować model post-place-and-route i nie jest ok

    Wracając do tablicy to tak:
    -była sobie tablica do której jedne z procesów zapisywał dane na początku (zawierające strukturę sieci neuronowych),
    - danych z tej tablicy używały dwa procesy do ładowania do liczników, czyli prościej mówiąc
    licznik_a<=tablica(adres_a)
    licznik_b<=tablica(adres_b)
    -niestety nie działało(tzn. tylko podczas post-place-and-rouute), pojawiały się sygnału typu X
    -uznałem że trzeba to zmienić
    -stworzyłem 2 tablce, do której wgrywam na początku te same dane,
    licznik_a<=tablica_a(adres_a)
    licznik_b<=tablica_b(adres_b)
    - zadziałało

    No i teraz mam dalsze problemy, otóż koprocesor liczy dane ale się myli gdzieś, no i muszę się tego dowiedzieć - oczywiście nie oczekuję że powiesz mi gdzie się myli :)
  • Pomocny post
    #12 4272499
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    pndemon:
    > zrobiłem dokładnie tak:
    /.../
    > - zacząłem testować model post-place-and-route i nie jest ok

    co jest wskaznikiem, ze nie jest ok ?
    widzisz na wyjsciowych pinach danych, ze powinna byc wartosc
    'X', a jest 'Y' ?
    masz jakis uklad, ktory rozpoznaje blad i zapala jakis rejestr ?

    pndemon:
    > licznik_a<=tablica(adres_a)
    > licznik_b<=tablica(adres_b)
    > -niestety nie działało(tzn. tylko podczas post-place-and-route),
    > pojawiały się sygnału typu X

    przychodza mi do glowy dwie przyczyny x-ow;
    - odczytujesz adres, ktory jeszcze nie zostal zapisany;
    [ew. odczytujesz w momencie zapisu]
    - ktorys z sygnalow sterujacych pamiecia
    [chip_select, write_enable, output_enable, etc] jest 'x';

    jesli jeszcze masz zamiar drazyc ten temat, to stosunkowo
    latwo powinno byc znalezc, ktory sygnal 'iksuje' jako pierwszy
    i powoduje iksy na danych;


    roznica w wynikach symulacji funkcjonalnej i czasowej
    moze wynikac stad, ze w testbench napisales, iz dane
    i clock zmieniaja sie w tym samym czasie Tx, dla analizy
    funkcjonalnej jest to ok, dla symulatora post_place&route nie;
    jesli tak jest, to przesun dane o kilka ns. w stosunku do clock;

    JA
  • #13 4272602
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    Ponieważ najlepiej uczyć się na błędach innych (w tym przypadku moich) chciałbym opisać co zrobiłem źle:

    Aby móc przetwarzać dane potrzebuje pewnych informacji na temat struktury sieci neuronowej. Dane te są zapisywane w kilku tablicach o różnych rozmiarach i długości słów (5,4,3,8 bitów). Dane do koprocesora przychodzą poprzez 16-bitowy FSL, stąd nie chcąc wysyłać po jednej dane postanowiłem połączyć je i tak każda z ramek jakie przychodziły zawierała różne dane, np. 8, 5 i 3 bitowe. Łącznie ramek było 12. Problem pojawił się jednak kiedy chciałem wyłuskać poszczególne dane z ramek i przypisać je do odpowiednich tablic, wykorzystałem do tego taki proces (sygnał init_str, to wyjście z licznika):
    str_writing: process(clk, init_str)
    variable a, b: std_logic_vector(1 downto 0);
    variable case_sig: std_logic_vector(4 downto 0);begin
    a := init_str(0)&'1';
    b := init_str(0)&'0';
    	if rising_edge(clk) then
    		if (str_write_en = '1') then
    			if (init_str = "1011") then
    				input_str(3) <= net_datain(4 downto 0);
    				input_str(2) <= net_datain(9 downto 5);
    			elsif (init_str = "1010") then
    				input_str(1) <= net_datain(4 downto 0);
    				input_str(0) <= net_datain(9 downto 5);
    				output_str <= net_datain(14 downto 10);
    			elsif (init_str = "1001") then	
    				af_type(3) <= net_datain(2 downto 0);
    				af_type(2) <= net_datain(5 downto 3);
    				af_type(1) <= net_datain(8 downto 6);
    				af_type(0) <= net_datain(11 downto 9);
    			elsif (init_str = "1000") then	
    				shift_array(3) <= net_datain(3 downto 0);
    				shift_array(2) <= net_datain(7 downto 4);
    				shift_array(1) <= net_datain(11 downto 8);
    				shift_array(0) <= net_datain(15 downto 12);
    			else
    				neuron_str(conv_integer(init_str(2 downto 1)), conv_integer(a)) <= net_datain(7 downto 0);
    				neuron_str(conv_integer(init_str(2 downto 1)), conv_integer(b))<= net_datain(15 downto 8);
    			end if;
    		end if;
    	end if;
    end process str_writing; 


    Niestety już praktycznie przy samym zapisie na niektórych bitach pojawiały się X, postanowiłem więc nieco zmienić podejście.

    Stworzyłem kilka RAMów, z czego każdy miał własny WEN
    
    if rising_edge(clk) then
    		if (init_input_str_wen = '1') then 
    			init_input_str(conv_integer(init_str(1 downto 0))) <= net_datain(12 downto 8);
    		end if;
    		if (data_input_str_wen = '1') then 
    			data_input_str(conv_integer(init_str(1 downto 0))) <= net_datain(12 downto 8);
    		end if;
    		if (output_str_wen = '1') then 
    			output_str <= net_datain(12 downto 8);
    		end if;
    		if (shift_array_wen = '1') then 
    			shift_array(conv_integer(init_str(1 downto 0))) <= net_datain(11 downto 8);
    		end if;
    		if (af_type_wen = '1') then 
    			af_type(conv_integer(init_str(1 downto 0))) <= net_datain(15 downto 13);
    		end if;
    		if (init_neuron_str_wen = '1') then 
    			init_neuron_str(conv_integer(init_str)) <= net_datain(7 downto 0);
    		end if;
    		if (data_neuron_str_wen = '1') then 
    			data_neuron_str(conv_integer(init_str)) <= net_datain(0);
    		end if;
    	end if;
    


    Dodatkowo zadbałem żeby przychodziło dokładnie 16 ramek z danymi, aby uniknąć problemów z adresowaniem. No i teraz w zależności od wartości licznika ustawiam tylko WEN
    case_sig := str_write_en & init_str;
    	case case_sig is
    		when "11111" | "11110" | "11101" | "11100" =>
    			init_input_str_wen <= '1';
    			data_input_str_wen <= '1';
    			shift_array_wen <= '0';
    			af_type_wen <= '1';
    			output_str_wen <= '0';
    			init_neuron_str_wen <= '1';
    			data_neuron_str_wen <= '1';
    		when "11011" | "11010" | "11001" | "11000" =>
    			init_input_str_wen <= '0';
    			data_input_str_wen <= '0';
    			shift_array_wen <= '1';
    			af_type_wen <= '0';
    			output_str_wen <= '0';
    			init_neuron_str_wen <= '1';
    			data_neuron_str_wen <= '1';
    		when "10111" =>
    			init_input_str_wen <= '0';
    			data_input_str_wen <= '0';
    			shift_array_wen <= '0';
    			af_type_wen <= '0';
    			output_str_wen <= '1';
    			init_neuron_str_wen <= '1';
    			data_neuron_str_wen <= '1';
    		when "10110" | "10101" | "10100" | "10011" | "10010" | "10001" | "10000" =>
    			init_input_str_wen <= '0';
    			data_input_str_wen <= '0';
    			shift_array_wen <= '0';
    			af_type_wen <= '0';
    			output_str_wen <= '0';
    			init_neuron_str_wen <= '1';
    			data_neuron_str_wen <= '1';
    		when others =>
    			init_input_str_wen <= '0';
    			data_input_str_wen <= '0';
    			shift_array_wen <= '0';
    			af_type_wen <= '0';
    			output_str_wen <= '0';
    			init_neuron_str_wen <= '0';
    			data_neuron_str_wen <= '0';
    	end case;


    Oczywiście struktura danych w ramkach też uległa zmianie.

    Może komuś się coś takiego nie podobać, ale tylko coś takiego przychodziło mi do głowy, w każdym razie działa tak jak powinno.

    Później jak już to działało, układ liczył, ale okazywało się że błędnie. Wiem to stąd że mam napisany dokładny model w Matlabie operacji matematycznych wykonywanych przez ten koprocesor. Generuje plik z danymi wejściowymi i tym co powinno być na wyjściu. Jak testbench wykryje różnice wywala błąd.

    Cytat:
    roznica w wynikach symulacji funkcjonalnej i czasowej
    moze wynikac stad, ze w testbench napisales, iz dane
    i clock zmieniaja sie w tym samym czasie Tx, dla analizy
    funkcjonalnej jest to ok, dla symulatora post_place&route nie;
    jesli tak jest, to przesun dane o kilka ns. w stosunku do clock;


    Właśnie udało mi się sprawić żeby układ działał poprawnie przy 80MHz, powodem złego liczenia bił za mały hold time na układach pamięciowych, w związku z czym część zapamiętanego sygnału pochodziła z następnej ramki. Ponieważ nie mam procesora którym steruje koprocesorem, to w zasadzie testbench jest MicroBlazem, musiałem tam dodać żeby dłużej trzymał dane na wyjściach, wcześniej zmieniały się one razem z zegarem, stąd układy pamięciowe, które zapisują synchronicznie, nie były w stanie zapamiętać danych.

    Teraz próbuję uruchomić go na 100MHz, ale już są jakieś nowe błędy i jeszcze nie wiem jakie.

    Dzięki za wytrzymałość w moich uciążliwych problemach.


    No i mam kolejny problem. Przy większych częstotliwościach, nawet write_en jest za krótko trzymany. Stąd zastanawiam się jak to zrobić żeby było dobrze. Działa to w tej chwili tak:
    -automat w pewnym stanie (write) chce zapisać coś do pamięci, wystawia więc na szynę dane oraz ustawia write_en
    -przy następnym narastającym zboczu zegarowym następuje zapis
    -no automat oczywiście przechodzi w inny stan i sygnały dane i write_en nie są już takie same
    -niestety proces zapisu do pamięci już się rozpoczął, i nie zakończył bo w trakcie zabrakło syg. data i write_en

    Jedyne co mi przychodzi do głowy to przesunięcie fazy zegara taktującego pamięć np o 270, wtedy zapis rozpocznie się zanim jeszcze automat zmieni swój stan.
    Taki jest mój pomysł, a może nie jest zbyt szczęśliwy, bo wymaga wprowadzenia drugiej domeny zegarowej?
  • #14 4274695
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    niestety obawiam sie, ze na bardziej szczegolowe pytania to ci rozsadnie
    nie odpowiem, bo zarowno vhdl jak i ise sa mi ideologicznie obce :(
    do ise nie mam dostepu, a na sledzenie twojego rtl z manualem po prostu
    nie mam czasu;

    o ile dobrze rozumiem taki kawalek:
    if rising_edge(clk) then
    if (str_write_en = '1') then
    if (init_str = "1011") then
    input_str(3) <= net_datain(4 downto 0);
    input_str(2) <= net_datain(9 downto 5);

    i jesli input_str to twoja dual-port, to nie da sie tego zaimplementowac
    jako pamiec, nie mozesz wpisywac pod dwa adresy jednoczesnie;
    ale pewnie zle rozumiem;
    bardziej 'po ludzku' byloby napisac pamiec jako osobny modul [ew. z parametrami
    definiujacymi dlugosc slowa i glebokosc], przesymulowac czy poprawnie dziala,
    a potem implementowac potrzebna ilosc razy;

    wewnetrzy ram we wspoczesnych ukladach xilinxa czy altery bez problemu
    chodzi powyzej 200MHz, wiec nie wierze, ze masz problem czasowy z pamiecia;
    byc moze kompilator twoje tablice zaimplementowal jako 'register file',
    czyli po prostu zestaw przerzutnilow z multiplekserami, co by moglo
    tlumaczyc klopoty z timingiem;
    z pewnoscia latwo jest to sprawdzic w ise, jak nie w logach kompilacji,
    to w jakims floorplan view;

    > Działa to w tej chwili tak:
    > -automat w pewnym stanie (write) chce zapisać coś do pamięci, wystawia więc na szynę
    > dane oraz ustawia write_en
    > -przy następnym narastającym zboczu zegarowym następuje zapis
    > -no automat oczywiście przechodzi w inny stan i sygnały dane i write_en nie są już takie same
    > -niestety proces zapisu do pamięci już się rozpoczął, i nie zakończył bo w trakcie zabrakło
    > syg. data i write_en

    jesli kompilator naprawde uzyl wew. ramu synchronicznego, to opisany efekt nie wystapi,
    pamiec zapisuje do swoich rejestrow wejsciowych stan linii adresowych, danych i sterujacych
    zboczem zegara i potrzebny jej hold time to picosekundy;
    jeszcze raz zastanow sie nad uzyciem wbudowanego w ise coregen [mam nadzieje, ze dobrze
    pamietam nazwe] do stworzenia pamieci, o ile sie nie myle dostaniesz rowniez przykladowe
    przebiegi czasowe takiej pamieci w html;

    JA
  • #15 4275042
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    Cytat:
    i jesli input_str to twoja dual-port, to nie da sie tego zaimplementowac
    jako pamiec, nie mozesz wpisywac pod dwa adresy jednoczesnie;
    ale pewnie zle rozumiem;

    coś w tym jest co mówisz :), no teraz już wiem że to nie wygląda za dobrze, był to jeden z pierwszych układów jakie napisałem dla tego projektu, i było to jakieś pół roku temu, a ponieważ jest to w zasadzie mój pierwszy poważny projekt, to dopiero się uczę podczas jego tworzenia, teraz jak no to patrzę, to też uważam że nie da się tego zaimplementować :), tzn. syntezer jakoś to łykał, ciekawe co z tego powstawało

    Cytat:
    niestety obawiam sie, ze na bardziej szczegolowe pytania to ci rozsadnie
    nie odpowiem, bo zarowno vhdl jak i ise sa mi ideologicznie obce

    no spoko

    Cytat:
    jesli kompilator naprawde uzyl wew. ramu synchronicznego, to opisany efekt nie wystapi,
    pamiec zapisuje do swoich rejestrow wejsciowych stan linii adresowych, danych i sterujacych
    zboczem zegara i potrzebny jej hold time to picosecundy;


    obawiam się że w tym przypadku korzystam z wbudowanych na matrycę block RAMów, generowanych przez coregen, zresztą podczas symulacji pojawiają się błędu typu "hold time validation", a pomysł z przesunięciem fazy nie był dobry, bo jest problem przy odczycie, że dostaje dane zbyt wcześnie :)
  • #16 4275143
    J.A
    Poziom 28  
    Posty: 596
    Pomógł: 159
    Ocena: 12
    Cytat:

    process(clk, init_str)


    jestes pewnien, ze w sens. list procesu powinien
    byc init_str ?
    bo to oznacza, ze oczekujesz, ze dane beda sie zmieniac
    rowniez po zmianie init_str, asynchronicznie do zegarka;

    po bozemu twoj ram powinien wygladac jakos tak:

       process (clk)
    
        if (piszemy)
             ram(licznik_piszacy) <= dane_z_wejscia
             licznik_piszacy      <= licznik_piszacy + 1;
        else 
             q                    <= ram(licznik_czytajacy)
    /ew./    licznik_czytajacy    <=licznik_czytajacy + 1;
       end process
    
     dane_typuA = q(A-1 downto 0)
     dane_typuB = q(B-1 downto A)
    itd
    


    JA
  • REKLAMA
  • #17 4275198
    pndemon
    Poziom 19  
    Posty: 444
    Pomógł: 35
    Ocena: 18
    oczywiście proces z pierwszego listingu jest zły, pod tym względem też, nie zauważyłem nawet tego wcześniej.

Podsumowanie tematu

✨ Problem dotyczy układu zaprojektowanego w środowisku Xilinx ISE, który mimo poprawnej analizy czasowej i braku błędów w walidacji ograniczeń czasowych (timing constraints) nie działa zgodnie z oczekiwaniami po etapie place-and-route. Układ nie zawiera asynchronicznych resetów, a najdłuższa ścieżka czasowa między rejestrami jest krótsza niż okres zegara (10 ns dla 100 MHz). Pomimo tego w symulacji post-place-and-route pojawiają się błędne dane (sygnały typu 'X'), co wskazuje na problemy funkcjonalne. Wskazano, że przyczyną mogą być błędy w opisie VHDL, szczególnie w implementacji pamięci (tablic) współdzielonych przez dwa procesy, które nie zostały poprawnie zsyntezowane jako pamięć dwuportowa. Rozwiązaniem było rozdzielenie tablic na dwie osobne, co poprawiło działanie. Dyskusja podkreśla konieczność testowania modułów oddzielnie, weryfikacji symulacji funkcjonalnej i czasowej oraz uważnego projektowania pamięci i procesów w VHDL. Zwrócono uwagę na narzędzia takie jak ModelSim do symulacji oraz Core Generator do generowania pamięci dwuportowych. Problemy z analizą sygnałów po place-and-route wynikają z dużej liczby sygnałów i zmiany nazw, co utrudnia debugowanie. Sugerowano także użycie narzędzi do monitorowania sygnałów w czasie rzeczywistym (np. ChipScope). Wskazano, że błędy mogą wynikać z niepoprawnego kodu FSM, niewłaściwych założeń dotyczących sekwencji wejść oraz problemów z sygnałami sterującymi pamięcią (chip_select, write_enable, output_enable). Podkreślono, że poprawna implementacja i testowanie na poziomie modułów jest kluczowe dla uniknięcia problemów w całym projekcie.
Wygenerowane przez model językowy.
REKLAMA