增加测试串行线路采样数据的代码, 可以回答晶体容限\漂移\滤波器效果等问题

This commit is contained in:
2025-08-19 09:10:43 +08:00
parent 4bdd1fd0ef
commit bd336313c6
2 changed files with 256 additions and 1 deletions

View File

@@ -53,9 +53,14 @@ testShin:
vvp -N ./tb/build/shinTest.iverilog -lxt2 || true vvp -N ./tb/build/shinTest.iverilog -lxt2 || true
./tb/shinTest/check_testcase.py ./tb/shinTest/check_testcase.py
testFilter:
./tb/shinTest/test_filter.py
vcdFilter:
gtkwave ./tb/build/test_filter.vcd 1>/dev/null 2>&1 &
vcdShin: vcdShin:
gtkwave ./tb/build/wave.vcd & gtkwave ./tb/build/wave.vcd 1>/dev/null 2>&1 &
ef: ef:
sbt "test:runMain test.testModule" sbt "test:runMain test.testModule"

250
tb/shinTest/test_filter.py Executable file
View File

@@ -0,0 +1,250 @@
#!/usr/bin/env python
#encoding=utf-8
import sys
from vcd import VCDWriter
import time
import random
def convert_4b_2_5b(data):
conv_table = [0b11110, 0b01001, 0b10100, 0b10101,
0b01010, 0b01011, 0b01110, 0b01111,
0b10010, 0b10011, 0b10110, 0b10111,
0b11010, 0b11011, 0b11100, 0b11101]
high = conv_table[(data >> 4) & 0xf]
low = conv_table[data & 0xf]
cv = (high << 5 | low) & 0x3ff
return cv
def data_map_bit(bit_order, use_code = True):
#rom = [0xa5, 0x5a, 0x5a, 0xa5]
rom = list(range(0, 255))
if use_code:
byte_order = int(bit_order / 10)
bit_order_in_byte = 9 - int(bit_order % 10)
if byte_order >= len(rom):
return 0
else:
data = convert_4b_2_5b(rom[byte_order])
if (data & (1 << bit_order_in_byte)) != 0:
return 1
else:
return 0
else:
byte_order = int(bit_order / 8)
bit_order_in_byte = 7 - int(bit_order % 8)
if byte_order >= len(rom):
return 0
else:
data = rom[byte_order]
if (data & (1 << bit_order_in_byte)) != 0:
return 1
else:
return 0
max_noise = 0
def get_noise(s):
global max_noise
#d = random.randint(-s, s)
d = random.randint(-1, 1) * s
'''
if d < 0:
if max_noise < -d:
max_noise = -d
else:
if max_noise < d:
max_noise = d
#print(f"{d}ns")
'''
return d
def filter_1(data, num = 9):
#'''
one_ctr = 0
zero_ctr = 0
for i in range(num):
if data[i] == 0:
zero_ctr = zero_ctr + 1
else:
one_ctr = one_ctr + 1
if zero_ctr > one_ctr:
return 0
else:
return 1
'''
r = data[0]+data[1]*2 +data[2]*8+data[3]*8+data[4]*8+data[5]*8+data[6]*2+data[7]
if r >= 16:
return 1
else:
return 0
#'''
if __name__ == '__main__':
f = open("./tb/build/test_filter.vcd", "wt+", encoding="utf-8", newline="\n")
ratio = 100
multi_clk_num = 16 #(4, 8, 16)
sys_clk_val = 1
tx_ratio = ratio
sim_stop_time = 525000 * multi_clk_num #ns
#噪声强度
phrase_noise_strength = int(multi_clk_num * ratio * 2 * 0.374)
reset_delay=100 #ns
ref_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))
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:
sys_clk = writer.register_var('ebus.clock', 'sys_clk', 'wire', size=1, init=0)
multi_clk = writer.register_var('ebus.clock', '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_val = 0
rx_clk_prev_val = 0
#发送时钟
tx_clk = writer.register_var('ebus', 'tx_clk', 'wire', size=1, init=0)
tx_clk_val = 0
tx_clk_prev_val = 0
data_out = writer.register_var('ebus', 'data_out', 'wire', size=1, init=0)
data_index = 0
ref_data_out = writer.register_var('ebus', 'ref_data_out', 'wire', size=1, init=0)
ref_data_index = 0
nosie_data_out = writer.register_var('ebus', 'nosie_data_out', 'wire', size=1, init=0)
nosie_data_index = 0
sample = list()
noise_sample = list()
for i in range(multi_clk_num):
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)
ref_sample_out_index = 0
filter_result_check = writer.register_var('ebus.sample', f'filter_result_check', 'wire', size=1, init=0)
data_bit = 0
noise_data_bit = 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)
noise_time = get_noise(phrase_noise_strength)
#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):
if timestamp >= reset_delay:
writer.change(sys_clk, timestamp, sys_clk_val)
t = timestamp % (2 * ratio)
if t == 0:
writer.change(multi_clk, timestamp, multi_clk_val)
if t == 0:
rx_clk_val = multi_clk_val & 0x1
if rx_clk_val != rx_clk_prev_val:
writer.change(rx_clk, timestamp, 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)
if (t2 == 0) and (timestamp >= ref_tx_dout_delay):
#if tx_clk_val != tx_clk_prev_val:
writer.change(tx_clk, timestamp, tx_clk_val)
if tx_clk_val == 1:
data_bit = data_map_bit(data_index)#, True)
writer.change(data_out, timestamp, data_bit)
data_index = data_index + 1
tx_clk_prev_val = tx_clk_val
tx_clk_val = 1 - tx_clk_val
#发送带噪声的数据
if timestamp >= (noise_dout_time + noise_time):
noise_data_bit = data_map_bit(nosie_data_index)
writer.change(nosie_data_out, timestamp, noise_data_bit)
nosie_data_index = nosie_data_index + 1
noise_dout_time = noise_dout_time + (tx_ratio * multi_clk_num * 2)
noise_time = get_noise(phrase_noise_strength)
#采样数据
if t == 0:
#空间采样时钟发生沿跳变
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)) != 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)
else:
multi_clk_prev_val = multi_clk_prev_val ^ (1<<i)
if t == 0:
multi_clk_val = ((multi_clk_val << 1) & (2 ** multi_clk_num - 1)) + ((multi_clk_val >> (multi_clk_num - 1)) & 0x1)
if timestamp % (ratio) == 0:
writer.change(ref_clk, timestamp, ref_clk_val)
ref_clk_val = 1 - ref_clk_val
#更新sys时钟
sys_clk_val = 1 - sys_clk_val
f.close()
print(f"max_noise={max_noise}ns")