在网上看到一篇文章,感觉还不错,给大家分享一下。网址:http://blog.csdn.net/csf111/article/details/6944148
频率合成技术是利用频率合成的方法,使某一(或多个)基准频率,通过一定的变换与处理后,形成一系列等间隔的离散频率。
直接数字频率合成器(Direct Digital Frequency Synthesize)技术是一种基于全数字技术,从相位概念出发直接合成所需波形的一种频率合成技术。其原理图如下:
如图所示,用VHDL编程的话,至少需要建立一个加法器、一个锁存器以及一个ROM存储器;加法器用来累加相位或者地址信号,锁存器用来所存输出信号以及反馈,ROM存储器则用来存储波形数据的数字幅度;最后还需要一个总得模块将三者结合在一起。
首先:建立ROM表;
在quartus II上面使用LPM_ROM,就必须学会MegaWizard Plug-in Manager的用法,要用MegaWizard Plug-in Manager,那么就必须先学会创建mif或者hex文件,下面具体以正弦波为例,介绍mif文件的创建方法以及如何调用LPM_ROM。
1、创建mif文件的三种方法(其实不只三种,下面就我调试成功的来一一说明,并且附上源代码吧):
根据需要设置每个字的位宽WIDTH和总字数DEPTH。然后设置地址和数据的进制基数ADDRESS_RADIX、DATA_RADIX,使用无符号数UNS。然后用如下方法生成需要的数据(按上边的格式,注意中间“:”,最后“;”),往CONTENT BEGIN和END中间一贴就行了。
1)用VC++软件编程实现:
2)用Matlab编程实现:
创建.m文件
- width=8; %数据宽度为10位;
- depth=2^width;
- N=0:1:depth-1;
- s=sin(pi*N/depth); %计算0~pi/2的Sin值;
- fidc=fopen('sin_matlab.mif','wt'); %以"wt"的形式打开,\n为换行
- % 写入 sin_matlab.mif %
- fprintf(fidc,'width=%d;\n',width);
- fprintf(fidc,'depth=%d;\n',depth);
- fprintf(fidc,'address_radix=uns;\n');
- fprintf(fidc,'data_radix = uns;\n');
- fprintf(fidc,'content begin\n');
- for(x=1:depth);
- fprintf(fidc,'%d:%d;\n',x-1, round( (depth/2-1)*sin(pi*(x-1)/(depth/2)) + depth/2) );
- end
- fprintf(fidc,'end;');
- fclose(fidc);
3)用软件Guagle_wave.exe自动生成mif或者hex文件软件下载地址:http://download.csdn.net/detail/csf111/37662642、使用tools\MegaWizard Plug-in Manager来新建LPM_ROM,具体方法不讲述,只要quartus II软件当中去了,相应的设置选项都很容易懂的,主要是要设置你的ROM地址宽度和数据点数,其间需要调用mif文件的,选择你刚才建立的mif即可;3、上面几步完成之后,quartus II 就会自动生成一个VHD文件,如下:
- -- megafunction wizard: %ROM: 1-PORT%
- -- GENERATION: STANDARD
- -- VERSION: WM1.0
- -- MODULE: lpm_rom
- -- ============================================================
- -- File Name: lpm_rom8.vhd
- -- Megafunction Name(s):
- -- lpm_rom
- --
- -- Simulation Library Files(s):
- -- lpm
- -- ============================================================
- -- ************************************************************
- -- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
- --
- -- 8.1 Build 163 10/28/2008 SJ Full Version
- -- ************************************************************
- --Copyright (C) 1991-2008 Altera Corporation
- --Your use of Altera Corporation's design tools, logic functions
- --and other software and tools, and its AMPP partner logic
- --functions, and any output files from any of the foregoing
- --(including device programming or simulation files), and any
- --associated documentation or information are expressly subject
- --to the terms and conditions of the Altera Program License
- --Subscription Agreement, Altera MegaCore Function License
- --Agreement, or other applicable license agreement, including,
- --without limitation, that your use is for the sole purpose of
- --programming logic devices manufactured by Altera and sold by
- --Altera or its authorized distributors. Please refer to the
- --applicable agreement for further details.
- LIBRARY ieee;
- USE ieee.std_logic_1164.all;
- LIBRARY lpm;
- USE lpm.all;
- ENTITY lpm_rom8 IS
- PORT
- (
- address : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
- inclock : IN STD_LOGIC ;
- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
- );
- END lpm_rom8;
- ARCHITECTURE SYN OF lpm_rom8 IS
- SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
- COMPONENT lpm_rom
- GENERIC (
- intended_device_family : STRING;
- lpm_address_control : STRING;
- lpm_file : STRING;
- lpm_outdata : STRING;
- lpm_type : STRING;
- lpm_width : NATURAL;
- lpm_widthad : NATURAL
- );
- PORT (
- address : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
- inclock : IN STD_LOGIC ;
- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
- );
- END COMPONENT;
- BEGIN
- q <= sub_wire0(7 DOWNTO 0);
- lpm_rom_component : lpm_rom
- GENERIC MAP (
- intended_device_family => "FLEX10K",
- lpm_address_control => "REGISTERED",
- lpm_file => "sin_soft.mif",
- lpm_outdata => "UNREGISTERED",
- lpm_type => "LPM_ROM",
- lpm_width => 8,
- lpm_widthad => 7
- )
- PORT MAP (
- address => address,
- inclock => inclock,
- q => sub_wire0
- );
- END SYN;
- -- ============================================================
- -- CNX file retrieval info
- -- ============================================================
- -- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
- -- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
- -- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
- -- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
- -- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
- -- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
- -- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
- -- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
- -- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
- -- Retrieval info: PRIVATE: Clken NUMERIC "0"
- -- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
- -- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
- -- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
- -- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "FLEX10K"
- -- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
- -- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
- -- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
- -- Retrieval info: PRIVATE: MIFfilename STRING "sin_soft.mif"
- -- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "128"
- -- Retrieval info: PRIVATE: OutputRegistered NUMERIC "0"
- -- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
- -- Retrieval info: PRIVATE: RegAdd NUMERIC "1"
- -- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
- -- Retrieval info: PRIVATE: RegOutput NUMERIC "0"
- -- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
- -- Retrieval info: PRIVATE: SingleClock NUMERIC "0"
- -- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
- -- Retrieval info: PRIVATE: WidthAddr NUMERIC "7"
- -- Retrieval info: PRIVATE: WidthData NUMERIC "8"
- -- Retrieval info: PRIVATE: rden NUMERIC "0"
- -- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "FLEX10K"
- -- Retrieval info: CONSTANT: LPM_ADDRESS_CONTROL STRING "REGISTERED"
- -- Retrieval info: CONSTANT: LPM_FILE STRING "sin_soft.mif"
- -- Retrieval info: CONSTANT: LPM_OUTDATA STRING "UNREGISTERED"
- -- Retrieval info: CONSTANT: LPM_TYPE STRING "LPM_ROM"
- -- Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
- -- Retrieval info: CONSTANT: LPM_WIDTHAD NUMERIC "7"
- -- Retrieval info: USED_PORT: address 0 0 7 0 INPUT NODEFVAL address[6..0]
- -- Retrieval info: USED_PORT: inclock 0 0 0 0 INPUT NODEFVAL inclock
- -- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
- -- Retrieval info: CONNECT: @address 0 0 7 0 address 0 0 7 0
- -- Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
- -- Retrieval info: CONNECT: @inclock 0 0 0 0 inclock 0 0 0 0
- -- Retrieval info: LIBRARY: lpm lpm.lpm_components.all
- -- Retrieval info: GEN_FILE: TYPE_NORMAL lpm_rom8.vhd TRUE
- -- Retrieval info: GEN_FILE: TYPE_NORMAL lpm_rom8.inc FALSE
- -- Retrieval info: GEN_FILE: TYPE_NORMAL lpm_rom8.cmp TRUE
- -- Retrieval info: GEN_FILE: TYPE_NORMAL lpm_rom8.bsf FALSE
- -- Retrieval info: GEN_FILE: TYPE_NORMAL lpm_rom8_inst.vhd FALSE
- -- Retrieval info: LIB_FILE: lpm
其次,建立锁存器模块;
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- ENTITY REG8B IS
- PORT ( Load : IN STD_LOGIC;
- DIN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) );
- END REG8B;
- ARCHITECTURE behav OF REG8B IS
- BEGIN
- PROCESS(Load, DIN)
- BEGIN
- IF Load'EVENT AND Load = '1' THEN -- 时钟到来时,锁存输入数据
- DOUT <= DIN;
- END IF;
- END PROCESS;
- END behav;
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
- ENTITY ADDER8B IS
- PORT ( A : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- B : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- S : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
- END ADDER8B;
- ARCHITECTURE behav OF ADDER8B IS
- BEGIN
- S <= A + B;
- END behav;
- ---------------------------------------------------------------------
- -- Designed By Michael Chen( chen sifan) ---
- -- 2011\11\07 ---
- ---------------------------------------------------------------------
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
- ---------------------------------------------------------------------
- ENTITY mydds IS -- 顶层设计
- PORT (
- CLK : IN STD_LOGIC;
- FWORD : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- FOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
- END mydds;
- ---------------------------------------------------------------------
- ARCHITECTURE behav OF mydds IS
- ---------------------------------------------------------------------
- COMPONENT REG8B --load 'event and load = 1 --dout <= din;
- PORT (
- LOAD : IN STD_LOGIC;
- DIN : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- DOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
- END COMPONENT;
- ---------------------------------------------------------------------
- COMPONENT ADDER8B
- PORT (
- A : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- B : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- S : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
- END COMPONENT;
- ---------------------------------------------------------------------
- COMPONENT lpm_rom8
- PORT (
- address : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
- inclock : IN STD_LOGIC ;
- q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
- END COMPONENT;
- -----------------------------------------------------------------------
- SIGNAL F8B : STD_LOGIC_VECTOR( 7 DOWNTO 0);
- SIGNAL A8B : STD_LOGIC_VECTOR( 7 DOWNTO 0);
- SIGNAL B8B : STD_LOGIC_VECTOR( 7 DOWNTO 0);
- SIGNAL C8B : STD_LOGIC_VECTOR( 7 DOWNTO 0);
- ---------------------------------------------------------------------
- BEGIN
- F8B<=FWORD;
- U1 : ADDER8B PORT MAP( A=>F8B,B=>B8B, S=>A8B );
- U2 : REG8B PORT MAP( DOUT=>B8B,DIN=>A8B, LOAD=>CLK );
- U3 : REG8B PORT MAP( DOUT=>C8B,DIN=>B8B, LOAD=>CLK );
- U4 : lpm_ROM8 PORT MAP( address=>C8B(7 downto 0), q=>FOUT, inclock=>CLK );
- END behav;
设置成模拟显示的方法如下图(Analog WaveForm选项 ):
最后,有兴趣的“玩家”可以将仿真的波形拿到Matlab当中去。具体方法如下:在quartus II中将波形仿真文件保存为tbl格式的文件,然后在Matlab环境下面去建立M文件去将tbl还原成波形图,顺带也把代码贴下面吧:
- %mydds.m
- %Designed By Michael Chen (Chen sifan),2011\11\07
- clear all;
- fid = fopen('D:\Program Files\alter\MyWork\MyDDS.tbl','r');%tbl文件的路径要写对哦
- data = fscanf(fid,'%s');
- fclose(fid);
- b = find(data == '=');
- number = length(b);
- j = 0;
- for i = 1 : number-1
- j = j+1;
- c_s(j,1) = data(b(i)+1);
- c_s(j,2) = data(b(i)+2);
- end;
- d_s = hex2dec(c_s);%将16进制的数据转换成十进制的
- plot(d_s);
波形图比较丑,是因为我的mif没有做好的缘故。请见谅哈!
Ok了,程序设计步骤大致如上所示,但是这个程序还只是实现了DDS一个基本的功能,想要探究DDS的强大功能的话,还要继续花大量时间去整理的。
在此,我附上我个人的仿真程序下载地址:http://download.csdn.net/detail/csf111/3767213
由于时间匆忙,错误是难免的,欢迎大家交流讨论


