小弟是初学者,刚刚学习Verilog不久,
想请问一道题目:如何用verilog 编写 频率可以控制的信号发生器(正弦或预先)
麻烦大牛们给出详细且具体的解答,万分感谢!!
先求出sin的多项逼近式,信号处理有讲,这样就可以用算法求解。预设一个周期显示点数。。。求出每个点对频率的值+DA就可以搞定
方案1 使用嵌入式内核(软核/硬核)生成所需数据,循环输出控制DA转换,放大输出。(一般的信号发生器就是这么做的)
方案2 如果预先确定的,如正弦信号/方波/三角波等,可以使用特定的算法实现来生成数据,如:正弦可以采用旋转坐标系的方法来实现。实时输出数据控制DA转换,放大输出。
我自己初学FPGA时所做的一个DDS,可产生频率可调的正弦波,方波,三角波。这个是报告,有基本原理介绍,图片可能传不上。
基于FPGA的直接数字频率合成器
的设计和实现
Txl
(hust automation)
摘要:直接数字频率合成技术是一种先进的频率合成技术。本文介绍了直接数字合成(DDS)的组成及工作原理,给出了基于公司的FPGA实现多波形信号发生器的设计过程,设计在QuartusⅡ中进行,应用硬件描叙语言Verilog,波形仿真后下载到FPGA芯片中实现频率可调的正弦波,三角波,方波三种波形。
关键词:FPGA,Verilog, 直接数字合成,波形发生器。
正 文:
一 引言
1971 年,美国学者J.Tierncy、C.M.Rader 和B.Gold 提出了以数字号处理理论为基础,从相位概念出发直接合成所需波形的一种新的全数字技术的频率合成方法。随着数字集成电路和微电子技术的发展和提高,一种新的频率合成技术——直接数字频率合成(DDS)得到了飞速的发展,它是继直接频率合成和间接频率合成之后发展起来的第三代频率合成技术。该技术在相对带宽、频率转换时间、相位连续性、正交输出、高分辨力以及集成化等一系列性能指标已远远超过了传统的频率合成技术所能达到的水平。
二DDS的组成和工作原理
DDS是利用信号相位与幅度的关系,对需要合成信号的波形进行相位分割,对分割后的相位值赋予相应的地址,然后按时钟频率以一定的步长抽取这些地址,因为它们对应相应的相位,从而也对应相应的幅度,这样按照一定的步长抽取地址(相位值)的同时,输出相应的幅度样值,这些幅度样值的包络反映了需要合成信号的波形。在时钟恒定时,合成信号的频率可以通过改变抽取地址的步长来改变,而如果在基准时钟后面加一级分频器电路,就可以通过改变时钟分频的方式在更大范围内调节输出信号的频率。图1是DDS的基本原理框图,包括基准时钟、相位累加器、相位寄存器、数据存储器(ROM查找表)、数模转换器(DAC)和低通平滑滤波器(LPF) 。
相位累加器由N位全加器和N位寄存器级联累加而成。每来一个时钟脉冲,相位累加器以频率控制字A为步长进行累加运算,产生所需的频率控制数据; 相位寄存器在时钟的控制下把累加的结果作为数据存储器(ROM)的地址(通常取其高十位的数据作为ROM的地址),对数据存储器(ROM)进行寻址,同时把累加运算的结果反馈给相位累加器,以便进行下一次累加运算。这样累加器在参考时钟的作用下,进行线形相位累加,当相位累加器累积满量时就会产生一次溢出,完成一个周期性的动作,这个周期便是DDS合成信号的一个周期,累加器的溢出频率便是DDS输出的信号频率。
由此可以知道对于位数为N的相位累加器,若频率控制字为A,则DDS系统输出的信号频率为:
可见,理论上通过设定相位累加器位数N,频率控制A和基准时钟的值,就可产生任一频率的输出。而频率的分辨率为:
由于基准频率一般固定,因此DDS的分辨率就取决于相位累加器的位数,相位累加器的为数越高,其分辨率也就越高。
数据存储器(ROM) 又称作查找表,实质是一波形存储器,其中存储离散后的波形幅值以及每个值对应的地址值。用相位累加器输出的数据作为取样地址,对波形存储器进行相位幅值转换,相位寄存器每寻址一次ROM, ROM就输出一个相对应的信号相位/幅度值,即可在给定的时间上确定输出的波形幅值。由于信号相位/幅度值用二进制码表示,如果需要输出模拟波形(例如正弦波) ,需送入D /A转换器进行数/模转换,最后经低通滤波器进行平滑处理,就可以得到平滑的信号波形了。
三 DDS的实现
1) 相位累加器和寄存器
在DDS的设计中,累加器是一个很关键的部分,它决定着频率的范围和分辨率。本设计中采用的是N=24位的二进制累加器和寄存器,其工作原理如图2所示:
在QuartusⅡ中实现DDS累加器和寄存器的设计如图3所示:其中累加器与寄存器在同一个模块中,累加器每加一次输入到寄存器中就进行一次锁存,再将锁存后的结果反馈给累加器作为其下一次累加的初始值。同时取锁存后的数据的
图3
高十位作为查表的地址值。在图3中 clk为系统时钟, fre_word 为输入24位的频率控制字,address为输出取锁存后取十位(其对应的离散波形为一个周期取1024点)的地址值。
2) 波形表的生成
在本设计中,DDS能输出三种波形,分别为方波,三角波和正弦波。为了
确不失真地输出原波形,将一个波形周期离散成1024对相位/幅值(也对应与前面的地址值),存储于表中。由于方波和三角波的实现算法相对简单,因此只是正弦波的算法用表来实现。
a.正弦波
正弦波的生成是先通过C语言实现正弦函数的算法并生成一个后缀为.mif 的文件sin.mif。其语言函数如下:
#include
#include"math.h"
void main()
{
int s;
int i;
FILE *fp;
fp=fopen("1024.mif","w+");
fprintf(fp," -- MAX+plus II - generated Memory Initialization File\n");
fprintf(fp," -- By 00022809\n\n\n\n\n");
fprintf(fp,"WIDTH=8;\n\n");
fprintf(fp,"DEPTH=1024;\n\n");
fprintf(fp,"ADDRESS_RADIX=HEX;\n\n");
fprintf(fp,"DATA_RADIX=HEX;\n\n");
fprintf(fp,"CONTENT BEGIN\n");
for(i=0;i<1024;i++)
{s=127+sin(atan(1.0)*8*i/1024)*127;
fprintf(fp,"%x\t:\t%x;\n",i,s);
}
fprintf(fp,"END;\n");
fclose(fp);
}
然后在QuartusⅡ生成一个基于 sin.mif 文件的后缀为 sin.v的文件,此文件即可作为一个模块来调用。其模块引脚图如图4所示:
图4
其中address为输入的地址值,clock为系统时钟,clken为使能信号,为高电平有效,q为输出的波形幅值。
b.方波的生成
方波算法比较容易实现。由于其只有高低电平两种状态,因此只需要在一个周期的时间中间位置翻转电平即可。其实现过程如下
由于相位累加器的值是线形累加的,因此地址address的值也是线形累加的,对所给地址值address进行判断,当地址值的最高位为0时,便将波形幅值各字位赋值1,否则赋值0。
c.三角波的生成
三角波的生成原理与方波生成原理相似,也是对地址address的值进行判断,当其最高位为0时,取其1~8位为三角波的波形幅值,即令q[7:0] =address[8:1]
当其最高位为1时,对其1~8位的值取反后再作为三角波的波形幅值,即令
q[7:0] = ~ address[8 : 1]。
3) 操作模块的实现
操作模块主要包括按键模块和状态转换模块
a.按键
在本设计中采用的是单脉冲式的按键模式,每按一次键,就产生一个标准时钟的脉冲。按键为低电平有效,检测到有键按下,便输出一个单脉冲。
b.状态转换
该模块是整个设计中的一个核心模块,其功能接受外部操作,并结合当前状态执行相应的处理,其实质是一个状态机。
在设计中一共用到了四个按键,各按键对应的功能如下表1:
键号 功能
1 复位键:在任何状态按下此键则输出频率为1Hz的正弦波
2 波形模式选择键:按键选择波形,每按一次键波形则改变一次,波形在正弦,方波,三角波三种模式下切换
3 频率挡位选择键:按键选择频率挡位,每按一次键选择到不同的频率挡位,频率一共分为四挡,分别为1Hz ~ 1KHz,
1KHz ~ 10KHz,10KHz ~ 200KHz,大于200KHz
4 频率步进选择键:按键选择频率步进值,每按一次键,其步进值根据此时所处的频率挡位的不同而不同:当频率处于1Hz ~ 1KHz 时,步进值为1Hz,当频率处于1KHz ~ 10KHz 时,步进值为100Hz,当频率处于10KHz ~ 200KHz 时,步进值为1KHz,当频率大于200KHz 时,步进值为10KHz,
表1 按键功能表
其程序的实现实质是一个Mealy状态机的实现,应用case语句对键值进行判断并进行各种状态的转换和对应操作。其模块引脚图如图5所示:
图5
其中 clk为系统时钟,keyin为输入键值,wavemode为输出波形模式值,length为输出频率控制字给累加器进行累加。
4) 频率显示模块的实现
频率显示模块所执行的功能是将当前输出波形的频率在LCD上显示出来。根据输出波形频率计算公式: 可知,只要知道了频率控制字A,标准时钟频率fclk,累加器的长度N,就可计算出输出频率 .
其实现过程依次用到的模块有:乘法模块,除法模块,二进制数转化为BCD码,LED显示模块。
小结:
本文简述了DDS的工作原理,介绍了DDS的FPGA实现。经实验证明,根据此思路设计的DDS具有频率范围宽,约为1Hz ~ 800K Hz,调节方便,波形高度保真的特点。但由于时间有限,其功能方便还有许多不足之处,有待进一步得到扩展。
查表法对于固定频率正余弦发生器很合适
但对于频率可控的, 只能用rotation法了
直接用芯片带的ip核就行了。xilinx的有nco,可以直接使用的,输出可以是正弦也可以是余弦,频率可控。几句代码即可完成。
如果是正余弦,就可以事先做张表,如5楼所说,然后在FPGA里面做一个ROM然后通过查询地址(address)经行调幅调相