kroszkanorber Napisano Kwiecień 17, 2025 Udostępnij Napisano Kwiecień 17, 2025 Witam Przykładowy kod dla Sumatora z przypisywaną długością danych (assigned data leght). W kodzie użyłem pętli for by skrócić zapis informacji opisujących połączenia w układzie. Jest to mim zdaniem duże udogodnienie dla użytkownika i gdy zrozumiałem działanie tej funkcji używam jej często. Programiści znają tą pętlę doskonale lecz niektórzy mają problem z zastosowaniem w opisie sprzętu. Jeden ze sposobów użycia tej pętli dotyczy funkcji "generate". Przy używaniu tej funkcji oprogramowanie syntezy jest informowane jak mają wyglądać połączenia na przykład: między DataIn (Port wejść danych) a Zatrzask(Wewnętrzny zatrzask danych). Pętla for z funkcją generate na podstawie indeksu i iteruje przez wszystkie wybrane bity o numerze indeksu i w DataIn i przypisuje je do wybranych bitów o numerze indeksu i do Zatrzasku. I to w sumie tyle. Czego tu nie rozumieć? jest między c, c++ i vhdl zasadnicza różnica w wykonaniu poleceń. Synteza zachodzi analogicznie do kompilacji, ale w układach programowalnych nie możemy w ten sposób tworzyć układów sekwencyjnych. W języku vhd tworzone są w tym kodzie połączenia, a w języku c generowana jest iteracja dla procesora. W języku c procesor wykonuje polecenia jedno po drugim aż kod zostanie przerwany, a w układach cpld, fpga itp robi połączenia bo tam nie ma rdzenia procesora który mógłby wykonać te polecenia. Jedyne miejsce gdzie możemy użyć pętli by iterować przez polecenia analogicznie do wykonywania kodów w języku c to symulator i tam używamy zamiast słowa generate słowo loop na przykład tak : -- Pętla do generowania różnych kombinacji for i in 0 to n-1 loop G(i) <= '1'; P(i) <= '1'; wait for 10 ns; -- Opóźnienie na symulację G(i) <= '0'; P(i) <= '0'; end loop; -- no może nie do końca W kodzie użyłem też słowa generic dla zdefiniowania szerokości magistrali dla danych. Moim zdaniem bardzo przydatna funkcja. Generic ( n : integer := 8 przypisuje wartość 8 dla zmiennej n. Tą zmienną można manipulować zmieniając jej wartość w innych nadrzędnych blokach programu. Dzięki temu możemy we wszystkich sygnałach ze zmienną n zmienić ilość przypisanych linii wpisując wartość dla generic n. Bardzo elastyczne i mało wymagające rozwiązanie przy pisaniu kodu. Jak takich sygnałów mamy kilkadziesiąt to na pewno docenimy taki zapis... A oto kod dla sumatora w języku VHDL. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ADDER_adl is Generic ( n : integer := 8); -- szerokość szyny danych Port ( A : in STD_LOGIC_VECTOR (n - 1 downto 0); -- dane wejściowe B : in STD_LOGIC_VECTOR (n - 1 downto 0); -- dane wejściowe Q : out STD_LOGIC_VECTOR (n - 1 downto 0); -- dane wyjściowe AS : in STD_LOGIC; -- wybór instrukcji ADD = '0'/ SUB = '1' CI : in STD_LOGIC; -- wejście przeniesienia CO : out STD_LOGIC; -- wyjście przeniesienia Z : out STD_LOGIC; -- flaga 0 NE : out STD_LOGIC; -- flaga liczba ujemna OV : out STD_LOGIC); -- flaga przepełnienie end ADDER_adl; architecture Behavioral of ADDER_adl is signal RES : std_logic_vector (n - 1 downto 0); signal BX : std_logic_vector (n - 1 downto 0); signal CX : std_logic; signal P : std_logic_vector (n - 1 downto 0); signal G : std_logic_vector (n - 1 downto 0); signal C : std_logic_vector (n downto 0); begin -- Określenie operacji )dodawamie: B, odejmowanie: -B + 1) BX <= (not A) when (AS = '1') else B; CX <= (not CI) when (AS = '1') else CI; -- Obliczanie propagacji i generacji generic_pg : for i in 0 to (n - 1) generate P(i) <= A(i) xor BX(i); G(i) <= A(i) and BX(i); end generate; -- Obliczanie przeniesienia C(0) <= CX; generate_carry : for i in 0 to (n - 1) generate C(i + 1) <= G(i) or (P(i) and C(i)); end generate; -- Obliczanie sumy generate_sum : for i in 0 to (n - 1) generate RES(i) <= P(i) xor C(i); end generate; -- Dekoder bitów statusowych CO <= C(n); Z <= '1' when RES((n - 1) downto 0) = 0 else '0'; NE <= RES(n - 1); OV <= C(n) xor C(n - 1); -- wynik Q <= RES; end Behavioral; Pozdrawiam. 2
kroszkanorber Maj 12, 2025 Autor tematu Udostępnij Maj 12, 2025 witam. W kodzie który podałem wyżej wkradł się chochlik. (BX <= (not A) when (AS = '1') else B;) = źle / (BX <= (not B) when (AS = '1') else B;) = poprawnie; W kodzie w instrukcji odejmowania negujemy wejście B i dodajemy jeden, zamiast tego błędny zapis neguje wejście A. Rozbudowałem kod do prostej jednostki ALU w której zaimplementowałem funkcje : ADD AND OR XOR RRC RLC RR RL. RRC to przesunięcie w prawo najmłodszy bit jest zastąpiony wejściem CI najstarszy bit przesunięty jest do CO. RR przesuwa wszystkie bity w prawo najmłodszy bit przesunięty jest w miejsce najstarszego. RLC i RL to przesunięcie w lewo odpowiednio z uwzględnieniem bitu przeniesienia i bez bitu przeniesienia. Dla zainteresowanych kod : library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ALU_adl is Generic ( n : integer := 8); -- szerokość szyny danych Port ( A : in STD_LOGIC_VECTOR (n - 1 downto 0); -- dane wejściowe B : in STD_LOGIC_VECTOR (n - 1 downto 0); -- dane wejściowe Q : out STD_LOGIC_VECTOR (n - 1 downto 0); -- dane wyjściowe S : in STD_LOGIC_VECTOR (2 downto 0); -- wybór operacji AS : in STD_LOGIC; -- wybór instrukcji ADD = '0'/ SUB = '1' CI : in STD_LOGIC; -- wejście przeniesienia CO : out STD_LOGIC; -- wyjście przeniesienia Z : out STD_LOGIC; -- flaga 0 NE : out STD_LOGIC; -- flaga liczba ujemna OV : out STD_LOGIC); -- flaga przepełnienie end ALU_adl; architecture Behavioral of ALU_adl is signal RES : std_logic_vector (n - 1 downto 0); signal BX : std_logic_vector (n - 1 downto 0); signal CX : std_logic; signal P : std_logic_vector (n - 1 downto 0); signal G : std_logic_vector (n - 1 downto 0); signal O : std_logic_vector (n - 1 downto 0); signal R : std_logic_vector (n - 1 downto 0); signal L : std_logic_vector (n - 1 downto 0); signal RC : std_logic_vector (n - 1 downto 0); signal LC : std_logic_vector (n - 1 downto 0); signal C : std_logic_vector (n downto 0); begin -- Określenie operacji )dodawamie: B, odejmowanie: -B + 1) BX <= (not B) when (AS = '1') else B; CX <= (not CI) when (AS = '1') else CI; -- Obliczanie propagacji i generacji generic_pg : for i in 0 to (n - 1) generate P(i) <= A(i) xor BX(i); G(i) <= A(i) and BX(i); O(i) <= A(i) or BX(i); end generate; -- Obliczanie przeniesienia C(0) <= CX; generate_carry : for i in 0 to (n - 1) generate C(i + 1) <= G(i) or (P(i) and C(i)); end generate; -- Obliczanie sumy generate_sum : for i in 0 to (n - 1) generate RES(i) <= P(i) xor C(i); end generate; -- Przesunięcie w prawo R <= A(0) & A(n - 1 downto 1); -- Przesunięcie w prawo + C RC <= CI & A(n - 1 downto 1); -- Przesunięcie w lewo L <= A(n - 2 downto 0) & A(n - 1); -- Przesunięcie w lewo + C LC <= A(n - 2 downto 0) & CI; -- Dekoder bitów statusowych Z <= '1' when RES((n - 1) downto 0) = 0 else '0'; NE <= RES(n - 1); OV <= C(n) xor C(n - 1); -- wynik with S select Q <= RES when "000", -- ADD P when "001", -- XOR G when "010", -- AND O when "011", -- OR RC when "100", -- RRC LC when "101", -- RLC R when "110", -- RR L when others; -- RL -- CO with S select CO <= A(0) when "100", A(n - 1) when "101", C(n) when others; end Behavioral;
kroszkanorber 2 lutego Autor tematu Udostępnij 2 lutego (edytowany) Witam. Zaimplementowałem jednostkę ALU w układzie CPLD. Kość XC9536XL-10 VQ44. Architektura 8 bitowa z podstawowymi funkcjami jest moim zdaniem lepsza od kultowego 181... Budując układy oparte na architekturze retro i trzymanie się oryginalnych układów w imię ideologii nie jest moim priorytetem. Nie testowałem układu i jestem ciekawy, czy można upchnąć więcej instrukcji w takim układzie... Kod programu: ADD/SUB zawsze wykonuje operację sumy wyrażeń A i B CI : wjście przeniesienia. Z : flaga zero C : flaga przepełnienia wyniku sumatora, lub rotacja przez carry N : flaga znak liczby w kodzie U2 OV: flaga przepełnienie dla liczby U2 w sumatorze AS : wybór odejmowanie = 1, dodawanie = 0. Nie ma wpływu na resztę funkcji S : wybór funkcji 1 z 8 EN : Aktywacja wyjść. (wyjścia dwustanowe, nieaktywne = 0) F : wynik wybranej funkcji -- S EN -- 000 1 F = ADD/SUB -- 001 1 F = A AND B -- 010 1 F = A OR B -- 011 1 F = A XOR B -- 100 1 F = ROL A -- 101 1 F = ROR A -- 110 1 F = RCL C < A < Ci -- 111 1 F = RCR Ci > A > C -- SSS 0 F = 0 -- 1 C = Cen -- 0 C = 0 -- 1 Z = Zen -- 0 Z = 0 -- 1 OV = OVen -- 0 OV = 0 -- AS -- 1 SUB -- 0 ADD library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ALU9536XL is Port ( A : in STD_LOGIC_VECTOR (7 downto 0); B : in STD_LOGIC_VECTOR (7 downto 0); S : in STD_LOGIC_VECTOR (2 downto 0); AS : in STD_LOGIC; CI : in STD_LOGIC; EN : in STD_LOGIC; C : out STD_LOGIC; Z : out STD_LOGIC; N : out STD_LOGIC; OV : out STD_LOGIC; F : out STD_LOGIC_VECTOR (7 downto 0)); end ALU9536XL; architecture Behavioral of ALU9536XL is signal SE : std_logic_vector (7 downto 0); signal E8 : std_logic_vector (8 downto 0); signal BX : std_logic_vector (8 downto 0); signal E7 : std_logic_vector (7 downto 0); signal A7 : std_logic_vector (7 downto 0); signal O7 : std_logic_vector (7 downto 0); signal X7 : std_logic_vector (7 downto 0); signal R7 : std_logic_vector (7 downto 0); signal L7 : std_logic_vector (7 downto 0); signal LC : std_logic_vector (7 downto 0); signal RC : std_logic_vector (7 downto 0); signal FE : std_logic_vector (7 downto 0); signal CX : std_logic; signal CR : std_logic; signal CL : std_logic; signal CE : std_logic; signal Fen : std_logic_vector (7 downto 0); signal Cen : std_logic; signal Zen : std_logic; signal Nen : std_logic; signal OVen : std_logic; begin with S select SE <= "00000001" when "000", -- 000 ADD/SUB "00000010" when "001", -- 001 AND "00000100" when "010", -- 010 OR "00001000" when "011", -- 011 XOR "00010000" when "100", -- 100 ROL "00100000" when "101", -- 101 ROR "01000000" when "110", -- 110 RCL "10000000" when others;-- 111 RCR BX <= ('0' & B) xor (8 downto 0 => AS); CX <= CI xor AS; E8 <= ('0' & A) + BX + CX; CE <= E8(8) and SE(0); CR <= A(0) and SE(7); CL <= A(7) and SE(6); E7 <= E8(7 downto 0) and (7 downto 0 => SE(0)); A7 <= (A and B) and (7 downto 0 => SE(1)); O7 <= (A or B) and (7 downto 0 => SE(2)); X7 <= (A xor B) and (7 downto 0 => SE(3)); L7 <= (A(6 downto 0) & A(7)) and (7 downto 0 => SE(4)); R7 <= (A(0) & A(7 downto 1)) and (7 downto 0 => SE(5)); LC <= (A(6 downto 0) & CI) and (7 downto 0 => SE(6)); RC <= (CI & A(7 downto 1)) and (7 downto 0 => SE(7)); FE <= E7 or A7 or O7 or X7 or R7 or L7 or LC or RC; Cen <= (CE or CR or CL) and EN; Fen <= FE and (7 downto 0 => EN); Zen <= (not (FE(7) or FE(6) or FE(5) or FE(4) or FE(3) or FE(2) or FE(1) or FE(0))) and EN; Nen <= FE(7) and EN; OVen <= (E8(8) xor E8(7)) and EN; F <= Fen; C <= Cen; Z <= Zen; N <= Nen; OV <= OVen; end Behavioral; Edytowano 3 lutego przez kroszkanorber 1
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »