This commit is contained in:
Imbus 2023-11-08 09:35:43 +01:00
commit d8e66ba4bf
11 changed files with 523 additions and 0 deletions

54
ALU.vhdl Normal file
View file

@ -0,0 +1,54 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity ALU is
Port (
A, B : in STD_LOGIC_VECTOR(7 downto 0); -- Input operands A and B
ALUOp : in STD_LOGIC_VECTOR(2 downto 0); -- ALU operation code
ALUSrc : in STD_LOGIC; -- Select between B and an immediate value
result : out STD_LOGIC_VECTOR(7 downto 0) -- Output result
);
end ALU;
architecture Behavioral of ALU is
begin
process (A, B, ALUOp, ALUSrc)
variable temp_result : STD_LOGIC_VECTOR(7 downto 0);
begin
-- Initialize temp_result to zero
temp_result := (others => '0');
-- Perform ALU operations based on ALUOp
case ALUOp is
when "000" =>
if ALUSrc = '1' then
temp_result := A + B; -- ADD operation
else
temp_result := A + (others => '1'); -- ADD with immediate value
end if;
when "001" =>
if ALUSrc = '1' then
temp_result := A - B; -- SUB operation
else
temp_result := A - (others => '1'); -- SUB with immediate value
end if;
when "010" =>
temp_result := A AND B; -- AND operation
when "011" =>
temp_result := A OR B; -- OR operation
when "100" =>
temp_result := A XOR B; -- XOR operation
when "101" =>
-- You can add more operations here as needed
-- temp_result := ...;
when others =>
-- Handle undefined or unsupported operations
temp_result := (others => '0');
end case;
result <= temp_result; -- Output the result
end process;
end Behavioral;

30
dest.vhdl Normal file
View file

@ -0,0 +1,30 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Destination_Block is
Port (
regEna : in STD_LOGIC; -- Input register enable signal
dest : in STD_LOGIC; -- Input destination select signal (0 or 1)
ena0 : out STD_LOGIC; -- Output enable signal for register 0
ena1 : out STD_LOGIC -- Output enable signal for register 1
);
end Destination_Block;
architecture Behavioral of Destination_Block is
begin
process (regEna, dest)
begin
-- Initialize outputs to default values
ena0 <= '0';
ena1 <= '0';
-- Enable the selected destination register based on dest signal
if regEna = '1' then
if dest = '0' then
ena0 <= '1';
else
ena1 <= '1';
end if;
end if;
end process;
end Behavioral;

70
instruction_decoder.vhdl Normal file
View file

@ -0,0 +1,70 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Instruction_Decoder is
Port (
opcode : in STD_LOGIC_VECTOR(3 downto 0); -- Input opcode
z_flag : in STD_LOGIC; -- Input zero flag
IntDone : in STD_LOGIC; -- Input interrupt done signal
stackOp : out STD_LOGIC; -- Output stack operation signal
addrSrc : out STD_LOGIC_VECTOR(1 downto 0); -- Output address source select
ALUOp : out STD_LOGIC_VECTOR(2 downto 0); -- Output ALU operation select
ALUSrc : out STD_LOGIC; -- Output ALU source select
regEna : out STD_LOGIC; -- Output register enable signal
OutEna : out STD_LOGIC -- Output data output enable signal
);
end Instruction_Decoder;
architecture Behavioral of Instruction_Decoder is
begin
process (opcode, z_flag, IntDone)
begin
-- Initialize outputs to default values
stackOp <= '0';
addrSrc <= "00";
ALUOp <= "000";
ALUSrc <= '0';
regEna <= '0';
OutEna <= '0';
-- Decode instructions based on opcode [12:9]
case opcode is
when "0000" =>
stackOp <= '1'; -- Instruction 0000: Push onto stack
when "0001" =>
stackOp <= '0'; -- Instruction 0001: Pop from stack
when "0010" =>
addrSrc <= "01"; -- Instruction 0010: Load address from register
regEna <= '1';
OutEna <= '1';
when "0011" =>
ALUOp <= "001"; -- Instruction 0011: ALU operation ADD
ALUSrc <= '1';
OutEna <= '1';
when "0100" =>
ALUOp <= "010"; -- Instruction 0100: ALU operation SUB
ALUSrc <= '1';
OutEna <= '1';
when "0101" =>
ALUOp <= "011"; -- Instruction 0101: ALU operation AND
ALUSrc <= '1';
OutEna <= '1';
when "0110" =>
ALUOp <= "100"; -- Instruction 0110: ALU operation OR
ALUSrc <= '1';
OutEna <= '1';
when "0111" =>
ALUOp <= "101"; -- Instruction 0111: ALU operation XOR
ALUSrc <= '1';
OutEna <= '1';
when "1000" =>
if z_flag = '1' then
addrSrc <= "10"; -- Instruction 1000: Jump if Zero (JZ)
else
addrSrc <= "11"; -- Instruction 1000: Jump if Not Zero (JNZ)
end if;
when others =>
null; -- Other instructions not specified, outputs remain at default values
end case;
end process;
end Behavioral;

60
int_handler_v1.vhdl Normal file
View file

@ -0,0 +1,60 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Interrupt_Handler is
Port (
int0 : in STD_LOGIC; -- Input interrupt request signal
int_done : in STD_LOGIC; -- Input signal indicating interrupt processing is done
int_addr : out STD_LOGIC_VECTOR(3 downto 0); -- Output interrupt address
int_mux : out STD_LOGIC; -- Output interrupt multiplexer control signal
save_wreg : out STD_LOGIC; -- Output signal to save work register content
restore_wreg: out STD_LOGIC -- Output signal to restore work register content
);
end Interrupt_Handler;
architecture Behavioral of Interrupt_Handler is
signal pending_interrupt : STD_LOGIC := '0'; -- Internal signal to track pending interrupts
begin
-- Logic to detect an interrupt request
process (int0, int_done)
begin
if int0 = '1' and int_done = '0' then
pending_interrupt <= '1'; -- Set pending_interrupt to indicate a new interrupt request
else
pending_interrupt <= '0';
end if;
end process;
-- Interrupt address generation logic (you can modify this as needed)
-- For simplicity, this example just assigns an address based on the presence of a pending interrupt.
process (pending_interrupt)
begin
if pending_interrupt = '1' then
int_addr <= "0000"; -- Set the interrupt address
else
int_addr <= (others => '0'); -- No interrupt pending, so address is all zeros
end if;
end process;
-- Interrupt multiplexer control logic (you can modify this as needed)
-- For simplicity, this example enables the multiplexer only if there's a pending interrupt.
process (pending_interrupt)
begin
if pending_interrupt = '1' then
int_mux <= '1'; -- Enable the multiplexer
else
int_mux <= '0'; -- Disable the multiplexer
end if;
end process;
-- Save and restore work register control signals (you can modify this as needed)
-- For simplicity, this example sets save_wreg when an interrupt is pending and
-- restore_wreg when interrupt processing is done.
process (pending_interrupt, int_done)
begin
save_wreg <= pending_interrupt;
restore_wreg <= int_done;
end process;
end Behavioral;

71
int_handler_v2.vhdl Normal file
View file

@ -0,0 +1,71 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Interrupt_Handler is
Port (
clk : in STD_LOGIC; -- Clock input
rst : in STD_LOGIC; -- Reset input
int0 : in STD_LOGIC; -- Input interrupt request signal
int_done : in STD_LOGIC; -- Input signal indicating interrupt processing is done
ret_addr : in STD_LOGIC_VECTOR(3 downto 0); -- Input return address
int_addr : out STD_LOGIC_VECTOR(3 downto 0); -- Output interrupt address
int_mux : out STD_LOGIC; -- Output interrupt multiplexer control signal
save_wreg : out STD_LOGIC; -- Output signal to save work register content
restore_wreg: out STD_LOGIC -- Output signal to restore work register content
);
end Interrupt_Handler;
architecture Behavioral of Interrupt_Handler is
signal pending_interrupt : STD_LOGIC := '0'; -- Internal signal to track pending interrupts
begin
-- Reset logic
process (rst)
begin
if rst = '1' then
pending_interrupt <= '0'; -- Clear pending interrupt on reset
end if;
end process;
-- Logic to detect an interrupt request
process (int0, int_done)
begin
if int0 = '1' and int_done = '0' then
pending_interrupt <= '1'; -- Set pending_interrupt to indicate a new interrupt request
else
pending_interrupt <= '0';
end if;
end process;
-- Interrupt address generation logic (you can modify this as needed)
-- For simplicity, this example just assigns an address based on the presence of a pending interrupt.
process (pending_interrupt)
begin
if pending_interrupt = '1' then
int_addr <= "0000"; -- Set the interrupt address
else
int_addr <= (others => '0'); -- No interrupt pending, so address is all zeros
end if;
end process;
-- Interrupt multiplexer control logic (you can modify this as needed)
-- For simplicity, this example enables the multiplexer only if there's a pending interrupt.
process (pending_interrupt)
begin
if pending_interrupt = '1' then
int_mux <= '1'; -- Enable the multiplexer
else
int_mux <= '0'; -- Disable the multiplexer
end if;
end process;
-- Save and restore work register control signals (you can modify this as needed)
-- For simplicity, this example sets save_wreg when an interrupt is pending and
-- restore_wreg when interrupt processing is done.
process (pending_interrupt, int_done)
begin
save_wreg <= pending_interrupt;
restore_wreg <= int_done;
end process;
end Behavioral;

24
mplex_8to1.vhdl Normal file
View file

@ -0,0 +1,24 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Multiplexer_8to1 is
Port (
Data_0 : in STD_LOGIC_VECTOR(7 downto 0);
Data_1 : in STD_LOGIC_VECTOR(7 downto 0);
Sel : in STD_LOGIC_VECTOR(2 downto 0);
Y : out STD_LOGIC_VECTOR(7 downto 0)
);
end Multiplexer_8to1;
architecture Behavioral of Multiplexer_8to1 is
begin
process(Data_0, Data_1, Sel)
begin
case Sel is
when "000" =>
Y <= Data_0;
when others =>
Y <= Data_1;
end case;
end process;
end Behavioral;

45
multiplexer.vhdl Normal file
View file

@ -0,0 +1,45 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Multiplexer_8to1 is
Port (
Data_0 : in STD_LOGIC;
Data_1 : in STD_LOGIC;
Data_2 : in STD_LOGIC;
Data_3 : in STD_LOGIC;
Data_4 : in STD_LOGIC;
Data_5 : in STD_LOGIC;
Data_6 : in STD_LOGIC;
Data_7 : in STD_LOGIC;
Sel : in STD_LOGIC_VECTOR(2 downto 0);
Y : out STD_LOGIC
);
end Multiplexer_8to1;
architecture Behavioral of Multiplexer_8to1 is
begin
process(Sel, Data_0, Data_1, Data_2, Data_3, Data_4, Data_5, Data_6, Data_7)
begin
case Sel is
when "000" =>
Y <= Data_0;
when "001" =>
Y <= Data_1;
when "010" =>
Y <= Data_2;
when "011" =>
Y <= Data_3;
when "100" =>
Y <= Data_4;
when "101" =>
Y <= Data_5;
when "110" =>
Y <= Data_6;
when others =>
Y <= Data_7;
end case;
end process;
end Behavioral;

31
program_counter.vhdl Normal file
View file

@ -0,0 +1,31 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Program_Counter is
Port (
clk : in STD_LOGIC; -- Clock input
rst : in STD_LOGIC; -- Reset input
increment : in STD_LOGIC; -- Signal to increment the PC
addr : out STD_LOGIC_VECTOR(7 downto 0) -- Program counter output
);
end Program_Counter;
architecture Behavioral of Program_Counter is
signal pc_reg : STD_LOGIC_VECTOR(7 downto 0) := "00000000"; -- Initial value for the program counter
begin
process (clk, rst, increment)
begin
if rst = '1' then
pc_reg <= "00000000"; -- Reset the program counter to 0
elsif rising_edge(clk) then
if increment = '1' then
pc_reg <= pc_reg + 1; -- Increment the program counter
end if;
end if;
end process;
addr <= pc_reg; -- Output the program counter value
end Behavioral;

29
reg_8.vhdl Normal file
View file

@ -0,0 +1,29 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Register_8bit is
Port (
D : in STD_LOGIC_VECTOR(7 downto 0);
ena : in STD_LOGIC;
clk : in STD_LOGIC;
rst : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR(7 downto 0)
);
end Register_8bit;
architecture Behavioral of Register_8bit is
signal Q_reg : STD_LOGIC_VECTOR(7 downto 0);
begin
process (clk, rst)
begin
if rst = '1' then
Q_reg <= (others => '0');
elsif rising_edge(clk) then
if ena = '1' then
Q_reg <= D;
end if;
end if;
end process;
Q <= Q_reg;
end Behavioral;

40
stack.vhdl Normal file
View file

@ -0,0 +1,40 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Stack is
Port (
push : in STD_LOGIC; -- Signal to push data onto the stack
pop : in STD_LOGIC; -- Signal to pop data from the stack
data_in : in STD_LOGIC_VECTOR(7 downto 0); -- Input data to be pushed onto the stack
data_out: out STD_LOGIC_VECTOR(7 downto 0) -- Data popped from the stack
);
end Stack;
architecture Behavioral of Stack is
type Stack_Type is array (0 to 7) of STD_LOGIC_VECTOR(7 downto 0);
signal stack_memory : Stack_Type;
signal stack_pointer: STD_LOGIC_VECTOR(2 downto 0) := "000"; -- Initial stack pointer
begin
process (push, pop, data_in)
begin
if push = '1' then
if stack_pointer = "111" then
-- Stack is full, no more pushing allowed
report "Stack Overflow";
else
stack_memory(to_integer(unsigned(stack_pointer))) <= data_in;
stack_pointer <= stack_pointer + 1;
end if;
elsif pop = '1' then
if stack_pointer = "000" then
-- Stack is empty, no more popping allowed
report "Stack Underflow";
else
stack_pointer <= stack_pointer - 1;
end if;
end if;
end process;
data_out <= stack_memory(to_integer(unsigned(stack_pointer))); -- Output the data from the stack
end Behavioral;

69
work_reg_block.vhdl Normal file
View file

@ -0,0 +1,69 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Work_Register_Block is
Port (
save_wreg : in STD_LOGIC;
restore_wreg: in STD_LOGIC;
D : in STD_LOGIC_VECTOR(7 downto 0);
ena : in STD_LOGIC;
clk : in STD_LOGIC;
rst : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR(7 downto 0)
);
end Work_Register_Block;
architecture Behavioral of Work_Register_Block is
signal reg1_out : STD_LOGIC_VECTOR(7 downto 0);
signal reg2_out : STD_LOGIC_VECTOR(7 downto 0);
signal mux_sel : STD_LOGIC_VECTOR(2 downto 0);
component Multiplexer_8to1 is
Port (
Data_0 : in STD_LOGIC_VECTOR(7 downto 0);
Data_1 : in STD_LOGIC_VECTOR(7 downto 0);
Sel : in STD_LOGIC_VECTOR(2 downto 0);
Y : out STD_LOGIC_VECTOR(7 downto 0)
);
end component;
component Register_8bit is
Port (
D : in STD_LOGIC_VECTOR(7 downto 0);
ena : in STD_LOGIC;
clk : in STD_LOGIC;
rst : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR(7 downto 0)
);
end component;
begin
mux_sel <= "000" when save_wreg = '1' else "001";
reg1_out <= D when save_wreg = '1' else reg2_out;
Mux1: Multiplexer_8to1
port map (
Data_0 => reg2_out,
Data_1 => D,
Sel => mux_sel,
Y => reg1_out
);
Register1: Register_8bit
port map (
D => reg1_out,
ena => ena,
clk => clk,
rst => rst,
Q => reg2_out
);
Register2: Register_8bit
port map (
D => reg2_out,
ena => restore_wreg,
clk => clk,
rst => rst,
Q => Q
);
end Behavioral;