二、基于FPGA的信號(hào)發(fā)生器設(shè)計(jì)
以FPGA 芯片為載體, 通過(guò)QuartusII 的LPM_ROM 模塊和VHDL 語(yǔ)言為核心設(shè)計(jì)一個(gè)多功能信號(hào)發(fā)生器,根據(jù)輸入信號(hào)的選擇可以輸出遞增鋸齒波、遞減鋸齒波、三角波、階梯波和方波等5 種信號(hào),通過(guò)QuartusII 軟件進(jìn)行波形仿真、定時(shí)分析,仿真正確后,利用實(shí)驗(yàn)板提供的資源,下載到芯片中實(shí)現(xiàn)預(yù)定功能。
信號(hào)發(fā)生器又稱(chēng)為波形發(fā)生器, 是一種常用的信號(hào)源,廣泛應(yīng)用于電子電路、通信、控制和教學(xué)實(shí)驗(yàn)等領(lǐng)域。它是科研及工程實(shí)踐中最重要的儀器之一, 以往多用硬件組成,系統(tǒng)結(jié)構(gòu)比較復(fù)雜,可維護(hù)性和可操作性不佳。隨著計(jì)算機(jī)技術(shù)的發(fā)展,信號(hào)發(fā)生器的設(shè)計(jì)制作越來(lái)越多的是用計(jì)算機(jī)技術(shù),種類(lèi)繁多,價(jià)格、性能差異很大。用FPGA 或CPLD 來(lái)實(shí)現(xiàn),它的優(yōu)點(diǎn)是可以進(jìn)行功能仿真,而且FPGA 和CPLD 的片內(nèi)資源豐富,設(shè)計(jì)的流程簡(jiǎn)單。用FPGA 所構(gòu)成的系統(tǒng)來(lái)產(chǎn)生波形信號(hào),這個(gè)系統(tǒng)既能和主機(jī)系統(tǒng)相連,用相應(yīng)的上層軟件展示波形信號(hào), 又方便程序的編寫(xiě), 而且還有A/D0809接口可以產(chǎn)生模擬信號(hào)的輸出和外面的示波器相連。
1 正弦信號(hào)發(fā)生器的LPM 定制
正弦信號(hào)發(fā)生器由計(jì)數(shù)器或地址發(fā)生器(6 位)、正弦信號(hào)數(shù)據(jù)ROM (6 位地址線(xiàn),8 位數(shù)據(jù)線(xiàn), 含有64 個(gè)8 位數(shù)據(jù), 一個(gè)周期)、原理圖頂層設(shè)計(jì)和8 位D/A ( 實(shí)驗(yàn)中用DAC0832 代替)。
其框圖如圖1 所示。其中信號(hào)產(chǎn)生模塊將產(chǎn)生所需的各種信號(hào),這些信號(hào)的產(chǎn)生可以有多種方式,如用計(jì)數(shù)器直接產(chǎn)生信號(hào)輸出,或者用計(jì)數(shù)器產(chǎn)生存儲(chǔ)器的地址,在存儲(chǔ)器中存放信號(hào)輸出的數(shù)據(jù)。信號(hào)發(fā)生器的控制模塊可以用數(shù)據(jù)選擇器實(shí)現(xiàn), 用8 選1 數(shù)據(jù)選擇器實(shí)現(xiàn)對(duì)5 種信號(hào)的選擇。
圖1 信號(hào)發(fā)生器結(jié)構(gòu)框圖
最后將波形數(shù)據(jù)送入D/A 轉(zhuǎn)換器,將數(shù)字信號(hào)轉(zhuǎn)換為模擬信號(hào)輸出。用示波器測(cè)試D/A 轉(zhuǎn)換器的輸出,可以觀測(cè)到5 種信號(hào)的輸出。
1.1 定制初始化數(shù)據(jù)文件
QuartusII 能接受的LPM_ROM 模塊中的初始化數(shù)據(jù)文件的格式有兩種:。mif 格式文件和。hex 格式文件。實(shí)際應(yīng)用中只要使用其中一種格式的文件即可。下面采用。mif 格式文件,調(diào)出產(chǎn)生ROM 數(shù)據(jù)文件大小的選擇窗。根據(jù)64 點(diǎn)8 位正弦數(shù)據(jù)的情況,可選ROM 的數(shù)據(jù)數(shù)Number 為64,數(shù)據(jù)寬Word size 取8 位。單擊OK 按鈕,將出現(xiàn)圖2 所示的空的。mif數(shù)據(jù)表格,表格中的數(shù)據(jù)格式可通過(guò)鼠標(biāo)右鍵單擊窗口邊緣的地址數(shù)據(jù)彈出的窗口選擇。
圖2 .mif 數(shù)據(jù)表格
將波形數(shù)據(jù)填入mif 文件表中也可以使用QuartusII 以外的編輯器設(shè)計(jì)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 命令行下執(zhí)行命令:
romgen 》 sin_ rom. mif;
1.2 定制LPM 元件
打開(kāi)Mega Wizard Plug_In Manager 初始對(duì)話(huà)框, 選擇Create a new custom… 項(xiàng)。單擊Next 按鈕后,選擇Storage 項(xiàng)下的LPM_ROM, 再選擇ACEX1K 器件和VHDL 語(yǔ)言方式;最后輸入ROM 文件存放的路徑和文件名:F:\sing_gnt\data_rom (定制的ROM 元件文件名),單擊Next 按鈕,選擇ROM 控制線(xiàn)、地址線(xiàn)和數(shù)據(jù)線(xiàn)。這里選擇地址線(xiàn)位寬和ROM 中數(shù)據(jù)數(shù)分別為6 和64; 選擇地址鎖存控制信號(hào)inclock。
對(duì)于地址信號(hào)發(fā)生器的設(shè)計(jì)。方法一:用VHDL 語(yǔ)言設(shè)計(jì)6 位計(jì)數(shù)器,產(chǎn)生其元件符號(hào);方法二:仍采用LPM 定制的方法。
1.3 完成頂層設(shè)計(jì)
按圖3 畫(huà)出頂層原理圖,然后進(jìn)行編譯,波形仿真如圖4所示。
圖3 簡(jiǎn)易正弦信號(hào)發(fā)生器頂層電路設(shè)計(jì)
圖4 當(dāng)前工程仿真波形輸出
對(duì)當(dāng)前設(shè)計(jì)通過(guò)執(zhí)行Quartus II 的命令Create ∠ Update/ Create Symbol Files for Current File,可以為設(shè)計(jì)電路建立一個(gè)元件符號(hào),以便被頂層設(shè)計(jì)多功能信號(hào)發(fā)生器所調(diào)用。
2 其他信號(hào)部分原程序
其他各信號(hào)發(fā)生器可參照正弦信號(hào)發(fā)生器的設(shè)計(jì)方法設(shè)計(jì)或直接采用VHDL 硬件描述語(yǔ)言進(jìn)行設(shè)計(jì)。
LIBRARY IEEE;--遞增鋸齒波的設(shè)計(jì)
USE IEEE.STD LOGIC 1164.ALL;
USE IEEE.STD LOGIC UNSIGNED.ALL;
ENTITY signal2 IS --遞增鋸齒波signal1
PORT(clk,reset:IN std_logic;--復(fù)位信號(hào)reset, 時(shí)鐘信號(hào)clk
q:OUT std_logic_vector (7 DOWNTO 0));--輸出信號(hào)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; --遞增信號(hào)的變化
END IF;
END IF;
q《=tmp:
END PROCESS;
END b;
LIBRARY IEEE;--方波的設(shè)計(jì)
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity signal5 is --方波signal5
PORT(clk,reset:in std_logic; --復(fù)位信號(hào)reset,時(shí)鐘信號(hào)clk
q:out std_logic_vector (7 DOWNTO 0)); --輸出信號(hào)q,8 位數(shù)字信號(hào)
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;
評(píng)論
查看更多