VHDL 的一個強大功能是用庫來組織 RTL 的不同部分。通過使用庫,不同的設(shè)計人員可以做這個工程中自己負責(zé)的那部分工作,而不必擔(dān)心會在命名方面與其他設(shè)計師發(fā)生沖突。在例化期間,這可以通過手動指定要使用的庫或者通過配置語句來完成。
例如,已經(jīng)在一個名為“my_lib1”的庫中創(chuàng)建并編譯了一個名為“bottom”的實體。
編譯到任何庫中的頂層可以輕松地通過直接實體例化來引用底層:
u0 : entity my_lib1.bottom port map (in1 => in1, out1 => out1);
通過采用上面的編碼方式,需要哪個版本的底層就顯而易見了。??“my_lib1”庫中的版本是正確無誤的版本。
一個常見的誤解與何時使用名為“work”的庫有關(guān)。??許多設(shè)計師將“work”用作庫,假設(shè)它與其他庫一樣,是一個物理庫。??但情況并非如此。名為“work”的庫在 VHDL 中的用法比較特殊。?
它不是一個物理庫,實際上它指的是“當(dāng)前庫”。
當(dāng)一個文件被編譯到一個特定的庫中,然后被告知從“work”中獲取邏輯時,它不會在名為“work”的物理庫查找,而是會在例化的文件被編譯到的庫中查找。??這一點可以通過幾個例子來展示。
實例 #1
在此示例中,有三個文件,top.vhd、bottom1.vhd 和 bottom2.vhd。? Top.vhd 是設(shè)計中的頂層,例化了一個名為“bottom”的實體。??底層的兩個文件都有一個名為“bottom”的實體。??在 bottom1.vhd 中,有一個輸出是由一個通過反相器過驅(qū)動的的輸出。??在 bottom2.vhd,中,輸出直接由輸入驅(qū)動。
頂層被編譯到名為 y_lib1、bottom1.vhd 的庫中(也在 my_lib1 庫中),而且,bottom2.vhd 在名為 my_lib2 的庫里。?
在頂層,例化看起來類似于以下內(nèi)容:
u0 : entity work.bottom port map (in1=> in1, out1 => out1);
查看詳細視圖,該示意圖如下所示:
這正是我們期待看到的結(jié)果。??更重要的是,當(dāng)使用相同的建立運行仿真時,波形圖如下例所示:
接下來,如果 top.vhd 文件的庫從 my_lib1 轉(zhuǎn)換到 my_lib2,則對詳細視圖所做的更改如下所示:
并且,仿真波形圖也會發(fā)生變化:
這正是我們預(yù)期的結(jié)果。??因為 top.vhd 文件在 my_lib2 中,并且在實體例化中使用了“work”,所以它將從 my_lib2 中獲取底層。
示例 #2
此示例將顯示假設(shè)“work”是物理庫所帶來的危險。??這是與示例?#1 類似的測試。??在此示例中,top.vhd 和 bottom1.vhd 將被編譯到“my_lib1”庫中,bottom2.vhd 將被編譯到名為“work”的庫中。?
與前面的示例一樣,頂層例化底部,如下所示:
u0: entity work.bottom port map (in1 => in1, out1 => out1)
這個設(shè)計的詳細視圖類似于以下示例:
仿真如下所示:
因此,即使 bottom2.vhd 已被編譯為一個名為“work”的物理庫,并且頂層由“work”庫例化了底部,但該工具仍然會使用 bottom1.vhd 中與top.vhd 編譯到同一個庫中的行為。
Vivado 默認庫:
默認情況下,將 VHDL 文件輸入 Vivado 工程時,該工具會將這些文件放入一個名為“xil_defaultlib”的庫中。??這樣做的原因是讓只使用庫的用戶能夠輕松地將舊的工程移植到 VHDL 中,同時還能幫助設(shè)置有更多組合結(jié)構(gòu)的用戶以恰當(dāng)?shù)姆绞皆?Vivado 中對他們的工程進行設(shè)置。
結(jié)論:
選擇 VHDL 文件的庫名時應(yīng)小心。??雖然名為“work”的庫是許多工程公用的庫名,但該工具處理這個庫名的方式與處理其他庫名的方式略有不同。??如果將頂層文件編譯到不同的庫中并引用“work”,那么它就不會從名為“work”的物理庫中獲取行為。??如果這不是所期望的,就可能會導(dǎo)致混亂的行為。
我的建議是永遠不要使用“work”庫。??相反,在例化較低層時,始終應(yīng)指定要使用的庫。?
這樣做有點費事,但通常會給你想要的行為。