增加CDR仿真下不同采样频率的代码
This commit is contained in:
@@ -126,80 +126,84 @@ if __name__ == '__main__':
|
|||||||
f = open("./tb/build/test_filter.vcd", "wt+", encoding="utf-8", newline="\n")
|
f = open("./tb/build/test_filter.vcd", "wt+", encoding="utf-8", newline="\n")
|
||||||
|
|
||||||
ratio = 100
|
ratio = 100
|
||||||
multi_clk_num = 16 #(4, 8, 16)
|
multi_clk_num = 4 #(4, 8, 16)
|
||||||
|
|
||||||
sys_clk_val = 1
|
sys_clk_val = 1
|
||||||
|
|
||||||
tx_ratio = ratio
|
tx_ratio = ratio - 1
|
||||||
|
|
||||||
sim_stop_time = 525000 * multi_clk_num #ns
|
sim_stop_time = 550000 * multi_clk_num #ns
|
||||||
#噪声强度
|
#噪声强度
|
||||||
phrase_noise_strength = int(multi_clk_num * ratio * 2 * 0.374)
|
phrase_noise_strength = int(multi_clk_num * ratio * 2 * 0.1)
|
||||||
|
|
||||||
|
|
||||||
reset_delay=100 #ns
|
reset_delay=100 #ns
|
||||||
ref_dout_delay = reset_delay + 100 #ns
|
tx_dout_delay = reset_delay + 100 #ns
|
||||||
ref_tx_dout_delay = reset_delay + 100 #ns
|
|
||||||
tx_dout_delay = ref_tx_dout_delay #ns
|
|
||||||
|
|
||||||
|
#random.seed(int(time.time() * 1000))
|
||||||
|
|
||||||
random.seed(int(time.time() * 1000))
|
|
||||||
|
|
||||||
|
|
||||||
multi_clk_val = (2 ** int(multi_clk_num / 2) - 1) << int(multi_clk_num / 2)
|
|
||||||
multi_clk_val = ((multi_clk_val << 1) & (2 ** multi_clk_num - 1)) + ((multi_clk_val >> (multi_clk_num - 1)) & 0x1)
|
|
||||||
multi_clk_prev_val = multi_clk_val
|
|
||||||
|
|
||||||
|
|
||||||
filter_result_check_delay = 375 * multi_clk_num
|
|
||||||
|
|
||||||
|
|
||||||
ref_clk_val = 1
|
|
||||||
with VCDWriter(f, timescale='1 ns', date='today') as writer:
|
with VCDWriter(f, timescale='1 ns', date='today') as writer:
|
||||||
sys_clk = writer.register_var('ebus.clock', 'sys_clk', 'wire', size=1, init=0)
|
sys_clk = writer.register_var('easybus', 'sys_clk', 'wire', size=1, init=0)
|
||||||
multi_clk = writer.register_var('ebus.clock', 'multi_clk', 'reg', size=multi_clk_num, init=0)
|
multi_clk = writer.register_var('easybus', 'multi_clk', 'reg', size=multi_clk_num, init=0)
|
||||||
ref_clk = writer.register_var('ebus.clock', 'ref_clk', 'wire', size=1, init=0)
|
|
||||||
|
|
||||||
#接收时钟
|
#接收时钟
|
||||||
rx_clk = writer.register_var('ebus', 'rx_clk', 'wire', size=1, init=0)
|
rx_clk = writer.register_var('easybus.sample', 'rx_clk', 'wire', size=1, init=0)
|
||||||
rx_clk_val = 0
|
rx_clk_val = 0
|
||||||
rx_clk_prev_val = 0
|
rx_clk_prev_val = 0
|
||||||
|
|
||||||
#发送时钟
|
#发送时钟
|
||||||
tx_clk = writer.register_var('ebus', 'tx_clk', 'wire', size=1, init=0)
|
tx_clk = writer.register_var('easybus', 'tx_clk', 'wire', size=1, init=0)
|
||||||
tx_clk_val = 0
|
tx_clk_val = 0
|
||||||
tx_clk_prev_val = 0
|
tx_clk_prev_val = 0
|
||||||
|
|
||||||
data_out = writer.register_var('ebus', 'data_out', 'wire', size=1, init=0)
|
#tx_clk data out
|
||||||
data_index = 0
|
tx_ser_dout = writer.register_var('easybus', 'tx_ser_dout', 'wire', size=1, init=0)
|
||||||
|
tx_ser_dout_idx = 0
|
||||||
|
tx_ser_dout_bit = 0
|
||||||
|
|
||||||
ref_data_out = writer.register_var('ebus', 'ref_data_out', 'wire', size=1, init=0)
|
#ref_clk data out, ref_clk == rx_clk
|
||||||
ref_data_index = 0
|
ref_clk = writer.register_var('easybus', 'ref_clk', 'wire', size=1, init=0)
|
||||||
|
ref_clk_val = 1
|
||||||
|
ref_clk_prev_val = 0
|
||||||
|
|
||||||
nosie_data_out = writer.register_var('ebus', 'nosie_data_out', 'wire', size=1, init=0)
|
ref_ser_dout = writer.register_var('easybus', 'ref_ser_dout', 'wire', size=1, init=0)
|
||||||
nosie_data_index = 0
|
ref_ser_dout_idx = 0
|
||||||
|
ref_ser_dout_bit = 0
|
||||||
|
|
||||||
sample = list()
|
chk_dout = writer.register_var('easybus', 'chk_dout', 'wire', size=1, init=0)
|
||||||
noise_sample = list()
|
chk_dout_val = 0
|
||||||
for i in range(multi_clk_num):
|
chk_dout_prev_val = 0
|
||||||
sample.append(writer.register_var('ebus.sample', f'sample_{i}', 'wire', size=1, init=0))
|
|
||||||
noise_sample.append(writer.register_var('ebus.sample', f'noise_sample_{i}', 'wire', size=1, init=0))
|
sa_dout = writer.register_var('easybus.sample', f'sa_dout', 'wire', size=1, init=0)
|
||||||
sample_out = writer.register_var('ebus.sample', f'sample_out', 'wire', size=1, init=0)
|
ref_sa_dout = writer.register_var('easybus.sample', f'ref_sa_dout', 'wire', size=1, init=0)
|
||||||
noise_sample_out = writer.register_var('ebus.sample', f'noise_sample_out', 'wire', size=1, init=0)
|
ref_sa_dout_idx = 0
|
||||||
|
|
||||||
|
det_edge = writer.register_var('easybus.sample', f'det_edge', 'wire', size=1, init=0)
|
||||||
|
det_edge_val = 0
|
||||||
|
|
||||||
|
sa_in_val = [0, ] * multi_clk_num * 3
|
||||||
|
ph_in_sa = [0, ] * multi_clk_num * 3
|
||||||
|
chg_pos = 0
|
||||||
|
#phrase_limit_clk_idx = 0
|
||||||
|
|
||||||
|
ph_reg = writer.register_var('easybus.sample', 'ph_reg', 'reg', size=4, init=0)
|
||||||
|
cur_ph = -1
|
||||||
|
|
||||||
|
start_rx = 0
|
||||||
|
temp_sa_bit = list()
|
||||||
|
output_sa_data = False
|
||||||
|
sa_bit = list()
|
||||||
|
ref_sa_bit = list()
|
||||||
|
|
||||||
|
|
||||||
ref_sample_out = writer.register_var('ebus.sample', f'ref_sample_out', 'wire', size=1, init=0)
|
result_check = writer.register_var('easybus.sample', f'result_check', 'wire', size=1, init=0)
|
||||||
ref_sample_out_index = 0
|
|
||||||
|
|
||||||
filter_result_check = writer.register_var('ebus.sample', f'filter_result_check', 'wire', size=1, init=0)
|
ref_dout_start = 0
|
||||||
|
ref_dout_start_time = 0
|
||||||
|
|
||||||
data_bit = 0
|
|
||||||
noise_data_bit = 0
|
multi_clk_val = 0
|
||||||
noise_dout_time = int((tx_dout_delay + tx_ratio * multi_clk_num * 2 - 1) / (tx_ratio * multi_clk_num * 2)) * (tx_ratio * multi_clk_num * 2)
|
multi_clk_init_val = 2 ** int(multi_clk_num / 2) - 1 #0b0000000011111111
|
||||||
noise_time = get_noise(phrase_noise_strength)
|
multi_clk_prev_val = multi_clk_val
|
||||||
#noise_dout_time_next = int((tx_dout_delay + tx_ratio * multi_clk_num * 2 - 1) / (tx_ratio * multi_clk_num * 2)) * (tx_ratio * multi_clk_num * 2) + (tx_ratio * multi_clk_num * 2) + get_noise(phrase_noise_strength)
|
|
||||||
sample_filter_data = [0, ] * multi_clk_num
|
|
||||||
noise_sample_filter_data = [0, ] * multi_clk_num
|
|
||||||
|
|
||||||
for timestamp in range(sim_stop_time):
|
for timestamp in range(sim_stop_time):
|
||||||
if timestamp >= reset_delay:
|
if timestamp >= reset_delay:
|
||||||
@@ -216,33 +220,35 @@ if __name__ == '__main__':
|
|||||||
writer.change(rx_clk, timestamp, rx_clk_val)
|
writer.change(rx_clk, timestamp, rx_clk_val)
|
||||||
rx_clk_prev_val = rx_clk_val
|
rx_clk_prev_val = rx_clk_val
|
||||||
|
|
||||||
|
|
||||||
#这里输出数据,主要做参考使用
|
|
||||||
if (rx_clk_val == 1) and (timestamp >= ref_dout_delay):
|
|
||||||
ref_data_bit = data_map_bit(ref_data_index)#, True)
|
|
||||||
writer.change(ref_data_out, timestamp, ref_data_bit)
|
|
||||||
ref_data_index = ref_data_index + 1
|
|
||||||
|
|
||||||
#发送数据
|
#发送数据
|
||||||
t2 = timestamp % (tx_ratio * multi_clk_num)
|
t2 = timestamp % (tx_ratio * multi_clk_num)
|
||||||
if (t2 == 0) and (timestamp >= ref_tx_dout_delay):
|
if (t2 == 0) and (timestamp >= tx_dout_delay):
|
||||||
#if tx_clk_val != tx_clk_prev_val:
|
|
||||||
writer.change(tx_clk, timestamp, tx_clk_val)
|
writer.change(tx_clk, timestamp, tx_clk_val)
|
||||||
if tx_clk_val == 1:
|
if tx_clk_val == 1:
|
||||||
data_bit = data_map_bit(data_index)#, True)
|
if ref_dout_start == 0:
|
||||||
writer.change(data_out, timestamp, data_bit)
|
ref_dout_start_time = timestamp
|
||||||
data_index = data_index + 1
|
ref_dout_start = 1
|
||||||
|
tx_ser_dout_bit = data_map_bit(tx_ser_dout_idx)#, True)
|
||||||
|
writer.change(tx_ser_dout, timestamp, tx_ser_dout_bit)
|
||||||
|
tx_ser_dout_idx = tx_ser_dout_idx + 1
|
||||||
|
|
||||||
tx_clk_prev_val = tx_clk_val
|
tx_clk_prev_val = tx_clk_val
|
||||||
tx_clk_val = 1 - tx_clk_val
|
tx_clk_val = 1 - tx_clk_val
|
||||||
|
|
||||||
#发送带噪声的数据
|
if (ref_dout_start == 1):
|
||||||
if timestamp >= (noise_dout_time + noise_time):
|
if ((timestamp - ref_dout_start_time) % (ratio * multi_clk_num)) == 0:
|
||||||
noise_data_bit = data_map_bit(nosie_data_index)
|
if ref_clk_val == 1:
|
||||||
writer.change(nosie_data_out, timestamp, noise_data_bit)
|
ref_ser_dout_bit = data_map_bit(ref_ser_dout_idx)#, True)
|
||||||
nosie_data_index = nosie_data_index + 1
|
writer.change(ref_ser_dout, timestamp, ref_ser_dout_bit)
|
||||||
noise_dout_time = noise_dout_time + (tx_ratio * multi_clk_num * 2)
|
ref_ser_dout_idx = ref_ser_dout_idx + 1
|
||||||
noise_time = get_noise(phrase_noise_strength)
|
writer.change(ref_clk, timestamp, ref_clk_val)
|
||||||
|
ref_clk_val = 1 - ref_clk_val
|
||||||
|
|
||||||
|
#检查输出与标准输出之间的差异
|
||||||
|
chk_dout_val = ref_ser_dout_bit ^ tx_ser_dout_bit
|
||||||
|
if chk_dout_val != chk_dout_prev_val:
|
||||||
|
writer.change(chk_dout, timestamp, chk_dout_val)
|
||||||
|
chk_dout_prev_val = chk_dout_val
|
||||||
|
|
||||||
#采样数据
|
#采样数据
|
||||||
if t == 0:
|
if t == 0:
|
||||||
@@ -250,37 +256,89 @@ if __name__ == '__main__':
|
|||||||
for i in range(multi_clk_num):
|
for i in range(multi_clk_num):
|
||||||
if ((multi_clk_val & (1<<i)) != (multi_clk_prev_val & (1<<i))):
|
if ((multi_clk_val & (1<<i)) != (multi_clk_prev_val & (1<<i))):
|
||||||
if (multi_clk_val & (1<<i)) != 0:
|
if (multi_clk_val & (1<<i)) != 0:
|
||||||
writer.change(sample[i], timestamp, data_bit)
|
|
||||||
writer.change(noise_sample[i], timestamp, noise_data_bit)
|
|
||||||
|
|
||||||
sample_filter_data = sample_filter_data[1:] + [data_bit, ]
|
|
||||||
noise_sample_filter_data = noise_sample_filter_data[1:] + [noise_data_bit, ]
|
|
||||||
if i == 0:
|
|
||||||
writer.change(sample_out, timestamp, filter_1(sample_filter_data))
|
|
||||||
b1 = filter_1(noise_sample_filter_data)
|
|
||||||
writer.change(noise_sample_out, timestamp, b1)
|
|
||||||
if timestamp > filter_result_check_delay:
|
|
||||||
b2 = data_map_bit(ref_sample_out_index)
|
|
||||||
writer.change(ref_sample_out, timestamp, b2)
|
|
||||||
writer.change(filter_result_check, timestamp, b1 ^ b2)
|
|
||||||
|
|
||||||
ref_sample_out_index = ref_sample_out_index + 1
|
|
||||||
|
|
||||||
|
|
||||||
multi_clk_prev_val = multi_clk_prev_val | (1<<i)
|
multi_clk_prev_val = multi_clk_prev_val | (1<<i)
|
||||||
|
sa_in_val = sa_in_val[1:] + [tx_ser_dout_bit, ]
|
||||||
|
ph_in_sa = ph_in_sa[1:] + [i, ]
|
||||||
|
det_edge_buf = [sa_in_val[i - 1] ^ sa_in_val[i] for i in range(1, len(sa_in_val))]
|
||||||
|
#print(sa_in_val, det_edge_buf, i)
|
||||||
|
|
||||||
|
#输出edge
|
||||||
|
if det_edge_buf[-1] != det_edge_val:
|
||||||
|
writer.change(det_edge, timestamp, det_edge_buf[-1])
|
||||||
|
det_edge_val = det_edge_buf[-1]
|
||||||
|
|
||||||
|
#更新当前的phrase
|
||||||
|
#'''
|
||||||
|
check_pos = - multi_clk_num * 2 - 1
|
||||||
|
|
||||||
|
if det_edge_buf[check_pos] == 1:
|
||||||
|
temp_ph = (ph_in_sa[check_pos] + (multi_clk_num >> 1) - 1) % multi_clk_num
|
||||||
|
if (cur_ph != -1):
|
||||||
|
if (cur_ph - temp_ph) >= (multi_clk_num >> 1):
|
||||||
|
chg_pos = 1
|
||||||
|
elif (temp_ph - cur_ph) > (multi_clk_num >> 1):
|
||||||
|
chg_pos = -1
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
cur_ph = temp_ph
|
||||||
|
writer.change(ph_reg, timestamp, cur_ph)
|
||||||
|
start_rx = 1
|
||||||
|
|
||||||
|
|
||||||
|
if (start_rx == 1) and (i == 0):
|
||||||
|
if chg_pos == 0:
|
||||||
|
ref_saout_bit = data_map_bit(ref_sa_dout_idx)
|
||||||
|
if output_sa_data:
|
||||||
|
ref_sa_bit.append(ref_saout_bit)
|
||||||
|
writer.change(ref_sa_dout, timestamp, ref_saout_bit)
|
||||||
|
ref_sa_dout_idx = ref_sa_dout_idx + 1
|
||||||
|
if output_sa_data:
|
||||||
|
sa_bit.append(sa_in_val[-multi_clk_num*2 - 1 + cur_ph])
|
||||||
|
|
||||||
|
temp_sa_bit.append(sa_in_val[-multi_clk_num*2 - 1 + cur_ph])
|
||||||
|
writer.change(sa_dout, timestamp, temp_sa_bit[0])
|
||||||
|
writer.change(result_check, timestamp, temp_sa_bit[0] ^ ref_saout_bit)
|
||||||
|
temp_sa_bit = temp_sa_bit[1:]
|
||||||
|
elif chg_pos == -1:
|
||||||
|
ref_saout_bit = data_map_bit(ref_sa_dout_idx)
|
||||||
|
if output_sa_data:
|
||||||
|
ref_sa_bit.append(ref_saout_bit)
|
||||||
|
writer.change(ref_sa_dout, timestamp, ref_saout_bit)
|
||||||
|
ref_sa_dout_idx = ref_sa_dout_idx + 1
|
||||||
|
|
||||||
|
if output_sa_data:
|
||||||
|
sa_bit.append(sa_in_val[-multi_clk_num*3 - 1 + cur_ph])
|
||||||
|
sa_bit.append(sa_in_val[-multi_clk_num*2 - 1 + cur_ph])
|
||||||
|
|
||||||
|
temp_sa_bit.append(sa_in_val[-multi_clk_num*3 - 1 + cur_ph])
|
||||||
|
temp_sa_bit.append(sa_in_val[-multi_clk_num*2 - 1 + cur_ph])
|
||||||
|
|
||||||
|
writer.change(sa_dout, timestamp, temp_sa_bit[0])
|
||||||
|
writer.change(result_check, timestamp, temp_sa_bit[0] ^ ref_saout_bit)
|
||||||
|
|
||||||
|
temp_sa_bit = temp_sa_bit[1:]
|
||||||
|
chg_pos = 0
|
||||||
|
else:
|
||||||
|
writer.change(ref_sa_dout, timestamp, 'X')
|
||||||
|
writer.change(sa_dout, timestamp, 'X')
|
||||||
|
chg_pos = 0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
multi_clk_prev_val = multi_clk_prev_val ^ (1<<i)
|
multi_clk_prev_val = multi_clk_prev_val ^ (1<<i)
|
||||||
|
|
||||||
|
|
||||||
if t == 0:
|
if t == 0:
|
||||||
multi_clk_val = ((multi_clk_val << 1) & (2 ** multi_clk_num - 1)) + ((multi_clk_val >> (multi_clk_num - 1)) & 0x1)
|
multi_clk_val = ((multi_clk_val << 1) & (2 ** multi_clk_num - 1)) + ((multi_clk_val >> (multi_clk_num - 1)) & 0x1) + (multi_clk_init_val & 0x1)
|
||||||
|
multi_clk_init_val = multi_clk_init_val >> 1
|
||||||
|
|
||||||
if timestamp % (ratio) == 0:
|
|
||||||
writer.change(ref_clk, timestamp, ref_clk_val)
|
|
||||||
ref_clk_val = 1 - ref_clk_val
|
|
||||||
|
|
||||||
#更新sys时钟
|
#更新sys时钟
|
||||||
sys_clk_val = 1 - sys_clk_val
|
sys_clk_val = 1 - sys_clk_val
|
||||||
|
if output_sa_data:
|
||||||
|
print(len(sa_bit), len(ref_sa_bit))
|
||||||
|
if len(sa_bit) < len(ref_sa_bit):
|
||||||
|
print(sa_bit == ref_sa_bit[:len(sa_bit)])
|
||||||
|
else:
|
||||||
|
print(sa_bit[:len(ref_sa_bit)] == ref_sa_bit)
|
||||||
f.close()
|
f.close()
|
||||||
print(f"max_noise={max_noise}ns")
|
|
||||||
Reference in New Issue
Block a user