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;
|
Hay quá ta!