|
|
|
@@ -0,0 +1,125 @@
|
|
|
|
|
-- Importiere die notwendigen Bibliotheken
|
|
|
|
|
library IEEE;
|
|
|
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
|
|
|
use IEEE.NUMERIC_STD.ALL;
|
|
|
|
|
|
|
|
|
|
-- Definiere eine ALU-Entity mit zwei Operanden, einem Opcode und einem Ergebnisausgang
|
|
|
|
|
entity SimpleALU is
|
|
|
|
|
Port (
|
|
|
|
|
clk : in STD_LOGIC; -- Takt
|
|
|
|
|
reset : in STD_LOGIC; -- Reset
|
|
|
|
|
operand_a : in STD_LOGIC_VECTOR(3 downto 0); -- Erster Operand
|
|
|
|
|
operand_b : in STD_LOGIC_VECTOR(3 downto 0); -- Zweiter Operand
|
|
|
|
|
opcode : in STD_LOGIC_VECTOR(1 downto 0); -- Opcode, der die Operation bestimmt
|
|
|
|
|
result_out : out STD_LOGIC_VECTOR(3 downto 0); -- Ergebnis der Operation
|
|
|
|
|
flag_zero_out : out STD_LOGIC; -- Flag, das anzeigt, ob das Ergebnis null ist
|
|
|
|
|
flag_or_out : out STD_LOGIC -- Flag, das anzeigt, ob eine Oder Operation bei den Operanden stattgefunden hat
|
|
|
|
|
);
|
|
|
|
|
end SimpleALU;
|
|
|
|
|
|
|
|
|
|
-- Architekturdefinition der ALU
|
|
|
|
|
architecture Behavioral of SimpleALU is
|
|
|
|
|
|
|
|
|
|
-- Legen Sie das Signal STD_LOGIC_VECTOR reg_a an, in diesem soll spaeter der Eingang operand_a gespeichert werden
|
|
|
|
|
signal reg_a : STD_LOGIC_VECTOR(3 downto 0);
|
|
|
|
|
|
|
|
|
|
-- Legen Sie das Signal STD_LOGIC_VECTOR reg_b an, in diesem soll spaeter der Eingang operand_b gespeichert werden
|
|
|
|
|
signal reg_b : STD_LOGIC_VECTOR(3 downto 0);
|
|
|
|
|
|
|
|
|
|
-- Legen Sie das Signal STD_LOGIC_VECTOR reg_opcode an, in diesem soll spaeter der Eingang opcode gespeichert werden
|
|
|
|
|
signal reg_opcode : STD_LOGIC_VECTOR(1 downto 0);
|
|
|
|
|
|
|
|
|
|
-- Legen Sie ein Signal flag_zero als STD_LOGIC an
|
|
|
|
|
signal flag_zero : STD_LOGIC;
|
|
|
|
|
|
|
|
|
|
-- Legen Sie ein Signal result als STD_LOGIC_VECTOR der Laenge 4 an
|
|
|
|
|
signal result : STD_LOGIC_VECTOR(3 downto 0);
|
|
|
|
|
|
|
|
|
|
-- Legen Sie ein Signal reg_flag_zero als STD_LOGIC
|
|
|
|
|
signal reg_flag_zero : STD_LOGIC;
|
|
|
|
|
|
|
|
|
|
-- Legen Sie ein Signal reg_result als STD_LOGIC_VECTOR der Laenge von result an
|
|
|
|
|
signal reg_result : STD_LOGIC_VECTOR(3 downto 0);
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
|
|
|
|
|
-- Prozess fuer die Eingangsregister reg_a, reg_b, reg_c
|
|
|
|
|
-- Bei einem Reset sollen die Register den Wert 0 haben
|
|
|
|
|
-- Ansonsten soll bei einer steigenden Flanke von clk der entsprechnde Eingang (entity) gespeichert werden
|
|
|
|
|
input_register : process(reset,clk)
|
|
|
|
|
begin
|
|
|
|
|
if reset = '1' then
|
|
|
|
|
reg_a <= (others => '0');
|
|
|
|
|
reg_b <= (others => '0');
|
|
|
|
|
reg_opcode <= (others => '0');
|
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
|
reg_a <= operand_a;
|
|
|
|
|
reg_b <= operand_b;
|
|
|
|
|
reg_opcode <= opcode;
|
|
|
|
|
end if;
|
|
|
|
|
end process input_register;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Prozess, der die ALU-Operationen durchfuehrt
|
|
|
|
|
alu_process: process(all)
|
|
|
|
|
begin
|
|
|
|
|
-- Anweisung fuer die Initialisierung fuer flag_zero mit dem Wert 0
|
|
|
|
|
flag_zero <= '0';
|
|
|
|
|
|
|
|
|
|
-- Entscheide basierend auf dem Opcode, welche Operation durchgefuehrt wird
|
|
|
|
|
-- Wenn reg_opcode:
|
|
|
|
|
-- 00 -> result = reg_a + reg_b
|
|
|
|
|
-- 01 -> result = reg_a - reg_b
|
|
|
|
|
-- 10 -> result = reg_a and reg_b
|
|
|
|
|
-- 11 -> result = reg_a or reg_b
|
|
|
|
|
-- Fuer diese Realisierung soll die case-Anweisung verwendet werden
|
|
|
|
|
-- Anm. Bei Berechnungen Datentypen beachten (std_logic_vector kann nicht direkt verwendet werden sondern es muss erst gecastet werden - signed verwenden)
|
|
|
|
|
case reg_opcode is
|
|
|
|
|
when "00" => -- Im Fall von "00" fuehre eine Addition durch
|
|
|
|
|
result <= std_logic_vector(signed(reg_a) + signed(reg_b));
|
|
|
|
|
when "01" => -- Im Fall von "01" fuehre eine Subtraktion durch
|
|
|
|
|
result <= std_logic_vector(signed(reg_a) - signed(reg_b));
|
|
|
|
|
when "10" => -- Im Fall von "10" fuehre eine bitweise AND-Operation durch
|
|
|
|
|
result <= reg_a and reg_b;
|
|
|
|
|
when "11" => -- Im Fall von "11" fuehre eine bitweise OR-Operation durch
|
|
|
|
|
result <= reg_a or reg_b;
|
|
|
|
|
when others => -- In allen anderen Faellen setze ein undefiniertes Verhalten
|
|
|
|
|
result <= (others => 'X');
|
|
|
|
|
end case;
|
|
|
|
|
|
|
|
|
|
-- ueberpruefe, ob das Ergebnis result null ist, und setze das flag_zero entsprechend (result = 0 dann 1 ansonsten 0)
|
|
|
|
|
-- Fuer diese Realisierung soll die if-Anweisung verwendet werden
|
|
|
|
|
if result = "0000" then
|
|
|
|
|
flag_zero <= '1';
|
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
end process alu_process;
|
|
|
|
|
|
|
|
|
|
-- Prozess fuer die Ausgangssregister reg_result, reg_flag_zero
|
|
|
|
|
-- Bei einem Reset sollen die Register den Wert 0 haben
|
|
|
|
|
-- Ansonsten soll bei einer steigenden Flanke von clk das entsprechnde Signal aus dem alu_process zugewiesen werden
|
|
|
|
|
output_register : process(reset,clk)
|
|
|
|
|
begin
|
|
|
|
|
if reset = '1' then
|
|
|
|
|
reg_result <= (others => '0');
|
|
|
|
|
reg_flag_zero <= '0';
|
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
|
reg_result <= result;
|
|
|
|
|
reg_flag_zero <= flag_zero;
|
|
|
|
|
end if;
|
|
|
|
|
end process output_register;
|
|
|
|
|
|
|
|
|
|
-- Anweisung um das Signal reg_result dem Ausgang result_out zu zuweisen
|
|
|
|
|
result_out <= reg_result;
|
|
|
|
|
|
|
|
|
|
-- Anweisung um das Signal reg_flag_zero dem Ausgang flag_zero_out zu zuweisen
|
|
|
|
|
flag_zero_out <= reg_flag_zero;
|
|
|
|
|
|
|
|
|
|
-- Bedingte Signalzuweisung fuer 'flag_or_out' außerhalb des Prozesses
|
|
|
|
|
-- Es soll anhand des Entity Eingang opcode mit einer With .. Select Anweisung der Ausgang flag_or_out gesetzt werden
|
|
|
|
|
-- opcode von or Operation dann 1 ansonsten 0
|
|
|
|
|
with opcode select
|
|
|
|
|
flag_or_out <= '1' when "11", -- Setze 'flag_or_out' auf '1', wenn 'opcode' "11" ist
|
|
|
|
|
'0' when others; -- Ansonsten 0
|
|
|
|
|
|
|
|
|
|
end Behavioral;
|