From 1649713a0ad79684da5ca2152a12c1bc47f41995 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Fri, 8 Apr 2022 13:53:09 +0200
Subject: [PATCH] Support g_round_even. Default g_round_even = true.

---
 libraries/dsp/rTwoSDF/src/vhdl/rTwoSDF.vhd    |  8 ++-
 .../dsp/rTwoSDF/src/vhdl/rTwoSDFStage.vhd     | 14 +++--
 libraries/dsp/rTwoSDF/src/vhdl/rTwoWMul.vhd   | 53 +++++++++++++++----
 libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd  |  3 +-
 4 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDF.vhd b/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDF.vhd
index 0674560603..feaaa25f8c 100644
--- a/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDF.vhd
+++ b/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDF.vhd
@@ -43,6 +43,7 @@ entity rTwoSDF is
     g_stage_dat_w : natural := 18;    -- number of bits used between the stages
     g_guard_w     : natural := 2;     -- guard bits are used to avoid overflow in single FFT stage.   
     g_nof_points  : natural := 1024;  -- N point FFT
+    g_round_even  : boolean := true;
     -- generics for rTwoSDFStage
     g_pipeline    : t_fft_pipeline := c_fft_pipeline
   );
@@ -104,6 +105,7 @@ begin
       g_stage_offset   => c_stage_offset,
       g_twiddle_offset => c_twiddle_offset,
       g_scale_enable   => sel_a_b(stage <= g_guard_w, FALSE, TRUE),  -- On average all stages have a gain factor of 2 therefore each stage needs to round 1 bit except for the last g_guard_w nof stages due to the input c_in_scale_w
+      g_round_even     => g_round_even,
       g_pipeline       => g_pipeline
     )
     port map (
@@ -157,7 +159,8 @@ begin
     g_representation      => "SIGNED",      
     g_lsb_w               => c_out_scale_w,      
     g_lsb_round           => TRUE,           
-    g_lsb_round_clip      => FALSE,      
+    g_lsb_round_clip      => FALSE,
+    g_lsb_round_even      => g_round_even,
     g_msb_clip            => FALSE,            
     g_msb_clip_symmetric  => FALSE,  
     g_pipeline_remove_lsb => 0, 
@@ -179,7 +182,8 @@ begin
     g_lsb_w               => c_out_scale_w,
     g_lsb_round           => TRUE,           
     g_lsb_round_clip      => FALSE,      
-    g_msb_clip            => FALSE,            
+    g_lsb_round_even      => g_round_even,
+    g_msb_clip            => FALSE,
     g_msb_clip_symmetric  => FALSE,  
     g_pipeline_remove_lsb => 0, 
     g_pipeline_remove_msb => 0, 
diff --git a/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDFStage.vhd b/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDFStage.vhd
index 8f40621d13..389aca4cd7 100644
--- a/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDFStage.vhd
+++ b/libraries/dsp/rTwoSDF/src/vhdl/rTwoSDFStage.vhd
@@ -31,7 +31,8 @@ entity rTwoSDFStage is
     g_stage          : natural := 8;
     g_stage_offset   : natural := 0; -- The Stage offset: 0 for normal FFT. Other than 0 in wideband FFT
     g_twiddle_offset : natural := 0; -- The twiddle offset: 0 for normal FFT. Other than 0 in wideband FFT
-    g_scale_enable   : boolean := TRUE; -- 
+    g_scale_enable   : boolean := TRUE;
+    g_round_even     : boolean := TRUE;
     g_pipeline       : t_fft_pipeline := c_fft_pipeline  -- internal pipeline settings
   );
   port (
@@ -146,8 +147,9 @@ begin
   ------------------------------------------------------------------------------
   u_TwiddleMult: entity work.rTwoWMul
   generic map (
-    g_stage => g_stage,
-    g_lat   => g_pipeline.mul_lat
+    g_stage      => g_stage,
+    g_round_even => g_round_even,
+    g_lat        => g_pipeline.mul_lat
   )
   port map (
     clk         => clk,
@@ -171,7 +173,8 @@ begin
     g_representation      => "SIGNED",      
     g_lsb_w               => c_r2_stage_bit_growth,
     g_lsb_round           => TRUE,           
-    g_lsb_round_clip      => FALSE,      
+    g_lsb_round_clip      => FALSE,
+    g_lsb_round_even      => g_round_even,
     g_msb_clip            => FALSE,            
     g_msb_clip_symmetric  => FALSE,  
     g_pipeline_remove_lsb => 0, 
@@ -193,7 +196,8 @@ begin
     g_lsb_w               => c_r2_stage_bit_growth,
     g_lsb_round           => TRUE,           
     g_lsb_round_clip      => FALSE,      
-    g_msb_clip            => FALSE,            
+    g_lsb_round_even      => g_round_even,
+    g_msb_clip            => FALSE,
     g_msb_clip_symmetric  => FALSE,  
     g_pipeline_remove_lsb => 0, 
     g_pipeline_remove_msb => 0, 
diff --git a/libraries/dsp/rTwoSDF/src/vhdl/rTwoWMul.vhd b/libraries/dsp/rTwoSDF/src/vhdl/rTwoWMul.vhd
index ead344fece..a508eda63d 100644
--- a/libraries/dsp/rTwoSDF/src/vhdl/rTwoWMul.vhd
+++ b/libraries/dsp/rTwoSDF/src/vhdl/rTwoWMul.vhd
@@ -29,6 +29,7 @@ entity rTwoWMul is
   generic (
     g_technology : NATURAL := c_tech_select_default;
     g_stage      : natural := 1;
+    g_round_even : boolean := true;
     g_lat        : natural := 3+1       -- 3 for mult, 1 for round
   );
   port (
@@ -184,17 +185,47 @@ begin
     
   
   gen_sround : if c_use_truncate=false GENERATE
-    -- Use resize_svec(s_round()) instead of truncate_and_resize_svec() to have symmetrical rounding around 0
-    -- Rounding takes logic due to adding 0.5 therefore need to use c_round_lat=1 to achieve timing
-    gen_comb : if c_round_lat=0 generate
-      ASSERT false REPORT "rTwoWMul: can probably not achieve timing for sround without pipeline" SEVERITY FAILURE;
-      round_re <= RESIZE_SVEC(s_round(product_re, c_round_w), c_out_dat_w);
-      round_im <= RESIZE_SVEC(s_round(product_im, c_round_w), c_out_dat_w);
-    end generate;
-    gen_reg : if c_round_lat=1 generate
-      round_re <= RESIZE_SVEC(s_round(product_re, c_round_w), c_out_dat_w) when rising_edge(clk);
-      round_im <= RESIZE_SVEC(s_round(product_im, c_round_w), c_out_dat_w) when rising_edge(clk);
-    end generate;
+    u_requantize_re : entity common_lib.common_requantize
+    generic map (
+      g_representation      => "SIGNED",
+      g_lsb_w               => c_round_w,
+      g_lsb_round           => TRUE,
+      g_lsb_round_clip      => FALSE,
+      g_lsb_round_even      => g_round_even,
+      g_msb_clip            => FALSE,
+      g_msb_clip_symmetric  => FALSE,
+      g_pipeline_remove_lsb => c_round_lat,
+      g_pipeline_remove_msb => 0,
+      g_in_dat_w            => c_prod_w,
+      g_out_dat_w           => c_out_dat_w
+    )
+    port map (
+      clk        => clk,
+      in_dat     => product_re,
+      out_dat    => round_re,
+      out_ovr    => open
+    );
+
+    u_requantize_im : entity common_lib.common_requantize
+    generic map (
+      g_representation      => "SIGNED",
+      g_lsb_w               => c_round_w,
+      g_lsb_round           => TRUE,
+      g_lsb_round_clip      => FALSE,
+      g_lsb_round_even      => g_round_even,
+      g_msb_clip            => FALSE,
+      g_msb_clip_symmetric  => FALSE,
+      g_pipeline_remove_lsb => c_round_lat,
+      g_pipeline_remove_msb => 0,
+      g_in_dat_w            => c_prod_w,
+      g_out_dat_w           => c_out_dat_w
+    )
+    port map (
+      clk        => clk,
+      in_dat     => product_im,
+      out_dat    => round_im,
+      out_ovr    => open
+    );
   end generate;
 
 
diff --git a/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd b/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd
index 4a008c8871..48c5eabc75 100644
--- a/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd
+++ b/libraries/dsp/rTwoSDF/tb/vhdl/tb_rTwoSDF.vhd
@@ -268,7 +268,8 @@ begin
     g_out_dat_w   => g_out_dat_w, 
     g_stage_dat_w => c_stage_dat_w,
     g_guard_w     => g_guard_w,
-    g_nof_points  => g_nof_points
+    g_nof_points  => g_nof_points,
+    g_round_even  => false   -- golden results use round half
   )
   port map(
     clk       => clk,
-- 
GitLab