10位100M,SAR ADC完整电路,包括仿真测试代码,建模代码,电路文件,奈奎斯特频有效位数9.8。
最近在折腾一款10位100MHz的SAR ADC设计,从系统建模到电路实现踩了不少坑。这种高速中精度ADC在IoT和传感器领域应用挺多,咱们直接来看核心设计要点。
建模阶段用Matlab验证架构可行性最省时间。先搭了个理想模型计算电容失配影响,关键代码段长这样:
LSB_weight = 1/(2^10); mismatch = 0.02; % 2% mismatch dac_error = randn(1,10)*mismatch.*(2.^(0:9)); INL = cumsum(dac_error)/LSB_weight;这段主要模拟DAC阵列的随机失配,发现当单位电容偏差超过0.5%时,有效位直接掉到9.5以下。后来在版图阶段特意给高四位电容加了dummy结构。
电路实现里比较头疼的是比较器设计。传统两级运放结构在100MHz时钟下根本来不及建立,后来改成了动态锁存比较器。实测代码里有个有趣的波形捕捉:
initial begin force tb.adc_clk = 0; #15 force tb.vinn = 0.3; // 模拟输入阶跃 #50 $display("LSB settling time: %t", $realtime); end这段强迫症测试暴露出比较器回踢噪声的问题——当输入接近阈值时会有周期性震荡。解决办法是在预放大级加了50mV的迟滞窗口。
控制逻辑用Verilog写了个状态机,重点注意时钟相位关系:
always @(negedge clk) begin // 下降沿采样 if (cycle_cnt < 10) begin dac_ctrl[9-cycle_cnt] <= cmp_out; cycle_cnt <= cycle_cnt + 1; end end这个倒序赋值操作对应SAR算法的权重迭代过程。仿真时发现如果不做时钟树平衡,最高位转换会引入0.7LSB的误差。
最终的测试脚本用Python做了自动化处理,核心是FFT分析:
npts = 8192 hanning = np.hanning(npts) spectrum = np.fft.fft(samples * hanning) enob = (np.sum(spectrum[1:npts//2]) - max(spectrum[1:npts//2])) / (npts/4 * noise_floor)这里用汉宁窗压制频谱泄露,实测在99.3MHz输入时依然保持9.82位有效精度。有个坑是必须等ADC完全建立后再取4096个周期以上的数据,否则ENOB计算结果会虚高0.3位左右。
整套设计跑下来,深有体会的是:SAR ADC本质上是个时序敏感的数字游戏,从建模时的理想参数到实际电路的时钟偏差补偿,每个环节都可能让性能断崖式下跌。不过看着实测曲线最终踩在9.8ENOB线上,感觉那些深夜调参的咖啡值回票价了。