From 3cf90717139d901fff1e6127ed1083170c18067e Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Sun, 17 Jan 2021 14:52:06 +0100
Subject: [PATCH] Added g_stage_dat_w to pft2 and pfb2, added g_switch_en to
 pfb2. Verified g_switch_en and g_stage_dat_w tin tb_tb_pft2.vhd (result OK).

---
 applications/lofar1/pfb2/src/vhdl/pfb2.vhd    | 76 +++++++++++--------
 applications/lofar1/pft2/src/vhdl/pft.vhd     | 14 ++--
 applications/lofar1/pft2/tb/vhdl/tb_pft2.vhd  | 12 ++-
 .../lofar1/pft2/tb/vhdl/tb_tb_pft2.vhd        | 67 +++++++++++-----
 4 files changed, 109 insertions(+), 60 deletions(-)

diff --git a/applications/lofar1/pfb2/src/vhdl/pfb2.vhd b/applications/lofar1/pfb2/src/vhdl/pfb2.vhd
index 62d2a5e3e9..db851833e0 100644
--- a/applications/lofar1/pfb2/src/vhdl/pfb2.vhd
+++ b/applications/lofar1/pfb2/src/vhdl/pfb2.vhd
@@ -27,7 +27,7 @@
 -- . Convert between LOFAR1 sync timing 1 clk before sop and streaming data path
 --   (DP) sync timing at sop.
 -- . g_switch_en = '1' decorrelates rounding crosstalk between the X and Y output
---   that can occur due to PFT_MODE_REAL2.
+--   that occurs due to shared complex FFT and seperate in PFT_MODE_REAL2.
 
 LIBRARY IEEE, common_lib, dp_lib, pfs_lib, pft2_lib;
 USE IEEE.std_logic_1164.ALL;
@@ -37,18 +37,20 @@ USE pft2_lib.pft_pkg.ALL;
 
 ENTITY pfb2 IS
   GENERIC (
-    g_nof_points     : NATURAL := 1024;
+    g_nof_points      : NATURAL := 1024;
 
     -- pfs
-    g_pfs_nof_taps   : NATURAL := 16;
-    g_pfs_in_dat_w   : NATURAL := 12;
-    g_pfs_out_dat_w  : NATURAL := 18;
-    g_pfs_coef_dat_w : NATURAL := 16;
+    g_pfs_bypass      : BOOLEAN := FALSE;
+    g_pfs_nof_taps    : NATURAL := 16;
+    g_pfs_in_dat_w    : NATURAL := 12;
+    g_pfs_out_dat_w   : NATURAL := 18;
+    g_pfs_coef_dat_w  : NATURAL := 16;
   
-  -- pft2
-    g_pft_mode       : PFT_MODE_TYPE := PFT_MODE_REAL2;
-    g_pft_switch_en  : STD_LOGIC := '1';
-    g_pft_out_dat_w  : NATURAL := 18
+    -- pft2
+    g_pft_mode        : PFT_MODE_TYPE := PFT_MODE_REAL2;
+    g_pft_switch_en   : STD_LOGIC := '1';
+    g_pft_stage_dat_w : NATURAL := c_pft_stage_dat_w;  -- c_pft_stage_dat_w = 20 in pft_pkg.vhd
+    g_pft_out_dat_w   : NATURAL := 18
   );
   PORT (
     dp_rst        : IN  STD_LOGIC;
@@ -86,38 +88,48 @@ BEGIN
   pfs_in_val   <= in_sosi.valid                         WHEN rising_edge(dp_clk);
   pfs_in_sync  <= in_sosi.sync;
   
-  pfs : ENTITY pfs_lib.pfs
-  GENERIC MAP (
-    g_nof_bands              => g_nof_points,
-    g_nof_taps               => c_nof_coeffs,
-    g_in_dat_w               => g_pfs_in_dat_w,
-    g_out_dat_w              => g_pfs_out_dat_w,
-    g_coef_dat_w             => g_pfs_coef_dat_w
-  )
-  PORT MAP (
-    in_dat_x                 => pfs_in_dat_x,
-    in_dat_y                 => pfs_in_dat_y,
-    in_val                   => pfs_in_val,
-    in_sync                  => pfs_in_sync,
-    out_dat_x                => fil_out_dat_x,
-    out_dat_y                => fil_out_dat_y,
-    out_val                  => fil_out_val,
-    out_sync                 => fil_out_sync,
-    clk                      => dp_clk,
-    rst                      => dp_rst,
-    restart                  => '0'
-  );
+  gen_pfs : IF g_pfs_bypass=FALSE GENERATE
+    u_pfs : ENTITY pfs_lib.pfs
+    GENERIC MAP (
+      g_nof_bands              => g_nof_points,
+      g_nof_taps               => c_nof_coeffs,
+      g_in_dat_w               => g_pfs_in_dat_w,
+      g_out_dat_w              => g_pfs_out_dat_w,
+      g_coef_dat_w             => g_pfs_coef_dat_w
+    )
+    PORT MAP (
+      in_dat_x                 => pfs_in_dat_x,
+      in_dat_y                 => pfs_in_dat_y,
+      in_val                   => pfs_in_val,
+      in_sync                  => pfs_in_sync,
+      out_dat_x                => fil_out_dat_x,
+      out_dat_y                => fil_out_dat_y,
+      out_val                  => fil_out_val,
+      out_sync                 => fil_out_sync,
+      clk                      => dp_clk,
+      rst                      => dp_rst,
+      restart                  => '0'
+    );
+  END GENERATE;
+  
+  no_pfs : IF g_pfs_bypass=TRUE GENERATE
+    fil_out_dat_x <= SHIFT_SVEC(pfs_in_dat_x, g_pfs_in_dat_w - g_pfs_out_dat_w);  -- < 0 is shift left, > 0 is shift right
+    fil_out_dat_y <= SHIFT_SVEC(pfs_in_dat_y, g_pfs_in_dat_w - g_pfs_out_dat_w);  -- < 0 is shift left, > 0 is shift right
+    fil_out_val   <= pfs_in_val,
+    fil_out_sync  <= pfs_in_sync,
+  END GENERATE;
   
   fil_sosi.re    <= RESIZE_DP_DSP_DATA(fil_out_dat_x);
   fil_sosi.im    <= RESIZE_DP_DSP_DATA(fil_out_dat_y);
   fil_sosi.valid <= fil_out_val;
   fil_sosi.sync  <= fil_out_sync;
   
-  pft : ENTITY pft2_lib.pft
+  u_pft : ENTITY pft2_lib.pft
   GENERIC MAP (
     g_fft_size_w             => ceil_log2(g_nof_points),
     g_in_dat_w               => g_pfs_out_dat_w,
     g_out_dat_w              => g_pft_out_dat_w,
+    g_stage_dat_w            => g_pft_stage_dat_w,
     g_mode                   => PFT_MODE_REAL2
   )
   PORT MAP (
diff --git a/applications/lofar1/pft2/src/vhdl/pft.vhd b/applications/lofar1/pft2/src/vhdl/pft.vhd
index 624d916f47..5ed7893acc 100644
--- a/applications/lofar1/pft2/src/vhdl/pft.vhd
+++ b/applications/lofar1/pft2/src/vhdl/pft.vhd
@@ -36,6 +36,7 @@ ENTITY pft IS
     g_fft_size_w   : NATURAL := 10;
     g_in_dat_w     : NATURAL := 18;
     g_out_dat_w    : NATURAL := 18;
+    g_stage_dat_w  : NATURAL := c_pft_stage_dat_w;  -- c_pft_stage_dat_w = 20 in pft_pkg.vhd
     g_mode         : PFT_MODE_TYPE  := PFT_MODE_BITREV
   );
   PORT (
@@ -68,12 +69,11 @@ ARCHITECTURE str OF pft IS
   END;
 
   CONSTANT c_nof_stages      : NATURAL := g_fft_size_w/2;
-  CONSTANT c_stage_dat_w     : NATURAL := c_pft_stage_dat_w;
   CONSTANT c_pft_dat_w       : NATURAL := pft_dat_w(g_out_dat_w, g_mode);
 
   TYPE stage_rec IS RECORD
-    re   : STD_LOGIC_VECTOR(c_stage_dat_w-1 DOWNTO 0);
-    im   : STD_LOGIC_VECTOR(c_stage_dat_w-1 DOWNTO 0);
+    re   : STD_LOGIC_VECTOR(g_stage_dat_w-1 DOWNTO 0);
+    im   : STD_LOGIC_VECTOR(g_stage_dat_w-1 DOWNTO 0);
     val  : STD_LOGIC;
     sync : STD_LOGIC;
   END RECORD;
@@ -154,7 +154,7 @@ BEGIN
       GENERIC MAP (
         g_index          => c_nof_stages-1,
         g_in_dat_w       => g_in_dat_w,
-        g_out_dat_w      => c_stage_dat_w
+        g_out_dat_w      => g_stage_dat_w
       )
       PORT MAP (
         in_re            => switch_re,
@@ -175,8 +175,8 @@ BEGIN
     middle_stage : ENTITY pft2_lib.pft_stage
       GENERIC MAP (
         g_index          => i,
-        g_in_dat_w       => c_stage_dat_w,
-        g_out_dat_w      => c_stage_dat_w
+        g_in_dat_w       => g_stage_dat_w,
+        g_out_dat_w      => g_stage_dat_w
       )
       PORT MAP (
         in_re            => stage(i).re,
@@ -196,7 +196,7 @@ BEGIN
     last_stage : ENTITY pft2_lib.pft_stage
       GENERIC MAP (
         g_index          => 0,
-        g_in_dat_w       => c_stage_dat_w,
+        g_in_dat_w       => g_stage_dat_w,
         g_out_dat_w      => c_pft_dat_w
       )
       PORT MAP (
diff --git a/applications/lofar1/pft2/tb/vhdl/tb_pft2.vhd b/applications/lofar1/pft2/tb/vhdl/tb_pft2.vhd
index 639aec0382..6d82563e30 100644
--- a/applications/lofar1/pft2/tb/vhdl/tb_pft2.vhd
+++ b/applications/lofar1/pft2/tb/vhdl/tb_pft2.vhd
@@ -28,6 +28,7 @@
 --     - PFT_MODE_BITREV, PFT_MODE_COMPLEX: out_fft_re, out_fft_im
 --     - PFT_MODE_REAL2: out_x_re, out_x_im, out_y_re, out_y_im
 --   . Copy these signals in Wave Window to view them in both literal format and analog format
+--   View diff_max_* in Wave Window, if diff_max_* < c_diff_max then tb yields OK.
 -- - The tb works OK for all three PFT modes.
 
 LIBRARY IEEE, tst_lib, common_lib;
@@ -39,6 +40,10 @@ USE common_lib.tb_common_pkg.ALL;
 
 ENTITY tb_pft2 IS
   GENERIC (
+    -- >>> PFT settings
+    g_switch_en    : STD_LOGIC := '0';
+    g_stage_dat_w  : NATURAL := c_pft_stage_dat_w;  -- c_pft_stage_dat_w = 20 in pft_pkg.vhd
+    
     -- The PFT has 3 modes:
     -- . PFT_MODE_BITREV   --> DIT output
     -- . PFT_MODE_COMPLEX  --> DIF output
@@ -50,6 +55,7 @@ ENTITY tb_pft2 IS
     -- . For PFT_MODE_REAL2 select any signal pair for X and Y input.
     -- . For PFT_MODE_BITREV and PFT_MODE_COMPLEX select zeros for Y input.
   
+    -- >>> Testbench settings
     -- Select one input signal for X (used as real input to the PFT)
     --g_name_x   : STRING  := "cosin_N2";
     --g_name_x   : STRING  := "cosin_1";
@@ -79,8 +85,9 @@ ENTITY tb_pft2 IS
     --g_name_y   : STRING  := "block_1";
     --g_name_y   : STRING  := "block_117";
     --g_name_y   : STRING  := "u_noise";
+
     g_repeat   : NATURAL := 2  -- minimal 2 due to PFT latency
-    --g_repeat   : NATURAL := 10  -- > c_nof_block_per_sync to view multiple in_sync and out_sync intervals
+    --g_repeat   : NATURAL := 10  -- > c_nof_block_per_sync to view multiple in_sync and out_sync intervals    
   );
 END tb_pft2;
 
@@ -554,6 +561,7 @@ BEGIN
     g_fft_size_w   => c_fft_size_w,
     g_in_dat_w     => c_in_dat_w,
     g_out_dat_w    => c_out_dat_w,
+    g_stage_dat_w  => g_stage_dat_w,
     g_mode         => g_pft_mode
   )
   PORT MAP (
@@ -561,7 +569,7 @@ BEGIN
     in_im          => in_dat_y,
     in_val         => in_val,
     in_sync        => in_sync,
-    switch_en      => '0',
+    switch_en      => g_switch_en,
     out_re         => out_re,
     out_im         => out_im,
     out_val        => out_val,
diff --git a/applications/lofar1/pft2/tb/vhdl/tb_tb_pft2.vhd b/applications/lofar1/pft2/tb/vhdl/tb_tb_pft2.vhd
index 398c87d757..53f218d6af 100644
--- a/applications/lofar1/pft2/tb/vhdl/tb_tb_pft2.vhd
+++ b/applications/lofar1/pft2/tb/vhdl/tb_tb_pft2.vhd
@@ -32,9 +32,16 @@ END tb_tb_pft2;
 USE work.pft_pkg.ALL;
 
 ARCHITECTURE tb OF tb_tb_pft2 IS
+  CONSTANT c_sw    : STD_LOGIC := '1';              -- default for g_switch_en
+  CONSTANT c_dat_w : NATURAL := c_pft_stage_dat_w;  -- default for g_stage_dat_w
+  
   SIGNAL tb_end : STD_LOGIC := '0';  -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
 BEGIN
 
+  -- >>> PFT settings
+  --g_switch_en    : STD_LOGIC := '0';
+  --g_stage_dat_w  : NATURAL := c_pft_stage_dat_w;  -- c_pft_stage_dat_w = 20 in pft_pkg.vhd
+  --
   -- The PFT has 3 modes:
   -- . PFT_MODE_BITREV   --> DIT output
   -- . PFT_MODE_COMPLEX  --> DIF output
@@ -46,6 +53,7 @@ BEGIN
   -- . For PFT_MODE_REAL2 select any signal pair for X and Y input.
   -- . For PFT_MODE_BITREV and PFT_MODE_COMPLEX select zeros for Y input.
   --
+  -- >>> Testbench settings
   -- Select one input signal for X (used as real input to the PFT)
   --g_name_x   : STRING  := "cosin_N2";
   --g_name_x   : STRING  := "cosin_1";
@@ -78,26 +86,47 @@ BEGIN
   --
   --g_repeat   : NATURAL := 2  -- minimal 2 due to PFT latency
   --g_repeat   : NATURAL := 10  -- > c_nof_block_per_sync to view multiple in_sync and out_sync intervals
-    
-  u_cosin_N2  : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "cosin_N2" , "zeros", 2);
-  u_cosin_1   : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "cosin_1"  , "zeros", 2);
-  u_cosin_39  : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "cosin_39" , "zeros", 2);
-  u_sinus_1   : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "sinus_1"  , "zeros", 2);
-  u_sinus_13  : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "sinus_13" , "zeros", 2);
-  u_sinus_13s : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "sinus_13s", "zeros", 2);
-  u_impulse_0 : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "impulse_0", "zeros", 2);
-  u_impulse_1 : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "impulse_1", "zeros", 2);
-  u_zeros     : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "zeros"    , "zeros", 2);
-  u_dc        : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "dc"       , "zeros", 2);
-  u_block_1   : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "block_1"  , "zeros", 2);
-  u_block_117 : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "block_117", "zeros", 2);
-  u_u_noise   : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "u_noise"  , "zeros", 2);
 
-  u_impulse_0_impulse_1 : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "impulse_0", "impulse_1", 2);
-  u_dc_cosin_N2         : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2,        "dc",  "cosin_N2", 2);
-  u_dc_sinus_13         : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2,        "dc",  "sinus_13", 2);
-  u_block_117_u_noise   : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2, "block_117",   "u_noise", 2);
-  u_u_noise_u_noise     : ENTITY work.tb_pft2 GENERIC MAP(PFT_MODE_REAL2,   "u_noise",   "u_noise", 2);
+  --                                              g_switch_en
+  --                                               .       g_stage_dat_w
+  --                                               .        .      g_pft_mode
+  --                                               .        .       .             g_name_x
+  --                                               .        .       .              .       g_name_y
+  --                                               .        .       .              .         .      g_repeat
+  --                                               .        .       .              .         .       .
+  -- One active input, other input zeros           .        .       .              .         .       .
+  u_cosin_N2  : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,  "cosin_N2", "zeros", 2);
+  u_cosin_1   : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,   "cosin_1", "zeros", 2);
+  u_cosin_39  : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,  "cosin_39", "zeros", 2);
+  u_sinus_1   : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,   "sinus_1", "zeros", 2);
+  u_sinus_13  : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,  "sinus_13", "zeros", 2);
+  u_sinus_13s : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2, "sinus_13s", "zeros", 2);
+  u_impulse_0 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2, "impulse_0", "zeros", 2);
+  u_impulse_1 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2, "impulse_1", "zeros", 2);
+  u_zeros     : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,     "zeros", "zeros", 2);
+  u_dc        : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,        "dc", "zeros", 2);
+  u_block_1   : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,   "block_1", "zeros", 2);
+  u_block_117 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2, "block_117", "zeros", 2);
+  u_u_noise   : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,   "u_noise", "zeros", 2);
+
+  -- Two active inputs
+  u_impulse_0_impulse_1 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2, "impulse_0", "impulse_1", 2);
+  u_dc_cosin_N2         : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,        "dc",  "cosin_N2", 2);
+  u_dc_sinus_13         : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,        "dc",  "sinus_13", 2);
+  u_block_117_u_noise   : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2, "block_117",   "u_noise", 2);
+  u_u_noise_u_noise     : ENTITY work.tb_pft2 GENERIC MAP(c_sw, c_dat_w, PFT_MODE_REAL2,   "u_noise",   "u_noise", 2);
+
+  -- Vary g_stage_dat_w (pft2 g_in_dat_w = g_out_dat_w = 18)
+  -- . for g_stage_dat_w = 16 tb result is still OK, but <= 15 it fails
+  u_16_cosin_39 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 16, PFT_MODE_REAL2,  "cosin_39", "zeros", 2);
+  u_17_cosin_39 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 17, PFT_MODE_REAL2,  "cosin_39", "zeros", 2);
+  u_18_cosin_39 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 18, PFT_MODE_REAL2,  "cosin_39", "zeros", 2);
+  u_19_cosin_39 : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 19, PFT_MODE_REAL2,  "cosin_39", "zeros", 2);
 
+  u_16_block_117_u_noise : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 16, PFT_MODE_REAL2, "block_117", "u_noise", 2);
+  u_17_block_117_u_noise : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 17, PFT_MODE_REAL2, "block_117", "u_noise", 2);
+  u_18_block_117_u_noise : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 18, PFT_MODE_REAL2, "block_117", "u_noise", 2);
+  u_19_block_117_u_noise : ENTITY work.tb_pft2 GENERIC MAP(c_sw, 19, PFT_MODE_REAL2, "block_117", "u_noise", 2);
+  -- . for g_stage_dat_w > 20 tb result is still OK, but diff_max_* does not reduce further
 
 END tb;
-- 
GitLab