news 2026/9/7 11:42:02

三阶连续时间Delta-Sigma ADC的Matlab行为级仿真与性能分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
三阶连续时间Delta-Sigma ADC的Matlab行为级仿真与性能分析

简介:这是一套3阶连续时间Delta-Sigma ADC的Matlab/Simulink仿真代码,适合正在学习过采样数据转换器、或从事模拟前端与信号处理算法验证的工程师和学生。资源共10个文件,包含3个Matlab脚本(用于主仿真、FFT频域计算和动态测试)、1个Simulink模型、3篇相关ADC设计论文PDF,另有参数计算表、操作说明与运行截图,压缩包仅3.14MB,结构清晰,便于对照学习。仿真覆盖时序行为、频域响应和功率谱密度分析,可直观观察三阶噪声整形效果与量化噪声分布;配合400倍过采样率、20MHz带宽等设计参数,能帮助理解高阶连续时间调制器的工作原理与性能权衡。目前已有954人学习下载,代码配合PDF论文和操作说明,可快速复现并深入掌握Delta-Sigma ADC的系统级建模与分析流程。 它可能听起来有点玄乎:3阶连续时间Delta-Sigma ADC,Matlab仿真代码。但拆开看其实不复杂。Delta-Sigma ADC在工业测量、音频、传感器采集里非常常见,连续时间结构又因为天然抗混叠、适合高速低功耗而一直有人在做。这篇文章我把一套可直接运行的3阶CT-DSM行为级仿真代码拆开讲清楚,包括架构怎么选、系数怎么定、环路怎么写、SNDR和ENOB怎么算,以及我调模型时踩过的几个坑。

这套代码适合谁?正在做ADC课程设计的学生、准备流片或做IP验证的工程师、以及想用Matlab快速评估调制器性能的硬件开发者。不需要你有多深的控制理论底子,但至少要知道积分器、采样保持、量化器这些基础概念。看懂之后,你可以自己改阶数、改过采样率、改量化位数,几分钟出一版性能评估结果。

1. 项目概述与设计初衷

1.1 为什么选三阶连续时间结构先说说为什么是三阶。Delta-Sigma调制器的核心思想是用过采样加噪声整形,把带内量化噪声压下去。一阶的整形斜率只有20dB/dec,二阶是40dB/dec,三阶能到60dB/dec。同样OSR下,三阶比二阶多出接近一个数量级的带内信噪比改善,但又不像四阶、五阶那样对系数容差和稳定性特别敏感。三阶是性能和可实现性之间一个非常平衡的折中,很多商用音频ADC和中等精度工业ADC都用的是这个阶数。

连续时间和离散时间的区别,通俗讲就是环路滤波器到底在哪个域工作。离散时间Delta-Sigma用的是开关电容积分器,工作在z域,积分器传递函数是1/(z-1);连续时间用的是RC或Gm-C积分器,工作在s域,传递函数是1/(sTs)这种形式。连续时间的最大好处是采样之前环路本身就有抗混叠能力,不用专门放一个大面积抗混叠滤波器,而且对运放的压摆率要求相对宽松,所以在高速中等精度场景里很吃香。

1.2 这套仿真能解决哪些问题

实际设计一个CT-DSM之前,最重要的一件事不是立刻画电路,而是先确认“这个架构在行为级能不能稳定工作、能拿到多少SNDR”。很多问题如果放到晶体管级再发现,改一版版图的时间成本非常痛苦。用Matlab做行为级仿真,可以在几分钟内验证环路系数、量化器位数、输入幅度对性能的影响,给后面Verilog-A建模和电路实现提供明确指标。

这套代码就是干这个的。它构建一个带输入正弦信号的三阶连续时间环路滤波器,配一个3比特量化器和理想NRZ反馈DAC,通过数值积分的方式模拟连续时间系统的逐周期行为,最终给出输出时域波形、功率谱密度、SNDR和ENOB。整个过程没有用到Simulink,纯脚本即可运行,适合快速批量参数扫描,也方便嵌入到自动化优化流程里。

2. 架构选型与关键参数设计

2.1 三阶环路滤波器结构

我用的结构是CIFB,也就是级联积分器加反馈。三个连续时间积分器串在一起,反馈DAC分别注入到第一、第二、第三个积分器的输入端,量化器采样第三级积分器的输出。对应的连续时间状态方程写出来就是:

d(x1)/dt = (u - a1*v)/Ts d(x2)/dt = (x1 - a2*v)/Ts d(x3)/dt = (x2 - a3*v)/Ts w = x3

其中u是输入信号,v是DAC反馈电平,w是量化器输入,a1、a2、a3是反馈系数。Ts是采样周期。这里把Ts写在分母上,是为了让离散域积分器1/(z-1)和连续域积分器1/(sTs)在低频段对齐。很多初学者在这里犯迷糊,直接照搬离散系数却不除以Ts,结果高频增益差了一个数量级,仿真直接发散或者性能差得离谱。

CIFB结构的好处是量化器输入信号比较干净,就是第三级积分器输出,不需要额外加前馈求和网络。缺点是系数稍大时稳定性比CIFF差,但三阶场景下用下面这组系数完全可以稳定工作。

2.2 关键参数与系数设定

设计目标定为:采样频率10MHz,过采样率OSR=64,信号带宽78.125kHz,内部量化器3比特8电平。输入正弦取满量程的0.4幅度,保证不过载又有一点动态余量。

参数数值说明
fs10 MHz采样频率
Ts100 ns采样周期
OSR64过采样率
fb78.125 kHz信号带宽
nlev8量化器电平数,3比特
Ain0.4输入幅度,满量程约0.5
fin7.629 kHz输入信号频率,选相干频率

反馈系数我在调通后取的是a1=0.7、a2=0.5、a3=0.1。这三个系数看起来不大,但配合积分器自身的极点,已经能在带内形成三阶噪声整形。系数再加大,低频整形更陡,但相位裕度变差,输入稍大就容易出现间歇性振荡;系数再减小,噪声整形效果又不够。行为级模型里可以通过参数扫描快速找到适合自己目标的折中点。

2.3 稳定性与精度权衡

三阶调制器的稳定性本质上靠的是多位量化器和环路增益的配合。量化器电平越多,等效量化增益越接近线性,环路越稳。3比特以上基本可以保证低输入幅度下不出现明显的极限环。另一个关键是输入信号幅度不能太大,0.6以上时第三级积分器输出很容易顶到量化器满量程,造成瞬时过载,频谱上会看到底噪整体抬升,SNDR断崖式下跌。

如果后续你要做单比特版本,必须把系数调小,并且大概率要加局部反馈谐振或者前馈路径来补偿稳定性。行为级仿真阶段多花点时间把稳定边界摸清楚,后面电路设计会轻松很多。

3. Matlab仿真代码实现

3.1 顶层参数与状态初始化

代码第一步是定义系统参数。为了让FFT分析不受频谱泄漏干扰,输入频率要选择相干频率,也就是fs/Ns的整数倍。我这里取Ns=32768,k=25,所以fin=25*fs/Ns=7.629kHz。相干采样配合矩形窗就能直接读谱,不需要加窗校正,非常省事。

clear; clc; close all; % 系统参数 fs = 10e6; % 采样频率 10MHz Ts = 1/fs; OSR = 64; % 过采样率 fb = fs/(2*OSR); % 带宽 78.125kHz % 仿真点数与相干输入频率 Ns = 32768; k = 25; fin = k*fs/Ns; % 输入信号 Ain = 0.4; t = (0:Ns-1)*Ts; u = Ain*sin(2*pi*fin*t); % 三阶CIFB反馈系数 a1 = 0.7; a2 = 0.5; a3 = 0.1; % 状态变量初始化 x = [0; 0; 0]; y = zeros(1, Ns); w = zeros(1, Ns); % 3比特量化器参数 nlev = 8; vmin = -1; vmax = 1; delta = (vmax - vmin) / (nlev - 1); % RK4子步设置 Nsub = 4; h = Ts / Nsub; % 状态方程右侧函数 f_rhs = @(xx, uu, vv) [ (uu - a1*vv)/Ts; ... (xx(1) - a2*vv)/Ts; ... (xx(2) - a3*vv)/Ts ];

这里的核心是f_rhs。它对应上面写的三阶连续时间状态方程。以后你要改成四阶或者换成CIFF结构,只需要改这个函数和状态个数,其他代码基本不用动。

3.2 主仿真循环实现

主循环里做的事情是:用当前状态x3算出量化器输出,把量化结果作为整个采样周期内的DAC反馈,然后用四阶龙格库塔法推进状态到下一个采样点。RK4是连续时间行为模型最常用的数值积分方式,4个子步对10MHz量级的系统已经足够,精度比简单欧拉法高不少,也不像ode45那样慢。

for n = 1:Ns % 采样量化器输入 w(n) = x(3); % 量化:round到最近电平 tmp = round((w(n) - vmin) / delta); tmp = max(0, min(nlev-1, tmp)); y(n) = vmin + tmp * delta; vfb = y(n); % NRZ反馈,本周期保持 % 在当前反馈和连续输入下,用RK4推进一个Ts t0 = (n-1)*Ts; for j = 1:Nsub ud1 = Ain*sin(2*pi*fin*(t0)); ud2 = Ain*sin(2*pi*fin*(t0 + h/2)); ud4 = Ain*sin(2*pi*fin*(t0 + h)); k1 = f_rhs(x, ud1, vfb); k2 = f_rhs(x + (h/2)*k1, ud2, vfb); k3 = f_rhs(x + (h/2)*k2, ud2, vfb); k4 = f_rhs(x + h*k3, ud4, vfb); x = x + (h/6)*(k1 + 2*k2 + 2*k3 + k4); t0 = t0 + h; end end

你可能注意到,这里反馈用的是当前周期算出的y(n),而不是上一周期的值。这样做更贴近CT调制器的真实工作方式:比较器在采样沿触发,DAC在同一周期内持续输出反馈电流或电压,不存在显式的一个周期环路延迟。如果你实现的是带过量环路延迟的架构,就要在反馈路径上额外加延迟,并且重新整定系数,这里不展开。

3.3 频谱分析与指标计算

仿真跑完,接下来就是把y序列做FFT,算带内噪声功率,然后求SNDR和ENOB。我用矩形窗,因为输入是相干采样,FFT结果不会泄漏。信号功率取信号频点附近几个bins,噪声功率取从直流以外到fb频段内所有bins之和再扣掉信号功率。

% FFT分析 Y = fft(y); P = abs(Y/Ns).^2; f = (0:Ns-1)*fs/Ns; % 带宽内bins数量 NBin = Ns/(2*OSR); % 256 bins,不含直流 signal_bins = k + 1; % 信号bin位置(从1开始) sig_power = sum(P(signal_bins)); % 相干采样信号集中在单个bin % 带内噪声功率 noise_bins = setdiff(2:NBin+1, signal_bins); noise_power = sum(P(noise_bins)); SNDR = 10*log10(sig_power / noise_power); ENOB = (SNDR - 1.76) / 6.02; fprintf('SNDR = %.2f dB\n', SNDR); fprintf('ENOB = %.2f bit\n', ENOB);

补一个画频谱的代码,方便直接看噪声整形曲线:

figure; semilogx(f(2:Ns/2), 10*log10(P(2:Ns/2)*2), 'LineWidth', 0.8); hold on; xline(fb, 'r--', 'Bandwidth'); xlabel('Frequency (Hz)'); ylabel('Power Spectral Density (dBFS/bin)'); title('3rd-order CT Delta-Sigma ADC Output Spectrum'); grid on; xlim([1e3 fs/2]);

频谱图上你应当能看到低频段很干净,噪声随频率以三阶斜率快速上升,穿过fb之后继续向上走,这就是典型的三阶单环噪声整形形状。

4. 仿真结果与关键指标解析

4.1 时域输出与稳定性判断

跑完上面的代码,前几百个采样点后系统会进入稳态,y序列会在几个离散电平之间切换,电平分布集中在输入信号附近。一个快速检查稳定性的方法是看w序列,也就是量化器输入。如果w经常被顶到±1以上,说明积分器状态过载,三阶环路容易进入临界振荡。正常稳定情况下,x3的幅度应该被反馈压住,不会无限制增长。

我实际测下来的结果,Ain=0.4、Ns=32768时,SNDR大约在70dB上下,ENOB在11bit出头。这个结果对3比特内部量化器来说是比较合理的:3比特本身提供约19.8dB理想量化信噪比,三阶整形在OSR=64时再贡献约50dB的改善,扣掉稳定性和非线性损耗,70dB是可预期的水平。

时域里还有一个值得观察的点:量化器输出在信号正半周和负半周的切换密度大致对称,如果不对称明显,很可能是输入直流偏置没处理好,或者DAC反馈系数存在静态失配。

4.2 功率谱密度与SNDR/ENOB分析

频谱图上最直观的是噪声整形曲线。带内从最低频到78kHz,噪声谱几乎是被“压平”在地板上的,过了fb之后噪声开始以每十倍频60dB的斜率抬头。如果曲线斜率只有40dB/dec,说明环路实际只体现了两阶整形,常见原因是某个积分器增益被系数压得太低,或者量化器过载导致等效增益下降。

SNDR指标要用带内总噪声算,而不是只看一个频点。很多新手喜欢盯频谱底噪,但底噪低不代表SNDR高,如果带内有一个明显的杂散,底噪再漂亮也没用。所以我上面的代码用的是全带内积分求噪声功率,这样更可靠。

ENOB和SNDR的换算关系是ENOB=(SNDR-1.76)/6.02,适用于满摆幅正弦输入的典型情况。如果你的输入幅度只有0.2,算出来的有效位数会偏低,那只是因为信号功率变小了,不代表ADC本身变差了。

4.3 参数扫描与鲁棒性验证

仿真代码最大的优势是方便批量扫参。我建议至少扫描三个维度:输入幅度、OSR、反馈系数。

输入幅度从0.1扫到0.6,你会看到SNDR先缓慢上升,到某个点后开始迅速下降。这个拐点就是调制器的过载点。对三阶多位调制器,过载点一般在满量程的60%到70%之间,超过之后积分器状态非线性振荡,性能崩得很快。

OSR从32扫到128,ENOB会跟随OSR增加而提升。理想三阶整形每倍频OSR提升约10.5dB,即约1.7bit/倍频。实际仿真结果低于这个理想值,因为量化器噪声并不完全是白噪声,还有高阶非线性成分。

反馈系数扫描我建议用一个小脚本,比如把a1、a2、a3乘以0.8到1.2的缩放因子,观察SNDR的变化范围。正常情况下SNDR应该在某个系数组合附近有一个较平缓的峰,偏移20%以内性能不会雪崩。如果稍微动一点系数就发散了,说明设计点离稳定边界太近,这种设计流片风险极高。

5. 常见问题与排查实录

5.1 仿真发散或输出出现极限环

最常见的问题是积分器状态呈指数增长,输出y在满量程反复跳变。这种在几十个采样点内就能看出来。先确认输入幅度是不是超了过载点,把Ain降到0.3再试。如果还是发散,把反馈系数整体乘0.6再看趋势。三阶环路系数偏大是导致发散的最常见原因,没有其他技巧,只能缩小系数。

还要检查你用的量化器步长是不是正确。8电平对应的步长是0.2857,不是0.5或0.25。如果步长算错,反馈DAC的实际增益会偏移,环路增益变化直接破坏噪声整形,严重时直接不稳定。

5.2 频谱泄漏与窗函数选择

如果输入频率没有严格满足相干采样条件,FFT频谱会在信号频点出现泄漏,旁瓣可能抬高带内底噪,严重时会吃掉10dB以上的SNDR。解决办法有两个:一是像我一样使用k*fs/Ns作为输入频率;二是在FFT之前加汉宁窗并做相干增益校正。后者对于非整周期采样的数据更稳妥,但要注意加窗会让噪声功率计算需要额外的倍数补偿。

我在代码里用了相干采样加矩形窗,是因为这样最简单且精度够。如果你要测任意频率点,建议改用pwelch做平均功率谱,不要直接用裸FFT看单次结果。

5.3 采样点数与仿真速度的取舍

行为级模型跑32768个点非常快,几秒钟就完了。但如果你把RK4子步数增加到20以上,或者把采样点加到100万,MATLAB里纯循环的速度会明显变慢。我建议:调稳阶段用16384点快速验证,确认稳定后再跑65536点或更高点数计算最终SNDR。RK4子步设定为4到8个足够,过多子步除了拖慢仿真速度,对结果改善非常有限,因为行为级模型的精度瓶颈主要来自量化器和环路系数,而不是数值积分。

5.4 DAC非理想特性与失配问题

这个仿真的DAC是理想NRZ反馈。实际上连续时间调制器的性能天花板很多时候由反馈DAC决定,尤其是单比特DAC的时钟抖动和多比特DAC的单元失配。如果你要更接近电路实际,可以在反馈路径上加入DAC失配噪声:给每个量化电平对应的DAC输出加一个固定偏差,再用蒙特卡洛跑几十次看SNDR分布。那样能直接评估这个架构对DAC线性度的要求,对后端电路设计非常有参考价值。

时钟抖动也是CT-DSM特有的关键问题。NRZ反馈对时钟抖动的敏感度比RZ反馈低一些,但三阶整形的环路对高频抖动仍然敏感。行为级仿真的做法是把采样时刻加一个高斯随机扰动,然后看SNDR变化量,这种做法在论文里很常见,但需要你自己扩展一下。

6. 一些实操后的体会

这套代码我前前后后改过好几版,最初直接照搬离散时间的系数进连续时间方程,跑出来频谱乱七八糟,后来把Ts因子补上才正常。还有一个容易忽略的细节是量化器输入到底取一个采样周期开始时的值还是积分完成后的值,这直接关系到环路有没有隐式延迟。我最后选择的是用当前状态算量化输出、再反馈到当前周期,这更符合连续时间调制的直觉,也更容易调稳。

你拿到代码之后,建议第一步先原样跑通,看SNDR是否在70dB上下;第二步开始扫输入幅度找过载点;第三步再改系数看鲁棒性。做完这三步,你对三阶连续时间Delta-Sigma的基本性格就有数了。后续如果想往真正电路方向走,可以把理想积分器换成带有限直流增益和有限带宽的模型,再把NRZ DAC换成带抖动的模型,行为级验证体系就这么一点点搭起来了。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 11:41:34

STM32F103驱动SPI屏幕移植LVGL:从底层显示驱动到应用层配置全解析

简介:面向STM32F103嵌入式开发者,一份自写可用的LVGL移植程序完整演示了通过SPI接口驱动显示屏并移植图形库的工程化流程,适用于课程设计、产品原型开发或GUI学习实践。压缩包共761个文件,整体仅3.77MB,以C/H源码为主体…

作者头像 李华
网站建设 2026/9/7 11:41:11

跑山智驾零接管背后:智驾系统如何应对复杂山路挑战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 11:39:39

飞书多维表格深度解析:从在线表格到轻量数据管理平台

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 11:38:53

AI Slop治理实战:从提示词到流程,彻底告别低质AI内容

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 11:38:40

从补全到智能体:Codex五年进化路线与2025实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 11:38:35

技术博客写作全攻略:从项目部署到问题排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华