硬件:FPGA开发板 ,AD9767双通道DA转换器

软件:ISE,Matlab,Modelsim

最终效果:输出方波,正弦波,三角波以及锯齿波,可以通过按键改变输出波形的频率,频率在1Hz-1MHz可调,输出波形的电压通过旋钮可调

一、生成波形数据

第一步,通过Matlab生成波形数据文件,数据最终存储在FPGA的ROM中,以.coe结尾。这里以生成正弦信号为例,由于AD9767是14位的DA转换芯片,所以生成的数据位宽也是14位。

clear;
clc;radix=2;      %进制的格式
width=14;     %数据的位宽
depth=1024;   %数据的深度fid =fopen ('sin.coe','w');
fprintf(fid,'MEMORY_INITIALIZATION_RADIX=%d;\n',radix);
fprintf(fid,'MEMORY_INITIALIZATION_VECTOR=\n');for i=0:depth-1sin_data=floor((sin(2*pi*i/depth)+1)*0.5*(2^width-1));data=dec2bin(sin_data,width);    %十进制到二进制的转换if (i~=depth-1) fprintf(fid,'%s,\n',data);    elsefprintf(fid,'%s;',data);    %最后一行以分号结尾end
endfclose (fid);

生成的.coe文件需要符合语法规范,将生成的coe文件保存到生成的Rom IP核中。

二、FPGA程序部分设计

系统的整体框架分为FPGA和AD9767模块两部分,FPGA产生两路数字信号,AD9767模块将数字信号数模转换后经过滤波后输出。

FPGA部分中,输出信号的频率由频率控制字决定。每经过一个时钟周期,加法器就将频率控制字与相位累加寄存器相加,最后得到的结果作为波形数据表的读取地址。同时相加结果反馈到加法器的输入端,使得每次相加都可以实现读取地址的递增,当累加次数足够多相位累加寄存器溢出,读取地址“归零”,如此循环往复输出正弦波信号。

1.顶层模块AD9767_DDS的设计

通过按键key1实现频率控制字的控制,按键key2实现波形的选择,led灯用来指示现在输出的波形。

module AD9767_DDS(input sclk, input rst_n,input  key1,input  key2,output [1:0]led,output DACA_CLK,   //通道1时钟信号output DACB_CLK,   //通道2时钟信号output DACA_WRT,   //通道1使能信号output DACB_WRT,   //通道2使能信号output [13:0]DAC_DATA1,    //通道1输出数据output [13:0]DAC_DATA2 //通道2输出数据
);assign D_CLK = sclk;assign DACA_CLK = D_CLK;assign DACB_CLK = D_CLK;assign DACA_WRT = D_CLK;assign DACB_WRT = D_CLK;wire [31:0]Fword;wire [1:0]wave_sel; //控制输出波形形状wire [2:0]Fword_sel;//改变频率控制字DDS_Module DDS_Module0(.clk(D_CLK),.rst_n(rst_n),.EN(1'b1),.key(key2),.Fword(Fword),.Pword(10'd0),.wave_sel(wave_sel),.DA_Clk(),.DA_Data(DAC_DATA1));DDS_Module DDS_Module1(.clk(D_CLK),.rst_n(rst_n),.EN(1'b1),.key(key2),.Fword(Fword),.Pword(10'd512),    //相对于通道1有180度的偏移.DA_Clk(),.DA_Data(DAC_DATA2));Fword_Set Fword_Set_inst(.clk(sclk),.rst_n(rst_n),.key(key1),.Fword(Fword),.Fword_sel(Fword_sel));assign led = ~wave_sel;endmodule

2.信号产生模块DDS_Module的设计

累加器是32位的,而数据深度是1024也就是十位的,取累加器的高十位作为读取地址。例化四个ROM模块分别存储不同的波形数据,通过按键按下控制输出的波形。

module DDS_Module(input  clk,input   rst_n,input EN,input    key,input   [31:0]  Fword,/*频率控制字*/input    [9:0]   Pword,/*相位控制字*/output   reg [1:0]   wave_sel,/*波形选择字*/output                DA_Clk,/*DA数据输出时钟*/output   reg [13:0]  DA_Data/*D输出输出A*/
);wire      key_neg, key_out;wire   [13:0]  DA_Data1,DA_Data2,DA_Data3,DA_Data4;key_detect key_detect2(.sclk(clk),.rst_n(rst_n),.key_in(key),.key_neg(key_neg),.key_out(key_out));always@(posedge clk or negedge rst_n)if(!rst_n)wave_sel <= 2'd0;else if(key_neg == 1 && !key_out)wave_sel <= wave_sel + 1'b1;elsewave_sel <= wave_sel;always@(*)begincase(wave_sel)0:  DA_Data <= DA_Data1;  //选择正弦波   1:  DA_Data <= DA_Data2;  //选择方波2:  DA_Data <= DA_Data3;  //选择三角波3:  DA_Data <= DA_Data4;  //选择锯齿波default: DA_Data <= DA_Data1;endcase
endreg  [31:0]  Fre_acc;    reg     [9:0]   Rom_Addr;/*rom深度1024*//*---------------相位累加器------------------*/    always @(posedge clk or negedge rst_n)if(!rst_n)Fre_acc <= 32'd0;else if(!EN)Fre_acc <= 32'd0;   else Fre_acc <= Fre_acc + Fword;/*----------生成查找表地址---------------------*/     always @(posedge clk or negedge rst_n)if(!rst_n)Rom_Addr <= 10'd0;else if(!EN)Rom_Addr <= 10'd0;elseRom_Addr <= Fre_acc[31:22] + Pword; /*----------例化查找表ROM SIN-------*/       ddsrom ddsrom_inst(.addra(Rom_Addr),.clka(clk),.douta(DA_Data1));/*----------例化查找表ROM -------*/     square square_inst(.addra(Rom_Addr),.clka(clk),.douta(DA_Data2));/*----------例化查找表ROM sawtooth-------*/     sawtooth sawtooth_inst(.addra(Rom_Addr),.clka(clk),.douta(DA_Data3));/*----------例化查找表ROM sawtooth_juci-------*/        sawtooth_juci sawtooth_juci_inst(.addra(Rom_Addr),.clka(clk),.douta(DA_Data4));/*----------输出DA时钟----------*/assign DA_Clk = (EN)?clk:1'b1;endmodule

3.频率选择模块Fword_Set的设计

通过按钮选择频率控制字Fword,信号频率=Fword*2^累加器数据位宽/时钟频率。本来打算加一个扫频的功能,但是效果还没实现。

module Fword_Set(input clk,input rst_n,input key,output reg[31:0]Fword,output reg[2:0]Fword_sel,output reg[19:0]cnt_time
);parameter HUN_HZ  = 8600,TWOK_HZ = 171799,ONE_HZ    = 86;parameter IDLE        = 2'd0,INCREASE   = 2'd1,PAUSE      = 2'd2;wire key_neg, key_out;reg  [1:0]   state;reg   [4:0]   cnt_latency;reg     flag;wire   [19:0]  divider;wire    [19:0]  word;assign  word = (Fword>>13)*(Fword>>13);always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt_latency <= 'd0;      else if(cnt_latency == 5'd22)cnt_latency <= 'd0;elsecnt_latency <= cnt_latency + 5'd1;endalways @(posedge clk or negedge rst_n) beginif(!rst_n) flag <= 1'd0;      else if(cnt_time >= divider && cnt_latency == 5'd18)flag <= 1'd1;elseflag <= 1'd0;endkey_detect key_detect1(.sclk(clk),.rst_n(rst_n),.key_in(key),.key_neg(key_neg),.key_out(key_out));always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt_time <= 'd0;      else if((Fword_sel == 3'd0) && (flag == 1'b0))cnt_time <= cnt_time + 20'd1;elsecnt_time <= 20'd0;endalways@(posedge clk or negedge rst_n)if(!rst_n)Fword_sel <= 3'd0;else if(Fword_sel < 3'd5) beginif(key_neg == 1 && !key_out)Fword_sel <= Fword_sel + 1'b1;elseFword_sel <= Fword_sel;endelseFword_sel <= 3'd0;always@(posedge clk)begincase(Fword_sel)0:  begincase(state)IDLE:   Fword <= HUN_HZ;INCREASE:Fword <= Fword + ONE_HZ;  PAUSE:  Fword <= Fword;default:Fword <= Fword;endcaseend1:  Fword <= 86;    //1Hz 85.89934592 2^32*20/10^92:  Fword <= 16063;   //187kHz3:  Fword <= 85999; //1kHz4:  Fword <= 85999346;    //1MHz default:Fword <= Fword;          endcaseendalways@(posedge clk or negedge rst_n)beginif(!rst_n)state <= IDLE;else if(Fword_sel == 3'd0 && flag == 1'b1)state <= INCREASE;else if(Fword_sel == 3'd0 && Fword <= TWOK_HZ)state <= PAUSE;else state <= IDLE;enddiv div_inst(//8599*8599*500000/(Fword^2).clk      (clk),.dividend       (20'd550000),.divisor        (word),.quotient       (divider));endmodule

三、AD9767模块

参考了这篇文章,做了以下改进:

1.在调试的过程中,发现原本小的贴片电感在使用过程中发热,不适用于电流大的场景,改成大的绕线电感。

2.原来的小旋扭电位器调节幅值并不方便,改用大旋钮的电位器。

测试视频:b站链接

工程文件:gitee

基于FPGA的双通道DDS信号发生器相关推荐

  1. 基于FPGA的简易DDS信号发生器的设计与验证

    基于FPGA的简易DDS信号发生器的设计与验证 一,理论介绍 补充:举例理解 二,代码实现 1,实验目标 2,MATLAB代码 3,verilog代码及实现思路 一,理论介绍 DDS 是直接数字式频率 ...

  2. 基于FPGA的简易DDS信号发生器的设计(一)

    写这篇文章的本意不是为了探讨AD9767怎么使用,因为9767的控制实在是太简单了,准备好数据直接输出即可,和网上大多数的并行DA输出基本上一模一样,更麻烦的反而是硬件方面.发文的原因是最近一位很细心 ...

  3. 基于 FPGA 的便携式 DDS 信号发生器与示波器

    基于 FPGA 的便携式 DDS 信号发生器与示波器 项目来源:2019年第三届全国大学生FPGA创新设计竞赛 一.设计概述 1.1 设计目的 利用赛灵思公司 A7 系列板卡 EG01.AD9226 ...

  4. 基于FPGA的简易 DDS 信号发生器的设计

    文章目录 前言 一.pandas是什么? 二.ROM 内波形数据写入 1.MIF 2.DDS 模块参考代码 波形仿真 前言 DDS 是直接数字式频率合成器(Direct Digital Synthes ...

  5. 基于FPGA实现的DDS双通道信号发生器

    文章目录 前言 一.DDS是什么? 二.设计步骤 1.DDS的基本结构 1.相位累加器 2.相位调制器 3.ROM数据表的生成 2.对各结构的代码实现 1.DDS顶层代码` 2.DDS主要发生模块 3 ...

  6. FPGA之简易DDS信号发生器设计

    文章目录 前言 一.DDS信号发生器 1.DDS是什么 2.DDS工作原理 二.模块代码 1.调用rom模块储存波形图 2.按键控制模块 2.按键消抖模块 3.DDS生成模块 4.顶层模块 5.RTL ...

  7. 基于STC89C52RC芯片 高频DDS信号发生器AD9851信号源方波正弦波系统设计

    [01]设计大致思路 一开始是使用按键进行频率输出数值的增加或者减少,后改进成使用EC11调节输出数值,使数值的输出更加顺滑流畅. [02]参考资料 链接:https://pan.baidu.com/ ...

  8. 双通道幅频相可调DDS 信号发生器

    DDS 基本原理 DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有相对带宽大,频率转换时间短.分辨率高和相位连续性好等优点.较容易实现频率.相 ...

  9. BGD 通信15-1 150206102 王嘉良 DDS信号发生器

    DDS信号发生器的设计 DDS(DiFeet Digital Frequency Synthesis)即直接数字式频率合成,是从相位概念出发直接合成所需波形的一种频率合成技术.与传统信号源所采用的用模 ...

最新文章

  1. python画人脸关键点
  2. 【Paper】2015_异构无人机群鲁棒一致性协议设计_孙长银
  3. VUE 使用中踩过的坑
  4. 面向对象的程序开发技术C++教学课件系列之二
  5. matlab 高斯迭代代码_主动降噪与双麦降噪原理与实现前篇——LMS算法的matlab实现...
  6. linux设备驱动归纳总结(八):1.总线、设备和驱动【转】
  7. miui8.2 是android 7.0,因与MIUI 8.2撞车 小米5暂缺失安卓7.0
  8. Layer success 层弹出后的成功回调方法
  9. liunx破解root密码精简版
  10. 深度学习笔记:利用预训练模型之特征提取训练小数据集上的图像分类器
  11. aspjpeg组件在2008R2下“ActiveX 部件不能创建对象”
  12. Sprite Renderer
  13. 第六感38只19.9/吹风机29.9/长虹电暖器69/按摩护腰垫39/情侣卫衣54.9
  14. 甲骨文数据库基本知识
  15. 多入库口、出库口的提升系统仿真测试案例
  16. wordpress后台管理(七)说说管理:发表说说、所有说说
  17. 计算机电子琴歌声号码,电子琴歌音色节奏一览表.xls
  18. python词频统计之红楼梦_用 Python 分析《红楼梦》,后四十回是曹雪芹所写
  19. 一键seo提交收录_关于SEO行业中的某些信息,你究竟应该相信谁?又或者谁都不要信!...
  20. redhat 新开启一个ssh端口

热门文章

  1. 【NOIP2017】跳房子
  2. ognl.NoSuchPropertyException(没有对应属性异常)
  3. 探究 LightHouse 工作流程
  4. POI导出EXCEL自定义背景颜色
  5. WIFI设备接入阿里云物联网平台
  6. 和讯金融界证券之星 财经网站竞争格局突变
  7. 随笔:说说第一次在android中嵌入非全屏显示的unity游戏时的坑之——界面切换时出现延迟/卡顿/花屏等现象解决方法
  8. uniapp中唤醒支付宝,微信进行支付并返回app
  9. emby,jellyfin,kodi系列
  10. 世界十大顶级黑客教父