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

[FPGA][VHDL] Symulacja prostego automatu

15 Cze 2011 14:43 5906 32
  • Poziom 34  
    Chcę wykonać symulację prostego dzielnika. Stworzony opis:
    Code:
    library IEEE;
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

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

    ---- Uncomment the following library declaration if instantiating
    ---- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;

    entity obrot is
        Port ( CLK : in  STD_LOGIC;
               WYJ : buffer  STD_LOGIC);
    end obrot;

    architecture Behavioral of obrot is
    type stany_automatu is (S0, S1, S2);
    signal stan:stany_automatu:=S0;

    begin

    obracanie: process(CLK)
    begin
       if rising_edge(CLK) then
          if stan=S0 then
             stan<=S1;
          end if;
          
          if stan=S1 then
             stan<=S2;
          end if;

          if stan=S2 then
             stan<=S0;
             WYJ <= not WYJ;
          end if;

       end if;
    end process obracanie;

    end Behavioral;


    Symulację chcę przeprowadzić w VHDL Simili. Wiem jak to zrobić, jednak nie wiem jak stworzyć sygnały testowe. Tzn. jak wytworzyć falę prostokątną dla wejścia zegara CLK ?
  • Computer Controls
  • Poziom 21  
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod
  • Computer Controls
  • Poziom 30  
    Akurat w ISE jak wybierzesz testbench, to na podstawie słowa klucz CLK, powinien sam wygenerować proces do generacji sygnału zegarowego, taki szablon. Do Ciebie należy tylko podanie sygnałów testowych na wejście Twojego modułu + obserwacja wyjścia/wejść np. w Isim czy Simili :D

    To tylko zwykły osobny plik .vhdl z obsadzoną Twoją jednostką jako komponent i z mapowanymi portami. Dlatego, że zawiera część niesyntezowalną jak wait i żeby nie grzebać w Twoim opisie tylko testować :D
  • Poziom 34  
    Co bym nie zrobił i tak nie powstaje sygnał prostokątny dla CLK. Jakie inne darmowe środowisko można jeszcze wypróbować ?
  • Poziom 21  
    A możesz pokazać kod ?? sam kod... Bo ja nie znam tego środowiska;) a po kodzie dojdziemy o co chodzi. Jeszcze coś ja jaki układ docelowy będzie ta struktura Xilinx Altera, czy inny...
  • Poziom 34  
    Kod:
    Code:
    library IEEE;
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;


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

    ---- Uncomment the following library declaration if instantiating
    ---- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;

    entity obrot is
        Port ( CLK : buffer  STD_LOGIC;
               WYJ : buffer  STD_LOGIC);
    end obrot;

    architecture Behavioral of obrot is
    type stany_automatu is (S0, S1, S2);
    signal stan:stany_automatu:=S0;

    begin

    obracanie: process(CLK)
    begin
       if rising_edge(CLK) then
          if stan=S0 then
             stan<=S1;
          end if;
          
          if stan=S1 then
             stan<=S2;
          end if;

          if stan=S2 then
             stan<=S0;
             WYJ <= not WYJ;
          end if;

       end if;
    end process obracanie;

    end Behavioral;



    -----------------
    architecture Behavioral of obrot is
    constant clk_period : time := 10 ns;
    BEGIN
       clock : PROCESS
       BEGIN
     
       clk <= NOT clk;
          wait for clk_period;
     
       END PROCESS;
    end Behavioral;


    Próbowałem też dodać część nie syntezowalną w osobnym pliku (dodanym do projektu i skompilowanym), jednak nic to nie zmienia. Jeżeli chodzi o układ docelowy, to nigdy nie będzie to umieszczane w FPGA. Muszę coś zrobić na zaliczenie. Będzie to bardziej skomplikowane od podanego opisu. Jednak ten automat wymyśliłem w celu sprawdzenia możliwości symulacji.
  • Poziom 30  
    Zacytuje samego Siebie, słowa klucze na grubo:
    tymon_x napisał:
    To tylko zwykły osobny plik .vhdl z obsadzoną Twoją jednostką jako komponent i z mapowanymi portami. Dlatego, że zawiera część niesyntezowalną jak wait i żeby nie grzebać w Twoim opisie tylko testować


    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    Popraw Swój opis, zegar CLK jest wejściem, czyli deklaracja jako IN. Powtórzyłeś podwójnie bibliotekę.
    A teraz attention:
    Tak się nie robi maszyny stanów!!!
    Poprawne, technika na dwa procesy, część sekwencyjną oraz kombinacyjną: FSM Example. Ważny jest dodanie stanu 'reset', co wprowadzi sygnały w stan początkowy.
  • Pomocny post
    Poziom 21  
    Wiesz co ja ci polecam darmowe środowisko Xilinxa jest tam wszystko co potrzebujesz na szybko edytowałem twój kod. Przesyntezowałem i dział teraz chyba jak należy bo nie wiem co chcesz otrzymać ale z print screen chyba będziesz starował I2c ;)

    Twój kod poprawiony troszkę.
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Test bencz
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Tak wyglądają przebiegi z
    [FPGA][VHDL] Symulacja prostego automatu [FPGA][VHDL] Symulacja prostego automatu
  • Poziom 34  
    tymon_x napisał:
    Tak się nie robi maszyny stanów!!!
    Poprawne, technika na dwa procesy, część sekwencyjną oraz kombinacyjną: FSM Example. Ważny jest dodanie stanu 'reset', co wprowadzi sygnały w stan początkowy.


    Wiem, że w zasadzie automat powinien składać się z części kombinacyjnej i sekwencyjnej. W tej drugiej powinna znaleźć się tzw. funkcja przejść, w pierwszej funkcja wyjść. Zatem myślę, że przejścia między stanami mogą być w ten sposób zrobione. Zaś funkcja wyjść powinna być opisana np. na with select when. Tłumaczyłaby ona stany automatu S0, S1, S2 na wartości dla pinu WYJ.

    Odpuściłem sobie VHDL Simili. Co by nie zrobić to i tak nie będzie symulować.

    Co ze strony Xilinxa pobrać ? Wystarczy SDK ? Czy muszę mieć ISE ?
  • Poziom 30  
    maciej_333 napisał:
    uściłem sobie VHDL Simili. Co by nie zrobić to i tak nie będzie symulować.

    Nie masz tam gdzieś w jakimś helpie (kolokwialnie) pomocy? Albo how-to? Symulacje odpalasz z poziomu testbench'a...

    maciej_333 napisał:
    Co ze strony Xilinxa pobrać ? Wystarczy SDK ? Czy muszę mieć ISE ?

    SDK jest do czegoś innego. Xilinx ISE to kobyła (4GB) i ma sens kiedy masz do czynienia z ich układami. A Tobie tylko symulacja wystarczy. Lepszym rozwiązaniem by było wykorzystać np. GHDL ?

    Masz tu tutka (linux): VHDL - ghdl + gtkwave.
  • Poziom 21  
    Nie wiem jakie masz łącze ale ściągnij sobie ISE tam jest wszystko masz kupę tutoriali jak posługiwać się tymi narzędziami naprawdę polecam. Wiem że to co proponuje Tymon jest racjonalnie uzasadnione ale jak widzę konsolę to mnie trafia.
    [FPGA][VHDL] Symulacja prostego automatu
  • Poziom 34  
    4GB dla Xilinxa to za wiele i nie mam szansy tego pobrać. W sumie jakoś udało mi się uruchomić symulację w VHDL Simili. Jednak to oprogramowanie jest dziwne...

    Może komuś to się przyda:
    W celu przeprowadzenia symulacji należy wybrać top-level dla naszego workspace na projekt_tb (behaviour). Potem klikamy compile all i jeszcze run simulate. Kolejno, aby nie było za łatwo dodajemy sygnały do waveform (za którymś razem się uda...) i klikamy simulate->go. Nie wiem czemu są problemy z dodaniem sygnałów do waveform i po co ta opcja go.
    [FPGA][VHDL] Symulacja prostego automatu
  • Poziom 21  
    Bardzo małe i fajne narzędzie pobawiłem się chwile nim nawet zrobiłem sobie mały tutorial aby nie zapomnieć o tym narzędziu. Taki jest efekt końcowy przebiegów ;) naprawdę fajnie że mi pokazałeś ten malutki programik.
    [FPGA][VHDL] Symulacja prostego automatu
    Jeszcze chwile się nim pobawiłem jak na takie małe "coś" jest naprawdę bardzo fajnym narzędziem. Sporo możliwości edytowanie przebiegów pod względem wyglądu i w ogóle. Na razie powoli mnie przekonuje. Po małe edycji aż sie prosi aby wklejać do jakiejś książki czy sprawozdania ;)
    [FPGA][VHDL] Symulacja prostego automatu
  • Poziom 34  
    Mam jeszcze inne pytania:

    1. Jak ustawić linię wyjściową struktury FPGA w stan wysokiej impedancji ?
    2. Załóżmy, że mamy 8-bitowy port dwukierunkowy, zdefiniowany jako zewnętrzny. Chciałbym wykonać coś takiego, aby zmiana stanu na tym porcie (wywołana sygnałem zewnętrznym) ustawiała w stan niski jakąś linię zewnętrzną układu FPGA. Z pewnością należy wpisać ten 8-bitowy rejestr w listę czułości procesu, ale jak sprawdzić zmianę stanu linii z 0 na 1, lub z 1 na 0 ?
  • Poziom 30  
    maciej_333 napisał:
    1. Jak ustawić linię wyjściową struktury FPGA w stan wysokiej impedancji ?

    W części współbieżnej, w Top Module:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Ważne jest sprawdzenie czy dany FPGA ma blok IO pozwalający na pracę w stanie wysokiej impedancji, ale nie powinno być z tym problemu.

    maciej_333 napisał:
    2. ... ale jak sprawdzić zmianę stanu linii z 0 na 1, lub z 1 na 0 ?

    Początku nie zrozumiałem, więc odpowiem na powyższe pytanie ;) Przepuścić przez przerzutniki, opóźniając o jeden takt, jeden inverter, sygnały przez bramkę and i masz detektor zbocza i go wykryć. Tylko nie korzystaj z 'event czy rising_edge/falling_edge, bo to jest nieeleganckie, większości wypadku wytrasuje Ci to jako linie zegarowe, a to są bardzo cenne linie w FPGA ;)
  • Poziom 11  
    tylko pamiętaj o jednym: jak masz szynę wyjściową, aby z niej czytać nie stosuj inout tylko buffer. Funkcjonalność będzie taka sama, ale rozwiązanie drugie będzie poprawne i eleganckie (nie będą w tym miejscu użyte wolne i kosztowne układy trójstanowe)
  • Poziom 34  
    Mam kolejne pytanie. Jak dodać do test bench sygnał wewnętrzny, tak by dało się go obserwować na Waveform ?
  • Poziom 21  
    maciej_333 napisał:
    Jak dodać do test bench sygnał wewnętrzny, tak by dało się go obserwować na Waveform ?


    Możesz to doprecyzować... Czy chcesz dodać jakiś inny sygnał do swojej struktury a potem do test bencha i go obserwować? Czy masz problem z obsługą VHDL Simili 3.1. bo nie wiesz jak to wywalić na przebiegi ??
  • Poziom 34  
    lss napisał:
    maciej_333 napisał:
    Jak dodać do test bench sygnał wewnętrzny, tak by dało się go obserwować na Waveform ?


    Możesz to doprecyzować... Czy chcesz dodać jakiś inny sygnał do swojej struktury a potem do test bencha i go obserwować? Czy masz problem z obsługą VHDL Simili 3.1. bo nie wiesz jak to wywalić na przebiegi ??


    Tu nie chodzi tym razem o VHDL Simili. Po słowie kluczowym architecture dodałem sygnał: signal cos_tam : std_logic_vector (4 downto 0) := "00000". W moim opisie coś tam dzieje się z tym sygnałem. VHDL Simili wyświetla mi listę sygnałów, które mogę dodać do waveform. Jednak jeżeli jakoś nie umieszczę sygnału "cos_tam" w test bench, to nie będzie można go dodać do waveform. Co z tym zrobić ?
  • Poziom 21  
    maciej_333 napisał:
    Jednak jeżeli jakoś nie umieszczę sygnału "cos_tam" w test bench, to nie będzie można go dodać do waveform. Co z tym zrobić ?
    Nie prawda ty masz chyba jednak problem z obsługa środowiska bo zobacz. Nadole przedstawiam mój kod dodałem rejestr cos_tam 5 bitowy i dział jak należy. Dodatkowo zrobiłem na nim licznik aby widać było że coś się dzieje z tym rejestrem.

    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    W test benczu nic nie dodałem, pozostaje bez zmian. Test bench to "czynniki zewnętrzne czy też środowisko" które pobudzają czarną skrzynkę czyli obrot do "życia". Ty podając coś na wejście oczekujesz czegoś na wyjściu. Jeżeli coś dodałeś w obrot.vhd o ile to nie zmienia nic w deklaracji ENTITY nic nie dopisujesz w test benchu Na dowód listing.

    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    Zrzuty z ekranu na dowód że wszystko jest ok
    [FPGA][VHDL] Symulacja prostego automatu
    Przybliżony
    [FPGA][VHDL] Symulacja prostego automatu
    Rozwinięty rejestr cos_tam
    [FPGA][VHDL] Symulacja prostego automatu

    Myślę że to jednak albo problem z opisem twojej struktury albo problem z obsługą środowiska. Jeżeli chcesz jakieś korki z tego środowiska odezwij się na priv.
  • Poziom 34  
    Pracuję nad SPI. Mój aktualny test bench:

    Code:
    LIBRARY ieee;
    
    USE ieee.std_logic_1164.ALL;
     
    -- Uncomment the following library declaration if using
    -- arithmetic functions with Signed or Unsigned values
    --USE ieee.numeric_std.ALL;
     
    ENTITY inter_spi_tb IS
    END inter_spi_tb;
     
    ARCHITECTURE behavior OF inter_spi_tb IS
     
        -- Component Declaration for the Unit Under Test (UUT)
     
        COMPONENT inter_spi
        PORT(
               CLK : in  STD_LOGIC;
               SCK : in  STD_LOGIC;    --zegar
               SI  : in  STD_LOGIC;    --wejście danych
               SO  : out  STD_LOGIC;   --wyjście danych
               CS  : in  STD_LOGIC;    --chip select - aktywne 0
               WYJ : out STD_LOGIC_VECTOR (7 downto 0) --wyjściowy port
            );
        END COMPONENT;
     
     
       --Inputs
       signal CLK : STD_LOGIC := '0';
       signal SCK : STD_LOGIC := '0';
       signal SI  : STD_LOGIC := '0';
       signal CS  : STD_LOGIC := '1';
               
        --Outputs
       signal SO  : STD_LOGIC;
       signal WYJ : STD_LOGIC_VECTOR (7 downto 0);
     
       -- Clock period definitions
       constant CLK_period : time := 10 ns;
     
    BEGIN
     
       -- Instantiate the Unit Under Test (UUT)
       uut: inter_spi PORT MAP (
              CLK => CLK,
              SCK => SCK,
              SI => SI,
              CS => CS,
              SO => SO,
              WYJ => WYJ
            );
     
       -- Clock process definitions
       CLK_process :process
       begin
          CLK <= '0';
          wait for CLK_period/2;
          CLK <= '1';
          wait for CLK_period/2;
       end process;
       
       SCK_proces :process
       begin
          SCK <= '0';
          wait for 45*CLK_period;
          SCK <= '1';
          wait for 45*CLK_period;
       end process;   
           
       -- Stimulus process
       stim_proc: process
       begin      
          -- hold reset state for 100 ns.
          wait for 100 ns;   
     
          wait for CLK_period*10;
     
          -- insert stimulus here

         
          wait;
       end process;
     
    END;


    Opis:
    Code:
    library IEEE;
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    ---- Uncomment the following library declaration if instantiating
    ---- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;

    entity inter_spi is
        Port ( CLK : in  STD_LOGIC;    --zegar dla struktury FPGA    f_CLK >> f_SCK
              SCK : in  STD_LOGIC;    --zegar z układu master SPI
               SI  : in  STD_LOGIC;    --wejście danych
               SO  : out  STD_LOGIC;   --wyjście danych
               CS  : in  STD_LOGIC;    --chip select - aktywne 0
               WYJ : out STD_LOGIC_VECTOR (7 downto 0)); --wyjściowy port
    end inter_spi;

    architecture Behavioral of inter_spi is
    signal synchro_zeg_SPI : STD_LOGIC_VECTOR (4 downto 0) := "00000";
    signal synch : STD_LOGIC := '0';

    signal pom : STD_LOGIC := '0';

    begin

       zegar_glowny: process(CLK)
       begin
          if rising_edge(CLK) then
             synchro_zeg_SPI <= SCK & synchro_zeg_SPI(4 downto 1);
          end if;
       end process;

       odbierz_dane: process(synch)
       begin
          if synch='1' then
             pom <= not pom;
          end if;
       end process;

    with synchro_zeg_SPI select
       synch <= '1' when "11110",
           '1' when "11100",
           '1' when "11000",
           '1' when "10000",
           '0' when others;
          
    SO <= pom;
    end Behavioral;


    Nie ma szansy, by dodać np. sygnał: synchro_zeg_SPI do waveform, bo w liście dostępnych sygnałów on nie występuje.
  • Pomocny post
    Poziom 30  
    maciej_333 napisał:
    Nie ma szansy, by dodać np. sygnał: synchro_zeg_SPI do waveform, bo w liście dostępnych sygnałów on nie występuje.

    Po lewej masz zakładkę "hierarchy", rozwiń w Twoim przypadku instancję uut (tak między nawiasami Unit Under Test) i dodaj wybrany sygnał. Jakby to był variable to bym się zgodził, że może go tam nie być, w szczególności jeśli znajdzie się w procesie, ale signal musi być, nawet w takim komercyjno-niekomercyjnym środowisku.

    Piszę to tak intuicyjnie, ale na bank powinno gdzieś tam być.
  • Poziom 34  
    Faktycznie, jak poklikałem tak, jak pisze kolega Tymon to można dodać wszystkie sygnały do waveform.

    Trochę z innej beczki. Właściwie, to jaką długość powinien mieć rejestr przesuwny synchro_zeg_SPI ? Wykorzystuję go do synchronizacji - wykrycia narastającego zbocza sygnału zegara, pochodzącego od układu MASTER SPI. Inna sprawa, czy rozwiązanie z tym rejestrem nie jest jakieś mało sensowne. Chciałem uniknąć stosowania dwa razy "rising_edge", bo wówczas byłyby dwa zegary i układ pewnie nie byłby w pełni synchroniczny.
  • Poziom 30  
    Każdy sygnał zewnętrzny powinno się traktować jako asynchroniczny. I tak samo ważne jest synchronizowanie go z zegarem głównym. Do tego wystarczą przynajmniej dwa przerzutniki (nie jeden!), a to wynika z zjawiska metastabilności układów, bo więcej szczegółów wygoogluj Sobie parametr MTBF.

    Co do długości rejestru do takich rzeczy, to zależy od układu, należałoby potraktować go jak prosty system próbkowania (bit - próbka, clk - f_próbkowania). Dla drgań z styków buttona poleciłbym dłuższy z wolniejszym zegarem (timer), a do SPI zależny od t_n i t_op zboczy.
  • Poziom 34  
    Udało już mi się jakoś zaimplementować SPI, teraz próbuję tworzyć RS232. W tym wypadku chcę mieć jedynie odbiór przez układ FPGA. Poniżej kod:

    Kod: vhdl
    Zaloguj się, aby zobaczyć kod


    Wszystko działa, sprawdzany jest błąd parzystości, bada czy bit startu i bity stopu mają właściwą wartość itd. W opisie tym bit jest próbkowany w połowie trwania, zgodnie z RS232. Prędkość transmisji 115200b/s, zegar taktujący układ FPGA 10MHz.

    Problem pojawia się po zakończeniu transmisji. Muszę jakoś wyzerować bit "odb_bit_startu". Jest on ustawiany w trakcie początku synchronizacji. Po odebraniu 12-bitów (bit startu, 8 bitów danych, bit parzystości, 2 bity stopu) muszę przestawić wszystko, tak, aby dało się odebrać kolejną ramkę. Tutaj właśnie kluczowe jest wyzerowanie wspomnianego bitu.

    Zdaję sobie sprawę, z tego, że jest to bardzo kiepski sposób opisu w VHDL'u, ale jakoś muszę poprawić ten kod.
  • Poziom 30  
    I tak o to umiera maszyna stanów... Wiem, że łatwiej tak się pisze standardowemu programiście przyzwyczajonego do strukturalnego języka jakim jest np. C (if...else). Ale takie, a nie inne użycie odzwierciedla jak synteza przełoży to na logikę. W dodatku, za pomocą FSM łatwiej wszystko kontrolować:
    Kod: vhdl
    Zaloguj się, aby zobaczyć kod

    Nie potrzebnie ludzie umieszczają wszystko w if..else bo im tak łatwiej, ale w dodatku sobie utrudniają i uczą się złych nawyków, np zagnieżdżając wszystko. A tu latch, a tu coś nie działa,... a weź takie coś analizuj, ja odpadam od razu, dla mnie to ciało nie ma rąk i nóg.