历史上的今天
返回首页

历史上的今天

今天是:2025年01月31日(星期五)

2020年01月31日 | 基于ROM的任意波形发生器(DDS)

2020-01-31 来源:elecfans

设计背景: 

    DDS(Direct Digital Synthesizer)直接数字式频率合成器,是一种新型频率合成技术,具有低成本、低功耗、高分辨率、相对带宽大和频率转换时间短等优点。较容易实现频率、相位以及幅度的数控调制,广泛应用在电信与电子仪器和通信领域。波形发生器是一种数据信号发生器,在调试硬件时,常常需要加入一些信号,以观察电路工作是否正常。加入的信号有:正弦波、三角波、方波和任意波形等。


设计原理: 

    相位(phase)是对于一个波,特定的时刻在它循环周期中的位置:一种它是否在波峰、波谷或它们之间的某点的标度。相位描述信号波形变化的度量,通常以度 (角度)作为单位,也称作相角。 当信号波形以周期的方式变化,波形循环一周即为360°。那么相位可调也可以简单的理解为:改变初始相位。


    频率,是单位时间内完成周期性变化的次数,是描述周期运动频繁程度的量,常用符号f或ν表示,单位为秒分之一,符号为s-1。频率可调也就是改变单位时间内完成周期性变化的次数。


    本设计采用DDS技术设计相位频率可调的波形发生器,已经知道了相位和频率可调分别代表什么,那么接下来就要知道怎样依靠DDS技术实现波形发生器,并且相位和频率可以调控。DDS的基本结构如下图所示:

    image.png?imageView2/2/w/550

    根据上图可以看出:DDS主要由相位累加器、波形数据表(ROM)、D/A转换器构成,本设计暂时不涉及D/A转换部分。相位累加器位宽为N,波形数据表的大小为2^P,累加器的高P位则用于寻址波形数据表,即ROM,从ROM中输出的数据则是产生的波形。如果累加器在系统时钟(CLOCK)的作用下,以步进为M累加直至溢出,则M为频率控制字(即图中的FWORD),相位控制字(PWORD)则作为累加器的输入初始值。这里的累加器,也可以理解为ROM的地址发生器。


    上段所述我们可具体理解为:改变地址的初值(PWORD)就可以改变初始的相位,由于我们设计中,ROM的数据为256,所以PWORD 的值在0~255之间,PWORD= 256*(初始相位/360度)。


    我们设计的系统时钟(CLOCK)为50MHz,周期为20ns,而正弦波被分成了256个点,波形发生器的频率就是195.31KHz。若想要输出别的频率,则可通过改变输出的点的个数,即改变有效地址的数量。我们用位宽为N位的累加器,假设FWORD为1,要产生一个完整波形的周期则为20ns*2^N,则产生波形的频率=系统时钟/2^N,即Fout = Fclk/2^N,如果FWORD为B,每次步进的间隔提高了B倍,所以计满一个波形周期的时间就缩小了B倍,即频率就提高了B倍。则波形频率的公式为:Fout = B*(Fclk/2^N)。之后我们取累加器的高8位,去寻址波形数据,对应点的还是个数一样的。本设计中我们将N取为32,当B=1,Fout约为0.012Hz,0.012就相当于最小精度,所以我们就实现了频率为0.012倍数的调制,但因为0.012值很小了,所以可以说基本实现了所有频率的调制。


设计架构图: 

    根据上述的原理图分析,本设计的架构如下图:

     image.png?imageView2/2/w/550

    

    架构图中的端口功能描述如下表:

    image.png?imageView2/2/w/550

    

    dds_addr模块是实现相位累加器的模块,这里用参数来调制FWORD和PWORD的值,累加之后,将地址高八位(addr_out)输出到rom模块,从而产生波形数据。

 

设计代码: 

    在具体写代码之前,我们需要先制作载有波形数据的mif文件,这时需要一个小软件(Mif_Maker2010),软件的链接如下:

    链接:http://pan.baidu.com/s/1gfzcOzL 密码:ietw


    具体操作步骤如下:

    打开Mif_Maker2010,在查看中点击全局参数,如下图:

    image.png?imageView2/2/w/550

    将全局参数设置如下图:数据长度为256,数据位宽为8,数据格式为无符号10进制,采样频率为1000。

    image.png?imageView2/2/w/550

    点击设定波形,选择想要生成的波形,这里我们以正弦波为例,如需要其他波形,都可进行修改:

    image.png?imageView2/2/w/550

    

    之后点击保存,则可生成mif文件,这里我们命名为sin.mif。打开sin.mif后,如下图所示:

    image.png?imageView2/2/w/550

    

    dds_addr模块代码:

    这里我们以初始相位为180度,频率为5KHz为例:

    

0   module dds_addr (clk, rst_n, addr_out);

2       input clk, rst_n;   //系统时钟复位

3       output [7:0] addr_out;  //输出的地址,对应到ROM内的数据

4        

5       parameter N = 32;

6       parameter PWORD = 128;  //相位控制字 (x/360)*256

7       parameter FWORD = 429497; //频率控制字F_out=B*(F_clk/2**32),fword=B

8       //5KHZ

9       reg [N-1:0] addr;  //32位累加器

10      

11      always @ (posedge clk or negedge rst_n)

12      begin

13          if (!rst_n)

14              begin

15                  addr <= 0;  

16              end

17          else

18              begin

19      /*每隔fword的大小,输出一位地址,若频率控制字FWORD等于2,那么地址计数器输出的就依次是0,2,4.....*/       

20                  addr <= addr + FWORD;

21              end     

22      end 

23      /*将累加器器的地址的高八位赋值给输出的地址(ROM的地址*/

24      assign addr_out = addr[N-1:N-8] + PWORD;

25

26  endmodule 

    rom模块为调用的IP核,该rom IP核中存储了sin.mif的数据。

    dds顶层模块代码:

    

0   module dds (clk, rst_n, q);

2       input clk, rst_n;   //系统时钟复位

3       output [7:0] q;     //输出波形数据

4       

5       wire [7:0] addr_out;  //8位地址,对应到ROM内的数据

6       

7       /*****相位累加器模块*****/

8       dds_addr dds_addr_inst(

9           .clk(clk), 

10          .rst_n(rst_n),

11          .addr_out(addr_out)

12      );

13      

14      /*****波形数据模块*****/

15      rom rom_inst (

16          .address ( addr_out ),

17          .clock ( clk ),

18          .q ( q )

19      );

20

21  endmodule 

dds_tb顶层模块的测试模块:

0   `timescale 1ns/1ps

2   module dds_tb;

4       reg clk, rst_n;

5       wire [7:0] q;

6       

7       initial begin

8           clk = 1;

9           rst_n = 0;

10          #200.1

11          rst_n = 1;

12          

13          #50_000_000 $stop;

14      end 

15

16      dds dds_dut(

17          .clk(clk), 

18          .rst_n(rst_n),

19          .q(q)

20      );

21      

22      always #10 clk = ~clk;

23

24  endmodule 


仿真图:

image.png?imageView2/2/w/550

根据上图可知,我们的设计正确。并且可以实现相位和频率可调。

推荐阅读

史海拾趣

驰兴电感(Coilank)公司的发展小趣事

驰兴电感自成立之初,就深知技术创新对于企业发展的重要性。公司投入大量资源进行研发,成功推出了一系列全自动、小型化的SMD绕线电感产品。这些产品不仅具有更高的性能和稳定性,而且满足了市场对小型化、轻量化的需求,迅速在市场上获得了广泛的认可。驰兴电感凭借技术创新的优势,逐渐在电子行业中崭露头角。

CUI Devices公司的发展小趣事

作为CUI Devices的重要组成部分,其电机品牌在近年来取得了显著的进步。公司的产品线涵盖了电位器、旋转编码器、步进电机、步进伺服电机和伺服电机等多个领域。通过不断的技术创新和市场拓展,CUI Devices的电机产品已经在全球范围内赢得了广泛的声誉和市场份额。

E-T-A [E-T-A Circuit Breakers]公司的发展小趣事

进入21世纪后,E-T-A公司开始关注智能电路保护技术的研发。公司投入大量资源进行技术创新,成功推出了多款智能电路保护产品。这些产品不仅具有更高的安全性和可靠性,还能实现远程监控和控制功能,为客户提供更加便捷和高效的服务。

Hitachi Chemical Co America Ltd公司的发展小趣事

进入1950年代,E-T-A公司开始关注固态远程电源控制器(SSRPCs)的研发。这一创新技术为电气系统提供了更加可靠和高效的电源管理方案。公司投入大量资源进行研发,成功推出了多款固态远程电源控制器产品,这些产品在市场上获得了广泛认可,并为公司带来了可观的收益。

DL Instruments LLC公司的发展小趣事

DL Instruments继承了Ithaco Corporation在精密仪器制造方面的技术积累,并在此基础上不断创新。公司推出了多种高性能的前置放大器产品,如低噪声电流前置放大器1211型、电流前置放大器1212型等。这些产品以其高阻抗差分或单端输入、共模抑制性能以及能在交流或直流耦合模式下运行的特点,赢得了市场的广泛认可。

Directed Energy Inc公司的发展小趣事

在电子行业中,创新是企业持续发展的关键。Directed Energy Inc始终将创新作为企业的核心竞争力之一,不断投入研发资源,推动技术创新和产品升级。公司拥有一支高素质的研发团队,他们紧跟行业发展趋势,不断探索新的技术和应用,为公司的发展注入了源源不断的动力。这种持续的创新精神使得Directed Energy Inc在电子行业中始终保持领先地位。

问答坊 | AI 解惑

最新IPHONE周边配件设计

本帖最后由 jameswangsynnex 于 2015-3-3 20:01 编辑 …

查看全部问答>

编写无错C程序秘诀

[ 本帖最后由 daicheng 于 2009-3-3 10:14 编辑 ]…

查看全部问答>

DOS下RS485双机通讯

问题有三: DOS下232串口编程和485串口编程有区别否,能通用吗? DOS下BC31写485通讯需要注意些什么? 有好点的类库推荐下吗? 谢谢!PS:我的双机是两个PC104…

查看全部问答>

什么时候我能看懂这个坛子里面大部分的贴?

什么时候我能看懂这个坛子里面大部分的贴?WINCE嵌入开发。那我就入门了。还是googleman老兄引领俺找到了这里。一来就离不开拉。努力努力在努力!这几天在eeworld的坛子里解决了很多应用程序的问题。继续学习! …

查看全部问答>

求教:DS生成的中断驱动程序

WIN2000下用DS编写ISA卡的带9号中断的驱动程序 用SOFTICE进行调试 INTOBJ看见中断39处是中断服务程序 用idt 39 看不到中断 服务程序 用GENINT 39软件出发中断,能过进入中断服务程序 可是让驱动程序运行后却截获不到任何关于9号中断的信息 这 ...…

查看全部问答>

LM3S9B96 能好买吗?多少一片啊?

TI那里没货申请不到哦! 市场上现在好买吗? 大概什么价格啊?…

查看全部问答>

关于MSP430G2231晶振问题

用示波器测P1.0脚观察ACLK输出,发现波形不是方波,频率一直在变从8HZ变到26K,难道是我芯片坏了吗?用万用表测试没有烧,在线等求助…

查看全部问答>

最近学习UART时老看到PSC,那PSC是什么东西呢?

最近学习UART是老是看到PSC如:UART_PSC、MCF_PSC_PSCSICR(channel) = MCF_PSC_PSCSICR_SIM_UART; 这个PSC是什么东西,我怎么在手册上找不到啊,搜索好像也没有什么号的解释呢,求解,谢谢!…

查看全部问答>

死循环的发生

在使用launchpad仿真时MSP430G2553时经常会出现变量参数溢出导致死循环,有没有哪位兄弟出现过这种问题啊, 例如void delay(uchar num) { while(num) num--; } 经常进入这里导致死循环。大家讨论下关于什么情况下会出现死循环吧…

查看全部问答>