FPGA—DDS信号发生器笔记

使用软件: Vivado

基本原理

DDS基本原理

[百度] DDS信号发生器采用直接数字频率合成(Direct Digital Synthesis,简称DDS)技术,把信号发生器的频率稳定度、准确度提高到与基准频率相同的水平,并且可以在很宽的频率范围内进行精细的频率调节。采用这种方法设计的信号源可工作于调制状态,可对输出电平进行调节,也可输出各种波形。
DDS基本结构图:
DDS结构图
由图可以看出,DDS 主要由相位累加器、相位调制器、波形数据表以及 D/A转换器构成。
其中相位累加器由 N 位加法器与 N 位寄存器构成。每个时钟周期的时钟上升沿,加法器就将频率控制字与累加寄存器输出的相位数据相加,相加的结果又反馈至累加寄存器的数据输入端,以使加法器在下一个时钟脉冲的作用下继续与频率控制字相加。这样,相位累加器在时钟作用下,不断对频率控制字进行线性相位累加。即在每一个时钟脉冲输入时,相位累加器便把频率控制字累加一次。
相位累加器输出的数据就是合成信号的相位。相位累加器的溢出频率,就是DDS 输出的信号频率,相位累加器输出的数据,作为波形存储器的相位采样地址,这样就可以把存储在波形存储器里的波形采样值经查表找出,完成相位到幅度的转换。波形存储器的输出数据送到 D/A 转换器,由 D/A 转换器将数字信号转换成模拟信号输出。
DDS信号流程示意图如下:
DDS信号流程
这里相位累加器位数为 N 位(N 的取值范围实际应用中一般为 24~32),相
当于把正弦信号在相位上的精度定义为 N 位,所以其分辨率为1/2N
若DDS的时钟频率为Fcl,频率控制字fword=B,则输出频率Fout=BxFclk/2N

因此理论上由以上三个参数就可以得出任意的Fout输出频率。且可得出频率分辨率由时钟频率和累加器的位数决定的结论。当参考时钟频率越高,累加器位数越高,输出频率分辨率就越高。
为了合理控制ROM的容量,此处选取ROM查询的地址时,可以采用截断式,即只取32位累加器的高M位。这里相位寄存器输出的位数一般取10~16位。

DDS模块

在本设计中参考时钟Fclk 频率为50 MHz,相位累加器位数 N 取32 位,频率控制字位数 M 取 12 位。经过以上的分析,可以得出 DDS 模块的端口模块如下图所示:
在这里插入图片描述
端口功能描述:
在这里插入图片描述

ROM IP的使用

单击 IP Catalog,在右边窗口 Search 位置输入rom,在Memories &Storage Elements 下可以看到有两个与 ROM 相关的 IP,一个是 Distributed Memory Generator,另一个是Block Memory Generator,先简单说说两个的差别,两者最主要的差别是生成的 Core所占用的 FPGA 资源不一样,从 Distributed Memory Generator 生成的 ROM/RAM Core 占用的资源是 LUT(查找表,查找表本质就是一个小的 RAM);从 Block Memory Generator 生成的 ROM/RAM Core 占用的资源是 Block Memory(嵌入式的硬件 RAM)
在这里插入图片描述
在 IP Catalog 窗口选择 Distributed Memory Generator 并双击。
在这里插入图片描述进入IP配置界面,如下。

在这里插入图片描述
(1)Documentation:IP 相关文档入口,点击后出现如下内容
(2)IP Location:生成 IP 的存放路径,可以通过点击 … 设置更换存放路径,默认是存放在工程路径下的 bin_counter.srcs\ sources_1\ ip,我这里就保持默认。
(3)Switch to Default:点击后所有的设置恢复到默认值
(4)Component Name:设置生成 IP Core 的名称,我这里将名字设置为 dist_mem_rom_ip;
(5)Depth:设置 ROM 深度,我这里设置 256;
(6)Data Width:设置数据位宽,我这里设置 8;
(7)Memory Type:选择存储类型,这里选择 ROM

在这里插入图片描述
(8)Input Options:设置是否对输入的地址增加一级寄存器,这里设置选择 Registered,对输入的地址增加一级寄存器(也可以选择 Non Registered,不增加寄存器)。
(9)Output Option:设置是否对输出的地址增加一级寄存器,这里设置选择 Both,对输出数据信号 spo 和增加一级寄存器后的输出数据信号 qspo 都从端口引出。下面还有个Single Port Output CE 可选配,当勾选后,ROM Core 就会多出一个 qspo_ce 的端口,这个信号是用来控制使能输出寄存器的时钟。这里没有用这个功能,不勾选该项。
在这里插入图片描述
(10)Pipeline Stages:流水线级数,在生成 ROM 模式下,不可配。
在这里插入图片描述

(11)添加 COE 文件位置,可以通过选择路径添加已有的 COE文件,软件会通过 COE 文件生成 ROM 初始化文件 MIF 文件。关于如何创建 COE 文件看下一步骤。
(12) 编辑按钮,当(11)中未加载 COE 文件时,点击这里按钮,会弹出提示框,点击YES 可进入到创建 COE 文件的流程,这里点击 YES。
(13)COE Options:设置 ROM 中初始化数据没有覆盖的区域的数值,比如 ROM 深度 256,添加的 COE 文件中仅初始化了200 个数据,这里就是统一设置剩下的 56 个数据的数值。
(14)Reset Options:添加输出寄存器复位信号,可添加同步复位或异步复位,这里就不勾选添加复位信号。
(15)ce overrides 设置
CE Overrides Sync Controls:在选择了输出寄存器同步复位和时钟使能才能启用,启用后,同步控制由时钟使能限定。
Sync Controls Overrides CE:在选择了输出寄存器同步复位和时钟使能才能启用,
启用后,同步控制信号会工作,不受时钟使能限定。
前面未勾选时钟使能信号 CE,这里就不可设置,保持默认即可。ROM IP 的各种参数设置完后点击 OK。
在这里插入图片描述
在这里插入图片描述
选择 COE 文件存放的路径位置和设置好 COE 文件名,点击 Save。
在这里插入图片描述
在这里插入图片描述
出现如上图弹窗,点击 Generate。
等 IP 生成完成后,出现如下图弹窗,点击 OK。
在这里插入图片描述

波形数据存储器

为了能产生相应的波形,我们需要创建 ROM 来分别存储正弦波、方波、三角波的波形数据。其中单端口的 ROM 主要配置数据如下图所示,其初始化文件选为已经生成的相应波形的 coe 文件。此处 coe 位宽为 14,深度为 4096。
在这里插入图片描述
关于生成 coe 文件需要注意的是,由于本次设计使用的是 Xilinx 出品的芯
片,所以在使用 Mif 精灵生成该文件时,应选择 Xilinx,同时 maxi 中数据应改
为 16383,其余设置如下图所示:

Mif精灵文件生成器网站:http://www.corecourse.cn/forum.php?mod=viewthread&tid=28374
在这里插入图片描述
选择sine wave生成正弦波数据。

然后载入生成的正弦波数据如下所示:
在这里插入图片描述
点击ok,保存生成即可。

代码及仿真

verilog代码

`timescale 1ns / 1ps
//
// Module Name: DDS_Moudle
// 
//


module DDS_Moudle(
	clk,
	Reset_n,
	Fword_i,		//频率控制字
	Pword,	//相位控制字
	Data	//输出
   );
   input clk;
   input Reset_n;
   input[31:0] Fword_i;
   input[11:0] Pword;
   output[13:0] Data; //输出14位?4096
   
   //频率控制字同步寄存器
   reg[31:0] Fword_r;
   always@(posedge clk) begin
	Fword_r <= Fword_i;
   end
   //相位控制字同步寄存器
   reg[11:0] Pword_r;
   always@(posedge clk)
		Pword_r <= Pword;
	//相位累加器
	reg[31:0] Freq_ACC;
	always@(posedge clk or negedge Reset_n) begin
		if(!Reset_n)
			Freq_ACC <= 0;
		else
			Freq_ACC <= Fword_r + Freq_ACC;
	end

	//相位累加器与相位控制字的结果输出 
	//wire[31:0] Freq_ACC_out;
	//assign Freq_ACC_out <= Freq_ACC+Pword_r;

	
	//波形数据表地址
	wire[11:0] Rom_Addr;
	/*为什么是取ROM高12位地址
	因为频率控制器就是12位,所以取高12位 Freq_ACC_out[31:20]
	B=2^20
	*/
	assign Rom_Addr = Freq_ACC[31:20]+Pword_r;
	rom rom(
	.clka(clk),
	.addra(Rom_Addr),
	.douta(Data)
	);
	
endmodule

仿真代码(Fword有值,Pword=0时)

`timescale 1ns / 1ps
//
// Module Name: sim_DDS_Moudle
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module sim_DDS_Moudle();
    reg clk;
    reg reset_n;
    reg[31:0] Fword;
    reg[11:0] Pword;
    wire[13:0] Data;
    
    DDS_Moudle uut(clk,reset_n,Fword,Pword,Data);
    initial clk=1;
    always #10 clk=~clk; //时钟周期20ns,仿真50M Hz
    
    initial begin
        reset_n=0;
        Fword=65536;
        Pword=0;
        #201;
        reset_n=1;
        #2000000;
        Fword=65536*1024;
        #2000000;
        Fword=65536*32;
        #2000000;
        $stop;
    end
endmodule

仿真结果及分析

点击下图按钮,获得10ms长的仿真结果
在这里插入图片描述

鼠标右键Data,找到[Waveform style],选择[Analog],查看模拟波形
在这里插入图片描述
经过调整缩放之后波形如下所示:
在这里插入图片描述
计算周期:
找到波形最高点然后点击Add marker键
在这里插入图片描述
找到另一个最高点,点击Add marker键
在这里插入图片描述
由上图可以看到,此时周期为1310.72μs
可以由此算出此时的频率:762.9394513125 Hz
在这里插入图片描述
从代码中可以看到此时Fword为65536=216
在这里插入图片描述
根据公式:Fout=BxFclk/2N
B=Fword=65536=216
Fclk = 50M
N=32
所以Fout=Fclk/216=762.939453125
在这里插入图片描述
同理可以算出Fword为其他值的时候的Fout输出值,与预期结果一致。

增加Pword(相位控制字之后)仿真代码

因为生成正弦信号数据总数为4096个,Pword=1024是它的1/4,与Pword=0相差90度;Pword=2048与Pword=0相差180度。
令PwordA=0;PwordB为1024和2048,从仿真结果中查看相位变化

`timescale 1ns / 1ps
//
// Create Date: 2022/10/16 19:06:41
// Design Name: 
// Module Name: sim_DDS_Moudle
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module sim_DDS_Moudle();
    reg clk;
    reg reset_n;
    reg[31:0] FwordA,FwordB;
    reg[11:0] PwordA,PwordB;
    wire[13:0] DataA,DataB;
    
    DDS_Moudle DDS_ModuleA(clk,reset_n,FwordA,PwordA,DataA);
    DDS_Moudle DDS_Moduleb(clk,reset_n,FwordB,PwordB,DataB);
    initial clk=1;
    always #10 clk=~clk; //时钟周期20ns,仿真50M Hz
    
    initial begin
        reset_n=0;
        FwordA=65536;
        PwordA=0;
        FwordB=65536;
        PwordB=1024;//因为数据一共4096个,取1/4个,相位相差90度
        #201;
        reset_n=1;
        #5000000;
        FwordA=65536*1024;
        FwordB=65536*1024;
        PwordA=0;
        PwordB=2048; //与A相位相差180度
        #1000000;
        $stop;
    end
endmodule

运行结果

从下图中可以看出前5ms结果中,DataA和DataB波形明显相差90度
在这里插入图片描述
从下图中可以看出前5ms结果中,DataA和DataB波形明显相差180度
在这里插入图片描述

  • 5
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值