安路SparkRoad开发板测评(4) ADC IP的使用
[复制链接]
EG4S20内部带了一个ADC,需要以IP的形式调用。FPGA IP核就当作一个积木来用,和自己编写的逻辑连起来就是了。
在TD的Tools菜单上选择“IP Generator”,出现对话框后选择新建IP核,然后给IP取一个名称(对应生成的Verilog文件名),确定后出现IP选择对话框,找到ADC
双击鼠标选择它,出现如下的配置界面:
紫色框代表硬件ADC模块,左边是输入,右边是输出。看名称能猜到信号都是什么意思了:eoc和soc分别是End of Conversion与Start of Conversion的意思,pd应该是Power Down吧。输出数据12-bit,只有一路,因此8个模拟输入通道需要选择,在方框中打勾表示使能对应的模拟输入通道,s[2:0] 决定转换哪一个模拟输入。
再填写一下Component name (需要和之前填写的IP名称一致,我觉是得多此一举),点OK按钮后将生成.v的文件。生成IP的一系列对话框都没有回退功能,界面缺乏说明,不清楚的要另找文档看。
生成的ADC模块是这样:
上面代码中的 EG_PHY_ADC就当作一个黑盒子好了。新工程中若没有其它模块,它就自动成为顶层,可以直接综合,出来结果:
注意,没有使用LE资源,也就是不需要额外的逻辑,ADC模块的引脚直接连到FPGA管脚了。现在没有写约束,,管脚是自动分配的。
注意,模拟输入引脚并不在I/O口列表中,也不能在I/O约束对话框中指定。那么,怎么指派模拟输入引脚呢?很可能模拟输入功能是固定的引脚,因为已经有8个输入通道了,从哪个输入模拟信号是八选一……去SparkRoad板子的电路图上找找线索。
果然,ADC的8个输入通道是引脚名称标住了的,跟MCU的ADC输入类似。
根据电路图看来,在SparkRoad上只有通道1~7可以用。
为了把ADC转换的值呈现出来,我要写一个12位数据转换成十进制,驱动LED数码管的逻辑。在没有CPU的情况下,进行这个转换就要费些工夫了,需要做三次除以10的整数运算。TD里面提供了除法器的IP可以拿来用,不过我不打算用除法,我想就用循环减法来做。
我的思路是这样的:9999以内的数,先与1000比较,若大于等于1000,就减去1000,千位计数加一,循环;然后与100比较,同理操作百位数字加一,循环;最后与10比较,直到小于10就转换完成了,以时钟周期为代价省去除法器。
再编写一个LED数码管扫描驱动就简单了,最后写一个顶层,将几个模块连起来工作:
ADC转换我试着给一个脉冲当soc信号,看看结果的情况。数据输出如果是锁存的话,经过我的十进制转换逻辑给扫描显示,稳定的数字就是结果。
我选择的通道1输入。引脚悬空时,数字会随机跳动。和GND短路,显示数字就稳定在0了。
接一节旧电池测量,读数在1642附近跳动(1643,1641都容易看到,也能看到1640,1644出现)
我用万用表测电池电压显示1.321V,测量板子上ADC_REF电压(C18两端)显示3.291V,则换算ADC转换理论值是1644,差不多。
最后测一下ADC转换的时间。将ADC的soc和eoc以及ADC用的时钟引到FPGA脚上接示波器。ADC时钟采用24MHz分频后的1.5MHz. 我的示波器只有两通道,因此一个通道测soc并触发,另一个通道先测时钟保存为参考,再测eoc.
可见转换过程用了15个时钟周期的样子。
FPGA内带的ADC和MCU带的是类似的,不同点在于FPGA里面直接操作ADC的控制信号,而MCU是读写总线上的ADC控制器的寄存器,是间接操作。
|