zoukankan      html  css  js  c++  java
  • 数字信号处理专题(1)——DDS函数发生器环路Demo

    一、前言

      会FPGA硬件描述语言、设计思想和接口协议,掌握些基本的算法是非常重要的,因此开设本专题探讨些基于AD DA数字信号处理系统的一些简单算法,在数字通信 信号分析与检测等领域都会或多或少有应用。我们还是从老生常谈的DDS函数发生器开始,讲解DAC ADC基本使用以及DDS算法原理与设计方式。

    二、设计预期

          功能:基于ROM的频率可调DDS正弦函数发生器

      DAC ADC型号与设计参数:DAC为AD9708,更新速率125MSPS,精度8bit;ADC为AD9280,采样率32MSPS,精度8bit。由于ADC采样率限制,设计使用32MHZ频率时钟更新与采样数据,并将ROM深度定义为1024.

      验证手段:MATLAB产生正弦函数,经过8bit量化后存储在ROM中,数据经过DAC 电缆 ADC环回到FPGA,ILA抓取ADC接收数据波形,观察对比发送与接收数据是否相近。

    三、DDS原理

      这里只介绍DDS的基本思想,关于详细原理,请参考:【图文】DDS原理_百度文库 https://wenku.baidu.com/view/11cfbf85a0116c175f0e4818.html 

      实际上,DDS的核心就是将正弦或余弦函数存储在ROM中,利用相位累加特性通过采用不同的步长对ROM寻址的方式产生频率可调正弦波。另外需要注意产生信号的频率范围要满足奈奎斯特采样定理,该定理支持若想无失真恢复原始信号,采样频率必须大于等于信号最高频率成分的2倍。反过来说:产生信号的最高频率小于等于采样率的1/2.采样频率即为FPGA是时钟频率。为防止信号混叠,一般取最高频率成分的1/3.

     四、MATLAB产生正弦序列.coe文件及ROM初始化

       MATLAB产生频率为1/2*pi标准正弦序列。验证无误后,在VIVADO中调用Block Memory Generator IP核,配置为单口ROM,使用刚才产生的系数文件初始化ROM地址数据。

    五、DAC ADC驱动

      该设计使用的DAC ADC均为为低速并口转换芯片,无需配置,只要FPGA给出时钟信号,并输出/入并行数据即可。根据AD9708 datasheet时序图,其在时钟上升沿采样,故FPGA在输出时钟下降沿更新数据可满足建立与保持时间要求。ADC同样上升沿开始更新数据,接收端在时钟是上升沿采集数据,这样每一时钟周期可以采到上一拍送出的数据。

    六、函数发生器及测试工程设计

     1 `timescale 1ns / 1ps
     2 
     3 module sin_generator#(parameter FCW_W = 16,
     4                                 DAC_W = 8)
     5  (
     6     input               clk,//DAC采样时钟 由PLL产生
     7     input               rst_n,
     8 
     9     input  [FCW_W-1:0]  fcw,
    10     output [DAC_W-1:0]  dac_data,
    11     output              dac_clk
    12     );
    13 
    14 reg [ (FCW_W-1):0]  sum     ;
    15 wire [9:0] addra;
    16 //reg [9:0] addra;//地址测试信号
    17 wire ena;
    18 wire [7:0] douta;
    19 
    20   //相位累加器
    21   //时钟下降沿产生数据 DAC上升沿采样
    22 always @(negedge clk or negedge rst_n )begin 
    23     if(rst_n==0) begin
    24         sum <= (0)  ;
    25     end
    26     else begin
    27         sum <= (sum+fcw)  ;
    28     end 
    29 end
    30 
    31 assign addra = sum[FCW_W-1-:10];
    32 
    33 //rom地址测试
    34 /*always @(posedge clk or negedge rst_n )begin 
    35     if(rst_n==0) begin
    36         addra <= (0)  ;
    37     end
    38     else begin
    39         addra <= (addra+1)  ;
    40     end 
    41 end*/
    42 
    43 
    44 blk_mem_gen_0 u_bram (
    45   .clka(clk),    // input wire clka
    46   .ena(ena),      // input wire ena
    47   .addra(addra),  // input wire [9 : 0] addra
    48   .douta(douta)  // output wire [7 : 0] douta
    49 );
    50 assign ena = 1'b1;
    51 //输出信号
    52 assign dac_data = douta;
    53 assign dac_clk = ~clk;
    54 
    55 endmodule
    sin_generator

      函数发生器模块由输入端口fcw数值确定频率控制字。测试工程顶层包括差分时钟转单端时钟原语,用于产生DAC ADC时钟的PLL 函数发生器模块,生成特定频率控制字的VIO IP核,还有接收端ADC数据采样逻辑以及ILA 调试IP核。

     1 `timescale 1ns / 1ps
     2 
     3 
     4 module DDS_Demo_top
     5 #(parameter AD_DA_W = 8)
     6     (
     7     input sys_clk_p,
     8     input sys_clk_n,
     9     input rst_n,
    10 
    11     output [AD_DA_W-1:0] DAC_data,
    12     output DAC_clk,
    13 
    14     input [AD_DA_W-1:0] ADC_data,
    15     output ADC_clk
    16     );
    17 
    18 localparam FCW_W = 16;
    19 
    20 wire sys_clk_ibufg;
    21 wire clk_dac,clk_adc;
    22 reg [ (AD_DA_W-1):0]  data_ad     ;
    23 
    24 wire [FCW_W-1 : 0] probe_out0;
    25 wire [AD_DA_W*2-1:0] probe0;
    26 
    27 //ADC接口信号
    28 //ADC在时钟上升沿后送出数据,FPGA下一个上升沿采样
    29 assign ADC_clk = clk_adc;
    30 
    31 always @(posedge clk_adc or negedge rst_n )begin 
    32     if(rst_n==0) begin
    33         data_ad <= (0)  ;
    34     end
    35     else begin
    36         data_ad <= (ADC_data)  ;
    37     end 
    38 end
    39 
    40 
    41 /***************************************子模块例化***************************************/
    42 IBUFGDS #
    43 (
    44 .DIFF_TERM ("FALSE"),
    45 .IBUF_LOW_PWR ("FALSE")
    46 )
    47 u_ibufg_sys_clk
    48 (
    49 .I (sys_clk_p),
    50 .IB (sys_clk_n),
    51 .O (sys_clk_ibufg)
    52 );
    53 
    54 clk_wiz_0 u_pll
    55    (
    56     // Clock out ports
    57     .clk_out1(clk_dac),         // output clk_out1
    58     .clk_out2(clk_adc),         // output clk_out2
    59     // Status and control signals
    60     .resetn(rst_n),             // input resetn
    61     .locked(),                  // output locked
    62    // Clock in ports
    63     .clk_in1(sys_clk_ibufg));   // input clk_in1
    64 
    65 sin_generator#(.FCW_W(FCW_W),
    66                .DAC_W(AD_DA_W))
    67 u_sin_gen
    68  (
    69     .clk      (clk_dac)  ,//DAC采样时钟 由PLL产生
    70     .rst_n    (rst_n)  ,
    71     .fcw      (probe_out0)  ,
    72     .dac_data (DAC_data)  ,
    73     .dac_clk  (DAC_clk)  //由clk_dac产生
    74     );
    75 
    76 //debug cores
    77 vio_0 u_vio (
    78   .clk(clk_dac),                // input wire clk
    79   .probe_out0(probe_out0)  // output wire [15 : 0] probe_out0
    80 );
    81 
    82 ila_0 u_ila (
    83     .clk(clk_adc), // input wire clk
    84     .probe0(probe0) // input wire [15:0] probe0
    85 );
    86 
    87 assign probe0[7:0] = DAC_data;
    88 assign probe0[15:8] = ADC_data;
    89 
    90 endmodule
    DDS_Demo

      最后添加引脚约束文件:

     1 #################################clock && reset###############################################
     2 create_clock -period 5 [get_ports sys_clk_p]
     3 set_property PACKAGE_PIN R4 [get_ports {sys_clk_p}]
     4 set_property IOSTANDARD DIFF_SSTL15 [get_ports {sys_clk_p}]
     5 
     6 set_property PACKAGE_PIN T6 [get_ports rst_n]
     7 set_property IOSTANDARD LVCMOS15 [get_ports rst_n]
     8 
     9 #####################DAC PIN connect J4 expansion interface##########################
    10 set_property PACKAGE_PIN H14 [get_ports {DAC_clk}]
    11 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_clk}]
    12 
    13 set_property PACKAGE_PIN J14 [get_ports {DAC_data[7]}]
    14 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[7]}]
    15 set_property PACKAGE_PIN H15 [get_ports {DAC_data[6]}]
    16 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[6]}]
    17 set_property PACKAGE_PIN J15 [get_ports {DAC_data[5]}]
    18 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[5]}]
    19 set_property PACKAGE_PIN G13 [get_ports {DAC_data[4]}]
    20 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[4]}]
    21 set_property PACKAGE_PIN H13 [get_ports {DAC_data[3]}]
    22 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[3]}]
    23 set_property PACKAGE_PIN J21 [get_ports {DAC_data[2]}]
    24 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[2]}]
    25 set_property PACKAGE_PIN J20 [get_ports {DAC_data[1]}]
    26 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[1]}]
    27 set_property PACKAGE_PIN G16 [get_ports {DAC_data[0]}]
    28 set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[0]}]
    29 
    30 #####################ADC PIN connect J4 expansion interface##########################
    31 
    32 set_property PACKAGE_PIN D22 [get_ports {ADC_clk}]
    33 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_clk}]
    34 
    35 set_property PACKAGE_PIN G21 [get_ports {ADC_data[7]}]
    36 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[7]}]
    37 set_property PACKAGE_PIN G22 [get_ports {ADC_data[6]}]
    38 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[6]}]
    39 set_property PACKAGE_PIN H20 [get_ports {ADC_data[5]}]
    40 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[5]}]
    41 set_property PACKAGE_PIN G20 [get_ports {ADC_data[4]}]
    42 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[4]}]
    43 set_property PACKAGE_PIN J22 [get_ports {ADC_data[3]}]
    44 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[3]}]
    45 set_property PACKAGE_PIN H22 [get_ports {ADC_data[2]}]
    46 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[2]}]
    47 set_property PACKAGE_PIN K21 [get_ports {ADC_data[1]}]
    48 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[1]}]
    49 set_property PACKAGE_PIN K22 [get_ports {ADC_data[0]}]
    50 set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[0]}]
    clk_pin

    七、实验结果分析

      依据之前的参数和DDS信号频率公式,所生成正弦函数频率最好在32/2^16~32/3MHZ之内,使用VIO改变频率控制字数值,观察ILA抓取的发送与接收数据模拟形式波形。任意给出三组频率范围内波形,频率依次由低到高。

      总体来讲还是比较简单。搭建好DAC ADC环路,后面可以验证些滤波 同步算法,或者做些数字频率计、示波器之类的实用设计。

  • 相关阅读:
    git一个项目导入MyEclipse上传到github
    python之列表练习
    python之元组
    python之列表
    python之替换文件内容和修改某行内容
    python之查询员工名单(读取文件,查询文件内容)
    js:函数一
    8.1(java学习笔记)注解(Annotation)
    8.2(java学习笔记)反射
    7.4 (java学习笔记)网络编程之TCP
  • 原文地址:https://www.cnblogs.com/moluoqishi/p/9396734.html
Copyright © 2011-2022 走看看