基于FPGA的正弦波信号发生器的设计.docx
《基于FPGA的正弦波信号发生器的设计.docx》由会员分享,可在线阅读,更多相关《基于FPGA的正弦波信号发生器的设计.docx(25页珍藏版)》请在冰豆网上搜索。
基于FPGA的正弦波信号发生器的设计
基于FPGA的正弦波信号发生器的设计
EDA
课程设计
题目名称:
基于FPGA的正弦信号发生器
班级:
姓名:
学号:
日期:
2012/07/06
基于FPGA的正弦信号发生器设计
1.1引言
直接数字频率合成(DigitalDirectFrequencySynthesis)是一种比较新颖的频率合成方法。
这个理论早在20世纪70年代就被提出,它的基本原理就是利用采样定理,通过查表法产生波形。
1.2方案比较与确定
设计要求:
利用EDA技术,建立正弦信号DDS产生模型,编写源程序,达到频率输出范围1KHz-10MHz、频率步进100Hz、频率稳定度优于10
、带50Ω负载输出电压峰峰值大于1V等要求,完成硬件实现与测试。
【方案一】采用分立元件模拟直接合成法。
这种方法转换速度快,频率分辨率高,但其转换量程靠手动来实现,不仅体积大难以集成,而且可靠性和准确度很难进一步提高。
【方案二】采用MAX038芯片来产生正弦波信号。
该集成块的输出波形种类多,频率覆盖范围广。
它采用的是RC充放电振荡结构。
第一,由于模拟器件元件分散性太大,外接的电阻、电容对参数的影响很大,因而产生的频率稳定度差,只能达到
。
第二,它的频率控制是通过充放电流的大小来实现。
因而要达到步进100HZ,所需的电流变化量非常小,精度要求很高。
所以采用MAX038芯片难以实现设计要求。
【方案三】采用锁相环合成方法。
采用该方案设计输出信号的频率可达到超高频甚至微波段,且输出信号频谱纯度较高。
由于锁相环技
图3.1信号发生器结构框图
图3.1为本次设计总体结构框图,其中相位累加器和波形存储器构成信号发生器核心部分。
该部分又与频率字控制模块共同构成信号发生器主模块。
而显示模块,D/A转换器和滤波电路则作为信号发生器外围硬件设计。
下面就分主模块软件设计和外围硬件设计两大部分来说明信号发生器的设计。
3.2主模块软件设计
3.2.1相位累加器的设计
图3.2相位累加器
图3.2为相位累加器内部结构图,它有一个N位的全加器和一个寄存器构成。
当系统时钟上升沿到来的时候,上一个时钟周期的相位值与频率字的相加值被送入累加寄存器,并输出高W位至波形存储器的地址线,同时相位值又被送回全加器进行相位累加。
相位累加器流程图如图3.3所示
开始
时钟上升沿到?
NO
YES
相位累加
累加值寄存
高W位输出
结束
图3.3相位累加器流程图
设计要求输出频率范围为50HZ—200HZ,频率步进为50HZ。
根据前面介绍最高输出一般是系统时钟的40%。
经过计算,设计选用系统时钟为40MHZ时能实现设计要求。
确定相位累加字长时,考虑到频率分辨率要等于或小于频率步进值,而且累加器字长一般为8的整数倍。
由第二章公式2.2计算后得出符合设计要求的累加器字长为N=24。
3.2.2波形ROM的设计
这个模块是一个相对简单的模块。
首先要确定波形ROM的地址线位数和数据的字长,根据噪声功率的角度看波形ROM的地址线位数应该等于或略大于字长。
由于设计选择的DAC位数为8,这样ROM的字长很明显该和DAC的字长相一致。
而地址线的位数同样确定为8位。
波形存储器利用相位累加器输出的高8位作为地址线来对其进行寻址,最后输出该相位对应的二进制正弦幅值。
将得出的结果转化为8位的二进制数据,起幅值对应在00000000-11111111区间内。
最后利用得到的二进制数据用VHDL编写程序实现正弦ROM的设计。
图3.4为正弦波形ROM模块。
图3.4正弦波形ROM
3.2.3频率控制模块的设计
设计要求频率步进为50HZ,在频率控制模块中,增加了4个附加的频率步进按钮。
分别为最小步进(50HZ)的1倍、2倍、3倍和4倍即50HZ、100HZ、150HZ和200HZ。
这样从大到小地利用频率步进值便可很快地调到所需要的频点。
由于设计要求频率输出范围为50HZ-200HZ,则K值的最小值为21,最大值为84。
设系统其始和复位时K的初值为21,即初始化频率为50HZ。
然后再根据所要输出的频率调整相应的步进量。
图3.5为VHDL设计的频率控制模块。
图3.5为VHDL设计的频率控制模块
3.3外围硬件设计
3.3.1D/A转换器
实现数字量转化为模拟信号的转换电路称为D/A转换器(DAC)。
D/A转换器是把数字量转换成模拟量的线性电路器件,已做成集成芯片。
由于实现这种转换的原理和电路结构及工艺技术有所不同,因而出现各种各样的D/A转换器。
目前,国外市场已有上百种产品出售,他们在转换速度、转换精度、分辨率以及使用价值上都各具特色。
衡量一个D/A转换器的性能的主要参数有:
(1)分辨率:
是指D/A转换器能够转换的二进制数的位数,位数多分辨率也就越高。
(2)转换时间:
指数字量输入到完成转换,输出达到最终值并稳定为止所需的时间。
电流型D/A转换较快,一般在几ns到几百ns之间。
电压型D/A转换较慢,取决于运算放大器的响应时间。
(3)精度:
指D/A转换器实际输出电压与理论值之间的误差,一般采用数字量的最低有效位作为衡量单位。
(4)线性度:
当数字量变化时,D/A转换器输出的模拟量按比例关系变化的程度。
理想的D/A转换器是线性的,但是实际上是有误差的,模拟输出偏离理想输出的最大值称为线性误差。
目前,D/A转换器芯片种类较多,对于一般的使用者而言,只需掌握DAC芯片性能及其与计算机之间接口的基本要求,就可根据应用系统的要求合理选用DAC芯片,并配置适当的接口电路。
3.3.2滤波及放大电路
在由数字信号至模拟信号这一过程转换好以后,得出的信号仍然是在时间上离散的点,需要将其用低通滤波器进行平滑处理,滤除高次频率的杂波,得到平滑标准的正弦波。
结束语
随着信息技术高速发展,集成电路的大规模使用,电子系统已经进入了一个高速发展的全新时段。
特别是EDA技术的日趋成熟的今天,通过计算机辅助设计,可以很好地完成电子设计的自动化。
在设计过程中,可根据需要随时改变器件的内部逻辑功能和管脚的信号方式,EDA技术借助于大规模集成的FPGA/CPLD和高效的设计软件,用户不仅可通过直接对芯片结构的设计实行多种数字逻辑系统功能,而且由于管脚定义的灵活性,大大减轻了电路图设计和电路板设计的工作量及难度,同时,这种基于可编程芯片的设计大大减少了系统芯片的数量,缩小了系统的体积,提高了系统的可靠性。
基于DDS的信号发生器是最为理想的信号产生模型,DDS系统有着其他信号发生器所无法比拟的优势。
今天DDS广泛用于接受机本振、信号发生器、仪器、通信系统、雷达系统等,尤其适合跳频无线电通信系统。
基于FPGA的正弦信号发生器结合了的EDA技术和DDS理论,在EDA技术高速、高效、高可靠性的前提下得到了更优的设计效果。
但是系统的功能还没有得到完全利用,由于DDS技术是利用查表法来产生波形的,则在基于FPGA设计时只要把ROM改成RAM变可实现任意波形的产生。
参考文献
[1]张玉兴.DDS高稳高纯频谱频率源技术[J].系统工程与电子技术.1997
(2)24-28
[2]冯程.用直接数字频率合成器产生正弦波[J].华中科技大学本科生论文.2003.7-27
[3]周国富.利用FPGA实现DDS专用集成电路[J].电子技术应用.No.2.1998.18-20
波形截图:
50Hz
100Hz
150Hz
200Hz
程序vhdl代码:
--顶层模块
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
entitysin256is
port(clk:
instd_logic;
rst:
instd_logic;
set:
instd_logic_vector(1downto0);--设置频率
q:
outstd_logic_vector(7downto0));
endsin256;
architectureBehavioralofsin256is
componentadder
port(a,b:
instd_logic_vector(23downto0);
c:
outstd_logic_vector(23downto0));
endcomponent;
componentD
port(clk:
instd_logic;
rst:
instd_logic;
d:
instd_logic_vector(23downto0);
q:
outstd_logic_vector(23downto0));
endcomponent;
componentsin_rom8_8
PORT(ADDER:
INSTD_LOGIC_VECTOR(7DOWNTO0);
DAOUT:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
endcomponent;
componentsetkp
port(set:
instd_logic_vector(1downto0);
k:
outstd_logic_vector(23downto0);
p:
outstd_logic_vector(23downto0));
endcomponent;
signalk,p:
std_logic_vector(23downto0);
signaltmp1,tmp2,tmp3:
std_logic_vector(23downto0);
begin
setk:
setkpportmap(set,k,p);
add1:
adderportmap(k,tmp2,tmp1);
d1:
Dportmap(clk,rst,tmp1,tmp2);
add2:
adderportmap(tmp2,p,tmp3);
sin_rom:
sin_rom8_8portmap(tmp3(23downto16),q);
endBehavioral;
--频率控制模块
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
entitysetkpis
port(set:
instd_logic_vector(1downto0);
k:
outstd_logic_vector(23downto0);
p:
outstd_logic_vector(23downto0));
endsetkp;
architectureBehavioralofsetkpis
begin
process(set)
begin
casesetis
when"00"=>k<="000000000000000000010101";--50Hz时k的值
when"01"=>k<="000000000000000000101010";--1000Hz时k的值
when"10"=>k<="000000000000000000111111";--150Hz时k的值
when"11"=>k<="000000000000000001010100";--2000Hz时k的值
whenothers=>k<="000000000000000000010101";
endcase;
endprocess;
p<="000000000000000000000000";
endBehavioral;
--相位累加模块,由加法器和D触发器组成
--加法器
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
entityadderis
port(a,b:
instd_logic_vector(23downto0);
c:
outstd_logic_vector(23downto0));
endadder;
architectureBehavioralofadderis
begin
c<=a+b;
endBehavioral;
--D触发器
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
entityDis
port(clk:
instd_logic;
rst:
instd_logic;
d:
instd_logic_vector(23downto0);
q:
outstd_logic_vector(23downto0)
);
endD;
architectureBehavioralofDis
begin
process(clk,rst)
begin
ifrst='1'then
q<=(others=>'0');
elsifclk'eventandclk='1'then
q<=d;
endif;
endprocess;
endBehavioral;
--sin量化rom
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
entitysin_rom8_8is
PORT(ADDER:
INSTD_LOGIC_VECTOR(7DOWNTO0);
DAOUT:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
endsin_rom8_8;
architectureBehavioralofsin_rom8_8is
begin
PROCESS(ADDER)IS
BEGIN
CASEADDERIS
when"00000000"=>DAOUT<="10000000";
when"00000001"=>DAOUT<="10000011";
when"00000010"=>DAOUT<="10000110";
when"00000011"=>DAOUT<="10001001";
when"00000100"=>DAOUT<="10001101";
when"00000101"=>DAOUT<="10010000";
when"00000110"=>DAOUT<="10010011";
when"00000111"=>DAOUT<="10010110";
when"00001000"=>DAOUT<="10011001";
when"00001001"=>DAOUT<="10011100";
when"00001010"=>DAOUT<="10011111";
when"00001011"=>DAOUT<="10100010";
when"00001100"=>DAOUT<="10100101";
when"00001101"=>DAOUT<="10101000";
when"00001110"=>DAOUT<="10101011";
when"00001111"=>DAOUT<="10101110";
when"00010000"=>DAOUT<="10110001";
when"00010001"=>DAOUT<="10110100";
when"00010010"=>DAOUT<="10110111";
when"00010011"=>DAOUT<="10111010";
when"00010100"=>DAOUT<="10111100";
when"00010101"=>DAOUT<="10111111";
when"00010110"=>DAOUT<="11000010";
when"00010111"=>DAOUT<="11000100";
when"00011000"=>DAOUT<="11000111";
when"00011001"=>DAOUT<="11001010";
when"00011010"=>DAOUT<="11001100";
when"00011011"=>DAOUT<="11001111";
when"00011100"=>DAOUT<="11010001";
when"00011101"=>DAOUT<="11010100";
when"00011110"=>DAOUT<="11010110";
when"00011111"=>DAOUT<="11011000";
when"00100000"=>DAOUT<="11011011";
when"00100001"=>DAOUT<="11011101";
when"00100010"=>DAOUT<="11011111";
when"00100011"=>DAOUT<="11100001";
when"00100100"=>DAOUT<="11100011";
when"00100101"=>DAOUT<="11100101";
when"00100110"=>DAOUT<="11100111";
when"00100111"=>DAOUT<="11101001";
when"00101000"=>DAOUT<="11101010";
when"00101001"=>DAOUT<="11101100";
when"00101010"=>DAOUT<="11101110";
when"00101011"=>DAOUT<="11101111";
when"00101100"=>DAOUT<="11110001";
when"00101101"=>DAOUT<="11110010";
when"00101110"=>DAOUT<="11110100";
when"00101111"=>DAOUT<="11110101";
when"00110000"=>DAOUT<="11110110";
when"00110001"=>DAOUT<="11110111";
when"00110010"=>DAOUT<="11111001";
when"00110011"=>DAOUT<="11111010";
when"00110100"=>DAOUT<="11111010";
when"00110101"=>DAOUT<="11111011";
when"00110110"=>DAOUT<="11111100";
when"00110111"=>DAOUT<="11111101";
when"00111000"=>DAOUT<="11111110";
when"00111001"=>DAOUT<="11111110";
when"00111010"=>DAOUT<="11111111";
when"00111011"=>DAOUT<="11111111";
when"00111100"=>DAOUT<="11111111";
when"00111101"=>DAOUT<="11111111";
when"00111110"=>DAOUT<="11111111";
when"00111111"=>DAOUT<="11111111";
when"01000000"=>DAOUT<="11111111";
when"01000001"=>DAOUT<="11111111";
when"01000010"=>DAOUT<="11111111";
when"01000011"=>DAOUT<="11111111";
when"01000100"=>DAOUT<="11111111";
when"01000101"=>DAOUT<="11111111";
when"01000110"=>DAOUT<="11111111";
when"01000111"=>DAOUT<="11111110";
when"01001000"=>DAOUT<="11111110";
when"01001001"=>DAOUT<="11111101";
when"01001010"=>DAOUT<="11111100";
when"01001011"=>DAOUT<="11111011";
when"01001100"=>DAOUT<="11111010";
when"01001101"=>DAOUT<="11111010";
when"01001110"=>DAOUT<="11111001";
when"01001111"=>DAOUT<="11110111";
when"01010000"=>DAOUT<="11110110";
when"01010001"=>DAOUT<="11110101";
when"01010010"=>DAOUT<="11110100";
when"01010011"=>DAOUT<="11110010";
when"01010100"=>DAOUT<="11110001";
when"01010101"=>DAOUT<="11101111";
when"01010110"=>DAOUT<="11101110";
when"01010111"=>DAOUT<="11101100";
when"01011000"=>DAOUT<="11101010";
when"01011001"=>DAOUT<="11101001";
when"01011010"=>DAOUT<="11100111";
when"01011011"=>DAOUT<="11100101";
when"01011100"=>DAOUT<="11100011";
when"01011101"=>DAOUT<="11100001";
when"01011110"=>DAOUT<="11011111";
when"