From 0fff028d26eb34ba23acfbc6b2d0c649a7cee28f Mon Sep 17 00:00:00 2001 From: kutningjo Date: Tue, 22 Oct 2024 21:22:06 +0200 Subject: [PATCH] Adds checks to tests --- .gitignore | 11 +++ U1_Datentypen/Makefile | 3 +- U1_Datentypen/test_DataTypesExample.vhd | 15 ++- U2_Entity_Component/Makefile | 1 + U2_Entity_Component/test_top_entity.vhd | 18 +++- U3_Anweisungen/Makefile | 11 +++ U3_Anweisungen/alu.vhd | 125 ++++++++++++++++++++++++ U3_Anweisungen/test_alu.vhd | 42 ++++++++ U3_Anweisungen/test_top_entity.wave | 2 + U3_Anweisungen/vsim.wave | 3 + scripts/questa-sim.mk | 2 + scripts/test_utility.vhd | 71 ++++++++++++++ 12 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 U3_Anweisungen/Makefile create mode 100644 U3_Anweisungen/alu.vhd create mode 100644 U3_Anweisungen/test_alu.vhd create mode 100644 U3_Anweisungen/test_top_entity.wave create mode 100644 U3_Anweisungen/vsim.wave create mode 100644 scripts/test_utility.vhd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a08b9c --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +U1_Datentypen/.libwork +U1_Datentypen/modelsim.ini +U1_Datentypen/transcript +U1_Datentypen/vish_stacktrace.vstf +U1_Datentypen/vsim.wlf +U1_Datentypen/work/ +U2_Entity_Component/.libwork +U2_Entity_Component/modelsim.ini +U2_Entity_Component/transcript +U2_Entity_Component/vsim.wlf +U2_Entity_Component/work/ diff --git a/U1_Datentypen/Makefile b/U1_Datentypen/Makefile index f26ae91..3cfa999 100644 --- a/U1_Datentypen/Makefile +++ b/U1_Datentypen/Makefile @@ -1,6 +1,7 @@ vhdl_srcs = DataTypesExample.vhd \ - test_DataTypesExample.vhd \ + ../scripts/test_utility.vhd \ + test_DataTypesExample.vhd \ main = test_DataTypesExample diff --git a/U1_Datentypen/test_DataTypesExample.vhd b/U1_Datentypen/test_DataTypesExample.vhd index e907489..0c9bcd2 100644 --- a/U1_Datentypen/test_DataTypesExample.vhd +++ b/U1_Datentypen/test_DataTypesExample.vhd @@ -4,8 +4,11 @@ library ieee; library std; use std.env.all; +library work; + use work.test_utility.all; + entity test_DataTypesExample is - generic( CHECK_RESULTS : boolean ); + generic( GUI_MODE : boolean; CHECK_RESULTS : boolean ); end entity test_DataTypesExample; architecture test of test_DataTypesExample is @@ -27,7 +30,15 @@ begin delay : process begin wait for 100 ns; - stop; + assert_eq( output_slv_calc, x"52" ); + assert_eq( output_slv_mask, x"5a" ); + assert_eq( output_slv_set, x"7a" ); + + if ( GUI_MODE ) then + std.env.stop; + else + std.env.finish; + end if; end process delay; end architecture test; diff --git a/U2_Entity_Component/Makefile b/U2_Entity_Component/Makefile index 1d8289a..15a24f6 100644 --- a/U2_Entity_Component/Makefile +++ b/U2_Entity_Component/Makefile @@ -1,5 +1,6 @@ vhdl_srcs = down_counter_int.vhd \ + ../scripts/test_utility.vhd \ top_entity.vhd \ test_top_entity.vhd \ diff --git a/U2_Entity_Component/test_top_entity.vhd b/U2_Entity_Component/test_top_entity.vhd index e109d7e..0adb631 100644 --- a/U2_Entity_Component/test_top_entity.vhd +++ b/U2_Entity_Component/test_top_entity.vhd @@ -4,8 +4,11 @@ library ieee; library std; use std.env.all; +library work; + use work.test_utility.all; + entity test_top_entity is - generic( CHECK_RESULTS : boolean ); + generic( GUI_MODE : boolean; CHECK_RESULTS : boolean ); end entity test_top_entity; architecture test of test_top_entity is @@ -31,12 +34,19 @@ begin p_run : process begin - wait until falling_edge( RESET ); + wait until falling_edge( RESET ); for i in 0 to 128 loop - wait until rising_edge( CLK ); + wait until rising_edge( CLK ); end loop; wait until rising_edge( CLK ); - stop; + + assert_eq( CNT, "0111000" ); + + if ( GUI_MODE ) then + std.env.stop; + else + std.env.finish; + end if; end process p_run; end architecture test; diff --git a/U3_Anweisungen/Makefile b/U3_Anweisungen/Makefile new file mode 100644 index 0000000..1d8289a --- /dev/null +++ b/U3_Anweisungen/Makefile @@ -0,0 +1,11 @@ + +vhdl_srcs = down_counter_int.vhd \ + top_entity.vhd \ + test_top_entity.vhd \ + +main = test_top_entity + +CHECK_RESULTS = true + +include ../scripts/vhdl.mk + diff --git a/U3_Anweisungen/alu.vhd b/U3_Anweisungen/alu.vhd new file mode 100644 index 0000000..be3d876 --- /dev/null +++ b/U3_Anweisungen/alu.vhd @@ -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; \ No newline at end of file diff --git a/U3_Anweisungen/test_alu.vhd b/U3_Anweisungen/test_alu.vhd new file mode 100644 index 0000000..e109d7e --- /dev/null +++ b/U3_Anweisungen/test_alu.vhd @@ -0,0 +1,42 @@ +library ieee; + use ieee.std_logic_1164.all; + +library std; + use std.env.all; + +entity test_top_entity is + generic( CHECK_RESULTS : boolean ); +end entity test_top_entity; + +architecture test of test_top_entity is + signal CLK : std_logic := '0'; + signal RESET : std_logic := '1'; + signal CNT : std_logic_vector(6 downto 0); +begin + u_top_entity : entity work.top_entity + port map ( + CLK => CLK, + RESET => RESET, + CNT => CNT + ); + + CLK <= not CLK after 10 ns; + + p_reset : process( CLK ) + begin + if falling_edge( CLK ) then + RESET <= '0'; + end if; + end process p_reset; + + p_run : process + begin + wait until falling_edge( RESET ); + for i in 0 to 128 loop + wait until rising_edge( CLK ); + end loop; + wait until rising_edge( CLK ); + stop; + end process p_run; + +end architecture test; diff --git a/U3_Anweisungen/test_top_entity.wave b/U3_Anweisungen/test_top_entity.wave new file mode 100644 index 0000000..e6e10ee --- /dev/null +++ b/U3_Anweisungen/test_top_entity.wave @@ -0,0 +1,2 @@ +$ version 1.1 +/test_DataTypesExample/u_DataTypesExample/* diff --git a/U3_Anweisungen/vsim.wave b/U3_Anweisungen/vsim.wave new file mode 100644 index 0000000..689218d --- /dev/null +++ b/U3_Anweisungen/vsim.wave @@ -0,0 +1,3 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate /test_top_entity/u_top_entity/* diff --git a/scripts/questa-sim.mk b/scripts/questa-sim.mk index d1b32d3..f6ee622 100644 --- a/scripts/questa-sim.mk +++ b/scripts/questa-sim.mk @@ -23,11 +23,13 @@ assert_level := error gui: ${verilog_objs} ${vhdl_objs} @vsim \ + -gGUI_MODE=true \ -gCHECK_RESULTS=$(CHECK_RESULTS) \ -voptargs=+acc work.${main} -do "do vsim.wave; run -all" sim: ${verilog_objs} ${vhdl_objs} @vsim \ + -gGUI_MODE=false \ -gCHECK_RESULTS=$(CHECK_RESULTS) \ -voptargs=+acc -c work.${main} -do "run -all" \ | ../scripts/highlight_test_results.sh diff --git a/scripts/test_utility.vhd b/scripts/test_utility.vhd new file mode 100644 index 0000000..cb1b586 --- /dev/null +++ b/scripts/test_utility.vhd @@ -0,0 +1,71 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + use ieee.float_pkg.all; + +library std; + use std.textio.all; + +package test_utility is + constant TEST_FAIL : string := "[ FAIL ]"; + constant TEST_OK : string := "[ OK ]" & LF; + + type real_array is array ( natural range <> ) of real; + + procedure assert_eq( a : in std_logic_vector; b : in std_logic_vector ); + + procedure assert_near( variable a : in real; + variable b : in real; + variable abs_err : in real ); + + procedure assert_element_near( variable a : in real; + variable b : in real; + variable abs_err : in real; + variable index : in integer ); + +end package test_utility; + +package body test_utility is + + procedure assert_eq( a : in std_logic_vector; b : in std_logic_vector ) is + begin + + assert( a = b ) + report TEST_FAIL & "assert_eq" & LF & + " a: " & to_string( a ) & LF & + " b: " & to_string( b ) & LF + severity error; + end procedure assert_eq; + + procedure assert_near( variable a : in real; + variable b : in real; + variable abs_err : in real ) is + variable abs_diff : real; + begin + abs_diff := abs( a - b ); + assert( abs_diff <= abs_err ) + report TEST_FAIL & "assert_near" & LF & + " a: " & to_string( a ) & LF & + " b: " & to_string( b ) & LF & + " " & to_string( abs_diff ) & " > " & to_string( abs_err ) & LF + severity error; + end procedure assert_near; + + procedure assert_element_near( variable a : in real; + variable b : in real; + variable abs_err : in real; + variable index : in integer ) is + variable abs_diff : real; + begin + abs_diff := abs( a - b ); + assert( abs_diff <= abs_err ) + report TEST_FAIL & "assert_element_near" & LF & + " element: " & integer'image( index ) & LF & + " a: " & to_string( a ) & LF & + " b: " & to_string( b ) & LF & + " " & to_string( abs_diff ) & " > " & to_string( abs_err ) & LF + severity error; + end procedure assert_element_near; + +end package body test_utility; +