mirror of
https://github.com/Lemonochrme/vhdl_processor.git
synced 2025-06-08 17:00:50 +02:00
274 lines
No EOL
9.8 KiB
VHDL
274 lines
No EOL
9.8 KiB
VHDL
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
|
|
|
entity cpu is
|
|
Port (
|
|
clk : in STD_LOGIC
|
|
);
|
|
end cpu;
|
|
|
|
ARCHITECTURE cpu_arch OF cpu IS
|
|
-- Code memory
|
|
COMPONENT instruction IS
|
|
PORT (
|
|
instruction : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Adresse de l'instruction
|
|
code : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); -- Code de l'instruction
|
|
clk : IN STD_LOGIC
|
|
);
|
|
END COMPONENT;
|
|
|
|
-- Data memory
|
|
COMPONENT data_memory IS
|
|
PORT (
|
|
clk : IN STD_LOGIC;
|
|
rst : IN STD_LOGIC; -- Reset actif à '1'
|
|
rw_enable : IN STD_LOGIC; -- Lecture: '1' Ecriture: '0'
|
|
addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Adresse de la zone mémoire
|
|
data_in : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data écrite à l'adresse addr
|
|
data_out : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) -- Data présente à l'adresse addr
|
|
);
|
|
END COMPONENT;
|
|
|
|
-- Register file
|
|
COMPONENT reg IS
|
|
PORT (
|
|
address_A : IN STD_LOGIC_VECTOR(3 DOWNTO 0); -- Permet de lire le registre à l'address_A sortie sur A_Data
|
|
address_B : IN STD_LOGIC_VECTOR(3 DOWNTO 0); -- Permet de lire le registre à l'address_B sortie sur B_Data
|
|
address_W : IN STD_LOGIC_VECTOR(3 DOWNTO 0); -- Permet d'écrire les données de W_Data à l'adresse address_W
|
|
W_Enable : IN STD_LOGIC; -- Si W_Enable='1' alors écriture
|
|
W_Data : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données à écrire
|
|
reset : IN STD_LOGIC; -- Reset actif à '0'
|
|
clk : IN STD_LOGIC;
|
|
A_Data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Sortie des données présentes à l'address_A
|
|
B_Data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) -- Sortie des données présentes à l'address_B
|
|
);
|
|
END COMPONENT;
|
|
|
|
-- Arithmentic Logic Unit
|
|
COMPONENT alu IS
|
|
PORT (
|
|
a : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Opérande a
|
|
b : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Opérande b
|
|
op : IN STD_LOGIC_VECTOR(2 DOWNTO 0); -- Code de l'operation
|
|
s : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Sortie de l'operation
|
|
flags : OUT STD_LOGIC_VECTOR(3 DOWNTO 0) -- Flags de l'ALU (C, N, Z, O)
|
|
);
|
|
END COMPONENT;
|
|
|
|
-- Signaux internes
|
|
signal PC : STD_LOGIC_VECTOR (7 downto 0) := "00000000"; -- Program Counter
|
|
signal IR : STD_LOGIC_VECTOR (31 downto 0); -- Instruction Register
|
|
|
|
signal OP_LI_DI : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal A_LI_DI : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal B_LI_DI : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal C_LI_DI : STD_LOGIC_VECTOR (7 downto 0);
|
|
|
|
signal OP_DI_EX : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal A_DI_EX : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal B_DI_EX : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal C_DI_EX : STD_LOGIC_VECTOR (7 downto 0);
|
|
|
|
signal OP_EX_MEM : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal A_EX_MEM : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal B_EX_MEM : STD_LOGIC_VECTOR (7 downto 0);
|
|
|
|
signal OP_MEM_RE: STD_LOGIC_VECTOR (7 downto 0);
|
|
signal A_MEM_RE : STD_LOGIC_VECTOR (7 downto 0);
|
|
signal B_MEM_RE : STD_LOGIC_VECTOR (7 downto 0);
|
|
|
|
|
|
|
|
|
|
-- Register file specific signals
|
|
signal R_ADDRESS_A_HANDLE : STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|
signal R_ADDRESS_B_HANDLE : STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|
signal W_ADDRESS_HANDLE : STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|
signal W_DATA_HANDLE : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal W_ENABLE_HANDLE : STD_LOGIC := '0';
|
|
signal A_DATA_OUT_HANDLE : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal B_DATA_OUT_HANDLE : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
|
|
-- ALU specific signals
|
|
signal ALU_A_OPERAND : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal ALU_B_OPERAND : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal ALU_OP_TYPE : STD_LOGIC_VECTOR(2 DOWNTO 0); -- Add, Soustraction, etc...
|
|
signal ALU_DATA_OUT : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal ALU_FLAGS : STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|
|
|
-- Data Memory specific signals
|
|
signal DATAMEM_RESET : STD_lOGIC := '0'; -- Reset invactif par defaut
|
|
signal DATAMEM_RW_ENABLE : STD_lOGIC := '1'; -- Lecture par defaut pour éviter les écritures non voulues
|
|
signal DATAMEM_ADDRESS : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal DATAMEM_DATA_IN : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
signal DATAMEM_DATA_OUT : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|
|
|
|
|
BEGIN
|
|
-- Instantiation des composants
|
|
RegisterFile_Instance: reg PORT MAP (
|
|
address_A => R_ADDRESS_A_HANDLE,
|
|
address_B => R_ADDRESS_B_HANDLE,
|
|
address_W => W_ADDRESS_HANDLE,
|
|
W_Enable => W_ENABLE_HANDLE,
|
|
W_Data => W_DATA_HANDLE,
|
|
reset => '1', -- Reset unactive
|
|
clk => clk,
|
|
A_Data => A_DATA_OUT_HANDLE,
|
|
B_Data => B_DATA_OUT_HANDLE
|
|
);
|
|
|
|
|
|
InstructionMemory_Instance: instruction PORT MAP (
|
|
instruction => PC,
|
|
code => IR,
|
|
clk => clk
|
|
);
|
|
|
|
ALU_Instance: alu PORT MAP (
|
|
a => ALU_A_OPERAND,
|
|
b => ALU_B_OPERAND,
|
|
op => ALU_OP_TYPE,
|
|
s => ALU_DATA_OUT,
|
|
flags => ALU_FLAGS
|
|
);
|
|
|
|
DataMemory_Instance: data_memory PORT MAP (
|
|
clk => clk,
|
|
rst => DATAMEM_RESET, -- Reset actif à '1'
|
|
rw_enable => DATAMEM_RW_ENABLE, -- Lecture: '1' Ecriture: '0'
|
|
addr => DATAMEM_ADDRESS, -- Adresse de la zone mémoire
|
|
data_in => DATAMEM_DATA_IN, -- Data écrite à l'adresse addr
|
|
data_out => DATAMEM_DATA_OUT -- Data présente à l'adresse addr
|
|
);
|
|
|
|
-- Pipeline
|
|
OP_LI_DI <= IR(31 downto 24);
|
|
A_LI_DI <= IR(23 downto 16);
|
|
B_LI_DI <= IR(15 downto 8);
|
|
C_LI_DI <= IR(7 downto 0);
|
|
LI_DI: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
-- Banc de registre
|
|
if OP_LI_DI = X"06" or OP_LI_DI = X"07" then -- AFC / LOAD
|
|
OP_DI_EX <= OP_LI_DI;
|
|
A_DI_EX <= A_LI_DI;
|
|
B_DI_EX <= B_LI_DI;
|
|
C_DI_EX <= C_LI_DI;
|
|
elsif OP_LI_DI = X"05" or OP_LI_DI = X"08" then -- COPY / STORE
|
|
OP_DI_EX <= OP_LI_DI;
|
|
A_DI_EX <= A_LI_DI;
|
|
C_DI_EX <= C_LI_DI;
|
|
R_ADDRESS_A_HANDLE <= B_LI_DI(3 downto 0);
|
|
elsif OP_LI_DI = X"01" or OP_LI_DI = X"02" or OP_LI_DI = X"03" then -- ALU
|
|
OP_DI_EX <= OP_LI_DI;
|
|
A_DI_EX <= A_LI_DI;
|
|
R_ADDRESS_B_HANDLE <= C_LI_DI(3 downto 0);
|
|
R_ADDRESS_A_HANDLE <= B_LI_DI(3 downto 0);
|
|
else
|
|
OP_DI_EX <= X"00";
|
|
A_DI_EX <= X"00";
|
|
B_DI_EX <= X"00";
|
|
C_DI_EX <= X"00";
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
DI_EX: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if OP_DI_EX = X"06" then
|
|
OP_EX_MEM <= OP_DI_EX;
|
|
A_EX_MEM <= A_DI_EX;
|
|
B_EX_MEM <= B_DI_EX;
|
|
elsif OP_DI_EX = X"05" or OP_DI_EX = X"08" then -- COPY / STORE
|
|
OP_EX_MEM <= OP_DI_EX;
|
|
A_EX_MEM <= A_DI_EX;
|
|
B_EX_MEM <= A_DATA_OUT_HANDLE; -- Pour éviter tout décallage temporel on passe directement A_DATA_OUT_HANDLE au lieu de B_DI_EX
|
|
elsif OP_DI_EX = X"01" or OP_DI_EX = X"02" or OP_DI_EX = X"03" then
|
|
-- ALU
|
|
OP_EX_MEM <= OP_DI_EX;
|
|
A_EX_MEM <= A_DI_EX;
|
|
ALU_A_OPERAND <= A_DATA_OUT_HANDLE;
|
|
ALU_B_OPERAND <= B_DATA_OUT_HANDLE;
|
|
if OP_DI_EX = X"01" then
|
|
ALU_OP_TYPE <= "000"; -- ADD
|
|
elsif OP_DI_EX = X"02" then
|
|
ALU_OP_TYPE <= "110"; -- Multiplication
|
|
elsif OP_DI_EX = X"03" then
|
|
ALU_OP_TYPE <= "001"; -- Soustraction
|
|
end if;
|
|
else
|
|
OP_EX_MEM <= X"00";
|
|
A_EX_MEM <= X"00";
|
|
B_EX_MEM <= X"00";
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
EX_MEM: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
-- Ecrire ou lire memoire des données
|
|
if OP_EX_MEM = X"06" or OP_EX_MEM = X"05" then
|
|
OP_MEM_RE <= OP_EX_MEM;
|
|
A_MEM_RE <= A_EX_MEM;
|
|
B_MEM_RE <= B_EX_MEM;
|
|
elsif OP_EX_MEM = X"01" or OP_EX_MEM = X"02" or OP_EX_MEM = X"03" then
|
|
OP_MEM_RE <= OP_EX_MEM;
|
|
A_MEM_RE <= A_EX_MEM;
|
|
B_MEM_RE <= ALU_DATA_OUT;
|
|
elsif OP_EX_MEM = X"08" then -- STORE
|
|
OP_MEM_RE <= OP_EX_MEM;
|
|
DATAMEM_RESET <= '0';
|
|
DATAMEM_RW_ENABLE <= '0'; -- Ecriture
|
|
DATAMEM_DATA_IN <= B_EX_MEM; -- On met ce qu'il y a dans B
|
|
DATAMEM_ADDRESS <= A_EX_MEM; -- A l'adresse de A
|
|
else
|
|
OP_MEM_RE <= X"00";
|
|
A_MEM_RE <= X"00";
|
|
B_MEM_RE <= X"00";
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-- Write Back (RE)
|
|
MEM_RE: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
-- Ecrire dans les registres
|
|
if OP_MEM_RE = X"06" or OP_MEM_RE = X"05" or OP_MEM_RE = X"01" or OP_MEM_RE = X"02" or OP_MEM_RE = X"03" then
|
|
W_ADDRESS_HANDLE <= A_MEM_RE(3 downto 0);
|
|
W_DATA_HANDLE <= B_MEM_RE;
|
|
elsif OP_MEM_RE = X"08" then
|
|
null;
|
|
else
|
|
null;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
-- W_ENABLE HANDLING "MUX"
|
|
process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if OP_MEM_RE = X"06" or OP_MEM_RE = X"05" or OP_MEM_RE = X"01" or OP_MEM_RE = X"02" or OP_MEM_RE = X"03" then
|
|
W_ENABLE_HANDLE <= '1';
|
|
else
|
|
W_ENABLE_HANDLE <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
PC_UPDATE: process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
PC <= PC + 1;
|
|
end if;
|
|
end process;
|
|
|
|
END cpu_arch; |