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.

Prośba o pomoc w skomentowaniu kodu źródłowego VHDL

19Adam87 04 Lip 2010 14:58 1965 3
  • #1 04 Lip 2010 14:58
    19Adam87
    Poziom 2  

    Witam

    Jakiś czas temu otrzymałem za zadanie napisanie prostego kalkulatora 8 bitowego w języku VHDL. Jako że ze mnie raczej kiepski programista, a już na pewno w języku opisu sprzętu, często wspomagałem się wiedzą ludzi z forum oraz kolegi z osiedla, który programowanie ma w małym palcu, z jego i Waszą drobną pomocą udało się sporządzić kod, wykładowca zaakceptował projekt, ale poprosił o szczegółowy opis kodu. Niestety kolega 2 dni temu wyjechał na wakacje a ja zostałem w czarnej... sami wiecie co :) Tyle o ile byłem w stanie opisać kod to zostało to uczynione jednakże, jako że jestem kiepskim programistą i części funkcji po prostu nie rozumiem, zwracam się do was z prośbą o jego w miarę przystępne opisanie. Ostatnio jeszcze w fazie pisania bardzo pomógł Tymon_x na jego udział w tym wątku także bardzo liczę :). Wszystkim pomocnym bardzo dziękuję

    Kod źródłowy i częściowy opis

    Code:
    library IEEE; 
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;    -------------Kod, który piszemy wymaga jednak dołączenia wielu pakietów, w których zdefiniowane są operacje dotyczące sygnałów typu std_logic. Jest to konieczne do poprawnego działania projektu. W języku VHDL typ ten nie jest predefiniowany, a zatem próba kompilacji takiego projektu wykazałaby błąd. Zauważyć należy, że mimo tego iż nie jest to typ predefiniowany jest to jeden z najpopularniej stosowanych typów w języku VHDL.-----------------

    entity calc1 is
    Port ( Clk : in std_logic;
    Switches : in std_logic_vector(7 downto 0);
    Buttons : in std_logic_vector(6 downto 0);
    Result : out std_logic_vector(7 downto 0));
    end calc1;
    architecture Behavioral of calc1 is
    Signal Q0,Q1,Q2,Q3: std_logic_vector(7 downto 0) := (others=>'0');
    Signal S: std_logic_vector(1 downto 0);
    Signal S3S2S1S0: std_logic_vector(3 downto 0);
    Signal D,B,T: std_logic_vector(7 downto 0);
    signal Old_buttons: std_logic_vector(6 downto 0);
    begin
    T <= Switches;
    B <= conv_std_logic_vector(0, 8);
    Result <= Q0;
    One_puls_detector:
    process( clk)
    variable One_pulses: std_logic_vector(6 downto 0);
    begin
    if rising_edge( Clk) then
    Old_buttons <= Buttons;
    One_pulses := not Old_buttons and Buttons;



    case One_pulses is
    ----------- Instrukcje CASE odpowiedzialne za poszczególne  parametry kalkulatora  definiujące operacje, mnożenia, dzielenia dodawania, odejmowania i przesunięcia.-------------
    when "0000001" => S <= "01"; S3S2S1S0 <= "0000"; -- Enter 
    when "0000010" => S <= "10"; S3S2S1S0 <= "0000"; -- Pop
    when "0000100" => S <= "11"; S3S2S1S0 <= "0001"; -- +
    when "0001000" => S <= "11"; S3S2S1S0 <= "0010"; -- -
    when "0010000" => S <= "11"; S3S2S1S0 <= "0100"; -- *
    when "0100000" => S <= "11"; S3S2S1S0 <= "1000"; -- /
    when others => null;
    end case;
    end if;
    end process;
    The_RPN_Stack:
    process( Clk)
    begin
    if rising_edge( Clk) then
    ----------Wykorzystanie instrukcji CASE dla konkretnych przypadków sygnałów wejściowych, wyjątkiem jest tu sygnał 00 w którym to nic nie następuje, a program rozumie to jako nie wprowadzenie żadnych zmiennych.-----------


    case S is
    When "00" => Null;
    When "01" => Q3<=Q2; Q2<=Q1; Q1<=Q0; Q0<=T;
    When "10" => Q0<=Q1; Q1<=Q2; Q2<=Q3; Q3<=B;
    When "11" => Q0<=D; Q1<=Q2; Q2<=Q3; Q3<=B;
    When others => Null;
    end case;
    end if;
    end process;
    ALU_process:
    ---------- Wykorzystanie bloku programowego ALU, operacje na zmiennych-----------
    process( S3S2S1S0, Q1, Q0)
    begin
    case S3S2S1S0 is
    when "0001" => D <= Q1+Q0;
    when "0010" => D <= Q1-Q0;
    when "0100" => D <= Q1(3 downto 0) * Q0(3 downto 0);
    when "1111" => D <= Q1 xor Q0;
    when others => D <= (others=>'0');
    end case;
    end process;
    end Behavioral;

    0 3
  • #2 04 Lip 2010 15:54
    tymon_x
    Poziom 30  

    19Adam87 napisał:
    ...i części funkcji po prostu nie rozumiem, zwracam się do was z prośbą o jego w miarę przystępne opisanie


    Sporządziłeś język opisu kalkulatorka, a nie rozumiesz jego podstawowych składni :?:
    Nie ma tu maszyny stanów, ani żadnej funkcji generic. Takie basic of basic (;

    Tutaj masz przystępny i kolorowy Kurs VHDL'a Józefa Kalisza, mogę Ci jeszcze polecić to Kurs VHDL'a od elki . Na jego podstawie, na pewno dokończysz resztę opisu.
    Ogarnij powyższą lekturę, uzupełnij komentarze do końca samodzielnie i w tedy z kiepskiego programisty może się coś zrodzić poważniejszego (;

    Sam na pewno dasz radę. Jakby były jakieś niuanse nie jasne dla Ciebie, daj znać, pomożemy.

    0
  • #3 04 Lip 2010 20:15
    19Adam87
    Poziom 2  

    no właśnie na podstawie tego drugiego kursu udało mi się napisać tyle ile widzisz... Jasne rzucę okiem na to raz jeszcze, ale tu chodzi o to, że z gościem mieliśmy tylko 3 zajęcia w ciągu semestru a on wymaga od nas nie wiadomo czego... Dlatego proszę żebyście chociaż tyle byli w stanie zrobić za mnie. Już ponad tydzień się z tym morduje :P

    Dodano po 3 [godziny] 33 [minuty]:

    Code:
    library IEEE; 
    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;    -------------Kod, który piszemy wymaga jednak dołączenia wielu pakietów, w których zdefiniowane są operacje dotyczące sygnałów typu std_logic. Jest to konieczne do poprawnego działania projektu. W języku VHDL typ ten nie jest predefiniowany, a zatem próba kompilacji takiego projektu wykazałaby błąd. Zauważyć należy, że mimo tego iż nie jest to typ predefiniowany jest to jeden z najpopularniej stosowanych typów w języku VHDL.-----------------

    entity calc1 is                ----- definicja obiektu calc1-----
    Port ( Clk : in std_logic;          ---port wejściowy zegara---            
    Switches : in std_logic_vector(7 downto 0);  --- na wejściu 8 przełączników  1-bitowych, w                      kolejności od prawej do lewej----
    Buttons : in std_logic_vector(6 downto 0);   --- na wejściu 7 przycisków 1-bitowych---
    Result : out std_logic_vector(7 downto 0));  ---na wyjściu rezultat---
    end calc1;  --- koniec definicji obiektu----
    architecture Behavioral of calc1 is
    Signal Q0, Q1, Q2, Q3: std logic vector (7 downto 0) := (others=>’0’); ---- ?----
    Signal S: std_logic_vector(1 downto 0);--- sygnał 2-bitowy
    Signal S3S2S1S0: std_logic_vector(3 downto 0); ---sygnał 3bitowy
    Signal D,B,T: std_logic_vector(7 downto 0);  --- sygnały 8-bitowe
    signal Old_buttons: std_logic_vector(6 downto 0); 
    begin
    T <= Switches; ---podstaw pod t przełączniki
    B <= conv_std_logic_vector(0, 8); --- podstaw pod b logiczny wektor 8 zer
    Result <= Q0; pod rezultat podstaw Q0
    One_puls_detector:
    process( clk) ---proces zatrzymany do chwili, gdy wejście zegrowe ulegnie zmianie---
    variable One_pulses: std_logic_vector(6 downto 0); ---kolejny wektor 7 bitowy
    begin ---rozpoczęcie procesu
    if rising_edge( Clk) then ---jeśli pojawi się wzrastające zbocze zegara, to: ---




    Old_buttons <= Buttons;  --- pod stare przyciski podstaw te, co są w danej chwili ----
    One_pulses := not Old_buttons and Buttons;  --- pod sygnały podstaw negacja starych I                   nowych---



    case One_pulses is
    ----------- Instrukcje CASE odpowiedzialne za poszczególne  parametry kalkulatora  definiujące operacje, mnożenia, dzielenia dodawania, odejmowania i przesunięcia.-------------
    when "0000001" => S <= "01"; S3S2S1S0 <= "0000"; -- Enter 
    when "0000010" => S <= "10"; S3S2S1S0 <= "0000"; -- Pop
    when "0000100" => S <= "11"; S3S2S1S0 <= "0001"; -- +
    when "0001000" => S <= "11"; S3S2S1S0 <= "0010"; -- -
    when "0010000" => S <= "11"; S3S2S1S0 <= "0100"; -- *
    when "0100000" => S <= "11"; S3S2S1S0 <= "1000"; -- /
    when others => null; – w przeciwnym wypadku wyzeruj--
    end case; ---koniec case---
    end if; --- koniec instrukcji warunkowej---
    end process;  --- koniec procesu
    The_RPN_Stack:
    process( Clk) ---kolejny proces zatrzymany do czasu zmiany wejścia zegarowego
    begin --- początek
    if rising_edge( Clk) then --- jeśli pojawi się wzrastające zbocze wejścia zegarowego to
    ----------Wykorzystanie instrukcji CASE dla konkretnych przypadków sygnałów wejściowych, wyjątkiem jest tu sygnał 00 w którym to nic nie następuje, a program rozumie to jako nie wprowadzenie żadnych zmiennych.-----------


    case S is
    When "00" => Null;
    When "01" => Q3<=Q2; Q2<=Q1; Q1<=Q0; Q0<=T; ---podstawienie zmiennych---
    When "10" => Q0<=Q1; Q1<=Q2; Q2<=Q3; Q3<=B;
    When "11" => Q0<=D; Q1<=Q2; Q2<=Q3; Q3<=B;
    When others => Null;
    end case;
    end if;
    end process;
    ALU_process:
    ---------- Wykorzystanie bloku programowego ALU, operacje na zmiennych-----------
    process( S3S2S1S0, Q1, Q0)  ---kolejny proces ---
    begin
    case S3S2S1S0 is –--kolejna instrukcja case
    when "0001" => D <= Q1+Q0; – podstaw sumę
    when "0010" => D <= Q1-Q0; ---podstaw różnicę
    when "0100" => D <= Q1(3 downto 0) * Q0(3 downto 0); --podstaw pod q1 o indeksach od 3                do 0 pomnożone przez q0 o tych samych indeksach    (trochę ciężko mi to Panie doktorze inaczej wyrazić ;)----
    when "1111" => D <= Q1 xor Q0;  ---zoruj q1 I q0
    when others => D <= (others=>'0'); --jeśli inne podstaw 0
    end case; ---koniec case
    end process; --koniec procesu
    end Behavioral;--koniec architektury




    Mniej więcej tak to rozumiem w miejscach, w których miałem wątpliwości postawiłem "?"


    Signal Q0, Q1, Q2, Q3: std logic vector (7 downto 0) := (others=>’0’); ---- ?---- <--- Tymon_x o co chodzi do jakiego wektora to odwołanie ?

    0
  • #4 04 Lip 2010 22:39
    tymon_x
    Poziom 30  

    Błądzisz synu, Twoja droga jest kręta i wyboista, ale weź te kajdany oświaty i następnym razem umieszczaj kod w przystosowanych do tego znacznikach, bo zdenerwujesz God-moda (;

    library IEEE - deklarujemy użycie biblioteki z standardu IEEE, używamy do tego pakietu STD_LOGIC_1164, który nadaje nam zgodność z przyjętymi standardami języku opisu. Czyli każdy może go odpalić w dowolnym miejscu i czasie, i sprawdzić co w nim buczy. Natomiast STD_LOGIC_ARITH pozwala nam zamieniać np. wektory na liczby i odmwrotnie. A magiczny STD_LOGIC_UNSIGNED, definiuje na wektor jako liczby bez znaku, czyli 0b11111111 to 255 i podstawowe operacje na nich, dodawanie itp.

    entity - dla ścisłości deklaracja jednostki. To będzie jego robocza nazwa, powiedzmy słynny TTL 7400 (; Tam deklarujemy w liście sygnałów port jego nóżki (in, out, inout czasem buffer).

    architecture - architektura jednostki, czyli jak sprawić, aby nasz 7400 naprawdę zachowywał się jak 4 bramki NAND (; To tutaj po niej deklarujemy sygnały wewnętrzne i bloczki co coś tam robią process().

    Signal Q0, Q1, Q2, Q3: std logic vector (7 downto 0) := (others=>’0’); - tym awersem sprawiamy, że nasze cztery sygnały ośmiobitowe wewnątrz architektury, na starcie (po włączeniu zasilania/resetu), są inicjalizowane wartościami początkowymi, w tym wypadku jest to 0b00000000, czyli liczbowo zero.

    process() - to co jest w nawiasie nazywamy listą czułości. Dobrą praktyką jest umieszczanie tam wszystkich sygnałów wejściowych procesu, a jeśli ma być to bloczek synchroniczny bez resetu synchronicznego/asynchronicznego, musi być jakiś clock wraz instrukcją typu if risising_edge/false() then coś_ tam; end if;. Każde takie wyzwalanie sprawia, że coś w takim bloczku po if się wykonuje. Lista czułości to takie śmieszne cuś, że bloczek reaguje na każdą zmianę sygnałów wewnątrz tej listy.

    case - instrukcja wyboru. Trzeba użyć wszystkich możliwych wartości dopuszczalnych w sygnale/zmiennej. Czyli, aby syntezer nie wywalił Ci błędu, musisz podać wszystkie kombinacje nawet z "X", "Z" itp. I co mnie najbardziej ubawiło:

    fragment kodu napisał:
    when others => null; – w przeciwnym wypadku wyzeruj--
    Dla ścisłości, aby nie wypisywać wszystkich kombo-możliwości używamy słowa klucz others, czyli dla reszty możliwości ze słowem null, nie robi nic (;

    Ojoj, praca niesamodzielna, nawet braki posługiwaniu się komentarzami (; Opisujemy rzeczy, jakie ma wykonywać nasz program/opis/cokolwiek, a nie rzeczy uznawane za oczywistą oczywistość, typu: koniec architektury. Podałem Ci na tacy podstawową "wiedzę teoretyczną", potrzebny jest jeszcze "szlif praktyczny", czyli komentarze jak faktycznie to działa. Co to za studia, gdzie ma się trzy zajęcia w semestrze ?

    0
  Szukaj w 5mln produktów