增加CDR仿真下不同采样频率的代码

This commit is contained in:
2025-08-24 16:53:35 +08:00
parent dc67fee68e
commit 7a54581b91

View File

@@ -126,81 +126,85 @@ 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))
sample_out = writer.register_var('ebus.sample', f'sample_out', 'wire', size=1, init=0)
noise_sample_out = writer.register_var('ebus.sample', f'noise_sample_out', 'wire', size=1, init=0)
ref_sample_out = writer.register_var('ebus.sample', f'ref_sample_out', 'wire', size=1, init=0) sa_dout = writer.register_var('easybus.sample', f'sa_dout', 'wire', size=1, init=0)
ref_sample_out_index = 0 ref_sa_dout = writer.register_var('easybus.sample', f'ref_sa_dout', '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
filter_result_check = writer.register_var('ebus.sample', f'filter_result_check', 'wire', size=1, init=0) ph_reg = writer.register_var('easybus.sample', 'ph_reg', 'reg', size=4, init=0)
cur_ph = -1
data_bit = 0 start_rx = 0
noise_data_bit = 0 temp_sa_bit = list()
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) output_sa_data = False
noise_time = get_noise(phrase_noise_strength) sa_bit = list()
#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) ref_sa_bit = list()
sample_filter_data = [0, ] * multi_clk_num
noise_sample_filter_data = [0, ] * multi_clk_num
result_check = writer.register_var('easybus.sample', f'result_check', 'wire', size=1, init=0)
ref_dout_start = 0
ref_dout_start_time = 0
multi_clk_val = 0
multi_clk_init_val = 2 ** int(multi_clk_num / 2) - 1 #0b0000000011111111
multi_clk_prev_val = multi_clk_val
for timestamp in range(sim_stop_time): for timestamp in range(sim_stop_time):
if timestamp >= reset_delay: if timestamp >= reset_delay:
writer.change(sys_clk, timestamp, sys_clk_val) writer.change(sys_clk, timestamp, sys_clk_val)
@@ -215,72 +219,126 @@ if __name__ == '__main__':
if rx_clk_val != rx_clk_prev_val: if rx_clk_val != rx_clk_prev_val:
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 - ref_dout_start_time) % (ratio * multi_clk_num)) == 0:
if ref_clk_val == 1:
ref_ser_dout_bit = data_map_bit(ref_ser_dout_idx)#, True)
writer.change(ref_ser_dout, timestamp, ref_ser_dout_bit)
ref_ser_dout_idx = ref_ser_dout_idx + 1
writer.change(ref_clk, timestamp, ref_clk_val)
ref_clk_val = 1 - ref_clk_val
#发送带噪声的数据 #检查输出与标准输出之间的差异
if timestamp >= (noise_dout_time + noise_time): chk_dout_val = ref_ser_dout_bit ^ tx_ser_dout_bit
noise_data_bit = data_map_bit(nosie_data_index) if chk_dout_val != chk_dout_prev_val:
writer.change(nosie_data_out, timestamp, noise_data_bit) writer.change(chk_dout, timestamp, chk_dout_val)
nosie_data_index = nosie_data_index + 1 chk_dout_prev_val = chk_dout_val
noise_dout_time = noise_dout_time + (tx_ratio * multi_clk_num * 2)
noise_time = get_noise(phrase_noise_strength)
#采样数据 #采样数据
if t == 0: if t == 0:
#空间采样时钟发生沿跳变 #空间采样时钟发生沿跳变
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")