From 7b438c87d0d24d69595fdcf657117e745fc3e938 Mon Sep 17 00:00:00 2001 From: kutningjo Date: Mon, 27 Oct 2025 18:10:48 +0100 Subject: [PATCH] Add the first version of the exercise with test bench --- Add_DataTypes.vhd | 47 ++++++++++++++++++++ Makefile | 11 +++++ scripts/check_test_results.sh | 15 +++++++ scripts/execute_and_highlight.sh | 14 ++++++ scripts/ghdl.mk | 65 ++++++++++++++++++++++++++++ scripts/highlight_test_results.sh | 7 +++ scripts/questa-sim.mk | 63 +++++++++++++++++++++++++++ scripts/vhdl.mk | 23 ++++++++++ test/tb_Add_DataTypes.vhd | 71 +++++++++++++++++++++++++++++++ test/tb_Add_DataTypes.wave | 2 + test/test_utility.vhd | 71 +++++++++++++++++++++++++++++++ test/vsim.wave | 24 +++++++++++ 12 files changed, 413 insertions(+) create mode 100644 Add_DataTypes.vhd create mode 100644 Makefile create mode 100755 scripts/check_test_results.sh create mode 100755 scripts/execute_and_highlight.sh create mode 100644 scripts/ghdl.mk create mode 100755 scripts/highlight_test_results.sh create mode 100644 scripts/questa-sim.mk create mode 100644 scripts/vhdl.mk create mode 100644 test/tb_Add_DataTypes.vhd create mode 100644 test/tb_Add_DataTypes.wave create mode 100644 test/test_utility.vhd create mode 100644 test/vsim.wave diff --git a/Add_DataTypes.vhd b/Add_DataTypes.vhd new file mode 100644 index 0000000..0afde4a --- /dev/null +++ b/Add_DataTypes.vhd @@ -0,0 +1,47 @@ + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; -- Bibliothek für std_logic und std_logic_vector +use IEEE.NUMERIC_STD.ALL; -- Bibliothek für signed und unsigned Datentypen + +entity AddDataTypes is + port ( + operand_a : in std_logic_vector(7 downto 0); -- Eingang operand a (8 Bit std_logic_vector) + operand_b : in std_logic_vector(7 downto 0); -- Eingang operand b (8 Bit std_logic_vector) + result_1 : out std_logic_vector(7 downto 0); -- Ausgang Ergebnis der Operanden Addition mit signed (8 Bit std_logic_vector) + result_2 : out std_logic_vector(7 downto 0) -- Ausgang Ergebnis der Operanden Addition mit signed (8 Bit std_logic_vector) + ); +end AddDataTypes; + +architecture Behavioral of AddDataTypes is + -- constant/signal Deklarationen + + -- Legen Sie ein Konstante eight_s als signed (Länge 8) mit Wert 8 an + + -- Legen Sie ein Konstante eight_i als integer mit Wert 8 an + + -- Legen Sie ein signal internal_operand_a_s als signed mit Laenge 8 an + + -- Legen Sie ein signal internal_operand_a_int als integer mit Wertebreich -128 to 127 an + + -- Legen Sie ein signal temp_result_s als signed mit Laenge 8 an + + -- Legen Sie ein signal temp_result_int als integer mit Wertebreich -128 to 127 an + + +begin + + -- Weisen Sie dem signal internal_operand_a_s den Eingang operand_a zu (Datentypen beachten Konvertierung noetig) + + -- Weisen Sie dem signal internal_operand_a_int den Eingang operand_a zu (Datentypen beachten Konvertierung noetig) + + -- Rechnen Sie die Addition internal_operand_a_s + operand_b + eight_s und speichern es in temp_result_s (Datentypen beachten Konvertierung bei operand_b noetig) + + -- Rechnen Sie die Addition internal_operand_a_int + operand_b + eight_i und speichern es in temp_result_int (Datentypen beachten Konvertierung bei operand_b noetig) + + -- Weisen Sie dem Ausgang result_1 das signal temp_result_s zu (Datentypen beachten Konvertierung noetig) + + -- Weisen Sie dem Ausgang result_2 das signal temp_result_int zu (Datentypen beachten Konvertierung noetig) + + +end Behavioral; + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b194757 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ + +vhdl_srcs = Add_DataTypes.vhd \ + test/test_utility.vhd \ + test/tb_Add_DataTypes.vhd \ + +main = tb_Add_DataTypes + +CHECK_RESULTS = true + +include scripts/vhdl.mk + diff --git a/scripts/check_test_results.sh b/scripts/check_test_results.sh new file mode 100755 index 0000000..e77051c --- /dev/null +++ b/scripts/check_test_results.sh @@ -0,0 +1,15 @@ +#!/bin/bash +script_dir=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) + +if [ $# -ne 1 ] +then + echo Usage $0 test-output-file + exit 1 +fi + +cat $1 | sed -z -e 's/\(py_.* \[\)/ \[/g' | ${script_dir}/highlight_test_results.sh + +if grep -q FAIL $1 +then + exit 1 +fi diff --git a/scripts/execute_and_highlight.sh b/scripts/execute_and_highlight.sh new file mode 100755 index 0000000..851117c --- /dev/null +++ b/scripts/execute_and_highlight.sh @@ -0,0 +1,14 @@ +#!/bin/bash +script_path="$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )" )" + +if [ $# -lt 1 ] +then + echo " usage: execute_and_highlight command arguments" + exit 1 +fi + +cmd=$1 +shift 1 +$cmd $@ | $script_path/highlight_test_results.sh +test ${PIPESTATUS[0]} -eq 0 + diff --git a/scripts/ghdl.mk b/scripts/ghdl.mk new file mode 100644 index 0000000..6a082e4 --- /dev/null +++ b/scripts/ghdl.mk @@ -0,0 +1,65 @@ +# +# +# +# + +# Make sure that the top level is assigned to main +$(if $(main),,\ +$(error Assign top level entity name to variable "main")) + +# Make sure that at least on vhdl source is assigned +$(if $(vhdl_srcs),,\ +$(error Assign at least on vhdl source to variable "vhdl_srcs")) + +# Append prefix -d to all generics +generics = $(addprefix -g,$(generics)) + +# Add VHDL 2008 as default build standard +vhdl_flags += --std=08 +vhdl_flags += -frelaxed-rules +#vhdl_flags += --ieee-asserts=disable-at-0 + +vhdl_objs = $(vhdl_srcs:.vhd=.o) + +assert_level := error + +.PHONY: sim clean + +sim: ${main} + @scripts/execute_and_highlight.sh \ + ghdl \ + -r ${vhdl_flags} ${main} \ + --ieee-asserts=disable-at-0 \ + -gCHECK_RESULTS=${CHECK_RESULTS} \ + --read-wave-opt=test/${main}.wave \ + --assert-level=${assert_level} + +gui: test/${main}.ghw + @echo "Viewing $<" + @gtkwave $< --script=test/gtkwave.view + +test/${main}.ghw: ${main} test/${main}.wave + @ghdl -r ${vhdl_flags} ${main} \ + --read-wave-opt=test/${main}.wave \ + --wave=$@ + +${main}: $(vhdl_objs) + @echo "Elaborating ${main}" + @ghdl -e ${vhdl_flags} ${main} + +%.o: %.vhd + @echo "Analysing $<" + @ghdl -a ${vhdl_flags} $< + +clean: + @ghdl --clean + @rm -rf ${main}.ghw work-obj08.cf ${vhdl_objs} ${main} ${artifacts} + +help: + @echo Use ghdl to simulate and synthesis a vhdl design. + @echo + @echo Build configuration variables: + @echo main main entity + @echo vhdl_flags + @echo generics + diff --git a/scripts/highlight_test_results.sh b/scripts/highlight_test_results.sh new file mode 100755 index 0000000..eb1066a --- /dev/null +++ b/scripts/highlight_test_results.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +red=$(tput setaf 1) +green=$(tput setaf 2) +default=$(tput sgr0) + +sed "s/FAIL/${red}FAIL${default}/" | sed "s/OK/${green}OK${default}/" diff --git a/scripts/questa-sim.mk b/scripts/questa-sim.mk new file mode 100644 index 0000000..c48729f --- /dev/null +++ b/scripts/questa-sim.mk @@ -0,0 +1,63 @@ +# +# +# +# + +# Make sure that the top level is assigned to main +$(if $(main),,\ +$(error Assign top level entity name to variable "main")) + +# Make sure that at least on vhdl source is assigned +$(if $(vhdl_srcs),,\ +$(error Assign at least on vhdl source to variable "vhdl_srcs")) + +# Append prefix -d to all generics +generics = $(addprefix -g,$(generics)) + +# Add VHDL 2008 as default build standard +vhdl_flags += -2008 + +vhdl_objs = $(vhdl_srcs:.vhd=.vhdo) +verilog_objs = $(verilog_srcs:.v=.vo) + +assert_level := error + +.PHONY: sim clean + +sim: ${verilog_objs} ${vhdl_objs} + @vsim -voptargs=+acc -c work.${main} -g CHECK_RESULTS=true -do "run -all" \ + | scripts/highlight_test_results.sh + +gui: ${verilog_objs} ${vhdl_objs} + @vsim -voptargs=+acc work.${main} -g CHECK_RESULTS=false -do "do test/vsim.wave; run -all" + +%.vo: %.v .libwork + @echo "Analysing $<" + @vlog -work work ${verilog_flags} $< + +%.vhdo: %.vhd .libwork + @echo "Analysing $<" + @vcom -work work ${vhdl_flags} $< + + +.libwork: + @vlib work && vmap work work && touch $@ + +clean: + @rm -rf work \ + .libwork \ + transcript \ + modelsim.ini \ + vlog.opt \ + vsim.wlf \ + data.py \ + data.pyc \ + +help: + @echo Use ghdl to simulate and synthesis a vhdl design. + @echo + @echo Build configuration variables: + @echo main main entity + @echo vhdl_flags + @echo generics + diff --git a/scripts/vhdl.mk b/scripts/vhdl.mk new file mode 100644 index 0000000..c4a9bca --- /dev/null +++ b/scripts/vhdl.mk @@ -0,0 +1,23 @@ + +ghdl_version = $(shell ghdl --version 2> /dev/null) +vsim_version = $(shell vsim -version 2> /dev/null) + +# in case verilog is part of the build a verilog capable simulator is required +ifdef verilog_srcs +ifneq (${vsim_version},) +include scripts/questa-sim.mk +else +$(error No HDL simulation tool found for verilog!) +endif +else +ifneq (${vsim_version},) +include scripts/questa-sim.mk +else +ifneq (${ghdl_version},) +include scripts/ghdl.mk +else +$(error No HDL simulation tool found!) +endif +endif +endif + diff --git a/test/tb_Add_DataTypes.vhd b/test/tb_Add_DataTypes.vhd new file mode 100644 index 0000000..dfd7647 --- /dev/null +++ b/test/tb_Add_DataTypes.vhd @@ -0,0 +1,71 @@ +library ieee; + use ieee.std_logic_1164.all; + +library std; + use std.env.all; + +library work; + use work.test_utility.all; + +entity tb_Add_DataTypes is + generic( CHECK_RESULTS : boolean ); +end; + +architecture test of tb_Add_DataTypes is + signal operand_a : std_logic_vector( 7 downto 0 ); + signal operand_b : std_logic_vector( 7 downto 0 ); + signal result_1 : std_logic_vector( 7 downto 0 ); + signal result_2 : std_logic_vector( 7 downto 0 ); +begin + u_AddDataTypes : entity work.AddDataTypes + port map ( + operand_a => operand_a, + operand_b => operand_b, + result_1 => result_1, + result_2 => result_2 + ); + + delay : process + variable result : std_logic_vector( operand_a'range ); + variable expected : std_logic_vector( operand_a'range ); + begin + operand_a <= x"05"; + operand_b <= x"07"; + wait for 10 ns; + result := result_1; + expected := x"14"; + assert_eq( result, expected ); + + result := result_2; + expected := x"14"; + assert_eq( result, expected ); + + operand_a <= x"05"; + operand_b <= x"f5"; + wait for 10 ns; + result := result_1; + expected := x"02"; + assert_eq( result, expected ); + result := result_2; + expected := x"02"; + assert_eq( result, expected ); + + operand_a <= x"f5"; + operand_b <= x"f7"; + wait for 10 ns; + result := result_1; + expected := x"f4"; + assert_eq( result, expected ); + + result := result_2; + expected := x"f4"; + assert_eq( result, expected ); + + if CHECK_RESULTS = true then + finish; + else + stop; + end if; + end process delay; + +end architecture test; diff --git a/test/tb_Add_DataTypes.wave b/test/tb_Add_DataTypes.wave new file mode 100644 index 0000000..2b51fc5 --- /dev/null +++ b/test/tb_Add_DataTypes.wave @@ -0,0 +1,2 @@ +$ version 1.1 +/tb_Add_DataTypes/u_AddDataTypes/* diff --git a/test/test_utility.vhd b/test/test_utility.vhd new file mode 100644 index 0000000..6a8ead6 --- /dev/null +++ b/test/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( variable a : in std_logic_vector; variable 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( variable a : in std_logic_vector; variable 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; + diff --git a/test/vsim.wave b/test/vsim.wave new file mode 100644 index 0000000..d0c23cc --- /dev/null +++ b/test/vsim.wave @@ -0,0 +1,24 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate /tb_add_datatypes/operand_a +add wave -noupdate /tb_add_datatypes/operand_b +add wave -noupdate /tb_add_datatypes/result_1 +add wave -noupdate /tb_add_datatypes/result_2 +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {0 ns} 0} +quietly wave cursor active 1 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 0 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {0 ns} {135 ns}