最近做电路蒙特卡洛仿真,想去找官方模型,但是官方模型没有现成的蒙特卡洛仿真模型。就想着自己取搭一个仿真模型。现在AI很火,就把规格书丢给AI帮忙了,让它帮我生成了一个ADC的蒙特卡洛仿真模型。刚好,趁着这个机会学习下AI是怎么搭建这个电路的。以下是AI写的SPICE模型网表。以下模型代码可以直接拷贝进LTspice使用,但是对于其它基于Spice语言的仿真软件,可能需要做部分修改:

        可以看到这是一个12位的ADC模型,它主要考虑了零点漂移误差,增益误差和非线性误差。

        输入端,通过定义引脚电容和封装电容,模拟ADC引脚到内部ADC的输入电容。然后通过一个多路复用器电阻,在接到内部采样电容。

        主要看行为级转换模型,对于第一个行为电源:OFFSET_ERR*LSB很好理解,是输入电压的零点漂移误差。那么为什么要除以(1+GAIN_ERR/FS_CODE)呢?怎么理解它呢?

        这个表达式的关键在于:偏移误差改变的是截距,而增益误差改变的是斜率。

        可以通过以下几个步骤拆解这个公式背后的物理和数学逻辑。

        1、理想的12位ADC,输入电压从0变到满量程VREF时,输出代码从0变到满量程FS_CODE(4095)。

        理论上的斜率(灵敏度)是:

Slope_{ideal}=\frac{FSCODE}{V_{REF}}

        2、带有增益误差的实际斜率

        增益误差是指ADC在满量程处偏离理想值的偏差(扣除零点误差后),如果数据手册标注的增益误差为GAIN_ERR(eg:+3.5LSB),意思是当输入真实达到满量程VREF时,ADC转换出来的数字代码不是恰好4095,而是4095+3.5,此时的实际转换斜率变成了:

Slope_{actual}=\frac{FSCODE+GAINERR}{V_{REF}}

        从实际斜率的公式里提取出理想斜率的部分,就会得到:

Slope_{actual}=\frac{FSCODE}{V_{REF}}*\frac{FSCODE+GAINERR}{FSCODE}

Slope_{actual}=Slope_{ideal}*(1+\frac{GAINERR}{FSCODE})

Slope_{ideal}=\frac{Slope_{actual}}{1+GAINERR/FSCODE}

        这里的(1+\frac{GAINERR}{FSCODE})就是增益修正系数(比例因子)

        如果GAIN_ERR是0,这个系数为1,斜率完美。若GAIN_ERR是3.5,系数则不为1,说明实际的斜率会更陡峭。

        那么怎么理解这里要去找理想模型的斜率,而不是用真实的斜率呢?

        其实,这里正是在制造误差。这是在“欺骗”理想量化器。在仿真软件中,系统自带的ADC核心模块,通常是一个绝对理想的量化器。它不懂什么是失调,也不懂什么是增益误差,它只会死板地执行一个完美的公式:

Code=\frac{V_{in}}{LSB}

        我其实需要一个不完美的真实的ADC,但是现在只有一个完美的量化器。这里它使用的就是对输入电压进行反向预失真,计算出Veff。通过将输入电压按照误差的逆运算扭曲一下,再喂给完美的量化器,则量化器输出的Code,就是我们最终想要的误差特征。

        可以进行数学推导看看,假设真实的非理想ADC,其输入电压Vin和输出代码对应的关系如下:

V_{in}=Code*LSB*Gain Factor+V_{offset}

        其中:GainFactor=(1+\frac{GAINERR}{FSCODE})     V_{offset}=OFFSET*LSB

        现在将公式反过来,求解如果用理想量化器,它应该接受到什么输入:

        先处理零点漂移误差:

V_{in}-V_{offset}=Code*LSB*Gain Factor

        再除以增益系数:

\frac{V_{in}-V_{offset}}{Gain Factor}=Code*LSB

        令等式左边等于Veff,等式右边正好是理想量化器的逆推公式。

V_{eff}=Code*LSB\Rightarrow Code=V_{eff}/LSB

        所以就需要Vin=Veff。

        弄清这个后,再看第二个行为源,Veff/LSB已经知道,是理论上应该输出的AD值,可是后面又是的公式代表什么呢?其实这里是在模拟积分非线性误差(INL):

        INL_ERR*sin(6.28*V(V_eff)/VREF),在理想AD值的基础上,叠加一个基于正弦波形态的扰动值。V(V_eff)/VREF是为了将输入电压归一化到0~1之间。

        这意味着,当输入电压为0到满量程Vref时,这个正弦函数刚好走过一个完美的2π周期。因为在真实的ADC中,积分非线性误差(INL)通常是由于内部电容阵列的梯度不匹配、电阻串的弯曲效应等物理缺陷引起的。真实的INL曲线往往呈现出类似“S型”或“弓型”的弯曲。仿真时,为体现出此弯曲,又简化计算量,最常用的手段就是叠加一个低频正弦波。这样不仅能在静态上模拟出最大的INL偏差,还能在FFT仿真中逼真的产生谐波失真。

        最终裁决由floor进行,它可以将输出值离散为数字。此函数可以向下取整。模拟真实ADC丢弃小数部分的行为,同时也自然的引入了量化误差。

        另外再聊下为什么设定误差的时候,要对规格书的误差除以3。这是因为我们拿到的数据手册(运放,电阻电容等),手册上给的通常是最大值3σ。为了让仿真器能理解,需要先将其除以3,转换成1σ,再输入给模型。

        当模型利用1σ进行成千上百次的运行后,会得到不同的输出结果,将输出结果进行统计,则可以算出结果的标准差1σ。然后,再对其乘3,还原为工业通用的3σ边界。

        这里看似先除再乘没有变化,但是实际并没有那么简单。因为随机误差是不能进行相加的。比如假设系统有2个独立误差源,各自的最大误差都是3mV。

        最坏情况(绝对相加):总误差就是3mV+3mV=6mV。

        但是实际情况往往是符合统计学的:两个误差同时达到最大值,且同方向的概率极小。统计学上,独立的随机误差合并遵循着方差和法则。

\sigma _{total}=\sqrt{\sigma_{1}^{2}+\sigma_{2}^{2}}

        如果直接算:

        先转成1σ:2个误差的1σ都是1mV。

        平方开根计算总1σ:\sqrt{1^{2}+1^{2}}=\sqrt{2}\approx 1.414mV

        乘以3得到3σ:1.414*3=4.242mV<<6mV

        这样设计可以避免过度设计,得到一个既安全又复合实际的最终误差评估。

        

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐