引言
VHDL編程語言語法內容很多很雜,包括用于編程的規定、用于仿真的規定以及用于描述的規定。對于剛剛接觸VHDL語言的設計者而言,拿到厚厚的VHDL編程語言書籍,往往有無從下手感覺,其實對于使用VHDL很久的人來講,也不一定會使用VHDL很多編程規范,今天對VHDL常用的編程規范進捋一捋。
命名規范
VHDL語言中的信號、變量或者常量都必須有一個屬于自己的名字,即標識符,然后才能在程序中進行引用。而VHDL語法中的命名規則如下:
1、標識符中只能包含字符、數字和下劃線,即”A-Z”,”a-z”,”0-9”,”_”;
2、標識符必須以字符開頭,即開頭符號只能是”A-Z”,”a-z”。
signal、variable和constant 定義和使用
vhdl編程語言對信號、變量或常量大小不敏感。signal、variable和constant 是vhdl三種經常使用的賦值對象。所有賦值對象都遵循先聲明后使用原則。特別說明:常量是不能單獨賦值的,僅僅能在聲明的同時被初始化賦值。
signal
signal 中文意思為“信號” ,一般對應電路中特定的物理連線或存儲單元。當程序中需要用到signal時,我們一般需要在VHDL基本程序框架中的architecture語法的聲明與定義部分先聲明一個signal,然后才能在architecture的語句部分使用它。 Signal的聲明語法如下:
聲明1
signal 信號名 :=初值 ; – 有初值
需要對signal 信號賦初值,只能定義一個信號名,eg
signal state : std_logic_vector(3 downto 0):=x"0";
聲明2
signal 信號名:信號類型 ; – 無初值
signal state1: std_logic_vector(4 downto 0);
signal cnt: integer range 0 to 31;
聲明3
如果有多個同樣類型的信號需要聲明,也可以用這樣的語法:
signal 信號名1,信號名2,信號名3: 信號類型 ; – 多個信號名之間用逗號隔開
signal state11,state12: std_logic_vector(4 downto 0);
signal cnt1,cnt2: integer range 0 to 31;
特殊的聲明-端口信號聲明
entity語法中的port語法結構中的in、out、buffer或者inout類型的端口,雖然沒有用關鍵字“signal”來聲明,但它們其實都是signal類型的,并且同類型的端口也支持逗號分隔單行書寫的方法。
entity div_des is
port
(
clk : in std_logic;
rst_n : in std_logic;
numer32 : in std_logic_vector( 31 downto 0);
demoniator32 : in std_logic_vector( 31 downto 0);
quotient32 : out std_logic_vector( 31 downto 0);
remainer32 : out std_logic_vector( 31 downto 0)
);
end div_des;
或
entity div_des is
port
(
clk,rst_n : in std_logic;
numer32 : in std_logic_vector( 31 downto 0);
demoniator32 : in std_logic_vector( 31 downto 0);
quotient32 : buffer std_logic_vector( 31 downto 0);
remainer32 : out std_logic_vector( 31 downto 0)
);
end div_des;
特殊聲明-package 中聲明signal
在library里的package語法中,也可以聲明signal。
package my pkg is
type byte is range 0 to 255; ---定義byte的范圍
subtye nibyte is byte range 0 to 15; 定義子類型
constant byte_ff: bcd:=255;
signal added: nibabc;
component byte_adder
port
(
a,b: in byte;
c: out byte;
overflow: out boolean
);
end component;
function my_fun (a: in byte)
return byte;
end my pkg;
Variable
Variable即是“變量”的意思,它不具有特定的物理意義,對應關系也不太直接,通常只代表暫存某些值的載體。** 在之前介紹的VHDL基本程序框架中,可以看到variable出現在process語句中,作為process的局部變量來使用。** 當程序中要用到variable時,只需要在process語法的敏感量列表與begin關鍵字之間先聲明一個variable,然后就能在process的語句體中使用它。Variable的聲明語法如下:
特別強調:變量只能在進程、function和procedure 語法結構中進行先聲明后使用!
變量定義與信號定義類似,除了關鍵字和聲明的位置不同外,其余定義都相同!
Constant
Constant即是“常量”的意思,它具有特定的物理意義,通常對應數字電路中的電源或者地。Constant能出現在所有signal和variable出現的場合中,它的聲明語法如下:
constant : := ;
可以注意到,常量是不能單獨賦值的,僅僅能在聲明的同時被初始化賦值。
總結一下:信號、變量和常量之間差別:
差別一:賦值符號不同
變量聲明使用variable,賦值符號位:=
而信號聲明用signal,賦值符號為<=
差別二:使用位置不同或作用的范圍不同
1、變量只能用在進程函數體,子程序內部
2、信號不能再進程中聲明,信號用在結構體、實體、程序包。
差別三:敏感信號表中只能為信號,不能為變量。
在一個進程中,變量及時賦值,信號在進程結束后賦值。
(1)loop語句中,若在一個循環體內需要多次對某一個數據操作,則必須用變量,因為對信號賦值進行多次賦值只在最后一次才會有效。
(2)數組的索引(index)只能用變量。如果使用信號則編譯會報錯
編程心得
(1)變量賦值無延時是針對進程運行而言的,只是一個理想值,對于變量的操作往往被綜合成為組合邏輯的形式,而硬件上的組合邏輯必然存在輸入到輸出延時。當進程內關于變量的操作越多,其組合邏輯就會變得越大越復雜。假設在一個進程內,有關于變量的3個 級連操作,其輸出延時 分別為5ns,6ns,7ns,則其最快的時鐘只能達到18ns。相反,采用信號編程,在時鐘控制下,往往綜合成觸發器的形式,特別是對于FPGA芯片而言,具有豐富的觸發器結構,易形成流水作業,其時鐘頻率只受控于延時最大的那一級,而不會與變量一樣層層累積。假設某個設計為3級流水作業,其每一級延時分別為10ns,11ns,12ns,則其最快時鐘可達12ns。因此,采用信號反而更能提高設計的速度。
(2)由于變量不具備信息的相關性,只有當前值,因此也無法在仿真時觀察其波形和狀態改變情況,無法對設計的運行情況有效驗證,而測試驗證工作量往往會占到整個設計70%~80%的工作量,采用信號則不會存在這類問題。
(3)變量有效范圍只能局限在單個進程或子程序中,要想將其值帶出與其余進程、子模塊之間相互作用,必須借助信號,這在一定程度上會造成代碼不夠簡潔,可讀性下降等缺點。