From bbc8f383d90ab90800e36ade957d4d0599a3194e Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Mon, 4 Jul 2022 08:25:21 +0200
Subject: [PATCH] added restart mechanism to local oscillator to start at BSN =
 0 (or any even BSN)

---
 .../tb_disturb2_unb2b_station_fsub.vhd        | 11 +++++--
 .../node_disturb_oversampled_filterbank.vhd   | 28 ++++++++++++++--
 .../DISTURB2_2x_oversampled_filterbank.ipynb  | 33 +++++++++++--------
 3 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/applications/disturb2/designs/disturb2_unb2b_station/revisions/disturb2_unb2b_station_fsub/tb_disturb2_unb2b_station_fsub.vhd b/applications/disturb2/designs/disturb2_unb2b_station/revisions/disturb2_unb2b_station_fsub/tb_disturb2_unb2b_station_fsub.vhd
index 85784ded77..c60186ebe4 100644
--- a/applications/disturb2/designs/disturb2_unb2b_station/revisions/disturb2_unb2b_station_fsub/tb_disturb2_unb2b_station_fsub.vhd
+++ b/applications/disturb2/designs/disturb2_unb2b_station/revisions/disturb2_unb2b_station_fsub/tb_disturb2_unb2b_station_fsub.vhd
@@ -112,7 +112,7 @@ ARCHITECTURE tb OF tb_disturb2_unb2b_station_fsub IS
   CONSTANT c_hi_factor           : REAL := 1.0 + c_percentage;  -- higher boundary
 
   -- WG
-  CONSTANT c_bsn_start_wg         : NATURAL := c_init_bsn + 2;  -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
+  CONSTANT c_bsn_start_wg         : NATURAL := c_init_bsn + 3;  -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
   -- .ampl
   CONSTANT c_wg_ampl              : NATURAL := NATURAL(g_wg_ampl * REAL(c_disturb_FS_adc));  -- in number of lsb
   CONSTANT c_exp_sp_power         : REAL := REAL(c_wg_ampl**2) / 2.0;
@@ -347,10 +347,15 @@ BEGIN
     --   3 : ampl[16:0]
     v_offset := g_sp * c_mm_span_reg_diag_wg;
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+    --mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, 0, tb_clk);  -- phase offset in degrees
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, INTEGER(REAL(g_subband) * c_disturb_wg_subband_freq_unit), tb_clk);  -- freq
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_wg_ampl) * c_disturb_wg_ampl_lsb), tb_clk);  -- ampl
-
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 4, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
+    --mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 5, INTEGER((c_wg_phase + 360.0 * REAL(c_wg_latency) * 0.5 / REAL(c_disturb_N_fft)) * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 5, 0, tb_clk);  -- phase offset in degrees
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 6, INTEGER((REAL(g_subband) - 0.5) * c_disturb_wg_subband_freq_unit), tb_clk);  -- freq
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 7, INTEGER(REAL(c_wg_ampl) * c_disturb_wg_ampl_lsb), tb_clk);  -- ampl
     -- Read current BSN
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO  0), tb_clk);
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk);
diff --git a/applications/disturb2/libraries/disturb/src/vhdl/node_disturb_oversampled_filterbank.vhd b/applications/disturb2/libraries/disturb/src/vhdl/node_disturb_oversampled_filterbank.vhd
index eb11644d06..ca30271d07 100644
--- a/applications/disturb2/libraries/disturb/src/vhdl/node_disturb_oversampled_filterbank.vhd
+++ b/applications/disturb2/libraries/disturb/src/vhdl/node_disturb_oversampled_filterbank.vhd
@@ -118,6 +118,7 @@ ARCHITECTURE str OF node_disturb_oversampled_filterbank IS
   CONSTANT c_buf_file       : STRING := "data/freq_shift_half_subband_2048x16_im_re.hex";
      
   CONSTANT c_wg_ctrl : t_diag_wg := (TO_UVEC(c_diag_wg_mode_repeat, c_diag_wg_mode_w), TO_UVEC(c_buf.nof_dat, c_diag_wg_nofsamples_w), (OTHERS => '0'), (OTHERS => '0'), (OTHERS => '0'));
+  CONSTANT c_wg_phase_offset : NATURAL := 6; -- Compensate for WG start latency. In nof samples.
 
   CONSTANT c_fil_coefs_mem_addr_w : NATURAL := ceil_log2(c_disturb_N_fft * c_disturb_N_taps);
 
@@ -139,6 +140,7 @@ ARCHITECTURE str OF node_disturb_oversampled_filterbank IS
   SIGNAL wg_rddata  : STD_LOGIC_VECTOR(c_buf.dat_w -1 DOWNTO 0);
   SIGNAL wg_rdval   : STD_LOGIC;
   SIGNAL wg_address : STD_LOGIC_VECTOR(c_buf.adr_w -1 DOWNTO 0);
+  SIGNAL wg_rom_address : STD_LOGIC_VECTOR(c_buf.adr_w -1 DOWNTO 0);
   SIGNAL wg_rd      : STD_LOGIC;
   SIGNAL wg_out_dat : STD_LOGIC_VECTOR(c_buf.dat_w -1 DOWNTO 0);
 
@@ -168,6 +170,8 @@ ARCHITECTURE str OF node_disturb_oversampled_filterbank IS
   SIGNAL selector_en                        : STD_LOGIC;
   SIGNAL weighted_subbands_flag             : STD_LOGIC;
   SIGNAL dp_bsn_source_restart_pipe         : STD_LOGIC;
+  SIGNAL dp_bsn_source_restart_delayed      : STD_LOGIC;
+  SIGNAL dp_bsn_source_restart_wg           : STD_LOGIC;
   SIGNAL dp_bsn_source_restart_pipe_complex : STD_LOGIC;
 BEGIN
   ---------------------------------------------------------------
@@ -264,18 +268,36 @@ BEGIN
     rd_val    => wg_rdval,
     rd_dat    => wg_rddata
   );
+
+  -- Waveform generator as local oscillator.
+  p_lo_restart : PROCESS(dp_clk, dp_rst)
+  BEGIN
+    IF rising_edge(dp_clk) THEN
+      dp_bsn_source_restart_wg <= '0';
+      IF dp_rst = '1' THEN
+        dp_bsn_source_restart_delayed <= '0';
+      ELSIF si_sosi_arr(0).sop = '1' THEN
+        dp_bsn_source_restart_delayed <= dp_bsn_source_restart_pipe;
+        IF dp_bsn_source_restart_pipe = '1' AND si_sosi_arr(0).bsn(0) = '0' THEN -- even bsn, start now.
+          dp_bsn_source_restart_wg <= '1';
+        ELSE -- Odd bsn, start 1 block later.
+          dp_bsn_source_restart_wg <= dp_bsn_source_restart_delayed;
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
   
-  -- Waveform generator
-  u_wg : ENTITY diag_lib.diag_wg
+  u_lo_wg : ENTITY diag_lib.diag_wg
   GENERIC MAP (
     g_buf_dat_w    => c_buf.dat_w,
     g_buf_addr_w   => c_buf.adr_w,
+    g_rate_offset  => c_wg_phase_offset,
     g_calc_support => FALSE
   )
   PORT MAP (
     rst            => dp_rst,
     clk            => dp_clk,
-    restart        => dp_bsn_source_restart_pipe,
+    restart        => dp_bsn_source_restart_wg,
   
     buf_rddat      => wg_rddata,
     buf_rdval      => wg_rdval,
diff --git a/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank.ipynb b/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank.ipynb
index 0e4f68a197..d603762411 100644
--- a/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank.ipynb
+++ b/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank.ipynb
@@ -39,7 +39,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": 1,
    "id": "bc607828",
    "metadata": {},
    "outputs": [],
@@ -56,19 +56,10 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 2,
    "id": "9b0dea9f",
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "[1.        +0.j         0.99999529+0.00306796j 0.99998118+0.00613588j ...\n",
-      " 0.99995764-0.00920375j 0.99998118-0.00613588j 0.99999529-0.00306796j]\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "\n",
     "# Constants\n",
@@ -79,7 +70,7 @@
     "N_sample     = 2 * N_sub\n",
     "N_blocks     = 16 # Also number of channels per subband\n",
     "wg_sub       = 50.5\n",
-    "wg_sub_n     = 50.0\n",
+    "wg_sub_n     = 50\n",
     "wg_freq      = wg_sub * ((sample_freq/2) / N_sub)\n",
     "wg_freq_n    = wg_sub_n * ((sample_freq/2) / N_sub)\n",
     "wg_ampl      = 1.0\n",
@@ -90,6 +81,12 @@
     "nof_rep   = ceil_div(N_blocks*N_sample, N_wg_samples)\n",
     "exp_array = np.tile([np.exp(w) for w in pow_array], nof_rep) # y[n] = e^(j * 2Pi * (f/Fs) * n)\n",
     "\n",
+    "#rotate exp_array\n",
+    "#rot = N_wg_samples // 2\n",
+    "#print(exp_array)\n",
+    "#exp_array = np.array(list(exp_array[rot:]) + list(exp_array[:rot]))\n",
+    "#print(exp_array)\n",
+    "\n",
     "# At what intervals time points are sampled\n",
     "samplingInterval = 1 / sample_freq;\n",
     "\n",
@@ -164,7 +161,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 6,
    "id": "70cfb6c9",
    "metadata": {
     "scrolled": false
@@ -229,6 +226,14 @@
     "\n",
     "plt.show()"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "52b7ccb0",
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
-- 
GitLab