强大的ADC行为级事件驱动仿真器,像Minecraft Bukkit API一样简单易用
像Minecraft插件一样,监听ADC转换的每个阶段,轻松实现非理想效应建模
3行代码完成仿真,用户代码量极少,支持超快速调用
内置ENOB、SNR、SFDR、THD、INL、DNL计算和IEEE JSSC风格绘图
支持SAR ADC、Pipeline ADC,易于添加新架构和自定义信号
别担心!跟着下面的步骤,10分钟内你就能运行第一个ADC仿真。
python --version看到版本号就说明安装成功了
# 在命令行中执行以下命令 # 方法1:进入项目目录安装(推荐) cd QuantiaMagica pip install -e . # 方法2:只安装依赖 pip install numpy matplotlib
用任意文本编辑器(记事本、VS Code、PyCharm都可以)创建文件 my_first_adc.py:
# my_first_adc.py - 我的第一个ADC仿真 from quantiamagica import SARADC # 创建一个10位SAR ADC adc = SARADC(bits=10, vref=1.0) # 运行仿真 adc.sim() # 显示结果 print(f"ENOB: {adc.enob():.2f} bits") # 画图 adc.plot()
# 在命令行中
python my_first_adc.py
你已经完成了第一个ADC仿真!继续阅读下面的内容学习更多用法。
以下是使用QuantiaMagica所需的所有Python语法,10分钟即可掌握:
# 变量赋值:直接写名字 = 值 bits = 12 # 整数 int vref = 1.0 # 小数 float name = "SAR-ADC" # 字符串 str enabled = True # 布尔值 True/False # 科学计数法(ADC仿真常用) fs = 1e6 # 1×10⁶ = 1000000 (1MHz) noise = 0.5e-3 # 0.5×10⁻³ = 0.0005 (0.5mV) fin = 10e3 # 10×10³ = 10000 (10kHz) # 运算符 a = 10 + 3 # 加法 = 13 b = 10 - 3 # 减法 = 7 c = 10 * 3 # 乘法 = 30 d = 10 / 3 # 除法 = 3.333... e = 10 // 3 # 整除 = 3 f = 10 % 3 # 取余 = 1 g = 2 ** 10 # 幂运算 = 1024
# 列表 list:用方括号,可索引 coeffs = [0.5, 0.3, 0.2] # 创建列表 first = coeffs[0] # 索引从0开始,= 0.5 coeffs.append(0.1) # 追加元素 length = len(coeffs) # 长度 = 4 # 字典 dict:键值对,用花括号 params = {'c1': 0.5, 'c2': 0.3, 'amplitude': 0.4} c1 = params['c1'] # 取值 = 0.5 params['c3'] = 0.2 # 添加新键值
# 从模块导入类/函数 from quantiamagica import SARADC # 导入一个 from quantiamagica import SARADC, Signal # 导入多个 from quantiamagica import * # 导入所有(不推荐) # 导入整个模块(需要前缀访问) import numpy as np # np是别名 noise = np.random.normal(0, 0.001) # 使用np.xxx访问 # 常用导入(本API需要) import numpy as np from quantiamagica import SARADC, PipelineADC, SigmaDeltaADC from quantiamagica import SamplingEvent, ComparatorEvent, QuantizerEvent from quantiamagica.optim import GeneticOptimizer, Gene
# 创建对象:类名(参数) adc = SARADC(bits=12, vref=1.0) # 命名参数 adc = SARADC(12, 1.0) # 位置参数 adc = SARADC(12) # 只传必要参数 # 调用方法:对象.方法名() adc.sim() # 无参数 adc.sim(fin=10e3) # 有参数 adc.sim(n_samples=4096, fs=1e6) # 多个参数 # 获取返回值 result = adc.sim() # 保存返回对象 enob = adc.enob() # 保存返回数字 # 链式调用 adc.sim().report() # 仿真完直接报告 # 访问属性 bits = adc.bits # 读取属性(无括号)
# 基本函数 def add(a, b): return a + b result = add(3, 5) # 调用函数,result = 8 # 带默认参数 def greet(name="World"): print(f"Hello, {name}!") greet() # Hello, World! greet("ADC") # Hello, ADC! # 适应度函数示例(遗传算法用) def fitness(params): # params是字典,如 {'c1': 0.5, 'c2': 0.3} c1 = params['c1'] c2 = params['c2'] # ... 计算ENOB ... return enob # 返回适应度值
# 装饰器:@xxx 放在函数定义上面 # 这是QuantiaMagica事件系统的核心! from quantiamagica import SARADC, SamplingEvent adc = SARADC(12) @adc.on(SamplingEvent) # ← 装饰器:监听采样事件 def add_noise(event): # ← 事件处理函数,参数是event event.voltage += 0.001 # ← 修改event的属性 # 装饰器的作用:当ADC采样时,自动调用add_noise函数 # 你不需要手动调用add_noise(),只需要运行adc.sim() adc.sim() # add_noise会在每次采样时被自动调用
# if-elif-else if enob > 10: print("优秀") elif enob > 8: print("良好") else: print("需改进") # for循环 for i in range(5): # i = 0, 1, 2, 3, 4 print(i) for c in [0.1, 0.2, 0.3]: # 遍历列表 print(c) # 列表推导式(创建列表的简洁写法) squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16] c_list = [params[f'c{i+1}'] for i in range(5)] # 提取c1-c5
# print() 打印到控制台 print("Hello") # 普通字符串 print(bits) # 打印变量 print("bits =", bits) # 多个值用逗号 # f-string格式化(推荐) print(f"ENOB: {enob}") # {}内放变量 print(f"ENOB: {enob:.2f} bits") # :.2f 保留2位小数 print(f"SNR: {snr:.1f} dB") # :.1f 保留1位小数 print(f"fs: {fs:.2e} Hz") # :.2e 科学计数法 print(f"提升: {improvement:+.2f}") # :+ 显示正负号
import numpy as np # 创建数组 arr = np.array([1, 2, 3]) # 从列表创建 zeros = np.zeros(10) # 10个0 ones = np.ones(10) # 10个1 t = np.arange(1024) # [0, 1, 2, ..., 1023] t = np.arange(0, 1, 0.001) # 0到1,步长0.001 t = np.linspace(0, 1, 1000) # 0到1,共1000个点 # 时间轴生成(ADC仿真常用) n_samples = 4096 fs = 1e6 t = np.arange(n_samples) / fs # 时间轴(秒) # 生成正弦波 fin = 10e3 # 信号频率10kHz amplitude = 0.4 # 振幅 offset = 0.5 # 直流偏置 signal = offset + amplitude * np.sin(2 * np.pi * fin * t) # 生成随机噪声 noise = np.random.normal(0, 0.001) # 单个随机数 noise = np.random.normal(0, 0.001, 1024) # 1024个随机数 # 数学函数 y = np.sin(x) # 正弦 y = np.cos(x) # 余弦 y = np.abs(x) # 绝对值 y = np.sqrt(x) # 平方根 y = np.log10(x) # log10 y = np.clip(x, 0, 1) # 裁剪到[0,1] # 统计函数 m = np.mean(arr) # 平均值 s = np.std(arr) # 标准差 mx = np.max(arr) # 最大值 mn = np.min(arr) # 最小值
# 捕获错误,防止程序崩溃 try: enob = evaluate_sd_adc(params) if enob <= 0 or np.isnan(enob): return -1000 # 返回惩罚值 return enob except: return -1000 # 出错也返回惩罚值
| 错误 | 原因 | 解决 |
|---|---|---|
ModuleNotFoundError | 模块未安装 | pip install -e . |
IndentationError | 缩进不对 | 用4个空格缩进 |
NameError: xxx not defined | 变量未定义 | 检查拼写或先赋值 |
TypeError: missing argument | 缺少参数 | 查看API文档补全参数 |
IndexError: list index out of range | 索引越界 | 检查列表长度 |
KeyError: 'xxx' | 字典键不存在 | 检查键名拼写 |
下面是一个完整的ADC仿真模板,包含所有常用功能。复制后修改参数即可运行。
""" QuantiaMagica ADC仿真模板 ======================== 复制此文件,修改参数即可运行 使用前请先安装: cd QuantiaMagica pip install -e . """ # ==================== 导入 ==================== import numpy as np from quantiamagica import SARADC, SamplingEvent, ComparatorEvent # ==================== 参数设置 ==================== BITS = 12 # ADC位数 VREF = 1.0 # 参考电压 (V) FS = 1e6 # 采样率 (Hz) FIN = 10e3 # 信号频率 (Hz) N_SAMPLES = 4096 # 采样点数 AMPLITUDE = 0.48 # 信号幅度 (V) OFFSET = 0.5 # 直流偏置 (V) # 非理想效应参数 THERMAL_NOISE = 0.5e-3 # 热噪声 (V RMS) COMPARATOR_OFFSET = 1e-3 # 比较器失调 (V) # ==================== 创建ADC ==================== adc = SARADC(bits=BITS, vref=VREF) # ==================== 添加非理想效应(可选) ==================== @adc.on(SamplingEvent) def add_thermal_noise(event): """采样时添加热噪声""" event.voltage += np.random.normal(0, THERMAL_NOISE) @adc.on(ComparatorEvent) def add_comparator_offset(event): """比较器失调""" event.offset = COMPARATOR_OFFSET # ==================== 运行仿真 ==================== print("运行仿真...") result = adc.sim( n_samples=N_SAMPLES, fs=FS, fin=FIN, amplitude=AMPLITUDE, offset=OFFSET ) # ==================== 查看结果 ==================== print(f"\n===== 仿真结果 =====") print(f"ENOB: {adc.enob():.2f} bits") print(f"SNR: {adc.snr():.1f} dB") print(f"SFDR: {adc.sfdr():.1f} dB") print(f"THD: {adc.thd():.1f} dB") # ==================== 可视化 ==================== # 完整报告(推荐) adc.report() # 或者单独查看 # adc.plot() # 时域图 # adc.spectrum() # 频谱图 # adc.report('static') # INL/DNL # ==================== 保存数据(可选) ==================== # result.save("output.npz") # NumPy格式 # result.save("output.csv", format="csv") # CSV格式
from quantiamagica import SARADC adc = SARADC(bits=12, vref=1.0) # 创建12位ADC adc.sim(fin=10e3) # 仿真10kHz正弦波 adc.plot() # 画图
# ============================================================= # 事件驱动是QuantiaMagica的核心! # 通过监听ADC转换过程中的各个事件,可以轻松添加非理想效应 # ============================================================= from quantiamagica import SARADC, SamplingEvent, ComparatorEvent import numpy as np # 第1步:创建ADC实例 adc = SARADC(bits=12, vref=1.0) # 第2步:用 @adc.on() 装饰器监听事件 # 当ADC采样时,这个函数会被自动调用 @adc.on(SamplingEvent) def add_thermal_noise(event): # event.voltage 是当前采样的电压值 # 我们给它加上高斯噪声来模拟热噪声 noise = np.random.normal(0, 0.0005) # 0.5mV RMS噪声 event.voltage += noise # 第3步:监听比较器事件,添加比较器失调 @adc.on(ComparatorEvent) def add_comparator_offset(event): # event.offset 是比较器失调电压 event.offset = 0.001 # 1mV失调 # event.noise_sigma 是比较器噪声 event.noise_sigma = 0.0002 # 0.2mV噪声 # 第4步:运行仿真 adc.sim(n_samples=4096, fs=1e6, fin=10e3) # 第5步:查看结果 print(f"带非理想效应的ENOB: {adc.enob():.2f} bits") print(f"SNR: {adc.snr():.1f} dB") # 画图看效果 adc.spectrum()
from quantiamagica import SARADC from quantiamagica.analysis import Analyzer adc = SARADC(bits=12) result = adc.sim() analyzer = Analyzer(result) print(analyzer.summary()) # 打印所有指标
from quantiamagica import SARADC, Signal adc = SARADC(bits=12) # 正弦波 sig = Signal.sine(n=1024, freq=10e3) # 方波 sig = Signal.square(n=1024, freq=1e3) # 三角波 sig = Signal.triangle(n=1024, freq=1e3) # 扫频信号 sig = Signal.chirp(n=2048, f_start=1e3, f_end=100e3) # 双音信号(IMD测试) sig = Signal.two_tone(f1=10e3, f2=11e3) # 从文件导入 sig = Signal.from_file("my_data.csv") # 用于仿真 adc.sim(sig)
导入: from quantiamagica import SARADC
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| bits | int | 10 | 分辨率位数 |
| vref | float | 1.0 | 参考电压上限 (V) |
| vmin | float | 0.0 | 参考电压下限 (V) |
| cap_unit | float | 1.0 | 单位电容 (fF) |
| name | str | "SAR-ADC" | ADC名称 |
专用方法:
| 方法 | 说明 |
|---|---|
set_radix(radix) | 设置非二进制基数 (如1.85用于冗余SAR) |
set_capacitor_mismatch(sigma) | 设置电容失配标准差 |
code_to_voltage(code) | 将输出码转换回电压 |
导入: from quantiamagica import Pipeline
架构说明:Pipeline是独立的类(不继承ADConverter),用于将多个ADC(SAR/Sigma-Delta)串联成高精度流水线结构。
输入V → [Stage1 ADC] → 残差×gain → [Stage2 ADC] → 残差×gain → [Stage3 ADC] → 合并输出码
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| stages | List[ADConverter] | 必填 | ADC实例列表 (SARADC/SigmaDeltaADC) |
| gains | List[float] | 自动(2^bits) | 级间增益列表,长度=len(stages)-1 |
| vref | float | 首级ADC的vref | 参考电压 |
| name | str | "Pipeline" | Pipeline名称 |
属性:
| 属性 | 类型 | 说明 |
|---|---|---|
bits | int | 总位数 = sum(各级bits) |
num_stages | int | 级数 |
lsb | float | 最小分辨电压 |
方法:
| 方法 | 说明 |
|---|---|
sim(n_samples, fs, fin, ...) | 运行仿真 |
enob() | 计算有效位数 |
snr(), sfdr(), thd() | 性能指标 |
spectrum(show=True) | 频谱分析与绘图 |
plot() | 完整仿真结果绘图 |
inl(plot=True), dnl(plot=True) | INL/DNL分析 |
report() | 打印性能报告 |
get_stage_info() | 获取各级配置信息 |
使用示例:
# 3×8-bit SAR → 24-bit Pipeline stages = [SARADC(bits=8) for _ in range(3)] pipeline = Pipeline(stages, gains=[256, 256]) # 也支持Sigma-Delta ADC sd_stages = [SigmaDeltaADC(order=1, bits=1, osr=16) for _ in range(2)] sd_pipeline = Pipeline(sd_stages, gains=[16])
以下方法适用于 SARADC(Pipeline类有独立实现)
| 方法 | 参数 | 说明 |
|---|---|---|
sim() |
input_voltage, n_samples, fs, signal, fin, amplitude, offset | 运行ADC仿真,返回SimulationResult |
sim_auto() |
fs, n_samples, verbose | 自动优化:DE算法+CUDA/CPU极限并发,自动检测GPU加速 |
convert(voltage) |
voltage: float或array | 转换单个或多个电压值 |
| 方法 | 返回值 | 说明 |
|---|---|---|
enob() | float | 有效位数 (bits) |
snr() | float | 信噪比 (dB) |
sfdr() | float | 无杂散动态范围 (dB) |
thd() | float | 总谐波失真 (dB) |
sinad() | float | 信号与噪声加失真比 (dB) |
inl() | ndarray | 积分非线性 (LSB) |
dnl() | ndarray | 微分非线性 (LSB) |
| 方法 | 参数 | 说明 |
|---|---|---|
plot() | save, show, dpi | 绘制时域/数字输出/误差/直方图 |
spectrum() | show, window, save | 绘制频谱图,返回(freqs, power_db, metrics) |
report(what) | what, save, show, columns | 推荐! 统一报告API (见下表) |
简洁灵活的分析报告API:
# 方式1: 链式调用 (仿真+报告一行完成) adc.sim().report() # 完整报告 # 方式2: 分开调用 (仿真一次,多种报告) adc.sim() # 先仿真 adc.report() # 完整报告 adc.report('spectrum') # 只看频谱图 adc.report('metrics') # 只打印数字 adc.report(save='fig.pdf') # 保存PDF
| 类型 | 说明 | 包含内容 | 使用场景 |
|---|---|---|---|
'all' |
完整报告 (默认) | 时域图 + 频谱图 + 数字输出图 | 日常分析、论文插图 |
'spectrum' |
频谱图 | FFT频谱 + ENOB/SNR/SFDR标注 | 查看噪声分布、谐波失真 |
'time' |
时域图 | 输入信号 vs 重建信号对比 | 检查采样是否正确 |
'static' |
静态特性 | INL曲线 + DNL曲线 | 分析非线性失真 |
'metrics' |
仅指标 (不画图) | 控制台打印 ENOB/SNR/SFDR/THD | 快速查看性能数字 |
| 参数 | 类型 | 说明 | 示例 |
|---|---|---|---|
| save | str | 保存图像到文件 | save='my_adc.pdf' |
| show | bool | 是否弹出图像窗口 (默认True) | show=False |
| columns | int | 图像宽度: 1=单栏(3.5英寸), 2=双栏(7.16英寸) | columns=2 |
不知道用什么?直接用 adc.sim().report() 就够了!它会显示所有你需要的信息。
| 函数 | 说明 | 使用场景 |
|---|---|---|
plot_spectrum(codes, fs) | 一键绘制频谱图 | 快速查看任意信号的频谱 |
plot_comparison(data_list, fs, labels) | 对比绘图 | 比较多个ADC性能 |
compute_inband_snr(codes, bits, fs, fin, bw) | 计算带内SNR | 过采样/Sigma-Delta系统 |
auto_time_unit(time_array) | 自动选择时间单位 | 绘图时自适应ns/μs/ms/s |
auto_freq_unit(freq_array) | 自动选择频率单位 | 绘图时自适应Hz/kHz/MHz |
apply_jssc_style() | 应用JSSC绘图风格 | 论文级图像 |
# ========== 示例1: 一键绘制频谱 ========== from quantiamagica import SARADC, plot_spectrum adc = SARADC(bits=12) result = adc.sim(n_samples=4096) # 一行代码画频谱!自动计算SNR/ENOB并标注 plot_spectrum(result.output_codes, fs=1e6, title="我的ADC频谱") # ========== 示例2: 对比两个ADC ========== from quantiamagica import SARADC, plot_comparison # 创建两个ADC adc1 = SARADC(bits=8) adc2 = SARADC(bits=12) # 分别仿真 r1 = adc1.sim(n_samples=4096) r2 = adc2.sim(n_samples=4096) # 一行代码对比两个频谱! plot_comparison( [r1.output_codes, r2.output_codes], # 数据列表 fs=1e6, # 采样率 labels=['8-bit', '12-bit'], # 标签 save='comparison.png' # 保存图片 ) # ========== 示例3: 计算带内SNR (Sigma-Delta/过采样) ========== from quantiamagica import compute_inband_snr # 假设你有过采样的ADC输出码 codes = ... # 你的数据 snr, enob = compute_inband_snr( codes, bits=4, # 量化器位数 fs=1e6, # 采样率 1MHz signal_freq=1e3, # 信号频率 1kHz bandwidth=10e3 # 只计算10kHz带宽内的噪声 ) print(f"带内SNR: {snr:.1f}dB, ENOB: {enob:.2f}bits")
| 方法 | 说明 |
|---|---|
on(EventType, priority) | 装饰器,注册事件处理函数 |
fire(event) | 触发事件 |
register(EventType, callback) | 编程式注册事件处理 |
unregister(EventType, callback) | 移除事件处理函数 |
导入: from quantiamagica import SamplingEvent, ComparatorEvent, ...
转换开始时触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| timestamp | float | 否 | 仿真时间 |
| sample_index | int | 否 | 当前采样索引 |
| input_voltage | float | 是 | 输入电压 |
采样阶段触发,用于添加采样噪声、失调等
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| voltage | float | 是 | 采样电压 (修改此值添加噪声) |
| sampling_capacitance | float | 是 | 采样电容 (fF) |
| sample_index | int | 否 | 当前采样索引 |
电容切换时触发,用于模拟电容失配
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| bit_index | int | 否 | 当前位索引 (MSB=0) |
| capacitance | float | 否 | 理想电容值 |
| capacitance_actual | float | 是 | 实际电容值 |
| weight | float | 是 | 位权重 |
| charge_injection | float | 是 | 电荷注入 (V) |
| settling_error | float | 是 | 建立误差 |
比较器判决时触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| input_voltage | float | 否 | 比较器输入 |
| threshold | float | 是 | 判决阈值 |
| offset | float | 是 | 比较器失调 (V) |
| noise_sigma | float | 是 | 比较器噪声标准差 (V) |
| decision | int | 是 | 判决结果 (0或1) |
| metastable | bool | 是 | 是否在亚稳态区 |
每位决定后触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| bit_index | int | 否 | 位索引 |
| bit_value | int | 是 | 位值 (可翻转) |
| dac_voltage | float | 否 | 当前DAC电压 |
输出码就绪时触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| code | int | 是 | 输出码 |
| input_voltage | float | 否 | 原始输入电压 |
转换结束时触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| code | int | 否 | 最终输出码 |
| conversion_time | float | 否 | 转换耗时 |
导入: from quantiamagica import Pipeline, SARADC, StageEvent, ResidueEvent, InterstageGainEvent
进入新的流水线级时触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| stage_index | int | 否 | 级索引 (0-indexed) |
| stage_adc | ADConverter | 否 | 该级使用的子ADC实例 |
| input_voltage | float | 否 | 级输入电压 |
| sample_index | int | 否 | 全局采样索引 |
计算残差电压时触发
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| stage_index | int | 否 | 级索引 |
| input_voltage | float | 否 | 级输入电压 |
| dac_voltage | float | 否 | DAC输出电压 |
| residue | float | 是 | 残差电压 (可注入误差) |
| ideal_residue | float | 否 | 理想残差 |
级间放大时触发,用于模拟运放非理想特性
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| stage_index | int | 否 | 级索引 |
| input_voltage | float | 否 | 放大器输入 (残差电压) |
| ideal_gain | float | 否 | 理想增益 (通常为2^stage_bits) |
| actual_gain | float | 是 | 实际增益 (模拟有限增益) |
| offset | float | 是 | 放大器失调 (V) |
| noise_sigma | float | 是 | 放大器噪声标准差 (V) |
| output_voltage | float | 否 | 放大输出电压 (事件后计算) |
| bandwidth | float | 是 | 放大器带宽 (Hz) |
| settling_error | float | 是 | 不完全建立误差 |
导入: from quantiamagica import SigmaDeltaADC, QuantizerEvent
简洁灵活的Sigma-Delta调制器,内置1阶/2阶CIFB实现,通过QuantizerEvent实现任意拓扑
| 参数 | 默认值 | 说明 |
|---|---|---|
| order | 1 | 调制器阶数 (1或2) |
| bits | 1 | 量化器位数 |
| osr | 64 | 过采样率 |
| vref | 1.0 | 参考电压 |
每个时钟周期触发,提供完整信息实现任意拓扑
| 属性 | 类型 | 可修改 | 说明 |
|---|---|---|---|
| input_signal | float | 否 | 当前输入 x[n] ([-1,1]) |
| prev_output | float | 否 | 前一输出 y[n-1] |
| integrator_states | List | 否 | 各级积分器状态(只读) |
| quantizer_input | float | 是 | 量化器输入(修改此值实现自定义拓扑) |
| output | float | 是 | 量化输出 ([-1,1]) |
| output_code | int | 是 | 数字码 |
| offset | float | 是 | 比较器偏移 |
| noise_sigma | float | 是 | 比较器噪声 |
from quantiamagica import SigmaDeltaADC, QuantizerEvent import numpy as np # 1阶1-bit SD,OSR=64 sd = SigmaDeltaADC(order=1, bits=1, osr=64) # 通过QuantizerEvent添加非理想效应 @sd.on(QuantizerEvent) def add_nonidealities(event): # 积分器泄漏:修改量化器输入 event.quantizer_input *= 0.999 # 比较器噪声 event.noise_sigma = 0.01 # 生成输入信号(amplitude由用户控制,推荐0.3-0.45) t = np.arange(8192) / 1e6 signal = 0.5 + 0.4 * np.sin(2 * np.pi * 1e3 * t) # 仿真 sd.sim(signal, fs=1e6) print(f"ENOB: {sd.enob():.2f}") # 自定义拓扑示例:完全自定义2阶调制器 my_u1, my_u2 = 0.0, 0.0 @sd.on(QuantizerEvent) def custom_2nd_order(event): global my_u1, my_u2 x, y_prev = event.input_signal, event.prev_output my_u1 = my_u1 + x - y_prev my_u2 = my_u2 + my_u1 - 2*y_prev event.quantizer_input = my_u2 # 覆盖默认
导入: from quantiamagica import EventPriority
| 优先级 | 值 | 说明 |
|---|---|---|
| LOWEST | 0 | 最先执行,可被后续处理器覆盖 |
| LOW | 1 | 低优先级 |
| NORMAL | 2 | 默认优先级 |
| HIGH | 3 | 高优先级 |
| HIGHEST | 4 | 最高优先级,最后修改机会 |
| MONITOR | 5 | 只读监控,不应修改事件 |
导入: from quantiamagica import Signal 或 from quantiamagica.signals import Signal
| 方法 | 参数 | 说明 |
|---|---|---|
Signal.sine() | n, fs, freq, amplitude, offset, phase, coherent | 正弦波 |
Signal.cosine() | 同上 | 余弦波 |
Signal.square() | n, fs, freq, amplitude, offset, duty | 方波 |
Signal.triangle() | n, fs, freq, amplitude, offset | 三角波 |
Signal.sawtooth() | n, fs, freq, amplitude, offset | 锯齿波 |
| 方法 | 说明 |
|---|---|
Signal.ramp() | 斜坡信号 (INL/DNL测试) |
Signal.step() | 阶跃信号 |
Signal.pulse() | 脉冲信号 |
| 方法 | 说明 |
|---|---|
Signal.multitone() | 多音信号 |
Signal.two_tone() | 双音信号 (IMD测试) |
| 方法 | 说明 |
|---|---|
Signal.chirp() | 扫频信号 |
Signal.am() | 调幅信号 |
Signal.fm() | 调频信号 |
| 方法 | 说明 |
|---|---|
Signal.noise_gaussian() | 高斯白噪声 |
Signal.noise_uniform() | 均匀分布噪声 |
| 方法 | 说明 |
|---|---|
Signal.from_file(path, fs) | 从CSV/NPZ文件导入 |
Signal.from_array(data, fs) | 从NumPy数组创建 |
signal.save(path) | 保存到文件 |
| 方法 | 说明 |
|---|---|
signal.add_noise(sigma) | 添加高斯噪声 |
signal.add_offset(offset) | 添加直流偏置 |
signal.scale(factor) | 缩放振幅 |
signal.clip(vmin, vmax) | 裁剪到范围 |
signal.normalize() | 归一化到[0,1] |
| 属性 | 说明 |
|---|---|
signal.data | 电压数据数组 |
signal.fs | 采样率 |
signal.n_samples | 采样点数 |
signal.vpp | 峰峰值电压 |
signal.vrms | RMS电压 |
signal.mean | 平均值 |
高度抽象的遗传算法优化库,支持CUDA/CPU并行计算,可用于优化任意ADC参数。自动斜率收敛,无需手动设置迭代次数。
导入: from quantiamagica.optim import Gene
| 参数 | 类型 | 说明 |
|---|---|---|
| name | str | 参数名称 |
| low | float | 下界 |
| high | float | 上界 |
| dtype | str | 'float', 'int', 'choice', 'bool' |
| choices | list | 离散选择列表 (仅dtype='choice'时) |
| log_scale | bool | 是否使用对数尺度 |
导入: from quantiamagica.optim import GeneticOptimizer
| 参数 | 类型 | 说明 |
|---|---|---|
| genes | List[Gene] | 基因定义列表 |
| fitness_fn | Callable | 适应度函数 (接受dict返回float) |
| maximize | bool | 是否最大化 (默认True) |
run() 方法参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
| population_size | 50 | 种群大小 |
| max_generations | 200 | 最大迭代代数(自动收敛通常不会到达) |
| slope_window | 5 | 斜率计算窗口 |
| slope_threshold | 0.001 | 收敛斜率阈值 |
| verbose | True | 显示进度 |
| seed | None | 随机种子 |
| 属性 | 类型 | 说明 |
|---|---|---|
| best_params | Dict | 最佳参数 |
| best_fitness | float | 最佳适应度 |
| history | List[float] | 每代最佳适应度历史 |
| generations | int | 实际迭代代数 |
| converged | bool | 是否收敛 |
导入: from quantiamagica.optim import SDCoeffOptimizer
| 参数 | 默认值 | 说明 |
|---|---|---|
| order | 2 | 调制器阶数 |
| bits | 1 | 量化器位数 |
| osr | 64 | 过采样率 |
| fs | 1e6 | 采样频率 |
注意: SAR/Pipeline ADC使用通用GeneticOptimizer进行高度自定义优化。
噪声整形将量化噪声推向高频,配合过采样(OSR)可在信号带宽内获得更高分辨率。
噪声传递函数: NTF = (1 - z⁻¹),一阶整形可提升约 0.5×log₂(OSR) + 1.5 bits ENOB。
from quantiamagica import SARADC, SamplingEvent, OutputCodeEvent, EventPriority import numpy as np # 参数设置 BITS = 8 FS = 1e6 # 采样率 1MHz OSR = 64 # 过采样率 SIGNAL_BW = FS / (2 * OSR) # 信号带宽 ≈ 7.8kHz # 创建NS-SAR插件类 class NoiseShapingSAR: def __init__(self, feedback_coeff=1.0): self.feedback_coeff = feedback_coeff self.prev_residue = 0.0 self.sampled_voltage = 0.0 def attach(self, adc): @adc.on(SamplingEvent, priority=EventPriority.HIGH) def apply_feedback(event): # 加入上次的量化残差 event.voltage += self.feedback_coeff * self.prev_residue self.sampled_voltage = event.voltage @adc.on(OutputCodeEvent, priority=EventPriority.HIGH) def capture_residue(event): # 残差 = 采样电压 - DAC输出 reconstructed = adc.code_to_voltage(event.code) self.prev_residue = self.sampled_voltage - reconstructed # 使用 adc = SARADC(bits=BITS, vref=1.0) ns_plugin = NoiseShapingSAR(feedback_coeff=1.0) ns_plugin.attach(adc) adc.sim(n_samples=16384, fs=FS, fin=1e3) print(f"NS-SAR 带内ENOB大幅提升!") # 运行 examples/03_ns_sar.py 查看完整对比
from quantiamagica import Pipeline, SARADC, InterstageGainEvent # 创建3个8-bit SAR ADC串联成24-bit Pipeline stages = [SARADC(bits=8) for _ in range(3)] pipeline = Pipeline(stages=stages, interstage_gains=[256, 256]) @pipeline.on(InterstageGainEvent) def gain_error(event): # 模拟1000倍运放有限增益带来的误差 opamp_gain = 1000 event.actual_gain = event.ideal_gain * (1 - 1/opamp_gain) event.offset = 0.5e-3 # 0.5mV失调 pipeline.sim(n_samples=65536) pipeline.spectrum() print(f"ENOB: {pipeline.enob():.2f}") # 理想~23.99, 带误差~17.9
from quantiamagica import SARADC adc = SARADC(bits=12) # 仿真一次 adc.sim() # 然后可以多次调用report()查看不同报告 (不会重复仿真) adc.report() # 完整报告 adc.report('spectrum') # 仅频谱 adc.report('metrics') # 仅打印指标 adc.report(save='fig.pdf') # 保存PDF # 可选参数: # what: 'all'|'spectrum'|'time'|'static'|'metrics' # columns: 1(单栏3.5") 或 2(双栏7.16")
差分进化算法(DE) + 极限并发 + 自适应参数:
要启用CUDA GPU加速,需安装PyTorch CUDA版本:
pip install torch --index-url https://download.pytorch.org/whl/cu121
若安装到自定义路径,需设置环境变量:
$env:PYTHONPATH = "D:\Python\Lib\site-packages" # PowerShell set PYTHONPATH=D:\Python\Lib\site-packages # CMD
支持NVIDIA显卡(RTX 20/30/40系列)。
from quantiamagica import SARADC adc = SARADC(bits=12) # 一行代码 - 自动优化! result = adc.sim_auto(fs=1e6) # 只需指定fs # 返回值包含最优参数 print(f"最佳fin: {result['best_fin']:.2f} Hz") print(f"最佳幅度: {result['best_amplitude']:.4f} V") print(f"最佳ENOB: {result['best_enob']:.4f} bits") print(f"收敛代数: {result['generations']}") print(f"收敛原因: {result['reason']}") # 结果已保存,可直接画图 adc.report() # 适用于所有ADC类型 from quantiamagica import PipelineADC, SigmaDeltaADC PipelineADC(12).sim_auto(fs=1e6) SigmaDeltaADC(order=2, bits=1, osr=64).sim_auto(fs=1e6)
# ============================================================= # Sigma-Delta ADC: 通过QuantizerEvent实现任意复杂拓扑 # 演示:自定义2阶CIFB差分方程 # ============================================================= from quantiamagica import SigmaDeltaADC, QuantizerEvent import numpy as np # 参数 OSR, FS, N = 64, 1e6, 64 * 2048 FIN = 13 * FS / N t = np.arange(N) / FS signal = 0.5 + 0.4 * np.sin(2 * np.pi * FIN * t) # 80%幅度 # =============== 自定义2阶CIFB拓扑 =============== # 差分方程: # u1[n] = u1[n-1] + x[n] - y[n-1] # u2[n] = u2[n-1] + u1[n] - 2*y[n-1] # v[n] = u2[n] (量化器输入) # NTF = (1-z^-1)^2 state = [0.0, 0.0] # [u1, u2] 积分器状态 sd = SigmaDeltaADC(order=1, bits=1, osr=OSR) @sd.on(QuantizerEvent) def custom_2nd_order_cifb(event): x = event.input_signal # 当前输入 y = event.prev_output # 前一输出 (反馈) # 实现2阶CIFB差分方程 state[0] = state[0] + x - y # 第一级积分器 state[1] = state[1] + state[0] - 2*y # 第二级积分器 # 覆盖量化器输入 (关键!) event.quantizer_input = state[1] sd.sim(signal, fs=FS) sd._result.metadata['fin'] = FIN print(f"自定义2阶ENOB: {sd.enob():.2f} bits") # ~11.67 bits # =============== 1-bit 3阶Sigma-Delta =============== # 1-bit 3阶需要: 缩放积分器(c=0.3) + 小输入幅度 u3 = [0.0, 0.0, 0.0] c = 0.3 # 积分器缩放系数 sd3 = SigmaDeltaADC(order=1, bits=1, osr=OSR) @sd3.on(QuantizerEvent) def third_order_1bit(event): x, y = event.input_signal, event.prev_output u3[0] = u3[0] + c * (x - y) u3[1] = u3[1] + c * (u3[0] - 2*y) u3[2] = u3[2] + c * (u3[1] - y) event.quantizer_input = u3[2] signal_3rd = 0.5 + 0.2 * np.sin(2 * np.pi * FIN * t) sd3.sim(signal_3rd, fs=FS) sd3._result.metadata['fin'] = FIN print(f"3阶1-bit ENOB: {sd3.enob():.2f} bits") # ~12.7 bits
Sigma-Delta调制器的性能取决于积分器增益(c1, c2)、反馈系数(a1, a2)和输入幅度(amplitude)。 不同的系数组合会影响:
import numpy as np from quantiamagica import SigmaDeltaADC, QuantizerEvent from quantiamagica.optim import GeneticOptimizer, Gene # ===================== Step 1: 定义仿真参数 ===================== OSR = 64 # 过采样率 FS = 1e6 # 采样频率 1MHz N_SAMPLES = OSR * 128 # 采样点数 FIN = 13 * FS / N_SAMPLES # 相干采样频率 # ===================== Step 2: 定义要优化的基因 ===================== # 每个Gene定义一个参数的搜索范围 genes = [ Gene('c1', 0.1, 0.8, 'float'), # 第1级积分器增益 Gene('c2', 0.1, 0.8, 'float'), # 第2级积分器增益 Gene('a1', 0.5, 2.5, 'float'), # 第1级反馈系数 Gene('a2', 0.5, 3.5, 'float'), # 第2级反馈系数 Gene('amplitude', 0.15, 0.4, 'float'), # 输入正弦波幅度 ] # ===================== Step 3: 定义评估函数 ===================== # 这个函数接收一组参数,返回ENOB def evaluate_sd_adc(params): """创建2阶CIFB Sigma-Delta并评估ENOB""" c1, c2 = params['c1'], params['c2'] a1, a2 = params['a1'], params['a2'] amplitude = params['amplitude'] # 创建基础1阶SD ADC(我们通过事件扩展为2阶) sd = SigmaDeltaADC(order=1, bits=1, osr=OSR) state = [0.0, 0.0] # 两个积分器的状态 # 定义2阶CIFB拓扑 @sd.on(QuantizerEvent) def second_order_cifb(event): x = event.input_signal # 输入信号 y = event.prev_output # 量化器输出反馈 (+1/-1) # CIFB结构: 两级积分器 + 反馈 state[0] = state[0] + c1 * (x - a1 * y) # 第1级 state[1] = state[1] + c2 * (state[0] - a2 * y) # 第2级 event.quantizer_input = state[1] # 输出到量化器 # 生成输入信号 t = np.arange(N_SAMPLES) / FS signal = 0.5 + amplitude * np.sin(2 * np.pi * FIN * t) # 仿真并计算ENOB sd.sim(signal, fs=FS) sd._result.metadata['fin'] = FIN return sd.enob() # ===================== Step 4: 定义适应度函数 ===================== # 遗传算法最大化此函数 def fitness(params): try: enob = evaluate_sd_adc(params) if enob <= 0 or np.isnan(enob) or enob > 30: return -1000 # 振荡或异常,给予惩罚 # 目标:最大化ENOB,同时奖励较大的输入幅度 return enob * 10 + params['amplitude'] * 5 except: return -1000 # ===================== Step 5: 运行优化 ===================== optimizer = GeneticOptimizer(genes, fitness, maximize=True) result = optimizer.run(population_size=40) # 自动收敛,无需设置代数 # ===================== Step 6: 获取优化后的系数 ===================== print("优化后的系数:") print(f" c1 = {result.best_params['c1']:.4f}") # 积分器1增益 print(f" c2 = {result.best_params['c2']:.4f}") # 积分器2增益 print(f" a1 = {result.best_params['a1']:.4f}") # 反馈系数1 print(f" a2 = {result.best_params['a2']:.4f}") # 反馈系数2 print(f" amplitude = {result.best_params['amplitude']:.4f}") # 验证优化结果 optimized_enob = evaluate_sd_adc(result.best_params) print(f"\n优化后ENOB: {optimized_enob:.2f} bits") # ===================== 对比:默认系数 vs 优化系数 ===================== default_params = {'c1': 0.5, 'c2': 0.5, 'a1': 1.0, 'a2': 2.0, 'amplitude': 0.3} default_enob = evaluate_sd_adc(default_params) print(f"默认系数ENOB: {default_enob:.2f} bits") print(f"提升: +{optimized_enob - default_enob:.2f} bits")
| 属性 | 说明 | 示例 |
|---|---|---|
result.best_params | 优化后的参数字典 | {'c1': 0.6018, 'c2': 0.6467, ...} |
result.best_fitness | 最佳适应度值 | 121.84 |
result.generations | 实际迭代代数 | 13 |
result.converged | 是否收敛 | True |
result.history | 每代最佳适应度 | [80.5, 95.2, ...] |
如果只需优化标准SD ADC系数,可以使用封装好的优化器:
from quantiamagica.optim import SDCoeffOptimizer # 一行创建 + 一行优化 sd_opt = SDCoeffOptimizer(order=2, bits=1, osr=64, fs=1e6) result = sd_opt.optimize() # 打印优化报告 print(result.summary()) # 获取优化后的系数 print(result.best_params) # 所有参数 print(result.best_params['c1']) # 单个参数 print(result.best_enob) # 优化后的ENOB print(result.baseline_enob) # 优化前的ENOB print(result.improvement) # 提升了多少bits
5阶SD ADC有11个待优化参数,搜索空间巨大。默认系数往往直接振荡(ENOB<0), 遗传算法可以找到稳定且高性能的系数组合。
from quantiamagica import SigmaDeltaADC, QuantizerEvent from quantiamagica.optim import GeneticOptimizer, Gene import numpy as np OSR, FS = 64, 1e6 N_SAMPLES = OSR * 256 FIN = 13 * FS / N_SAMPLES # 定义5阶SD ADC的11个基因 genes = [ # 积分器增益 (越往后越小以保持稳定) Gene('c1', 0.1, 0.5, 'float'), Gene('c2', 0.08, 0.4, 'float'), Gene('c3', 0.05, 0.3, 'float'), Gene('c4', 0.03, 0.2, 'float'), Gene('c5', 0.02, 0.15, 'float'), # 反馈系数 Gene('a1', 0.8, 3.0, 'float'), Gene('a2', 0.5, 2.5, 'float'), Gene('a3', 0.3, 2.0, 'float'), Gene('a4', 0.2, 1.5, 'float'), Gene('a5', 0.1, 1.0, 'float'), Gene('amplitude', 0.08, 0.25, 'float'), ] def evaluate_5th_order(params): c = [params[f'c{i+1}'] for i in range(5)] a = [params[f'a{i+1}'] for i in range(5)] sd = SigmaDeltaADC(order=1, bits=1, osr=OSR) state = [0.0] * 5 @sd.on(QuantizerEvent) def fifth_order(event): x, y = event.input_signal, event.prev_output state[0] = state[0] + c[0] * (x - a[0] * y) for i in range(1, 5): state[i] = state[i] + c[i] * (state[i-1] - a[i] * y) event.quantizer_input = state[4] t = np.arange(N_SAMPLES) / FS signal = 0.5 + params['amplitude'] * np.sin(2*np.pi*FIN*t) sd.sim(signal, fs=FS) sd._result.metadata['fin'] = FIN return sd.enob() def fitness(params): enob = evaluate_5th_order(params) return enob if enob > 0 else -1000 optimizer = GeneticOptimizer(genes, fitness, maximize=True) result = optimizer.run(population_size=80) print(f"优化后ENOB: {result.best_fitness:.2f} bits") print(f"系数: {result.best_params}")
默认系数: 振荡 (ENOB=-3.55) → 优化后: 16.19 bits
收敛代数: 24代,进度条显示斜率收敛过程
确保你已经安装了QuantiaMagica。在项目目录下运行 pip install -e .
这是matplotlib字体问题。可以设置中文字体:
import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 黑体
result = adc.sim() result.save("data.npz") # NumPy格式 result.save("data.csv", format="csv") # CSV格式
from quantiamagica import Signal # CSV文件格式:每行一个电压值 sig = Signal.from_file("my_signal.csv", fs=1e6) adc.sim(sig)
通过以下练习题逐步掌握QuantiaMagica的使用。点击"查看答案"可以看到参考解答。
目标:创建一个8位SAR ADC,运行仿真并打印ENOB值。
要求:
ENOB: X.XX bitsSARADC(bits=8) 创建ADC,adc.sim() 运行仿真,adc.enob() 获取ENOB。
from quantiamagica import SARADC # 创建8位SAR ADC adc = SARADC(bits=8) # 运行仿真 adc.sim() # 打印ENOB print(f"ENOB: {adc.enob():.2f} bits")
预期输出:ENOB: 7.xx bits(理想8位ADC的ENOB接近8)
目标:创建12位ADC,仿真后打印SNR、SFDR、THD三个指标。
要求:
adc.snr()、adc.sfdr()、adc.thd() 获取各指标。
from quantiamagica import SARADC adc = SARADC(bits=12) adc.sim(n_samples=4096) print(f"SNR: {adc.snr():.1f} dB") print(f"SFDR: {adc.sfdr():.1f} dB") print(f"THD: {adc.thd():.1f} dB")
目标:创建10位ADC,使用50kHz输入信号仿真,绘制频谱图。
要求:
adc.sim(fin=50e3, fs=1e6) 设置参数,adc.spectrum() 绘制频谱。
from quantiamagica import SARADC adc = SARADC(bits=10) adc.sim(fin=50e3, fs=1e6, n_samples=4096) adc.spectrum()
说明:频谱图中可以看到50kHz处的基波和量化噪声底。
目标:同时使用SamplingEvent、CapacitorSwitchEvent、ComparatorEvent三种事件,模拟真实ADC的多种非理想效应。
要求:
noise_sigma = sqrt(kT/C),其中kT = 1.38e-23 * 300。电容失配用 event.capacitance_actual = event.capacitance * (1 + mismatch)。
from quantiamagica import ( SARADC, SamplingEvent, CapacitorSwitchEvent, ComparatorEvent, ) import numpy as np # ========== 理想ADC ========== ideal_adc = SARADC(bits=10, vref=1.0, name="Ideal") ideal_adc.sim(n_samples=1024, fs=1e6, fin=10e3) # ========== 非理想ADC ========== real_adc = SARADC(bits=10, vref=1.0, name="Realistic") # 事件1: 采样时添加kT/C热噪声 @real_adc.on(SamplingEvent) def add_thermal_noise(event): kT = 1.38e-23 * 300 # Boltzmann * Temperature C = 1000e-15 # 1000fF = 1pF noise_sigma = np.sqrt(kT / C) event.voltage += np.random.normal(0, noise_sigma) # 事件2: 电容切换时添加失配 @real_adc.on(CapacitorSwitchEvent) def add_cap_mismatch(event): mismatch = np.random.normal(0, 0.005) # 0.5% mismatch event.capacitance_actual = event.capacitance * (1 + mismatch) # 事件3: 比较器非理想效应 @real_adc.on(ComparatorEvent) def add_comparator_effects(event): event.offset = 0.5e-3 # 0.5mV失调 event.noise_sigma = 0.1e-3 # 0.1mV噪声 real_adc.sim(n_samples=1024, fs=1e6, fin=10e3) # ========== 对比结果 ========== print(f"理想ADC: ENOB={ideal_adc.enob():.2f}, SNR={ideal_adc.snr():.1f}dB") print(f"非理想ADC: ENOB={real_adc.enob():.2f}, SNR={real_adc.snr():.1f}dB")
说明:这展示了事件驱动的核心:每个事件对应ADC转换过程中的一个物理步骤,可以在该步骤注入非理想效应。
目标:使用EventPriority控制事件处理顺序,使用MONITOR优先级记录转换结果。
要求:
@adc.on(Event, priority=EventPriority.HIGH)。MONITOR优先级的处理器不应修改事件。
from quantiamagica import ( SARADC, SamplingEvent, ComparatorEvent, OutputCodeEvent, EventPriority, ) import numpy as np adc = SARADC(bits=10, vref=1.0, name="Priority-Demo") # HIGH优先级:最先执行 @adc.on(SamplingEvent, priority=EventPriority.HIGH) def add_noise_first(event): """采样噪声,优先执行""" kT = 1.38e-23 * 300 C = event.sampling_capacitance * 1e-15 noise_sigma = np.sqrt(kT / C) event.voltage += np.random.normal(0, noise_sigma) # NORMAL优先级:默认顺序 @adc.on(ComparatorEvent) def comparator_effects(event): """比较器效应""" event.offset = 0.5e-3 event.noise_sigma = 0.1e-3 # MONITOR优先级:只读监控,最后执行 @adc.on(OutputCodeEvent, priority=EventPriority.MONITOR) def log_output(event): """记录转换结果(只读)""" if event.source._sample_index < 5: print(f"Sample {event.source._sample_index}: " f"V={event.input_voltage:.4f}V -> Code={event.code}") print("前5个采样的转换记录:") adc.sim(n_samples=1024, fs=1e6, fin=10e3) print(f"\nENOB: {adc.enob():.2f} bits")
优先级顺序:HIGHEST > HIGH > NORMAL > LOW > LOWEST > MONITOR
目标:使用新的Pipeline类(不继承ADConverter)将3个8-bit SAR ADC串联成24-bit高精度Pipeline,并用InterstageGainEvent添加非理想效应。
Pipeline架构说明:
输入V → [Stage1: 8-bit SAR] → 残差×256 → [Stage2: 8-bit SAR] → 残差×256 → [Stage3: 8-bit SAR] → 输出
↓ ↓ ↓
code1 (MSB 8位) code2 (中间8位) code3 (LSB 8位)
↓
最终24位码 = code1<<16 | code2<<8 | code3
要求:
Pipeline([s1,s2,s3], gains=[256,256])创建24-bit流水线。增益误差=1-1/opamp_gain。
from quantiamagica import Pipeline, SARADC, InterstageGainEvent # ========== 创建3个8-bit SAR ADC ========== stage1 = SARADC(bits=8, vref=1.0, name="SAR-Stage1") stage2 = SARADC(bits=8, vref=1.0, name="SAR-Stage2") stage3 = SARADC(bits=8, vref=1.0, name="SAR-Stage3") # ========== 理想Pipeline (24-bit) ========== ideal_pipe = Pipeline( stages=[stage1, stage2, stage3], gains=[256.0, 256.0], # 级间增益=2^8 name="24-bit-Ideal" ) ideal_pipe.sim(n_samples=65536, fs=1e6, fin=10e3) # ========== 带增益误差的Pipeline ========== s1_err = SARADC(bits=8, vref=1.0, name="SAR-Stage1") s2_err = SARADC(bits=8, vref=1.0, name="SAR-Stage2") s3_err = SARADC(bits=8, vref=1.0, name="SAR-Stage3") real_pipe = Pipeline( stages=[s1_err, s2_err, s3_err], gains=[256.0, 256.0], name="24-bit-GainError" ) @real_pipe.on(InterstageGainEvent) def add_gain_error(event): """模拟有限运放增益导致的非理想效应""" opamp_gain = 1000 # 运放增益 gain_error = 1 - 1/opamp_gain # ~0.1%误差 event.actual_gain = event.ideal_gain * gain_error event.offset = 0.5e-3 # 0.5mV失调 event.noise_sigma = 0.1e-3 # 0.1mV噪声 real_pipe.sim(n_samples=65536, fs=1e6, fin=10e3) # ========== 对比结果 ========== print("3×8-bit SAR → 24-bit Pipeline 分析") print("=" * 50) print(f"理想Pipeline: ENOB={ideal_pipe.enob():.2f} bits, SNR={ideal_pipe.snr():.1f}dB") print(f"带增益误差: ENOB={real_pipe.enob():.2f} bits, SNR={real_pipe.snr():.1f}dB") print(f"ENOB损失: {ideal_pipe.enob() - real_pipe.enob():.2f} bits")
预期结果:理想Pipeline ENOB≈23.9 bits(接近24-bit理论值),带增益误差后ENOB会有所下降。
目标:创建一个可复用的RealisticSARPlugin类,封装多种非理想效应,可一键attach到任意ADC。
要求:
attach(adc)方法attach方法内部定义事件处理函数,使用self访问插件参数。热噪声电压 = sqrt(kT/C)。
from quantiamagica import ( SARADC, SamplingEvent, CapacitorSwitchEvent, ComparatorEvent, EventPriority, ) import numpy as np class RealisticSARPlugin: """可复用的SAR ADC非理想效应插件""" def __init__(self, cap_mismatch_sigma=0.005, # 0.5%电容失配 comparator_offset=0.5e-3, # 0.5mV失调 comparator_noise=0.2e-3, # 0.2mV噪声 sampling_cap_fF=500.0): # 500fF采样电容 self.cap_mismatch_sigma = cap_mismatch_sigma self.comparator_offset = comparator_offset self.comparator_noise = comparator_noise self.sampling_cap_fF = sampling_cap_fF self.cap_mismatches = None def attach(self, adc): """将所有非理想效应附加到ADC""" # 预生成固定的电容失配值 self.cap_mismatches = 1 + np.random.normal( 0, self.cap_mismatch_sigma, adc.bits ) # 计算热噪声电压 kT = 1.38e-23 * 300 C = self.sampling_cap_fF * 1e-15 self.thermal_noise_v = np.sqrt(kT / C) # 注册事件处理器 @adc.on(SamplingEvent, priority=EventPriority.HIGH) def add_sampling_noise(event): event.voltage += np.random.normal(0, self.thermal_noise_v) @adc.on(CapacitorSwitchEvent) def add_cap_mismatch(event): event.capacitance_actual = ( event.capacitance * self.cap_mismatches[event.bit_index] ) @adc.on(ComparatorEvent) def add_comparator_effects(event): event.offset = self.comparator_offset event.noise_sigma = self.comparator_noise # ========== 使用插件 ========== print("1. 理想ADC") ideal = SARADC(bits=12, vref=1.0) ideal.sim(n_samples=2048, fs=1e6, fin=10e3) print(f" ENOB: {ideal.enob():.2f} bits") print("\n2. 使用插件的非理想ADC") real = SARADC(bits=12, vref=1.0) plugin = RealisticSARPlugin() plugin.attach(real) real.sim(n_samples=2048, fs=1e6, fin=10e3) print(f" ENOB: {real.enob():.2f} bits") print(f" 热噪声: {plugin.thermal_noise_v*1e6:.2f} uV rms")
说明:插件模式可以复用,只需plugin.attach(adc)即可给任意ADC添加相同的非理想效应。
目标:创建2阶1位Sigma-Delta ADC,OSR=64,计算带内ENOB。
要求:
SigmaDeltaADC(order=2, bits=1, osr=64)。带内ENOB会比SAR ADC高很多。
from quantiamagica import SigmaDeltaADC import numpy as np sd = SigmaDeltaADC(order=2, bits=1, osr=64) # 生成输入信号 fs = 1e6 fin = 1e3 n_samples = 8192 t = np.arange(n_samples) / fs signal = 0.5 + 0.4 * np.sin(2 * np.pi * fin * t) sd.sim(signal, fs=fs) print(f"Sigma-Delta ENOB: {sd.enob():.2f} bits")
说明:2阶SD ADC的带内ENOB可达10+bits,远高于1位量化器本身。
目标:使用SDCoeffOptimizer优化2阶SD ADC的系数,对比优化前后的ENOB。
要求:
SDCoeffOptimizer,调用 optimize() 方法,结果的 summary() 方法会打印完整报告。
from quantiamagica.optim import SDCoeffOptimizer # 创建优化器 optimizer = SDCoeffOptimizer( order=2, bits=1, osr=64, fs=1e6 ) # 运行优化 result = optimizer.optimize() # 打印结果 print(result.summary()) print(f"\n优化前ENOB: {result.baseline_enob:.2f} bits") print(f"优化后ENOB: {result.best_enob:.2f} bits") print(f"提升: +{result.improvement:.2f} bits")
目标:使用遗传算法优化5阶Sigma-Delta ADC的11个参数(5个积分器增益c1-c5、5个反馈系数a1-a5、1个输入幅度),实现16-20 bits的极致ENOB。
五阶CIFB结构说明:
输入x → [积分器1] → [积分器2] → [积分器3] → [积分器4] → [积分器5] → [量化器] → 输出y
↑ c1 ↑ c2 ↑ c3 ↑ c4 ↑ c5
└─a1·y──────┴─a2·y──────┴─a3·y──────┴─a4·y──────┴─a5·y (分布式反馈)
状态更新方程:
state[0] = state[0] + c1 * (x - a1 * y) // 第1级
state[i] = state[i] + c[i] * (state[i-1] - a[i] * y) // 第2-5级
quantizer_input = state[4] // 输出到量化器
要求:
参数范围参考:
| 参数 | 范围 | 说明 |
|---|---|---|
| c1-c5 | 0.01~0.6(递减) | 积分器增益,高阶需较小值保稳定 |
| a1-a5 | 0.05~4.0(递减) | 反馈系数 |
| amplitude | 0.03~0.2 | 高阶SD需小幅度避免过载 |
try-except捕获异常返回惩罚值-1000。用QuantizerEvent的event.input_signal、event.prev_output、event.quantizer_input实现状态更新。
from quantiamagica import SigmaDeltaADC, QuantizerEvent from quantiamagica.optim import GeneticOptimizer, Gene import numpy as np # ===================== 仿真参数 ===================== OSR = 64 BITS = 1 FS = 1e6 N_SAMPLES = OSR * 512 FIN = 13 * FS / N_SAMPLES # 相干采样 # ===================== 定义11个基因 ===================== genes = [ # 积分器增益(递减范围) Gene('c1', 0.05, 0.6, 'float'), Gene('c2', 0.04, 0.5, 'float'), Gene('c3', 0.03, 0.4, 'float'), Gene('c4', 0.02, 0.3, 'float'), Gene('c5', 0.01, 0.2, 'float'), # 反馈系数 Gene('a1', 0.5, 4.0, 'float'), Gene('a2', 0.3, 3.5, 'float'), Gene('a3', 0.2, 3.0, 'float'), Gene('a4', 0.1, 2.5, 'float'), Gene('a5', 0.05, 2.0, 'float'), # 输入幅度 Gene('amplitude', 0.03, 0.2, 'float'), ] # ===================== 评估函数 ===================== def evaluate_5th_order_sd(params): """创建并评估5阶SD ADC""" c = [params[f'c{i+1}'] for i in range(5)] a = [params[f'a{i+1}'] for i in range(5)] amplitude = params['amplitude'] sd = SigmaDeltaADC(order=1, bits=BITS, osr=OSR) state = [0.0] * 5 # 5个积分器状态 @sd.on(QuantizerEvent) def fifth_order_cifb(event): """5阶CIFB结构""" x = event.input_signal y = event.prev_output # 5阶级联积分器 + 分布式反馈 state[0] = state[0] + c[0] * (x - a[0] * y) for i in range(1, 5): state[i] = state[i] + c[i] * (state[i-1] - a[i] * y) event.quantizer_input = state[4] # 输出到量化器 # 生成输入信号 t = np.arange(N_SAMPLES) / FS signal = 0.5 + amplitude * np.sin(2 * np.pi * FIN * t) sd.sim(signal, fs=FS) sd._result.metadata['fin'] = FIN return sd.enob() # ===================== 适应度函数 ===================== def fitness(params): try: enob = evaluate_5th_order_sd(params) if enob <= 0 or np.isnan(enob) or enob > 35: return -1000 # 振荡或异常,给惩罚 return enob except: return -1000 # ===================== 基准测试 ===================== baseline_params = { 'c1': 0.25, 'c2': 0.18, 'c3': 0.12, 'c4': 0.08, 'c5': 0.05, 'a1': 2.0, 'a2': 1.5, 'a3': 1.0, 'a4': 0.6, 'a5': 0.3, 'amplitude': 0.1 } baseline_enob = evaluate_5th_order_sd(baseline_params) print(f"默认系数 ENOB: {baseline_enob:.2f} bits") # ===================== 运行优化 ===================== print("开始优化11维参数空间...") optimizer = GeneticOptimizer(genes, fitness, maximize=True) result = optimizer.run( population_size=300, # 大种群探索高维空间 max_generations=500, mutation_rate=0.18, elite_ratio=0.10, seed=2024 ) # ===================== 输出结果 ===================== best_enob = evaluate_5th_order_sd(result.best_params) print(f"\n优化后 ENOB: {best_enob:.2f} bits") print(f"提升: +{best_enob - baseline_enob:.2f} bits") print(f"\n优化后系数:") print(f" 积分器: c1={result.best_params['c1']:.4f}, c2={result.best_params['c2']:.4f}, " f"c3={result.best_params['c3']:.4f}, c4={result.best_params['c4']:.4f}, c5={result.best_params['c5']:.4f}") print(f" 反馈: a1={result.best_params['a1']:.4f}, a2={result.best_params['a2']:.4f}, " f"a3={result.best_params['a3']:.4f}, a4={result.best_params['a4']:.4f}, a5={result.best_params['a5']:.4f}") print(f" 幅度: amplitude={result.best_params['amplitude']:.4f}")
说明:5阶SD ADC有11个待优化参数,搜索空间巨大。默认系数往往直接振荡(ENOB<0),遗传算法可以找到稳定且高性能的系数组合,达到16-20 bits的极致ENOB。