diff --git a/libraries/base/common/tb/vhdl/tb_round.vhd b/libraries/base/common/tb/vhdl/tb_round.vhd index 51bbcbbfeeed191825ffe4bd9d8bd470d4bef8b8..8f029daca7bbb6542de687569f50f13b730f06eb 100644 --- a/libraries/base/common/tb/vhdl/tb_round.vhd +++ b/libraries/base/common/tb/vhdl/tb_round.vhd @@ -19,8 +19,15 @@ -- ------------------------------------------------------------------------------- --- Author: E. Kooistra 2009, updated in 2021 +-- Author: E. Kooistra 2009, updated in 2021 using common_round_tb.py -- Purpose: Test bench for common_round.vhd +-- Description: +-- The signal names in this VHDL tb are the same as in the document [1] and +-- in the Python tb [2]. +-- The verification uses expected results from [2]. +-- References: +-- [1] https://support.astron.nl/confluence/display/L2M/L4+SDPFW+Decision%3A+Number+representation%2C+resizing+and+rounding +-- [2] common_round_tb.py -- Usage: -- > as 5 -- and manually set the signed data output signals to radix decimal @@ -57,75 +64,45 @@ ARCHITECTURE tb OF tb_round IS SIGNAL tb_end : STD_LOGIC := '0'; SIGNAL clk : STD_LOGIC := '1'; - SIGNAL in_val : STD_LOGIC; - SIGNAL in_dat : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); - SIGNAL reg_val : STD_LOGIC; - SIGNAL reg_dat : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); + -- Input data + SIGNAL in_val : STD_LOGIC; + SIGNAL in_dat : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); + SIGNAL reg_val : STD_LOGIC; + SIGNAL reg_dat : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); -- Signed output data -- . view as radix decimal in Wave window - SIGNAL reg_sdat : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); - SIGNAL round_sdat_rclip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL round_sdat_rclip_even : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL round_sdat_no_rclip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL round_sdat_no_rclip_even : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL trunc_sdat : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_signed_integer : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); + SIGNAL fs_signed_truncate : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_signed_round_half_away : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_signed_round_half_away_clip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_signed_round_half_even : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_signed_round_half_even_clip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- . show as real in Wave window - SIGNAL reg_sreal : REAL := 0.0; - SIGNAL round_sreal_rclip : REAL := 0.0; - SIGNAL round_sreal_rclip_even : REAL := 0.0; - SIGNAL round_sreal_no_rclip : REAL := 0.0; - SIGNAL round_sreal_no_rclip_even : REAL := 0.0; - SIGNAL trunc_sreal : REAL := 0.0; - - -- . sum values to determine bias compared to input range - SIGNAL sum_reg_sreal : REAL; - SIGNAL sum_round_sreal_rclip : REAL; - SIGNAL sum_round_sreal_rclip_even : REAL; - SIGNAL sum_round_sreal_no_rclip : REAL; - SIGNAL sum_round_sreal_no_rclip_even : REAL; - SIGNAL sum_trunc_sreal : REAL; + SIGNAL fs_sreal_fixed_point : REAL := 0.0; + SIGNAL fs_sreal_truncate : REAL := 0.0; + SIGNAL fs_sreal_round_half_away : REAL := 0.0; + SIGNAL fs_sreal_round_half_away_clip : REAL := 0.0; + SIGNAL fs_sreal_round_half_even : REAL := 0.0; + SIGNAL fs_sreal_round_half_even_clip : REAL := 0.0; -- Unsigned output data -- . view as radix unsigned in Wave window - SIGNAL reg_udat : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); - SIGNAL round_udat_rclip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL round_udat_rclip_even : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL round_udat_no_rclip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL round_udat_no_rclip_even : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - SIGNAL trunc_udat : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - - -- . show as real in Wave window - SIGNAL reg_ureal : REAL := 0.0; - SIGNAL round_ureal_rclip : REAL := 0.0; - SIGNAL round_ureal_rclip_even : REAL := 0.0; - SIGNAL round_ureal_no_rclip : REAL := 0.0; - SIGNAL round_ureal_no_rclip_even : REAL := 0.0; - SIGNAL trunc_ureal : REAL := 0.0; - - -- . sum values to determine bias compared to input range - SIGNAL sum_reg_ureal : REAL; - SIGNAL sum_round_ureal_rclip : REAL; - SIGNAL sum_round_ureal_rclip_even : REAL; - SIGNAL sum_round_ureal_no_rclip : REAL; - SIGNAL sum_round_ureal_no_rclip_even : REAL; - SIGNAL sum_trunc_ureal : REAL; + SIGNAL fs_unsigned_integer : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); + SIGNAL fs_unsigned_truncate : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_unsigned_round_half_up : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_unsigned_round_half_up_clip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_unsigned_round_half_even : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); + SIGNAL fs_unsigned_round_half_even_clip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); - -- Hold sums - SIGNAL reg_sum_reg_sreal : REAL := 0.0; - SIGNAL reg_sum_round_sreal_rclip : REAL := 0.0; - SIGNAL reg_sum_round_sreal_rclip_even : REAL := 0.0; - SIGNAL reg_sum_round_sreal_no_rclip : REAL := 0.0; - SIGNAL reg_sum_round_sreal_no_rclip_even : REAL := 0.0; - SIGNAL reg_sum_trunc_sreal : REAL := 0.0; - - SIGNAL reg_sum_reg_ureal : REAL := 0.0; - SIGNAL reg_sum_round_ureal_rclip : REAL := 0.0; - SIGNAL reg_sum_round_ureal_rclip_even : REAL := 0.0; - SIGNAL reg_sum_round_ureal_no_rclip : REAL := 0.0; - SIGNAL reg_sum_round_ureal_no_rclip_even : REAL := 0.0; - SIGNAL reg_sum_trunc_ureal : REAL := 0.0; + -- . show as real in Wave window + SIGNAL fs_ureal_fixed_point : REAL := 0.0; + SIGNAL fs_ureal_truncate : REAL := 0.0; + SIGNAL fs_ureal_round_half_away : REAL := 0.0; + SIGNAL fs_ureal_round_half_away_clip : REAL := 0.0; + SIGNAL fs_ureal_round_half_even : REAL := 0.0; + SIGNAL fs_ureal_round_half_even_clip : REAL := 0.0; BEGIN @@ -150,61 +127,21 @@ BEGIN WAIT; END PROCESS; - -- Sum fractions - -- . signed, skip c_in_smin from sum to have final input sum_reg_sreal = 0 - sum_reg_sreal <= reg_sum_reg_sreal + sel_a_b(SIGNED(reg_sdat) = c_in_smin, 0.0, reg_sreal); -- input - sum_round_sreal_no_rclip <= reg_sum_round_sreal_no_rclip + sel_a_b(SIGNED(reg_sdat) = c_in_smin, 0.0, round_sreal_no_rclip); -- outputs - sum_round_sreal_rclip <= reg_sum_round_sreal_rclip + sel_a_b(SIGNED(reg_sdat) = c_in_smin, 0.0, round_sreal_rclip); - sum_round_sreal_no_rclip_even <= reg_sum_round_sreal_no_rclip_even + sel_a_b(SIGNED(reg_sdat) = c_in_smin, 0.0, round_sreal_no_rclip_even); - sum_round_sreal_rclip_even <= reg_sum_round_sreal_rclip_even + sel_a_b(SIGNED(reg_sdat) = c_in_smin, 0.0, round_sreal_rclip_even); - sum_trunc_sreal <= reg_sum_trunc_sreal + sel_a_b(SIGNED(reg_sdat) = c_in_smin, 0.0, trunc_sreal); - - -- . unsigned, output sums get disturbed due to clip or wrap of round up overflow when UNSIGNED(reg_udat) > c_in_umax_no_clip - sum_reg_ureal <= reg_sum_reg_ureal + reg_ureal; -- input - sum_round_ureal_no_rclip <= reg_sum_round_ureal_no_rclip + round_ureal_no_rclip; -- outputs - sum_round_ureal_rclip <= reg_sum_round_ureal_rclip + round_ureal_rclip; - sum_round_ureal_no_rclip_even <= reg_sum_round_ureal_no_rclip_even + round_ureal_no_rclip_even; - sum_round_ureal_rclip_even <= reg_sum_round_ureal_rclip_even + round_ureal_rclip_even; - sum_trunc_ureal <= reg_sum_trunc_ureal + trunc_ureal; - - p_reg : PROCESS(clk) - BEGIN - IF rising_edge(clk) THEN - IF reg_val = '1' THEN - -- . signed - reg_sum_reg_sreal <= sum_reg_sreal; -- input - reg_sum_round_sreal_no_rclip <= sum_round_sreal_no_rclip; -- outputs - reg_sum_round_sreal_rclip <= sum_round_sreal_rclip; - reg_sum_round_sreal_no_rclip_even <= sum_round_sreal_no_rclip_even; - reg_sum_round_sreal_rclip_even <= sum_round_sreal_rclip_even; - reg_sum_trunc_sreal <= sum_trunc_sreal; - - -- . unsigned - reg_sum_reg_ureal <= sum_reg_ureal; -- input - reg_sum_round_ureal_no_rclip <= sum_round_ureal_no_rclip; -- outputs - reg_sum_round_ureal_rclip <= sum_round_ureal_rclip; - reg_sum_round_ureal_no_rclip_even <= sum_round_ureal_no_rclip_even; - reg_sum_round_ureal_rclip_even <= sum_round_ureal_rclip_even; - reg_sum_trunc_ureal <= sum_trunc_ureal; - END IF; - END IF; - END PROCESS; - -- Delay input as much as DUT output, assume c_pipeline = 0 reg_val <= in_val; reg_dat <= in_dat; - reg_sdat <= reg_dat; - reg_udat <= reg_dat; + fs_signed_integer <= reg_dat; + fs_unsigned_integer <= reg_dat; ----------------------------------------------------------------------------- -- SIGNED DUTs ----------------------------------------------------------------------------- - s_round_no_rclip : ENTITY work.common_round + s_truncate : ENTITY work.common_round GENERIC MAP ( g_representation => "SIGNED", - g_round => TRUE, + g_round => FALSE, g_round_clip => FALSE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, @@ -214,14 +151,14 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_sdat_no_rclip + out_dat => fs_signed_truncate ); - s_round_rclip : ENTITY work.common_round + s_round_half_away : ENTITY work.common_round GENERIC MAP ( g_representation => "SIGNED", g_round => TRUE, - g_round_clip => TRUE, + g_round_clip => FALSE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, g_in_dat_w => g_in_dat_w, @@ -230,15 +167,14 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_sdat_rclip + out_dat => fs_signed_round_half_away ); - - s_round_no_rclip_even : ENTITY work.common_round + + s_round_half_away_clip : ENTITY work.common_round GENERIC MAP ( g_representation => "SIGNED", g_round => TRUE, g_round_clip => TRUE, - g_round_even => TRUE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, g_in_dat_w => g_in_dat_w, @@ -247,10 +183,10 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_sdat_no_rclip_even + out_dat => fs_signed_round_half_away_clip ); - - s_round_rclip_even : ENTITY work.common_round + + s_round_half_even : ENTITY work.common_round GENERIC MAP ( g_representation => "SIGNED", g_round => TRUE, @@ -264,14 +200,15 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_sdat_rclip_even + out_dat => fs_signed_round_half_even ); - s_truncate : ENTITY work.common_round + s_round_half_even_clip : ENTITY work.common_round GENERIC MAP ( g_representation => "SIGNED", - g_round => FALSE, - g_round_clip => FALSE, + g_round => TRUE, + g_round_clip => TRUE, + g_round_even => TRUE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, g_in_dat_w => g_in_dat_w, @@ -280,7 +217,7 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => trunc_sdat + out_dat => fs_signed_round_half_even_clip ); @@ -288,10 +225,11 @@ BEGIN -- UNSIGNED DUTs ----------------------------------------------------------------------------- - u_round_no_rclip : ENTITY work.common_round + -- DUT for truncate + u_truncate : ENTITY work.common_round GENERIC MAP ( g_representation => "UNSIGNED", - g_round => TRUE, + g_round => FALSE, g_round_clip => FALSE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, @@ -301,14 +239,14 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_udat_no_rclip + out_dat => fs_unsigned_truncate ); - - u_round_rclip : ENTITY work.common_round + + u_round_half_up : ENTITY work.common_round GENERIC MAP ( g_representation => "UNSIGNED", g_round => TRUE, - g_round_clip => TRUE, + g_round_clip => FALSE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, g_in_dat_w => g_in_dat_w, @@ -317,15 +255,14 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_udat_rclip + out_dat => fs_unsigned_round_half_up ); - - u_round_no_rclip_even : ENTITY work.common_round + + u_round_half_up_clip : ENTITY work.common_round GENERIC MAP ( g_representation => "UNSIGNED", g_round => TRUE, - g_round_clip => FALSE, - g_round_even => TRUE, + g_round_clip => TRUE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, g_in_dat_w => g_in_dat_w, @@ -334,14 +271,14 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_udat_no_rclip_even + out_dat => fs_unsigned_round_half_up_clip ); - u_round_rclip_even : ENTITY work.common_round + u_round_half_even : ENTITY work.common_round GENERIC MAP ( g_representation => "UNSIGNED", g_round => TRUE, - g_round_clip => TRUE, + g_round_clip => FALSE, g_round_even => TRUE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, @@ -351,15 +288,15 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => round_udat_rclip_even + out_dat => fs_unsigned_round_half_even ); - -- DUT for truncate - u_truncate : ENTITY work.common_round + u_round_half_even_clip : ENTITY work.common_round GENERIC MAP ( g_representation => "UNSIGNED", - g_round => FALSE, - g_round_clip => FALSE, + g_round => TRUE, + g_round_clip => TRUE, + g_round_even => TRUE, g_pipeline_input => c_pipeline_input, g_pipeline_output => c_pipeline_output, g_in_dat_w => g_in_dat_w, @@ -368,25 +305,25 @@ BEGIN PORT MAP ( clk => clk, in_dat => in_dat, - out_dat => trunc_udat + out_dat => fs_unsigned_round_half_even_clip ); - + -- Observe fixed point SLV values as REAL -- . signed - reg_sreal <= TO_SREAL(reg_sdat, c_round_w); - round_sreal_no_rclip <= TO_SREAL(round_sdat_no_rclip, 0); - round_sreal_rclip <= TO_SREAL(round_sdat_rclip, 0); - round_sreal_no_rclip_even <= TO_SREAL(round_sdat_no_rclip_even, 0); - round_sreal_rclip_even <= TO_SREAL(round_sdat_rclip_even, 0); - trunc_sreal <= TO_SREAL(trunc_sdat, 0); + fs_sreal_fixed_point <= TO_SREAL(fs_signed_integer, c_round_w); + fs_sreal_truncate <= TO_SREAL(fs_signed_truncate, 0); + fs_sreal_round_half_away <= TO_SREAL(fs_signed_round_half_away, 0); + fs_sreal_round_half_away_clip <= TO_SREAL(fs_signed_round_half_away_clip, 0); + fs_sreal_round_half_even <= TO_SREAL(fs_signed_round_half_even, 0); + fs_sreal_round_half_even_clip <= TO_SREAL(fs_signed_round_half_even_clip, 0); -- . unsigned - reg_ureal <= TO_UREAL(reg_udat, c_round_w); - round_ureal_no_rclip <= TO_UREAL(round_udat_no_rclip, 0); - round_ureal_rclip <= TO_UREAL(round_udat_rclip, 0); - round_ureal_no_rclip_even <= TO_UREAL(round_udat_no_rclip_even, 0); - round_ureal_rclip_even <= TO_UREAL(round_udat_rclip_even, 0); - trunc_ureal <= TO_UREAL(trunc_udat, 0); + fs_ureal_fixed_point <= TO_UREAL(fs_unsigned_integer, c_round_w); + fs_ureal_truncate <= TO_UREAL(fs_unsigned_truncate, 0); + fs_ureal_round_half_away <= TO_UREAL(fs_unsigned_round_half_up, 0); + fs_ureal_round_half_away_clip <= TO_UREAL(fs_unsigned_round_half_up_clip, 0); + fs_ureal_round_half_even <= TO_UREAL(fs_unsigned_round_half_even, 0); + fs_ureal_round_half_even_clip <= TO_UREAL(fs_unsigned_round_half_even_clip, 0); -- Verification p_verify : PROCESS @@ -396,19 +333,20 @@ BEGIN IF c_round_w = 0 THEN -- Without rounding the expected value is same as input value -- . signed - ASSERT SIGNED(round_sdat_no_rclip ) = SIGNED(reg_dat) REPORT "Wrong wired round_sdat_no_rclip" SEVERITY ERROR; - ASSERT SIGNED(round_sdat_rclip ) = SIGNED(reg_dat) REPORT "Wrong wired round_sdat_rclip" SEVERITY ERROR; - ASSERT SIGNED(round_sdat_no_rclip_even ) = SIGNED(reg_dat) REPORT "Wrong wired round_sdat_no_rclip_even" SEVERITY ERROR; - ASSERT SIGNED(round_sdat_rclip_even ) = SIGNED(reg_dat) REPORT "Wrong wired round_sdat_rclip_even" SEVERITY ERROR; - ASSERT SIGNED(trunc_sdat ) = SIGNED(reg_dat) REPORT "Wrong wired trunc_sdat" SEVERITY ERROR; + ASSERT SIGNED(fs_signed_truncate ) = SIGNED(reg_dat) REPORT "Wrong wired fs_signed_truncate" SEVERITY ERROR; + ASSERT SIGNED(fs_signed_round_half_away ) = SIGNED(reg_dat) REPORT "Wrong wired fs_signed_round_half_away" SEVERITY ERROR; + ASSERT SIGNED(fs_signed_round_half_away_clip) = SIGNED(reg_dat) REPORT "Wrong wired fs_signed_round_half_away_clip" SEVERITY ERROR; + ASSERT SIGNED(fs_signed_round_half_even ) = SIGNED(reg_dat) REPORT "Wrong wired fs_signed_round_half_even" SEVERITY ERROR; + ASSERT SIGNED(fs_signed_round_half_even_clip) = SIGNED(reg_dat) REPORT "Wrong wired fs_signed_round_half_even_clip" SEVERITY ERROR; -- . unsigned - ASSERT UNSIGNED(round_udat_no_rclip ) = UNSIGNED(reg_dat) REPORT "Wrong wired round_udat_no_rclip" SEVERITY ERROR; - ASSERT UNSIGNED(round_udat_rclip ) = UNSIGNED(reg_dat) REPORT "Wrong wired round_udat_rclip" SEVERITY ERROR; - ASSERT UNSIGNED(round_udat_no_rclip_even ) = UNSIGNED(reg_dat) REPORT "Wrong wired round_udat_no_rclip_even" SEVERITY ERROR; - ASSERT UNSIGNED(round_udat_rclip_even ) = UNSIGNED(reg_dat) REPORT "Wrong wired round_udat_rclip_even" SEVERITY ERROR; - ASSERT UNSIGNED(trunc_udat ) = UNSIGNED(reg_dat) REPORT "Wrong wired trunc_udat" SEVERITY ERROR; + ASSERT UNSIGNED(fs_unsigned_truncate ) = UNSIGNED(reg_dat) REPORT "Wrong wired fs_unsigned_truncate" SEVERITY ERROR; + ASSERT UNSIGNED(fs_unsigned_round_half_up ) = UNSIGNED(reg_dat) REPORT "Wrong wired fs_unsigned_round_half_up" SEVERITY ERROR; + ASSERT UNSIGNED(fs_unsigned_round_half_up_clip ) = UNSIGNED(reg_dat) REPORT "Wrong wired fs_unsigned_round_half_up_clip" SEVERITY ERROR; + ASSERT UNSIGNED(fs_unsigned_round_half_even ) = UNSIGNED(reg_dat) REPORT "Wrong wired fs_unsigned_round_half_even" SEVERITY ERROR; + ASSERT UNSIGNED(fs_unsigned_round_half_even_clip) = UNSIGNED(reg_dat) REPORT "Wrong wired fs_unsigned_round_half_even_clip" SEVERITY ERROR; ELSE - -- For reduced width compare unsigned with lowrange + -- For reduced width compare with expected list of values from common_round_tb.py + END IF; END IF; END PROCESS;