二、基于FPGA的信号发生器设计
以FPGA 芯片为载体, 通过QuartusII 的LPM_ROM 模块和VHDL 语言为核心设计一个多功能信号发生器,根据输入信号的选择可以输出递增锯齿波、递减锯齿波、三角波、阶梯波和方波等5 种信号,通过QuartusII 软件进行波形仿真、定时分析,仿真正确后,利用实验板提供的资源,下载到芯片中实现预定功能。
信号发生器又称为波形发生器, 是一种常用的信号源,广泛应用于电子电路、通信、控制和教学实验等领域。它是科研及工程实践中最重要的仪器之一, 以往多用硬件组成,系统结构比较复杂,可维护性和可操作性不佳。随着计算机技术的发展,信号发生器的设计制作越来越多的是用计算机技术,种类繁多,价格、性能差异很大。用FPGA 或CPLD 来实现,它的优点是可以进行功能仿真,而且FPGA 和CPLD 的片内资源丰富,设计的流程简单。用FPGA 所构成的系统来产生波形信号,这个系统既能和主机系统相连,用相应的上层软件展示波形信号, 又方便程序的编写, 而且还有A/D0809接口可以产生模拟信号的输出和外面的示波器相连。
1 正弦信号发生器的LPM 定制
正弦信号发生器由计数器或地址发生器(6 位)、正弦信号数据ROM (6 位地址线,8 位数据线, 含有64 个8 位数据, 一个周期)、原理图顶层设计和8 位D/A ( 实验中用DAC0832 代替)。
其框图如图1 所示。其中信号产生模块将产生所需的各种信号,这些信号的产生可以有多种方式,如用计数器直接产生信号输出,或者用计数器产生存储器的地址,在存储器中存放信号输出的数据。信号发生器的控制模块可以用数据选择器实现, 用8 选1 数据选择器实现对5 种信号的选择。
图1 信号发生器结构框图
最后将波形数据送入D/A 转换器,将数字信号转换为模拟信号输出。用示波器测试D/A 转换器的输出,可以观测到5 种信号的输出。
1.1 定制初始化数据文件
QuartusII 能接受的LPM_ROM 模块中的初始化数据文件的格式有两种:。mif 格式文件和。hex 格式文件。实际应用中只要使用其中一种格式的文件即可。下面采用。mif 格式文件,调出产生ROM 数据文件大小的选择窗。根据64 点8 位正弦数据的情况,可选ROM 的数据数Number 为64,数据宽Word size 取8 位。单击OK 按钮,将出现图2 所示的空的。mif数据表格,表格中的数据格式可通过鼠标右键单击窗口边缘的地址数据弹出的窗口选择。
图2 .mif 数据表格
将波形数据填入mif 文件表中也可以使用QuartusII 以外的编辑器设计MIF 文件,其格式如下:
#include 《STdio.h》
#include “math.h”
main()
{int i;float s;
for (i=0;i《1024; i++)
{ s = sin(atan(1)*8*i/1024);
printf(“%d : %d;\n”,i,(int)((s+1)*1023/2)); }}
把上述程序编译成程序后, 可在DOS 命令行下执行命令:
romgen 》 sin_ rom. mif;
1.2 定制LPM 元件
打开Mega Wizard Plug_In Manager 初始对话框, 选择Create a new custom… 项。单击Next 按钮后,选择Storage 项下的LPM_ROM, 再选择ACEX1K 器件和VHDL 语言方式;最后输入ROM 文件存放的路径和文件名:F:\sing_gnt\data_rom (定制的ROM 元件文件名),单击Next 按钮,选择ROM 控制线、地址线和数据线。这里选择地址线位宽和ROM 中数据数分别为6 和64; 选择地址锁存控制信号inclock。
对于地址信号发生器的设计。方法一:用VHDL 语言设计6 位计数器,产生其元件符号;方法二:仍采用LPM 定制的方法。
1.3 完成顶层设计
按图3 画出顶层原理图,然后进行编译,波形仿真如图4所示。
图3 简易正弦信号发生器顶层电路设计
图4 当前工程仿真波形输出
对当前设计通过执行Quartus II 的命令Create ∠ Update/ Create Symbol Files for Current File,可以为设计电路建立一个元件符号,以便被顶层设计多功能信号发生器所调用。
2 其他信号部分原程序
其他各信号发生器可参照正弦信号发生器的设计方法设计或直接采用VHDL 硬件描述语言进行设计。
LIBRARY IEEE;--递增锯齿波的设计
USE IEEE.STD LOGIC 1164.ALL;
USE IEEE.STD LOGIC UNSIGNED.ALL;
ENTITY signal2 IS --递增锯齿波signal1
PORT(clk,reset:IN std_logic;--复位信号reset, 时钟信号clk
q:OUT std_logic_vector (7 DOWNTO 0));--输出信号q
END signal2;
ARCHITECTURE b OF signal2 IS
BEGIN
PROCESS(clk,reset)
VARIABLE tmp:std_logic_vector(7 DOWNTO 0);
BEGIN
IF reset=‘0’ THEN
tmp:=“00000000”;
ELSIT rising_ege(clk)THEN
IF tmp=“11111111”THEN
tmp:=“00000000”;
ELSE
tmp:=tmp+1; --递增信号的变化
END IF;
END IF;
q《=tmp:
END PROCESS;
END b;
LIBRARY IEEE;--方波的设计
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity signal5 is --方波signal5
PORT(clk,reset:in std_logic; --复位信号reset,时钟信号clk
q:out std_logic_vector (7 DOWNTO 0)); --输出信号q,8 位数字信号
END signal5;
ARCHITEECTURE a OF signal5 IS
SIGNAL; a:std_logic;
BEGIN
PROCESS(clk,reset)
YARIABLE tmp:std_logic_vector(7 downto 0);
BEQIN
IF reset=‘0’ then
a《=‘0’;
elsif rising_edge(clk)THEN
IF tmp=“11111111” THEN
tmp:=“00000000”;
ELSE
tmp:=tmp+1;
END IF;
if tmp《=“10000000” then
a《=‘1’;
else
a《=‘0’;
END IF;
END IF;
END PROCESS;
PROCESS(clk,a)
BEGIN
IF rising_edge(clk)THEN
IF a=‘1’ THEN
q《=“11111111”;
ELSE
q《=“00000000”;
END IF;
END IF;
END PROCESS;
END a;
评论
查看更多