重拾VHDL和Verilog系列(一)——VHDL編寫結構


已經有幾年沒有接觸過VDHL或者Verilog了,在大二時,對VHDL是如此的熱愛,瘋狂得不用看仿真只通過看代碼就能知道問題所在,在那一年,我喜歡FPGA,喜歡了VHDL。

就在那一年,老師給我的項目失敗了,可能是自己技術不到家(那時連SDRAM工作原理還不懂,卻說要用VHDL實現SDRAM讀寫,當年還是有很多東西不了解,也沒有自己的一套學習方法),為了不讓老師失望,我決意轉向ARM,從此,我與FPGA、VHDL失去了交集,漸漸地,我把VHDL遺忘了。。。。。

其中在那一年,雖然主攻VHDL,但對Verilog也有作過少許學習(畢竟Verilog學習資料多),只是隨着時間的推移,Verilog與VHDL的轉換已成為過去。

今年,我又有機會與VHDL產生交集,其實是我主動向上司要求,我想研究FPGA、VHDL,可以減輕團隊的壓力。

好了,費話了一堆。現在的我又要從頭開始撿起VHDL了。

 

VHDL中的庫文件包含:

在VHDL中,少不了一些標准庫,如:std_logic這類聲明,都是來源於ieee這個庫的。

library ieee;
use ieee.std_logic_1164.all;

 

VHDL中實體聲明:

和高級語言一樣,VHDL也要聲明,這時有點不同的是,這種聲明是用於對外的接口,即輸入/輸出都在這里聲明的。

entity CRC_Unit is
port(
      iBitVal : in std_logic;
      iClock : in std_logic;
      iClear : in std_logic;
      oCRC : out std_logic_vector(4 downto 0)
);
end CRC_Unit;

 

VHDL結構功能:

有了對外的接口外,還得有內部的處理,這樣才能算是一個整體。architecture 就是對實體的內部功能的描述。

architecture ClacCRC of CRC_Unit is
signal inv : std_logic;
signal CRC : std_logic_vector(4 downto 0);

begin

inv <= iBitVal xor CRC(4);

process(iClock,iClear)
begin
      if iClear = '1' then
            CRC <= (others =>'0');
      elsif falling_edge(iClock) then
            CRC(4) <= CRC(3);
            CRC(3) <= CRC(2) xor inv;
            CRC(2) <= CRC(1);
            CRC(1) <= CRC(0) xor inv;
            CRC(0) <= inv;
      end if;
end process;

oCRC <= CRC;

end ClacCRC;

到此,就把VHDL的結構簡述完畢。

別急,我還沒有說完,下面還會對各個部分進行分析。由於代碼已經在上文給出,下文將不會再重復代碼。

 

 

VHDL中的庫

VHDL中的庫有哪些?

std_logic_1164
std_logic_arith
std_logic_unsigned
std_logic_signed

除了系統自帶的庫外,自己也可以編寫自己的,編寫格式如下:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

package PackageName is 

component Component1 is 
    PORT
    (    
          ...
    );
end component;

component Component2 is 
    PORT
    (    
         ...
    );
end component; 

end package;

格式和寫一個普通的VHDL文件差不多,不同的是,這個沒有實體,也沒有結構,只有包(component后面將描述)。

 

VHDL如何使用庫?

庫可以分為二大類,一類是系統自帶的標准庫,另一類的用戶自己編寫的,兩種類調用方式不太一樣。

上面代碼講到如何調用庫,如果使用標准庫,一般如下:

library ieee;     --表示使用什么庫
use ieee.std_logic_1164.all;    --表示使用庫中的具體的庫

其中std_logic_1164是在ieee庫中的,一般情況下,上而兩行代碼是必需的。

如果使用的是用戶自編寫庫,就要:

use work.PackageName.all;  --work表示當前工作目錄

使用用戶自編寫的庫看起來就簡單多了,只要使用use就可以了,值得注意的是,work是指當前工作目錄,而PackageName就是包的名字,前面的講述到。

 

 

VHDL中的實體

VHDL中的實體就簡單多了,主要是對引腳(或接口)的輸入、輸出或者雙向作定義。

其中port();中的為對外引腳。

引腳分三種:

輸入使用關鍵字:in

輸出使用關鍵字:out

雙向使用關鍵字:inout

對不同引腳要定義具體類型,引腳常用只有兩種類型,一種是單點引腳,一種是多點引腳。(單點、多點引腳是我的說法,不一定正常,但能表示其意思)

單點引腳使用:std_logic

多點引腳使用:std_logic_vertor(x downto 0)

有點類似普通變量和數組變量,一個表示單線、一個表示集合了多條單線(類似總線)。

注:在port();中,最后一個引腳不要加分號!

 

 

VHDL中的architecture

在architecture中且在begin前聲明

1、信號。信號如其名,就是傳遞信號用的。

2、組件(component),組件就是其他已經寫好的VHDL,組件只是把其引腳復述一遍,用於后期數據處理。

architecture XXX of XXX_Unit is
signal One:std_logic;    --聲明信號

component Component1 is  --聲明組件
    port
    (    
          ...  --具體一個實體的引腳
    );
end component;

begin
     ...
end XXX;

組件是將一個已經寫好的VHDL模塊(實現某一功能的VHDL文件) ,加入本VHDL中的方式,但加入還不夠,還要使用port map,下文將描述。

 

在architecture中且在begin后

在begin后常用的有語句不多,主要有if...else...end if,if...elsif...elsif...end if,process,port map等(這些語句能實現大部分邏輯)。

architecture XXX of XXX_Unit is

component CRC_Unit is
port(
      iBitVal : in std_logic;
      iClock : in std_logic;
      iClear : in std_logic;
      oCRC : out std_logic_vector(4 downto 0)
);
end component;

signal bitVal : std_logic;
signal clock  : std_logic;
signal clr    : std_logic;
signal crc    : std_logic_vector(4 downto 0);

begin

    oOut <= One;

    process(rst)      --敏感信號列表
    begin
         if rst = '0' then
           ...
         elsif
           ...
         end if;
    end process;

   u1:CRC_Unit port map(iBitVal => bitVal ,iClock => clock ,iClear => clr ,oCRC =>crc);
end XXX;

在VHDL中,只要在architecture中的語句都會被同時執行,但process一點特別,同時執行的是整個process,而不是process里面的各行語句。process其實更像是一個塊,一個對外同時執行,對內順序執行的一個單元。

在process的括號中的rst,被稱為敏感信號列表,只要放在這括號中的數據發生變化,就會同時執行期間觸發process內部操作。即oOut <= One、process及port map同時執行。

 port map是將原來component進architecture的組件進行使用,port map 后,會將對應的信號輸入或輸出。

 

VHDL architecture中的變量

變量需要聲明在process中,而且只能在process中被賦值,被調用。變量聲明在process中begin前。

process(rst)
variable val : integer ;
begin
      val := 10;
end process;

 

VHDL architecture中的賦值 

VHDL中有兩種賦值方式,一種是直接賦值,一種是延時賦值。還有一種不太像賦值,而是像指向的方式,port map (符號是"=>"),這里不把此方式當作賦值。

直接賦值:(賦值符號為":=" )

variable 就是直接的代表,當賦值后,左值將等於右值。

延時賦值:(賦值符號為"<=“ )

所有信號、引腳被賦值都是延時賦值。那什么是延時賦值?個人認為可以與實際電路理解(雖然不知是否正確)。信號可以看成一條線(引腳也是),當我在線的右端給出高電平的瞬間,左端的電平還沒有變化,因為從右到左需要一定的時間(那時間是光速),所以在同一周期作出了操作,但信號的值還沒有來得及改變,所以出現了延時賦值。

在VHDL中只有兩種賦值操作,如果想和高級語言一樣使用"="一般會出錯,因為在VHDL中"="是比較操作。

 

 

總結:

由於邊幅太長不利瀏覽,因此對VHDL、Verilog將以一個系列來講述。局限於本人技術有限,可能上文會有表達不通,或者表達不清的情況,如果有看不懂的,或者找出錯處的,歡迎大家提出。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM