FPGA——DDS信号发生器设计

文章目录

任务要求

1)利用DDS技术合成正弦波和方波;

2)输出信号的频率范围为10Hz~5MHz,最小频率分辨率小于1kHz;

3)使用嵌入式逻辑分析仪SignalTap II实时测试输出波形的离散数据。

一、DDS简介

直接数字频率合成(Direct Digital Frequency Synthesis, 简称DDS或DDFS)是一种应用数字技术产生信号波形的方法,它是由美国学者J. Tierney、C.M. Rader和B.Gold在1971年提出的,他们以数字信号处理理论为基础,从相位概念出发提出了一种新的直接合成所需波形的全数字频率合成方法。
DDS产生正弦信号波形的工作原理

虽然正弦波的幅度不是线性的,但是它的相位却是线性增加的,DDS正是利用了这一特点来产生正弦信号。因为一个连续的正弦信号其相位是时间的线性函数,相位对时间的导数为ω,即:
θ ( t ) = 2 π f t = ω t \theta(t)=2\pi ft=\omega t \quad θ(t)=2πft=ωt
d θ ( t ) d t = 2 π f = ω \frac{d\theta(t)}{dt}=2\pi f=\omega \quad dtdθ(t)=2πf=ω

当角频率ω为一定值时,其相位斜率dθ/dt也是一个确定值。此时,正弦波形信号的相位与时间呈线性关系,即Δθ=ω×Δt。根据这一基本关系,利用采样定理,通过查表法就能够产生波形。

图8.7.1是产生正弦信号的原理框图。图中CP为系统基准时钟源,其周期为T。在CP的作用下,地址计数器(从0~(2^N-1)计数)产生数据存储器所需的地地信号。在时钟作用下,周期性地读出正弦波形存储器中的正弦幅值,经过D/A转换器及低通滤波器就可以合成模拟波形。

二、设计过程

1、相位累加器的设计

bash 复制代码
module addr_cnt(CPi,K,ROMaddr,Address);
    input CPi;
    input [12:0] K;
    output reg [9:0] ROMaddr;
    output reg [16:0] Address;
    always @(posedge CPi) begin
        Address=Address+K;
        ROMaddr=Address[16:7];
    end
endmodule

输入上述代码,选择主菜单中的File→Create/Update→Create Symbol Files for Current File命令,生成该模块的符号,打开其addr_cnt.bsf文件即可查看,如图所示。

2、波形存储器设计

  • 方波模块
bash 复制代码
module squwave(CPi,RSTn,Address,Qsquare);
    input CPi;
    input RSTn;
    input [16:0] Address;
    output reg [11:0] Qsquare;
    always @(posedge CPi)
    if (!RSTn)Qsquare=12'h000; 
    else begin
        if(Address<=17'h0FFFF)
            Qsquare=12'hFFF;
        else Qsquare=12'h000;
    end
endmodule

模型符号如图所示。

  • 正弦波形存储器模块
    C语言程序
c 复制代码
#include <stdio.h>
#include <math.h>

#define PI 3.141592
#define DEPTH 1024 //数据深度,即存储单元的个数
#define WIDTH 12   //存储单元的宽度

int main(void)
{
    int n, temp;
    float v;
    FILE *fp;

    /*建立文件名为Sine1024.aif的新文件,先写入数据,对文件名没有特殊要求,但扩展名必须为.aif*/
    fp=fopen("Sine1024.aif", "w+");
    if(NULL==fp)
        printf("Can not creat file\n");
    else
    {
        printf("File created successfully!\n");

        /*生成文件头,注意不要忘了"\n"*/
        fprintf(fp, DEPTH =%d.\n",DEPTH);
        fprintf(fp, WIDTH =%d.\n",WIDTH);
        fprintf(fp, ADDRESS_RADIX=HEX.\n");
        fprintf(fp, DATA_RADIX=HEX.\n");
        fprintf(fp, BEGIN\n");

        /*以下六行是刷新输出地址和数据指令*/

        for(n=0; n<DEPTH; n++)
        {
            v=sin(2*PI*n/DEPTH); /*sin函数在-1~+1之间的正弦波的值被扩展到0~4095之间*/
            temp=(int)(v+1)*2048/2; /*+1将数值平移到0~2之间,*以十六进制输出地址和数据*/
            fprintf(fp, %x\t%x\n", n, temp);
        }
        fprintf(fp, END\n");
    }
    fclose(fp); //关闭文件
}

以文件名Sine1024.c保存文件,接着进行编译,产生Sine1024.exe文件,双击运行Sine1024.exe,生成Sine1024.mif文件。

接着,验证生成的数据是否正确。用记事本打开生成的.mif文件,同时用Quartus Prime软件打开mif文件,若能成功导入数据且数据一致,则说明生成文件正确。

3、锁相环倍频电路设计

在左侧的IP Catalog搜索ALTPLL(嵌入式锁相环),定制一个名为PLL100M_CP的始终模块。

该模块的输入inclko为50MHz时钟信号,输出c0为100MHz的脉冲信号,占空比为50%,带有相位锁定指示输出端locked。

除此之外其他地方不用改,一直next,最后finish。

4、顶层电路设计

bash 复制代码
module DDS_top (CLOCK_50,RSTn,WaveSel,K,
WaveValue,LEDG,CLOCK_100);
    input CLOCK_50;
    input RSTn;
    input [1:0] WaveSel;

    input [12:0] K;
    output reg [11:0] WaveValue;
    wire [9:0] ROMaddr/* synthesis keep */;
    wire [16:0] Address;
    wire [11:0] Qsine,Qsquare;
    output [0:0] LEDG;
    output CLOCK_100;
    wire CPi=CLOCK_100;
    PLL100M_CP PLL100M_CP_inst(
        .inclk0(CLOCK_50),
        .c0(CLOCK_100),
        .locked(LEDG[0])
    );

    addr_cnt U0_instance(CPi,K,ROMaddr,Address);

    SineROM ROM_inst(
        .address(ROMaddr),
        .clock(CPi),
        .q(Qsine)
    );
    squwave U1(CPi,RSTn,Address,Qsquare);
    always @(posedge CPi)
    begin
        case(WaveSel)
            2'b01:WaveValue=Qsine;
            2'b10:WaveValue=Qsquare;
            default:WaveValue=Qsine;
        endcase
    end
endmodule

三、设计实现

将该模块设置为顶层模块,全编译后只需配置三个引脚。

SW[16]------PIN_Y24

SW[17]------PIN_Y23

CLOCK_50------PIN_Y2

bash 复制代码
module DE2_115_DDS_top(CLOCK_50,KEY,SW,GPIO_0,LEDG);
    input CLOCK_50;
    input [3:3] KEY;
    input [17:0] SW;
    output [12:0] GPIO_0;
    output [0:0] LEDG;
    wire CLOCK_100;
    assign GPIO_0[12]=CLOCK_100;
    wire RSTn=KEY[3];
    wire [1:0] WaveSel=SW[17:16];
    wire [12:0] K=SW[12:0];
    wire [11:0] WaveValue;
    assign GPIO_0[11:0]=WaveValue;
    DDS_top DE2(CLOCK_50,RSTn,WaveSel,K,WaveValue,LEDG,CLOCK_100);
endmodule

配置完后再次编译。使用嵌入式逻辑分析仪 SignalTap II 实时测试输出波形的离散数据。选择 Tools→SignalTap II Logic Analyzer 命令,选择锁相环输出的 100MHz 信号(GPIO_0[12]) 作为采样时钟,添加待测节点信号,并设置 ROM 地址为 0 时触发采样。然后保存设置,并将该模块添加到当前工程项目中。

四、运行结果

正弦波

SW[16]拨为1,SW[17]拨为0

方波

SW[16]拨为0,SW[17]拨为1

总结

因为初次接触到DDS,所以操作过程中遇到了很多问题,比如逻辑分析仪 SignalTap II 的使用,所以以后会花一些时间去进一步了解。

参考资料

https://blog.csdn.net/weixin_72935906/article/details/147195590

https://blog.csdn.net/changtianFirst/article/details/147097698

相关推荐
丝斯20115 小时前
AI学习笔记整理(42)——NLP之大规模预训练模型Transformer
人工智能·笔记·学习
凉、介7 小时前
深入 QEMU Guest Agent:虚拟机内外通信的隐形纽带
c语言·笔记·学习·嵌入式·虚拟化
njsgcs8 小时前
SIMA2 论文阅读 Google 任务设定器、智能体、奖励模型
人工智能·笔记
3有青年8 小时前
Altera FPGA操作系统支持的情况分析
fpga开发
云半S一9 小时前
pytest的学习过程
经验分享·笔记·学习·pytest
AI视觉网奇9 小时前
ue5.7 配置 audio2face
笔记·ue5
国科安芯9 小时前
卫星通讯导航FPGA供电单元DCDC芯片ASP4644S2B可靠性分析
单片机·嵌入式硬件·fpga开发·架构·安全性测试
崎岖Qiu11 小时前
【OS笔记35】:文件系统的使用、实现与管理
笔记·操作系统·存储管理·文件系统·os
曦月逸霜11 小时前
离散数学-学习笔记(持续更新中~)
笔记·学习·离散数学
hunter145012 小时前
windows server AD域与CA部署证书
笔记