From d8e66ba4bfaa560cefe1b4a3d74f4245edd95136 Mon Sep 17 00:00:00 2001 From: Imbus Date: Wed, 8 Nov 2023 09:35:43 +0100 Subject: [PATCH] Init --- ALU.vhdl | 54 ++++++++++++++++++++++++++++++ dest.vhdl | 30 +++++++++++++++++ instruction_decoder.vhdl | 70 +++++++++++++++++++++++++++++++++++++++ int_handler_v1.vhdl | 60 +++++++++++++++++++++++++++++++++ int_handler_v2.vhdl | 71 ++++++++++++++++++++++++++++++++++++++++ mplex_8to1.vhdl | 24 ++++++++++++++ multiplexer.vhdl | 45 +++++++++++++++++++++++++ program_counter.vhdl | 31 ++++++++++++++++++ reg_8.vhdl | 29 ++++++++++++++++ stack.vhdl | 40 ++++++++++++++++++++++ work_reg_block.vhdl | 69 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 523 insertions(+) create mode 100644 ALU.vhdl create mode 100644 dest.vhdl create mode 100644 instruction_decoder.vhdl create mode 100644 int_handler_v1.vhdl create mode 100644 int_handler_v2.vhdl create mode 100644 mplex_8to1.vhdl create mode 100644 multiplexer.vhdl create mode 100644 program_counter.vhdl create mode 100644 reg_8.vhdl create mode 100644 stack.vhdl create mode 100644 work_reg_block.vhdl diff --git a/ALU.vhdl b/ALU.vhdl new file mode 100644 index 0000000..2054dc0 --- /dev/null +++ b/ALU.vhdl @@ -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; diff --git a/dest.vhdl b/dest.vhdl new file mode 100644 index 0000000..c73ecc2 --- /dev/null +++ b/dest.vhdl @@ -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; diff --git a/instruction_decoder.vhdl b/instruction_decoder.vhdl new file mode 100644 index 0000000..c488abd --- /dev/null +++ b/instruction_decoder.vhdl @@ -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; diff --git a/int_handler_v1.vhdl b/int_handler_v1.vhdl new file mode 100644 index 0000000..1804e18 --- /dev/null +++ b/int_handler_v1.vhdl @@ -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; \ No newline at end of file diff --git a/int_handler_v2.vhdl b/int_handler_v2.vhdl new file mode 100644 index 0000000..0d7394e --- /dev/null +++ b/int_handler_v2.vhdl @@ -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; diff --git a/mplex_8to1.vhdl b/mplex_8to1.vhdl new file mode 100644 index 0000000..ca6acc1 --- /dev/null +++ b/mplex_8to1.vhdl @@ -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; diff --git a/multiplexer.vhdl b/multiplexer.vhdl new file mode 100644 index 0000000..80522cf --- /dev/null +++ b/multiplexer.vhdl @@ -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; + diff --git a/program_counter.vhdl b/program_counter.vhdl new file mode 100644 index 0000000..13b9ff9 --- /dev/null +++ b/program_counter.vhdl @@ -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; diff --git a/reg_8.vhdl b/reg_8.vhdl new file mode 100644 index 0000000..f36f201 --- /dev/null +++ b/reg_8.vhdl @@ -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; diff --git a/stack.vhdl b/stack.vhdl new file mode 100644 index 0000000..a2dbbb9 --- /dev/null +++ b/stack.vhdl @@ -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; diff --git a/work_reg_block.vhdl b/work_reg_block.vhdl new file mode 100644 index 0000000..8ef6fc7 --- /dev/null +++ b/work_reg_block.vhdl @@ -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;