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.

Pamięć flash M28W640FCB, błędy danych przy zapisie?

ronaldo_poznan 19 Sty 2008 12:19 1698 9
  • #1 19 Sty 2008 12:19
    ronaldo_poznan
    Poziom 10  

    Witam!
    Mam, pytanie czy ktoś z Was korzystał z tej pamięci? Kończę właśnie projekt i jedynym moim problemem w tej chwili jest właśnie ta pamięć...
    Chciałem Was zapytać, czy fakt pomyślnego zakończenia operacji zapisu może mimo wszystko powodować błąd zapisu? Tzn. chodzi mi o to, że zapisuję w tej pamięci stan
    kilku liczników. Następnie po wyłączeniu zasilania odczytuję z pamięci ich stan i tu pojawia się problem, ponieważ czasem wartości się nie zgadzają. Dzieje się tak prawie zawsze gdy po włączeniu zasilania, poprawnym odczycie danych, następnie zapisuję do pamięci nowe wartości liczników. Inaczej, gdy odczytuje i zapisuję stale te same wartości, nic się złego nie dzieje. Gdy staram się zapisać nowe wartości, liczniki się nie zgadzają.
    Macie jakieś sugestie? Czy możliwe że mimo sprawdzenia statusu operacji zapisu, dane się nie zgadzają?

    0 9
  • #2 24 Sty 2008 18:00
    ijon_tichy
    Poziom 13  

    Witaj
    Nic nie napisałeś czy stosujesz jakiś miękki procesor czy też napisałeś własny kontroler w HDLu. Jeśli programujesz w C być może twój kompilator optymalizuje sobie kod i zamiast naprawdę czytać komórkę pamięta zmienną którą zapisywałeś. Jeśli zaś piszesz w HDLu sprawa wydaje się poważniejsza. Napisz coś więcej , może poradze. (kilka tygodni walczyłem z SRAMem podpiętym do Niosa).

    0
  • #3 27 Sty 2008 19:56
    ronaldo_poznan
    Poziom 10  

    No cześć!
    Więc, napisałem własny kontroler-sterownik pamięci w vhdl'u.
    Walczę z nim już jakiś czas, generalni jest to w tej chwili mój ostatni problem. Wyczaiłem, już że problem nie tkwi w samej pamięci. Tylko bardziej w tym co napisałem.
    Wyjaśnię może jak to wszystko zrobiłem. Do pamięci zapisuję stany 4 liczników kilometrów - rejestrów o długości 34, 26 i dwa po 23 bity.
    Jako że wymiana danych z pamięcią odbywa się za pośrednictwem magistrali 16 bitowej. Dane z pierwszego licznika zapisuję pod adresami 0, 1 i 2. Z drugiego 3 i 4, itd. Każde 16 bitów zapisuję jako pojedyńczą operację programowania. Dane do zapisu, a także komendy które wysyłam do pamięci wybieram za pośrednictwem multipleksera. Sygnały do sterowania pamięcią (enable, write, output enable) generuje maszyna stanów. Wyborem danych do zapisu, uruchomieniem maszyn odczytujących, zapisujących steruje kolejna maszyna stanów.
    Tak wygląda po krótce to co napisałem. Mniej więcej jestem pewien że dane wysypują mi się gdzieś pomiędzy rejestrami a pamięcią. Opóźnienia?
    Na multiplekserze?
    Dzięki z góry za jakieś rady

    0
  • #4 27 Sty 2008 23:40
    J.A
    Poziom 27  

    ronaldo_poznan napisał:
    Dzięki z góry za jakieś rady

    trudno o jakies rady, jesli nie pokazesz kodu;
    uzyj symulatora/chipscope do sprawdzenia gdzie masz klopoty;
    jezeli wyjscie z multipleksera idzie bezposrednio do pamieci,
    dodaj rejestry, tzn. zapisuj w rejestrach dane i adres, a potem
    generuj za pomoca fsm sygnaly sterujace pamiecia [enable, write];

    J.A

    0
  • #5 28 Sty 2008 09:53
    [g.d.]
    Poziom 18  

    ronaldo_poznan napisał:
    Mniej więcej jestem pewien że dane wysypują mi się gdzieś pomiędzy rejestrami a pamięcią. Opóźnienia?
    Na multiplekserze?
    Dzięki z góry za jakieś rady

    Jeśli opóźnienia to sumaryczne z zasobów połaczeniowych, I/O i ścieżek na poziomie "miedzi" za ostatnimi rejestrami a przed pamięcią.

    Zadbaja żeby ostatnie (i pierwsze) rejestry prowdzące do i z pamięci w układzie FPGA trafiły do bloków IO.

    Rozumiem że masz już constraint na częstotliwość zegara, w kwestii opóźnień bloki IO mają czasem filtr dolnoprzepustowy który można wyłączyć i zwykle programowalną wydajność prądową.

    Przeczytałem cały watek i dalej nie wiem do jakiej rodziny nalezy ta kość FPGA/CPLD.

    0
  • #6 28 Sty 2008 13:33
    ronaldo_poznan
    Poziom 10  

    No hej! Dzięki za zainteresowanie... Więc, programuję kość Spartan 3 xc3s200.
    Co do kwestii kodu, to wyjaśnię może od początku. Minimoduł firmy Propox, nad którym walczę ma na pokładzie kość flash - wyżej wymienioną oraz kość ram - z której nie korzystam. Ram i flash połączone są ze sprartanem magistralą 16 bitową, z której 8 bitów jest wyprowadzone w postaci pinów na płytce. Do 4 z tych 8 bitów mam podłączonego LCD. Od razu uprzedzę pytania, czy ram mam wyłączony i czy przypadkiem nie gadam z LCD podczas zapisu do flasha. Jedyne co to sygnał między częścią sterującą flashem a lcd'kiem jest multipleksowany w taki sposób:

    Code:
    --JESLI FLASH_EN='1', to odczyt i zapis do flasza
    
    --jesli FLASH_EN='0', to zapis z lcd
    process (FLASH_EN, LCD,DIN)
    begin
       if (FLASH_EN='0') then
          dane_do_zapisu(3 downto 0) <= (others => '0');
          dane_do_zapisu(7 downto 4) <= LCD;
          dane_do_zapisu(15 downto 8) <= (others => '0');
       else
          dane_do_zapisu <= DIN;
       end if;
    end process;               

    FLASH_DATA <= dane_do_zapisu when RD = '0' else "ZZZZZZZZZZZZZZZZ";
       DOUT <= FLASH_DATA;

    FLASH_DATA jest oczywiście dwukierunkowe. DOUT to dane odczytane z flasha, a DIN to, to co chce zapisać.

    Teraz kwestia, tego co chcę wysłać do flasha. Kolejny multiplekser, przełączający poszczególne fragmenty liczników oraz komendy.
    Code:
    --dekoder danych do zapisu
    
    process (co_zapisac_sig, przebieg_sig, trip_sig, pb_sig, lpg_sig, komenda_sig)
    begin
       case co_zapisac_sig is
       when "0000" =>
          if (komenda_sig='0') then
             DOUT <= przebieg_sig(15 downto 0);
          else
             DOUT(7 downto 0) <= program;
             DOUT(15 downto 8) <= "00000000";
          end if;
       when "0001" =>
          if (komenda_sig='0') then
             DOUT <= przebieg_sig(31 downto 16);
          else
             DOUT(7 downto 0) <= erase;
             DOUT(15 downto 8) <= "00000000";
          end if;
       when "0010" =>
          if (komenda_sig='0') then




             DOUT(1 downto 0) <= przebieg_sig(33 downto 32);
             DOUT(15 downto 2) <= (others => '0');
          else
             DOUT(7 downto 0) <= blck_unlq;
             DOUT(15 downto 8) <= "00000000";
          end if;
       when "0011" =>
          if (komenda_sig='0') then
             DOUT <= trip_sig(15 downto 0);
          else
             DOUT(7 downto 0) <= rd_sign;
             DOUT(15 downto 8) <= "00000000";
          end if;
       when "0100" =>
          if (komenda_sig='0') then
             DOUT(10 downto 0) <= trip_sig(26 downto 16);
             DOUT(15 downto 11) <= (others => '0');
          else
             DOUT(7 downto 0) <= confirm;
             DOUT(15 downto 8) <= "00000000";
          end if;
       when "0101" =>
          if (komenda_sig='0') then
             DOUT <= lpg_sig(15 downto 0);
          else
             DOUT(7 downto 0) <= rd_array;
             DOUT(15 downto 8) <= "00000000";
          end if;
       when "0110" =>
          DOUT(6 downto 0) <= lpg_sig(22 downto 16);
          DOUT(15 downto 7) <= (others => '0');
       when "0111" =>
          DOUT <= pb_sig(15 downto 0);
       when others =>
          DOUT(6 downto 0) <= pb_sig(22 downto 16);
          DOUT(15 downto 7) <= (others => '0');
    end case;

    end process;

    Wyjście DOUT z powyższego mux'a jest połączone z wejściem DIN tego pierwszego. Sygnał co_zapisac_sig pochodzi z muxa ktory wybiera czy wysyłam do flasha komendy z maszyny kasującej bloki czy z maszyny sterującej zapisem. Sygnał komenda_sig dla maszyny kasującej jest zawsze 1 a dla zapisującej jest 1 dla wysyłania komend, natomiast 0 dla wysyłania stanów liczników. Komendy są zadeklarowane jako stałe 8 bitówe. Ponieważ podejrzewałem również że liczniki podczas zapisu mi się w jakiś dziwny sposób inkrementują, przed zapisem dla pewności zatrzaskuję ich wartości w rejestrach, ale przed tymi wszystkimi mux'ami.
    Co do symulowania tego wszystkiego, to. Mam ze strony STM opis w VHDL'u tej pamięci flash. Więc wszystko przesymulowałem oczywiście. I byłem pewien że działa, do póty do póki nie sprawdziłem tego realnie. Generalnie błędy w zapisie pojawiają się mniejwięcej w 1/3 przypadków przy zapisywaniu nowych danych. Bo jeżeli po odczycie nie zmienił się stan liczników, wówczas wszystko jest zapisywane poprawnie.
    Mam nadzieję że wyjaśniłem wszystko.
    Cytat:
    Rozumiem że masz już constraint na częstotliwość zegara, w kwestii opóźnień bloki IO mają czasem filtr dolnoprzepustowy który można wyłączyć i zwykle programowalną wydajność prądową.

    Nie rozumiem tego o zegarze... Co do samych linii I/O to rozumiem.
    Czy chodzi Ci o to? Z ucf'a?
    Code:
    NET "CLK50MHZ" TNM_NET = "CLK50MHZ";
    
    TIMESPEC "TS_CLK50MHZ" = PERIOD "CLK50MHZ" 20 ns HIGH 50 %;

    0
  • #7 29 Sty 2008 01:52
    J.A
    Poziom 27  

    ronaldo napisał:

    Code:

    process (FLASH_EN, LCD,DIN)
    begin
       if (FLASH_EN='0') then
          dane_do_zapisu(3 downto 0) <= (others => '0');
     /........../

    process (co_zapisac_sig, przebieg_sig, trip_sig, pb_sig, lpg_sig, komenda_sig)
    begin
       case co_zapisac_sig is
       when "0000" => /..../


    celowo stworzyles calkiem spora logike asynchroniczna ?
    generalnie to brakuje mi jakiegos sygnalu zegarowego,
    ktory synchonizowalby to wszystko;

    Cytat:
    Więc wszystko przesymulowałem oczywiście.

    symulacja funkcjonalna, podejrzewam ? czy zrobiles takze
    timing simulation ?

    istotna sprawa jest polozenie sygnalow kontrolnych do pamieci
    [w czasie] wzgledem adresu i danych, czego nie ma w tych kawalkach
    kodu;

    J.A

    0
  • #8 29 Sty 2008 09:23
    ronaldo_poznan
    Poziom 10  

    Generalnie, to korzystałem z różnych przykładów, z ISE i z XST, no i nie widziałem multiplekserów popędzanych sygnałem zegarowym. Ale, próbowałem coś takiego zrobić no i w efekcie zrobiło się jeszcze gorzej, tzn. każdy zapis był obarczony błędem.
    Co do symulacji czasowej, to wstyd się przyznać, ale nie wiem jak ją wykonać, w ISE?

    0
  • #9 29 Sty 2008 13:23
    J.A
    Poziom 27  

    ronaldo napisał:
    Co do symulacji czasowej, to wstyd się przyznać, ale nie wiem jak ją wykonać

    tu ci nie pomoge, musisz poczekac na wsparcie jakiegos uzytkownika ise,
    a takich tu wiekszosc, albo przestudiowac user manual;

    ronaldo napisał:
    /.../próbowałem coś takiego zrobić no i w efekcie zrobiło
    się jeszcze gorzej


    tak jak to napisales nie ma prawa dzialac w ogole;
    podejrzewam, ze 'dziala' ci przez przypadek, bo nie wyswietlasz
    na lcd danych odczytanych z pamieci, a cos co jest jeszcze w fpga;

    zrob moze tak - zacznij od modulu, ktory wpisuje pod pare adresow
    dane z jakiegos licznika, i drugi modul, ktory odczytuje te same adresy
    i wyswietla dane na lcd;
    zapisz pamiec modulem pierwszym, wgraj modul drugi, odczytaj;
    dzieki temu sprawdzisz transmisje fpga <=> pamiec;
    ja to bedzie dzialac, dobudujemy reszte;

    J.A

    0
  • #10 29 Sty 2008 15:23
    pndemon
    Poziom 19  

    Symulacja czasowa w ISE jest dosyć prosta, musisz po prostu wygenerować tzw. "Post Place and Route Simulation Model". Opcję tą znajdziesz na liście 'Processes' (po lewej na ekranie) w dziale 'Implement Design' => 'Place & Route'. Opcję tą można zaznaczyć na stałe klikając prawym na 'Implement Design' => properties => place & route properties.

    Jak już wygenerujesz ten model to na karcie 'Sources for:' wybierasz "Post Route Simulation". No i wtedy w zależności od tego jaki masz zainstalowany symulator pojawią się opcje do jego uruchomienia.

    0