引言
VHDL編程語言語法內(nèi)容很多很雜,包括用于編程的規(guī)定、用于仿真的規(guī)定以及用于描述的規(guī)定。對于剛剛接觸VHDL語言的設(shè)計者而言,拿到厚厚的VHDL編程語言書籍,往往有無從下手感覺,其實對于使用VHDL很久的人來講,也不一定會使用VHDL很多編程規(guī)范,今天對VHDL常用的編程規(guī)范進(jìn)捋一捋。
命名規(guī)范
VHDL語言中的信號、變量或者常量都必須有一個屬于自己的名字,即標(biāo)識符,然后才能在程序中進(jìn)行引用。而VHDL語法中的命名規(guī)則如下:
1、標(biāo)識符中只能包含字符、數(shù)字和下劃線,即”A-Z”,”a-z”,”0-9”,”_”;
2、標(biāo)識符必須以字符開頭,即開頭符號只能是”A-Z”,”a-z”。
signal、variable和constant 定義和使用
vhdl編程語言對信號、變量或常量大小不敏感。signal、variable和constant 是vhdl三種經(jīng)常使用的賦值對象。所有賦值對象都遵循先聲明后使用原則。特別說明:常量是不能單獨賦值的,僅僅能在聲明的同時被初始化賦值。
signal
signal 中文意思為“信號” ,一般對應(yīng)電路中特定的物理連線或存儲單元。當(dāng)程序中需要用到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語法結(jié)構(gòu)中的in、out、buffer或者inout類型的端口,雖然沒有用關(guān)鍵字“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即是“變量”的意思,它不具有特定的物理意義,對應(yīng)關(guān)系也不太直接,通常只代表暫存某些值的載體。** 在之前介紹的VHDL基本程序框架中,可以看到variable出現(xiàn)在process語句中,作為process的局部變量來使用。** 當(dāng)程序中要用到variable時,只需要在process語法的敏感量列表與begin關(guān)鍵字之間先聲明一個variable,然后就能在process的語句體中使用它。Variable的聲明語法如下:
特別強調(diào):變量只能在進(jìn)程、function和procedure 語法結(jié)構(gòu)中進(jìn)行先聲明后使用!
變量定義與信號定義類似,除了關(guān)鍵字和聲明的位置不同外,其余定義都相同!
Constant
Constant即是“常量”的意思,它具有特定的物理意義,通常對應(yīng)數(shù)字電路中的電源或者地。Constant能出現(xiàn)在所有signal和variable出現(xiàn)的場合中,它的聲明語法如下:
constant : := ;
可以注意到,常量是不能單獨賦值的,僅僅能在聲明的同時被初始化賦值。
總結(jié)一下:信號、變量和常量之間差別:
差別一:賦值符號不同
變量聲明使用variable,賦值符號位:=
而信號聲明用signal,賦值符號為<=
差別二:使用位置不同或作用的范圍不同
1、變量只能用在進(jìn)程函數(shù)體,子程序內(nèi)部
2、信號不能再進(jìn)程中聲明,信號用在結(jié)構(gòu)體、實體、程序包。
差別三:敏感信號表中只能為信號,不能為變量。
在一個進(jìn)程中,變量及時賦值,信號在進(jìn)程結(jié)束后賦值。
(1)loop語句中,若在一個循環(huán)體內(nèi)需要多次對某一個數(shù)據(jù)操作,則必須用變量,因為對信號賦值進(jìn)行多次賦值只在最后一次才會有效。
(2)數(shù)組的索引(index)只能用變量。如果使用信號則編譯會報錯
編程心得
(1)變量賦值無延時是針對進(jìn)程運行而言的,只是一個理想值,對于變量的操作往往被綜合成為組合邏輯的形式,而硬件上的組合邏輯必然存在輸入到輸出延時。當(dāng)進(jìn)程內(nèi)關(guān)于變量的操作越多,其組合邏輯就會變得越大越復(fù)雜。假設(shè)在一個進(jìn)程內(nèi),有關(guān)于變量的3個 級連操作,其輸出延時 分別為5ns,6ns,7ns,則其最快的時鐘只能達(dá)到18ns。相反,采用信號編程,在時鐘控制下,往往綜合成觸發(fā)器的形式,特別是對于FPGA芯片而言,具有豐富的觸發(fā)器結(jié)構(gòu),易形成流水作業(yè),其時鐘頻率只受控于延時最大的那一級,而不會與變量一樣層層累積。假設(shè)某個設(shè)計為3級流水作業(yè),其每一級延時分別為10ns,11ns,12ns,則其最快時鐘可達(dá)12ns。因此,采用信號反而更能提高設(shè)計的速度。
(2)由于變量不具備信息的相關(guān)性,只有當(dāng)前值,因此也無法在仿真時觀察其波形和狀態(tài)改變情況,無法對設(shè)計的運行情況有效驗證,而測試驗證工作量往往會占到整個設(shè)計70%~80%的工作量,采用信號則不會存在這類問題。
(3)變量有效范圍只能局限在單個進(jìn)程或子程序中,要想將其值帶出與其余進(jìn)程、子模塊之間相互作用,必須借助信號,這在一定程度上會造成代碼不夠簡潔,可讀性下降等缺點。