先说说DDS算法 的基本原理:

DDS是直接式数字频率合成的简称。它在无线通信系统实现中是一门关键技术。其实,DDS在FPGA中的实现方法说白了就是在定义好的ROM数据中寻址并找到该地址对应的波形数据。在系统参考时钟的驱动下,通过控制频率控制字来驱动相位累加寄存器数值的变化,从而是在ROM中寻址并找到对应数据,最后输出为波形数据。其中,在每一个系统时钟脉冲来临时,相位累加寄存器都会相应叠加一次频率控制字。其实,频率控制字的功能就是控制步进长度,也就是形成的波形的频率和系统时钟频率的比例关系,最终可以确定输出波形的频率。比如要输出正弦波,系统参考时钟频率为20M,输出每位宽度为10bit,则令频率控制字位宽为20bit,f(out)=(频率控制字/2^20)*f(clk)。这样就可以控制输出波形的频率。

本人用的是QUETUS II开发环境。对于quatus ii 中ROM 可用的数据文件格式为mif。此文件数据可以用MATLAB来产生。

具体产生方法如下:

新建一个.m文件,然后输入:

width=10;//位宽
depth=2^width;//数据深度
t=linspace(0,6.28,depth);
sin_val=sin(t);
cos_val=cos(t);
sin_val=fix(sin_val*(2^width-1)/2+0.5);//四舍五入求结果
cos_val=fix(cos_val*(2^width-1)/2+0.5);

addr=[0:1023];
%存盘
file=fopen('f:/My Works/FPGA Examples/sin.mif','wt');
fprintf(file,'WIDTH=%d;\n',width);
fprintf(file,'DEPTH=%d;\n',depth);
fprintf(file,'ADDRESS_RADIX=UNS;\n');
fprintf(file,'DATA_RADIX=DEC;\n');//这个数据格式最好不要变,不然改动会很麻烦
fprintf(file,'CONTENT BEGIN\n');
for i=1:depth
    fprintf(file,'%d:%d;\n',addr(i),sin_val(i));
end
fprintf(file,'END;\n');
fclose(file);

file=fopen('f:/My Works/FPGA Examples/cos.mif','wt');
fprintf(file,'WIDTH=%d;\n',width);
fprintf(file,'DEPTH=%d;\n',depth);
fprintf(file,'ADDRESS_RADIX=UNS;\n');
fprintf(file,'DATA_RADIX=DEC;\n');
fprintf(file,'CONTENT BEGIN\n');
for i=1:depth
    fprintf(file,'%d:%d;\n',addr(i),cos_val(i));
end
fprintf(file,'END;\n');
fclose(file);

上述程序可以产生可用的mif文件数据,并可以导入ROM中。

最后就是编写verilog代码。

module DDS(clk,rst,A,
           data0,data1,data2,data3,
           out_signal0,out_signal1,out_signal2,out_signal3,
           we,ddse
           );
           
input clk;
input rst;
input we;
input ddse;
input[3:0] A;
input[19:0] data0;
input[19:0] data1;
input[19:0] data2;
input[19:0] data3;
output[9:0] out_signal0;
output[9:0] out_signal1;
output[9:0] out_signal2;
output[9:0] out_signal3;

reg[19:0] ADD_A[3:0];
reg[19:0] ADD_B0,ADD_B1,ADD_B2,ADD_B3;
reg[9:0] signal_r[3:0];

wire[9:0] signal_d[3:0];
wire[9:0] ROM[3:0];

assign out_signal0=signal_r[0];
assign out_signal1=signal_r[1];
assign out_signal2=signal_r[2];
assign out_signal3=signal_r[3];
assign ROM[0]=ADD_B0[19:10];
assign ROM[1]=ADD_B1[19:10];
assign ROM[2]=ADD_B2[19:10];
assign ROM[3]=ADD_B3[19:10];

always@(posedge clk or negedge rst) begin
          if(!rst) begin ADD_A[0] <= 20'b0; ADD_A[1] <= 20'b0;
                         ADD_A[2] <= 20'b0; ADD_A[3] <= 20'b0;
                   end
          else if(we)
            begin
              if(A==3'b0) begin ADD_A[0] <= 20'b0; ADD_A[1] <= 20'b0;
                                ADD_A[2] <= 20'b0; ADD_A[3] <= 20'b0;
                          end
              else begin ADD_A[0] <= data0; ADD_A[1] <= data1;
                         ADD_A[2] <= data2; ADD_A[3] <= data3;
                   end
            end
          else begin ADD_A[0] <= 20'b0; ADD_A[1] <= 20'b0;
                     ADD_A[2] <= 20'b0; ADD_A[3] <= 20'b0;
               end
end

always@(posedge clk or negedge rst) begin
          if(!rst) begin ADD_B0 <= 20'b0;ADD_B1 <= 20'b0;
                         ADD_B2 <= 20'b0;ADD_B3 <= 20'b0;
                   end
          else if(ddse)
            begin
               if(A) begin
                   ADD_B0 <= ADD_A[0] + ADD_B0;
                   ADD_B1 <= ADD_A[1] + ADD_B1;
                   ADD_B2 <= ADD_A[2] + ADD_B2;
                   ADD_B3 <= ADD_A[3] + ADD_B3;
                end
                else begin ADD_B0 <= 20'b0;ADD_B1 <= 20'b0;ADD_B2 <= 20'b0;ADD_B3 <= 20'b0; end
            end
          else begin ADD_B0 <= ADD_B0; ADD_B1 <= ADD_B1;ADD_B2 <= ADD_B2;ADD_B3 <= ADD_B3; end
end

always@(posedge clk or negedge rst) begin
          if(!rst) begin signal_r[0] <= 10'b0; signal_r[1] <= 10'b0;
                         signal_r[2] <= 10'b0; signal_r[3] <= 10'b0;
                   end
          else if(ddse)
               begin if(A)
                   begin
                    case(A)
                     4'b0001:begin signal_r[0] <= signal_d[0]; signal_r[1] <= 10'b0;
                                  signal_r[2] <= 10'b0;       signal_r[3] <= 10'b0;
                            end
                     4'b0010:begin signal_r[0] <= 10'b0;      signal_r[1] <= signal_d[1];
                                  signal_r[2] <= 10'b0;       signal_r[3] <= 10'b0;
                            end
                     4'b0011:begin signal_r[0] <= signal_d[0]; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= 10'b0;        signal_r[3] <= 10'b0;
                            end
                     4'b0100:begin signal_r[0] <= 10'b0;      signal_r[1] <= 10'b0;
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= 10'b0;
                            end
                     4'b0101:begin signal_r[0] <= signal_d[0]; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= signal_d[3];
                            end
                     4'b0110:begin signal_r[0] <= 10'b0; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= 10'b0;
                            end
                     4'b0111:begin signal_r[0] <= signal_d[0]; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= 10'b0;
                            end
                     4'b1000:begin signal_r[0] <= 10'b0; signal_r[1] <= 10'b0;
                                  signal_r[2] <= 10'b0; signal_r[3] <= signal_d[3];
                            end
                     4'b1001:begin signal_r[0] <= signal_d[0]; signal_r[1] <= 10'b0;
                                  signal_r[2] <= 10'b0; signal_r[3] <= signal_d[3];
                            end
                     4'b1010:begin signal_r[0] <= 10'b0; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= 10'b0; signal_r[3] <= signal_d[3];
                            end
                     4'b1011:begin signal_r[0] <= signal_d[0]; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= 10'b0; signal_r[3] <= signal_d[3];
                            end
                     4'b1100:begin signal_r[0] <= 10'b0; signal_r[1] <= 10'b0;
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= signal_d[3];
                            end
                     4'b1101:begin signal_r[0] <= signal_d[0]; signal_r[1] <= 10'b0;
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= signal_d[3];
                            end
                     4'b1110:begin signal_r[0] <= 10'b0; signal_r[1] <= signal_d[1];
                                  signal_r[2] <= signal_d[2]; signal_r[3] <= signal_d[3];
                            end
                     4'b1111:begin signal_r[0] <= signal_d[0]; signal_r[1] <= signal_d[1];
                                   signal_r[2] <= signal_d[2]; signal_r[3] <= signal_d[3];
                             end
                     default:begin signal_r[0] <= 10'b0; signal_r[1] <= 10'b0;
                                   signal_r[2] <= 10'b0; signal_r[3] <= 10'b0;
                             end
                     endcase
                   end
                   else begin signal_r[0] <= 10'b0; signal_r[1] <= 10'b0;
                              signal_r[2] <= 10'b0; signal_r[3] <= 10'b0;
                        end
               end
          else begin signal_r[0] <= 10'b0; signal_r[1] <= 10'b0;
                     signal_r[2] <= 10'b0; signal_r[3] <= 10'b0;
               end
end

rom_sin rom_sin1(
                 .address(ROM[0]),
                 .clock(clk),
                 .q(signal_d[0])
                 );
                 
rom_sin rom_sin2(
                 .address(ROM[1]),
                 .clock(clk),
                 .q(signal_d[1])
                 );
                 
rom_cos rom_cos1(
                 .address(ROM[2]),
                 .clock(clk),
                 .q(signal_d[2])
                 );  
                 
rom_cos rom_cos2(
                 .address(ROM[3]),
                 .clock(clk),
                 .q(signal_d[3])
                 );
            
endmodule

上述代码的功能是实现四路自选信号的产生,但是说实话,本程序是没有使用价值的,因为IO端口占用太多,没有复用,只是觉得好玩,编写着看看的。

从图中可以看到有很多毛刺,需要改进,这个要今后再说。

DDS的verilog 实现个人总结相关推荐

  1. DTMF双音频信令检测,基于Goertzel(戈泽尔算法),FPGA实现

    目录 1.引言 2.细节介绍 3.DTMF双音频信号的产生 4.DTMF双音频信号的检测 4.1(Goertzel)戈泽尔算法的使用 4.2戈泽尔算法的详细计算过程 4.3计算的优化 4.3.1时间复 ...

  2. DDS发生器的verilog实现(三)

    DDS发生器的verilog实现(三) 前面讲解了正弦波发生器和DDS基础知识,这篇文章主要讲解如何在fpga上实现DDS发生器,同时对上一篇的文章进行补充. 确定频率控制字的DDS发生器 首先对初始 ...

  3. 基于verilog 实现的DDS的发生器

    关于DDS具体理论可以查看我的上一篇博客 https://blog.csdn.net/weixin_45614076/article/details/124973803?spm=1001.2014.3 ...

  4. 基于FPGA的DDS直接数字频率合成器,频率和相位控制字可配置,在vivado2019.2平台中verilog开发.含testbench

    目录 1.算法概述 2.仿真效果 3.verilog程序 1.算法概述 DDS同DSP(数字信号处理)一样,也是一项关键的数字化技术.DDS是直接数字式频率合成器(Direct Digital Syn ...

  5. 【FPGA Verilog】手把手教你实现一个DDS信号发生器

    信号发⽣器的设计与实现 1.输出波形:⽅波(占空⽐50%).锯⻮波.三⻆波.脉冲信号(占空⽐连续可调).正弦波.任意波等 2.输出频率:100KHz 3.波形选择:使⽤拨码开关选择 思路: 使用FPG ...

  6. 六、基于Verilog的信号发生器DDS的设计

    1.前言 采用 Verilog 设计了一个简单的信号发生器,可输出正弦波.方波.三角波.锯齿波这 4 种频率.相位和幅值可调的波形. 2.具体功能 module dds(input wire clk, ...

  7. ​基于Verilog的DDS波形发生器的分析与实现(三角波、正弦波)

    原文作者:FPGA设计论坛 基于Verilog的DDS波形发生器的分析与实现(三角波.正弦波) 最近学习了一下关于DDS的相关知识,本篇概要记录一下自己的理解与实现. DDS信号发生器采用直接数字频率 ...

  8. AD9910高速集成DDS芯片(verilog篇-串行模式篇-22个寄存器SPI通信周期控制)

    文章目录 0.引言 1.verilog思路 2.modelsim调试 3.总结 0.引言 经过对疫情期间某天下午写的代码进行,多次调试后,终于输出了波形,下面我们逐步跟着思路,对22个寄存器不同长度的 ...

  9. verilog宏功能中dds信号发生器_什么是相位相干性?了解生成相位相干射频信号的三种配置方法...

    如何克服多天线系统面临的测试挑战???测试多天线系统时,要求测试系统必须能够提供多个信号,并且信号之间要有恒定的相位关系.生成相位相干信号时,不同的配置方法会导致不同的测量结果. 概述 随着更高吞吐量 ...

最新文章

  1. 德勤发布《中国智能制造分析报告》
  2. Design Pattern: Singleton 模式
  3. linux下面jmeter对百度进行压力测试
  4. 【Mac】mac 安装Axure RP 8 点不开 就一直跳-后闪退-报错Expected an Int64 but got a System.UInt64
  5. 第2章 自由落体的小球(《C和C++游戏趣味编程》配套教学视频)
  6. 计算机打印机节支措施,“节支降耗,从我做起 ”倡导篇 ——节约纸张
  7. TCP的三次握手和四次挥手(超详解)
  8. 数理统计实(试)验—双因素方差分析(无交互作用)excel操作分析方差分析表怎么看?
  9. YOLO7 姿势识别实例
  10. 续费Namecheap域名教程附如何便宜续费域名方法
  11. c#未能加载程序集oracle.dataaccess,未能加载文件或程序集“Oracle.DataAccess, Version=2.112.1.0...
  12. 利用计算机画统计图.doc,信息技术应用利用计算机画统计图.pptx
  13. 怎么做好数据可视化(文末送书)
  14. 滴滴一技术总监4年累计受贿1000万,被开除并移送公安机关
  15. 《新概念英语》有声电子书的实现
  16. xgboost算法_xgboost算法原理篇
  17. HDU 2547 无剑无我 水水。。
  18. nsis 学习笔记(2)
  19. 麒麟985和骁龙865哪个好
  20. JUC 三大辅助类解读

热门文章

  1. 201819102040张辰飞
  2. 影音视频领域开源项目专区
  3. 就在这一天,我结束了北漂的生活
  4. 工程行业管理系统-专业的工程管理软件-提供一站式服务
  5. 9343拆机 xps13_《拆机Pa》十二期 第二代XPS 13是进步还是退步
  6. 【华人学者风采】李海洲 新加坡国立大学
  7. arduino: 各种Arduino基础器件的用法图
  8. html+css:自定义鼠标指针图案
  9. 30天敏捷生活(12): 整理你的空间
  10. 将正式数据库中的表与测试库同步