Adds initial version of the testbench
This commit is contained in:
parent
65d16659d0
commit
04768b5d14
12
Makefile
12
Makefile
@ -1,10 +1,14 @@
|
|||||||
|
|
||||||
vhdl_srcs = float_add.vhd \
|
vhdl_srcs = test/float_add.vhd \
|
||||||
top_entity_float_add.vhd \
|
fsm_add.vhd \
|
||||||
|
test/float.vhd \
|
||||||
test/test_utility.vhd \
|
test/test_utility.vhd \
|
||||||
test/tb_top_entity_float_add.vhd \
|
test/sine.vhd \
|
||||||
|
test/cosine.vhd \
|
||||||
|
test/sine_cosine.vhd \
|
||||||
|
test/tb_fsm_add.vhd \
|
||||||
|
|
||||||
main = tb_top_entity_float_add
|
main = tb_fsm_add
|
||||||
|
|
||||||
CHECK_RESULTS = true
|
CHECK_RESULTS = true
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
9
test/cosine.vhd
Normal file
9
test/cosine.vhd
Normal file
File diff suppressed because one or more lines are too long
144
test/float.vhd
Normal file
144
test/float.vhd
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
package float is
|
||||||
|
constant SIGN : std_logic_vector( 31 downto 31 ) := ( others => '0' );
|
||||||
|
constant EXP : std_logic_vector( 30 downto 23 ) := ( others => '0' );
|
||||||
|
constant MANTISSA : std_logic_vector( 22 downto 0 ) := ( others => '0' );
|
||||||
|
|
||||||
|
function find_leftmost( arg : unsigned; value : std_ulogic ) return integer;
|
||||||
|
|
||||||
|
function count_leading_digits( arg : unsigned; value : std_ulogic ) return integer;
|
||||||
|
|
||||||
|
function to_float( arg : std_logic_vector ) return std_logic_vector;
|
||||||
|
|
||||||
|
function to_fixed( arg : std_logic_vector ) return std_logic_vector;
|
||||||
|
|
||||||
|
end package float;
|
||||||
|
|
||||||
|
package body float is
|
||||||
|
function find_leftmost( arg : unsigned; value : std_ulogic ) return integer is
|
||||||
|
begin
|
||||||
|
for i in arg'left downto arg'right loop
|
||||||
|
if ( arg( i ) = value ) then
|
||||||
|
return i;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
end function find_leftmost;
|
||||||
|
|
||||||
|
function count_leading_digits( arg : unsigned; value : std_ulogic ) return integer is
|
||||||
|
variable left_most_value : integer range -1 to arg'high;
|
||||||
|
variable leading_values : integer range 0 to arg'high;
|
||||||
|
begin
|
||||||
|
left_most_value := find_leftmost( arg, not value );
|
||||||
|
leading_values := 0;
|
||||||
|
|
||||||
|
if ( left_most_value /= -1 ) then
|
||||||
|
leading_values := arg'high - left_most_value;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return leading_values;
|
||||||
|
end function count_leading_digits;
|
||||||
|
|
||||||
|
function to_float( arg : std_logic_vector ) return std_logic_vector is
|
||||||
|
variable y : std_logic_vector( 31 downto 0 );
|
||||||
|
variable s : std_logic;
|
||||||
|
variable e : unsigned( 7 downto 0 );
|
||||||
|
variable m : unsigned( 22 downto 0 );
|
||||||
|
variable value : unsigned( 30 downto 0 );
|
||||||
|
|
||||||
|
variable leading_sign_digits : integer range 0 to value'high;
|
||||||
|
variable reminding : integer range 0 to value'high;
|
||||||
|
begin
|
||||||
|
s := arg( 31 );
|
||||||
|
|
||||||
|
if ( s = '0' ) then
|
||||||
|
value := unsigned( arg( 30 downto 0 ) );
|
||||||
|
else
|
||||||
|
value := not unsigned( arg( 30 downto 0 ) );
|
||||||
|
value := value +1;
|
||||||
|
end if;
|
||||||
|
leading_sign_digits := count_leading_digits( value, '0' );
|
||||||
|
reminding := value'high - leading_sign_digits;
|
||||||
|
e := to_unsigned( 126 - leading_sign_digits, e'length );
|
||||||
|
|
||||||
|
if ( reminding > m'length ) then
|
||||||
|
m := value( reminding - 1 downto reminding - m'length );
|
||||||
|
elsif ( reminding > 1 ) then
|
||||||
|
m := ( others => '0' );
|
||||||
|
m( m'high downto m'high - reminding + 1 ) := value( reminding - 1 downto 0 );
|
||||||
|
else
|
||||||
|
m := ( others => '0' );
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if (arg = x"00000000") then
|
||||||
|
y := (others => '0');
|
||||||
|
else
|
||||||
|
y := s & std_logic_vector( e ) & std_logic_vector( m );
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return y;
|
||||||
|
end function to_float;
|
||||||
|
|
||||||
|
function to_fixed( arg : std_logic_vector ) return std_logic_vector is
|
||||||
|
variable y : unsigned( 31 downto 0 );
|
||||||
|
variable s : std_logic;
|
||||||
|
variable e : unsigned( 7 downto 0 );
|
||||||
|
variable m_index_max : integer range -127 to 128;
|
||||||
|
|
||||||
|
begin
|
||||||
|
s := arg( 31 );
|
||||||
|
e := unsigned(arg(30 downto 23));
|
||||||
|
m_index_max := to_integer(signed(30-(126-e)));
|
||||||
|
|
||||||
|
if (arg = x"00000000") then
|
||||||
|
y := (others => '0');
|
||||||
|
else
|
||||||
|
y := (others => '0');
|
||||||
|
case m_index_max is
|
||||||
|
when 30 => y(30 downto 7):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 29 => y(29 downto 6):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 28 => y(28 downto 5):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 27 => y(27 downto 4):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 26 => y(26 downto 3):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 25 => y(25 downto 2):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 24 => y(24 downto 1):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 23 => y(23 downto 0):= '1' & unsigned( arg(22 downto 0) );
|
||||||
|
when 22 => y(22 downto 0):= '1' & unsigned( arg(22 downto 1) );
|
||||||
|
when 21 => y(21 downto 0):= '1' & unsigned( arg(22 downto 2) );
|
||||||
|
when 20 => y(20 downto 0):= '1' & unsigned( arg(22 downto 3) );
|
||||||
|
when 19 => y(19 downto 0):= '1' & unsigned( arg(22 downto 4) );
|
||||||
|
when 18 => y(18 downto 0):= '1' & unsigned( arg(22 downto 5) );
|
||||||
|
when 17 => y(17 downto 0):= '1' & unsigned( arg(22 downto 6) );
|
||||||
|
when 16 => y(16 downto 0):= '1' & unsigned( arg(22 downto 7) );
|
||||||
|
when 15 => y(15 downto 0):= '1' & unsigned( arg(22 downto 8) );
|
||||||
|
when 14 => y(14 downto 0):= '1' & unsigned( arg(22 downto 9) );
|
||||||
|
when 13 => y(13 downto 0):= '1' & unsigned( arg(22 downto 10) );
|
||||||
|
when 12 => y(12 downto 0):= '1' & unsigned( arg(22 downto 11) );
|
||||||
|
when 11 => y(11 downto 0):= '1' & unsigned( arg(22 downto 12) );
|
||||||
|
when 10 => y(10 downto 0):= '1' & unsigned( arg(22 downto 13) );
|
||||||
|
when 9 => y(9 downto 0):= '1' & unsigned( arg(22 downto 14) );
|
||||||
|
when 8 => y(8 downto 0):= '1' & unsigned( arg(22 downto 15) );
|
||||||
|
when 7 => y(7 downto 0):= '1' & unsigned( arg(22 downto 16) );
|
||||||
|
when 6 => y(6 downto 0):= '1' & unsigned( arg(22 downto 17) );
|
||||||
|
when 5 => y(5 downto 0):= '1' & unsigned( arg(22 downto 18) );
|
||||||
|
when 4 => y(4 downto 0):= '1' & unsigned( arg(22 downto 19) );
|
||||||
|
when 3 => y(3 downto 0):= '1' & unsigned( arg(22 downto 20) );
|
||||||
|
when 2 => y(2 downto 0):= '1' & unsigned( arg(22 downto 21) );
|
||||||
|
when 1 => y(1 downto 0):= '1' & unsigned( arg(22 downto 22) );
|
||||||
|
when 0 => y(0):= '1';
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
if ( s = '1' ) then
|
||||||
|
y := not(y);
|
||||||
|
y:= y + x"00000001";
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return std_logic_vector( y );
|
||||||
|
end function to_fixed;
|
||||||
|
|
||||||
|
end package body float;
|
||||||
9
test/sine.vhd
Normal file
9
test/sine.vhd
Normal file
File diff suppressed because one or more lines are too long
9
test/sine_cosine.vhd
Normal file
9
test/sine_cosine.vhd
Normal file
File diff suppressed because one or more lines are too long
115
test/tb_fsm_add.vhd
Normal file
115
test/tb_fsm_add.vhd
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.float_pkg.all;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.test_utility.all;
|
||||||
|
use work.sine_data.all;
|
||||||
|
use work.cosine_data.all;
|
||||||
|
use work.sine_cosine_data.all;
|
||||||
|
|
||||||
|
library std;
|
||||||
|
use std.env.all;
|
||||||
|
use std.textio.all;
|
||||||
|
|
||||||
|
entity tb_fsm_add is
|
||||||
|
generic( CHECK_RESULTS : boolean; GUI_MODE : boolean := true );
|
||||||
|
end;
|
||||||
|
|
||||||
|
architecture test of tb_fsm_add is
|
||||||
|
signal clk : std_logic := '0';
|
||||||
|
signal reset : std_logic := '1';
|
||||||
|
signal run_calc : std_logic;
|
||||||
|
signal calc_cnt : std_logic_vector( 3 downto 0 );
|
||||||
|
|
||||||
|
signal signal_a_read : std_logic;
|
||||||
|
signal signal_a_readdata : std_logic_vector( 31 downto 0 );
|
||||||
|
|
||||||
|
signal signal_b_read : std_logic;
|
||||||
|
signal signal_b_readdata : std_logic_vector( 31 downto 0 );
|
||||||
|
|
||||||
|
signal signal_write : std_logic;
|
||||||
|
signal signal_writedata : std_logic_vector( 31 downto 0 );
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
u_fsm_add : entity work.fsm_add
|
||||||
|
port map (
|
||||||
|
clk => clk,
|
||||||
|
reset => reset,
|
||||||
|
run_calc => run_calc,
|
||||||
|
calc_cnt => calc_cnt,
|
||||||
|
|
||||||
|
signal_a_read => signal_a_read,
|
||||||
|
signal_a_readdata => signal_a_readdata,
|
||||||
|
|
||||||
|
signal_b_read => signal_b_read,
|
||||||
|
signal_b_readdata => signal_b_readdata,
|
||||||
|
|
||||||
|
signal_write => signal_write,
|
||||||
|
signal_writedata => signal_writedata
|
||||||
|
);
|
||||||
|
|
||||||
|
a_clk: clk <= not clk after 10 ns;
|
||||||
|
|
||||||
|
a_reset: process( clk )
|
||||||
|
begin
|
||||||
|
if falling_edge( clk ) then
|
||||||
|
reset <= '0';
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
input_data_a_simulus: process is
|
||||||
|
variable index : integer := 0;
|
||||||
|
begin
|
||||||
|
while true loop
|
||||||
|
signal_a_readdata <= to_std_logic_vector( to_float( work.sine_data.expected( index ) ) );
|
||||||
|
wait until rising_edge( signal_a_read );
|
||||||
|
if ( index < 1023 ) then
|
||||||
|
index := index + 1;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end process input_data_a_simulus;
|
||||||
|
|
||||||
|
input_data_b_simulus: process is
|
||||||
|
variable index : integer := 0;
|
||||||
|
begin
|
||||||
|
while true loop
|
||||||
|
signal_b_readdata <= to_std_logic_vector( to_float( work.cosine_data.expected( index ) ) );
|
||||||
|
wait until rising_edge( signal_b_read );
|
||||||
|
if ( index < 1023 ) then
|
||||||
|
index := index + 1;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end process input_data_b_simulus;
|
||||||
|
|
||||||
|
stimulus: process is
|
||||||
|
variable expected : real;
|
||||||
|
variable float_value : float32;
|
||||||
|
variable real_value : real;
|
||||||
|
variable abs_err : real := 0.5e-1;
|
||||||
|
begin
|
||||||
|
std.textio.write( std.textio.OUTPUT, "--------------------------------------------------------------------------------" & LF );
|
||||||
|
std.textio.write( std.textio.OUTPUT, "Starting tb_fsm_add" & LF );
|
||||||
|
wait until falling_edge( reset );
|
||||||
|
|
||||||
|
wait until falling_edge( clk );
|
||||||
|
run_calc <= '1';
|
||||||
|
wait until falling_edge( clk );
|
||||||
|
|
||||||
|
for i in 0 to 16 loop
|
||||||
|
wait until rising_edge( signal_write );
|
||||||
|
expected := work.sine_cosine_data.expected( i + 1 );
|
||||||
|
float_value := to_float( signal_writedata );
|
||||||
|
real_value := to_real( float_value );
|
||||||
|
assert_near( real_value, expected, abs_err );
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
if GUI_MODE = true then
|
||||||
|
finish;
|
||||||
|
else
|
||||||
|
stop;
|
||||||
|
end if;
|
||||||
|
end process stimulus;
|
||||||
|
|
||||||
|
end architecture test;
|
||||||
3
test/tb_fsm_add.wave
Normal file
3
test/tb_fsm_add.wave
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
$ version 1.1
|
||||||
|
/tb_fsm_add/*
|
||||||
|
/tb_fsm_add/u_fsm_add/*
|
||||||
@ -1,85 +0,0 @@
|
|||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
|
|
||||||
library std;
|
|
||||||
use std.env.all;
|
|
||||||
|
|
||||||
library work;
|
|
||||||
use work.test_utility.all;
|
|
||||||
|
|
||||||
entity tb_top_entity_float_add is
|
|
||||||
generic( CHECK_RESULTS : boolean; GUI_MODE : boolean := true );
|
|
||||||
end;
|
|
||||||
|
|
||||||
architecture test of tb_top_entity_float_add is
|
|
||||||
signal clk : std_logic := '0';
|
|
||||||
signal reset : std_logic := '1';
|
|
||||||
signal run_calc : std_logic := '0';
|
|
||||||
signal operand_a : std_logic_vector(31 downto 0) := ( others => '0' );
|
|
||||||
signal operand_b : std_logic_vector(31 downto 0) := ( others => '0' );
|
|
||||||
signal result : std_logic_vector(31 downto 0);
|
|
||||||
signal calc_complete : std_logic;
|
|
||||||
begin
|
|
||||||
|
|
||||||
u_top_entity_float_add : entity work.top_entity_float_add
|
|
||||||
port map (
|
|
||||||
clk => clk,
|
|
||||||
reset => reset,
|
|
||||||
run_calc => run_calc,
|
|
||||||
operand_a => operand_a,
|
|
||||||
operand_b => operand_b,
|
|
||||||
result => result,
|
|
||||||
calc_complete => calc_complete
|
|
||||||
);
|
|
||||||
|
|
||||||
a_clk: clk <= not clk after 10 ns;
|
|
||||||
|
|
||||||
a_reset: process( clk )
|
|
||||||
begin
|
|
||||||
if falling_edge( clk ) then
|
|
||||||
reset <= '0';
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
delay : process
|
|
||||||
variable res : std_logic_vector( 31 downto 0 );
|
|
||||||
variable expected : std_logic_vector( 31 downto 0 );
|
|
||||||
begin
|
|
||||||
|
|
||||||
wait until falling_edge( reset );
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
wait until rising_edge( clk );
|
|
||||||
run_calc <= '1';
|
|
||||||
operand_a <= x"01000000";
|
|
||||||
operand_b <= x"02000000";
|
|
||||||
wait until rising_edge( calc_complete );
|
|
||||||
run_calc <= '0';
|
|
||||||
if ( CHECK_RESULTS ) then
|
|
||||||
res := result;
|
|
||||||
expected := x"02200000";
|
|
||||||
assert_eq( res, expected );
|
|
||||||
end if;
|
|
||||||
wait until rising_edge( clk );
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
|
||||||
wait until rising_edge( clk );
|
|
||||||
run_calc <= '1';
|
|
||||||
operand_a <= x"4048f5c3"; -- 3.14
|
|
||||||
operand_b <= x"402d70a4"; -- 2.71
|
|
||||||
wait until rising_edge( calc_complete );
|
|
||||||
if ( CHECK_RESULTS ) then
|
|
||||||
res := result;
|
|
||||||
expected := x"40bb3333"; -- 5.85
|
|
||||||
assert_eq( res, expected );
|
|
||||||
end if;
|
|
||||||
wait until rising_edge( clk );
|
|
||||||
|
|
||||||
if GUI_MODE = true then
|
|
||||||
finish;
|
|
||||||
else
|
|
||||||
stop;
|
|
||||||
end if;
|
|
||||||
end process delay;
|
|
||||||
|
|
||||||
end architecture test;
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
|
|
||||||
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 top_entity_float_add is
|
|
||||||
port (
|
|
||||||
clk : in std_logic; -- Eingangssignal Systemtakt
|
|
||||||
reset : in std_logic; -- Eingangssignal Reset zum Setzen der Default Werte
|
|
||||||
run_calc: in std_logic; -- Eingangssignal wenn aktiv soll gerechnet werden
|
|
||||||
operand_a : in STD_LOGIC_VECTOR(31 downto 0); -- Erster Operand in 32-bit float
|
|
||||||
operand_b : in STD_LOGIC_VECTOR(31 downto 0); -- Zweiter Operand in 32-bit float
|
|
||||||
result : out std_logic_vector(31 downto 0); -- Endergebnis Berechnung Addition (im slv ist ein 32-bit float gespeichert)
|
|
||||||
calc_complete : out std_logic -- Flag das anzeiugt wann die Berechnung fertig ist (bei 1=high)
|
|
||||||
);
|
|
||||||
end top_entity_float_add;
|
|
||||||
|
|
||||||
architecture Behavioral of top_entity_float_add is
|
|
||||||
|
|
||||||
-- Legen Sie ein signal result_sum als std_logic_vector mit Laenge 32 Bit an
|
|
||||||
|
|
||||||
-- Legen Sie ein signal start als std_logic
|
|
||||||
|
|
||||||
-- Legen Sie ein signal done als std_logic
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
-- Instanziieren Sie direkt die float_add Komponente
|
|
||||||
-- Als Takt und Reset sollen die jeweiligen Eingaenge der top_entity_float_add uebergeben werden
|
|
||||||
-- An den anderen Ports die jeweiligen zugehoerigen Signale (welche oben angelegt worden sind)
|
|
||||||
u_float_add : entity work.float_add
|
|
||||||
port map(
|
|
||||||
-- Eingangssignal fuer den Takt
|
|
||||||
clk => ,
|
|
||||||
-- Eingangssignal zum Zuruecksetzen des Zaehlers
|
|
||||||
reset => ,
|
|
||||||
-- Eingang um die Berechnung zu starten
|
|
||||||
start => ,
|
|
||||||
-- Ausgang der anzeigt, dass die Berechnung fertig ist
|
|
||||||
done => ,
|
|
||||||
-- floating point operand a
|
|
||||||
A => ,
|
|
||||||
-- floating point operand b
|
|
||||||
B => ,
|
|
||||||
-- Ergebnis der Addition in floating point
|
|
||||||
sum =>
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Realisieren Sie einen getakteten Prozess control mit folgenden Verhalten
|
|
||||||
--
|
|
||||||
-- Initialisierung der Signale bei Reset aktiv (reset=1):
|
|
||||||
-- result soll=0 sein
|
|
||||||
-- start soll=0 sein
|
|
||||||
-- calc_complete soll=0 sein
|
|
||||||
--
|
|
||||||
-- bei steigende Flanke:
|
|
||||||
-- Nur wenn run_calc gleich 1 ist:
|
|
||||||
-- dann soll wenn done=1 und start=1 ist
|
|
||||||
-- start=0, calc_complete=1 und result_sum dem Ausgang result zugewiesen werden
|
|
||||||
-- ansonsten soll
|
|
||||||
-- start=1, calc_complete=0 sein
|
|
||||||
--
|
|
||||||
control : process(reset,clk)
|
|
||||||
begin
|
|
||||||
|
|
||||||
end process control;
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
Loading…
x
Reference in New Issue
Block a user