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

[VHDL] Jednostka ALU z możliwością mnożenia i dzielenia.

lss 20 Kwi 2009 16:18 2708 7
REKLAMA
  • #1 6436737
    lss
    Poziom 21  
    Posty: 352
    Pomógł: 59
    Ocena: 20
    Witam wszystkich!!!

    Ten post będzie się składał z dwóch części:
    Pierwsza część postu
    -------------------------------------------------------------------------------
    1) Musze zrobić blok do mojego projektu lecz stanąłem w martwym punkcie. Konkretnie zatrzymałem się na bloku ALU który będzie odpowiadał za mnożenie dzielenie... musi się w nim dokonywać takie działanie C = A / (1,1 *B) lub C = (10*A) / (11*B). Kiedy biorę sprawdzanie kodu jest wszystko ok lecz później jest problem jak chce cały kod wrzucić w Spartana... Jest taki komunikat zwrotny:

    "Analyzing Entity <test> in library <work> (Architecture <behavioral>).
    ERROR:Xst:769 - "D:/Bibloteki/MATH/test.vhd" line 26: Operator <DIVIDE> must have constant operands or first operand must be power of 2"


    I nie wiem za nic w świecie co robić.

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

    entity test is
    Port ( we : in std_logic;
    C : out std_logic_vector(128 downto 0);-- 128 to wartość z palca wysłana no bie wiem jakiej długości się na razie tu spodziewać jest to w fazie testu
    B : in std_logic_vector(19 downto 0)
    );

    end test;

    architecture Behavioral of test is

    signal A: integer;
    signal temp1: integer;
    signal stala1 : integer :=2;
    signal stala2 : integer :=100000000;
    signal stala3 : integer :=10;
    signal stala4 : integer :=11;

    begin

    A <= (conv_integer(we)* stala1)/stala2;
    temp1 <= ( stala3 * A ) / ( stala4 * conv_integer(B));
    C <= conv_std_logic_vector(temp1, 128);

    end Behavioral;

    Ok krótki komentarz do kodu. Stale powprowadzałem większe 10 razy aby nie używac wartości real. Po prostu zamiast dawać 1,1 dałem 11 a A zwiększyłem 10 razy niby nic a pozbyłem się real... co co go używać jak zajmuje zbyt dużo zasobów układu...ale to na nawiasie

    Co mam z tym fantem zrobić...

    Druga część postu
    -------------------------------------------------------------------------
    2) Jak zamienić cały ciąg bitów po wyliczeniu C na wartość na wyświetlaczu. Moja propozycja jest na razie taka...
    Wynik będzie porównywany z tablicą (dekoder) którą napiszę a będzie to wyglądała mniej więcej tak

    Przykład

    Wartość C po obliczeniu w powyższym bloku będzie równa 101010000011110011101010110 skok do dekodera który sprawdzi mi jakiej wartości odpowiada... w tym przypadku załóżmy ze będzie to 400,000 [jednostka] ... Dokonał bym tego po przez sklejenie bo na płycie S3E (500) jest LCD i sprawdziłem jakim wartościom w tablicy odpowiadają liczby 0 do 9. Mam przed sobą specyfikacji LCD jest to "0011"MSB sklejenie & a reszta do 0000 do 1001 LSB i tak bym miał cyfry od zera do dziewięciu.
    Przecinek lub kropkę zapisać jako pełne słowo czyli 00101100 albo też przez sklejenie, aby unikać długiego klepania w klawiaturę

    Następny krok to dekoder

    000000000000000000000000000=>LCD<=S0,S0,S0,Sp,(Sk),S0,S0,S0;---000,000
    .
    .
    .
    101010000011110011101010110 =>LCD<= S4,S0,S0,Sp,(Sk),S0,S0,S0;--- 400,000
    .
    .
    .
    gdzie

    S0 :=0000;--0
    S1 :=0001;--1
    .
    .
    .
    S0 :=1001;--9
    Sp :="00101100"--przecinek
    Sk :="00101110" -- kropka

    Pierwsze pytanie do drugiej części

    Czy mój pomysł ma sens??

    Jak nie to jak by to można inaczej zrobić ???

    Drugie....

    Generując tak długi wektor nie ma jakiegoś patentu aby sam mi wypisał wszystkie kombinacja... a resztę mu sam dopisze tą z S???

    Pozdrawiam
    lss
  • REKLAMA
  • #2 6436969
    Zaquadnik
    Poziom 27  
    Posty: 998
    Pomógł: 103
    Ocena: 25
    Czytaj komunikaty błędów. Dzielenie jest niesyntezowalne, chyba, że oba agrumenty są stałe, wówczas podzieli je kompilator i zostaną zaimplementowane jako stałą, lub jest realizowane jako dzielenie przez potęgi dwójki, czyli przesuwanie w prawo o odpowiednią ilość bitów. Jeśli chcesz zrealizować dzielenie w FPGA to musisz albo zaprojektować układ dzielący i opisać jego działanie, albo skorzystać z gotowego IPcore. Poczytaj nieco o CORDIC, jest to algorytm iteracyjny umożliwiający realizację różnych działań matematycznych przy pomocy operacji dodawania i przesuwania bitowego.
  • REKLAMA
  • #3 6437318
    Dr.Vee
    VIP Zasłużony dla elektroda
    Posty: 1784
    Pomógł: 307
    Ocena: 76
    Co do drugiej części - wszystko byłoby ok, ale w liczbach binarnych moga znaleźć się są jeszcze inne ciągi bitów niż 0000 ... 1001 - i co wtedy?

    W tej chwili tak naprawdę wypisujesz reprezentację heksadecymalną liczby, oprócz tego, że pomijasz cyfry A-F. Jeśli chcesz wypisać reprezentację dziesiętną, to musisz przeprowadzić konwersję. Istnieje prosty algorytm iteracyjny który wykona konwersję bin->bcd.

    Po konwersji na bcd generujesz znaki ascii poprzez dodanie kodu znaku '0' (0x30) do cyfry i wysyłasz znaki na wyświetlacz.

    Pozdrawiam,
    Dr.Vee
  • REKLAMA
  • #4 6444245
    lss
    Poziom 21  
    Posty: 352
    Pomógł: 59
    Ocena: 20
    I tu jest pies pogrzebany z tym ALU... bo w gotowych IP Core jest coś związanego z CORDIC (Poczytałem o tym Zaquadnik, dziękować że rozszerzasz moje choryzonty)... lecz tylko pierwiastek, sinus i cosinus, tangens (sinush i cosinush, tangensh) Nie ma tam mowy nic o realizacji mnożenia i dzielenia obecnie te funkcje mnie nie interesują... Przeszukałem dokładnie IP Core (gotowce) i znalazłem tam bloki dzielące, sumujące, mnożące i w ogóle to co mnie interesuje:D... z tym że korzystanie z nich nakłada potężne użycie zasobów układu. Próbowałem skorzystać z jednego z nich wiele razy lecz sorry za określenie DU*A... Bo przy tworzeniu takiego bloku musisz mu podać jakąś długości, którą będzie mnożył czy też dzielił liczby i wynik końcowy jest stałą liczbą bitów końcowych, a ja będe miał je zmienne, bo A będzie się zmieniać jak i B. Będą zależne one od wielkości C badanej... I powiem stoję w miejscu.... Gdyby chodziło o wynik końcowy że ma stałą liczbę bitów to mi w to graj... ale te wejściowe...

    Dre.Veee -> dziękować za podpowiedz czyli miałem choć dobrą koncepcje :) teraz posiedzę w nocy i postudiuje ten materiał który podrzuciłeś... No i przerobie na VHDL...

    Może macie jakieś pomysły roziązania pozdrawiam
  • #5 6470623
    lss
    Poziom 21  
    Posty: 352
    Pomógł: 59
    Ocena: 20
    Chce odświeżyć temat bo mam problem ze zrozumieniem dzielenia. Jak
    dział dzielenie w układach cyfrowych...

    Przeczytałem kilka publikacji związanych z arytmetyką zmienno i
    stałoprzecinkową lecz mam problem dalej z tym. Od ostatniego posta
    jest lepiej bo prawie dostaje to co chce.

    Zastosowałem gotowy blok z IP Coregen. Przeczytałem do niego
    napisany data sheet i tu się zaczęły małe schody... miedzy tym co jest
    napisane w specyfikacji a w wynikach otrzymywanych przeze mnie. Jak
    dziele liczby np.


    * 9/4 to dostaje
    quotient: 00000010
    remainder:00000001

    powinno być 2,25 a jest z tego co liczę to jest 2,00390625 albo 2,5

    * 111/4 to dostaje
    quotient: 00011011
    remainder:00000011

    powinno być 27,75 a jest z tego co liczę to jest 27,01171875 albo 27,75
    -> to bym był pewien że pierwszy przykład jest po prostu jakimś błędem
    zaokrąglenia lecz nie

    * 111/7 to dostaje
    quotient: 00001111
    remainder:00000110

    powinno być ok. 15,86 a jest z tego co liczę to jest 15,0234375 albo
    15,375 zależy który przyjemy sobie bit LSB a który MSB w remaiderze
    (reszcie)

    Wyniki analizuje na diodach to raz a to kod jak wygląda

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

    entity box is
    Port(
    clk: IN std_logic;
    Cx: out std_logic_vector(7 downto 0);-- wynik
    RCx: out std_logic_vector(7 downto 0) -- reszta
    );

    end box;

    architecture Behavioral of box is

    signal a: std_logic_VECTOR(7 downto 0):= "01101111"; --dzielna 111
    signal b: std_logic_VECTOR(7 downto 0):= "00000111"; --dzielnik 7

    component div is --blok dzielący
    port (
    clk: IN std_logic;
    dividend: IN std_logic_VECTOR(7 downto 0);
    divisor: IN std_logic_VECTOR(7 downto 0);
    quotient: OUT std_logic_VECTOR(7 downto 0);
    remainder: OUT std_logic_VECTOR(7 downto 0);
    rfd: OUT std_logic);
    end component div;

    begin

    dzielnik: div Port Map (clk=>clk,
    dividend=>a,
    divisor=>b,
    quotient=>Cx,
    remainder=>RCx
    );
    end Behavioral;
    -----------------------------------------------------------------------------

    Jak mam interpretować resztę z dzielenia?? użyłem do tego bloku o
    stałoprzecinkowych i nie wiem czego tak wychodzi przecież do pewnego
    momentu jest ok czyli liczby po lewej. Co z tą resztą i czego się tak
    dzieje. Co można zrobić aby ten wynik był dokładniejszy. Zastanawiałem
    się nad blokiem zmiennoprzecinkowymi lecz on chyba będzie mi
    zbędny... Zajmuje za dużo bloków logicznych...

    Pozdrawiam
    L.
  • Pomocny post
    #6 6470772
    Dr.Vee
    VIP Zasłużony dla elektroda
    Posty: 1784
    Pomógł: 307
    Ocena: 76
    Eh kolego, nie uważałeś na matematyce?

    Dzielenie całkowitoliczbowe to $$Q \cdot D + R = X$$, gdzie Q (quotient) to iloraz, D (divisor) to dzielnik, R (remainder) to reszta, a X to dzielna. Żeby było tylko jedno rozwiązanie to zakłada się że $$R \in [0; D)$$. Dla liczb ujemnych są problemy ze znakami, więc to na razie pomińmy.

    Jeśli chcesz korzystać z reprezentacji stałoprzecinkowej, to poczytaj o formacie liczbowym Q. W największym skrócie - zależy Ci na 8 bitach po przecinku, więc oba argumenty dzielenia przesuwasz w lewo o 8 bitów, wykonesz dzielenie, następnie przesuwasz iloraz w prawo o 8 bitów i na najmłodszych 8 bitach masz część ułamkową dzielenia, a na pozostałych bitach część całkowitą.

    Pozdrawiam,
    Dr.Vee
  • REKLAMA
  • #7 6474943
    l_smolinski
    Poziom 11  
    Posty: 37
    Pomógł: 1
    Cytat:
    C = (10*A) / (11*B)


    Tak sobie patrze na to i przychodzi mi jeden artykuł do głowy, który ostatnio przeczytałem. Zbieg okoliczności czy twój laborant chce cię wykorzystać ??

    No a w core generator xilinxa masz ip cory dla arytmetyki zmiennoprzecinkowej (mnożenie i dzielenie).

    pozdrawiam.


    Link
  • #8 6474999
    lss
    Poziom 21  
    Posty: 352
    Pomógł: 59
    Ocena: 20
    No nie Dr.Vee zaczyna wyrastać na tym forum na mego idola... Odpowiedz w stu procentach wystarczająca -> Dr.Vee RULE. Szkoda że nie znam tego forumowicza osobiście bo bym wiele mógł się od niego nauczyć -> (jaka wazelina a cóż tak uważam) Nie wiem komu mogę postawić 0,5l ale pieć punktów przyznam jak to jest możliwe...

    Co do uważania w szkole podczas nauki dzielenia to byłem, prymusem ale widocznie nie potrafiłem tego przenieść na inne boisko -> matołem :) ze mnie

    l_smolinski -> wydaj mi się że to przypadek -> kto wie -> dzięki za artykuł poczytam z chęcią....

    Pytanie do Dr. Vee a jak by wyglądała konwersja liczb zmiennoprzecinkowych dodatnich na BCD a później wysyłanie na LCD ???

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik poszukuje rozwiązania problemu z implementacją jednostki ALU w VHDL na układzie FPGA Xilinx Spartan, która ma realizować działania mnożenia i dzielenia na zmiennych liczbach. Podczas syntezy występuje błąd Xst:769 informujący o ograniczeniach operatora dzielenia w VHDL, który dopuszcza jedynie dzielenie przez stałą lub potęgę dwójki. Rozwiązaniem jest implementacja własnego algorytmu dzielenia, skorzystanie z gotowych bloków IP core (np. z Xilinx Coregen) do arytmetyki całkowitoliczbowej lub zmiennoprzecinkowej, lub wykorzystanie algorytmów iteracyjnych jak CORDIC. Dyskusja objęła wyjaśnienie różnicy między dzieleniem całkowitoliczbowym a zmienno/stałoprzecinkowym oraz sposób reprezentacji ułamków przy użyciu formatu Q i przesunięć bitowych. Poruszono również temat konwersji wyników do formatu BCD dla wyświetlaczy LCD.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA