fix helper PLL glitches
sim: rename collector to phase_collector sim: add period_collector for gtx tags sim: trigger helper PLL after period_collector_r sim: remove cycle slip compensation sim: generator gtx in time loop wave_gen: replace square generator with phase accumulator wave_gen&wrpll: add white_noise generator docs: remove section & png about cycle slipping and deglitcher failure
This commit is contained in:
parent
da5908e754
commit
0a66f4c343
17
README.md
17
README.md
@ -49,20 +49,3 @@ source .venv/bin/activate
|
|||||||
|
|
||||||
## Limitation
|
## Limitation
|
||||||
As the simulation is not cycle nor delay accurate, there will be more glitches than the hardware implementation
|
As the simulation is not cycle nor delay accurate, there will be more glitches than the hardware implementation
|
||||||
|
|
||||||
### Helper PLL glitches (remedies are added to follow hardware behavior)
|
|
||||||
|
|
||||||
- Cycle slipping issue will appear as $|\Delta{period}| \sim N$
|
|
||||||
- During hardware testing, slipping issue is not common
|
|
||||||
- It's recommended to turn cycle_slip_comp ON to reduce slipping and have a more accurate simulation
|
|
||||||
|
|
||||||
![cycle_slip](img/cycle_slipping.png)
|
|
||||||
|
|
||||||
|
|
||||||
- Deglitcher fail issue will appear as $|\Delta{period}| \sim N/2$
|
|
||||||
- There are no such issue for hardware
|
|
||||||
- It's recommended to set blind_period higher than the hardware setting (around 300 is sufficient)
|
|
||||||
|
|
||||||
![deglitch_fail](img/deglitch_fail.png)
|
|
||||||
|
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 23 KiB |
141
src/sim.py
141
src/sim.py
@ -6,7 +6,8 @@ from wave_gen import square
|
|||||||
@njit
|
@njit
|
||||||
def simulation_jit(
|
def simulation_jit(
|
||||||
time,
|
time,
|
||||||
gtx,
|
gtx_freq,
|
||||||
|
gtx_jitter,
|
||||||
helper_pll,
|
helper_pll,
|
||||||
main_pll,
|
main_pll,
|
||||||
h_KP,
|
h_KP,
|
||||||
@ -16,13 +17,13 @@ def simulation_jit(
|
|||||||
m_KI,
|
m_KI,
|
||||||
m_KD,
|
m_KD,
|
||||||
dcxo_freq,
|
dcxo_freq,
|
||||||
dcxo_jitter_SD,
|
h_jitter,
|
||||||
|
m_jitter,
|
||||||
base_adpll,
|
base_adpll,
|
||||||
N,
|
N,
|
||||||
adpll_write_period,
|
adpll_write_period,
|
||||||
blind_period,
|
blind_period,
|
||||||
start_up_delay,
|
start_up_delay,
|
||||||
cycle_slip_comp=True,
|
|
||||||
helper_init_freq=0
|
helper_init_freq=0
|
||||||
):
|
):
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ def simulation_jit(
|
|||||||
|
|
||||||
main = np.zeros(arr_len, dtype=np.int8)
|
main = np.zeros(arr_len, dtype=np.int8)
|
||||||
helper = np.zeros(arr_len, dtype=np.int8)
|
helper = np.zeros(arr_len, dtype=np.int8)
|
||||||
|
gtx = np.zeros(arr_len, dtype=np.int8)
|
||||||
|
|
||||||
gtx_tag = 0
|
gtx_tag = 0
|
||||||
gtx_ready = 0
|
gtx_ready = 0
|
||||||
@ -40,7 +42,6 @@ def simulation_jit(
|
|||||||
main_ready = 0
|
main_ready = 0
|
||||||
main_FF = 0
|
main_FF = 0
|
||||||
main_beating = np.zeros(arr_len, dtype=np.int8)
|
main_beating = np.zeros(arr_len, dtype=np.int8)
|
||||||
collector_r = 0
|
|
||||||
|
|
||||||
phase_err_arr = np.zeros(arr_len, dtype=np.int16)
|
phase_err_arr = np.zeros(arr_len, dtype=np.int16)
|
||||||
period_err_arr = np.zeros(arr_len, dtype=np.int16)
|
period_err_arr = np.zeros(arr_len, dtype=np.int16)
|
||||||
@ -50,15 +51,20 @@ def simulation_jit(
|
|||||||
helperfreq = np.zeros(arr_len, dtype=np.int32)
|
helperfreq = np.zeros(arr_len, dtype=np.int32)
|
||||||
mainfreq = np.zeros(arr_len, dtype=np.int32)
|
mainfreq = np.zeros(arr_len, dtype=np.int32)
|
||||||
|
|
||||||
# initial condition
|
phase_collector_r = 0
|
||||||
main_init_offset = (np.random.uniform(0, 360)) / (360 * dcxo_freq)
|
colr_gtx_tag = colr_main_tag = 0
|
||||||
helper_init_offset = (np.random.uniform(0, 360)) / (360 * dcxo_freq)
|
phase_collector_state = 0
|
||||||
|
|
||||||
# intermediate values
|
period_collector_r = 0
|
||||||
helper_jitter = np.random.normal(0, dcxo_jitter_SD)
|
colr_last_gtx_tag = 0
|
||||||
main_jitter = np.random.normal(0, dcxo_jitter_SD)
|
beating_period = 0
|
||||||
helper_cycle_num = 0
|
period_collector_state = 0
|
||||||
main_cycle_num = 0
|
|
||||||
|
# initial condition
|
||||||
|
timestep = time[1] - time[0]
|
||||||
|
gtx_phase = 0
|
||||||
|
h_phase = np.random.uniform(0, 360)
|
||||||
|
m_phase = np.random.uniform(0, 360)
|
||||||
|
|
||||||
if main_pll and not helper_pll:
|
if main_pll and not helper_pll:
|
||||||
helper_freq = helper_init_freq
|
helper_freq = helper_init_freq
|
||||||
@ -66,12 +72,10 @@ def simulation_jit(
|
|||||||
helper_freq = dcxo_freq * (1 + base_adpll * 0.0001164 / 1_000_000) * ((N-1) / N)
|
helper_freq = dcxo_freq * (1 + base_adpll * 0.0001164 / 1_000_000) * ((N-1) / N)
|
||||||
main_freq = dcxo_freq * (1 + base_adpll * 0.0001164 / 1_000_000)
|
main_freq = dcxo_freq * (1 + base_adpll * 0.0001164 / 1_000_000)
|
||||||
|
|
||||||
FSM_state = 0
|
|
||||||
coll_gtx_tag = coll_main_tag = 0
|
|
||||||
last_gtx_tag = last_gtx_FF = last_gtx_beat = 0
|
last_gtx_tag = last_gtx_FF = last_gtx_beat = 0
|
||||||
last_main_tag = last_main_FF = last_main_beat = 0
|
last_main_tag = last_main_FF = last_main_beat = 0
|
||||||
|
|
||||||
last_helper = last_main = 0
|
last_helper = 0
|
||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
gtx_blind_counter = 0
|
gtx_blind_counter = 0
|
||||||
@ -84,38 +88,32 @@ def simulation_jit(
|
|||||||
wait_main = True
|
wait_main = True
|
||||||
|
|
||||||
# firmware values
|
# firmware values
|
||||||
FW_gtx_tag = FW_last_gtx_tag = 0
|
FW_gtx_tag = 0
|
||||||
FW_main_tag = 0
|
FW_main_tag = 0
|
||||||
|
|
||||||
period_err = last_period_err = 0
|
period_err = last_period_err = 0
|
||||||
h_prop = h_integrator = h_derivative = 0
|
h_prop = h_integrator = h_derivative = 0
|
||||||
h_adpll = base_adpll
|
h_adpll = base_adpll
|
||||||
h_i2c_active = False
|
period_colr_arm = h_i2c_active = False
|
||||||
|
|
||||||
phase_err = last_phase_err = 0
|
phase_err = last_phase_err = 0
|
||||||
m_prop = m_integrator = m_derivative = 0
|
m_prop = m_integrator = m_derivative = 0
|
||||||
m_adpll = base_adpll
|
m_adpll = base_adpll
|
||||||
m_i2c_active = False
|
phase_colr_arm = m_i2c_active = False
|
||||||
|
|
||||||
adpll_active = False
|
|
||||||
adpll_max = 8161512
|
adpll_max = 8161512
|
||||||
def clip(n, minn, maxn): return max(min(maxn, n), minn)
|
def clip(n, minn, maxn): return max(min(maxn, n), minn)
|
||||||
|
|
||||||
for i, t in enumerate(time):
|
for i, t in enumerate(time):
|
||||||
|
|
||||||
helper[i], helper_cycle_num, helper_jitter = square(
|
h_phase += 360 * helper_freq * (timestep + h_jitter[i])
|
||||||
t + helper_init_offset, helper_freq, dcxo_jitter_SD, helper_jitter, helper_cycle_num)
|
helper[i] = square(h_phase)
|
||||||
main[i], main_cycle_num, main_jitter = square(
|
|
||||||
t + main_init_offset, main_freq, dcxo_jitter_SD, main_jitter, main_cycle_num)
|
|
||||||
|
|
||||||
# continuous glitchless output, assume very small frequency change
|
m_phase += 360 * main_freq * (timestep + m_jitter[i])
|
||||||
if h_i2c_active and helper[i]:
|
main[i] = square(m_phase)
|
||||||
helper_freq = dcxo_freq * (1 + h_adpll * 0.0001164 / 1_000_000) * ((N-1) / N)
|
|
||||||
h_i2c_active = False
|
|
||||||
|
|
||||||
if m_i2c_active and main[i]:
|
gtx_phase += 360 * gtx_freq * (timestep + gtx_jitter[i])
|
||||||
main_freq = dcxo_freq * (1 + m_adpll * 0.0001164 / 1_000_000)
|
gtx[i] = square(gtx_phase)
|
||||||
m_i2c_active = False
|
|
||||||
|
|
||||||
if not last_helper and helper[i]:
|
if not last_helper and helper[i]:
|
||||||
|
|
||||||
@ -130,12 +128,15 @@ def simulation_jit(
|
|||||||
main_blind_counter, main_blinded, blind_period,
|
main_blind_counter, main_blinded, blind_period,
|
||||||
last_main_beat, last_main_tag, counter)
|
last_main_beat, last_main_tag, counter)
|
||||||
|
|
||||||
collector_r, wait_gtx, wait_main, coll_gtx_tag, coll_main_tag, FSM_state = Collector_FSM(gtx_ready, main_ready, gtx_tag, main_tag,
|
phase_collector_r, wait_gtx, wait_main, colr_gtx_tag, colr_main_tag, phase_collector_state = phase_collector_FSM(gtx_ready, main_ready, gtx_tag, main_tag,
|
||||||
wait_gtx, wait_main, coll_gtx_tag, coll_main_tag, FSM_state)
|
wait_gtx, wait_main, colr_gtx_tag, colr_main_tag, phase_collector_state)
|
||||||
|
|
||||||
if collector_r:
|
if phase_collector_r:
|
||||||
FW_gtx_tag = coll_gtx_tag
|
FW_gtx_tag = colr_gtx_tag
|
||||||
FW_main_tag = coll_main_tag
|
FW_main_tag = colr_main_tag
|
||||||
|
|
||||||
|
period_collector_r, colr_last_gtx_tag, beating_period, period_collector_state = period_collector_FSM(gtx_ready, gtx_tag,
|
||||||
|
colr_last_gtx_tag, period_collector_state)
|
||||||
|
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
@ -158,20 +159,11 @@ def simulation_jit(
|
|||||||
if i > start_up_delay:
|
if i > start_up_delay:
|
||||||
|
|
||||||
# Firmware filters
|
# Firmware filters
|
||||||
if adpll_active and collector_r:
|
|
||||||
if cycle_slip_comp:
|
|
||||||
period = FW_gtx_tag - FW_last_gtx_tag
|
|
||||||
if period > 3 * N/2:
|
|
||||||
period = period - N
|
|
||||||
period_err = N - period
|
|
||||||
else:
|
|
||||||
period_err = (N - (FW_gtx_tag - FW_last_gtx_tag))
|
|
||||||
|
|
||||||
tag_diff = ((FW_main_tag - FW_gtx_tag) % N)
|
if period_colr_arm and period_collector_r:
|
||||||
if tag_diff > N/2:
|
|
||||||
phase_err = tag_diff - N
|
period_colr_arm = False
|
||||||
else:
|
period_err = N - beating_period
|
||||||
phase_err = tag_diff
|
|
||||||
|
|
||||||
if helper_pll:
|
if helper_pll:
|
||||||
h_prop = period_err * h_KP
|
h_prop = period_err * h_KP
|
||||||
@ -180,8 +172,18 @@ def simulation_jit(
|
|||||||
|
|
||||||
h_adpll = clip(int(base_adpll + h_prop + h_integrator + h_derivative), -adpll_max, adpll_max)
|
h_adpll = clip(int(base_adpll + h_prop + h_integrator + h_derivative), -adpll_max, adpll_max)
|
||||||
last_period_err = period_err
|
last_period_err = period_err
|
||||||
|
helper_freq = dcxo_freq * (1 + h_adpll * 0.0001164 / 1_000_000) * ((N-1) / N)
|
||||||
h_i2c_active = True
|
h_i2c_active = True
|
||||||
|
|
||||||
|
if phase_colr_arm and phase_collector_r:
|
||||||
|
|
||||||
|
phase_colr_arm = False
|
||||||
|
tag_diff = ((FW_main_tag - FW_gtx_tag) % N)
|
||||||
|
if tag_diff > N/2:
|
||||||
|
phase_err = tag_diff - N
|
||||||
|
else:
|
||||||
|
phase_err = tag_diff
|
||||||
|
|
||||||
if main_pll:
|
if main_pll:
|
||||||
m_prop = phase_err * m_KP
|
m_prop = phase_err * m_KP
|
||||||
m_integrator += phase_err * m_KI
|
m_integrator += phase_err * m_KI
|
||||||
@ -189,16 +191,13 @@ def simulation_jit(
|
|||||||
|
|
||||||
m_adpll = clip(int(base_adpll + m_prop + m_integrator + m_derivative), -adpll_max, adpll_max)
|
m_adpll = clip(int(base_adpll + m_prop + m_integrator + m_derivative), -adpll_max, adpll_max)
|
||||||
last_phase_err = phase_err
|
last_phase_err = phase_err
|
||||||
|
main_freq = dcxo_freq * (1 + m_adpll * 0.0001164 / 1_000_000)
|
||||||
m_i2c_active = True
|
m_i2c_active = True
|
||||||
|
|
||||||
adpll_active = False
|
|
||||||
|
|
||||||
if i % adpll_write_period == 0:
|
if i % adpll_write_period == 0:
|
||||||
adpll_active = True
|
period_colr_arm = phase_colr_arm = True
|
||||||
FW_last_gtx_tag = FW_gtx_tag
|
|
||||||
|
|
||||||
last_helper = helper[i]
|
last_helper = helper[i]
|
||||||
last_main = main[i]
|
|
||||||
|
|
||||||
# Data
|
# Data
|
||||||
period_err_arr[i] = period_err
|
period_err_arr[i] = period_err
|
||||||
@ -208,7 +207,7 @@ def simulation_jit(
|
|||||||
helperfreq[i] = helper_freq
|
helperfreq[i] = helper_freq
|
||||||
mainfreq[i] = main_freq
|
mainfreq[i] = main_freq
|
||||||
|
|
||||||
return period_err_arr, phase_err_arr, helper_adpll_arr, main_adpll_arr, gtx_beating, main_beating, helper, main, helperfreq, mainfreq
|
return period_err_arr, phase_err_arr, helper_adpll_arr, main_adpll_arr, gtx_beating, main_beating, gtx, helper, main, helperfreq, mainfreq
|
||||||
|
|
||||||
|
|
||||||
@njit
|
@njit
|
||||||
@ -237,37 +236,55 @@ def Deglitcher(beating, t_out, t_ready, blind_counter, blinded, blind_period, la
|
|||||||
|
|
||||||
|
|
||||||
@njit
|
@njit
|
||||||
def Collector_FSM(g_tag_r, m_tag_r, gtx_tag, main_tag, wait_gtx, wait_main, coll_gtx_tag, coll_main_tag, FSM_state):
|
def phase_collector_FSM(g_tag_r, m_tag_r, gtx_tag, main_tag, wait_gtx, wait_main, colr_gtx_tag, colr_main_tag, FSM_state):
|
||||||
|
|
||||||
collector_r = 0
|
collector_r = 0
|
||||||
|
|
||||||
match FSM_state:
|
match FSM_state:
|
||||||
case 0: # IDEL
|
case 0: # IDEL
|
||||||
if g_tag_r and m_tag_r:
|
if g_tag_r and m_tag_r:
|
||||||
coll_gtx_tag = gtx_tag
|
colr_gtx_tag = gtx_tag
|
||||||
coll_main_tag = main_tag
|
colr_main_tag = main_tag
|
||||||
FSM_state = 3 # OUTPUT
|
FSM_state = 3 # OUTPUT
|
||||||
|
|
||||||
elif g_tag_r:
|
elif g_tag_r:
|
||||||
coll_gtx_tag = gtx_tag
|
colr_gtx_tag = gtx_tag
|
||||||
wait_main = True
|
wait_main = True
|
||||||
FSM_state = 2 # WAITMAIN
|
FSM_state = 2 # WAITMAIN
|
||||||
|
|
||||||
elif m_tag_r:
|
elif m_tag_r:
|
||||||
coll_main_tag = main_tag
|
colr_main_tag = main_tag
|
||||||
wait_gtx = True
|
wait_gtx = True
|
||||||
FSM_state = 1 # WAITGTX
|
FSM_state = 1 # WAITGTX
|
||||||
case 1: # WAITGTX
|
case 1: # WAITGTX
|
||||||
if g_tag_r:
|
if g_tag_r:
|
||||||
coll_gtx_tag = gtx_tag
|
colr_gtx_tag = gtx_tag
|
||||||
FSM_state = 3 # OUTPUT
|
FSM_state = 3 # OUTPUT
|
||||||
case 2: # WAITMAIN
|
case 2: # WAITMAIN
|
||||||
if m_tag_r:
|
if m_tag_r:
|
||||||
coll_main_tag = main_tag
|
colr_main_tag = main_tag
|
||||||
FSM_state = 3 # OUTPUT
|
FSM_state = 3 # OUTPUT
|
||||||
case 3: # OUTPUT
|
case 3: # OUTPUT
|
||||||
wait_gtx = wait_main = False
|
wait_gtx = wait_main = False
|
||||||
collector_r = 1
|
collector_r = 1
|
||||||
FSM_state = 0
|
FSM_state = 0
|
||||||
|
|
||||||
return collector_r, wait_gtx, wait_main, coll_gtx_tag, coll_main_tag, FSM_state
|
return collector_r, wait_gtx, wait_main, colr_gtx_tag, colr_main_tag, FSM_state
|
||||||
|
|
||||||
|
|
||||||
|
@njit
|
||||||
|
def period_collector_FSM(g_tag_r, gtx_tag, colr_last_gtx_tag, FSM_state):
|
||||||
|
collector_r = 0
|
||||||
|
beating_period = 0
|
||||||
|
match FSM_state:
|
||||||
|
case 0: # IDEL
|
||||||
|
if g_tag_r:
|
||||||
|
colr_last_gtx_tag = gtx_tag
|
||||||
|
FSM_state = 1
|
||||||
|
case 1: # OUTPUT
|
||||||
|
if g_tag_r:
|
||||||
|
beating_period = gtx_tag - colr_last_gtx_tag
|
||||||
|
collector_r = 1
|
||||||
|
FSM_state = 0 # IDEL
|
||||||
|
|
||||||
|
return collector_r, colr_last_gtx_tag, beating_period, FSM_state
|
||||||
|
@ -1,69 +1,28 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
import numba as nb
|
||||||
from numba import njit
|
from numba import njit
|
||||||
|
|
||||||
|
|
||||||
@njit
|
def white_noise(low, high, size, seed=None):
|
||||||
def square(time, freq, jitter_SD, jitter, cycle_num):
|
return np.random.default_rng(seed).uniform(low, high, size)
|
||||||
"""
|
|
||||||
|
|
||||||
A scipy like square wave with jitter
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
time : timestamp, in seconds
|
|
||||||
|
|
||||||
freq : frequency in Hz
|
|
||||||
|
|
||||||
jitter_SD : standard deviation of jitter, in seconds
|
|
||||||
|
|
||||||
jitter : gaussian noise with `jitter_SD` as its standard deviation
|
|
||||||
|
|
||||||
cycle_num : time // period = cycle_num
|
|
||||||
----------
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
period = 1/(freq)
|
|
||||||
quarter = (period / 4)
|
|
||||||
out = 0
|
|
||||||
|
|
||||||
# A T/4 shift is applied to the following to match scipy square fn
|
|
||||||
# ┌──────┐
|
|
||||||
# ───┘ └────
|
|
||||||
# T/4 3T/4
|
|
||||||
nth_cycle, t = np.divmod(time + period / 4, period)
|
|
||||||
if t >= (quarter + jitter) and t <= (3*quarter + jitter):
|
|
||||||
out = 1
|
|
||||||
else:
|
|
||||||
out = 0
|
|
||||||
|
|
||||||
# update jitter every cycle
|
|
||||||
if nth_cycle != cycle_num:
|
|
||||||
jitter = np.random.normal(0, jitter_SD)
|
|
||||||
cycle_num = nth_cycle
|
|
||||||
|
|
||||||
return out, cycle_num, jitter
|
|
||||||
|
|
||||||
|
|
||||||
@njit
|
@njit(fastmath=True)
|
||||||
def square_arr(time, freq, jitter_SD):
|
def square_with_jitter(time, freq, jitter):
|
||||||
"""
|
n = len(time)
|
||||||
|
wave = np.empty(n)
|
||||||
A scipy like square wave with jitter
|
timestep = time[1] - time[0]
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
time : numpy array
|
|
||||||
|
|
||||||
freq : frequency in Hz
|
|
||||||
|
|
||||||
jitter_SD : standard deviation of jitter, in seconds
|
|
||||||
----------
|
|
||||||
|
|
||||||
"""
|
|
||||||
wave = np.zeros(len(time))
|
|
||||||
jitter = np.random.normal(0, jitter_SD)
|
|
||||||
cycle_num = 0
|
|
||||||
|
|
||||||
for i, t in enumerate(time):
|
|
||||||
wave[i], cycle_num, jitter = square(t, freq, jitter_SD, jitter, cycle_num)
|
|
||||||
|
|
||||||
|
phase = 0.
|
||||||
|
for i in range(n):
|
||||||
|
phase += 360 * freq * (timestep + jitter[i])
|
||||||
|
wave[i] = square(phase)
|
||||||
return wave
|
return wave
|
||||||
|
|
||||||
|
|
||||||
|
@njit
|
||||||
|
def square(x):
|
||||||
|
if np.mod(x, 360) < 180:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
28
src/wrpll.py
28
src/wrpll.py
@ -1,5 +1,5 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from wave_gen import square_arr
|
from wave_gen import white_noise
|
||||||
from sim import simulation_jit
|
from sim import simulation_jit
|
||||||
|
|
||||||
|
|
||||||
@ -12,16 +12,16 @@ class WRPLL_simulator():
|
|||||||
helper_filter,
|
helper_filter,
|
||||||
main_filter,
|
main_filter,
|
||||||
gtx_freq,
|
gtx_freq,
|
||||||
gtx_jitter_SD,
|
gtx_jitter,
|
||||||
dcxo_freq,
|
dcxo_freq,
|
||||||
dcxo_jitter_SD,
|
dcxo_jitter,
|
||||||
freq_acquisition_SD,
|
freq_acquisition_SD,
|
||||||
N,
|
N,
|
||||||
adpll_write_period,
|
adpll_write_period,
|
||||||
blind_period,
|
blind_period,
|
||||||
start_up_delay,
|
start_up_delay,
|
||||||
cycle_slip_comp,
|
helper_init_freq=None,
|
||||||
helper_init_freq=None
|
seed=None
|
||||||
):
|
):
|
||||||
|
|
||||||
self.time = time
|
self.time = time
|
||||||
@ -34,13 +34,15 @@ class WRPLL_simulator():
|
|||||||
self.m_KD = main_filter["KD"]
|
self.m_KD = main_filter["KD"]
|
||||||
|
|
||||||
# init condition
|
# init condition
|
||||||
|
self.gtx_freq = gtx_freq
|
||||||
|
self.gtx_jitter = white_noise(-gtx_jitter, gtx_jitter, len(time), seed)
|
||||||
|
|
||||||
self.dcxo_freq = dcxo_freq
|
self.dcxo_freq = dcxo_freq
|
||||||
self.dcxo_jitter_SD = dcxo_jitter_SD
|
self.h_jitter = white_noise(-dcxo_jitter, dcxo_jitter, len(time), seed)
|
||||||
|
self.m_jitter = white_noise(-dcxo_jitter, dcxo_jitter, len(time), seed)
|
||||||
self.N = N
|
self.N = N
|
||||||
self.helper_init_freq = helper_init_freq
|
self.helper_init_freq = helper_init_freq
|
||||||
|
|
||||||
self.gtx = square_arr(time, gtx_freq, gtx_jitter_SD)
|
|
||||||
|
|
||||||
# freq_acquisition() error
|
# freq_acquisition() error
|
||||||
freq_diff = gtx_freq - dcxo_freq + np.random.normal(0, freq_acquisition_SD)
|
freq_diff = gtx_freq - dcxo_freq + np.random.normal(0, freq_acquisition_SD)
|
||||||
self.base_adpll = int(freq_diff * (1 / dcxo_freq) * (1e6 / 0.0001164))
|
self.base_adpll = int(freq_diff * (1 / dcxo_freq) * (1e6 / 0.0001164))
|
||||||
@ -49,7 +51,6 @@ class WRPLL_simulator():
|
|||||||
self.adpll_write_period = adpll_write_period
|
self.adpll_write_period = adpll_write_period
|
||||||
self.blind_period = blind_period
|
self.blind_period = blind_period
|
||||||
self.start_up_delay = start_up_delay
|
self.start_up_delay = start_up_delay
|
||||||
self.cycle_slip_comp = cycle_slip_comp
|
|
||||||
|
|
||||||
if type(self.sim_mode) is not str:
|
if type(self.sim_mode) is not str:
|
||||||
raise ValueError(f"pll_type {type(self.sim_mode)} is not a string")
|
raise ValueError(f"pll_type {type(self.sim_mode)} is not a string")
|
||||||
@ -68,9 +69,10 @@ class WRPLL_simulator():
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
print("running simulation...")
|
print("running simulation...")
|
||||||
self.period_err, self.phase_err, self.helper_adpll, self.main_adpll, self.gtx_beating, self.main_beating, self.helper, self.main, self.helperfreq, self.mainfreq = simulation_jit(
|
self.period_err, self.phase_err, self.helper_adpll, self.main_adpll, self.gtx_beating, self.main_beating, self.gtx, self.helper, self.main, self.helperfreq, self.mainfreq = simulation_jit(
|
||||||
self.time,
|
self.time,
|
||||||
self.gtx,
|
self.gtx_freq,
|
||||||
|
self.gtx_jitter,
|
||||||
self.helper_pll,
|
self.helper_pll,
|
||||||
self.main_pll,
|
self.main_pll,
|
||||||
self.h_KP,
|
self.h_KP,
|
||||||
@ -80,13 +82,13 @@ class WRPLL_simulator():
|
|||||||
self.m_KI,
|
self.m_KI,
|
||||||
self.m_KD,
|
self.m_KD,
|
||||||
self.dcxo_freq,
|
self.dcxo_freq,
|
||||||
self.dcxo_jitter_SD,
|
self.h_jitter,
|
||||||
|
self.m_jitter,
|
||||||
self.base_adpll,
|
self.base_adpll,
|
||||||
self.N,
|
self.N,
|
||||||
self.adpll_write_period,
|
self.adpll_write_period,
|
||||||
self.blind_period,
|
self.blind_period,
|
||||||
self.start_up_delay,
|
self.start_up_delay,
|
||||||
self.cycle_slip_comp,
|
|
||||||
self.helper_init_freq
|
self.helper_init_freq
|
||||||
)
|
)
|
||||||
print("Done!")
|
print("Done!")
|
||||||
|
Loading…
Reference in New Issue
Block a user