基于FPGA的DDS信号发生器

前言

此处仅为基于Vivado实现DDS信号发生器的仿真实现,Vivado的安装请看下面的文章,这里我只是安装了一个标准版本,只要能够仿真波形即可。

FPGA开发Vivado安装教程_vivado安装 csdn-CSDN博客

DDS原理

DDS技术是一种通过数字计算生成波形信号的方法,其核心原理是利用数字相位累加器和波形查找表(ROM)生成高精度、频率可调的波形信号。DDS系统的主要组成部分包括频率控制字(Fword)、相位累加器、相位控制字(Pword)和波形查找表。

DDS的基本结构图如下所示:

在DDS系统中,频率控制字决定了输出波形的频率。频率控制字越大,相位累加器每个时钟周期增加的相位值就越大,从而输出波形的频率越高。相位累加器是DDS系统的核心部件,用于累加频率控制字。在每个时钟周期,相位累加器会将上一个周期的累加值与频率控制字相加,生成新的相位值。这个相位值用于波形查找表的地址生成。

要理解这个频率字对应的输出频率,可以使用以下公式:

f_{out}=\frac{F_{word}\times f_{clock}}{2^{N}}

其中,f_{out}是输出频率,F_{word}是频率控制字,f_{clock}是驱动DDS的时钟频率,N是相位累加器的位宽,通常是DDS设计中的一个常数。假设这里f_{clock}为50MHz,N为32位,输出频率位1MHz,那么频率控制字即为85899345(仅去整数部分)。

这里还比较了1MHz、500KHz、100KHz的正弦波信号,如下图所示。

相位控制字用于实现相位偏移,通过将相位控制字加到相位累加器的输出中,可以实现输出波形的相位偏移,从而便于同步或相位调制等应用。波形查找表存储了一个周期波形的数据,例如正弦波、方波和三角波。相位累加器的输出作为地址输入到波形查找表,查找到相应的波形数据输出。 

使用IP核生成ROM表

波形ROM模块通过查找表方式存储和输出波形数据。每种波形的数据表根据相应的波形公式预先计算并存储在ROM中。在系统运行过程中,DDS模块根据当前相位值读取ROM中的波形数据。

你可以使用软件去生成波形数据文件.coe文件。

在IP Catalog中找到ROM IP核,直接搜索即可。

修改名字,并且讲Memory Type类型改为Single Port ROM。

点击Port A Options修改宽度和深度。

 在换到Other Options选择我们刚刚生成的.coe文件路径。

接下来和之前的一样对方波和正弦波做同样的处理。然后切换到IP Sources,点击每个的.v文件

这里应当以你自己的标准为准,然后进行实例化。

DDS波形仿真

模块中实例化了三个波形生成子模块,这里应该按照你自己的方式来。

`timescale 1ns / 1ps

module DDS(
        Clk,
        Reset_n,
        Fword,
        Pword,
        mode,
        Data_out
    );
        input                         Clk;
        input                         Reset_n; 
        input [31:0]                  Fword;
        input [11:0]                  Pword;
        input [1:0]                   mode;  // 2位模式输入,用于选择波形
        output reg [13:0]             Data_out;  // 输出选择的波形数据
         
        // 频率控制字同步寄存器
        reg [31:0] Fword_r;
        always @(posedge Clk)
            Fword_r <= Fword;
        
        // 相位控制字同步寄存器
        reg [11:0] Pword_r;
        always @(posedge Clk)
            Pword_r <= Pword; 
        
        // 相位累加器    
        reg [31:0] Freq_ACC;
        always @(posedge Clk or negedge Reset_n)
            if (!Reset_n)
                Freq_ACC <= 0;
            else
                Freq_ACC <= Fword_r + Freq_ACC;
    
        // 波形数据表地址
        wire [11:0] Rom_Addr;      
        assign Rom_Addr = Freq_ACC[31:20] + Pword_r;
        
        // 波形数据输出
        wire [13:0] Data_sine;
        wire [13:0] Data_square;
        wire [13:0] Data_transqure;
        
        // 实例化正弦波模块
        sine_wav sine_wav (
            .clka(Clk),         // 输入时钟
            .ena(1'b1),         // 使能信号置高
            .addra(Rom_Addr),   // 输入地址
            .douta(Data_sine)   // 输出正弦波数据
        );
        
        // 实例化方波模块    
        square_wav square_wav (
            .clka(Clk),         // 输入时钟
            .ena(1'b1),         // 使能信号置高
            .addra(Rom_Addr),   // 输入地址
            .douta(Data_square) // 输出方波数据
        );
        
        // 实例化三角波模块    
        triangular_wav triangular_wav (
            .clka(Clk),            // 输入时钟
            .ena(1'b1),            // 使能信号置高
            .addra(Rom_Addr),      // 输入地址
            .douta(Data_transqure) // 输出三角波数据
        );
        
        // 多路复用器根据 mode 选择波形数据输出
        always @(*) begin
            case (mode)
                2'b00: Data_out = Data_sine;      // mode = 00 时输出正弦波
                2'b01: Data_out = Data_square;    // mode = 01 时输出方波
                2'b10: Data_out = Data_transqure; // mode = 10 时输出三角波
                default: Data_out = 14'b0;        // 默认情况下输出0
            endcase
        end

endmodule

仿真使用的tb文件

`timescale 1ns / 1ps

module DDS_tb;

       reg                         Clk;
       reg                         Reset_n; 
       reg [31:0]                  Fword;
       reg [11:0]                  Pword;
       reg [1:0]                   mode;
       wire [13:0]                 Data_out;

    DDS DDS(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Fword(Fword),
        .Pword(Pword),
        .mode(mode),
        .Data_out(Data_out)
    );

    initial Clk = 1;
    always #10 Clk = ~Clk;
    
    initial begin
        Reset_n = 0;
        Fword = 85899345;  // 1M初始频率控制字设置为较大值
        Pword = 0;
        mode = 2'b00;  // 选择正弦波
        #201
        Reset_n = 1;
        #20000
        
        Fword = 42949673;  // 500k更改频率控制字,降低频率
        #20000
        
        Fword = 8589935;  // 100k更改频率控制字,进一步降低频率
        #20000
        
        $stop;  
        
//     initial begin
//        Reset_n = 0;
//        Fword = 85899345;
//        Pword = 0;
//        mode = 2'b00;  // 正弦波
//        #201
//        Reset_n = 1;
//        #100000
        
//        mode = 2'b01;  // 方波
//        #100000
        
//        mode = 2'b10;  // 三角波
//        #100000
        
//        $stop;  
    end

endmodule

修改波的类型为模拟信号即可,对于方波这种还需要进行以下设置。

完整工程资源

按理来说,可以通过博客就完成了,但如果你比较懒,你可以从这里下载完整工程。

基于FPGA的DDS信号仿真资源-CSDN文库

因为这个模块只是一个课程设计的一部分,涉及到通过串口控制的部分由其他同学负责,因此这里仅记录我所完成的部分。我对FPGA的理解还有限,后续不会对这方面进行答疑。

参考文章

DDS原理及FPGA实现_dds fpga-CSDN博客

基于FPGA的DDS算法实现(可调幅值,附ISE联合Modelsim仿真结果)-CSDN博客

基于FPGA的DDS信号发生器-CSDN博客 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/766764.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux shell编程学习笔记61: pstree 命令——显示进程树

0 前言 在 Linux shell编程学习笔记59&#xff1a; ps 获取系统进程信息&#xff0c;类似于Windows系统中的tasklist 命令https://blog.csdn.net/Purpleendurer/article/details/139696466?spm1001.2014.3001.5501 中我们研究了ps命令。在Linux中&#xff0c;通过ps命令&am…

Perl语言入门指南

一、绪论 1.1 Perl语言概述 1.2 Perl的特色 1.3 Perl面临的问题 1.4 Perl语言的应用领域 二、Perl语言基础 2.1 Perl语言的历史发展 2.2 Perl语言的基本语法 2.3 Perl语言的数据类型 三、Perl语言控制结构 3.1 条件语句 3.2 循环结构 3.3 函数和子程序 四、Perl语…

RK3568驱动指南|第十五篇 I2C-第183章 SMBus总线介绍

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

电脑版微信自动发送微信消息给好友或者群聊

一.软件下载 点击微信自动发送消息下载 二.相关使用方法 1.打开软件&#xff0c;输入想自动发送的内容 2.确保登录了微信电脑版【PC端】&#xff0c;然后切换到想要自动发送的好友或群聊的窗口。 3.点击开始&#xff0c;现在自动发送即可&#xff0c;稍等三秒程序自动运行。 …

小程序开发平台版源码系统——万能门店小程序功能 前后端分离 带完整的安装代码包以及搭建教程

系统概述 在移动互联网的浪潮中&#xff0c;小程序以其轻量、便捷、无需下载即可使用的特点&#xff0c;迅速成为连接用户与商家的新桥梁。为了满足广大商家快速搭建个性化、高效运营的小程序需求&#xff0c;我们精心打造了“小程序开发平台版源码系统——万能门店小程序功能…

秋招——MySQL补充——MySQL是如何加行级锁

文章目录 引言正文什么SQL语句会加行级锁查询操作增加对应的行级锁事务的写法 update和delete修改操作也会增加行级锁 行级锁有哪些种类记录锁间隙锁Next-Key锁 MySQL是如何加行级锁&#xff1f;唯一索引等值查询查询记录是存在的查询记录是不存在的 唯一索引范围查找针对大于或…

【python脚本】批量检测sql延时注入

文章目录 前言批量检测sql延时注入工作原理脚本演示 前言 SQL延时注入是一种在Web应用程序中利用SQL注入漏洞的技术&#xff0c;当传统的基于错误信息或数据回显的注入方法不可行时&#xff0c;例如当Web应用进行了安全配置&#xff0c;不显示任何错误信息或敏感数据时&#x…

Element中的消息提示组件Message和弹框组件MessageBox

简述&#xff1a;在 Element UI 中&#xff0c;Message和MessageBox都是比较常用的组件&#xff0c;Message用来提示消息&#xff0c;而MessageBox是一个用于创建模态对话框的组件。它可以用于在页面上快速展示信息、警告或错误提示&#xff0c;而不会阻止用户的其他操作。简单…

Pandas_DataFrame读写详解:案例解析(第24天)

系列文章目录 一、 读写文件数据 二、df查询数据操作 三、df增加列操作 四、df删除行列操作 五、df数据去重操作 六、df数据修改操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、 读写文…

华为DCN之:SDN和NFV

1. SDN概述 1.1 SDN的起源 SDN&#xff08;Software Defined Network&#xff09;即软件定义网络。是由斯坦福大学Clean Slate研究组提出的一种新型网络创新架构。其核心理念通过将网络设备控制平面与数据平面分离&#xff0c;从而实现了网络控制平面的集中控制&#xff0c;为…

深入理解C++中的锁

目录 1.基本互斥锁&#xff08;std::mutex&#xff09; 2.递归互斥锁&#xff08;std::recursive_mutex&#xff09; 3.带超时机制的互斥锁&#xff08;std::timed_mutex&#xff09; 4.带超时机制的递归互斥锁&#xff08;std::recursive_timed_mutex&#xff09; 5.共享…

图解 Kafka 架构

写在前面 Kafka 是一个可横向扩展&#xff0c;高可靠的实时消息中间件&#xff0c;常用于服务解耦、流量削峰。 好像是 LinkedIn 团队开发的&#xff0c;后面捐赠给apache基金会了。 kafka 总体架构图 Producer&#xff1a;生产者&#xff0c;消息的产生者&#xff0c;是消息的…

android AIDL使用demo

背景 最近打算学习一下如何在framework层添加一个自定义service。 了解到自定义service需要使用aidl&#xff0c;为了加强对aidl的了解和使用过程&#xff0c;特意又温习了一下aidl的使用&#xff0c;并用博客的形式记录下来。 aidl官方参考&#xff1a;https://developer.and…

不同系统间数据交换要通过 api 不能直接数据库访问

很多大数据开发提供数据给外部系统直接给表结构&#xff0c;这是不好的方式。在不同系统间进行数据交换时&#xff0c;通过API&#xff08;应用程序编程接口&#xff09;而非直接访问数据库是现代系统集成的一种最佳实践。 目录 为什么要通过API进行数据交换如何通过API进行数据…

论文辅导 | 基于多尺度分解的LSTM⁃ARIMA锂电池寿命预测

辅导文章 模型描述 锂电池剩余使用寿命&#xff08;Remaining useful life&#xff0c;RUL&#xff09;预测是锂电池研究的一个重要方向&#xff0c;通过对RUL的准确预测&#xff0c;可以更好地管理和维护电池&#xff0c;延长电池使用寿命。为了能够准确预测锂电池的RUL&…

STM32 看门狗 HAL

由时钟图可以看出看门狗采用的是内部低速时钟&#xff0c;频率为40KHz 打开看门狗&#xff0c;采用32分频&#xff0c;计数1250。 结合设置的分频系数和重载计数值&#xff0c;我们可以计算出看门狗的定时时间&#xff1a; 32*1250/40kHz 1s 主函数中喂狗就行 HAL_IWDG_Ref…

STM32 HAL库读取ID

在stm32f1xx_hal.c文件中由读取ID号的子函数&#xff0c;不同单片机的UID_BASE不同&#xff0c;本单片机用的是STM32F103CBT6,跳转之后可以看到地址为&#xff1a;0x1FFFF7E8 在程序中只需定义一个数组调用读取ID的函数即可 uint32_t UID[3]; while(1) { UID[0] HAL_GetUIDw0…

catia数控加工仿真铣平面粗加工

1&#xff0c;零件建模&#xff0c;毛坯建模 2 在毛坯上建立坐标系 3 添加资料刀具 4&#xff0c;双击对相关加工信息做设置 5 Roughing 加工设置 高亮红色区域是必选的&#xff0c;其他可以默认 6 完成加工仿真 7 加工余量

EasyExcel4导入导出数据(基于MyBatisPlus)

一、POM依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><m…

Camera Raw:编辑 - 细节

Camera Raw “编辑”模块中的细节 Detail面板用于增强照片的锐度和减少噪点。通过对锐化和降噪进行精细调整&#xff0c;可以提高图像的清晰度&#xff0c;减少噪点&#xff0c;提高图像质量。 ◆ ◆ ◆ 使用方法与技巧 1、增强照片锐度 较小的“半径”&#xff0c;较大的“细…