大俠好,歡迎來到FPGA技術(shù)江湖,江湖偌大,相見即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。
今天給大俠帶來FPGA 之 VHDL 語法學(xué)習(xí)筆記,話不多說,上貨。
VHDL語法學(xué)習(xí)筆記
一、VHDL簡介
1.1 VHDL 的歷史
VHDL 的 英 文 全 名 是 Very-High-Speed Integrated Circuit Hardware DescriptionLanguage,誕生于 1982 年。
1987 年底,VHDL 被 IEEE 和美國國防部確認(rèn)為標(biāo)準(zhǔn)硬件描述語言。自 IEEE 公布了 VHDL 的標(biāo)準(zhǔn)版本 IEEE-1076(簡稱 87 版)之后,各 EDA 公司相繼推出了自己的 VHDL 設(shè)計環(huán)境,或宣布自己的設(shè)計工具可以提供 VHDL 接口。此后 VHDL 在電子設(shè)計領(lǐng)域逐步取代了原有的各種非標(biāo)準(zhǔn)硬件描述語言。
1993 年,IEEE 對 VHDL 進(jìn)行了修訂,從更高的抽象層次和系統(tǒng)描述能力上擴(kuò)展 VHDL 的內(nèi)容,并公布了新版本的 VHDL,即 IEEE 標(biāo)準(zhǔn)的 1076-1993版本(簡稱 93 版)。
現(xiàn)在,VHDL 和 Verilog HDL 作為 IEEE 的工業(yè)標(biāo)準(zhǔn)硬件描述語言,在電子工程領(lǐng)域已成為事實上的通用硬件描述語言。
1.2 VHDL 的特點
VHDL 主要用于描述數(shù)字系統(tǒng)的結(jié)構(gòu)、行為、功能和接口。除了含有許多具有硬件特征的語句外,VHDL 在語言形式、描述風(fēng)格和句法上與一般的計算機(jī)高級語言十分相似。VHDL 的程序結(jié)構(gòu)特點是將一項工程設(shè)計,或稱設(shè)計實體(可以是一個元件、一個電路模塊或一個系統(tǒng))分成外部和內(nèi)部兩部分。
外部也可稱為可視部分,它描述了此模塊的端口,而內(nèi)部可稱為不可視部分,它涉及到實體的功能實現(xiàn)和算法完成。在對一個設(shè)計實體定義了外部端口后,一旦其內(nèi)部開發(fā)完成,其他的設(shè)計就可以直接調(diào)用這個實體。這種將設(shè)計實體分成內(nèi)外部分的概念是VHDL 系統(tǒng)設(shè)計的基本點。
應(yīng)用 VHDL 進(jìn)行工程設(shè)計有以下的優(yōu)點:
1.行為描述
與其他的硬件描述語言相比,VHDL 具有更強(qiáng)的行為描述能力,強(qiáng)大的行為描述能力是避開具體的器件結(jié)構(gòu),從邏輯行為上描述和設(shè)計大規(guī)模電子系統(tǒng)的重要保證。
2.仿真模擬
VHDL 豐富的仿真語句和庫函數(shù),使得在任何系統(tǒng)的設(shè)計早期就能查驗設(shè)計系統(tǒng)的功能可行性,隨時可對設(shè)計進(jìn)行仿真模擬。
3.大規(guī)模設(shè)計
一些大型的 FPGA 設(shè)計項目必須有多人甚至多個開發(fā)組共同并行工作才能實現(xiàn)。VHDL 語句的行為描述能力和程序結(jié)構(gòu)決定了它具有支持大規(guī)模設(shè)計的分解和已有設(shè)計的再利用功能。
4.門級網(wǎng)表
對于用 VHDL 完成的一個確定的設(shè)計,可以利用 EDA 工具進(jìn)行邏輯綜合和優(yōu)化,并自動把VHDL 描述設(shè)計轉(zhuǎn)變成門級網(wǎng)表。
5.獨立性
VHDL 對設(shè)計的描述具有相對獨立性,設(shè)計者可以不懂硬件的結(jié)構(gòu),也不必對最終設(shè)計實現(xiàn)的目標(biāo)器件有很深入地了解。
二、VHDL 程序基本結(jié)構(gòu)
一般的 VHDL 程序可以由實體(Entity)、結(jié)構(gòu)體(Architecture)、配置(Configuration)、程序包和程序包體(Package)以及庫(Library)5 個部分組成,它們是 VHDL 程序的設(shè)計單元。
其中實體、配置和程序包屬于初級設(shè)計單元,主要的功能是進(jìn)行端口、行為、函數(shù)等的定義。結(jié)構(gòu)體和程序包體是次級設(shè)計單元,包含了所有行為以及函數(shù)的實現(xiàn)代碼。其中,程序包和程序包體又屬于公用設(shè)計單元,即它們是被其他程序模塊調(diào)用的。庫則是一批程序包的集合。
圖 1 所示為 VHDL 程序設(shè)計單元之間的關(guān)系。
圖 1 VHDL 程序設(shè)計單元關(guān)系圖
無論是復(fù)雜的還是簡單的數(shù)字模塊,用 VHDL 來描述都至少需要包括兩個部分,即實體申明(Entity Declaration)和結(jié)構(gòu)體(Architecture)。其中實體申明用于說明模塊的端口,而結(jié)構(gòu)體用于描述模塊的功能。本節(jié)下面將詳細(xì)介紹 VHDL 程序的各個設(shè)計單元。
2.1 實體的申明方法
實體是設(shè)計的基本模塊和設(shè)計的初級單元,在分層次設(shè)計中,頂層有頂級實體,含在頂級實體中的較低層次的描述為低級實體,通過配置可把頂層實體和底層實體連接起來??梢詫嶓w理解為電路圖設(shè)計中的芯片符號(Symbol),符號規(guī)定了電路的符號名、接口和數(shù)據(jù)類型。由連線(或信號)將符號互連建立設(shè)計所需的電路圖,互連線生成的網(wǎng)表,在設(shè)計實現(xiàn)之前一直是設(shè)計驗證的仿真模型,并在設(shè)計驗證后,由網(wǎng)表向布線工具提供所需的連接信息和層信息。
圖 2 所示是傳統(tǒng)設(shè)計中 R-S 觸發(fā)器的符號圖,用 VHDL 對其進(jìn)行描述的代碼如下:
ENTITY rsff IS
PORT (
Set, Reset : IN BIT;
Q, QB : BUFFER BIT );
END rsff;
圖 2 R-S 觸發(fā)器的 VHDL 實體描述和符號
實體語句用關(guān)鍵詞 ENTITY 開頭,實體名 rsff 是描述的符號名,在結(jié)束實體語句的 END rsff之間,實體語句可以用關(guān)鍵詞 BEGIN 把實體語句分成兩部分:即 BEGIN 之前是實體說明,BEGIN之后是實體語句。
在 ENTITY 語句的實體說明部分,常用 PORT 付語描述實體對外界連接的端口(數(shù)目、方向和數(shù)據(jù)類型)。實體 rsff 有 4 個端口,Set/Reset 是輸入 IN 模式,Q/QB 是輸出BUFFER(緩沖)模式,都為 BIT 類型。實體說明中還可說明數(shù)據(jù)類型、子程序和常量等數(shù)據(jù)信息,實體語句常用于描述設(shè)計經(jīng)常用到的判斷和檢查信息。
實體描述的格式如下:
ENTITY 實體名 IS
[GENERIC(參數(shù)表);]
[PORT(端口表);]
[BEGIN
實體語句部分;]
END [ENTITY] [實體名];
其中,GENERIC 是用于說明設(shè)計實體和其外部環(huán)境通信的對象,規(guī)定端口的大小、實體中子元件的數(shù)目、實體的延時特性等。只能用整數(shù)類型表示,如整型、時間型等,其他類型的數(shù)據(jù)不能邏輯綜合。格式如下:
GENERIC ([CONSTANT]屬性名稱:[IN]子類型標(biāo)識[:=靜態(tài)表達(dá)式],……);
PORT 關(guān)鍵字用于定義模塊的端口,它的格式如下:
PORT( [SIGNAL] 端口名稱:[方向]類型標(biāo)識[BUS] [:=靜態(tài)表達(dá)式],
[SIGNAL] 端口名稱:[方向] 類型標(biāo)識[BUS] [:=靜態(tài)表達(dá)式],
…
[SIGNAL] 端口名稱:[方向] 類型標(biāo)識[BUS] [:=靜態(tài)表達(dá)式]);
? SIGNAL:SIGNAL 是關(guān)鍵字,但是由于 PORT 之后必須是信號類,所以一般可以將 SIGNAL關(guān)鍵字省略。
? 端口名稱:是該端口的標(biāo)識,通常由英文字母和數(shù)字組成,但是必須是英文字母打頭。
? 方向:定義了端口是輸入還是輸出,如 IN、OUT。表明端口方向的關(guān)鍵字如表1所示。
? 類型標(biāo)識:說明流過該端口的數(shù)據(jù)類型,常用的數(shù)據(jù)類型有 BIT(位)、BIT_VECTOR(位向量)、BOOLEAN(布爾型)和 INTEGER(整數(shù)型)4 種。
? BUS 關(guān)鍵字:在該端口和多個輸出端相連的情況下使用。
表 1 端口方向關(guān)鍵字說明表
2.2 結(jié)構(gòu)體的描述方法
結(jié)構(gòu)體描述實體的行為功能,一個實體可以有多個結(jié)構(gòu)體。結(jié)構(gòu)體是一個基本設(shè)計單元,它具體地指明了所設(shè)計模塊的行為、元件及內(nèi)部的連接關(guān)系,也就是說它定義了設(shè)計單元具體的功能。結(jié)構(gòu)體對其基本設(shè)計單元的輸入/輸出關(guān)系可以用 3 種方式進(jìn)行描述,即行為描述(基本設(shè)計單元的數(shù)學(xué)模型描述)、寄存器傳輸描述(數(shù)據(jù)流描述)和結(jié)構(gòu)描述(邏輯元件連接描述)。
不同的描述方式只體現(xiàn)在描述語句上,而結(jié)構(gòu)體的結(jié)構(gòu)是完全一樣的。由于結(jié)構(gòu)體是對實體功能的具體描述,因此它一定要跟在實體的后面。通常,先編譯實體之后才能對結(jié)構(gòu)體進(jìn)行編譯。如果實體需要重新編譯,那么相應(yīng)結(jié)構(gòu)體也應(yīng)重新進(jìn)行編譯。
結(jié)構(gòu)體的格式如下:
ARCHITECTURE 結(jié)構(gòu)體名 OF 實體名 IS
[定義語句]
BEGIN
[并行處理語句]
END 結(jié)構(gòu)體名;
定義語句用于對結(jié)構(gòu)體內(nèi)部所使用的信號、常數(shù)、數(shù)據(jù)類型和函數(shù)等進(jìn)行定義。信號定義和端口說明的語句一樣,應(yīng)有信號名和數(shù)據(jù)類型的說明,但因它是內(nèi)部連接用的信號,故沒有也不需有方向的說明。并行處理語句具體地描述了結(jié)構(gòu)體的行為及其連接關(guān)系,它們都是可以并行執(zhí)行的。
以上面介紹的 R-S 觸發(fā)器為例。假設(shè)已經(jīng)有一個實現(xiàn)了與非功能的模塊 nand2,用它實現(xiàn)R-S 觸發(fā)器的原理圖如圖 3 所示。
圖 3 R-S 觸發(fā)器的實現(xiàn)原理圖
對應(yīng)以上原理圖的結(jié)構(gòu)體描述如下:
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY rsff is
PORT (
set, reset: in bit;
q, qb: buffer
);
END ENTITY;
ARCHITECTURE arch_rsff OF rsff IS
COMPONENT nand2
PORT (
a, b : IN BIT;
c: OUT BIT);
??????END?COMPONENT;?????
BEGIN
U1: nand2
PORT MAP (set, qb, q);
U2: nand2
PORT MAP (reset, q, qb);
END arch_rsff;
上面的代碼中,以關(guān)鍵字 ARCHITECTURE 作為結(jié)構(gòu)體的開頭,結(jié)構(gòu)體名為 arch_rsff,表示描述 rsff 實體的結(jié)構(gòu)體 arch_rsff。ARCHITECTURE 和 BEGIN 之間是結(jié)構(gòu)體說明區(qū), BEGIN和 END 之間是結(jié)構(gòu)體語句區(qū)。結(jié)構(gòu)體說明區(qū)描述組件(COMPONENT)和局部信號,結(jié)構(gòu)體語句中用的具體元件(上例是 nand2)均應(yīng)在結(jié)構(gòu)體說明中說明接口,以便將描述的信息通知給編輯器。
如果設(shè)計者希望將模塊分為若干個相對比較獨立的子模塊進(jìn)行描述,可以將一個結(jié)構(gòu)體用幾個子結(jié)構(gòu)來構(gòu)成。VHDL 結(jié)構(gòu)體描述常常用到 3 種語句結(jié)構(gòu):PROCESS 語句結(jié)構(gòu)、BLOCK 語句結(jié)構(gòu)和子程序結(jié)構(gòu)。
1).PROCESS 語句結(jié)構(gòu)
進(jìn)程語句是一種并發(fā)處理語句,在一個結(jié)構(gòu)體中多個 PROCESS 語句可以同時并行運行(相當(dāng)于多個 CPU 同時運作)。PROCESS 語句是 VHDL 語言中描述硬件系統(tǒng)并發(fā)行為的最基本語句。
PROCESS 語句歸納起來有如下幾個特點:
? 它可以與其他進(jìn)程并發(fā)運行,并可存取結(jié)構(gòu)體或?qū)嶓w號中所定義的信號;? 進(jìn)程結(jié)構(gòu)中的所有語句都是按順序執(zhí)行的;
? 為啟動進(jìn)程,在進(jìn)行結(jié)構(gòu)中必須包含一個顯式的敏感信號量表或包含一個 WAIT 語句;
? 進(jìn)程之間的通信是通過信號量傳遞來實現(xiàn)的。
PROCESS 語句的格式如下:
[進(jìn)程名]:PROCESS(信號 1,信號 2,…)
BEGIN
…
END PROCESS;
一般情況下進(jìn)程名可以被省略。進(jìn)程申明關(guān)鍵字 PROCESS 后面括號內(nèi)的信號是此進(jìn)程的敏感信號,這些信號的變化會激活過程的執(zhí)行。例如下面的代碼就表示過程 main_proc 在信號clk 和 reset 變化時執(zhí)行:
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY counter is
PORT (
clk, reset: in bit;
c: out bit
);
END ENTITY;
ARCHITECTURE arch of counter is
BEGIN
main_proc:
PROCESS(clk, reset)
BEGIN
if (reset = '1') then
…
end if;
END PROCESS;
END
在進(jìn)程中也可以定義一些變量,這些變量是局部量,只能在進(jìn)程內(nèi)部使用,它們的賦值是立即生效的。局部變量定義的格式如下:
VARIABLE 變量名:數(shù)據(jù)類型 [約束條件] [:=表達(dá)式];
下面的代碼演示了定義一個局部變量并且使用它的方法:
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY counter is
PORT (
a: in bit;
c: out bit
);
END ENTITY;
ARCHITECTURE arch of counter is
BEGIN
main_proc:
PROCESS(a)
VARIABLE item:array0(7 downto 0); --定義一個變量 item
BEGIN
item(7):=a;
c<=item(7);
END PROCESS;
END
2).BLOCK 語句結(jié)構(gòu)
BLOCK 語句的格式如下:
塊名:BLOCK(條件)
[參數(shù) GENERIC 說明; [參數(shù)映射;] ]
[端口說明; [端口映射;] ]
[塊說明語句]
BEGIN
并發(fā)語句組;
END BLOCK 塊名;
BLOCK 放在結(jié)構(gòu)體的并行語句組中,每一個 BLOCK 相當(dāng)于一個子電路原理圖。和 PROCESS語句不同,BLOCK 內(nèi)的語句是并發(fā)執(zhí)行的。只要 BLOCK 右邊的條件滿足,BLOCK 內(nèi)的語句就被執(zhí)行。如果省略條件,表示本 BLOCK 被無條件執(zhí)行。下面是一個 BLOCK 語句的例子:
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY test is
PORT (
a, b: in bit;
s, c: out bit
?????????);
END ENTITY;
ARCHITECTURE arch of test is
BEGIN
block_demo: BLOCK(clk='1')
BEGIN
s<=a xor b;
c<=a and b;
END BLOCK block_demo;
END;
上面的程序表示當(dāng) clk 信號變?yōu)?1 時,并行執(zhí)行 BLOCK 語句內(nèi)的程序,即將 a 和 b 兩個信號的異或結(jié)果賦給 s 信號,同時將 a 和 b 信號的與結(jié)果賦給 c 信號。
3).子程序結(jié)構(gòu)
所謂子程序結(jié)構(gòu)就是將一部分實現(xiàn)代碼放到公用的程序(即程序包 Package)文件中實現(xiàn)。程序包中的代碼以子程序的方式提供給 VHDL 程序調(diào)用,這樣代碼可以實現(xiàn)共享,同時還使得VHDL 程序的結(jié)構(gòu)明了。
子程序在調(diào)用時首先要進(jìn)行初始化,執(zhí)行結(jié)束后子程序就終止,再調(diào)用時要再進(jìn)行初始化。因此子程序內(nèi)部的值不能保持,子程序返回以后才能被再調(diào)用,它是一個非重入的程序。
VHDL 中有兩種類型的子程序—過程(Procedure)和函數(shù)(Function),下面分別介紹一下它們的格式。
? 過程過程的格式如下:
PROCEDURE 過程名(參數(shù) 1;參數(shù) 2;……) IS
定義語句;
BEGIN
順序語句組;
END 過程名;
每個參數(shù)的說明格式如下:
參數(shù)名:方向 類型
方向一般為 3 種:IN、OUT、INOUT。如果方向為 IN 則可省略方向說明。
? 函數(shù)
函數(shù)的格式如下:
FUNCTION 函數(shù)名(參數(shù) 1;參數(shù) 2;……) RETURN 數(shù)據(jù)類型 IS
定義語句;
BEGIN
順序語句組;
RETURN [返回變量名];
END 函數(shù)名;
在 VHDL 語言中,函數(shù)的所有參數(shù)都是輸入?yún)?shù),因此都是 IN 的方向,可以省略方向說明。
在下面介紹程序包(PACKAGE)的時候?qū)榻B函數(shù)、過程定義的例子,在此不再舉例說明。
2.3 程序包和程序包體
程序包說明類似 C 語言中的 include 語句,用來羅列 VHDL 語言中所要用到的信號定義、常數(shù)定義、數(shù)據(jù)類型、元件語句、函數(shù)定義和過程定義等,它是一個可編譯的設(shè)計單元,也是庫結(jié)構(gòu)中的一個層次。
程序包的結(jié)構(gòu)如圖 4 所示。
圖 4 VHDL 程序包結(jié)構(gòu)圖
一個程序包由兩大部分組成:程序包申明和程序包體。程序包體是一個可選項,也就是說,程序包可以僅僅由程序包標(biāo)題構(gòu)成。一般程序包標(biāo)題列出所有項的名稱,而程序包體具體給出各項的細(xì)節(jié)。
下面介紹一個包含與非函數(shù)的程序包的實現(xiàn)以及調(diào)用方法。實現(xiàn)與非函數(shù)程序包的代碼如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
-- 程序包申明
PACKAGE package_demo is
-- 函數(shù)申明
FUNCTION nand2(a, b : in bit)
RETURN bit;
END package_demo;
-- 程序包體
PACKAGE BODY package_demo is
-- 函數(shù)實現(xiàn)
FUNCTION nand2(a, b : in bit)
RETURN bit IS
VARIABLE ret: bit;
BEGIN
ret = not(a and b);
return ret;
END nand2;
END BODY;
上面的代碼在程序包申明中申明了函數(shù) nand2,然后在程序包體中具體實現(xiàn)了此函數(shù)的功能。下面舉個例子來說明程序包的使用方法,即函數(shù)的調(diào)用方法。假設(shè)要得到如下的邏輯關(guān)系式:
可以用下面的代碼描述:
library IEEE;
use IEEE.std_logic_1164.all;
use WORK.package_demo.all; -- 調(diào)用自定義的程序包
ENTITY test is
PORT (
A1, B1, A2, B2: in bit;
D: out bit
);
END ENTITY;
ARCHITECTURE arch of test is
BEGIN
-- 調(diào)用 nand 函數(shù)
D = nand2(A1, B1) and nand2(A2, B2);
END;
自定義的程序包必須首先進(jìn)行編譯,然后才能夠編譯調(diào)用此程序包的 VHDL 程序。自定義的程序包屬于 WORK 庫,所以申明調(diào)用的代碼是:
use WORK.自定義程序包名稱.all;
調(diào)用程序包中函數(shù)或者過程的方法和一般高級語言(如 C 語言)一樣直接調(diào)用就可以了。
2.4 配置的申明方法
一個實體可以包含多個結(jié)構(gòu)體,配置的作用就是根據(jù)需要選擇實體的結(jié)構(gòu)體。配置語句描述層與層之間的連接關(guān)系以及實體與結(jié)構(gòu)之間的連接關(guān)系。設(shè)計者可以利用這種配置語句來選擇不同的結(jié)構(gòu)體,使其與要設(shè)計的實體相對應(yīng)。在仿真某一個實體時,可以利用配置來選擇不同的結(jié)構(gòu)體,進(jìn)行性能對比試驗以得到性能最佳的結(jié)構(gòu)體。
例如,設(shè)計一個二輸入、四輸出的譯碼器。如果一種結(jié)構(gòu)中的基本單元采用反相器和三輸入與門,而另一種結(jié)構(gòu)中的基本元件都采用與非門。它們各自的結(jié)構(gòu)體是不一樣的,并且都放在各自不同的庫中。那么現(xiàn)在要設(shè)計的譯碼器,就可以利用配置語句實現(xiàn)對兩種不同構(gòu)造的選擇。
配置的基本格式如下:
CONFIGURATION 配置名 OF 實體名 IS
[語句說明]
END 配置名;
如果一個實體僅僅具有一個結(jié)構(gòu)體,也需要定義其配置,但是可以寫成一種最為簡潔的格式:
CONFIGURATION 配置名 OF 實體名 IS
FOR 所選的構(gòu)造體名
END FOR;
END 配置名;
如果一個模塊比較復(fù)雜,含有多個子模塊,使用低層次配置可以為每個子模塊選擇其結(jié)構(gòu)體,代碼如下:
CONFIGURATION 配置名 OF 實體名 IS
FOR 所選的構(gòu)造體名
FOR 標(biāo)號 1:元件名 1 USE CONFIGURATION WORK.配置體名 1;
END FOR;
FOR 標(biāo)號 2:元件名 2 USE ENTITY WORK.實體名 2(構(gòu)造體名 2);
END FOR;
…
END FOR;
END 配置名;
其中,低層次構(gòu)造體名可用 ALL 或 OTHERS,構(gòu)造體名 2 可以省略。
2.5 VHDL 程序的庫
庫(Library)是經(jīng)編譯后的數(shù)據(jù)的集合,它存放包集合申明、實體申明、構(gòu)造體申明和配置定義。它的功能類似于 UNIX 和 MS-DOS 操作系統(tǒng)中的目錄,在 VHDL 中,庫的說明總是放在設(shè)計單元的最前面,這樣在設(shè)計單元內(nèi)的語句就可以使用庫中的數(shù)據(jù)了。由此可見,使用庫的好處是使設(shè)計者可以共享已經(jīng)編譯過的設(shè)計結(jié)果。在 VHDL 中可以存在多個不同的庫,但是庫和庫之間是獨立的,不能互相嵌套。
申明庫的格式如下:
LIBRARY 庫名;
在 VHDL 語言中存在的庫大致可以歸納為 5 種:IEEE 庫、STD 庫、ASIC 矢量庫、用戶定義庫和 WORK 庫。
1).IEEE 庫
在 IEEE 庫中的“STD_LOGIC_1164”包集合是 IEEE 正式認(rèn)可的標(biāo)準(zhǔn)包集合?,F(xiàn)在有些公司提供的包集合如“STD_LOGIC_ARITH”、“STD_LOGIC_UNSIGNED”等,盡管沒有得到 IEEE 的承認(rèn),但是仍匯集在 IEEE 庫中。
2).STD 庫
STD 庫是 VHDL 的標(biāo)準(zhǔn)庫,在庫中存放有“STANDARD”包集合。由于它是 VHDL 的標(biāo)準(zhǔn)配置,因此設(shè)計者如要調(diào)用“STANDARD”中的數(shù)據(jù)可以不按標(biāo)準(zhǔn)格式說明。STD 庫中還包含有“TEXTIO”包集合,在測試時使用。使用“TEXTIO”包集合中的數(shù)據(jù)時,應(yīng)先說明庫和包集合名:
LIBRARY STD;
USE STD.TEXTIO.ALL;
3).ASIC 矢量庫
在 VHDL 中,為了進(jìn)行門級仿真,各公司可提供面向 ASIC 的邏輯門庫。在該庫中存放著與邏輯門一一對應(yīng)的實體。
4).WORK 庫
WORK 庫是現(xiàn)行作業(yè)庫。設(shè)計者所描述的 VHDL 語句不需要任何說明,都將存放在 WORK 庫中。在使用該庫時無需進(jìn)行任何說明。
5).用戶定義庫
將用戶自身設(shè)計開發(fā)的包、實體等匯集在一起定義成一個庫,就是用戶定義庫或稱用戶庫。在使用用戶定義庫時同樣要首先說明庫名。
以上各種庫中,除 WORK 庫外,其他 4 類庫在使用前都首先要進(jìn)行說明,格式為:
USE 庫名.包集合名.項目名;
如果項目名為 ALL,則表示包集合中的所有項目都要使用,例如:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.ALL;
USE WORK.STD_ARITH.ALL;
…
庫說明語句的作用范圍從一個實體說明開始到它所屬的構(gòu)造體、配置結(jié)束為止。當(dāng)一個源程序出現(xiàn)兩個或兩個以上的實體時,兩條作為使用庫的說明語句就在每個實體說明語句前重復(fù)書寫。例如,在一個 VHDL 文件中定義兩個實體,庫的申明如下:
-- 第一個實體的庫申明
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1644.ALL;
-- 第一個實體申明
ENTITY ent1 is
…
END ent1;
-- 第一個實體的結(jié)構(gòu)體
ARCHITECTURE arch1 of ent1 is
…
END arch1;
-- 第一個實體的配置
CONFIGURATION cfg1 of ent1 is
…
END cfg1;
-- 第二個實體的庫申明
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1644.ALL;
-- 第二個實體申明
ENTITY ent2 is
…
END ent2;
-- 第二個實體的結(jié)構(gòu)體
ARCHITECTURE arch2 of ent2 is
三、VHDL 語言的數(shù)據(jù)類型和運算符
VHDL 和其他高級語言一樣,具有多種數(shù)據(jù)類型。對大多數(shù)數(shù)據(jù)類型的定義兩者是一致的(例如整數(shù)型),但是也有一些數(shù)據(jù)類型是 VHDL 所獨有的。表 2 所示為 VHDL 支持的數(shù)據(jù)類型和它的數(shù)據(jù)對象。
表 2 VHDL 數(shù)據(jù)類型和數(shù)據(jù)對象表
注意:表?2 中帶*號的數(shù)據(jù)類型表示不可以綜合的類型或?qū)ο蟆?/p>
3.1 VHDL 語言的數(shù)據(jù)對象
VHDL 對象有 4 種,即信號(Signal)、變量(Variable)、常量(Constant)和文件(File)。
其中文件(File)是 VHDL’93 標(biāo)準(zhǔn)中新通過的,它是不可以綜合的。下面介紹一下常量、信號和變量的申明方法。
1).信號(Signal)
信號用于將元件的裝配端口連在一起形成模塊,它的作用相當(dāng)于連接元件的導(dǎo)線。信號是實體間動態(tài)數(shù)據(jù)交換的手段,信號申明格式如下:
SIGNAL signal_name : signal_type [ :=initial_value ] ;
在關(guān)鍵字 SIGNAL 后跟一個或者多個信號名,每個信號名將建立一個新信號,用冒號把信號名和信號的數(shù)據(jù)類型分隔開,信號數(shù)據(jù)類型規(guī)定信號包含的數(shù)據(jù)類型信息及初始化信號指定的初值。
實體說明部分、結(jié)構(gòu)體說明和程序包說明都能聲明信號,全局信號在程序包中聲明,它們被所屬的實體分享。
2).變量(Variable)
變量用于存儲進(jìn)程和子程序中的局部數(shù)據(jù),變量的賦值是立即執(zhí)行的,沒有延時。變量的申明格式如下:
VARIABLE variable_name ,variable_name : variable_type[:= value];
關(guān)鍵字 VARIABLE 后跟著一個或多個變量名,每個變量名對應(yīng)建立一個新變量。variable_type 字段定義了變量的數(shù)據(jù)類型,并且還可以指定一個可選的初值。此外,還需要注意的是只可以在進(jìn)程說明部分和子程序說明部分聲明變量。
和信號相比,變量有以下優(yōu)點:
? 變量處理起來更快,因為變量賦值是立即發(fā)生的,而信號卻必須為此事件作相應(yīng)的處理。
? 變量用很少的存儲器,相反為了做一個調(diào)度安排和處理信號屬性,需要存儲更多的信號信息。
? 變量比信號更容易實現(xiàn)同步處理。
3).常量
常量是為特定的數(shù)據(jù)類型值所賦予的名稱,如果需要在多個具體元件中存放一個固定值就使用常量。例如可以如下定義常量 PI(π ):
CONSTANT PI: REAL:= 3.1416;
定義常量的格式如下:
CONSTANT constant_name,constant_name: type_name[:= value];
一般情況下,VHDL 中的常量是在程序包申明中進(jìn)行申明,而在程序包體中指定具體的值。使用常量需要注意以下幾個問題:
? 在程序包中說明的常量被全局化。
? 在實體說明部分的常量被那個實體中任何結(jié)構(gòu)體引用。
? 在結(jié)構(gòu)體中的常量能被其結(jié)構(gòu)體內(nèi)部任何語句采用,包括為進(jìn)程語句采用。
? 在進(jìn)程說明中說明的常量只能在進(jìn)程中使用。
? 在數(shù)組和一些線性運算中經(jīng)常用常量表,VHDL 的設(shè)計描述用常量表特別適于實現(xiàn) ROM 網(wǎng)絡(luò)的電路與函數(shù)設(shè)計。
3.2 VHDL 語言的數(shù)據(jù)類型
VHDL 的數(shù)據(jù)類型根據(jù)使用目的和場合,可以分為標(biāo)準(zhǔn)數(shù)據(jù)類型和用戶定義的數(shù)據(jù)類型兩種。
1).標(biāo)準(zhǔn)數(shù)據(jù)類型
VHDL 中定義的標(biāo)準(zhǔn)數(shù)據(jù)類型如表 3 所示。
表 3 VHDL 中的標(biāo)準(zhǔn)數(shù)據(jù)類型
其中,在數(shù)據(jù)類型后面,可以加上約束區(qū)間,比如:
INTEGER RANGE 100 downto 1;
BIT_VECTOR(3 downto 1) real range 2.0 to 30.0;
STD_LOGIC 和 STD_LOGIC_VECTOR 的邏輯數(shù)據(jù)取值可以有 9 種狀態(tài),如表 4 所示。
表 4 標(biāo)準(zhǔn)邏輯(向量)取值表
2).用戶定義的數(shù)據(jù)類型
用戶定義數(shù)據(jù)類型的格式如下:
TYPE 數(shù)據(jù)類型名 {,數(shù)據(jù)類型名} 數(shù)據(jù)類型定義;
數(shù)據(jù)類型定義放在語句的定義部分中,定義范圍為從本定義行開始到本語句作用的最后。
一般用戶定義的數(shù)據(jù)類型分為以下幾種。
? 枚舉類型(enumeration)
枚舉類型的格式如下:
TYPE 數(shù)據(jù)類型名 IS (元素,元素,……)
例如,將一星期七天作為一個枚舉,可以如下定義:
TYPE week IS (sun, mon, tue, wed, thu, fri, sat);
在枚舉類型中,元素是有序列性的,第 1 個元素對應(yīng)邏輯電路狀態(tài) 000,第 2 個為狀態(tài) 001,第 3 個為狀態(tài) 010……后一個邏輯狀態(tài)為前一個元素邏輯狀態(tài)加 1。所以,上面的例子中,sun對應(yīng)邏輯狀態(tài) 000,mon 對應(yīng)邏輯狀態(tài) 001,……,sat 對應(yīng)邏輯狀態(tài) 110。
? 整數(shù)類型、實數(shù)類型(INTEGER,REAL)
這里的整數(shù)類型和實數(shù)類型其實是前面所述的標(biāo)準(zhǔn)整數(shù)類型和實數(shù)類型的子類,定義的格式如下:
TYPE 數(shù)據(jù)類型名 IS 數(shù)據(jù)類型定義 約束范圍
例如:
TYPE current IS REAL RANGE -1E4 TO 1E4
定義了 current 類型實數(shù)的范圍是-104到 104。
? 數(shù)組(ARRAY)
數(shù)組定義的格式如下:
TYPE 數(shù)據(jù)類型名 IS ARRAY 范圍 OF 原數(shù)據(jù)類型名;
注意:如果 范圍 這一項沒有被指定,則使用整數(shù)數(shù)據(jù)類型。
下面通過例子說明數(shù)組的定義方法。
TYPE word IS ARRAY (1 TO 8) OF STD_LOGIC;
TYPE tmem IS ARRAY (0 TO 2, 3 DOWNTO 0) OF STD_LOGIC;
以上定義了 tmem 一種數(shù)組類型,可以定義一個此類新的常數(shù),如下:
CONSTANT mem:tmem:= ( ('0', '0', '0', '0'),
('0', '0', '1', '0'),
('1', '1', '0', '0'));
當(dāng)范圍這一項需用整數(shù)類型以外的其他數(shù)據(jù)類型時(如枚舉類型),則應(yīng)在指定數(shù)據(jù)范圍前加數(shù)據(jù)類型名。例如:
TYPE week IS (sun, mon, tue, wed, thu, fri, sat);
TYPE workdate IS ARRAY (week mon TO fri) OF STD_LOGIC;
如果要取得數(shù)組內(nèi)的一個元素,格式如下:
數(shù)組名(下標(biāo))
例如,word(1)區(qū)的 word 數(shù)組序號為 1 的元素。
當(dāng)數(shù)組類型定義中的范圍用“(Natural Range <>)”或“(Positive Range <>)”代替時,表示本數(shù)組類型為非限定的類型,下標(biāo)范圍在信號或變量定義時再具體指定。
例如下面的代碼中定義的 array0 就是非限定類型的數(shù)組。
library IEEE;
use IEEE.std_logic_1164.all;
entity tmyarray is
port(a:in std_logic;c:out std_logic);
end ;
architecture myarray of tmyarray is
type array0 is array (natural range <>) of std_logic;
begin
process(a)
variable item:array0(7 downto 0);--定義一個變量 item
begin
item(7):=a;
c<=item(7);
end process;
end;
??時間(TIME)
定義時間的格式如下:
TYPE 數(shù)據(jù)類型名 IS 范圍
UNITS 基本單位;
單位描述;
END UNITS
例如:
TYPE 數(shù)據(jù)類型名 IS 范圍
UNITS 基本單位;
單位描述;
END UNITS
TYPE time IS RANGE -1E18 TO 1E18
UNITS fs;
ps=1000fs;
ns=1000ps;
us=1000ns;
ms=1000us;
sec=1000ms;
min=60sec;
hr=60min;
END UNITS;
? 記錄(Record)
記錄的定義格式是:
TYPE 數(shù)據(jù)類型名 IS RECORD
元素名:數(shù)據(jù)類型名;
元素名:數(shù)據(jù)類型名;
…
元素名:數(shù)據(jù)類型名;
END RECORD;
注意:引用記錄數(shù)據(jù)類型中的元素應(yīng)使用“.”,而不是數(shù)組的括號。
例如,定義一個窗口尺寸的記錄,如下:
TYPE window IS RECORD
length:INTEGER;
width:INTEGER;
END RECORD;
當(dāng)需要使用 window 類型記錄的元素時,方法如下:
signal win: window;
win.length<=10;
? 用戶定義的子類型
用戶定義的子類型是用戶對已定義的數(shù)據(jù)類型做一些范圍限制而形成的一種數(shù)據(jù)類型。子類型的名稱通常采用用戶較容易理解的名字。子類型的定義格式為:
SUBTYPE 子類型名 IS 數(shù)據(jù)類型名[范圍];
例如:
SUBTYPE digit IS INTEGER RANGE 0 TO 9;
SUBTYPE abus IS STD_LOGIC_VECTOR(7 DOWNTO 0);
signal a: STD_LOGIC_VECTOR (7 downto 0);
signal b: STD_LOGIC_VECTOR (15 downto 0);
signal c: abus;
a<=c; --正確
b<=c; --錯誤
在 VHDL 中,數(shù)據(jù)類型的定義是相當(dāng)嚴(yán)格的,不同類型的數(shù)據(jù)是不能進(jìn)行運算和直接代入的。為了實現(xiàn)正確的代入操作,必須將要代入的數(shù)據(jù)進(jìn)行類型變換。
變 換 函 數(shù) 通 常 由 VHDL 語 言 的 包 集 合 提 供 。 例 如 在 “ STD_LOGIC_1164 ”、“STD_LOGIC_ARITH”、STD_LOGIC_UNSIGNED”的包集合中提供了如表 2-5 所示的數(shù)據(jù)類型變換函數(shù)。
表 5 類型變換函數(shù)表
有些數(shù)據(jù),從數(shù)據(jù)本身是斷定不出其類型的,如“01010001”,如果沒有上下文,VHDL 編譯器就無法知道它是字串型還是位數(shù)組類型。這時就要進(jìn)行數(shù)據(jù)類型的限定。類型限定的格式如下:
類型名'(數(shù)據(jù))
例如:
a<=std_logic_vector'("01010001");
這樣,編譯器知道“01010001”肯定是矢量型,而不是別的類型。
3.3 VHDL 語言的運算符
在 VHDL 語言中,常用的運算符有邏輯運算(Logic)、關(guān)系運算(Relational)、算術(shù)運算(Arithmetic)和移位運算(Shift),下面分別對它們進(jìn)行介紹。
1).邏輯運算符
邏輯運算符可以對 bit 和 boolean 類型的值進(jìn)行運算,也可對這些類型的一維數(shù)組進(jìn)行運算。對數(shù)組型的運算,運算施加于數(shù)組中的每個元素,結(jié)果與原來數(shù)組長度相同。
邏輯判斷的運算為“短路運算”,也就是說,條件表達(dá)式的左邊成立時,就不再進(jìn)行右邊的判斷。比如,IF (a=0) AND (b/a>2) THEN…這個判斷運算,當(dāng) a=0 時,后面的判斷不再繼續(xù),避免出現(xiàn)除數(shù)為 0 的運算。
VHDL 的邏輯運算符如表 6 所示。
表 6 VHDL 邏輯運算符
2).關(guān)系運算符
關(guān)系運算符兩邊必須為相同的類型,其結(jié)果為 boolean 類型。
等號(=)和不等號(/=)兩邊可以為任意類型的運算對象。其他關(guān)系運算符的運算對象必須為標(biāo)量類型或離散類型的一維數(shù)組。對于復(fù)雜的運算對象,如數(shù)組,兩個值相等意味著兩個值的所有對應(yīng)元素相等。VHDL 的關(guān)系運算符如表 7 所示。
表 7 VHDL 關(guān)系運算符
3).算術(shù)運算符
算術(shù)運算符包括一些基本的算術(shù)運算,使用算術(shù)運算符需要注意的是乘方(**)運算的右邊必須為整數(shù)。VHDL 的算術(shù)運算符如表 8 所示。
表 8 VHDL 算術(shù)運算符
4).移位運算符
移位運算符為二元運算符,左邊必須為一維數(shù)組,且元素類型為 bit 或 boolean 類型。右邊運算數(shù)為整數(shù),可以為負(fù)數(shù),相當(dāng)于反方向移位。一位移位與循環(huán)移位的語義示意如圖 5 所示。
圖 5 一位移位與循環(huán)移位示意圖
VHDL 的移位運算符如表 9 所示。
表 9 VHDL 移位運算符
除了上面介紹的,VHDL 中運算符還包括正號“+”、負(fù)號“-” 以及“&”。其中,連接符號(&)用于一維數(shù)組,這個數(shù)組的元素個數(shù)可以為 1,運算結(jié)果為右邊數(shù)組連接在左邊數(shù)組之后形成新數(shù)組,例如:
sel <= a & b;
假設(shè) a 信號為“0”,b 信號為“1”,那么得到的 sel 信號就是“01”。
所有的 VHDL 運算符之間都有優(yōu)先級的關(guān)系,各運算符優(yōu)先級從最高到最低,順序如表 10 所示(同一行優(yōu)先級相同)。
表 10 運算符的優(yōu)先順序
四、 VHDL 語言的描述語句
使用 VHDL 進(jìn)行數(shù)字電路描述時候,如果按照執(zhí)行順序?qū)?VHDL 的程序進(jìn)行分類,可以分為順序(sequential)描述語句和并行(concurrent)描述語句。順序語句描述的程序總是按照程序書寫的順序執(zhí)行;而并行語句都是同時執(zhí)行的,和程序的書寫順序無關(guān)。
4.1 VHDL 順序語句描述方法
VHDL 中的順序語句一般在進(jìn)程中出現(xiàn),或者以函數(shù)、過程的方式在進(jìn)程中被調(diào)用。順序語句所涉及到的系統(tǒng)行為有時序流、控制、條件和迭代等。
VHDL 中的順序語句有 WAIT 語句、斷言語句、IF 語句、CASE 語句、LOOP 語句、NEXT 語句、過程調(diào)用語句和 NULL 語句,下面就對它們進(jìn)行詳細(xì)介紹。
1).WAIT 語句
WAIT 語句允許把一個順序執(zhí)行的進(jìn)程或子程序掛起,掛起的進(jìn)程或子程序恢復(fù)的條件由 3種不同的方法指定。WAIT 語句可以有不同的格式,分別有不同的作用,例如 WAIT ON 表示等待到信號變化,WAIT UNTIL 表示等到一個表達(dá)式為真,而 WAIT FOR 表示等待一個固定的事件,如果僅僅寫一個 WAIT 的話就表示無限期的等待。
WAIT 語句能用于多種不同的目的,常用于為綜合工具指定時鐘輸入。另一用途是將進(jìn)程的執(zhí)行延時一段時間或者是為了動態(tài)地修改進(jìn)程敏感表。
為了避免無休止的等待可以加一個超時付句,不管進(jìn)行到哪兒或是條件有沒有滿足都允許執(zhí)行超時處理。下面的代碼就演示了 WAIT UNTIL 語句的使用方法和超時處理的方法:
WAIT UNTIL (sendB = '1') FOR 1 ns;
ASSERT (sendB = '1')
REPORT "sendB timed out at '1'"
SEVERITY ERROR;
2).?dāng)嘌哉Z句
斷言語句的功能是為設(shè)計者報告一個文本字符串。斷言語句包含一個布爾表達(dá)式,表達(dá)式為真,該語句不做任何事;反之,它將輸出一用戶規(guī)定的字符串到標(biāo)準(zhǔn)輸出終端。
斷言語句規(guī)定輸出字符串的嚴(yán)重程度為 4 個級別(NOTE、WARNING、ERROR 和 FAILURE),它們的意思分別是注意、警告、錯誤和失敗,嚴(yán)重層次遞增。
斷言語句的格式如下:
ASSERT_STATEMENT ::=
ASSERT CONDITION
[REPORT EXPRESSION]
[SEVERITY EXPRESSION];
其中,關(guān)鍵字 ASSERT 后跟 CONDITION 布爾值表達(dá)式,它的條件決定 REPORT 付句規(guī)定的文字表達(dá)式輸出不輸出,如果是假,文字表達(dá)式輸出,如果是真,該文字表達(dá)式不輸出。
此外還有兩個可選的付句,REPORT 付句允許設(shè)計者指定輸出文字表達(dá)式的值,如果不指定 REPORT 語句,默認(rèn)值是 ASSERTION VIOLATION,SEVERITY 付句允許設(shè)計者指定斷言語句的嚴(yán)重級別,如果沒指定 SEVERITY 付句,其默認(rèn)值是 ERROR。
下面是一個斷言語句的使用實例,它表示對輸入時鐘進(jìn)行檢查,如果其建立時間小于20ns,則輸出 ERROR 信號:
PROCESS (clk,din)
VARIABLE last_d_change :TIME := 0 ns;
VARIABLE last_d_value :std_logic := 'X';
VARIABLE last_clk_value :std_logic := 'X';
BEGIN
IF (last_d_value /= din) THEN -- /= is not equal
last_d_change := NOW;
last_d_value := din;
END IF;
IF (last_clk_value /= clk) THEN
last_clk_value := clk;
IF (clk = '1') THEN
-- 斷言語句
ASSERT (NOW - last_d_change >= 20 ns)
REPORT "setup violation"
SEVERITY WARNING;
END IF;
END IF;
END PROCESS;
3).IF 語句
IF 語句是根據(jù)所指定的條件來確定執(zhí)行哪些語句,其格式如下:
IF condition THEN
sequence_of_statements
ELSIF condition THEN
sequence_of_statements
ELSE
sequence_of_statement
END IF;
IF 語句用關(guān)鍵字 IF 開頭和用關(guān)鍵字 END IF 結(jié)尾,END IF 分開拼寫。有兩個可選付句(ELSIF付句和 ELSE 付句),ELSIF 付句可重復(fù)并允許有多個 ELSIF 付句,可選 ELSE 付句但只允許有一個 ELSE 付句。付句中的條件是一布爾表達(dá)式,如條件為真值,則下一語句被執(zhí)行;如果條件不為真,那么接著執(zhí)行跟在 ELSE 付句后的順序語句。
下面舉一個 IF 語句的使用例子,如下:
IF (day = sunday) THEN
weekend := TRUE;
ELSIF (day = saturday) THEN
weekend := TRUE;
ELSE
weekday := TRUE;
END IF;
以上代碼的意義如下:有兩個變量 weekend 和 weekday,每當(dāng) day 等于 saturday 或 sunday時變量 weekend 變?yōu)檎妫瑘?zhí)行跟著的下一句并控制轉(zhuǎn)到跟在 END IF 之后的語句,否則轉(zhuǎn)到 ELSIF語句部分并檢查 day 是否為 Saturday;當(dāng)變量 day 等于 saturday,執(zhí)行跟著的下一句并再次控制轉(zhuǎn)到跟在 END IF 之后的語句;若 day 并不等于 sunday 或 saturday,執(zhí)行 ELSE 語句部分。
4).CASE 語句
當(dāng)單個表達(dá)式的值在多個起作用的項中選擇時用 CASE 語句。CASE 語句的格式如下:
CASE expression IS
WHEN choice1 =>
sequence_of_statements
WHEN choice2 | choice3 =>
sequence_of_statements
…
WHEN OTHERS =>
sequence_of_statements
END CASE;
下面是一個使用 CASE 語句執(zhí)行處理器指令的例子:
CASE instruction IS
WHEN load_accum =>
accum <= data;
WHEN store_out =>
data_out <= accum;
WHEN load|store =>
process_IO(addr);
WHEN OTHERS =>
process_error(instruction);
END CASE
?5).循環(huán)語句
當(dāng)需要重復(fù)操作時用循環(huán)語句,或者實現(xiàn)的模塊需要很強(qiáng)的迭代能力時用循環(huán)語句:
[循環(huán)標(biāo)示 :] [循環(huán)條件] LOOP
順序處理語句
END LOOP[LOOP_label];
其中循環(huán)條件可以用 WHILE 語句或者 FOR 語句來描述。WHLIE 語句有一個循環(huán)控制的條件 condition,只要條件表達(dá)式為真,WHILE 循環(huán)語句就一直執(zhí)行下去,除非要退出循環(huán)。例如:
WHILE (day = weekday) LOOP
day := get_next_day(day);
END LOOP
FOR 循環(huán)是根據(jù)預(yù)先的設(shè)定進(jìn)行迭代,所指定的范圍并不一定必須為整數(shù)值,也可以表示成一個子類型的指示或者一個范圍語句,例如:
PROCESS (clk)
TYPE day_of_week IS (sun,mon,tue,wed,thur,fri,sat);
BEGIN
FOR i IN day_of_week LOOP
IF i = sat THEN
son <= mow_lawn;
ELSEIF i = sun THEN
church <= family;
ELSE
dad <= go_to_work;
END IF;
END LOOP;
END PROCESS;
FOR LOOP 語句的指數(shù)值(i)由 FOR 語句局部地說明,這和進(jìn)程、函數(shù)和過程中變量 I 不是一會事,它不需要顯式地說明,由于 FOR LOOP 語句的虛擬性,循環(huán)指數(shù)要局部說明之。這樣在進(jìn)程、函數(shù)或過程中存在同名變量時,它們會被分別處理并由它們的內(nèi)含尋址。
此外,關(guān)于循環(huán)需要特別注意的是,在某些編程語言中循環(huán)指數(shù)的值可由賦予內(nèi)部循環(huán)值來改變,但是 VHDL 中是不允許對循環(huán)指數(shù)的任何賦值,這排除了在任何函數(shù)返回值中或在過程的輸出與雙向參量中存在循環(huán)指數(shù)。
6).NEXT 語句
如果必須在這次迭代或循環(huán)中停下正在執(zhí)行的語句,而轉(zhuǎn)向下一個迭代時,用 NEXT 語句。執(zhí)行 NEXT 語句時,模塊處理停在當(dāng)前點并轉(zhuǎn)到循環(huán)語句的開始。隨著循環(huán)的第一個語句執(zhí)行,循環(huán)變量增加一個迭代值,直到迭代的限制值,循環(huán)停止。
下面是一個 NEXT 語句使用的例子:
PROCESS(A,B)
CONSTANT max_limit :INTEGER := 255;
TYPE d_type IS ARRAY (0 to max_limit) OF BOOLEAN ;
VARIABLE done : d_type;
BEGIN
FOR i IN 0 TO max_limit LOOP
IF (done(i) = TRUE ) THEN
NEXT;
ELSE
done (i) := TRUE;
END IF;
q(i) <= a(i) AND b(i);
END LOOP;
END PROCESS;
7).EXIT 語句
EXIT 語句提供完全停下循環(huán)執(zhí)行的能力。執(zhí)行期間發(fā)生了明顯的錯誤或者所有的進(jìn)程已執(zhí)行完畢就跳出循環(huán),EXIT 語句允許退出或跳出循環(huán)語句。執(zhí)行 EXIT 語句后 EXIT 語句后面的語句暫停執(zhí)行,去執(zhí)行循環(huán)語句后面的語句。
EXIT 語句的基本書寫格式如下:
EXIT [循環(huán)標(biāo)號][WHEN 條件]
循環(huán)標(biāo)號一般在多重循環(huán)中用于標(biāo)明循環(huán)層次,如果 EXIT 語句后面添加循環(huán)標(biāo)號,它將會退出循環(huán)標(biāo)號指定的循環(huán)?!癢HEN 條件”項用于表明 EXIT 語句執(zhí)行的條件,此條件為真時才推出循環(huán)。
EXIT 語句的使用實例如下:
PROCESS (a)
BEGIN
first_loop:FOR i IN 0 TO 100 LOOP
second_loop:FOR j IN 1 TO 10 LOOP
......
EXIT second_loop;
......
EXIT first_loop;
END LOOP;
END LOOP;
END PROCESS;
4.2 VHDL 并行語句描述方法
VHDL 不僅僅提供了一系列的順序語句,同樣也提供了很多并行語句。在 VHDL 中,并行語句主要包括以下幾種:
? 進(jìn)程(PROCESS)語句;
? 塊(BLOCK)語句;
? 并發(fā)信號賦值;
? 條件信號賦值;
? 選擇信號賦值。
其中進(jìn)程語句和塊語句已經(jīng)在結(jié)構(gòu)體的描述方法中介紹過了,在此不再累贅,后面主要介紹余下的 3 種并行語句。
1).并發(fā)信號賦值
信號賦值就是使用信號賦值操作符“<=”修改一個信號的狀態(tài),如果此語句是在一個進(jìn)程中,那么它是一個順序語句,反之如果它是在進(jìn)程外面(和進(jìn)程并列關(guān)系),那么它就是一個并行賦值的語句。
下面是一個信號賦值的例子,其中 c1、c2 是順序賦值的,c2 在 c1 之后賦值;d1 和 d2是并行賦值的,它們同時被賦值:
ARCHITECTURE arch of demo is
BEGIN
-- 并行賦值
d1 <= din
d2 <= din
-- 進(jìn)程
PROCESS(din)
BEGIN
-- 順序賦值
c1 <= din
c2 <= din
END PROCESS;
END arch;
2).條件信號賦值
條件信號賦值的格式如下:
目的信號 <= 表達(dá)式 1 WHEN 條件 1 ELSE
表達(dá)式 2 WHEN 條件 2 ELSE
表達(dá)式 3 WHEN 條件 3 ELSE
…
表達(dá)式 n;
最后一個表達(dá)式 n 表示以上 n-1 個條件都不滿足時自動選用此表達(dá)式,如果有條件滿足,則條件對應(yīng)的表達(dá)式會計算賦值給目的信號量。條件信號代入語句也是并發(fā)描述語句,它可以根據(jù)不同條件將不同的多個表達(dá)式之一的值代入信號量。
下面通過一個四選一選擇器的實現(xiàn)方法來介紹條件信號代入語句的使用方法:
ENTITY mux4 IS
PORT (
din0, din1, din2, din3,sel0,sel1: in bit;
dout: out bit );
END mux4;
ARCHITECTURE arch of mux4 is
SIGNAL sel : bit_vector(1 downto 0);
BEGIN
sel <= sel1 & sel0;
dout <= din0 WHEN sel = “00” ELSE
din1 WHEN sel = “01” ELSE
din2 WHEN sel = “10” ELSE
din3 WHEN sel = “11” ELSE
‘X’;
END mux4;
3).選擇信號賦值
選擇信號賦值類似于 CASE 語句,它的格式如下:
WITH 表達(dá)式 SELECT
目的信號量 <= 表達(dá)式 1 WHEN 條件 1;
表達(dá)式 2 WHEN 條件 2;
表達(dá)式 3 WHEN 條件 3;
…
表達(dá)式 n WHEN 條件 n;
如果使用選擇信號賦值實現(xiàn)上面的四選一選擇器,代碼如下:
ENTITY mux4 IS
PORT (
din0, din1, din2, din3,sel0,sel1: in bit;
dout: out bit );
END mux4;
ARCHITECTURE arch of mux4 is
SIGNAL sel : bit_vector(1 downto 0);
BEGIN
sel <= sel1 & sel0;
WITH sel SELECT
dout <= din1 when “00”,
dout <= din1 when “01”,
dout <= din2 when “10”,
dout <= din3 when “1”,
‘X” WHEN OTHERS;
END mux4;
五、 VHDL 語言的預(yù)定義屬性
在 VHDL 中,屬性是指關(guān)于設(shè)計實體、結(jié)構(gòu)體、類型、信號等項目的制定特征,利用屬性可以使得 VHDL 代碼更加簡明扼要、易于理解。
VHDL 提供了下面 5 類預(yù)定義屬性:值類屬性、函數(shù)類屬性、信號類屬性、數(shù)據(jù)類型類屬性和數(shù)據(jù)范圍類屬性。
5.1 值類預(yù)定義屬性
值類屬性返回有關(guān)數(shù)組類型、塊和常用數(shù)據(jù)類型的特定值,值類屬性還用于返回數(shù)組的長度或者類型的最低邊界,值類屬性分成 3 個子類。
1).值類型屬性:返回類型的邊界
值類型屬性用來返回類型的邊界,有 4 種預(yù)定義屬性:
? T'LEFT 用于返回類型或者子類型的左邊界;
? T'RIGHT 用于返回類型或者子類型的右邊界;
? T'High 用于返回類型或者子類型的上限值;
? T'Low 用于返回類型或者子類型的下限值。
用字符“'”指定屬性并后跟屬性名,“'”前的對象是所附屬性的對象,字首大寫“T”指所附屬性的對象是類型(TYPE),“'”字符標(biāo)點符號(tick)是 VHDL 特有的標(biāo)號。
2).值類數(shù)組屬性:返回數(shù)組長度
值類數(shù)組屬性只有一個,即 LENGTH,該屬性返回指定數(shù)組范圍的總長度,它用于帶某種標(biāo)量類型的數(shù)組范圍和帶標(biāo)量類型范圍的多維數(shù)組。
3).值類塊屬性:返回塊的信息
用屬性'STRUCTURE 和'BEHAVIOR 返回有關(guān)在塊和結(jié)構(gòu)體中塊是如何建模的信息。在塊和結(jié)構(gòu)體中如不含元件具體裝配語句,則屬性'BEHAVIOR 將返回真值,如果塊或者結(jié)構(gòu)體中只含元件具體裝配語句或被動進(jìn)程,則屬性'STRUCTUTE 將返回真值。
5.2 函數(shù)類預(yù)定義屬性
函數(shù)類屬性為設(shè)計者返回類型、數(shù)組和信號信息。用函數(shù)類屬性時,函數(shù)調(diào)用由輸入變元的值返回一個值,返回值為可枚舉值的位置號碼、在一個△時間內(nèi)信號是否改變的指示或者一個數(shù)組的邊界。函數(shù)類屬性可細(xì)分為 3 個常見的類別。
1).函數(shù)類型屬性:返回類型值
函數(shù)類型屬性返回類型內(nèi)部值的位置號碼、返回特定類型輸入值的左和右邊的值,函數(shù)類型屬性分為 6 種:
? 'POS(value)返回傳入值的位置號碼;
? 'VAL(value)返回從該位置號碼傳入的值;
? 'SUCC(value)返回輸入值后類型中的下一個值;
? 'PRED(value)返回輸入值前類型中的原先的值;
? 'LEFTOF(value)表示立即返回一個值到輸入值的左邊;
? 'RIGHTOF(value)表示立即返回一值到輸入值的右邊。函數(shù)類型屬性主要用于從可枚舉數(shù)或物理類型的數(shù)轉(zhuǎn)換到整數(shù)類型。
2).函數(shù)數(shù)組屬性:返回數(shù)組的邊界
函數(shù)數(shù)組類屬性返回數(shù)組類型的邊界,分 4 類:
? 數(shù)組'LEFT(n)返回指數(shù)范圍 n 的左邊界;
? 數(shù)組'RIGHT(n)返回指數(shù)范圍 n 的右邊界;
? 數(shù)組'HIGH(n)返回指數(shù)范圍 n 的上限值;
? 數(shù)組'LOW(n)返回指數(shù)范圍 n 的下限值。值類數(shù)組屬性只有一個即 LENGTH,該屬性返回指定數(shù)組范圍的總長度,它用于帶某種標(biāo)量類型的數(shù)組范圍和帶標(biāo)量類型范圍的多維數(shù)組。
3).函數(shù)信號屬性:返回信號歷史信息
函數(shù)信號屬性用來返回有關(guān)信號行為功能的信息,例如報告究竟一個信號是否正好有值的變化,報告從上次事件中跳變過了多少時間以及該信號原來的值是什么。
函數(shù)信號屬性有如下 5 類:
? S'EVENT,如果當(dāng)前的△時間期間發(fā)生了事件返回真,否則返回假(信號是否有值的變化);
? S'ACTIVE,如果在當(dāng)前的△時間期間做了事項處理返回真,否則返回假;
? S'LAST_EVENT,返回從信號原先事件的跳變至今所經(jīng)歷的時間;
? S'LAST_VALUE,返回在上一次事件之前 S 的原先值;
? S'LAST_ACTIVE,返回自信號原先一次的事項處理至今所經(jīng)歷的時間。
5.3 信號類預(yù)定義屬性
信號類屬性用于根據(jù)另一個信號創(chuàng)建一些專用的信號,由類專用信號為設(shè)計者返回有關(guān)所附屬性的信號信息(在一指定時間范圍內(nèi)該信號是否已經(jīng)穩(wěn)定的信息、在信號上有無事項處理的信息和建立的信號的延遲形式)。
對這類信號是不能在子程序內(nèi)部使用的,返回的信息和由某種函數(shù)屬性所提供的功能非常類似,區(qū)別是這類專用信號用于正常信號能用的任何場合,包括在敏感表中。有如下的 4 類屬性:
? S'DELAYED[(time)] 建立和參考信號同類型的信號,該信號后跟參考信號和延時可選時間表示式的時間。'DELAYED 屬性為信號建立延遲的版本并附在該信號上,它和傳輸延時信號賦值的功能相同,但簡單。
? S'STABLE[(time)] 在選擇時間表達(dá)式指定的時間內(nèi)參考信號無事件發(fā)生時,屬性建立為真值的布爾信號。
? S'QUIET[(time)] 參考信號或所選時間表達(dá)式指定時間內(nèi)沒事項處理時,屬性建立一個為真值的布爾信號。
? S'TRANSACTION 信號上有事件發(fā)生或為每個事項處理而翻轉(zhuǎn)它的值時,該屬性建立一個 BIT 類型的信號。
5.4 數(shù)據(jù)類型類預(yù)定義屬性
數(shù)據(jù)類型類的屬性只有一個 t'BASE 類型屬性,它必須由另一個值或函數(shù)類型屬性用該屬性。這個屬性將返回類型或者子類型的基本類型,這個屬性只能作另一屬性的前綴。
5.5 數(shù)據(jù)范圍類預(yù)定義屬性
數(shù)據(jù)范圍類屬性返回數(shù)組類型的范圍值,并由所選的輸入?yún)?shù)返回指定的指數(shù)范圍,這種屬性標(biāo)記如下:a'RANGE[(n)];a'REVERSE_RANGE[(n)]。
屬性 RANGE 將返回由參數(shù) n 值指明的第 n 個范圍和按指定排序的范圍,'REVERSE_RANGE將返回按逆序的范圍,屬性'RANGE 和'REVERSE_RANGE 也用于控制循環(huán)語句的循環(huán)次數(shù)。
REVERSE_RANGE 屬性的用法和 RANGE 屬性相類似,只是它按逆序返回一范圍而已。 比如假設(shè)'RANGE 屬性是返回 0 到 15,那么'REVERSE_RANGE 屬性返回 15 下降到 0。