【MAX10初体验】片内ADC的使用

作者: lucky88717
上传时间为: 2015-01-26 10:46 AM
2015-01-26
阅读:

一、片内ADC横向对比

      片内ADC,做单片机开发或者FPGA开发应该都不会陌生。单片机都会带有一个片内ADC,高端的FPGA由于高频工作发热太大,一般也会带有ADC用作芯片温度检测,多出来的通道,用户可以任意发挥。

       MAX10的片内ADC性能中规中矩,最大的亮点就是,面向低成本的FPGA也提供了片内ADC,屌丝大爱。

      下面列举了几款不同芯片的片内ADC的参数,供大家对比参考:


      MAX10 ADC物理特性(节选自datasheet):

MAX10 ADC结构(节选自datasheet)




二、MAX10 初体验——片内ADC的使用

        1.在IP Catalog里面搜索adc,双击打开,居然打开了Qsys。看来Altera的这个ADC跟nios血缘更近。不过不用担心,即便是nios也能把他的IO拉出来,最坏的情况就是自己写avalon总线的逻辑。

        由于我只想用逻辑完全控制,选择了ADC control core only,这个模式用户可以自由的控制转换通道。

          

         PS:当在设置时钟频率的时候,右侧有提示“ADC的时钟由PLL1或PLL3的C0驱动,由于ADC内核必须工作在1M下,ADC核内的分频器只能接受1M的整数倍时钟”。有的片子有两个ADC,必须使用adc对应的PLL驱动,否则实现会报错。

         2.在生成HDL之前,我们看一下IP核的IO,在右上侧点击block symbol,了解一下信号功能位宽及方向。

               

                     IP核接口信号功能,参见代码注释。

         3.生成HDL

            生成HDL后,将生成的synthesis目录里面的qip文件添加到工程中。qip文件为索引文件,quartus将根据索引路径获取综合仿真所需的文件。

         4.例化PLL

            打开PLL IP,设置C0输出为40M(对应ADC IP核中的时钟,ADC核将把此时钟分频到1M供采样使用),C1为80M。

            其中C1为用户逻辑用时钟,可根据实际情况设置。此时钟也需要提供给ADC核,以便与用户接口同时钟域。

        5.程序源码:

module adc_test(
input wire i_clk,
input wire i_rst_n,
output wire adc_valid,
output wire [4:0]adc_chnanel,
output wire [11:0]adc_data,
output wire clk80
);
wire clk40;
wire rst;   
wire locked;   

pll u_pll (
	.areset		(~i_rst_n ),
	.inclk0		(i_clk    ),
	.c0	        (clk40    ),//c0 for adc
	.c1         (clk80    ),//c1 for user logic
	.locked		(locked   )
);

assign rst = ~( i_rst_n & locked );

adc u0_adc (
	.clock_clk              (clk80       ), //user_clk
	.reset_sink_reset_n     (~rst        ), //user_reset_n
	.adc_pll_clock_clk      (clk40       ), //must use pll_c0
	.adc_pll_locked_export  (locked      ), //adc_pll_locked
	.response_valid         (adc_valid   ), //adc_valid
	.response_channel       (adc_chnanel ), //adc_chnanel
	.response_data          (adc_data    ), //adc_data
	.response_startofpacket (            ), //startofpacket
	.response_endofpacket   (            ), //endofpacket
	.command_valid          (1'b1        ), //command.valid
	.command_channel        (5'd7        ), //set output channel
	.command_startofpacket  (1'b0        ), //startofpacket
	.command_endofpacket    (1'b0        ), //endofpacket
	.command_ready          (   )  //ready to accept new command
);


endmodule

       5.sinaltap抓数:

         为了观测ADC转换的效果,通过调整10M08 Evaluation Kit 左下角的R94阻值,改变ADC的7通道输入电压,用万用表测量对应的FPGA IO输入电压为1.774V,转换结果显示为12‘d2176。

         

         参考电压为3.3V,当输入电压为1.774V时,对应ADC值应为(4096*1.774/3.3)-1=2200,与ADC转换值相差24.........我一点也不郁闷,毕竟我那万用表精度有限,另外PCB布线也不是特别讲究,况且板上的3.3V与数字电路混用抖动较大。总的来说结果还是比较准确的。


三、个人感受

        1.在ADC的IP核中选择需要用到的ADC通道,综合后FPGA将把对应IO自动设置为模拟输入,不需要用户添加管脚约束。

        2.ADC单通道可以达到1M,多通道只能共享一个转换器,所以当开启多个通道时,上述代码用户需要根据command_ready状态,下发通道切换命令(command_channel)来控制转换器对哪个通道的模拟输入进行转换。

3.即使IP核为Qsys内的IP,依然可以hdl直接例化,不一定非要上nios。即便是avalone接口,依然可以通过hdl来控制。哪怕用了Qsys的模块间连线功能,我们依旧可以将需要引出的信号设置为IO拉出Qsys。


后续将继续测评User Flash和DSP……

全部评论 ()
条评论
写评论

创建讨论帖子

登录 后参与评论
系统提示