一、引言
去年,我在学习通信原理的时候,做了一个有趣的实验:用一根50米长的网线传输10Gbps的高速数据。理论上应该完美传输,结果接收端看到的却是"满屏雪花"。那一刻我突然意识到------高速数字世界里的比特,就像深夜酒吧里传话的醉汉,每个环节都可能让信息失真。
这让我想起了福尔摩斯的名言:"当你排除了所有不可能,剩下的无论多么难以置信,一定是真相。" 在信号完整性分析中,我们就是要成为数字世界的福尔摩斯,找出比特"撒谎"的真相。
今天,我要分享的就是这样一个"侦探工具箱"------用Python实现的信号完整性分析系统。它不仅能生成眼图、分析抖动,还能像侦探一样推理出系统问题的根源。
二、项目概述
该项目的核心功能如下:
-
PRBS测试序列生成 - 数字系统的"标准试纸"
-
通道建模与失真模拟 - 信号旅途的"路况模拟器"
-
眼图生成与分析 - 信号健康的"心电图仪"
-
频率响应诊断 - 系统带宽的"听力测试"
-
误码率评估 - 通信质量的"成绩单"
三、代码详解:侦探破案的每个步骤
1.第一步:设定案发现场参数
python
# 参数设置 - 定义"犯罪现场"的时空坐标
fs = 100e9 # 采样频率:100GHz,相当于每秒拍1000亿张照片
bit_rate = 10e9 # 比特率:10Gbps,每秒传递100亿个比特
samples_per_bit = fs/bit_rate # 每比特10个采样点
num_bits = 10000 # 分析10000个比特,足够统计显著性
现实比喻 :想象你在观察高速公路的车流。fs是你的摄像机帧率,bit_rate是车流量,samples_per_bit是每辆车被拍到的照片数量。
2.第二步:准备测试信号 - PRBS生成器
python
def generate_prbs(order, length_bits):
"""生成PRBS序列 - 数字系统的'标准台词'"""
# PRBS的核心:线性反馈移位寄存器
# 就像一个有记忆的密码生成器
n = order # 阶数决定序列复杂度
register = np.ones(n, dtype=int) # 初始化寄存器
for i in range(2**n - 1):
# 关键算法:反馈与移位
feedback = register[-1] ^ register[-2] # 最后两位异或
register = np.roll(register, 1) # 整体右移
register[0] = feedback # 新位插入最左
return register_to_bits(register)
深度理解:
-
PRBS-7(127位周期)就像一段127个字的绕口令,包含了所有可能的发音组合
-
选择PRBS-7的原因:足够复杂又不会太长,就像用绕口令测试播音员的嘴皮子
-
数学原理:最大长度序列,在周期内0和1几乎各半,自相关函数接近δ函数
完整的项目源代码:
python
"""
高速数字信号完整性分析系统 - Python版(修复版)
作者:free-elcmacom
功能:眼图生成、抖动分析、BER估计等
环境:Python 3.10, PyCharm IDE
所需库:numpy, scipy, matplotlib
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy.interpolate import interp1d
import warnings
warnings.filterwarnings('ignore')
# ==================== 字体配置 ====================
# 修复字体显示问题
try:
# 尝试使用系统可用的中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = True # 解决负号显示问题
print("字体配置成功")
except:
print("字体配置失败,使用默认字体")
# ==================== 函数定义部分 ====================
def generate_prbs(order, length_bits):
"""
生成PRBS序列
:param order: PRBS阶数
:param length_bits: 需要生成的比特数
:return: PRBS序列
"""
n = order
prbs_length = 2**n - 1
# 根据阶数选择反馈抽头
if n == 7:
taps = [7, 6] # PRBS-7:x⁷ + x⁶ + 1
elif n == 9:
taps = [9, 5] # PRBS-9:x⁹ + x⁵ + 1
elif n == 11:
taps = [11, 9] # PRBS-11:x¹¹ + x⁹ + 1
elif n == 15:
taps = [15, 14] # PRBS-15:x¹⁵ + x¹⁴ + 1
elif n == 23:
taps = [23, 18] # PRBS-23:x²³ + x¹⁸ + 1
elif n == 31:
taps = [31, 28] # PRBS-31:x³¹ + x²⁸ + 1
else:
taps = [n, n-1] # 默认抽头
# 初始化移位寄存器
register = np.ones(n, dtype=int)
prbs = np.zeros(prbs_length, dtype=int)
# 生成序列
for i in range(prbs_length):
prbs[i] = register[-1] # 输出最高位
# 计算反馈值
feedback = 0
for tap in taps:
feedback ^= register[tap-1] # tap是从1开始计数的
# 移位
register = np.roll(register, 1)
register[0] = feedback
# 重复序列以达到所需长度
repeats = int(np.ceil(length_bits / prbs_length))
data = np.tile(prbs, repeats)
return data[:length_bits]
def calculate_eye_parameters(eye_data, time_axis, bit_period):
"""
计算眼图参数
:param eye_data: 眼图数据矩阵,每行是一个眼图轨迹
:param time_axis: 时间轴
:param bit_period: 比特周期
:return: 眼高, 眼宽, 眼幅度
"""
# 找到比特周期中心位置
center_idx = len(time_axis) // 2
# 计算眼高(在最佳采样点处)
center_samples = eye_data[:, center_idx]
# 分离正负电平
positive_samples = center_samples[center_samples > 0]
negative_samples = center_samples[center_samples < 0]
if len(positive_samples) > 0 and len(negative_samples) > 0:
eye_height = np.min(positive_samples) - np.max(negative_samples)
else:
eye_height = 0
# 简化计算眼宽(实际应基于眼图测量)
eye_width = 0.7 * bit_period * 1e12 # ps
# 计算眼幅度
eye_amplitude = np.max(eye_data) - np.min(eye_data)
return eye_height, eye_width, eye_amplitude
def plot_eye_diagram(signal_data, samples_per_bit, bit_period, fs, num_eyes=100):
"""
绘制眼图
:param signal_data: 输入信号
:param samples_per_bit: 每比特采样点数
:param bit_period: 比特周期
:param fs: 采样频率
:param num_eyes: 显示的眼图数量
"""
Ts = 1/fs
samples_per_eye = int(2 * samples_per_bit) # 显示两个比特周期
num_samples = len(signal_data)
# 计算可以提取多少个眼图段
num_segments = int(np.floor(num_samples / samples_per_bit)) - 1
num_segments = min(num_segments, int(num_eyes * samples_per_bit))
# 准备存储所有眼图轨迹
eye_data = []
# 提取每个比特段的波形
for i in range(num_segments):
start_idx = i * int(samples_per_bit)
end_idx = min(start_idx + samples_per_eye, num_samples)
if end_idx < num_samples and (end_idx - start_idx) == samples_per_eye:
segment = signal_data[start_idx:end_idx]
eye_data.append(segment)
if not eye_data:
raise ValueError("无法提取足够的眼图数据,请检查参数设置")
eye_data = np.array(eye_data)
# 创建时间轴(两个比特周期)
time_axis = np.arange(samples_per_eye) * Ts * 1e12 # 转换为ps
# 创建眼图
fig = plt.figure(figsize=(12, 8), dpi=100)
fig.suptitle('眼图分析', fontsize=14, fontweight='bold')
# 主眼图
ax_main = plt.subplot2grid((2, 3), (0, 0), colspan=2, rowspan=2)
# 绘制所有轨迹(限制数量避免过载)
max_traces = min(200, len(eye_data))
for i in range(max_traces):
ax_main.plot(time_axis, eye_data[i], 'b-', linewidth=0.1, alpha=0.1)
# 计算眼图统计
mean_eye = np.mean(eye_data, axis=0)
std_eye = np.std(eye_data, axis=0)
# 绘制平均眼图
ax_main.plot(time_axis, mean_eye, 'r-', linewidth=2, label='平均眼图')
# 绘制眼图模板(可根据标准调整)
template_upper = mean_eye + 3 * std_eye
template_lower = mean_eye - 3 * std_eye
ax_main.plot(time_axis, template_upper, 'g--', linewidth=1.5, label='±3σ边界')
ax_main.plot(time_axis, template_lower, 'g--', linewidth=1.5)
ax_main.set_xlabel('时间 (ps)')
ax_main.set_ylabel('幅度 (V)')
ax_main.grid(True, alpha=0.3)
ax_main.legend(loc='upper right')
# 标记重要参数
ax_main.axvline(bit_period * 1e12, color='k', linestyle='--', linewidth=1.5, alpha=0.7)
ax_main.axvline(2 * bit_period * 1e12, color='k', linestyle='--', linewidth=1.5, alpha=0.7)
ax_main.axhline(0, color='k', linestyle='-', linewidth=1, alpha=0.7)
# 眼图参数计算
eye_height, eye_width, eye_amplitude = calculate_eye_parameters(eye_data, time_axis, bit_period)
# 参数显示
ax_text = plt.subplot2grid((2, 3), (0, 2))
ax_text.axis('off')
text_y = 0.9
text_params = [
'眼图参数:',
f'眼高: {eye_height:.3f} V',
f'眼宽: {eye_width:.1f} ps',
f'眼幅度: {eye_amplitude:.3f} V',
f'轨迹数: {len(eye_data)}',
f'比特率: {1/(bit_period*1e9):.1f} Gbps'
]
for i, text in enumerate(text_params):
if i == 0:
ax_text.text(0.1, text_y - i*0.12, text, fontsize=12, fontweight='bold')
else:
ax_text.text(0.1, text_y - i*0.12, text, fontsize=10)
# 直方图分析(眼图中心采样点分布)
ax_hist = plt.subplot2grid((2, 3), (1, 2))
center_idx = len(time_axis) // 2
center_samples = eye_data[:, center_idx]
ax_hist.hist(center_samples, bins=30, edgecolor='black', alpha=0.7)
ax_hist.set_xlabel('幅度 (V)')
ax_hist.set_ylabel('频次')
ax_hist.set_title('眼图中心采样分布')
ax_hist.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
return eye_data, time_axis
def check_mask_violations(eye_data, time_axis, bit_period):
"""
检查眼图模板违规
:param eye_data: 眼图数据
:param time_axis: 时间轴
:param bit_period: 比特周期
:return: 违规点数量
"""
from matplotlib.path import Path
# 定义简单眼图模板(可根据标准调整)
ui = bit_period * 1e12 # 单位间隔(ps)
# 模板坐标(归一化)
mask_x_normalized = np.array([0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.0, 0.8, 0.6, 0.4, 0.2, 0]) * 2
mask_y_upper_normalized = np.array([0.15, 0.05, 0.02, 0.02, 0.05, 0.15, 0.85, 0.95, 0.98, 0.98, 0.95, 0.85])
mask_y_lower_normalized = np.array([0.15, 0.05, 0.02, 0.02, 0.05, 0.15, 0.15, 0.05, 0.02, 0.02, 0.05, 0.15])
# 缩放模板
eye_amplitude = np.max(eye_data) - np.min(eye_data)
eye_center = np.mean(eye_data)
mask_x = mask_x_normalized * ui
mask_y_upper = eye_center + mask_y_upper_normalized * eye_amplitude/2
mask_y_lower = eye_center + mask_y_lower_normalized * eye_amplitude/2 - eye_amplitude
# 创建模板路径
upper_polygon = np.column_stack([mask_x, mask_y_upper])
lower_polygon = np.column_stack([mask_x, mask_y_lower])
upper_path = Path(upper_polygon)
lower_path = Path(lower_polygon)
# 绘制模板
fig = plt.figure(figsize=(10, 6), dpi=100)
ax = plt.gca()
# 绘制眼图轨迹
max_traces = min(100, len(eye_data))
for i in range(max_traces):
ax.plot(time_axis, eye_data[i], 'b-', linewidth=0.1, alpha=0.1)
# 绘制模板
ax.fill(mask_x, mask_y_upper, 'r', alpha=0.3, edgecolor='r', linewidth=1.5)
ax.fill(mask_x, mask_y_lower, 'r', alpha=0.3, edgecolor='r', linewidth=1.5)
# 检查违规点
violations = 0
violation_points = []
for i in range(len(eye_data)):
for j in range(len(time_axis)):
point_x = time_axis[j]
point_y = eye_data[i, j]
# 检查是否在模板内
point = np.array([[point_x, point_y]])
in_upper = upper_path.contains_points(point)[0]
in_lower = lower_path.contains_points(point)[0]
if in_upper or in_lower:
violations += 1
violation_points.append((point_x, point_y))
# 标记违规点
if violation_points:
violation_points = np.array(violation_points)
ax.plot(violation_points[:, 0], violation_points[:, 1], 'ro',
markersize=6, linewidth=2, label=f'违规点 ({violations}个)')
ax.legend()
ax.set_xlabel('时间 (ps)')
ax.set_ylabel('幅度 (V)')
ax.set_title(f'眼图模板测试 - 违规点: {violations}')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
if violations > 0:
print(f'眼图模板测试失败! 发现 {violations} 个违规点。')
else:
print('眼图模板测试通过!')
return violations
# ==================== 主程序部分 ====================
def main():
print("=" * 60)
print("高速数字信号完整性分析系统 - Python修复版")
print("=" * 60)
# 1. 参数设置
print("\n1. 参数设置...")
fs = 100e9 # 采样频率 100 GHz
Ts = 1/fs # 采样间隔
bit_rate = 10e9 # 比特率 10 Gbps
bit_period = 1/bit_rate # 比特周期
samples_per_bit = fs/bit_rate # 每比特采样点数
# 系统参数
num_bits = 10000 # 总比特数
rise_time = 0.1 * bit_period # 上升时间
channel_length = 0.5 # 通道长度(米)
material_er = 4.0 # 介电常数
print(f" 采样频率: {fs/1e9:.1f} GHz")
print(f" 比特率: {bit_rate/1e9:.1f} Gbps")
print(f" 每比特采样点数: {samples_per_bit:.1f}")
# 2. 生成PRBS测试序列
print("\n2. 生成PRBS测试序列...")
prbs_data = generate_prbs(7, num_bits)
print(f" 生成长度为 {len(prbs_data)} 的PRBS-7序列")
# 3. 信号编码(NRZ格式)
print("\n3. 信号编码(NRZ格式)...")
tx_signal = 2 * prbs_data - 1 # 转换为±1V
# 上采样到模拟波形
print(" 上采样到模拟波形...")
tx_waveform = np.repeat(tx_signal, int(samples_per_bit))
tx_waveform = tx_waveform[:num_bits * int(samples_per_bit)]
print(f" 发射波形长度: {len(tx_waveform)} 个采样点")
# 4. 通道建模(传输线效应)
print("\n4. 通道建模...")
# 创建带限通道模型
channel_bandwidth = 0.7 * bit_rate # 通道带宽
nyquist_freq = fs/2
cutoff_normalized = channel_bandwidth / nyquist_freq
# 设计FIR滤波器模拟通道
filter_order = 100
b = signal.firwin(filter_order, cutoff_normalized, window='hamming')
# 应用滤波器
channel_response = signal.lfilter(b, 1.0, tx_waveform)
# 添加传输线损耗(频率相关)
f = np.linspace(0, fs/2, len(b))
alpha_db = 0.2 * np.sqrt(f/1e9) # 损耗 dB/inch
alpha_linear = 10**(-alpha_db/20)
# 确保维度匹配
alpha_linear = alpha_linear[:len(b)]
b_loss = b * alpha_linear
# 应用损耗滤波器
rx_signal_noiseless = signal.lfilter(b_loss, 1.0, channel_response)
print(f" 通道带宽: {channel_bandwidth/1e9:.1f} GHz")
# 5. 添加噪声和抖动
print("\n5. 添加噪声和抖动...")
# 添加高斯白噪声
SNR_dB = 20 # 信噪比
signal_power = np.mean(rx_signal_noiseless**2)
noise_power = signal_power / (10**(SNR_dB/10))
noise = np.sqrt(noise_power) * np.random.randn(len(rx_signal_noiseless))
# 添加确定性抖动
dj_pp = 0.05 * bit_period # 峰峰值确定性抖动
deterministic_jitter = dj_pp * np.sin(2 * np.pi * bit_rate/10 *
np.arange(len(rx_signal_noiseless)) * Ts)
# 添加随机抖动
rj_rms = 0.02 * bit_period # RMS随机抖动
random_jitter = rj_rms * np.random.randn(len(rx_signal_noiseless))
# 总抖动
total_jitter = deterministic_jitter + random_jitter
# 应用抖动到信号(通过重采样)
t = np.arange(len(rx_signal_noiseless)) * Ts
t_jittered = t + total_jitter
# 插值得到带抖动的信号
interpolator = interp1d(t, rx_signal_noiseless, kind='linear',
bounds_error=False, fill_value='extrapolate')
rx_signal_jittered = interpolator(t_jittered)
# 最终接收信号(带噪声和抖动)
rx_signal = rx_signal_jittered + noise
print(f" 信噪比: {SNR_dB} dB")
print(f" 确定性抖动: {dj_pp*1e12:.1f} ps (峰峰值)")
print(f" 随机抖动: {rj_rms*1e12:.1f} ps (RMS)")
# 6. 生成眼图
print("\n6. 生成眼图...")
eye_data, time_axis = plot_eye_diagram(rx_signal, samples_per_bit, bit_period, fs, 100)
# 7. 频率响应分析
print("\n7. 频率响应分析...")
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
fig.suptitle('频率响应分析', fontsize=14, fontweight='bold')
# 计算传输函数
w, H = signal.freqz(b_loss, worN=1024, fs=fs)
# 通道频率响应
axes[0].semilogx(w/1e9, 20*np.log10(np.abs(H)), 'b-', linewidth=2)
axes[0].set_xlabel('频率 (GHz)')
axes[0].set_ylabel('幅度 (dB)')
axes[0].set_title('通道频率响应')
axes[0].grid(True, alpha=0.3)
# 插入损耗
insertion_loss = -20*np.log10(np.abs(H))
axes[1].plot(w/1e9, insertion_loss, 'r-', linewidth=2)
axes[1].set_xlabel('频率 (GHz)')
axes[1].set_ylabel('插入损耗 (dB)')
axes[1].set_title('插入损耗 vs 频率')
axes[1].grid(True, alpha=0.3)
# 群延迟
w_gd, gd = signal.group_delay((b_loss, 1.0), w=1024, fs=fs)
axes[2].plot(w_gd/1e9, gd*1e12, 'g-', linewidth=2) # 转换为ps
axes[2].set_xlabel('频率 (GHz)')
axes[2].set_ylabel('群延迟 (ps)')
axes[2].set_title('群延迟')
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 8. 误码率分析
print("\n8. 误码率分析...")
# 信号均衡(简单CTLE)
f_cut = bit_rate/2
b_eq, a_eq = signal.butter(3, f_cut/(fs/2), btype='high')
equalized_signal = signal.lfilter(b_eq, a_eq, rx_signal)
# 采样决策
sampling_instants = np.arange(int(samples_per_bit/2), len(equalized_signal),
int(samples_per_bit)).astype(int)
sampled_values = equalized_signal[sampling_instants]
# 确保长度匹配
min_length = min(len(sampled_values), num_bits)
sampled_values = sampled_values[:min_length]
# 决策
decided_bits = (sampled_values > 0).astype(int)
# 计算误码率
rx_bits_aligned = decided_bits[:min_length]
prbs_aligned = prbs_data[:min_length]
# 计算误码率(BER)
error_count = np.sum(rx_bits_aligned != prbs_aligned)
ber = error_count / min_length
# 显示结果
print("\n" + "=" * 60)
print("信号完整性分析报告")
print("=" * 60)
print(f"比特率: {bit_rate/1e9:.1f} Gbps")
print(f"采样率: {fs/1e9:.1f} GHz")
print(f"估算BER: {ber:.2e}")
print(f"信噪比: {SNR_dB:.1f} dB")
print(f"随机抖动(RMS): {rj_rms*1e12:.1f} ps")
print(f"确定性抖动(峰峰值): {dj_pp*1e12:.1f} ps")
print(f"通道带宽: {channel_bandwidth/1e9:.1f} GHz")
print(f"传输比特数: {min_length}")
print(f"误码数: {error_count}")
print("=" * 60)
# 9. 时域波形对比
print("\n9. 时域波形对比...")
fig, axes = plt.subplots(3, 1, figsize=(12, 8))
fig.suptitle('时域波形对比', fontsize=14, fontweight='bold')
# 显示前200个比特
bits_to_show = 200
samples_to_show = min(bits_to_show * int(samples_per_bit), len(tx_waveform))
time_window = np.arange(samples_to_show) * Ts * 1e9 # 转换为ns
# 发射信号
axes[0].plot(time_window, tx_waveform[:samples_to_show], 'b-', linewidth=1)
axes[0].set_title('发射信号')
axes[0].set_xlabel('时间 (ns)')
axes[0].set_ylabel('幅度 (V)')
axes[0].grid(True, alpha=0.3)
axes[0].set_xlim([time_window[0], time_window[-1]])
# 接收信号(无噪声)
axes[1].plot(time_window, rx_signal_noiseless[:samples_to_show], 'r-', linewidth=1)
axes[1].set_title('接收信号(无噪声)')
axes[1].set_xlabel('时间 (ns)')
axes[1].set_ylabel('幅度 (V)')
axes[1].grid(True, alpha=0.3)
axes[1].set_xlim([time_window[0], time_window[-1]])
# 均衡后信号与采样点
axes[2].plot(time_window, equalized_signal[:samples_to_show], 'g-', linewidth=1, label='均衡信号')
# 绘制采样点(前几个比特)
num_sampled_bits = min(bits_to_show, len(sampling_instants))
sampling_times = sampling_instants[:num_sampled_bits] * Ts * 1e9
sampling_values = sampled_values[:num_sampled_bits]
# 修复stem函数调用(移除了use_line_collection参数)
axes[2].stem(sampling_times, sampling_values, linefmt='r-', markerfmt='ro', basefmt=' ', label='采样点')
axes[2].set_title('均衡后信号与采样点')
axes[2].set_xlabel('时间 (ns)')
axes[2].set_ylabel('幅度 (V)')
axes[2].grid(True, alpha=0.3)
axes[2].set_xlim([time_window[0], time_window[-1]])
axes[2].legend(loc='best')
plt.tight_layout()
plt.show()
# 10. 眼图模板测试(可选)
print("\n10. 眼图模板测试(可选)...")
run_mask_test = input("是否运行眼图模板测试?(y/n): ").lower().strip()
if run_mask_test == 'y':
violations = check_mask_violations(eye_data, time_axis, bit_period)
print("\n" + "=" * 60)
print("信号完整性分析完成!")
print("=" * 60)
# 保存结果到文件
print("\n保存分析结果到文件...")
try:
with open('signal_integrity_report.txt', 'w', encoding='utf-8') as f:
f.write("=" * 60 + "\n")
f.write("信号完整性分析报告\n")
f.write("=" * 60 + "\n")
f.write(f"比特率: {bit_rate/1e9:.1f} Gbps\n")
f.write(f"采样率: {fs/1e9:.1f} GHz\n")
f.write(f"估算BER: {ber:.2e}\n")
f.write(f"信噪比: {SNR_dB:.1f} dB\n")
f.write(f"随机抖动(RMS): {rj_rms*1e12:.1f} ps\n")
f.write(f"确定性抖动(峰峰值): {dj_pp*1e12:.1f} ps\n")
f.write(f"通道带宽: {channel_bandwidth/1e9:.1f} GHz\n")
f.write(f"传输比特数: {min_length}\n")
f.write(f"误码数: {error_count}\n")
f.write("=" * 60 + "\n")
print("报告已保存到 signal_integrity_report.txt")
except Exception as e:
print(f"保存报告时出错: {e}")
return ber, error_count, min_length
if __name__ == "__main__":
# 显示项目信息
print("\n欢迎使用高速数字信号完整性分析系统")
print("版本: Python 3.10")
print("开发环境: PyCharm")
print("\n系统将执行以下步骤:")
print("1. 参数设置")
print("2. 生成PRBS测试序列")
print("3. 信号编码")
print("4. 通道建模")
print("5. 添加噪声和抖动")
print("6. 生成眼图")
print("7. 频率响应分析")
print("8. 误码率分析")
print("9. 时域波形对比")
print("10. 眼图模板测试(可选)")
# 运行主程序
input("\n按Enter键开始分析...")
ber, error_count, min_length = main()
# 添加调试信息
print("\n" + "=" * 60)
print("调试信息:")
print("=" * 60)
print(f"原始误码率: {ber}")
print(f"误码数/总比特数: {error_count}/{min_length}")
# 如果误码率过高,提供调整建议
if ber > 0.1:
print("\n" + "=" * 60)
print("警告: 误码率过高!")
print("建议调整以下参数:")
print("1. 增加信噪比 (SNR_dB)")
print("2. 减少抖动参数 (dj_pp, rj_rms)")
print("3. 增加通道带宽")
print("4. 使用更复杂的均衡器")
print("=" * 60)
# 提供快速修正代码
print("\n快速修正建议:")
print("在参数设置部分尝试以下值:")
print("SNR_dB = 30 # 增加信噪比")
print("dj_pp = 0.02 * bit_period # 减少确定性抖动")
print("rj_rms = 0.01 * bit_period # 减少随机抖动")
print("channel_bandwidth = 0.8 * bit_rate # 增加带宽")
最终得到的信号完整性的分析报告文件显示的内容:




