FPGA ile İşlemci Tasarımı / BT-I / #4 (Program Counter)

Program counter yani program sayacı, yürütülecek komutun ROM üzerindeki adresini taşır. Her bir cycle'da değeri komut seti uzunluğu olan 2 Byte kadar artar. Tasarımı şu şekildedir:

PC: Program counter registeri. 16 tane D tipi flip-flop'tan oluşur. VHDL kodu şu şekildedir:

D tipi Flip-Flop:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity D_FF is
    PORT(Clk : in std_logic; --Clock girişi
        D : in std_logic;    --Data girişi
        Q :out std_logic);   --Data çıkışı
end D_FF;

architecture Behavioral of D_FF is

    signal QSignal : std_logic := '0';

begin
        process(Clk)
        begin
            if rising_edge(Clk) then --Clockun yükselen kenarı ile
                QSignal <= D;        --Data girişindeki veriyi QSignal'e at
            end if;
        end process;
        
        Q <= QSignal;    --QSignal'i Data çıkışına bağla
end Behavioral;

PC Registeri:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity PC_Register is
    PORT(Clk : in std_logic;                            --Clock sinyali
        Data_In : in std_logic_vector(15 downto 0);     --Data girişi
        Data_Out : out std_logic_vector(15 downto 0));  --Data çıkışı
end PC_Register;


architecture Behavioral of PC_Register is

--Komponent tanımlaması
component D_FF            
    PORT(Clk : in std_logic;
        D : in std_logic;
        Q :out std_logic);
end component;

begin
--16 tane D tipi Flip-Flop u paralel şekilde bağla
            U1 : for i in 0 to 15 generate
                U1 : D_FF PORT MAP(Clk, Data_In(i), Data_Out(i));
            end generate;
end Behavioral;

Toplayıcı: 16 tane Full-Adder'dan oluşur. VHDL kodu şu şekildedir:

Full-Adder:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity FA is
    port(A, B, Cin : in std_logic; --Girişler
        O, Cout : out std_logic);  --Çıkışlar
end FA;

architecture Behavioral of FA is
    signal AxorB : std_logic;
begin
--Tam toplayıcı
    AxorB <= A xor B;
    O <= AxorB xor Cin;
    Cout <= (A and B) or (AxorB and Cin);
end Behavioral;

16-Bitlik toplayıcı:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Adder_16 is
    port(A, B : in std_logic_vector(15 downto 0); --16 bitlik girişler
        O : out std_logic_vector(15 downto 0));   --Çıkış
end Adder_16;

architecture Behavioral of Adder_16 is

--Komponent tanımlaması
component FA
    port(A, B, Cin : in std_logic;
        O, Cout : out std_logic);
end component;

--Elde sinyalleri
    signal Carry : std_logic_vector(16 downto 0) := (others => '0');

begin
--Full-Adder ların birleştirilmesi
        U1: for i in 0 to 15 generate
            U1 : FA PORT MAP(A(i), B(i), Carry(i), O(i), Carry((i + 1)));
        end generate;

--Toplamanın işaretli olabilmesi için B sinyalinin işaret biti
--toplayıcının elde girişine bağlanır. Bu sayede "1...." şeklinde
--bir sinyal girdiğinde çıkarma işlemi yapılır.    
        Carry(0) <= B(15);
        
end Behavioral;

Modüllerin birleştirilmesi:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Program_Counter is
    PORT(Clk : in std_logic;                           --Clock girişi
        Rl_Address : in std_logic_vector(7 downto 0);  --Relatif adres girişi
        Im_Address : in std_logic_vector(15 downto 0); --Direkt adres girişi
        Branch_Sel : in std_logic_vector(1 downto 0);  --Dallanma seçimi girişi
        PC : out std_logic_vector(15 downto 0));       --Program adresi çıkışı
end Program_Counter;


architecture Behavioral of Program_Counter is

--Komponent tanımlamaları
component PC_Register
    PORT(Clk : in std_logic;
        Data_In : in std_logic_vector(15 downto 0);
        Data_Out : out std_logic_vector(15 downto 0));
end component;

component Adder_16
    PORT(A, B : in std_logic_vector(15 downto 0);
        O : out std_logic_vector(15 downto 0));
end component;

    signal PC_In : std_logic_vector(15 downto 0);
    signal PC_Out : std_logic_vector(15 downto 0);
    signal PC_Sum_Out : std_logic_vector(15 downto 0);
    signal SumL : std_logic_vector(7 downto 0);
    signal SumH : std_logic_vector(7 downto 0);
    signal Mux_Sel : std_logic_vector(1 downto 0);
    
begin
--PC registerinin oluşturulması
    PC_Reg : PC_Register
        PORT MAP(Clk, PC_In, PC_Out);

--Toplayıcı modülün oluşturulması        
    Adder : Adder_16
        PORT MAP(PC_Out, SumH & SumL, PC_Sum_Out);

--Relatif adres ile X"02" arasında seçim yapan mux    
    with Mux_Sel(0) select
        SumL <= X"02" when '0',
                  Rl_Address when others;

--Relatif adrese gelen direkt veri 8 bitlik olduğundan
--bu verinin toplayıcı için 16 bitlik veriye dönüştürülmesi
--gerekir. Burada direkt verinin 7. bitinin değeri, 8-15 bitlerine
--aktarılır.                  
    U1 : for i in 0 to 7 generate
        SumH(i) <= SumL(7);
    end generate;

--Direkt dallanma için seçim yapan mux    
    with Mux_Sel(1) select
        PC_In <= PC_Sum_Out when '0',
                    Im_Address when others;
    
    PC <= PC_Out;
    
    Mux_Sel(0) <= Branch_Sel(0) and (not Branch_Sel(1));
    Mux_Sel(1) <= Branch_Sel(0) and Branch_Sel(1);
        
end Behavioral;

Aşağıda Quartus II programının oluşturduğu RTL modelleri görülmektedir:

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir