DDS技术之FPGA技术之LPM_ROM生成正弦波

       频率合成技术是利用频率合成的方法,使某一(或多个)基准频率,通过一定的变换与处理后,形成一系列等间隔的离散频率。

       直接数字频率合成器(Direct Digital Frequency Synthesize)技术是一种基于全数字技术,从相位概念出发直接合成所需波形的一种频率合成技术。其原理图如下:

       DDS技术之FPGA技术之LPM_ROM生成正弦波_第1张图片

         如图所示,用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++软件编程实现:

#include<iostream.h>
#include<fstream.h>
#include<math.h>
void main()
{
	double pi=3.141593;
	double step=pi*2/256;
	ofstream outfile;
	outfile.open("sin.mif");
	outfile<<"--Maxplus Memory Initiallization File"<<endl;
	outfile<<"--sin.mif"<<endl;
	outfile<<"WIDTH=8;"<<endl;
	outfile<<"DEPTH=256;"<<endl;
	outfile<<"ADDRESS_RADIX=HEX;"<<endl;
	outfile<<"DATA_RADIX=DEC;"<<endl<<endl;
	outfile<<"CONTENT BEGIN"<<endl;
	for(int i=0;i<256;i++)
	{
		outfile<<hex<<i<<" : "<<dec<<int((sin(i*step)+1)/2*255+0.5)<<";"<<endl;
	}
	outfile<<"END;";
} 
      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/3766264

2、使用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);

DDS技术之FPGA技术之LPM_ROM生成正弦波_第2张图片   

      波形图比较丑,是因为我的mif没有做好的缘故。请见谅哈!

      Ok了,程序设计步骤大致如上所示,但是这个程序还只是实现了DDS一个基本的功能,想要探究DDS的强大功能的话,还要继续花大量时间去整理的。

      在此,我附上我个人的仿真程序下载地址:http://download.csdn.net/detail/csf111/3767213

      由于时间匆忙,错误是难免的,欢迎大家交流讨论。


你可能感兴趣的:(vector,String,File,matlab,library,Signal)