EDA实验报告频率计及DDS

时间:2024.4.8

EDA实验II

信号源、频率计的设计

姓名:叶爽

班级:08042100

学号:0804210147

指导教师:花汉兵 蒋立平

摘要

  本实验利用ALTERA公司的CYCLONE系列硬件平台和QUARTUSⅡ软件平台,对Cyclone系列的EP1C12Q240C8芯片进行设计,实现了一个简单的正弦波,三角波及调幅波信号源和频率计。

关键字:

FPGA  QURATUS数字钟  VHDL

In this experiment, we use the hardware platform of cyclone produced by ALTERA and the software platform which called quartus II.We design a simple sine wave and triangle wave and amplitude-modulation wave generator on the chip of ep1c12q240c8 of cyclone series.

Keyword: FPGA QURATUS Ⅱ VHDL, Signal Generator.                         

实验目的   P4

实验要求   P4

实验步骤及设计过程  P4

编译下载   P13

经验总结   P13

一.实验目的。

1.       熟悉QUARTEUS-Ⅱ软件的使用方法,和实现FPGA电路设计的一般流程。

2.       了解VHDL语言编程。

3.       了解基本的自顶向下模块化设计思想。

二.实验要求。

1.利用DDS的方案,产生一个正弦波输出,频率可控。

2.利用DDS产生调制信号和载波信号,并根据所学的高频电子线路知识产生标准调幅波。

3.设计一个数字频率计,能够将频率显示在数码管上。

三、实验步骤及设计过程。

1.DDS信号发生模块(半周期数据,正弦波,三角波)(模块名:)

未命名

DDS其实质是以基准频率源(系统时钟)对相位进行等间隔的采样。由图见,DDS 由相位累加器和波形存储器(即,ROM查询表)构成的数控振荡器(NCO_ Numerically Controlled Oscillators)、数模转换器(DAC)组成。在每一个时钟周期,N位相位累加器与其反馈值进行累加,其结果的高L位作为查询表的地址,然后从ROM中读出相应的幅度值送到DAC。再由DAC将其转换成为阶梯模拟波形,最后由具有内插作用的LPF将其平滑为连续的正弦波形作为输出。因此,通过改变频率控制字K就可以改变输出频率

DDS模块中,遇到的第一个问题就是如何产生有符号数的ROM。在实验指导手册里提供的都是产生无符号数的计算机程序,但是由于后面涉及到调幅波中的相乘运算,使用无符号数的话会非常麻烦,因此第一步必须做出有符号数的ROM出来。产生有符号数的C++程序如下。其中加下划线的部分就是有符号数和无符号数的程序区别所在。

#include"iostream.h"

#include"stdio.h"

#include"math.h"

int main(int argc,char*argv[])

{

       int i;

       double s;

       for(i=0;i<2048;i++)

       {

              s=sin(atan(1)*8*i/4096);

              printf("%d:%x;\n",i,(int)(s*511));

       }

       return 0;

}

相位累加器,寄存器均由VHDL语言编写,比较简单,此处只给出源程序,略去分析。

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

entity phase_adder is

port(

k:in std_logic_vector(11 downto 0);

clk:in std_logic;

en:in std_logic;

reset:in std_logic;

out1:out std_logic_vector(11 downto 0)

);

end entity phase_adder;

architecture art of phase_adder is

signal temp:std_logic_vector(11 downto 0);

begin

process(clk,en,reset)

begin

if reset='1' then

temp<="000000000000";

else

if clk'event and clk='1' then

if en='1' then

temp<=temp+k;

end if;

end if;

end if;

out1<=temp;

end process;

end architecture;

==================================

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

entity reg11 is

port

(

clk:in std_logic;

d:in std_logic_vector(11 downto 0);

q:out std_logic_vector(10 downto 0)

);

end reg11;

architecture art of reg11 is

signal temp:std_logic_vector(11 downto 0);

begin

process(clk)

begin

if(clk'event and clk='1') then

    if (d<"100000000000") then

    temp<=d;

    else temp<=("111111111111"-d);

end if;

end if;

end process;

q<=(temp(10)&temp(9)&temp(8)&temp(7)&temp(6)&temp(5)&temp(4)&temp(3)&temp(2)&temp(1)&temp(0));

end art;

======================================

在本次实验中,为了节约存储空间,我的ROM里只存储了半周期数据。但如果按照正弦函数的前半周期来保存的话,后半周期会涉及到符号位的转换,比较麻烦,因此我选择保存了余弦函数的前半周期数据。对于送进来的频率控制字K,如果在0-PI之间,那么不做变换,直接输出,如果在PI-2PI之间,那么输出2PI-K,即关于PI做了一个对称变换,由正弦波的对称性知,这样不会改变波形。分析寄存器的代码就可以发现,寄存器是12位地址输入,却只有11位地址输出,就是因为做了一次对称变换,接口宽度缩减了一半。

对于三角波,其核心就是改变ROM的内容,也就是产生MIF文件的计算机程序需要修改一下。我直接定义了一个周期为2PI,幅度为2的三角波函数TRIANGLE.那么MAIN函数中只要把SIN改为TRIANGLE就可以了。程序如下。

#include"iostream.h"

#include"stdio.h"

#include"math.h"

double triangle(double x)

{

       if (0<=x&&x<=4*atan(1))

              return ((2*atan(1))-x)/(2*atan(1));

              else return (triangle(8*atan(1)-x));

}

int main(int argc,char*argv[])

{

       int i;

       double s;

       for(i=0;i<2048;i++)

       {

              s=triangle(atan(1)*8*i/4096);

              printf("%d:%x;\n",i,(int)(s*511));

       }

       return 0;

}

对于反相功能,其实就是在寄存器之前加一个反相模块就可以了。VHDL如下。

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

entity phase_reverse is

port(

en,clk:in std_logic;

phase_ctrl:in std_logic_Vector(11 downto 0);

dout:out std_logic_vector(11 downto 0)

);

end phase_reverse;

architecture beh of phase_reverse is

signal temp:std_logic_vector(11 downto 0);

begin

process(clk)

begin

if clk'event and clk='1' then

  if en='1' then temp<=phase_ctrl+"100000000000";

  else temp<=phase_ctrl;

  end if;

end if;

end process;

dout<=temp;

end architecture;

============================================

仔细分析一下,就是当反相开关打开以后,相位控制字统一加上2048,正好是半个周期,因此反相。

untitled.bmp

完整的DDS模块

untitled.bmp

完整的DDS(反相)模块

untitled.bmp

DDS模块封装,KCUSTOM是自定义的频率控制字,CLK为时钟输入,DAIN为输出的正弦波信号。

2.调幅波模块

根据已学过的高频电子线路知识知道调幅波的表达式如下:

考虑到这当中用到大量的运算,如果一个一个单独定制乘法加法模块较为繁琐,因此直接使用VHDL语言编写,简洁明了。VHDL代码如下。

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

use ieee.std_logic_arith.all;

entity test is

generic(ma:integer:=7);

port (

clk:in std_logic;

sig:in signed (9 downto 0);

carry:in signed (9 downto 0);

amwave:out signed (9 downto 0)

);

end test;

architecture beh of test is

signal s:signed(3 downto 0);

signal t:signed(23 downto 0);

begin

s<=conv_signed(ma,4);

process(clk)

begin

if clk'event and clk='1' then

t<=(s*sig+3577)*carry;

amwave<=t(22 downto 13);

end if;

end process;

end beh;

========================================

在这当中最难理解的莫过于3577这个数了。在十进制中,我们加上的是1。之前接触的一直是10进制,没有仔细思考这个1的含义。现在换成2进制,当然不能加上二进制的1,而要换成别的。十进制当中,这个1是调制度M的最大值与正弦函数的最大值1相乘的结果。而在二进制中,调制度用四位有符号数表示,最大为7,正弦函数用10位有符号二进制数表示,最大值为511。因此,相乘后结果就是3577。用它来替换原来十进制中的1,才能得出正确的结果。

untitled.bmp

如图所示为AM模块的原理图

3.频率计模块

频率计的原理有两种,一种是计数式测量,一种是周期式测量。前者对与频率较高的信号测量较为准确,后者对于频率较低的信号测量较为准确。考虑到我们要测量的信号频率都很高,因此选择前者。我设计的频率计有4个量程,×1,×10,×100,×1000。原理很简单,例如×1档来说,只要给一个1HZ脉冲,通过计数器计算出在脉冲时间内信号上升沿的个数就可以了,也就是把信号的符号位接在计数器的CLK端。

untitled.bmp

TIMER模块为定时电路,控制计数的停止与开始,送到T_CON模块后,由该模块发出使能信号。CNT4*10模块为计数模块,DISPREG为显示寄存器,使得示数不至于变化的太快。

4.基准频率源模块

由于频率计模块中涉及到需要产生精确的基准频率,因此需要对系统48M频率进行分频。对48分解质因数可知,需要2,3,5分频。2,3分频的模块在数字钟里已有。5分频的原理和3分频非常类似,同样是利用把PQ变量错开半周期,不同的是判断语句不一样,而且在5分频里PQ要变为三位矢量,否则没有足够多的状态数来产生分频效果。

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

entity FP5 is

port(

clk:in std_logic;

clkout:out std_logic

);

end FP5;

architecture rtl of FP5 is

signal p,q:std_logic_vector(2 downto 0);

begin

process(clk)

begin

if (clk'event and clk='1') then

if p="100" then p<="000";

else

  p<=p+1;

end if;

  end if;

end process;

process(clk)

begin

if (clk'event and clk='0')

then

if q="100" then q<="000";

else

q<=q+1;

end if;

end if;

end process;

clkout<='1' when (p(2)='0' and q(2)='0' and (p(1)='0' or p(0)='0')) else '0';

end rtl;

====================================================

5.AD转换(未完成)

我在周二的时候就已经做完了所有的基本功能,然后开始思考如何加上一些附加功能。我首先考虑的就是,我的频率计能不能测量一个外部的信号的频率。由于板子内部全部是数字信号,因此外部的模拟信号进来必须要经过AD转换。将外部的信号接在板子上的SGIN引脚处,对ADC做适当的设定,在ADC的8个输出脚上就会产生相应的数字信号。于是我在接完线以后尝试使用SIGNALTAP逻辑分析仪来捕捉ADC的输出信号,但是很遗憾,尝试了一个下午,ADC输出口出来的数字信号始终无规律,而按照理论它应该是正弦波。更换实验台也无果。这个问题曾经在去年的华为杯比赛时出现过,我们为了这个问题调试了整整一天,直至最后才解决。不过我已经记不清当时是如何解决的了,当时做的报告上也没有写这方面的内容。所以,以后写报告的时候一定要有经验总结的内容,把实验中遇到的所有问题都记录下来。

6.相位测量(未完成)

相位测量的原理也是比较简单的。对于两个用DDS产生的正弦波信号,只需取出他们同一时刻的频率控制字的差值,计算其差值,再换算成相位,送到显示电路显示即可。但是很遗憾的是,我在接入相位测量电路以后,频率计的示数错误。在之前的调试过程中曾经出现过这样的状况,我知道是时钟信号太多,互相之间有干扰的原因,但是在我尽全力把所有的多余的高频率时钟去掉以后,问题仍然没有解决。由于时间已经到快验收的时间了,所以不得已只能使用做相位测量之前的备份版去验收,这个功能没有能够出现在最后的验收作品中。

7.动态显示电路

动态显示电路主要目的就是显示频率计的示数。与之前数字钟的设计几乎完全一致,只不过此次是4位数码管而已,所以对上次的电路略加修改就可以了。

untitled.bmp

8.显示切换电路

由于要在正弦调幅波,三角调幅波,反相波三者之间切换,所以我自己写了个简单的数据选择器来实现切换功能。

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

ENTITY MUX42 IS

PORT(

CLK,SW2,SW3:IN STD_LOGIC;

SIGIN,AMWAVEIN,SIG_ORI,SIG_REV,TRI_SIG,TRI_MOD:STD_LOGIC_vECTOR(9 DOWNTO 0);

DA1IN,DA2IN:OUT STD_LOGIC_VECTOR(9 DOWNTO 0)

);

END MUX42;

ARCHITECTURE BEH OF MUX42 IS

SIGNAL TEMP1,TEMP2:STD_LOGIC_VECTOR(9 DOWNTO 0);

BEGIN

PROCESS(CLK)

BEGIN

IF CLK'EVENT AND CLK='1' THEN

  IF SW2='1' THEN

  TEMP1<=SIG_ORI;

  TEMP2<=SIG_REV;

  ELSIF SW3='1' THEN

  TEMP1<=SIGIN;

  TEMP2<=AMWAVEIN;

  ELSE

  TEMP1<=TRI_SIG;

  TEMP2<=TRI_MOD;

  END IF;

END IF;

END PROCESS;

DA1IN<=TEMP1;

DA2IN<=TEMP2;

END BEH;

===========================================

10.其它

总图内还有很多其它的小模块比如常数模块等,比较简单,用VHDL写也就是几行的工作量,在此略去。

11.总图

untitled.bmp

三.      编译下载

首先进行引脚的设置,先对最终的xianshi电路进行编译,然后点Assignments->Pins,然后按书后附录配置引脚。

配置完再点Assignments->Settings设置其余管脚,然后再编译,点下载按钮,再点Hardware Setup将平台改为ByteBlaster[LPT1],再点START即可。

四.      实验总结和感受。

1.我在实验中遇到过的比较大的困难。

1)频率计示数错误。 其实这个问题的解决纯粹是经验了,因为单单去排查频率计和显示电路都没有任何问题。我只是联想到做电子钟的时候有一次因为多引了一个1000HZ的OUTPUT出来并且没有锁定任何端口,结果直接导致钟走时不稳定。所以我怀疑是不是还是这方面的问题。我把所有多余的时钟信号全部删掉以后,问题解决。所以SIMPLE IS BEST是永恒不变的真理,在实现同样的功能的情况下,结构简单意味着高可靠性!不仅是电路,现在的机械设计都有回归简单的趋势,都是一个道理,简单的东西维护成本低,故障率小。尤其是我电路里多出来的时钟这样多余的东西,更是不应当保留。

2)调幅波波形不对。某天下午我一直都在折腾调幅波公式里的1换算成2进制到底是多少。由于我进度比较快,也没有别人可以求助,于是我从差不多从12位2进制的0一直试到111111111111,几乎见过了所有的错误波形,没有一个是对的。所有的波形都基本上都是由调幅波做某种变换而来,都很像,但都不对。晚上回去静下心来翻了一会高频书,终于弄懂了,觉得应该是7×511。第二天上机一试,果然成功了。所以我觉得以后做实验千万不能急于求成,看到东西近在眼前却搞不定就急躁,乱来。我要是下午就翻翻书,也许下午就搞出来了,不用等晚上了。所以做实验的时候心态要好。

2.我在绘制原理图过程中的经验总结

1.使用VHDL代码写模块时,保存的VHD文件的名字最好和代码里ENTITY后的实体名保持一致,否则在你写了多个相似模块以后,QUARTUS很有可能张冠李戴,在你双击了这个模块以后它却打开了另一个VHD文件,不注意的话很容易出错。

2.连线要简洁。这个感受是我在做电子钟的时候就体会到的。对于那些密密麻麻的端口连接,直接用信号名就可以,简洁明了。

3.对于从书上看来的源代码的原理一定要弄懂。我之前电子钟里面的3分频代码是从书上看来的,当时我对它的原理不是太清楚。后来偶然的机会我用仿真的方法仔细观察了一下波形,一目了然,弄清了它的原理。于是本次实验中需要5分频的时候我就能很顺利的在源代码的基础上改一下就产生了5分频。直接抄代码的话,一旦电路出现任何问题,根本都不知道从哪下手。

4.关于创新设计。这次实验我的进度比较快,所以我有比较充裕的时间来思考一些附加功能。从实用的角度出发,我首先想到的就是,我能不能测量一个外部进来的正弦信号的频率,老是测量板子里面产生的频率我觉得有点自己和自己玩的感觉,没什么意思。后来很遗憾,卡在AD转换那一步了。然后我设计了一个三角波发生器,这个我觉得还比较实用。后来周三的晚上我曾经去图书馆查了一下有没有什么比较好的设计,感觉都不大实用,比如LCD图片显示,音乐播放等等,音乐播放也不是什么特别难的代码,但是没什么实用性,我就没加了.另外,半周期数据ROM我觉得是个好设计思路,甚至可以简化成1/4周期,因为这样的设计可以节约存储空间。现在一个周期只有4096个点,当精度要求提高,或者波形种类大幅增多以后,一半,或者1/4节省出来的存储空间就非常可观了,可以留出空间给那些需要更多ROM空间的模块。

我觉得,简单就是最好的。所有的创新设计,其目的都应当是强大一个产品的功能,而不是是它看上去更炫。一个电路设计,完成了它的功能以后,再加上若干工作指示灯,就可以了。工作指示灯是绝对必须的。在做成成品板子以后,如果你连电路的工作状态都不知道,出了问题,怎么查错?就比如实验箱上的AD/DA PACK,上面两个LED是常亮的,一个左上角的电源灯,还有一个右下角的配置成功指示灯(在配置的过程中会熄灭)。非常的实用。我也曾经拆过一些成品电子产品的板子,除了那些给用户看的指示灯以外,在板子上还有若干个用于调试的指示灯,很实用。至于那些花里胡哨的东西,我觉得就不必了吧。花里胡哨的东西加多了只会让人有山寨的感觉,想当年山寨的名字刚出现的时候,就是因为花哨的东西太多,华而不实。一切的设计都应当以实用为主。

5.遗憾之处。这次相位测量没能做进最后的电路里不得不说是一大遗憾。究其根本原因在于,时钟电路设计不合理!我一共三个模块需要用到时钟,三角波,正弦波,以及正弦波反相。这三个模块都是始终接着48M时钟在,一直工作,只不过每次只有两路送到DA芯片罢了。如此高频的时钟振荡,很难保证他们之前不相互影响。我还发现,三角波的频率如果和正弦波不一样的话,频率计也不准。原因还是同时工作会有干扰。所以,合理的设计应该是,需要工作的模块接时钟,不需要的不接。我之前一直不把这个问题当回事,直到周四意识到干扰的严重性以后才匆忙写了个时钟切换模块,但是估计是代码写的不好,这个模块压根没工作,时间也来不及了,所以就直接交了备份上去验收了。所以,对待高频振荡的时钟一定要慎之又慎!

更多相关推荐:
频率计实验报告

频率计实验报告频率计实验报告一实验目的1应用AT89S52单片机单片机的IO端口外扩驱动器74HC573和74HC138LED数码管动态显示等实现对外部信号频率进行准确计数的设计二实验要求A基本要求使用单片机的...

数字频率计实验报告

数字电路与系统课程设计大连理工大学城市学院数字电路与系统课程设计设计题目数字频率计学院电子与自动化学院专业自动化学生揣智涵同组人王晓宁周英茹指导教师于海霞完成日期20xx年3月26日1数字电路与系统课程设计目录...

频率计设计实验报告

频率计设计实验报告智能090120xx010993周红蕊一设计任务设计一个频率计电路要求有4位十进制数码显示可测量函数发生器输出的信号频率1可测量9999KHZ以内的频率并显示24位数的任意脉冲计数和显示3将灵...

数字频率计实验报告 20xx年

20xx年电子技术实验实验报告频率计一概述数字频率计是使用领域非常广泛的测量仪器在计算机通讯设备音频视频等科研生产领域不可缺少通过十进制数字显示被测信号频率具有测量迅速精度高显示直观等诸多优点本实验中我们使用V...

频率计实验报告_20xx011014

数字逻辑与处理器基础实验三频率计实验报告实验目的掌握频率计的原理和设计方法实验工具1Verilog语言2QuartusII903DE2实验板实验设计1总体思路以及模块总述设计的基本思路是按照实验指导书上给出的原...

简易数字频率计设计实验报告1赵勇

南理工紫金学院课题实验设计报告学生姓名赵勇学号专业电气工程及其自动化题目电子综合应用实践1课程设计任务书2课程设计任务书1封面课程设计题目班级姓名2设计任务书3目录4设计方案简介5设计条件及主要参数表6设计主要...

四位数字频率计实验报告

数字逻辑电路大型实验报告姓名指导教师专业班级学院信息工程学院提交日期1一实验目的学习用FPGA实现数字系统的方法二实验内容1FPGAQuartusII和VHDL使用练习2四位数字频率计的设计三四位数字频率计的设...

频率计实验报告

实验课题函数波形发生器和频率计设计一设计目的1掌握低频数字频率计的设计原理与设计方法2学会安装与调试数字电路的方法与步骤3熟练掌握计数锁存译码显示电路的应用二设计任务与要求1测量信号范围方波正弦波幅度055V频...

简易数字频率计设计实验报告

电子线路课程设计报告第1页共14页电子线路课程设计报告姓名学号专业电子信息日期20xx413南京理工大学紫金学院电光系20xx4131电子线路课程设计报告第引言2页共14页电子线路课程设计是一门理论和实践相结合...

综合课程设计报告——简易数字频率计-精品

综合课程设计报告题目系别专业班级姓名导师成绩基于单片机的简易数字频率计设计电子信息与电气工程系电子信息工程20xx年12月25日目录摘要21引言211设计任务212设计要求22系统设计221设计思路222总体方...

综合电子实验设计报告(频率计)

综合电子系统设计报告实验名称基于STM32的频率计设计班级电子1202学号03号姓名指导老师20xx年4月13日一系统设计1方案论证一控制部分的选择方案一C51单片机本身的资源就太少做个频率计就需要用到一个定时...

实验报告模板:实验四 数字频率计设计

EDA与数字系统设计实验报告第专业班级学号姓名实验四数字频率计设计1实验目的1掌握数字频率计的Verilog描述方法2学习设计仿真工具的使用方法3学习层次化设计方法实验内容1用4位十进制计数器对用户输入时钟进行...

频率计实验报告(28篇)