引言
PLD具有以下优点:
1.快速设计开发,PLD极大的灵活性,使其在缩短设计时间上有很大的优势;
2.设计弹性。由于PLD的规模和容量不断提升,从而提高了设计系统的弹性,可以根据用户的实际情况和要求做出相应的修改;同时随着PLD行业的发展,其设计资源也随之剧增;
3.提供良好升级性能。PLD具有较强的软件升级功能,利用业界标准的HDL和PLD制造商提供的基于平台和工具集方法的工具,可以很方便地实现软件在各代PLD中的无缝移植;
4.提供高抗扰能力。PLD的串行连接技术可以减少引脚数量、减小接头尺寸、降低电磁干扰辐射(EMI)、提高信号完整性和更好地抵抗噪声,从而大大提升了系统的抗干扰能力;
5 .更有效的利用IP资源。越来越多的设计人员,将系统设计模块化、IP化,为设计带来了快捷和方便。使设计人员充分利用IP资源,提高开发效率,缩减面市时间,降低研发费用及风险。
综上所述,PLD的发展,不仅可使系统的体积小、功耗低,更重要的是提高系统的可靠性。另外,笔者认为,伴随着微控制器技术的发展,两种技术必将走向融合,这种趋势在Atmel公司推出的FPSILC芯片中已经体现。
本文利用PLD器件实现直接数字频率合成技术,来验证PLD的优越性。
系统分析设计
DDS的基本原理
如下图所示,将要产生的波形数据存入波形存储器中,然后在参考脉冲的作用下,对输入的频率数据进行累加,并将累加器输出的一部分作为读取波形存储器的地址, 将读出的波形数据经D/A 转换为相应的电压信号,D/A 转换器输出的一系列的阶梯电压信号经低通滤波器滤波后便输出了光滑的合成波形信号。DDS 的输出信号的频率为:
DDS原理框图(略)
f_{out}=\frac{?Phase}{2^{N}}f_{clk}
?Phase=2π?\frac{f_{out}}{f_{clk}}?弧度
其中: f out 为信号合成频率; f clk 为参考时钟频率;△Phase为频率设置数据,也称为频率控制字;N为相位累加器的位数。
DDS 的频率分辨率即最低频率为:
?f_{out}=\frac{1}{2^{N}}f_{out}
所以只要N 足够大, DDS 可以得到很小的频率间隔。要改变DDS 的输出信号的频率,只要改变△Phase 即可。根据奈奎斯特抽样定理,DDS 的最大频率为:
f_{max}=\frac{1}{2}f_{clk}
方案比较
a方案一:采用单片机函数发生器(如8031),8031可同时产生正弦波、脉冲波,方法简单易行;用D/A转换器的输出来改变调节电压,也可以实现数控调整频率,但步长难以满足要求,且频率稳定度不太高。
b方案二:采用专用芯片实现,利用锁相环,将压控振荡器(VCO)的输出频率锁定在所需频率上,该方案性能良好,但难以达到输出频率覆盖系数的要求,且电路复杂,不适于产生低频信号。
c方案三:采用直接数字频率合成器(DDS),可用硬件或软件实现。即用累加器按频率要求相对应的相位增量进行累加,再以累加相位值作为地址码,取存放于ROM中的波形数据,经D/A转换、滤波即得所需波形。方法简单,频率稳定度高,易于程控。
虽然有的专用DDS芯片的功能也比较多,但控制方式却是固定的,因此不一定是我们所需要的。而可编程逻辑器件以其速度高、规模大、可编程、以及有强大EDA软件支持等特性,十分适用于实现DDS技术。利用PLD可以根据需要实现各种复杂的调频、调相和调幅功能,具有良好的实用性。
具体系统设计
本方案软件采用了结构化系统设计方法,整个软件自顶向下细化,每个模块完成一项功能,并遵守上层模块调用下层模块,同层模块不能相互调用的原则。以四种基础波形为设计与实现的对象,即正弦波、三角波、锯齿波及方波。四个波形作为同一个任意波形发生器里的四个部分,有着同一个输入与输出,因此在设计上还需要对波形进行选择与控制,通过对时钟脉冲输入的选择,使得四个波形模块只有一个输入为时钟脉冲,其他三个模块的输入始终为0,输出的波形数字信号,通过D/A芯片转换为模拟信号。基本框图如下:
图(略)
以下是对各个波形及波形的选择与控制的具体设计思路与步骤。
正弦波的设计
由图和正弦波公式可以看出,只需要算出1/4个周期的幅值,则可得出其他3/4个周期的幅值,在本设计中,采用此规律来简化采样点数。但仅以原始波形为基础进行采样,必然会出现小数和负数,这将使编程变得困难。为了消除小数和负数,我们采用了以下算法:
图1 (略)
首先,将原始波形幅度扩大为原来的127.5倍,如图2。然后将波形 向上移动127.5,如图3。为了简化采样与编程的需要,对图3进行了变化,将正弦波左移1/4个周期,如图4,按余弦来采样,即cosa。在(0到π) 之间取了64个cosa点,而(π到2π)之间的点则是(0到π)之间的点的反方向排列。采样点的计算公式为(cosa+1)*127.5。
图2 (略)
图3 (略)
图4 (略)
以下为正弦波的VHDL语言编程源程序:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity sin4 is
port(clk4:in std_logic;
dd4:out integer range 255 downto 0);---输出范围为
0到255
end;
architecture dacc of sin4 is
signal q: integer range 63 downto 0;
begin
process(clk4)
begin
if (clk4'event and clk4='1') then
q<=q+1;
end if;
end process;
process(q)
begin
case q is
when 00=>dd4<=255;
when 01=>dd4<=254;
when 02=>dd4<=253;
when 03=>dd4<=250;
when 04=>dd4<=245;
when 05=>dd4<=240;
when 06=>dd4<=234;
when 07=>dd4<=226;
when 08=>dd4<=218;
when 09=>dd4<=208;
when 10=>dd4<=198;
when 11=>dd4<=188;
when 12=>dd4<=176;
when 13=>dd4<=165;
when 14=>dd4<=152;
when 15=>dd4<=140;
when 16=>dd4<=128;
when 17=>dd4<=115;
when 18=>dd4<=103;
when 19=>dd4<=90;
when 20=>dd4<=79;
when 21=>dd4<=67;
when 22=>dd4<=57;
when 23=>dd4<=47;
when 24=>dd4<=37;
when 25=>dd4<=29;
when 26=>dd4<=21;
when 27=>dd4<=15;
when 28=>dd4<=10;
when 29=>dd4<=5;
when 30=>dd4<=2;
when 31=>dd4<=1;
when 32=>dd4<=0;
when 33=>dd4<=1;
when 34=>dd4<=2;
when 35=>dd4<=5;
when 36=>dd4<=10;
when 37=>dd4<=15;
when 38=>dd4<=21;
when 39=>dd4<=29;
when 40=>dd4<=37;
when 41=>dd4<=47;
when 42=>dd4<=57;
when 43=>dd4<=67;
when 44=>dd4<=79;
when 45=>dd4<=90;
when 46=>dd4<=103;
when 47=>dd4<=115;
when 48=>dd4<=128;
when 49=>dd4<=140;
when 50=>dd4<=165;
when 51=>dd4<=176;
when 52=>dd4<=188;
when 53=>dd4<=198;
when 54=>dd4<=208;
when 55=>dd4<=218;
when 56=>dd4<=226;
when 57=>dd4<=234;
when 58=>dd4<=240;
when 59=>dd4<=245;
when 60=>dd4<=250;
when 61=>dd4<=253;
when 62=>dd4<=254;
when 63=>dd4<=255;
when others=>null;
end case;
end process;
end architecture;
三角波的设计
由于三角是由线形增加和线形递减的两个直线构成,所以可以直接使用VHDL语言编程来实现三角波,当线形自加到最高点时,由控制语句控制其自减,直到减到最低点时再重复之前过程,从而实现三角波。以下是采用VHDL语言的三角波编程源程序:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity sanj is
port(clk3:in std_logic;
dd3:out std_logic_vector(7 downto 0));
end sanj;
architecture art of sanj is
signal b:std_logic;
signal c:std_logic_vector(7 downto 0);
begin
process(clk3)
begin
if (clk3'event and clk3='1') then
if(b='0') then
c<=c+1;
if(c=250) then
b<='1';
end if;
elsif(b='1') then
c<=c-1;
if(c=1) then
b<='0';
end if;
end if;
dd3<=c;
end if;
end process;
end art;
锯齿波的设计
对于锯齿波的采样,也可以完全用VHDL语言来实现,当加到所要求的最高点时,由控制语句使其返回0点重复以前过程,从而实现锯齿波。另外,设置一个控制按键,来控制输出上升锯齿波形或下降锯齿波形,如图5、图6所示。
图5 (略)
图6 (略)
以下为锯齿波VHDL语言编程源程序:
library ieee;
use ieee.std_logic.1164.all;
entity jvchi2 is
potr(clk2,up_down: in std_logic;
dd2:buffer integer range 255 downto 0);
end;
architecture one of jvchi2 is
signal d,temp:integer range 255 downto 0;
begin
process(clk2)
begin
if(clk2'event and clk2='1') then
if temp<198 then temp<=temp+2;
else temp<=0;
end if;
end if;
end process;
process(temp,up_down)
begin
if up_down='0' then d<=temp;
else d<=198-temp;
end if;
end process;
dd2<=d;
end;
方波的设计
由于时钟脉冲输出即是方波波形,所以对方波的设计可以简化为直接输出时钟脉冲信号。但是,在本设计中方波与其他三个波形要同步且要经过D/A转换,所以还需把时钟脉冲变成8位输出才可以经由D/A转换输出,具体过程可以由以下程序实现:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity fang2 is
port(
clk1 : in std_logic;
dd1 : buffer integer range 255 downto 0);
end;
architecture dacc of fang2 is
signal q: integer range 1 downto 0;
begin
process(clk1)
begin
if (clk1'event and clk1='1') then
q<=q+1;
end if;
end process;
process(q)
begin
case q is
when 0=>dd1<=255;
when 1=>dd1<=0;
when others=>null;
end case;
end process;
end architecture;
波形选择与控制的设计
在前面已经分别设计了四种基础波形,现在需做的是如何将四种波形融合在一起成为一个整体,并使它们能按操作输出所需波形,这就需要波形选择与控制模块。这个功能由时钟脉冲输入选择模块完成。当选择了一种情况时,对应的波形模块输入时钟脉冲,并输出波形数据,其他三个则始终输入为0,不能输出波形。但是,其他波形始终有0信号输入,也能产生数据,会对波形产生干扰。因此,需要输出波形选择模块来选择有用的波形,隔离干扰数据。为了达到时钟脉冲选择与输出波形选择的统一,同时也为了消除延迟,在输出波形选择模块与时钟脉冲选择模块里控制开关是同一组。这样当输入一种控制数据时,输出的波形也就是所需的波形。这样设计,可以减少按键的数量,节省资源降低错误几率。下面是设计的连线总图及时钟脉冲选择与输出波形选择程序:
图 (略)
时钟脉冲输入选择器VHDL语言编程源程序:
library ieee;
use ieee.std_logic_1164.all;
entity mux42 is
port(clk : in std_logic;
s: in std_logic_vector(1 downto 0);
z1,z2,z3,z4: out std_logic);
end entity mux42;
architecture art of mux42 is
begin
process(s)
begin
case s is
when "00"=>z1<=clk;
when "01"=>z2<=clk;
when "10"=>z3<=clk;
when "11"=>z4<=clk;
when others=>z1<=null;
z2<=null;
z3<=null;
z4<=null;
end case;
end process;
end art;
输出波形选择器VHDL语言编程源程序:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity yand1 is
p ort(dd1,dd2,dd3,dd4 : in std_logic_vector (7 downto 0);
s: in std_logic_vector(1 downto 0);
y: : out std_logic_vector (7 downto 0));
end entity yand1;
architecture art of yand1 is
begin
process(s)
begin
case s is
when "00"=>y<=dd4;
when "01"=>y<=dd3;
when "10"=>y<=dd2;
when "11"=>y<=dd1;
when others=>null;
end case;
end process;
end architecture art;
设计结果与理论设计的比较
软件模拟数据和示波器显示波形相吻合,波形的稳定及光滑程度与理论波形有着一定差距,但这差距并不大,不影响设计结果、波形的观察和测量及该任意波形发生器的使用。造成这差距的原因主要有算法的选择、采样的点数及精确度,以及输入时钟脉冲频率的选择。
结束语
由于时间较短,笔者仅完成了最基本的设计部分,还有很多功能没有增加,比如:设置输出频率、调节占空比、调节幅度等,或者换种思路利用DSP Builder 设计DDS。这些功能会在以后逐步实现,从而提高对EDA技术的掌握。 |