DDS设计报告带程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

电子线路课程设计直接数字频率合成计
摘要
本实验通过使用QuartusⅡ7.1软件,并结合verilog语言的知识设计直接频率合成器,简
212⨯类型的芯片实现,基准频率为1MHz,称DDS。

DDS中的正余弦波形存储器模块用10
利用实验箱上的D/A转换器件将ROM输出的数字信号转换为模拟信号,能够通过示波器观察到正、余弦两路波形。

除此之外,本实验还实现了多种波形任意切换,0-200kHz频率任意可调,并在数码管上显示生成的波形频率等附加功能。

关键词
QuartusII,直接数字频率合成计(DDS),Verilog HDL,状态机
Abstract
In this study, by using QuartusⅡ7.1 software, combined with the knowledge of verilog-language, we designed the direct frequency synthesizer, also called DDS. The type of sine
212⨯. And the reference frequency is 1MHz. and cosine waveform memory module in DDS is 10
Passing through the D/A experimental box, the digital signal conversion device converts the output of the ROM to an analog signal. We can observe two waveform on the screen of oscilloscope. In addition, this experiment also implements an arbitrary waveform switching, a 0-200kHz arbitrary frequency switching, and the resulting waveform frequency displaying.
Key words
QuartusⅡ, Direct frequency synthesizer , Verilog HDL, State machine
目录
一、设计要求 (3)
二、分层设计及其分工 (3)
三、直接数字频率合成计顶层设计 (4)
四、各子模块设计原理及程序 (5)
4.1 分频电路 (5)
4.2 相位累加器和数据锁存器器电路 (6)
4.3 波形存储器ROM的生成 (6)
4.4 三角波及方波输出电路 (7)
4.5 波形的综合输出电路 (8)
4.6 状态机控制电路 (8)
4.7 状态机专用消颤电路 (10)
4.8 LED频率显示电路 (11)
五、程序下载、仿真与调试 (13)
5.1 管脚设定 (13)
5.2 修改Device&Pins Options 及重新编译 (14)
5.3 程序下载及运行结果 (15)
六、实验中遇到的问题及其应对方案 (15)
七、实验总结与感想 (15)
八、参考文献 (16)
一、设计要求
1.1 设计基本部分要求
①利用QuartusII 软件和SmartSOPC 试验箱实现DDS 的设计;
②DDS 中的波形存储器模块用Altera 公司的CycloneIII 系列FPGA 芯片中的ROM 实现,
ROM 结构配置成10212
⨯类型;
③具体参数要求:频率控制字K 取4位;基准频率
MHz f c 1=,由实验板上的系统时钟分频得到;
④系统具有使能功能;
⑤利用实验箱上的D/A 转换器件将ROM 输出的数字信号转换为模拟信号,能够通过示波器观察到正、余弦两路波形;
⑥通过开关输入DDS 的频率和相位控制字,并能用示波器观察加以验证;
1.2 设计提高部分要求
①通过按键(实验箱上的Si )输入DDS 的频率和相位控制字,以扩大频率控制和相位控制的范围;(注意:按键后有消颤电路)
②在数码管上显示生成的波形频率;
③设计能输出多种波形(三角波、锯齿波、方波等)的多功能波形发生器; ④充分考虑ROM 结构及正弦函数的特点,进行合理的配置,提高计算精度; ⑤基于DDS 的AM 调制器的设计;
⑥自己添加其他功能。

二、分层设计及其分工
2.1 分层设计
为了实现直接数字频率合成计,我们采用了Verilog 语言描述其功能,如图2.1所示,为本实验的层次分析设计结构图。

图2.1 直接数字频率合成计的层次模型
①原始分频电路将系统提供的48MHz晶振频率分为1MHz的基础频率,是所有子模块中clk的基础。

②状态机可以实现复位、波形切换、0-200kHz频率任意可调的功能。

③LED电路通过对频率与相位控制字的相对数量计算,实现了显示频率的功能
2.2 分工情况
整个直接数字频率合成器设计由郑蕤荻和我(徐洁)共同完成,既有明确的分工以提高效率,也有互相帮助,互相指出错误的合作过程,以下为我们两个人明确分工的情况:***:DDS频率发生器顶层设计、状态机控制电路、LED显示电路;
**:三种波形的生成、状态机专用消颤电路、相位累加器及锁存器、分频电路。

.
三、直接数字频率合成计顶层设计
DDS为整个直接数字频率合成计的顶层设计,它直接或间接的调用了所有的子程序,实现了将整个底层程序贯穿联接的功能,规定了直接数字频率合成计的输入和输出。

输入有:EP3C25F324C8的自带晶振频率48MHz,键入值;输出有:波形数据,LED管的位码和段码,接地信号。

verilog语言程序如下:
module
dds(_48MHz,keyin,wavevalue,wavevalue2,Segout,SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8,GND, GND2,clk);
input _48MHz;
output clk;
output GND,GND2;
input[3:0]keyin;
output [9:0]wavevalue,wavevalue2;
output[6:0]Segout;
output SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8; //select LED
wire[11:0]address;
wire[1:0]wavemode;
wire[23:0]length;
wire [9:0]wavevalue,wavevalue2;
wire [3:0] keyOUT;
wire _48MHz,clk;
supply0 GND,GND2;
key S0(clk,keyin,keyOUT);
Original_Frequency S1(_48MHz,clk);
control S2(clk,keyOUT,wavemode,length);
counter S3(clk,length,address);
selection S4(clk,address,wavemode,wavevalue);
cos_rom S5(address,clk,wavevalue2);
shumaguan S6(clk,length,Segout,SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8);
endmodule
四、各子模块设计原理及程序
4.1 分频电路
分频模块是为了实现EP3C25F324C8的自带晶振频率48MHz,往1MHz的分频,主体思想是使用一个模48计数器直接取其最高位,下面是该电路的verilog程序:
//Original_Frequency.v
module Original_Frequency (_48MHz,_1MHz);
input _48MHz;
output _1MHz;
reg [3:0] CntH,CntL;
wire _1MHz;
always@(posedge _48MHz)
begin
if ((CntH>4)||(CntL>9)||(CntH==4)&&(CntL>=7))
{CntH,CntL}<=8'h00;
else if ((CntH==4)&&(CntL<7))
begin CntH<=CntH; CntL<=CntL+1'b1;end
else if (CntL==9)
begin CntH<=CntH+1'b1; CntL<=4'b0000;end
else
begin CntH<=CntH; CntL<=CntL+1'b1;end
end
assign _1MHz=CntH[2];
endmodule
分频电路的仿真波形图如下:
4.2 相位累加器和数据锁存器器电路
相位累加器是DDS系统设计的核心,它决定着频率的范围和分辨率。

本设计中采用的是24位的二进制累加器和寄存器,其中累加器与寄存器在同一个模块中,并取锁存数据的高十位作为查表的地址值。

V erilog程序如下:
//counter.v
module counter(clk,fre_word,address);
input clk;
input [23:0]fre_word;
output reg [11:0]address;
reg [23:0] phaseadder;
always@(posedge clk)
begin
phaseadder= phaseadder+fre_word;
address= phaseadder[23:12];
end
endmodule
4.3 波形存储器ROM的生成
在我们的程序中,波形存储器ROM是由VC++程序生成的,以*.mif文件的格式存放在电脑中,并可以被QuartusII调用。

程序及其原理简介如下:
#include<stdio.h>
#include"math.h"
void main ()
{ int s;
int i;
FILE* fp;
fp=fopen("4096.mif", "w+"); //新建4096.mif文件,只写模式
fprintf (fp,"- - MAX+ plus - generated Memory Initialization File\n");
fprintf (fp,"- - By Di and Jie\n\n\n\n\n"); //作者
fprintf (fp,"WIDTH=10;\n\n"); //定义字宽
fprintf (fp,"DEPTH=4096;\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<4096;i++)
{s=512+511*sin(i*atan(1.0)*8/4096); //512和511是为了最大的利用sinx小数点后面的有效内容,并将其调节为x轴上方的无符号数,4*atan(1.0)为π,再乘以2i除以4096是将sin的一个周期分为4096个值。

fprintf(fp,"% x\t:\t%x;\n",i,s);} //Quartus调用*.mif文件时所需满足的格式fprintf(fp,"END;\n"); // 内存结束
fclose (fp);
}
余弦波文件的生成与正弦波文件的生成是一样的,只是将公式改为
{s=512+511*sin(i*atan(1.0)*8/4096+2*atan(1.0));当然,这样做只是为了简便编程者的操作,我们也可以将address的值加上4096/4之后进行寻址,便可以减少内存的使用。

4.4 三角波及方波输出电路
由于方波只有高、低电平两种状态,因此只需要在一个周期时间的中间位置翻转电平就可以形成方波。

程序及其原理简介如下:
//fangbo.v
module fangbo(clk,enable,address,qsquare);
input clk;
input enable;
input [11:0]address;
output reg [9:0] qsquare;
always@(posedge clk)
if (!enable) qsquare=10'b00_0000_0000;
else begin
if (address<=12'b0111_1111_1111)
qsquare[9:0]=10'b11_1111_1111; //利用address在中间位置实现翻转else qsquare [9:0]=10'b00_0000_0000;
end
endmodule
三角波则是先判断出address的中间状态,然后将address或address的非赋给相应的输出,即可得到我们所需的三角波。

其verilog语言及原理简介如下:
//sanjiao.v
module sanjiao (clk,enable,address,qtriangle);
input clk,enable;
input [11:0]address;
output [9:0] qtriangle;
reg [9:0] qtriangle;
always@(posedge clk)
if (! enable) qtriangle=10'b00_0000_0000;
else begin
if (address<=12'b0111_1111_1111)
qtriangle[9:0]= address[10:1];
else qtriangle[9:0]=~address [10:1]; //address的非与address一个递减一个递增,正好形成了三角波的一个周期。

end
endmodule
4.5 波形的综合输出电路
有了三种波形,就要在特定时刻进行选择,在每一个时刻只能有一种波输出,在示波器上显示,所以用case语句写了一个选择性输出,程序如下:
//selection.v
module selection (clk,address,wavemode,wavevalue);
input clk;
input [1:0]wavemode;
input [11:0]address;
output [9:0]wavevalue;
reg [9:0] wavevalue;
wire [9:0]wavevalue1,wavevalue2,wavevalue3;
wire [9:0]q;
supply1 Vdd;
fangbo U0(clk,Vdd,address,wavevalue2);
sanjiao U1(clk,Vdd,address,wavevalue3);
sin_rom U2(address,clk,q);
assign wavevalue1=q;
always@(posedge clk)
case (wavemode)
2'b01: wavevalue= wavevalue1;
2'b10: wavevalue= wavevalue2;
2'b11: wavevalue= wavevalue3;
endcase
endmodule
4.6 状态机控制电路
状态机控制电路主要包括按键模块和工作模块两个部分,由于按键的有限性,状态机的利用大大的提高开关的利用率,使得我们0-200kHz频率任意切换的功能得以实现。

其verilog 程序如下,思路清晰,使用简便,将在实验结果中具体介绍,也是本实验的亮点所在。

//control.v
module control(clk,keyin,wavemode,length);
input[3:0]keyin;
input clk;
output reg [1:0]wavemode;
output reg[23:0]length;
reg [23:0] fredata;
reg[3:0]key;
integer single_state= 1,single_frc= 1;
always@(posedge clk)
begin
key=keyin;
case(key)
4'b0001:begin wavemode= 2'b01;length= 24'd17;end //key1-reset
4'b0010:begin case (single_state) //key2-wavemode
1: wavemode= 2'b01; //sin
2: wavemode= 2'b10; //fangbo
3: wavemode= 2'b11; //sanjiao
default:begin wavemode= 2'b01; single_state= 0; end
endcase
single_state= single_state+1;
end
4'b0100:begin case(single_frc) //key3-frequency dangwei
1: length= 24'd17; //1Hz~100Hz
2: length= 24'd1678; //100Hz~500Hz
3: length= 24'd8389; //500Hz~1kHz
4: length= 24'd16777; //1kHz~5kHz
5: length= 42'd83886; //5kHz~10kHz
6: length= 24'd167772; //10kHz~50kHz
7: length= 24'd838861; //50kHz~200kHz
default: begin length= 24'd671088;single_frc= 0;end
endcase
single_frc= single_frc+1;
end
4'b1000:begin case(single_frc) //key4-frequency bujin
1: length= length+24'd16777; //1kHz
2: length= length+24'd17; //1Hz
3: length= length+24'd168; //10Hz
4: length= length+24'd839; //50Hz
5: length= length+24'd1678; //100Hz
6: length= length+24'd8389; //500Hz
7: length= length+24'd16777; //1kHz
8: length= length+24'd83886; //5kHz
default: length= length+24'd0; //0
endcase
end
endcase
end
endmodule
4.7 状态机专用消颤电路
消颤电路时经常用到的一种电路,普通消颤电路以D触发器锁存并在时钟上升沿赋值为基础,原理简便,但并不适用于状态机电路。

状态机电路会在每一个时钟上升沿检测开关的0、1状态,如果高电平时间长(大于1us),将会导致其测试出无数个高电平而使得输出只能是循环的任意状态,或累加的最高状态。

状态机专用消颤电路,既继承了普通消颤电路忽略开关的颤的的功能,又使得开关按下后每0.5s才产生一个1us的微小脉冲,相当于状态机切换一个状态,使得状态机的功能得以全部实现。

以下为状态机专用消颤电路的verilog程序及原理简介:
//key.v
module key(clk,keyIN,keyOUT);
input clk;
input[3:0]keyIN;
output[3:0]keyOUT;
reg [3:0] keyOUT;
reg[19:0] scan;
wire [3:0]keyIN;
always@(posedge clk)
if(scan==20'h7A120) //每50000个系统脉冲(合为0.5s)的持续1可输出一个1us的脉冲begin keyOUT<=keyIN; scan<=scan+1; end
else if(scan==20'h7A121)
begin keyOUT<=0; scan<=0; end
else
begin
if((keyIN[0]==1)||(keyIN[1]==1)||(keyIN[2]==1)||(keyIN[3]==1))
scan<=scan+1'b1;
else begin keyOUT<=0; scan<=0; end
end
endmodule
由于仿真时不可能在1MHz的系统时钟下输出一个0.5s量级的才出现的脉冲波,所以仿真时,将50000个脉冲改为100个(即0.1ms),将栅格设为0.01ms,仿真波形如下:
4.8 LED频率显示电路
LED电路利用频率字就分辨率,对每一个频率的个、十、百、千、万及以上共八位进行了计算,并将计算结果通过译码管显示电路输出到七段译码管上。

Verilog程序及原理简介如下:
module shumaguan(clk,length,Segout,SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8);//changed
input clk;
output[6:0]Segout; // 7-segment code output,segout[6...0]-gfedcba
output SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8; //select LED
input [24:0] length;
reg [24:0] temp= 24'd596046;
reg [45:0] AA;
reg [23:0] fre;
reg [3:0] A1,A2,A3,A4,A5,A6,A7,A8;
reg SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8;
reg [6:0]Segout;
reg [2:0]Count; //internal 3-bit counter
reg [3:0]Seg_in;
always@(posedge clk)
begin
AA= length*temp;
fre= AA/24'd1000000;
A1=(fre/28'd1*******); //百万
A2=(fre/24'd1000000)%4'd10; //十万
A3=(fre/24'd100000)%4'd10; //万位
A4=(fre/24'd10000)%4'd10; //千位
A5=(fre/24'd1000)%4'd10; //百位
A6=(fre/24'd100)%4'd10; //十位
A7=(fre/24'd10)%4'd10; //个位
A8= fre%4'd10;
end
always@(posedge clk) //clk=1kHz
case(Count)
3'b000:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b01111111; //LED0 display Seg_in=A1[3:0];
Count=Count+1; //Count=1
end
3'b001:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b10111111; //LED1 display Seg_in=A2[3:0];
Count=Count+1; //Count=2
end
3'b010:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b11011111; //LED2 display
Seg_in=A3[3:0];
Count=Count+1; //Count=3
end
3'b011: begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b11101111; //LED3 display Seg_in=A4[3:0];
Count=Count+1; //Count=4
end
3'b100:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b11110111; //LED4 display Seg_in=A5[3:0];
Count=Count+1; //Count=5
end
3'b101:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b11111011; //LED5 display Seg_in=A6[3:0];
Count=Count+1; //Count=6
end
3'b110:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b11111101; //LED6 display Seg_in=A7[3:0];
Count=Count+1; //Count=7
end
3'b111:begin {SG1,SG2,SG3,SG4,SG5,SG6,SG7,SG8}=8'b11111110; //LED7 display Seg_in=A8[3:0];
Count=Count+1; //Count=0
end
endcase
// BCD Code=>7 Segment Code(a~g)
always@(Seg_in)
case(Seg_in)
//gfedcba
4'd0:Segout=7'b1000000;
4'd1:Segout=7'b1111001;
4'd2:Segout=7'b0100100;
4'd3:Segout=7'b0110000;
4'd4:Segout=7'b0011001;
4'd5:Segout=7'b0010010;
4'd6:Segout=7'b0000010;
4'd7:Segout=7'b1111000;
4'd8:Segout=7'b0000000;
4'd9:Segout=7'b0010000;
default: Segout= 7'b0100011;
endcase
endmodule
五、程序下载、仿真与调试
编译好的程序经过管脚设定后即可下载到FPGA 芯片进行调试。

5.1 管脚设定
具体的管脚设定如下:
5.2 修改Device&Pins Options 及重新
编译管脚分配保存好后,选择Assignments 选项中的Device,点击“Device and Pin Option…”,选择“Unused Pins”页中“Reserve all unused pins:”选项中的“As input tri-stated”选项,将未用引脚设为三态输入,并对整个电路进行重新编译。

5.3 程序下载及运行结果
编译点击工具栏上的(Programmer)按钮,选择要下载的文件,点击“Start”即可下载程序。

下载完毕即可在模拟试验箱上观察结果并进行调试。

程序在多次试验后终于成功,按键总结如图5-3-1所示,所有按键功能均可实现。

图5-3-1 按键设置表格
六、实验中遇到的问题及其应对方案
问题①:按键操作不正常,切换不到想要的状态。

问题分析:状态机电路会在每一个时钟上升沿检测开关的0、1状态,如果高电平时间长(大于1us),将会导致其测试出无数个高电平而使得输出只能是循环的任意状态,或累加的最高状态。

解决方案:添加一个状态机专用的消颤电路
问题②:做完消颤电路接上去之后,整个按键都没有用,而单独仿真又是完全正确的。

问题分析:一定是调用时候的联接出了问题。

解决方案:在主程序中加入一个wire型变量的keyOUT,否则调用时变量数据不能线性传送。

七、实验总结与感想
直接数字频率合成器的波形生成还是一个比较基础的设计过程,我主要学到了ROM的调用,和生成*.mif文件,使用address寻址并从ROM中输出需要的内容。

这个实验,我们研究的重点在于用状态机控制各种想要的输出,虽然研究的过程中遇到了各种问题,但是我们都一一解决了,其中我做的状态机专用消颤部分,就是先画出想要得到的波形,然后用人类的思维开始分析如何得出这样的波形,再转换为机器语言,这个过程虽然是比较困难的,但是也让我感受到了成功的喜悦。

在我看来,实验可以学到的内容,是远大于单纯的理论学习的,是一种将知识综合利用,总结提升的最好方式。

八、参考文献
[1]《Veriloge HDL 数字系统设计与验证》——乔庐峰.电子工业出版社
[2]《EDA设计实验指导书》——南京理工大学电子技术中心
[3]《Veriloge 编程艺术》——魏家明.电子工业出版社。

相关文档
最新文档