这一篇在干嘛?
很多同学以为 FPGA 只会处理”0 和 1”,但 EG4S20 的芯片里其实内置了一个 ADC(Analog-to-Digital Converter,模数转换器),可以把外部连续变化的电压变成 FPGA 能算的数字。这一篇我们就把它拆开看:它长什么样、能测多大电压、怎么控制它采样、结果从哪里读出来,以及官方手册里反复强调的那些”坑”。
先弄懂三个名词:ADC、SAR、GPIO
手册开头给了三个缩写,先把它们说人话:
- ADC(Analog-to-Digital Converter,模数转换器):把”连续的电压值”翻译成”数字”的器件。比如 1.23V 对应某个数,2.5V 对应另一个数。
- SAR(Successive Approximation Register,逐次逼近):ADC 内部常用的一种工作方式,像”猜数字”一样一位一位逼近真实电压。
- GPIO(General Purpose Input Output,通用输入/输出):芯片上最普通的引脚,既能输入也能输出。
记住 ADC 和 SAR 这两个词就够了,后面提到”SAR 型 ADC”你就知道它是用逐次逼近的方式做转换。
片上 ADC 长什么样:8 通道 + 引脚复用
EG4S20 这类 EAGLE 系列芯片内嵌了 1 个 8 通道的 SAR 型 ADC 模块。它的结构可以看下面这张模块图:

这里有两个关键点,零基础同学一定要理解:
- 通道和普通 IO 是”复用”的。这 8 个 ADC 通道的输入引脚,平时就是普通 GPIO。你不用 ADC 的时候,它们就是普通 IO;用了 ADC,对应引脚才切换成模拟输入。每个通道的复用设置互相独立,比如只用通道 0,剩下 7 个引脚照样可以当普通 IO 用。
- 用 ADC 时对供电有要求:相关 BANK 的 VCCIO 电压不能低于 ADC 的模拟电源电压。这一点在硬件设计阶段就要注意,后面讲注意事项时还会再提。
性能参数一张表:它到底能测多大电压
下面这张表是手册给出的 ADC 性能汇总,是全篇最核心的数据,建议对照记忆:
| 参数 | 性能 |
|---|---|
| 工作电压 | 3.3V 模拟电源(VDDA)和 3.3V 数字电源(VDDD) |
| 最高采样速率 | 1MHz |
| 通道数 | 8 |
| 采样范围 | 0.1×VREF ~ 0.9×VREF |
| 动态性能 | >50dB SFDR,>45dB SINAD |
| 线性度性能 | INL<1 LSB,DNL<1 LSB(8bit 精度) |
| 最高时钟频率 | 16MHz |
| ADC 参考电压 VREF | 0.5~1.0×VDDA |
| 输出数字位宽 | 12bit |
| 有效精度 | 8bit |
几个容易困惑的地方,帮你翻译一下:
- “输出 12bit,但有效精度只有 8bit”:芯片吐出来的结果是 12 位数字,但真正可信、能保证线性度的是高 8 位。别指望 12 位每一位都精确。
- “采样范围 0.1×VREF ~ 0.9×VREF”:能正常测量的电压不是从 0 到满量程,而是参考电压 VREF 的 10% 到 90% 这个区间。低于或高于这个区间的信号,读数就不可靠了。
- “最高时钟 16MHz、最高采样 1MHz”:给 ADC 的时钟不能超过 16MHz,采样动作最快每秒 100 万次,超过就会出错。
VREF 是 ADC 的"尺子",必须又准又干净
手册专门强调:ADC 的精度和参考电压关系非常紧密。板上要给 ADC 提供非常准确、干净的 VREF,精度要控制在 VDDA ±0.2% 以内。尺子不准,量出来的数全都不准——这是硬件问题,写再多代码也救不回来。
VREF 尽量设成 1.0×VDDA
VREF 的可接受范围是 0.5×VDDA ~ 1.0×VDDA,而输入信号范围是由 VREF 决定的。VREF 越高,能测的电压区间越大,所以建议直接把 VREF 设成 1.0×VDDA(即 3.3V),把量程”用满”。
数字接口:6 个端口看懂 ADC 怎么”对话”
FPGA 里不能像操作电脑软件一样”点按钮”,一切靠信号握手。ADC 模块对外就 6 个端口,一一记住它们:
| 内部端口名 | 方向 | 位宽/bit | 说明 |
|---|---|---|---|
| clk | input | 1 | ADC 工作时钟,fmax=16MHz |
| pd | input | 1 | 低功耗掉电模式控制 |
| s | input | 3 | 通道选择信号(3 位正好选 8 个通道) |
| soc | input | 1 | 采样使能(Start of Conversion),高有效 |
| eoc | output | 1 | 转换完成标志(End of Conversion),高有效 |
| dout | output | 12 | 对应通道的转换结果 |
工作流程用一句话概括:你用 s 选好通道,给 soc 一个高电平”下令采样”,ADC 转换完成后拉高 eoc 通知你,此时去 dout 上读 12 位结果即可。
pd(power down)平时接 0,让 ADC 正常工作;它还有一个特殊用法,在注意事项里会讲到。
IP 例化:把 ADC 加进你的工程
在 TD 软件里,通过 IP generate 的方法就能把这个 ADC 模块生成到自己的工程里,不需要手写它的内部逻辑。模块的 Verilog 接口长这样:
module EG_PHY_ADC(clk, pd, s, soc, eoc, dout);
input clk; // 时钟
input pd; // 掉电控制,1'b0 正常工作
input [2:0] s; // 通道选择
input soc; // 开始转换
output eoc; // 转换结束
output [11:0] dout; // 12bit 转换结果
parameter CHO = "DISABLE";
parameter CH1 = "DISABLE";
// ...CH2 ~ CH7 同理
parameter VREF = "DISABLE";
endmodule除了端口,模块还有一组 参数(parameter),用来告诉工具”你要用哪些资源”:
| 参数 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
| VREF | ”DISABLE” / “ENABLE" | "DISABLE” | 参考电压使能 |
| CH0 ~ CH7 | ”DISABLE” / “ENABLE" | "DISABLE” | 通道 0 ~ 7 使能 |
也就是说,例化时把你要用的通道参数改成 "ENABLE",其他保持 "DISABLE" 就行。比如只用通道 0 和通道 1,就只把 CH0、CH1 打开。在 TD 里操作的样子可以参考下图:

采样控制时序:soc 和 eoc 的”一问一答”
最后看怎么驱动它采样。ADC 的采样控制时序如下:

读时序图的思路很简单,就是一场”问答”:
- 先把通道号放到 3 位
s信号上; - 拉高
soc(高有效),相当于喊一声”开始采样”; - ADC 内部做逐次逼近转换,期间你别动
s; - 转换完成后
eoc输出高电平,说一声”做完了”; - 此时
dout上的 12 位数据就是结果,读走即可。
写状态机时把 soc/eoc 当作标准握手
实际工程里通常用一个小的状态机:IDLE → 置 s、拉 soc → 等 eoc → 锁存 dout → 回 IDLE。这个”发令—等待—取结果”的模式和很多外设通用,学会一次处处能用。
注意事项:三个最容易翻车的地方
手册虽然短,注意事项却值得单独背下来:
1. 采样间隔别拉太大。 建议 SOC 的采样间隔小于 10us,也就是采样频率不要低于 100kHz。这不是”越快越好”的建议,而是这个 ADC 的工作特性决定的。
2. 真要大间隔采样,先”叫醒”ADC。 如果你确实需要很长间隔才采一次样,必须在 SOC 到来 5 个时钟周期之前,先把 pd 脚拉高一下,然后再进行采样。忘了这一步,采出来的数据可能就是错的。
大间隔采样忘记拉 PD 是最隐蔽的坑
低频采样时程序”看起来能跑”,数据却莫名不对,八成就是漏了”SOC 前 5 个时钟周期拉高 PD”这一步。把这个动作直接写进你的采样状态机里,别靠手动时序。
3. 电源和布局要给 ADC 让路。 除了前面说的 VREF 要准、要干净,使用 ADC 时还要尽量避免使用与 ADC IO 相同 BANK 的数字 IO,以减小数字开关噪声对模拟采样行的干扰;相关 BANK 的 VCCIO 电压也不能低于 ADC 模拟电源电压。
一句话总结硬件侧要点
VREF = 1.0×VDDA、VREF 精度 ±0.2%、ADC 所在 BANK 少放数字 IO、VCCIO ≥ 模拟电源——这四条写进你的硬件检查清单。
回顾:这一篇你学到了什么
- EG4S20 内置 1 个 8 通道 SAR 型 ADC,通道引脚与普通 IO 复用,不用时可以照常当 GPIO。
- 性能上:3.3V 供电、最高 16MHz 时钟、最高 1MHz 采样率、输出 12bit 但有效精度 8bit、量程为 0.1×VREF ~ 0.9×VREF。
- 接口上:
s选通道、soc启动、eoc通知完成、dout给出 12 位结果;例化时通过 CH0~CH7 和 VREF 参数使能所需资源。 - 避坑上:采样间隔小于 10us;大间隔采样要在 SOC 前 5 个时钟周期拉高 PD;VREF 要准(±0.2%)、要设成 1.0×VDDA;ADC 所在 BANK 尽量别跑数字 IO。
自测 1:我想测一个最高 3.0V 的信号,VREF 设成 1.0×VDDA(3.3V)够用吗?
够。此时量程是 0.1×3.3V = 0.33V 到 0.9×3.3V = 2.97V……注意 3.0V 已经略微超出 0.9×VREF 的上限,严格来说不能可靠测量,需要衰减信号或调整方案。这道题就是提醒你:量程上限是 0.9×VREF,不是 VREF 本身。
自测 2:我的应用每 1ms 才采一次样(1kHz),SOC 之前应该多做什么动作?
这属于大间隔采样(间隔远大于 10us),需要提前拉高
pd:在 SOC 到来 5 个时钟周期之前先拉高一下pd,再发起采样,否则结果不可靠。