基于FPGA的直接数字频率合成器设计.docx
《基于FPGA的直接数字频率合成器设计.docx》由会员分享,可在线阅读,更多相关《基于FPGA的直接数字频率合成器设计.docx(25页珍藏版)》请在冰豆网上搜索。
基于FPGA的直接数字频率合成器设计
JIANGSUUNIVERSITYOFTECHNOLOGY
FPGA技术实验报告
基于FPGA的直接数字频率合成器设计
学院:
电气信息工程学院
专业:
电子信息工程
班级:
姓名:
学号:
指导教师:
戴霞娟、陈海忠
时间:
2015年9月17日
目录
1.功能要求2
2.方案设计及原理框图2
2.1方案设计2
2.2原理框图3
2.2.1输入电路3
2.2.2FPGA电路3
2.2.3D/A转换电路4
3.硬件电路设计及原理分析4
3.1硬件电路图4
3.2原理分析5
3.3DAC0832转换器5
3.4LM358芯片5
4.程序模块设计、仿真结果及分析6
4.1顶层模块6
4.2分频模块6
4.3时钟模块10
4.4正弦波产生模块11
4.5三角波产生模块13
4.6方波产生模块15
4.7锯齿波产生模块17
4.8波形选择模块19
5.软硬件调试20
5.1软件调试22
5.2硬件调试22
6.调试结果说明25
7.心得体会25
8.参考文献25
附录26
1.功能要求
通过本课题训练,使学生掌握使用FPGA实现频率合成的方法。
要求学生根据正弦波形发生器的设计实例,举一反三,设计多功能波形发生器。
该波形发生器能产生正弦波、方波、三角波、锯齿波和由用户编辑的特定形状波形,并且幅度、频率可调。
具体要求如下:
基本要求:
(1)具有产生正弦波、方波、三角波、锯齿波4种周期性波形的功能。
(2)输出波形的频率范围为100HZ~200kHZ;至少可以输出8种频率的波形。
(3)输出波形幅度不大于5V(峰-峰值),且幅度可调。
扩展要求:
(1)在频率范围为100HZ~200kHZ内,频率步进间隔≤100HZ。
(2)输出波形幅度范围0~5V(峰-峰值),可按步进0.1V(峰-峰值)调整。
(3)用LCD1602显示输出波形的类型、重复频率(周期)和幅度。
(4)用键盘输入编辑生成上述4种波形(同周期)的线性组合波形。
(5)用键盘和其他输入装置产生任意波形。
(6)具有波形存储功能。
2.方案设计及原理框图
2.1方案设计
利用FPGA来完成设计,FPGA编程灵活,可以实现三角波、方波、锯齿波和正弦波的数字化处理,将一个周期内的采样点存储起来,生成频率可调的正弦波、方波、锯齿波或者三角波,再通过D/A转换和滤波电路便可得到模拟波形。
利用该方法,编程简单,实现灵活。
2.2原理框图
数字信号发生器系统主要由输入部分、FPGA部分、D/A转换部分、频率调节和波形转换部分组成。
原理框图如下图1:
调频3
图1:
多功能波形信号发生器原理框图
2.2.1输入部分
输入部分包含以下功能按键:
时钟、复位、波形、调频1、调频2和调频3。
(1)时钟:
标准的50MHZ时钟输入。
(2)复位:
低电平复位。
(3)波形:
为波形输出选择开关,可以选择单波形的输出。
(4)调频1,2,3:
可以改变正弦波、三角波、方波和锯齿波的频率,总共可以输出8种不同频率。
2.2.2FPGA部分
FPGA是整个系统的核心,包括系统控制器、波形数据生成器、加法器、运算/译码、分频器等电路。
各部分具体功能如下:
系统控制器:
控制系统的每个部分状态之间的协调。
分频:
分频系数有的固定不变,也有可改变的。
正弦波:
通过循环不断地从RAM中依次读取正弦波一个周期在时域上1024个采样点的波形数据送入波形DAC,从而产生正弦波。
正弦波的频率取决于读取数据的速度。
三角波:
三角波波形是对称的,每边呈线性变化,所以可以根据地址数据做简单运算,就可以得到三角波。
锯齿波:
产生单调性锯齿波,因此把地址数据进行左移2位,结果送波形DAC就可。
方波:
方波产生有1024个采样点组成,1024个采样点的数据只有“低电平”和“高电平”2种状态。
2.2.3波形D/A转换部分
采用具有8位分辨率的D/A转换集成芯片DAC0832作为多种波形发生器的数模转换器。
由于多种波形发生器制使用一路D/A转换,因而DAC0832可连续接成单缓冲器方式。
另外,因DAC0832是一种电流输出型D/A转换器,要获得模拟电压输出时,需外接运放来实现电流转换为电压。
由于在实际使用中输出波形不仅需要单极性的(0~+5V或-5~0V)有时还需要双极性的(±5V),因而可用两组运算放大器作为模拟电压输出电路,运放可选用LM358,其片内集成了两个运算放大器。
3.硬件电路设计及原理分析
3.1硬件电路图
图2:
波形信号发生器硬件电路图
3.2原理分析
本设计的工作原理为将要产生的波形数据存入波形存储器,然后在参考时钟的作用下,对输入的频率数据进行累加,并且将累加器的输出一部分作为读取波形存储器的地址,将读出的波形数据经D/A转换为相应的模拟电压信号。
本研究的重点就是用VHDL来实现DDS的功能,能够达到高精度的输出,同时标准波形数据生成存放在ROM中,可以简化运算过程,提高运算速度,加快反应时间。
3.3DAC0832转换器
DAC0832是双列直插式8位D/A转换器,在电路中DAC0832被接成单缓冲器方式。
它的ILE,VCC,8脚与+5V相连,CS,XFER,WR2,WR1,3脚,10脚与GND相连,WR1与CP信号相连。
这样DAC0832的8位DAC寄存器始终处于导通状态,因此当CP变成低电平时,数据线上的数据便可直接通过8位DAC寄存器,并有其8位D/A转换器进行转换。
图3:
DAC0832芯片引脚图
3.4LM358芯片
LM358是常用的双运,LM358里面包括有两个高增益、独立的、内部频率补偿的双运放,适用于电压范围很宽的单电源,而且也适用于双电源工作方式,它的应用范围包括传感放大器、直流增益模块和其他所有可用单电源供电的使用运放的地方使用。
图4:
LM358芯片引脚图
4.程序模块设计、仿真结果分析
波形发生器可以由顶层模块、分频模块、时钟模块、正弦波产生模块、三角波产生模块、方波产生模块和输出波形选择模块组成。
4.1顶层模块
顶层文件将已经设计的各个模块联系在一起成为一个整体,实验时使用QuartusⅡ9.0编写VHDL程序实现顶层文件设计。
顶层文件仿真图如下5:
图5:
顶层文件仿真图
4.2分频模块
根据DAC0832输出控制时序,利用接口电路图,DAC0832是8位的D/A转换器,转换周期为1μs,又因为FPGA的系统时钟为50MHz,必须对其进行分频处理,实验使用100分频,实验时使用QuartusⅡ9.0编写VHDL程序生成时钟分频器。
VHDL程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYwxm_CLKIS
PORT(CLK:
INSTD_LOGIC;
EN,EN1,EN2:
INSTD_LOGIC;
CLKOUT:
OUTSTD_LOGIC);
END;
ARCHITECTUREBEHAVEOFwxm_CLKIS
SIGNALCNT:
STD_LOGIC_VECTOR(19DOWNTO0);
SIGNALEN3,EN4,EN5:
STD_LOGIC;
SIGNALEN6:
STD_LOGIC_VECTOR(2DOWNTO0);
BEGIN
EN6<=EN3&EN4&EN5;
PROCESS(EN)
BEGIN
IFEN'EVENTANDEN='0'THEN
IFEN3='0'THEN
EN3<='1';
ELSE
EN3<='0';
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(EN1)
BEGIN
IFEN1'EVENTANDEN1='0'THEN
IFEN4='0'THEN
EN4<='1';
ELSE
EN4<='0';
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(EN2)
BEGIN
IFEN2'EVENTANDEN2='0'THEN
IFEN5='0'THEN
EN5<='1';
ELSE
EN5<='0';
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(CLK,EN6)
BEGIN
IFCLK'EVENTANDCLK='1'ANDEN6="000"THEN
IFCNT>4THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>2THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="001"THEN
IFCNT>8THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>4THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="010"THEN
IFCNT>16THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>8THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="011"THEN
IFCNT>30THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>15THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="100"THEN
IFCNT>62THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>31THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="101"THEN
IFCNT>124THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>62THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="110"THEN
IFCNT>250THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>125THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ELSIFCLK'EVENTANDCLK='1'ANDEN6="111"THEN
IFCNT>500THEN
CNT<=(OTHERS=>'0');
CLKOUT<='0';
ELSIFCNT>250THEN
CLKOUT<='1';
CNT<=CNT+1;
ELSE
CNT<=CNT+1;
ENDIF;
ENDIF;
ENDPROCESS;
END;
4.3时钟模块
图6
VHDL程序
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYCNT1024IS
PORT(CLK:
INSTD_LOGIC;
Q:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
END;
ARCHITECTUREBHVOFCNT1024IS
SIGNALQ1:
STD_LOGIC_VECTOR(9DOWNTO0);
BEGIN
PROCESS(CLK)
BEGIN
IFCLK'EVENTANDCLK='1'THEN
Q1<=Q1+1;
ENDIF;
ENDPROCESS;
Q<=Q1;
END;
4.4正弦波产生模块
该模块输入信号由时钟(clk)和复位信号(reset)构成,当信号发生器选择信号(sel[2..0])为4时,该模块输出端(q[9..0])对外输出。
模块振幅随时钟的变化阶梯性递增,输出波形参数可以通过程序进行设定。
VHDL程序为:
LIBRARYieee;
USEieee.std_logic_1164.all;
LIBRARYaltera_mf;
USEaltera_mf.all;
ENTITYcyy_sinIS
PORT
(address:
INSTD_LOGIC_VECTOR(9DOWNTO0);
clock:
INSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
ENDcyy_sin;
ARCHITECTURESYNOFcyy_sinIS
SIGNALsub_wire0:
STD_LOGIC_VECTOR(9DOWNTO0);
COMPONENTaltsyncram
GENERIC(clock_enable_input_a:
STRING;
clock_enable_output_a:
STRING;
init_file:
STRING;
intended_device_family:
STRING;
lpm_hint:
STRING;
lpm_type:
STRING;
numwords_a:
NATURAL;
operation_mode:
STRING;
outdata_aclr_a:
STRING;
outdata_reg_a:
STRING;
widthad_a:
NATURAL;
width_a:
NATURAL;
width_byteena_a:
NATURAL);
PORT(clock0:
INSTD_LOGIC;
address_a:
INSTD_LOGIC_VECTOR(9DOWNTO0);
q_a:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
ENDCOMPONENT;
BEGIN
q<=sub_wire0(9DOWNTO0);
altsyncram_component:
altsyncram
GENERICMAP(clock_enable_input_a=>"BYPASS",
clock_enable_output_a=>"BYPASS",
init_file=>"E:
/wxm/wxm_sin.mif",
intended_device_family=>"CycloneII",
lpm_hint=>"ENABLE_RUNTIME_MOD=NO",
lpm_type=>"altsyncram",
numwords_a=>1024,
operation_mode=>"ROM",
outdata_aclr_a=>"NONE",
outdata_reg_a=>"CLOCK0",
widthad_a=>10,
width_a=>10,
width_byteena_a=>1)
PORTMAP(clock0=>clock,
address_a=>address,
q_a=>sub_wire0);
ENDSYN;
仿真结果:
4.5三角波产生模块
该模块输入信号由时钟(clk)和复位信号(reset)构成,当信号发生器选择信号(sel[2..0])为2时,该模块输出端(q[9..0])对外输出。
模块内计数器随时钟先递增后递减,波形随之先递增后递减,输出波形参数可以通过程序进行设定。
VHDL程序
LIBRARYieee;
USEieee.std_logic_1164.all;
LIBRARYaltera_mf;
USEaltera_mf.all;
ENTITYcyy_sjIS
PORT(address:
INSTD_LOGIC_VECTOR(9DOWNTO0);
clock:
INSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
ENDcyy_sj;
ARCHITECTURESYNOFcyy_sjIS
SIGNALsub_wire0:
STD_LOGIC_VECTOR(9DOWNTO0);
COMPONENTaltsyncram
GENERIC(clock_enable_input_a:
STRING;
clock_enable_output_a:
STRING;
init_file:
STRING;
intended_device_family:
STRING;
lpm_hint:
STRING;
lpm_type:
STRING;
numwords_a:
NATURAL;
operation_mode:
STRING;
outdata_aclr_a:
STRING;
outdata_reg_a:
STRING;
widthad_a:
NATURAL;
width_a:
NATURAL;
width_byteena_a:
NATURAL);
PORT(clock0:
INSTD_LOGIC;
address_a:
INSTD_LOGIC_VECTOR(9DOWNTO0);
q_a:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
ENDCOMPONENT;
BEGIN
q<=sub_wire0(9DOWNTO0);
altsyncram_component:
altsyncram
GENERICMAP(clock_enable_input_a=>"BYPASS",
clock_enable_output_a=>"BYPASS",
init_file=>"E:
/wxm/wxm_sj.mif",
intended_device_family=>"CycloneII",
lpm_hint=>"ENABLE_RUNTIME_MOD=NO",
lpm_type=>"altsyncram",
numwords_a=>1024,
operation_mode=>"ROM",
outdata_aclr_a=>"NONE",
outdata_reg_a=>"CLOCK0",
widthad_a=>10,
width_a=>10,
width_byteena_a=>1)
PORTMAP(clock0=>clock,
address_a=>address,
q_a=>sub_wire0);
ENDSYN;
仿真结果:
4.6方波产生模块
该模块输入信号由时钟(clk)和复位信号(reset)构成,当信号发生器选择信号(sel[2..0])为5时,该模块输出端(q[9..0])对外输出。
模块振幅随时钟的变化持续变为高电平或低电平,输出波形参数可以通过程序进行设定。
VHLIBRARYieee;
USEieee.std_logic_1164.all;
LIBRARYaltera_mf;
USEaltera_mf.all;
ENTITYcyy_squareIS
PORT(address:
INSTD_LOGIC_VECTOR(9DOWNTO0);
clock:
INSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
ENDcyy_square;
ARCHITECTURESYNOFcyy_squareIS
SIGNALsub_wire0:
STD_LOGIC_VECTOR(9DOWNTO0);
COMPONENTaltsyncram
GENERIC(clock_enable_input_a:
STRING;
clock_enable_output_a:
STRING;
init_file:
STRING;
intended_device_family:
STRING;
lpm_hint:
STRING;
lpm_type:
STRING;
numwords_a:
NATURAL;
operation_mode:
STRING;
outdata_aclr_a:
STRING;
outdata_reg_a:
STRING;
widthad_a:
NATURAL;
width_a:
NATURAL;
width_byteena_a:
NATURAL);
PORT(clock0:
INSTD_LOGIC;
address_a:
INSTD_LOGIC_VECTOR(9DOWNTO0);
q_a:
OUTSTD_LOGIC_VECTOR(9DOWNTO0));
ENDCOMPONENT
BEGIN
q<=sub_wire0(9DOWNTO0);
altsyncram_component:
altsyncram
GENERICMAP(clock_enable_input_a=>"BYPASS",
clock_enable_output_a=>"BYPASS",
init_file=>"E:
/wxm/wxm_square.mif",
intended_device_family=>"CycloneII",
lpm_hint=>"ENABLE_RUNTIME_MOD=NO",
lpm_type=>"