0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA上可以用一个比较器实现ADC的功能?1

jf_78858299 来源:硬禾学堂 作者:苏老师 2023-04-25 11:18 次阅读

使用的平台:

图片

多数FPGA芯片上没有ADC的功能,而一些应用则需要用到ADC对一些模拟信号,比如直流电压等进行量化,有没有特别简单、低成本的实现方法呢?

在要求转换速率不高的情况下,完全可以借助一颗高速比较器(成本只有几毛钱)来实现对模拟信号的量化,Lattice的官网上一篇文章就介绍了如何制作一个简易的Sigma Delta ADC,如果FPGA能够提供LVDS的接口,连外部的高速比较器都可以省掉。由于我们的小脚丫FPGA核心模块在设计的时候没有考虑到LVDS的应用场景,所以还是需要搭配一个高速的比较器来实现Lattice官网上推荐的简易Sigma Delta ADC的功能。

让小脚丫FPGA通过锁相环PLL运行于120MHz的主时钟(还可以更高,提速到240MHz、360MHz都应该没有问题),测试1KHz以内的模拟信号是没有问题的。

Lattice的官网上就可以下载到简易Sigma Delta ADC的Verilog源代码,可以非常方便地用在其它品牌、其它系列的FPGA上。

下面的截图就是采用120MHz的主时钟实现的对1KHz模拟信号的采样,并通过DDS/DAC输出,口袋仪器M2000采集并显示的模拟信号波形。

图片

M2000口袋仪器显示的1KHz的波形

工作原理

详细的工作原理介绍可以参考项目https://www.eetree.cn/project/detail/255 及项目页面中的参考资料,在这里以几幅图片来示例一下。

图片

简易Sigma Delta ADC的工作原理

图片

直接连接 - 被测模拟信号的幅度范围为0-3.3V

图片

通过电阻分压网络输入,并在比较器+端提供参考电压,则被采集模拟信号的电压变化范围可以扩展

图片

简易Sigma Delta ADC的性能与逻辑电路的工作频率

图片

在不同的FPGA平台上消耗的逻辑资源

以下就是我们的电赛综合训练板上简易Sigma Delta ADC部分的电路连接

图片

核心代码:

顶层调用代码:

wire [7:0] sd_adc_out; // sigma delta adc data output


wire sample_rdy;    // flag for adc conversion


ADC_top my_adc(.clk_in(clk_hs),.rstn(1'b1),.digital_out(sd_adc_out), .analog_cmp(comp_in),.analog_out(ad_pwm),.sample_rdy(sample_rdy));


assign dac_data = sd_adc_out;
assign dac_clk = clk_hs; //120MHz generated by PLL

Sigma Delta ADC顶层程序

//*********************************************************************
//
//  ADC Top Level Module
//
//*********************************************************************


module ADC_top (
  clk_in,
  rstn,
  digital_out,
  analog_cmp,  
  analog_out,
  sample_rdy);


parameter 
ADC_WIDTH = 8,              // ADC Convertor Bit Precision
ACCUM_BITS = 10,            // 2^ACCUM_BITS is decimation rate of accumulator
LPF_DEPTH_BITS = 3,         // 2^LPF_DEPTH_BITS is decimation rate of averager
INPUT_TOPOLOGY = 1;         // 0: DIRECT: Analog input directly connected to + input of comparitor
                            // 1: NETWORK:Analog input connected through R divider to - input of comp.


//input ports
input  clk_in;        // 62.5Mhz on Control Demo board
input  rstn;   
input  analog_cmp;      // from LVDS buffer or external comparitor


//output ports
output  analog_out;         // feedback to RC network
output  sample_rdy;
output [7:0] digital_out;   // connected to LED field on control demo bd.



//**********************************************************************
//
//  Internal Wire & Reg Signals
//
//**********************************************************************
wire              clk;
wire              analog_out_i;
wire              sample_rdy_i;
wire [ADC_WIDTH-1:0]      digital_out_i;
wire [ADC_WIDTH-1:0]      digital_out_abs;




assign clk = clk_in;


//***********************************************************************
//
//  SSD ADC using onboard LVDS buffer or external comparitor
//
//***********************************************************************
sigmadelta_adc #(
  .ADC_WIDTH(ADC_WIDTH),
  .ACCUM_BITS(ACCUM_BITS),
  .LPF_DEPTH_BITS(LPF_DEPTH_BITS)
  )
SSD_ADC(
  .clk(clk),
  .rstn(rstn),
  .analog_cmp(analog_cmp),
  .digital_out(digital_out_i),
  .analog_out(analog_out_i),
  .sample_rdy(sample_rdy_i)
  );


assign digital_out_abs = INPUT_TOPOLOGY ? ~digital_out_i : digital_out_i;  


//***********************************************************************
//
//  output assignments
//
//***********************************************************************


assign digital_out   = ~digital_out_abs;   // invert bits for LED display 
assign analog_out    =  analog_out_i;
assign sample_rdy    =  sample_rdy_i;


endmodule

Sigma Delta ADC主程序

//*********************************************************************
//
//  SSD Top Level Module
//
//*********************************************************************


module sigmadelta_adc (
  clk,                    
  rstn,                   
  digital_out,            
  analog_cmp,              
  analog_out,             
  sample_rdy);            


parameter 
ADC_WIDTH = 8,              // ADC Convertor Bit Precision
ACCUM_BITS = 10,            // 2^ACCUM_BITS is decimation rate of accumulator
LPF_DEPTH_BITS = 3;         // 2^LPF_DEPTH_BITS is decimation rate of averager


//input ports
input  clk;                            // sample rate clock
input  rstn;                           // async reset, asserted low
input  analog_cmp ;                    // input from LVDS buffer (comparitor)


//output ports
output  analog_out;                     // feedback to comparitor input RC circuit
output  sample_rdy;                     // digital_out is ready
output [ADC_WIDTH-1:0]  digital_out;    // digital output word of ADC


//**********************************************************************
//
//  Internal Wire & Reg Signals
//
//**********************************************************************
reg                         delta;          // captured comparitor output
reg [ACCUM_BITS-1:0]      sigma;          // running accumulator value
reg [ADC_WIDTH-1:0]          accum;          // latched accumulator value
reg [ACCUM_BITS-1:0]      counter;        // decimation counter for accumulator
reg              rollover;       // decimation counter terminal count
reg              accum_rdy;      // latched accumulator value 'ready' 


//***********************************************************************
//
//  SSD 'Analog' Input - PWM
//
//  External Comparator Generates High/Low Value
//
//***********************************************************************


always @ (posedge clk)
begin
    delta <= analog_cmp;        // capture comparitor output
end


assign analog_out = delta;      // feedback to comparitor LPF


//***********************************************************************
//
//  Accumulator Stage
//
//  Adds PWM positive pulses over accumulator period
//
//***********************************************************************


always @ (posedge clk or negedge rstn)
begin
  if( ~rstn ) 
    begin
    sigma       <= 0;
    accum       <= 0;
    accum_rdy   <= 0;
    end else begin
        if (rollover) begin
            // latch top ADC_WIDTH bits of sigma accumulator (drop LSBs)
            accum <= sigma[ACCUM_BITS-1:ACCUM_BITS-ADC_WIDTH];
            sigma <= delta;         // reset accumulator, prime with current delta value
        end else begin
            if (&sigma != 1'b1)         // if not saturated
                sigma <= sigma + delta; // accumulate 
        end
        accum_rdy <= rollover;     // latch 'rdy' (to align with accum)
    end
end


//***********************************************************************
//
//  Box filter Average
//
//  Acts as simple decimating Low-Pass Filter
//
//***********************************************************************


box_ave #(
    .ADC_WIDTH(ADC_WIDTH),
    .LPF_DEPTH_BITS(LPF_DEPTH_BITS))
box_ave (
    .clk(clk),
    .rstn(rstn),
    .sample(accum_rdy),
    .raw_data_in(accum),
    .ave_data_out(digital_out),
    .data_out_valid(sample_rdy)
);


//************************************************************************
//
// Sample Control - Accumulator Timing
//  
//************************************************************************


always @(posedge clk or negedge rstn)
begin
  if( ~rstn ) begin
    counter <= 0;
    rollover <= 0;
    end
  else begin
    counter <= counter + 1;       // running count
    rollover <= &counter;         // assert 'rollover' when counter is all 1's
    end
end
endmodule
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1625

    文章

    21664

    浏览量

    601727
  • 芯片
    +关注

    关注

    453

    文章

    50378

    浏览量

    421706
  • adc
    adc
    +关注

    关注

    98

    文章

    6430

    浏览量

    544056
收藏 人收藏

    评论

    相关推荐

    fpga开发板使用教程之在K7Ibert实现基本的GTX测试

    测试,而且基本可以达到不用敲代码就可以完成测试的目的。 下面按步骤,实现。重点的地方我
    发表于 12-31 15:36 7695次阅读

    ADC实现IO挂多个按键

    有时候做设计时,我们会遇到外部按键比较多,IO口不够用的情况。这时大部分人会考虑通过其它芯片扩展IO,或者直接换一个IO口足够的MCU。其实,还有方法可以
    发表于 09-01 13:25 2907次阅读

    如何用STM32F407实现可编程的模拟比较功能

    STM32F407没有独立的模拟比较端口,如何能实现可编程的模拟比较
    发表于 11-28 14:00

    STM32F303VCT6比较只有三可以用

    STM32F303VCT6共有7比较,为何只有COMP1、COMP2、COMP7这三可以用
    发表于 02-13 07:13

    怎么利用FPGA和CPLD数字逻辑实现ADC

    数字系统的设计人员擅长在其印制电路板FPGA和CPLD将各种处理、存储和标准的功能元件粘
    发表于 08-19 06:15

    如何利用FPGA实现高频率ADC

    数字系统的设计人员擅长在其印制电路板FPGA和CPLD将各种处理、存储和标准的功能元件粘
    发表于 09-19 06:18

    可以用STM32实现什么?为什么使用STM32而不是8051

    你问,如何系统地入门学习STM32?本身就是错误的问题。假如你会使用8051 , 会写C语言,那么STM32本身并不需要刻意的学习。你要考虑的是, 我可以用STM32实现
    发表于 02-25 06:43

    matlab来实现fpga功能的设计

    matlab来实现fpga功能的设计 摘要:System Generator for DSP是Xilinx公司开发的基于Matlab的DSP开发工具?熗?时也是
    发表于 01-16 18:10 1.1w次阅读
    <b class='flag-5'>用</b>matlab来<b class='flag-5'>实现</b><b class='flag-5'>fpga</b><b class='flag-5'>功能</b>的设计

    基于FPGA和CPLD数字逻辑实现ADC技术

    基于FPGA和CPLD数字逻辑实现ADC技术 数字系统的设计人员擅长在其印制电路板FPGA
    发表于 05-25 09:39 1428次阅读
    基于<b class='flag-5'>FPGA</b>和CPLD数字逻辑<b class='flag-5'>实现</b><b class='flag-5'>ADC</b>技术

    基于fpga和cpld低频/最小逻辑ADC实现

    数字系统的设计人员擅长在其印制电路板FPGA和CPLD将各种处理、存储和标准的功能元件粘
    发表于 04-26 11:53 1328次阅读
    基于<b class='flag-5'>fpga</b>和cpld低频/最小逻辑<b class='flag-5'>ADC</b><b class='flag-5'>实现</b>

    编写可以用GRUB来引导的简单x86内核

    我们将从零开始,动手编写可以用GRUB来引导的简单x86内核,该内核会在屏幕打印条信息,然后——挂起!
    的头像 发表于 01-21 09:12 7549次阅读

    如何制作简易的Sigma Delta ADC

    本文为备战电赛的案例之,涉及到的知识技能: FPGA的使用 ADC的原理及构成 PWM的产生 比较的应用 数字滤波
    的头像 发表于 04-01 10:27 4367次阅读
    如何制作<b class='flag-5'>一</b><b class='flag-5'>个</b>简易的Sigma Delta <b class='flag-5'>ADC</b>?

    FPGA搭配3电阻、1电容制作的1bit SDR接收机

    搭配3电阻、1电容制作的1bit SDR接收机,接上喇叭,可以收听中、长波电台,连ADC都没
    的头像 发表于 11-09 09:15 4962次阅读

    FPGA可以用比较实现ADC功能?2

    多数FPGA芯片没有ADC功能,而些应用则需要用到ADC
    的头像 发表于 04-25 11:19 1128次阅读

    文看懂电感可以用大的替换小的吗

    需要尽快更换电感。那么,电路中的电感可不可以用大电感替换小电感呢?今天我们就来讨论下这个问题。 是不是可以用大电感来替换小电感,我们还是要考虑多个因素: 1、封装大小
    的头像 发表于 01-13 21:56 750次阅读