Skocz do zawartości

Przykładowy program ADDER _adl VHDL


Pomocna odpowiedź

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.

  • Lubię! 2
Link do komentarza
Share on other sites

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;

 

Link do komentarza
Share on other sites

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ę »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.