Skip to main content

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;

fa_tb

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

adder64_tb

FPGA üzerinde girdi-çıktı sinyalinin izlediği yol

ADDER_64

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

ADDER_CLA_WS

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

ADDER_MACRO

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

ADDER_PLUS_SIGN

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.

vhdl_adder_comparison

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.