数字信号处理专题(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同样上升沿开始更新数据,接收端在时钟是上升沿采集数据,这样每一时钟周期可以采到上一拍送出的数据。
六、函数发生器及测试工程设计
`timescale 1ns / 1ps module sin_generator#(parameter FCW_W = ,
DAC_W = )
(
input clk,//DAC采样时钟 由PLL产生
input rst_n, input [FCW_W-:] fcw,
output [DAC_W-:] dac_data,
output dac_clk
); reg [ (FCW_W-):] sum ;
wire [:] addra;
//reg [9:0] addra;//地址测试信号
wire ena;
wire [:] douta; //相位累加器
//时钟下降沿产生数据 DAC上升沿采样
always @(negedge clk or negedge rst_n )begin
if(rst_n==) begin
sum <= () ;
end
else begin
sum <= (sum+fcw) ;
end
end assign addra = sum[FCW_W--:]; //rom地址测试
/*always @(posedge clk or negedge rst_n )begin
if(rst_n==0) begin
addra <= (0) ;
end
else begin
addra <= (addra+1) ;
end
end*/ blk_mem_gen_0 u_bram (
.clka(clk), // input wire clka
.ena(ena), // input wire ena
.addra(addra), // input wire [9 : 0] addra
.douta(douta) // output wire [7 : 0] douta
);
assign ena = 'b1;
//输出信号
assign dac_data = douta;
assign dac_clk = ~clk; endmodule
sin_generator
函数发生器模块由输入端口fcw数值确定频率控制字。测试工程顶层包括差分时钟转单端时钟原语,用于产生DAC ADC时钟的PLL 函数发生器模块,生成特定频率控制字的VIO IP核,还有接收端ADC数据采样逻辑以及ILA 调试IP核。
`timescale 1ns / 1ps module DDS_Demo_top
#(parameter AD_DA_W = )
(
input sys_clk_p,
input sys_clk_n,
input rst_n, output [AD_DA_W-:] DAC_data,
output DAC_clk, input [AD_DA_W-:] ADC_data,
output ADC_clk
); localparam FCW_W = ; wire sys_clk_ibufg;
wire clk_dac,clk_adc;
reg [ (AD_DA_W-):] data_ad ; wire [FCW_W- : ] probe_out0;
wire [AD_DA_W*-:] probe0; //ADC接口信号
//ADC在时钟上升沿后送出数据,FPGA下一个上升沿采样
assign ADC_clk = clk_adc; always @(posedge clk_adc or negedge rst_n )begin
if(rst_n==) begin
data_ad <= () ;
end
else begin
data_ad <= (ADC_data) ;
end
end /***************************************子模块例化***************************************/
IBUFGDS #
(
.DIFF_TERM ("FALSE"),
.IBUF_LOW_PWR ("FALSE")
)
u_ibufg_sys_clk
(
.I (sys_clk_p),
.IB (sys_clk_n),
.O (sys_clk_ibufg)
); clk_wiz_0 u_pll
(
// Clock out ports
.clk_out1(clk_dac), // output clk_out1
.clk_out2(clk_adc), // output clk_out2
// Status and control signals
.resetn(rst_n), // input resetn
.locked(), // output locked
// Clock in ports
.clk_in1(sys_clk_ibufg)); // input clk_in1 sin_generator#(.FCW_W(FCW_W),
.DAC_W(AD_DA_W))
u_sin_gen
(
.clk (clk_dac) ,//DAC采样时钟 由PLL产生
.rst_n (rst_n) ,
.fcw (probe_out0) ,
.dac_data (DAC_data) ,
.dac_clk (DAC_clk) //由clk_dac产生
); //debug cores
vio_0 u_vio (
.clk(clk_dac), // input wire clk
.probe_out0(probe_out0) // output wire [15 : 0] probe_out0
); ila_0 u_ila (
.clk(clk_adc), // input wire clk
.probe0(probe0) // input wire [15:0] probe0
); assign probe0[:] = DAC_data;
assign probe0[:] = ADC_data; endmodule
DDS_Demo
最后添加引脚约束文件:
#################################clock && reset###############################################
create_clock -period [get_ports sys_clk_p]
set_property PACKAGE_PIN R4 [get_ports {sys_clk_p}]
set_property IOSTANDARD DIFF_SSTL15 [get_ports {sys_clk_p}] set_property PACKAGE_PIN T6 [get_ports rst_n]
set_property IOSTANDARD LVCMOS15 [get_ports rst_n] #####################DAC PIN connect J4 expansion interface##########################
set_property PACKAGE_PIN H14 [get_ports {DAC_clk}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_clk}] set_property PACKAGE_PIN J14 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN H15 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN J15 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN G13 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN H13 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN J21 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN J20 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}]
set_property PACKAGE_PIN G16 [get_ports {DAC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DAC_data[]}] #####################ADC PIN connect J4 expansion interface########################## set_property PACKAGE_PIN D22 [get_ports {ADC_clk}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_clk}] set_property PACKAGE_PIN G21 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN G22 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN H20 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN G20 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN J22 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN H22 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN K21 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
set_property PACKAGE_PIN K22 [get_ports {ADC_data[]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ADC_data[]}]
clk_pin
七、实验结果分析
依据之前的参数和DDS信号频率公式,所生成正弦函数频率最好在32/2^16~32/3MHZ之内,使用VIO改变频率控制字数值,观察ILA抓取的发送与接收数据模拟形式波形。任意给出三组频率范围内波形,频率依次由低到高。
总体来讲还是比较简单。搭建好DAC ADC环路,后面可以验证些滤波 同步算法,或者做些数字频率计、示波器之类的实用设计。
数字信号处理专题(1)——DDS函数发生器环路Demo的更多相关文章
- 数字信号处理专题(3)——FFT运算初探
一.前言 FFT运算是目前最常用的信号频谱分析算法.在本科学习数字信号处理这门课时一直在想:学这些东西有啥用?公式推来推去的,有实用价值么?到了研究生后期才知道,广义上的数字信号处理无处不在:手机等各 ...
- 数字信号处理专题(2)——利用FPGA进行基本运算及特殊函数定点运算
一.前言 FPGA以擅长高速并行数据处理而闻名,从有线/无线通信到图像处理中各种DSP算法,再到现今火爆的AI应用,都离不开卷积.滤波.变换等基本的数学运算.但由于FPGA的硬件结构和开发特性使得其对 ...
- FPGA与数字信号处理
过去十几年,通信与多媒体技术的快速发展极大地扩展了数字信号处理(DSP)的应用范围.眼下正在发生的是,以更高的速度和更低的成本实现越来越复杂的算法,这是针对高级信息服更高带宽以及增强的多媒体处理能力等 ...
- 数字信号处理--FFT与蝶形算法
在数字信号处理中常常需要用到离散傅立叶变换(DFT),以获取信号的频域特征.尽管传统的DFT算法能够获取信号频域特征,但是算法计算量大,耗时长,不利于计算机实时对信号进行处理.因此至DFT被发现以来, ...
- 数字信号处理与音频处理(使用Audition)
前一阵子由于考博学习须要,看了<数字信号处理>,之前一直不清除这门课的理论在哪里应用比較广泛. 这次正巧用Audition处理了一段音频,猛然发现<数字信号处理>这门课还是很实 ...
- 数字信号处理MATLAB简单序列
数字信号处理应用的几个基本序列: 1 单位样本序列 function mainImseq() clc clear disp('生成抽样序列'); y=imseq(,,); %调用样本函数,此时序列下标 ...
- 现代数字信号处理——AR模型
1. AR模型概念观 AR模型是一种线性预测,即已知N个数据,可由模型推出第N点前面或后面的数据(设推出P点),所以其本质类似于插值,其目的都是为了增加有效数据,只是AR模型是由N点递推, ...
- 如何使用Matlab做数字信号处理的仿真1
例如 第三版数字信号处理P51 -1.14习题时域离散信号的相关性研究x(n)=Asin(ωn)+u(n),其中ω=π/16,u(n)是白噪声,现要求 ⑴.产生均值为0,功率P=0.1的均匀分布白噪声 ...
- FS,FT,DFS,DTFT,DFT,FFT的联系和区别 数字信号处理
DCT变换的原理及算法 文库介绍 对于初学数字信号处理(DSP)的人来说,这几种变换是最为头疼的,它们是数字信号处理的理论基础,贯穿整个信号的处理. 学习过<高等数学>和<信号与系统 ...
随机推荐
- Docker系列教程01-Centos7安装新版Docker教程(10步)
最近一直忙于开发,没有时间好好总结一下docker的知识.其实现在docker的教程已经很多很多了,但是很多系统的教程都是基于Ubuntu系统,因为官方推荐使用Ubuntu系统啊,原因在于Ubuntu ...
- JVM基础系列第11讲:JVM参数之堆栈空间配置
JVM 中最重要的一部分就是堆空间了,基本上大多数的线上 JVM 问题都是因为堆空间造成的 OutOfMemoryError.因此掌握 JVM 关于堆空间的参数配置对于排查线上问题非常重要. tips ...
- 在.net core上使用Entity FramWork(Db first)
在.net core中不可以向往常一样去直接可视化创建EF了,那我们可以通过命令安装 其依赖项有 Install-package Microsoft.EntityFrameworkCore Insta ...
- Spring RestTemplate中几种常见的请求方式
https://github.com/lenve/SimpleSpringCloud/tree/master/RestTemplate在Spring Cloud中服务的发现与消费一文中,当我们从服务消 ...
- docker~在centos容器中安装新程序
上一篇我们使用了阿里加速器安装了centos镜像,然后创建了一个新容器,运行了这个镜像,这一讲我们来为这个镜像添加一些应用程序,然后再保存容器,push容器到仓储,大家就可以直接pull我生产的容器了 ...
- [软件开发技巧]·树莓派极简安装OpenCv
树莓派极简安装OpenCv 个人主页–> https://xiaosongshine.github.io/ 因为最近在开发使用树莓派+usb摄像头识别模块,打算用OpenCv,发现网上的树莓派O ...
- Kubernetes 弹性伸缩全场景解析 (四)- 让核心组件充满弹性
前言 在本系列的前三篇中,我们介绍了弹性伸缩的整体布局以及HPA的一些原理,HPA的部分还遗留了一些内容需要进行详细解析.在准备这部分内容的期间,会穿插几篇弹性伸缩组件的最佳实践.今天我们要讲解的是 ...
- SpringCloud应对高并发的思路
一.Eureka的高可用性 Eureka下面的服务实例默认每隔30秒会发送一个HTTP心跳给Eureka,来告诉Eureka服务还活着,每个服务实例每隔30秒也会通过HTTP请求向Eureka获取服务 ...
- 解读经典《C#高级编程》泛型 页122-127.章4
前言 本篇继续讲解泛型.上一篇讲解了泛型类的创建.本篇讲解泛型类创建和使用的细节. 泛型类 上篇举了个我产品中用到的例子,本篇的功能可以对照着此案例进行理解. /// <summary> ...
- babel版本兼容报错处理:Plugin/Preset files are not allowed to export objects
原文地址: https://www.cnblogs.com/jiebba/p/9618930.html 1.为什么会报错 ? 这里抱着错误是因为 babel 的版本冲突. 多是因为你的 babel 依 ...