CPU Design: Đơn vị xử lý dữ liệu Datapath

 
Giới thiệu     
Trong bộ vi xử lý, Đơn vị xử lý dữ liệu Datapath thực hiện tất cả phép tính được yêu cầu bởi bộ vi xử lý. Datapath thường được cấu thành bởi các mạch để thực hiện các toán tử số học (cộng, trừ, nhân, so sánh …) và các phép tính logic (and, or, ..), các bộ hợp kênh và phân kênh để điều hướng luồng dữ liệu, các phần tử nhớ (thường là các thanh ghi) để lưu dữ liệu và kết quả trung gian trong quá trình vi xử lý hoạt động. Bài này giới thiệu quá trình thiết kế và thực hiện đơn vị xử lý dapath trong loạt bài về hướng dẫn thiết kế CPU (CPU Design). 
1. Thiết kế đơn vị số học và logic ALU
 
      Các phép tính được hỗ trợ bởi ALU
 
ALUs
ALUr
00
OPr1 + OPr2
01
OPr1 – Opr2
10
OPr1 OR OPr2
11
OPr1 AND OPr2
2. Tệp thanh ghi RF
3. Mã nguồn VHDL
Table 1. ALU.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use WORK.MICROPROCESSOR_LIB.ALL;
— Uncomment the following library declaration if using
— arithmetic functions with Signed or Unsigned values
–use IEEE.NUMERIC_STD.ALL;

Uncomment the following library declaration if instantiating

any Xilinx leaf cells in this code.
–library
UNISIM;
–use
UNISIM.VComponents.all;
entity
ALU is
    Port ( OPr1 : in STD_LOGIC_VECTOR
(DATA_WIDTH – 1 downto 0);
           OPr2 : in STD_LOGIC_VECTOR
(DATA_WIDTH – 1 downto 0);
           ALUs : in STD_LOGIC_VECTOR (1
downto 0);
           ALUr : out STD_LOGIC_VECTOR
(DATA_WIDTH – 1 downto 0);
           ALUz : out STD_LOGIC;
           ALUeq: out STD_LOGIC;
           ALUgt : out STD_LOGIC
        );
end
ALU;
architecture
ALU of ALU is
signal
result : STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
begin
    process(ALUs, Opr1, Opr2)
    begin
        case(ALUs) is
            when “00” => — Add
                result <= OPr1 + OPr2;
            when “01” => — Sub
OPr1 – OPr2
                result <= OPr1 – OPr2;
            when “10” =>
                result <= OPr1 or OPr2;
            when “11” =>
                result <= OPr1 and OPr2;
          
            when others => — Preset
                result <= (others =>
‘1’);
        end case;
    end process;
    ALUr <= result;
    ALUz <= ‘1’ when OPr1 =
x”0000″ else ‘0’;
    ALUeq <= ‘1’ when OPr1 = OPr2 else
‘0’;
    ALugt <= ‘1’ when OPr1 > OPr2 else
‘0’;
end
ALU;
Table 2. MUX3to1.vhd
———————————————————————————-
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.MICROPROCESSOR_LIB.ALL;
— Uncomment the following library declaration if using
— arithmetic functions with Signed or Unsigned values
–use IEEE.NUMERIC_STD.ALL;
— Uncomment the following library declaration if instantiating
— any Xilinx leaf cells in this code.
–library UNISIM;
–use UNISIM.VComponents.all;
entity mux3to1 is
    port( data_in0, data_in1,
data_in2 : in STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
        sel : in
STD_LOGIC_VECTOR(1 downto 0);
        data_out : out
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0)
    );
end mux3to1;
architecture mux3to1 of mux3to1 is
begin
    with sel select
        data_out <= data_in0
when “00”,
                    data_in1
when “01”,
                    data_in2
when others;
end mux3to1;
Table 3. Register_file.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use WORK.MICROPROCESSOR_LIB.ALL;
— Uncomment the following library declaration if using
— arithmetic functions with Signed or Unsigned values
–use IEEE.NUMERIC_STD.ALL;
— Uncomment the following library declaration if instantiating
— any Xilinx leaf cells in this code.
–library UNISIM;
–use UNISIM.VComponents.all;
entity register_file is
    Port ( reset : in STD_LOGIC;
           clk : in STD_LOGIC;
           RFin : in
STD_LOGIC_VECTOR (DATA_WIDTH – 1 downto 0);
           RFwa : in
STD_LOGIC_VECTOR (ADDR_WIDTH – 1 downto 0);
           RFwe : in STD_LOGIC;
           OPr1a : in
STD_LOGIC_VECTOR (ADDR_WIDTH – 1 downto 0);
           OPr1e : in STD_LOGIC;
           OPr2a : in
STD_LOGIC_VECTOR (ADDR_WIDTH – 1 downto 0);
           OPr2e : in STD_LOGIC;
           OPr1 : out
STD_LOGIC_VECTOR (DATA_WIDTH – 1 downto 0);
           OPr2 : out
STD_LOGIC_VECTOR (DATA_WIDTH – 1 downto 0));
end register_file;
architecture register_file of register_file is
    type DATA_ARRAY is array
(integer range<>) of STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
    signal RF : DATA_ARRAY(0 to
15) := (others => (others => ‘0’)); — Memory model
begin
    RW_Proc: process(clk, reset)
    begin
        if reset = ‘1’ then
            OPr1 <= (others
=> ‘0’);
            OPr2 <= (others
=> ‘0’);
            RF <= (others
=> (others => ‘0’));
        elsif clk’event and clk
= ‘1’ then
            if RFwe = ‘1’ then

RF(conv_integer(RFwa)) <= RFin;
            end if;
            if OPr1e = ‘1’ then
                OPr1 <=
RF(conv_integer(OPr1a));
            end if;
            if OPr2e = ‘1’ then
                OPr2 <=
RF(conv_integer(OPr2a));
            end if;
        end if;
    end process RW_Proc;
end register_file;
Table 4. Datapath.vhd
  
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.MICROPROCESSOR_LIB.ALL;
— Uncomment the following library declaration if using
— arithmetic functions with Signed or Unsigned values
–use IEEE.NUMERIC_STD.ALL;
— Uncomment the following library declaration if instantiating
— any Xilinx leaf cells in this code.
–library UNISIM;
–use UNISIM.VComponents.all;
entity datapath is
    Port(reset : in STD_LOGIC;
        clk: in STD_LOGIC;
        data_in1 : in
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
        data_in2 : in
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
        RFs : in
STD_LOGIC_VECTOR(1 downto 0);
        RFwa, OPr1a, OPr2a : in
STD_LOGIC_VECTOR(ADDR_WIDTH – 1 downto 0);
        RFwe, OPr1e, OPr2e : in STD_LOGIC;
        ALUs : in
STD_LOGIC_VECTOR(1 downto 0);
        ALUz : out STD_LOGIC;
        ALUeq : out STD_LOGIC;
        ALUgt : out STD_LOGIC;
            Addr_out : out
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
        data_out : out
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0)
        );
end datapath;
architecture datapath_arc of datapath is
    signal OPr1, OPr2 :
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
    signal RFin :
STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
    Signal data_in0 :  STD_LOGIC_VECTOR(DATA_WIDTH – 1 downto 0);
begin
    MUX_U : mux3to1
    port map(data_in0 =>
data_in0,
            data_in1 =>
data_in1,
            data_in2 =>
data_in2,
            sel => RFs,
            data_out =>
RFin);
   
    RF_U : register_file
    port map(clk => clk,
        reset => reset,
        RFin => RFin,
        RFwa => RFwa,
        RFwe => RFwe,
        OPr1a => OPr1a,
        OPr1e => OPr1e,
        OPr2a => OPr2a,
        OPr2e => OPr2e,
        OPr1 => OPr1,
        OPr2 => OPr2
        );
Addr_out <= OPr2;
Data_out <= OPR1;
    ALU_U: ALU
    port map( OPr1 => OPr1,
            OPr2 => OPr2,
            ALUs => ALUs,
            ALUr => data_in0,
            ALUz => ALUz,
            ALUeq => ALUeq,
            ALUgt => ALUgt);
end datapath_arc;

This Post Has One Comment

Trả lời