2.VHDL的基本結構和語法(一)
目錄
1.VHDL基本結構
- 實體(Entity) :描述所設計的系統的外部介面訊號 ,定義電路設計中所有的輸入和輸出埠;
- 結構體 (Architecture) :描述系統內部的結構和行為;
- 包集合 (Package): 存放各設模組能共享的資料型別 、常數和子程式等 ;
- 配置 (Configuration): 指定實體所對應的結構體;
- 庫 (Library): 存放已經編譯的實體 、結構體 、包集合和配置。
VHDL的基本設計的基本設計單元結構:程式包說明 、實體說明和結構體說明三部分:
1.1.實體(Entity)
實體描述了設計單元的輸入輸出介面訊號或引腳 ,是設計實體經封裝後對外的一個通訊介面。
定義方式:
ENTITY 實體名 IS [ GENERIC( 常數名 :資料型別 :設定值) ]PORT ( 埠名1: 埠方向 埠型別; 埠名2: 埠方向 埠型別; . . 埠名n: 埠方向 埠類 型 ); END [實體名];
注意:實體名由設計者自由命名 ,用來表示被設計電路晶片的名稱 , 但是必須與VHDL程式的程式的檔名稱相同。 要與文 件 名一 致 。
-
類屬說明
類屬為設計實體與外界通訊的靜態資訊提供通道 ,用來規定埠的大小、實體中子元件的數目和實體的定時特性等。
格 式 :GENERIC( 常數名 :資料型別 :設定值; ∶ 常數名 :資料型別 :設定值 );
例 如:
GENERIC (wide :integer:=32); -- 說明寬度為32 GENERIC (tmp :integer:=1ns); -- 說明延時1 ns
-
埠方向:IN, OUT ,INOUT ,BUFFER
OUT” 和“BUFFER”都可定義輸出埠;
注意:若實體內部需要反饋輸出訊號 ,則輸出埠必須被設定為為“BUFFER”, 而不能為能為“OUT”。
- 同方向 、同類型的埠可放在同一個說明語句中。
1.2.結構體 (Architecture)
結構 體定義了設計單元具體的功能,描述了該基本設計單元的行為、 元件和內部的連線關係 .
定義方式:
ARCHITECTURE 結構體名 OF 實體名 IS [宣告語句]BEGIN 功能描述語句END [ 結構體名];
提示:
1.宣告語句的作用:用於宣告該結構體將用到的訊號 、資料型別 、常數、子程式和元件等 。 宣告的內容是區域性的。
2.功能描述語句:具體描述結構體的功能和行為。
- 一 個實體可對應多個結構體 , 每個結構體代表該實體功能的不同實現方案或不同實現方式 。同一時刻只有一個結構體起作用,通過CONFIGURATION決定用哪個結構體進行模擬或綜合。
- 在結構體描述中, 具體給出了輸入 、 輸出訊號之間的邏輯關係 。
1.3.庫、程式包的呼叫
方法:
LIBRARY 庫名; USE 庫名. 程式包名.專案名;
例子:
LIBRARY IEEE; USE IEEE.Std_Logic_1164.ALL;--呼叫此程式包的所有資源
其他例子:
LIBRARY IEEE; USE IEEE.Std_Logic_1164.ALL ; USE IEEE.Std_Logic_Arith.ALL ; USE IEEE.Std_Logic_Unsigned.ALL
1.4.VHDL語句
1.4.1.並行語句
在結構體中的執行是同時進行, 執行順序與書寫順序無關。如下圖所示
-
並行訊號賦值
- 簡單賦值語句
目標訊號名 <= 表示式
注意:目標訊號的資料型別與右邊表示式一 致。
- 選擇訊號賦值語句
WITH 選擇表示式 SELECT 賦值目標訊號 <= 表示式1 WHEN 選擇值 1, 表示式2 WHEN 選擇值 1, 表示式n WHEN OTHERS;
注意:
1.選擇值要覆蓋所有可能情況 , 若不能一一指定,用OTHERS為其他情況找個出口。
2.選擇值必須互斥 ,不能出現條件重複或重疊的情況。
例子:
實現一個4X1多路選擇器,當選擇訊號為00則輸出訊號為Data0的資料,選擇為01輸出Data1的訊號,依次類推:
程式如下:
library ieee;
use ieee.std_logic_1164.all;
entity mux is
port
(Data0,Data1,Data2,Data3:IN std_logic_Vector(7 downto 0);
Sel : IN std_logic_vector(1 downto 0);
Dout: out std_logic_vector(7 downto 0)
);
end;
architecture DataFolw of mux is
begin
with Sel select
Dout<= Data0 WHEN "00",
Data1 WHEN "01",
Data2 WHEN "10",
Data3 WHEN "11",
"00000000" WHEN OTHERS;
end;
進行模擬測試:
- 條件訊號賦值語句
賦值目標訊號 <= 表示式1 WHEN 賦值條件1 ELSE 表示式2 WHEN 賦值條件2 ELSE 表示式n WHEN 賦值條件n ELSE 表示式;
注意:
1.各賦值語句有優先順序的差別 , 按書寫順序從高到低排列;
2.各賦值條件可以重疊。
例子:
實現8輸入優先編碼器:
程式如下:
library ieee;
use ieee.std_logic_1164.all;
entity Priority_Encoder is
port
(I : in std_logic_vector(7 downto 0);
A : out std_logic_vector(2 downto 0)
);
end;
architecture DataFlow of priority_Encoder is
begin
A<="111" WHEN I(7)='1' ElSE
"110" WHEN I(6)='1' ElSE
"101" WHEN I(5)='1' ElSE
"100" WHEN I(4)='1' ElSE
"011" WHEN I(3)='1' ElSE
"010" WHEN I(2)='1' ElSE
"001" WHEN I(1)='1' ElSE
"000" WHEN I(0)='1' ElSE
"111";
end;
進行模擬測試:
1.4.2.程序語句
程序語句定義順序語句模組 ,用於將從外部獲得的訊號值 ,或內部的運算資料向其他的訊號進行賦值 。
- 程序本身是並行語句, 但內部是順序語句 ;
- 程序只有在特定的時刻 ( 敏感訊號發生變化) 才會被啟用。
語法:
[ 程序標號 :] ] PROCESS ( 敏感訊號引數表 ) [宣告區 ] ; BEGIN 順序語句 END PROCESS [程序標號] ;
注意:
1.一 個程序可以有多個敏感訊號 , 任一 敏感訊號發生變化都會啟用程序。
2.宣告區的作用:在程序中起作用的區域性變數。
-
程序的工作原理:
注意事項:
1.程序掛起:則執行過程終止。
2.當某個敏感訊號的值發生變化時,每個程序語句立即完成程序內順序語句所定義的功能行為。
3.順序語句所定義的功能行為的結果可以賦值給訊號,並通過訊號被其他簡稱讀取或賦值。
-
程序與時鐘
在每個上升沿啟動一次程序( 執行程序內所有的語句 ) 。
描述方法:
上升沿描述: Clock’ EVENT AND Clock=‘1’ 下降沿描述: Clock’ EVENT AND Clock=‘0’ 上升沿描述: rising_edge (Clock) 下降沿描述: falling_edge (Clock)
例子1:
把clock設為敏感訊號,當clock上升沿時,輸出時鐘就進行取反一次。
程式如下:
library ieee;
use ieee.std_logic_1164.all;
entity FreDevider is
port
(Clock: in std_logic;
Clkout:out std_logic
);
end;
architecture Behavior of FreDevider is
Signal Clk:std_logic;
begin
process(Clock)
begin
if rising_edge(Clock) THEN
Clk<=NOT Clk;
end if;
end process;
Clkout<=Clk;
end;
模擬波形如下:
例子2:
本例子做一個自加器,沒遇到一個clock的上升沿,num就自加1,加到3就自動清零,重新開始,迴圈進行,還有一個復位按鈕,只要檢測是reset的值為1,num的數值就清零,重新開始計數。
程式碼如下:
library ieee;
use ieee.std_logic_1164.all;
entity Counter is
port
(reset: in std_logic; --非同步時鐘復位訊號
clock: in std_logic; --時鐘訊號
num :buffer integer range 0 to 3); --設定一個整形變數,範圍從0到3
end;
architecture Behavior of Counter is
begin
process(reset,clock) --將復位,和時鐘作為程序的敏感訊號
begin
if reset='1' THEN
num<=0; --當檢測到reset=1時,num清零
elsif rising_edge(clock) THEN
if num=3 THEN
num<=0; --如果num=3就,清零
else
num<=num+1; --否則自加1
end if;
end if;
end process;
end;
模擬結果如下:
-
程序的啟動
- 當process的敏感訊號引數表中沒有列出任何敏感訊號時 ,程序通過wait 語句啟動
例子:
ARCHITECTURE Behavior OF state IS BEGIN PROCESS -- 敏感訊號列表為 空 BEGIN wait until Clock; -- 等待clock啟用程序 IF ( drive=‘1’) THEN CASE output IS WHEN s1 => output <= s2; WHEN s2 => output <= s3; WHEN s3 => output <= s4; WHEN s4 => output <= s1; END CASE; END IF; END PROCESS; END;
-
程序的注意事項
- 程序本身是並行語句, 但內部為順序語句 ;
- 程序在敏感訊號發生變化時被啟用 ,在使用了敏感表的程序中不能含wait 語句 ;
- 在同一程序中對同一訊號多次賦值 , 只有最後一次生 效 ;
- 在不同程序中,不可對同一訊號進行賦值;
- 一個程序不可同時對時鐘上 、下沿敏感 。
- 程序中的訊號賦值是在程序掛起時生效的,而變數賦值是即時生 效。
- 相對於結構體而言, 訊號具有全域性性 ,是程序間進行並行聯絡的重要途徑 。
- 程序為綜合器支援 ,且其建模方式直接影響模擬和綜合結果 ,綜合後對應於程序的硬體結構對程序中所有可讀入訊號都是敏感的。
1.5.元件例化語句
- 元件例化引入一種連線關係 , 將預先設計好的實體定義為元件 , 並將此元件與當前設計實體中的埠相連線 , 從而為當前設計實體引入一個新的低一級的設計層次 。
舉例:把元件比喻成要插在電路系統板上的晶片,埠比喻成準備接受晶片的插座。
元件例化的方式:
元件定義語句:
Component 元件名 port ( 埠名錶); End component 元件名;
元件例化語句:例化名 : 元件名 port map ( [元件埠名=>]連線埠名 , …);
注意:
1.port當中列出對外通訊的各埠名。
2.埠的關聯方式有兩種,第一:名字關聯法,port map的語句中位置可以隨意,第二:位置關聯法,埠名和關聯連線符號可以省去,連線埠名的排列方式與所需例化的元件埠定義的埠名順序相對應。
3.連線埠名:當前系統與準備接入的元件對應埠相連的通訊埠。
例子:
設計一個四輸入的與非門,如下圖所示:
此時我們需要設計一個2輸入的與非門,然後通過元件例化這個二輸入的與非門,實現四輸入與非門的功能。
-
實現元件例化的詳細步驟
1.在電腦本地新建兩個資料夾,分別用於存放二輸入與非門的檔案,另一個是實現這個與非門例化實現功能的元件。
在我們電腦本地目錄下:D:\QuartusII_Test,新建兩個資料夾如下所示:
2.然後再QuartusII新建一個VHDL檔案,實現二輸入與非門的功能,具體程式碼如下:
library ieee;
use ieee.std_logic_1164.all;
entity nd2 is
port
(a,b :in std_logic;
c :out std_logic
);
end;
architecture nd2bhv of nd2 is
begin
c<=a nand b;
end;
3.然後儲存到D:\QuartusII_Test\nd2中,工程也要命名為:nd2
4.編輯成功後,新建一個模擬波形圖,如下功能模擬正確
5.新建一個工程,工程儲存到D:\QuartusII_Test\ord41 ,然後命名為ord41
6.新建一個VHDL檔案,使用二輸入與非門的元件例化,程式碼編輯如下:
library ieee;
use ieee.std_logic_1164.all;
entity ord41 is
port
(a1,b1,c1,d1 :in std_logic;
z1 :out std_logic);
end ord41;
architecture ord41bhv of ord41 is
component nd2
port(a,b:in std_logic;
c :out std_logic);
end component;
signal x,y:std_logic;
begin
u1:nd2 port map(a1,b1,x);
u2:nd2 port map(a=>c1,c=>y,b=>d1);
u3:nd2 port map(x,y,c=>z1);
end ord41bhv;
附錄:對上面例子的說明
7.儲存,檔名為ord41
8.這一步很重要,如果沒有這一步編譯將會報錯!!!
新增庫剛剛nd2的庫到這個工程。
點選assignment下拉選單中的settings選項,並選中user libraries選項,則下圖所示:
點選library name 後面的“…” 按鈕,找到nd2資料夾,點選Add, 如下圖所示:
9.點選編譯按鈕,對ord41工程進行編譯,如果設定好第8步,而且語法沒有錯的話不會報錯。
10.編譯成功後,然後新建模擬圖進行模擬,模擬結果如下: