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

[VHDL] Jak zapisać poprawnie program

04 Lut 2010 23:12 2233 6
  • Poziom 31  
    Na wstępie chciałbym zaznaczyć, że zabrałem się za FPGA i programowanie 3 tygodnie temu i bardzo proszę się nie śmiać :-)

    Załączam kod.
    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_SIGNED.ALL;

    entity Test is
        port(
       clk:   in  std_logic;
       reset:   in  std_logic;
       x:    in std_logic_vector(31 downto 0);
       y:    in std_logic_vector(31 downto 0);
       A:    out std_logic_vector(31 downto 0);
       B:    out std_logic_vector(31 downto 0)
       );
    end Test;

    architecture Main of Test is          

    signal y1: std_logic_vector(63 downto 0);
    signal y2: std_logic_vector(63 downto 0);    
    signal x1: std_logic_vector(31 downto 0);
    signal x2: std_logic_vector(31 downto 0);
    signal z1: std_logic_vector(31 downto 0);
    signal z2: std_logic_vector(31 downto 0);

    begin
    process (clk,reset)   
       begin
       if(reset = '1') then
          y1 <= (others=>'0');
          y2 <= (others=>'0');
          x1 <= (others=>'0'); 
          x2 <= (others=>'0');
          z1 <= conv_std_logic_vector(30,32); 
          z2 <= conv_std_logic_vector(50,32); 
          elsif
             rising_edge(clk) then   
              x1<="00" & x(31 downto 2);
             x2<=y(29 downto 0) & "00";
             y1<=x1*z1;
             y2<=x2*z2;
             A<=y1(31 downto 0);
             B<=y2(31 downto 0);
             end if;    
       end process;
    end Main;
     

    Problem polega na takim zapisie programu, żeby na wyjściu dane zmieniały się tylko raz po przetworzeniu wejść. W tej chwili po zmianie wartości wejściowych otrzymuję dwa wyniki przesunięte o 1 sygnał zegarowy (przy czym ten drugi jest poprawnym wynikiem obliczeń). Skąd to się bierze jest dla mnie jasne, ale jak zapisać program, żeby zjawiska nie było to sprawa gorsza. Nie mogę i nie chcę używać zmiennych [variable] (za długo później przebiega synteza na rzeczywistą matrycę FPGA).
  • Poziom 17  
    może tak?
    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_SIGNED.ALL;

    entity Test is
        port(
       clk:   in  std_logic;
       reset:   in  std_logic;
       x:    in std_logic_vector(31 downto 0);
       y:    in std_logic_vector(31 downto 0);
       A:    out std_logic_vector(31 downto 0);
       B:    out std_logic_vector(31 downto 0)
       );
    end Test;

    architecture Main of Test is          

    signal y1: std_logic_vector(63 downto 0);
    signal y2: std_logic_vector(63 downto 0);    
    signal x1: std_logic_vector(31 downto 0);
    signal x2: std_logic_vector(31 downto 0);
    signal z1: std_logic_vector(31 downto 0);
    signal z2: std_logic_vector(31 downto 0);

    begin
    process (clk,reset)   
       begin
       if(reset = '1') then
          y1 <= (others=>'0');
          y2 <= (others=>'0');
          x1 <= (others=>'0'); 
          x2 <= (others=>'0');
          z1 <= conv_std_logic_vector(30,32); 
          z2 <= conv_std_logic_vector(50,32); 
          elsif
             rising_edge(clk) then   
              x1<="00" & x(31 downto 2);
             x2<=y(29 downto 0) & "00";
             y1<=(("00" & x(31 downto 2))*z1);
             y2<=((y(29 downto 0) & "00")*z2);
             A<=(("00" & x(31 downto 2))*z1)(31 downto 0);
             B<=((y(29 downto 0) & "00")*z2)(31 downto 0);
             end if;    
       end process;
    end Main;
     

    albo coś w ten deseń
    przy czym coś mi sie te mnożenia nie podobają
    pozdrawiam
    modi
  • Poziom 31  
    Niestety kompilator przyczepił się do zapisów na A i B;
    Próbowałem zwijać, ale wtedy można bardzo łatwo zrobić błąd. Ale myślę, że jest na to jakiś "patent".
  • Poziom 17  
    Cytat:
    Ale myślę, że jest na to jakiś "patent".

    ten patent sie nazywa variable...

    edit

    to wyciągnij sygnały a i b poza proces
    Code:
    library IEEE;
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_SIGNED.ALL;

    entity Test is
        port(
       clk:   in  std_logic;
       reset:   in  std_logic;
       x:    in std_logic_vector(31 downto 0);
       y:    in std_logic_vector(31 downto 0);
       A:    out std_logic_vector(31 downto 0);
       B:    out std_logic_vector(31 downto 0)
       );
    end Test;

    architecture Main of Test is         

    signal y1: std_logic_vector(63 downto 0);
    signal y2: std_logic_vector(63 downto 0);   
    signal x1: std_logic_vector(31 downto 0);
    signal x2: std_logic_vector(31 downto 0);
    signal z1: std_logic_vector(31 downto 0);
    signal z2: std_logic_vector(31 downto 0);

    begin
    process (clk,reset)   
       begin
       if(reset = '1') then
          y1 <= (others=>'0');
          y2 <= (others=>'0');
          x1 <= (others=>'0');
          x2 <= (others=>'0');
          z1 <= conv_std_logic_vector(30,32);
          z2 <= conv_std_logic_vector(50,32);
          elsif
             rising_edge(clk) then   
              x1<="00" & x(31 downto 2);
             x2<=y(29 downto 0) & "00";
             y1<=(("00" & x(31 downto 2))*z1);
             y2<=((y(29 downto 0) & "00")*z2);

             end if;   
       end process;
     A<=y1(31 downto 0);
     B<=y2(31 downto 0);
    end Main;
  • Poziom 31  
    Wyciąganie poza proces rozwiązuje tylko ten konkretny problem. Przy większym skomplikowaniu obliczeń niestety błąd będzie powracał. Użycie zmiennych też nie do końca załatwia sprawę (i synteza zwalnia... w moim przypadku z 7minut do 68min).
    Na tą chwilę problem rozwiązałem pisząc kod w formie kontrolowanej sekwencji wykonywanych działań. Nie jest to optymalne, ale zapewnia poprawność wyniku.
    Nie chcę tworzyć nowego tematu, ale mam jeszcze kilka pytań.
    Znalazłem dużo tekstów o VHDL w stylu "nie stosować", "nie wolno" itd. bez jakiegokolwiek uzasadnienia.

    1) Dlaczego nie można inicjować sygnałów na poziomie ich deklaracji (czym to grozi)?
    np.
    Code:

    architecture Main of Test is         
    signal y1: std_logic_vector(7 downto 0):="00011000";
    ....


    2) Dlaczego nie należy deklarować w części entity sygnałów typu "inout" i "buffer"?

    3)Dlaczego zalecana jest tylko forma malejąca dla zapisu np A(7 downto 0) a nie A(0 to 7)?

    Czy istnieje dobry dokument na temat VHDL w użyciu praktycznym. Te wszystkie kusy i wykłady w necie są zorientowane wyłącznie pod kątem teoretycznym. Praktyka to już "wyższa szkoła latania na miotle" - ściśle tajne! Nadziałem się już wielokrotnie na błędy generowane dopiero przy syntezie.
    Np. to, że użycie operacji dzielenia wymaga odpowiedniej budowy wyrażenia i argumentów (rozumiem mechanizm, ale wkurza mnie, że o jakiś ograniczeniach jestem informowany "po czasie", tym bardziej, że symulacja idzie świetnie:-)).
  • Poziom 21  
    Cytat:
    1) Dlaczego nie można inicjować sygnałów na poziomie ich deklaracji (czym to grozi)?
    np.
    Kod:

    architecture Main of Test is
    signal y1: std_logic_vector(7 downto 0):="00011000";
    ....


    To nie prawda, że nie można jak coś takiego robić, jak znalazłeś taki tekst to od razu napisz do autora że... Czym to grozi to ci mogę napisać. Jest to po prostu wymuszenie określonej wartości(stanu). Np. chcesz aby układ liczył od zera wtedy wymuszasz na nim po przez przypisanie zera logicznego(stanu początkowego) i on zaczyna liczyć wtedy od zera. Odeśle cię do w obojętnie jakiej książce od VHDl-a abyś przeczytał czym cechują się dane wielkości sygnałów takie jak bit, std_logic, integer, wtedy zrozumiesz dokładnie o co chodzi.

    Cytat:
    2) Dlaczego nie należy deklarować w części entity sygnałów typu "inout" i "buffer"?


    W tym przypadku to zależy do czego jest dany moduł. Są bloki cyfrowe które muszą mieć na wejściu buffer lub inout. Często jest to nie wskazane i tu jest racja gdyż dużo osób stosuje je nie potrzebnie i przez to tak komplikuje prostą budowę układów że pojawiają się błędy syntezy na poziomie RTL, nie zgodności czasowe. Dlatego to nie jest wskazane...

    Cytat:
    Dlaczego zalecana jest tylko forma malejąca dla zapisu np A(7 downto 0) a nie A(0 to 7)?


    Abyś to zrozumiał zadam ci pytanie ale odpowiedz sobie sam na to pytanie... albo nie napisze przykład

    3 downto 0 -> 1011 -> jest to w systemie dziesiętnym 11
    0 to 3 -> 1011 -> jest to w systemie dziesiętnym 13

    Mam nadzieje że ten przykład rozjaśni ci w myśleniu. Na dobrą sprawę to jest tak jeżeli piszesz "to" to musisz być konsekwentny i pisać do końca "to" jeżeli piszesz "downto" to do końca "downto". Druga forma jest preferowana w układach cyfrowych bo przyjęło się że najstarszy bit MSB jest po lewej stronie a najmłodszy LSB jest po prawej. Sprawa prosta tak samo jak czytasz w systemie dziesiętny 123 to wiesz że to jest 123 a nie 321...

    Cytat:
    Czy istnieje dobry dokument na temat VHDL w użyciu praktycznym.

    Szczerze jest wiele takich kursów(książek i to w praktyce) tylko jest warunek język angielski, praktyka, cierpliwość, własne doświadczenia i przemyślenia. Może to jest banalne co pisze ale tak jest. Po to są fora internetowe abyś mógł podpytać. Nikt cie nie nauczy programowania jak się sam nie nauczysz. Pisze do z własnego doświadczenia, choć nie czuje się ani gram programistą.

    Do tych błędów generowanych po czasie musisz się przyzwyczaić i zacząć czytać co ci zwraca program, co pokazuje struktura RTL. Z czasem jak będziesz je analizował to sam będziesz w stanie 90% błędów wyłapać.

    Co do symulacji i tu konkretnie dzielenia to symulator jest w stanie to zrobić bez problemu lecz twój układ FPGA nie posiada bloków dzielenia wiec jak ma realizować tą operacje w fizycznie dlatego błędy ... Są rózne sposoby dlatego tu odsyłam do matematyki numerycznej i algorytmów. Na dzieleniu zjadłem kupę zdrowia i pierwiastkowaniu ale podpowiem ci że istnieją już biblioteki które to robią. Jak będzie cię to interesowało to Google ci pomoże... Jednym z algorytmów dzielenia jest np. odejmowanie i przesuwanie...

    Mam nadzieje że pomogłem

    Pozdrawiam
  • Poziom 31  
    Już myślałem, że nikt nie odpowie :-)

    Ad1
    Inicjalizację sygnałów mogę zrobić tak jak napisałem (przy deklaracji) lub (tak jak to jest w pierwszym poście) w obszarze uzależnionym od sygnału reset. I to jest jasne. Natomiast nie wiem jaka będzie różnica w fizycznej realizacji. Jeżeli ktoś pisze, że nie należy tego robić przy deklaracji to pewnie ma do tego powód (np. wynikający z wiedzy praktycznej).

    Ad2 Tu spotkałem w kilku "kursach" silne stwierdzenie: "nie stosować w praktycznych realizacjach" stąd pytanie. Myślałem, że to znów jakiś wynalazek przydatny tylko do symulacji. W wolnej chwili zobaczę jakie będą rezultaty, jeżeli będę miał port "inout".

    Ad3 OK. Myślałem, że w tym zapisie znów jest jakieś niebezpieczństwo w syntezie.

    AD4
    Cytat:

    Szczerze jest wiele takich kursów(książek i to w praktyce)


    Możesz konkretnie coś zaproponować (może być po angielsku)?

    Cytat:

    Może to jest banalne co pisze ale tak jest. Po to są fora internetowe abyś mógł podpytać. Nikt cie nie nauczy programowania jak się sam nie nauczysz. Pisze do z własnego doświadczenia, choć nie czuje się ani gram programistą.
    Do tych błędów generowanych po czasie musisz się przyzwyczaić i zacząć czytać co ci zwraca program, co pokazuje struktura RTL. Z czasem jak będziesz je analizował to sam będziesz w stanie 90% błędów wyłapać.


    O tym już się zdążyłem przekonać. Niestety wszystkie opracowania traktują problem teoretycznie, bo tak jest najprościej. A już większość wykładów (z polskich uczelni), które są zamieszczone w internecie mają tragiczną jakość (w odniesieniu praktycznym)!
    Co do cierpliwości to jakoś nie bardzo mi się podoba otrzymać informację o błędzie po 50 minutach syntezy. Ale pewnie taki urok FPGA.
    Ogólnie poszukuję jakiś publikacji dotyczących wyjątków i "patentów" (czego unikać i jak stosować sprawdzone rozwiązania). Śledzę przykłady, ale tu jest niebezpieczeństwo, że trafię na rozwiązania "kosmiczne".
    Na forum to raczej panuje wątek AVRowo-ARMowy + PLCaki :-). Masz może namiar na dobre forum o tematyce czysto związanej z układami programowalnymi?

    Cytat:

    Co do symulacji i tu konkretnie dzielenia to symulator jest w stanie to zrobić bez problemu lecz twój układ FPGA nie posiada bloków dzielenia wiec jak ma realizować tą operacje w fizycznie dlatego błędy ... Są rózne sposoby dlatego tu odsyłam do matematyki numerycznej i algorytmów. Na dzieleniu zjadłem kupę zdrowia i pierwiastkowaniu ale podpowiem ci że istnieją już biblioteki które to robią. Jak będzie cię to interesowało to Google ci pomoże... Jednym z algorytmów dzielenia jest np. odejmowanie i przesuwanie...


    Rozwiązanie dzielenia nie stanowi żadnego problemu. Nie w tym rzecz. Ja podałem tylko przykład. Nie chcę tracić czasu na trywialne błędy. Np. tylko w jednej publikacji znalazłem tekst o tym, że typ real nie jest syntezowalny (wiedziałem trochę o tym wcześniej). Ale można zrobić "sprytny" algorytm i się zdziwić.

    Jeżeli masz jakieś konkretne dokumenty traktujące praktycznie o FPGA to byłbym zainteresowany.