a) Full-Adder devresini VHDL kullanarak gerçekleyiniz.
Bunun için öncelikle bize bir Half-Adder bloğu gereklidir.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity HA is Port ( a : in STD_LOGIC; b : in STD_LOGIC; s : out STD_LOGIC; c : out STD_LOGIC); end HA; architecture Behavioral of HA is begin s <= a xor b; c <= a and b; end Behavioral;
Bu Half-Adder bloğu kullanılarak Full-Adder oluşturursak,
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity FA is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c_in : in STD_LOGIC; s : out STD_LOGIC; c_out : out STD_LOGIC); end FA; architecture Behavioral of FA is component HA is Port ( a : in STD_LOGIC; b : in STD_LOGIC; s : out STD_LOGIC; c : out STD_LOGIC); end component; Signal sum1 : STD_LOGIC; Signal carry1 : STD_LOGIC; Signal carry2 : STD_LOGIC; begin HA1 : HA port map(a=>a,b=>b,s=>sum1,c=>carry1); HA2 : HA port map(a=>c_in,b=>sum1,s=>s,c=>carry2); c_out <= carry1 or carry2; end Behavioral;
Full-Adder devresi Testbench kodu:
entity TB_FA is -- Port ( ); end TB_FA; architecture Behavioral of TB_FA is component FA is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c_in : in STD_LOGIC; s : out STD_LOGIC; c_out : out STD_LOGIC); end component; Signal a,b,c_in,s,c_out : STD_LOGIC; begin FA1 : FA port map(a=>a,b=>b,c_in=>c_in,s=>s,c_out=>c_out); process begin a <= '1'; b <= '0'; c_in <= '0'; wait for 50ns; a <= '1'; b <= '1'; c_in <= '1'; wait for 50ns; end process; end Behavioral;
b) Gerçeklemesini yaptığınız Full-Adder devresini kullanarak GENERATE statement yardımıyla iki tane 64 bitlik sayıyı toplayan bir adder fonksiyonunu VHDL kullanarak gerçekleyiniz. Gerçeklemesini yapacağınız adder devresinin girişleri A_IN,B_IN (64bit), çıkışları SUM_OUT (64 bit), CARRY_OUT (1 bit) olacaktır. (ADDER_64.vhd)
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity ADDER_64 is Port ( A_IN : in STD_LOGIC_VECTOR (63 downto 0); B_IN : in STD_LOGIC_VECTOR (63 downto 0); SUM_OUT : out STD_LOGIC_VECTOR (63 downto 0); CARRY_OUT : out STD_LOGIC); end ADDER_64; architecture Behavioral of ADDER_64 is component FA is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c_in : in STD_LOGIC; s : out STD_LOGIC; c_out : out STD_LOGIC); end component; Signal CARRY : STD_LOGIC_VECTOR (63 downto 0); begin FA0 : FA port map( a=>A_IN(0), b=>B_IN(0), c_in=>'0', s=>SUM_OUT(0), c_out=>carry(0)); G : for i in 1 to 63 generate begin U : FA port map( a=>A_IN(i), b=>B_IN(i), c_in=>carry(i-1), s=>SUM_OUT(i), c_out=>carry(i)); end generate G; CARRY_OUT <= carry(63); end Behavioral;
Testbench kodu:
entity TB_ADDER_64 is -- Port ( ); end TB_ADDER_64; architecture Behavioral of TB_ADDER_64 is component ADDER_64 is Port ( A_IN : in STD_LOGIC_VECTOR (63 downto 0); B_IN : in STD_LOGIC_VECTOR (63 downto 0); SUM_OUT : out STD_LOGIC_VECTOR (63 downto 0); CARRY_OUT : out STD_LOGIC); end component; Signal a,b,s : STD_LOGIC_VECTOR (63 downto 0); Signal c_out : STD_LOGIC; begin FA64 : ADDER_64 port map(A_IN=>a,B_IN=>b,SUM_OUT=>s,CARRY_OUT=>c_out); process begin a <= X"00000000_0000001F"; b <= X"00000000_000000AF"; wait for 50ns; a <= X"00000000_000000FF"; b <= X"00000000_0000001F"; wait for 50ns; a <= X"FFFFFFFF_FFFFFFF0"; b <= X"00000000_0000001F"; wait for 50ns; end process; end Behavioral;
Simulasyon sonucu
FPGA üzerinde girdi-çıktı sinyalinin izlediği yol
c) 64 bit’lik Full-Adder devresini, CARRY-LOOKAHEAD ADDER yöntemi ile gerçekleyiniz. (ADDER_CARRY_LOOKAHEAD.vhd)
entity ADDER_CARRY_LOOKAHEAD is Port ( A_IN : in STD_LOGIC_VECTOR (63 downto 0); B_IN : in STD_LOGIC_VECTOR (63 downto 0); SUM_OUT : out STD_LOGIC_VECTOR (63 downto 0); CARRY_OUT : out STD_LOGIC); end ADDER_CARRY_LOOKAHEAD; architecture Behavioral of ADDER_CARRY_LOOKAHEAD is component FA is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c_in : in STD_LOGIC; s : out STD_LOGIC; c_out : out STD_LOGIC); end component; Signal G : STD_LOGIC_VECTOR (63 downto 0); -- GENERATE Signal P : STD_LOGIC_VECTOR (63 downto 0); -- PROPOGATE Signal C : STD_LOGIC_VECTOR (64 downto 0); -- CARRY Signal tempC : STD_LOGIC_VECTOR (63 downto 0); -- TEMP CARRY begin GEN1 : for i in 0 to 63 generate begin U : FA port map( a=>A_IN(i), b=>B_IN(i), c_in=>C(i), s=>SUM_OUT(i), c_out=>tempC(i)); end generate GEN1; C(0) <= '0'; GEN2 : for j in 0 to 63 generate begin G(j) <= A_IN(j) and B_IN(j); P(j) <= A_IN(j) or B_IN(j); C(j+1) <= G(j) or (P(j) and C(j)); end generate GEN2; CARRY_OUT <= C(64); end Behavioral;
d) 64 bit’lik Full-Adder devresini, CARRY-LOOKAHEAD ADDER yöntemi ile gerçekleyiniz. Multiplexer’ları gerçeklemek amacıyla WITH-SELECT statement kullanınız. (ADDER_CARRY_LOOKAHEAD_WS.vhd)
Full-Adder bloğu
entity FA_WS is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c_in : in STD_LOGIC; s : out STD_LOGIC; c_out : out STD_LOGIC); end FA_WS; architecture Behavioral of FA_WS is Signal axorb : STD_LOGIC; begin axorb <= a xor b; s <= axorb xor c_in; with axorb select c_out <= c_in when '1', a when others; end Behavioral;
Adder bloğu
entity ADDER_CARRY_LOOKAHEAD_WS is Port ( A_IN : in STD_LOGIC_VECTOR (63 downto 0); B_IN : in STD_LOGIC_VECTOR (63 downto 0); SUM_OUT : out STD_LOGIC_VECTOR (63 downto 0); CARRY_OUT : out STD_LOGIC); end ADDER_CARRY_LOOKAHEAD_WS; architecture Behavioral of ADDER_CARRY_LOOKAHEAD_WS is component FA_WS is Port ( a : in STD_LOGIC; b : in STD_LOGIC; c_in : in STD_LOGIC; s : out STD_LOGIC; c_out : out STD_LOGIC); end component; Signal C : STD_LOGIC_VECTOR (64 downto 0); -- CARRY begin C(0) <= '0'; GEN1 : for i in 0 to 63 generate begin U : FA_WS port map( a=>A_IN(i), b=>B_IN(i), c_in=>C(i), s=>SUM_OUT(i), c_out=>C(i+1)); end generate GEN1; CARRY_OUT <= C(64); end Behavioral;
FPGA üzerinde girdi-çıktı sinyalinin izlediği yol
e) 64 bit’lik Full-Adder devresini, CARRY-LOOKAHEAD ADDER yöntemi ile Virtex-7 serisi FPGA’ların CARRY4 makrosunu kullanarak gerçekleyiniz (ADDER_CARRY_LOOKAHEAD_MACRO.vhd). CARRY4 makrosunun nasıl instantiate edileceği ile bilgiyi aşağıdaki linkte bulabilirsiniz:
CARRY4 Makrosu
entity ADDER_CARRY_LOOKAHEAD_MACRO is Port ( A_IN : in STD_LOGIC_VECTOR (63 downto 0); B_IN : in STD_LOGIC_VECTOR (63 downto 0); SUM_OUT : out STD_LOGIC_VECTOR (63 downto 0); CARRY_OUT : out STD_LOGIC); end ADDER_CARRY_LOOKAHEAD_MACRO; architecture Behavioral of ADDER_CARRY_LOOKAHEAD_MACRO is Signal CARRY : STD_LOGIC_VECTOR (63 downto 0); Signal AXORB : STD_LOGIC_VECTOR (63 downto 0); begin GEN1 : for i in 0 to 63 generate begin AXORB(i) <= A_IN(i) xor B_IN(i); end generate GEN1; U0 : CARRY4 port map ( CO => CARRY(3 downto 0), -- 4-bit carry out O => SUM_OUT(3 downto 0), -- 4-bit carry chain XOR data out CI => '0', -- 1-bit carry cascade input CYINIT => '0', -- 1-bit carry initialization DI => B_IN(3 downto 0), -- 4-bit carry-MUX data in S => AXORB(3 downto 0) -- 4-bit carry-MUX select input ); GEN2 : for i in 1 to 15 generate begin U : CARRY4 port map ( CO => CARRY((4*(i+1)-1) downto (4*i)), -- 4-bit carry out O => SUM_OUT((4*(i+1)-1) downto (4*i)), -- 4-bit carry chain XOR data out CI => CARRY(4*i-1), -- 1-bit carry cascade input CYINIT => '0', -- 1-bit carry initialization DI => B_IN((4*(i+1)-1) downto (4*i)), -- 4-bit carry-MUX data in S => AXORB((4*(i+1)-1) downto (4*i)) -- 4-bit carry-MUX select input ); end generate GEN2; CARRY_OUT <= CARRY(63); end Behavioral;
FPGA üzerinde girdi-çıktı sinyalinin izlediği yol
f) IEEE_STD_LOGIC_ARITH.ALL ve IEEE_STD_LOGIC_UNSIGNED.ALL paketleri ‘+’ operatörünün toplama yaparken kullanılmasına imkan vermektedir. Bu paketlerin vhdl kodları aşagıdaki klasörde yer alır.
<Xilinx kurulum klasörü>\Vivado\<2015.4>\data\vhdl\src\ieee\distributable
64 bitlik adder devresini + operatörünü kullanarak, girişleri INTEGER’a çevirerek gerçekleştiriniz. (ADDER_PLUS_SIGN.vhd)
Burada iki integer toplanacak, daha sonra STD_LOGIC’e geri çevirilecek. Değişkenleri STD_LOGIC’den INTEGER’a çevirmek, INTEGER’dan STD_LOGIC’e dödürmek için aşağıdaki fonksiyonlara ihtiyacınız olacaktır. Bunlar yukarıdaki kütüphanelerde tanımlıdır.
function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER)
return STD_LOGIC_VECTOR
function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER
Önemli Not: 64 bit’lik integer yoktur!
Full-Adder bloğu
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity FA_PLUS is Port ( A_IN : in STD_LOGIC_VECTOR (15 downto 0); B_IN : in STD_LOGIC_VECTOR (15 downto 0); CARRY_IN : in STD_LOGIC; SUM_OUT : out STD_LOGIC_VECTOR (15 downto 0); CARRY_OUT : out STD_LOGIC); end FA_PLUS; architecture Behavioral of FA_PLUS is Signal A : integer; Signal B : integer; Signal CARRY : integer; Signal SUM : integer; Signal TEMP_SUM : STD_LOGIC_VECTOR (16 downto 0); begin A <= CONV_INTEGER(A_IN); B <= CONV_INTEGER(B_IN); CARRY <= CONV_INTEGER(CARRY_IN); SUM <= A + B + CARRY; TEMP_SUM <= CONV_STD_LOGIC_VECTOR(SUM, 17); SUM_OUT <= TEMP_SUM(15 downto 0); CARRY_OUT <= TEMP_SUM(16); end Behavioral;
Adder bloğu
entity ADDER_PLUS_SIGN is Port ( A_IN : in STD_LOGIC_VECTOR (63 downto 0); B_IN : in STD_LOGIC_VECTOR (63 downto 0); SUM_OUT : out STD_LOGIC_VECTOR (63 downto 0); CARRY_OUT : out STD_LOGIC); end ADDER_PLUS_SIGN; architecture Behavioral of ADDER_PLUS_SIGN is component FA_PLUS is Port ( A_IN : in STD_LOGIC_VECTOR (15 downto 0); B_IN : in STD_LOGIC_VECTOR (15 downto 0); CARRY_IN : in STD_LOGIC; SUM_OUT : out STD_LOGIC_VECTOR (15 downto 0); CARRY_OUT : out STD_LOGIC); end component; Signal TEMP_CARRY : STD_LOGIC_VECTOR (3 downto 0); begin FA0 : FA_PLUS port map( A_IN=>A_IN(15 downto 0), B_IN=>B_IN(15 downto 0), CARRY_IN=>'0', SUM_OUT=>SUM_OUT(15 downto 0), CARRY_OUT=>TEMP_CARRY(0)); FA1 : FA_PLUS port map( A_IN=>A_IN(31 downto 16), B_IN=>B_IN(31 downto 16), CARRY_IN=>TEMP_CARRY(0), SUM_OUT=>SUM_OUT(31 downto 16), CARRY_OUT=>TEMP_CARRY(1)); FA2 : FA_PLUS port map( A_IN=>A_IN(47 downto 32), B_IN=>B_IN(47 downto 32), CARRY_IN=>TEMP_CARRY(1), SUM_OUT=>SUM_OUT(47 downto 32), CARRY_OUT=>TEMP_CARRY(2)); FA3 : FA_PLUS port map( A_IN=>A_IN(63 downto 48), B_IN=>B_IN(63 downto 48), CARRY_IN=>TEMP_CARRY(2), SUM_OUT=>SUM_OUT(63 downto 48), CARRY_OUT=>TEMP_CARRY(3)); CARRY_OUT <= TEMP_CARRY(3); end Behavioral;
FPGA üzerinde girdi-çıktı sinyalinin izlediği yol
SONUÇ
XDC dosyası kullanılarak hesaplanan zamanlama değerleri nano saniye cinsinden aşağıdaki tabloda verilmiştir. Burada CLA kısaltması CARRY_LOOKAHEAD, ADDER_CLA_WS ise soruda d şıkkında istenen “with – select” statement’ı ile hazırlanan 64 bitlik Carry lookahead modülüdür. Tablo başlıklarında kullanılan kısaltmalar optimizasyon çeşitlerine karşılık gelmektedir. Burada “D” default değerlere, “P” performans altındaki optimizasyonlara, “F” ise Flow altındaki optimizasyonlara karşılık gelmektedir. Ek olarak, örneğin dördüncü kolonda kullanılan “D-P(Explore)” başlığı, sentez ayarlarının Default, Implement ayarlarının Performance(Runtime) optimizasyonu altında yapıldığını göstermektedir. Buna göre farklı optimizasyon çeşitleri ve varsayılan ayarlara göre yapılan sentez ve implementasyon sonucunda hesaplanan süre değerleri aşağıdaki gibidir. Burada farklı optimizasyon çeşitleri eğer süre olarak ciddi bir fark yaratmıyorsa, not edilmemiştir.
Burada en hızlı sonuç integer değişkenlerin kullanıldığı ADDER_PLUS_SIGN modülünden elde edilmiştir. Daha sonra ise CARRY4 makrosu kullanan modülden oldukça yakın bir süre elde edilmiştir. Bu iki bloğun diğerleri ile neredeyse yarı yarıya hızlı çalışmasının sebebi, bu blokta kullanılan toplama işlemi ve CARRY4 bloğunun toplama işlemine özel olarak optimize edilmiş olan belirli blokları kullanıyor olmasıdır. Özellikle PLUS_SIGN bloğu içerisinde yapılan tek satırda yazılan üç elemanın toplama işlemi sentezleyici tarafından carry-in içeren tek bir toplama modülüne çevrilmiş olup, böylece ciddi bir hızlanma elde edilmiştir. Ek olarak, bu bloklar çip üzerinde birbirine yakın lokasyonlarda bulunmakta, böylece iletişimi de ciddi anlamda hızlandırmaktadır. Diğer toplayıcı türlerinin, özellikle “with-select” statement kullanılan toplayıcının, kullandığı bloklarının çip içindeki yerleşimine bakıldığında ciddi anlamda optimizasyona açık olduğu kolayca görülebilmektedir. Bu bloklarda kullanılan alt blokların çip içerisinde daha iyi konumlandırılabileceği ve daha kısa mesafeler ile haberleştirilebileceği açıkça görülebilmektedir. İmplementasyon sonucu oluşan DATA_IN-CARRY_OUT veri yolu ve kullanılan SLICE’lar farklı devreler için aşağıda gösterilmiştir.