Skip to content
Snippets Groups Projects
Commit 0349a28c authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

Merge branch 'DIST2-2' into 'master'

Resolve DIST2-2

Closes DIST2-2

See merge request desp/hdl!277
parents 6a55d0df 5533e34c
No related branches found
No related tags found
1 merge request!277Resolve DIST2-2
Pipeline #35130 passed
Showing
with 29172 additions and 30 deletions
%% Cell type:markdown id:ceaadd7c tags:
Copyright 2022
ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--------------------------------------------------------------------------------
Author: R vd Walle
Purpose: Simulate the principle of the DISTURB2 filterbank firmware
Description: Generate an input signal containing 2 sine waves with frequencies
at the center frequency of subband 50 and subband 50.5. This demonstrates how
the two FFT results from a normal FFT and the FFT of a frequency shifted (by
half a subband) input show that both are not ideal. Thereafter, the two FFT
results are combined to generate the ideal output. This is done by first
performing FFT's on each subband using 16 samples to create channels. Then
the channels are combined by using the middle 8 channels of each subband
interleaving the channels from the normal FFT and the shifted FFT.
%% Cell type:code id:bc607828 tags:
``` python
# System imports
import numpy as np
from scipy import signal
import matplotlib
import matplotlib.pyplot as plt
from tools import *
from common import *
```
%% Cell type:code id:9b0dea9f tags:
``` python
# Constants
N_sub = 512
N_wg_samples = 4 * N_sub
sample_freq = 200000000
shift_freq = 0.5 * ((sample_freq/2 ) / N_sub) # half a subband
N_sample = 2 * N_sub
N_blocks = 16 # Also number of channels per subband
wg_sub = 50.5
wg_sub_n = 50
wg_freq = wg_sub * ((sample_freq/2) / N_sub)
wg_freq_n = wg_sub_n * ((sample_freq/2) / N_sub)
wg_ampl = 1.0
# Frequency shifting signal
n_array = np.arange(0, N_wg_samples, 1)
pow_array = [complex(0,1) * 2 * np.pi * (shift_freq / sample_freq) * n for n in n_array]
nof_rep = ceil_div(N_blocks*N_sample, N_wg_samples)
exp_array = np.tile([np.exp(w) for w in pow_array], nof_rep) # y[n] = e^(j * 2Pi * (f/Fs) * n)
#rotate exp_array
#rot = N_wg_samples // 2
#print(exp_array)
#exp_array = np.array(list(exp_array[rot:]) + list(exp_array[:rot]))
#print(exp_array)
# At what intervals time points are sampled
samplingInterval = 1 / sample_freq;
# Begin time period of the signals
beginTime = 0;
# End time period of the signals
endTime = N_blocks * N_sample * samplingInterval;
# Time points
time = np.arange(beginTime, endTime, samplingInterval);
# Create input signal
amplitude = np.sin(2*np.pi*wg_freq*time) + np.sin(2*np.pi*wg_freq_n*time)
spr_blocks = [amplitude[i * N_sample : (i+1) * N_sample] for i in range(N_blocks)]
# Shifted signal
amplitude_shft = amplitude * exp_array[0:len(time)]
spc_blocks = [amplitude_shft[i * N_sample : (i+1) * N_sample] for i in range(N_blocks)]
# Bin indices for input/shifted signal
freq = np.fft.fftfreq(np.arange(N_sample).shape[-1], samplingInterval)
subbands = [f/(shift_freq*2) for f in freq]
# Channel indices.
freq_ch = np.fft.fftfreq(np.arange(N_blocks*N_sample).shape[-1], samplingInterval)
channels = [f/(shift_freq*2) for f in freq_ch]
channels = channels[0:len(channels) // 2:] # Only positive part is used.
```
%% Cell type:code id:ae0fdaf0 tags:
``` python
# FFT of every block
spr = [np.fft.fft(spr_block) for spr_block in spr_blocks]
# spr contains [blocks (N_blocks)][subbands (N_sample)]
# We only need the positive part of the FFT and we need it in order [subbands][blocks] for channels
sprT = [x[:N_sub] for x in spr] # Take positive part, like we receive from the FPGA.
sprT = np.transpose(np.array(sprT)) # transpose
# FFT of every subband, creating channels.
spr_ch = np.array([np.fft.fftshift(np.fft.fft(band)) for band in sprT])
# The same for the shifted subbands
spc = [np.fft.fft(spc_block) for spc_block in spc_blocks]
spcT = [x[:N_sub] for x in spc]
spcT = np.transpose(np.array(spcT))
spc_ch = np.array([np.fft.fftshift(np.fft.fft(band)) for band in spcT])
# Combine the channels.
combined = [0] * N_blocks * N_sub
for i in range(N_sub):
# for N_blocks = number of channels per subband = 16
#0:8 = spr_ch[0][4:12]
#8:16 = spc_ch[0][4:12]
#16:24 = spr_ch[1][4:12]
#24:32 = spc_ch[1][4:12]
# ...
n_ch = N_blocks // 2
combined[ 2 * i * n_ch : (2 * i + 1) * n_ch] = spc_ch[i][n_ch // 2 : n_ch + (n_ch // 2)]
combined[(2 * i + 1) * n_ch : (2 * i + 2) * n_ch] = spr_ch[i][n_ch // 2 : n_ch + (n_ch // 2)]
# shift 3/4 subband to 0
combined = np.array(combined)
combined = combined[(3 * N_blocks // 4):]
combined = np.append(combined, spc_ch[N_sub-1][N_blocks // 4:])
```
%% Cell type:code id:70cfb6c9 tags:
``` python
# Create subplot
figure, axis = plt.subplots(5, 1, figsize=(15,20))
plt.subplots_adjust(hspace=1)
windowRange = [48, 54]
# Time domain representation of the input signal
axis[0].set_title('ADC input signal')
axis[0].plot(time, amplitude)
axis[0].set_xlabel('Time')
axis[0].set_ylabel('Amplitude')
# Time domain representation of the frequency shifted signal
axis[1].set_title('Shifted input')
axis[1].plot(time, amplitude_shft.real, time, amplitude_shft.imag)
axis[1].set_xlabel('Time')
axis[1].set_ylabel('Amplitude')
# Frequency domain representation of input signal
x = subbands[windowRange[0]:windowRange[1]]
y = spr[0][windowRange[0]:windowRange[1]]
axis[2].set_title('Fourier transform of ADC input')
axis[2].plot(x, y.real, x, y.imag)
axis[2].set_xlabel('Subband')
axis[2].set_ylabel('Amplitude')
# Frequency domain representation of frequency shifted signal
x = subbands[windowRange[0]:windowRange[1]]
y = spc[0][windowRange[0]:windowRange[1]]
axis[3].set_title('Fourier transform of shifted input')
axis[3].plot(x, y.real, x, y.imag)
axis[3].set_xlabel('Subband')
axis[3].set_ylabel('Amplitude')
x = channels[N_blocks * windowRange[0]:N_blocks * windowRange[1]]
y = combined[N_blocks * windowRange[0]:N_blocks * windowRange[1]]
# Frequency domain representation of combined channels
axis[4].set_title('Fourier transform of combined')
axis[4].plot(x, y.real, x, y.imag)
axis[4].set_xlabel('Subband')
axis[4].set_ylabel('Amplitude')
plt.show()
```
%% Output
%% Cell type:code id:52b7ccb0 tags:
``` python
```
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -21,6 +21,7 @@ parameters:
- { name: c_N_taps, value: 16 }
- { name: c_W_adc_jesd, value: 16 }
- { name: c_W_adc, value: 14 }
- { name: c_R_os, value: 2 }
- { name: c_V_sample_delay, value: 4096 }
- { name: c_V_si_db_large, value: 131072 }
- { name: c_V_si_db, value: 1024 }
......@@ -202,6 +203,8 @@ peripherals:
- REG_SI
- peripheral_name: filter/fil_ppf_w
number_of_peripherals: c_R_os # Disturb uses 2x oversample
peripheral_span: ceil_pow2(c_N_taps) * ceil_pow2(c_N_fft) * MM_BUS_SIZE # number_of_ports = ceil_pow2(c_N_taps), mm_port_span = ceil_pow2(c_N_fft) words
parameter_overrides:
- { name: g_fil_ppf.wb_factor, value: 1 } # process at sample rate (so no parallel wideband factor)
- { name: g_fil_ppf.nof_chan, value: 0 } # process at sample rate (so no serial time multiplexing)
......@@ -213,6 +216,8 @@ peripherals:
- RAM_FIL_COEFS
- peripheral_name: sdp/sdp_subband_equalizer
parameter_overrides:
- { name: P_pfb, value: c_R_os * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
mm_port_names:
- RAM_EQUALIZER_GAINS
......@@ -221,6 +226,8 @@ peripherals:
- REG_DP_SELECTOR # input_select = 0 for weighted subbands, input_select = 1 for raw subbands
- peripheral_name: st/st_sst_for_sdp
parameter_overrides:
- { name: g_nof_instances, value: c_R_os * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
mm_port_names:
- RAM_ST_SST
......@@ -402,7 +409,6 @@ peripherals:
peripheral_group: ring_rx_bf
number_of_peripherals: c_N_beamsets
peripheral_span: 8 * MM_BUS_SIZE # number_of_ports = 1, mm_port_span = 8 words
parameter_overrides:
- { name: g_nof_streams, value: 1 }
mm_port_names:
......
......@@ -129,7 +129,7 @@
<spirit:parameter>
<spirit:name>addressSpan</spirit:name>
<spirit:displayName>Address span</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="addressSpan">32768</spirit:value>
<spirit:value spirit:format="string" spirit:id="addressSpan">65536</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>addressUnits</spirit:name>
......@@ -607,7 +607,7 @@
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>12</spirit:right>
<spirit:right>13</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
......@@ -703,7 +703,7 @@
<spirit:direction>out</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>12</spirit:right>
<spirit:right>13</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
......@@ -783,7 +783,7 @@
<spirit:parameter>
<spirit:name>g_adr_w</spirit:name>
<spirit:displayName>g_adr_w</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="g_adr_w">13</spirit:value>
<spirit:value spirit:format="long" spirit:id="g_adr_w">14</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>g_dat_w</spirit:name>
......@@ -846,7 +846,7 @@
<name>coe_address_export</name>
<role>export</role>
<direction>Output</direction>
<width>13</width>
<width>14</width>
<lowerBound>0</lowerBound>
<vhdlType>STD_LOGIC_VECTOR</vhdlType>
</port>
......@@ -910,7 +910,7 @@
<name>avs_mem_address</name>
<role>address</role>
<direction>Input</direction>
<width>13</width>
<width>14</width>
<lowerBound>0</lowerBound>
<vhdlType>STD_LOGIC_VECTOR</vhdlType>
</port>
......@@ -979,7 +979,7 @@
</entry>
<entry>
<key>addressSpan</key>
<value>32768</value>
<value>65536</value>
</entry>
<entry>
<key>addressUnits</key>
......@@ -1374,11 +1374,11 @@
<consumedSystemInfos>
<entry>
<key>ADDRESS_MAP</key>
<value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x8000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
<value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x10000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
</entry>
<entry>
<key>ADDRESS_WIDTH</key>
<value>15</value>
<value>16</value>
</entry>
<entry>
<key>MAX_SLAVE_DATA_WIDTH</key>
......
......@@ -129,7 +129,7 @@
<spirit:parameter>
<spirit:name>addressSpan</spirit:name>
<spirit:displayName>Address span</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="addressSpan">65536</spirit:value>
<spirit:value spirit:format="string" spirit:id="addressSpan">131072</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>addressUnits</spirit:name>
......@@ -607,7 +607,7 @@
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>13</spirit:right>
<spirit:right>14</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
......@@ -703,7 +703,7 @@
<spirit:direction>out</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>13</spirit:right>
<spirit:right>14</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
......@@ -783,7 +783,7 @@
<spirit:parameter>
<spirit:name>g_adr_w</spirit:name>
<spirit:displayName>g_adr_w</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="g_adr_w">14</spirit:value>
<spirit:value spirit:format="long" spirit:id="g_adr_w">15</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>g_dat_w</spirit:name>
......@@ -846,7 +846,7 @@
<name>coe_address_export</name>
<role>export</role>
<direction>Output</direction>
<width>14</width>
<width>15</width>
<lowerBound>0</lowerBound>
<vhdlType>STD_LOGIC_VECTOR</vhdlType>
</port>
......@@ -910,7 +910,7 @@
<name>avs_mem_address</name>
<role>address</role>
<direction>Input</direction>
<width>14</width>
<width>15</width>
<lowerBound>0</lowerBound>
<vhdlType>STD_LOGIC_VECTOR</vhdlType>
</port>
......@@ -979,7 +979,7 @@
</entry>
<entry>
<key>addressSpan</key>
<value>65536</value>
<value>131072</value>
</entry>
<entry>
<key>addressUnits</key>
......@@ -1374,11 +1374,11 @@
<consumedSystemInfos>
<entry>
<key>ADDRESS_MAP</key>
<value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x10000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
<value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x20000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
</entry>
<entry>
<key>ADDRESS_WIDTH</key>
<value>16</value>
<value>17</value>
</entry>
<entry>
<key>MAX_SLAVE_DATA_WIDTH</key>
......
......@@ -129,7 +129,7 @@
<spirit:parameter>
<spirit:name>addressSpan</spirit:name>
<spirit:displayName>Address span</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="addressSpan">65536</spirit:value>
<spirit:value spirit:format="string" spirit:id="addressSpan">131072</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>addressUnits</spirit:name>
......@@ -607,7 +607,7 @@
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>13</spirit:right>
<spirit:right>14</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
......@@ -703,7 +703,7 @@
<spirit:direction>out</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>13</spirit:right>
<spirit:right>14</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
......@@ -783,7 +783,7 @@
<spirit:parameter>
<spirit:name>g_adr_w</spirit:name>
<spirit:displayName>g_adr_w</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="g_adr_w">14</spirit:value>
<spirit:value spirit:format="long" spirit:id="g_adr_w">15</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>g_dat_w</spirit:name>
......@@ -846,7 +846,7 @@
<name>coe_address_export</name>
<role>export</role>
<direction>Output</direction>
<width>14</width>
<width>15</width>
<lowerBound>0</lowerBound>
<vhdlType>STD_LOGIC_VECTOR</vhdlType>
</port>
......@@ -910,7 +910,7 @@
<name>avs_mem_address</name>
<role>address</role>
<direction>Input</direction>
<width>14</width>
<width>15</width>
<lowerBound>0</lowerBound>
<vhdlType>STD_LOGIC_VECTOR</vhdlType>
</port>
......@@ -979,7 +979,7 @@
</entry>
<entry>
<key>addressSpan</key>
<value>65536</value>
<value>131072</value>
</entry>
<entry>
<key>addressUnits</key>
......@@ -1374,11 +1374,11 @@
<consumedSystemInfos>
<entry>
<key>ADDRESS_MAP</key>
<value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x10000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
<value>&lt;address-map&gt;&lt;slave name='mem' start='0x0' end='0x20000' datawidth='32' /&gt;&lt;/address-map&gt;</value>
</entry>
<entry>
<key>ADDRESS_WIDTH</key>
<value>16</value>
<value>17</value>
</entry>
<entry>
<key>MAX_SLAVE_DATA_WIDTH</key>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment