引言
現場可編程門陣列(FPGA)的出現是超大規模集成電路(VLSI)技術和計算機輔助設計(CAD)技術發展的結果。FPGA器件具有集成度高、體積小、可以通過用戶編程實現專門應用的特點。這些特點非常適合大學計算機教學中的計算機硬件實驗。在計算機硬件實驗中,三態電路有著廣泛的應用,例如構建一個具有分時共享功能的總線電路就需要用到多個三態電路。傳統的實驗方法要先畫出原理圖,然后通過手工連線各個芯片來搭建三態電路。在基于FPGA的硬件實驗中,一種方法是利用圖形方式,在MAX+PLUSⅡ中畫出三態電路圖,并編譯完成實現三態的功能;另一種方法是直接用VHDL語言編寫出三態電路程序,同樣需要編譯完成實現三態的功能。但是,在MAX+PLUSⅡ環境下,應用三態電路時常會遇到了很多問題,這些問題阻礙著用VHDL語言正確使用三態電路的功能。我們在FPGA應用設計中也發現了類似問題,經過仔細的分析和對多種不同實現方法的嘗試,最后掌握了正確的實現方法,同時也找出了一般方法出錯的原因。
在MAX+PLUSⅡ環境下最常見的三態應用程序及問題
在MAX+PLUSⅡ環境下,由于軟件本身提供了三態總線電路的模塊,因此可以在VHDL編程時直接調用lpm_bustri模塊。下面是一個用VHDL編寫的8位單向總線電路的程序片斷:
entity tri_bus is
port(a,b: in std_logic_vector(7 downto 0);
aen,ben: in std_logic;
q:out std_logic_vector(7 downto 0));
end tri_bus;
architecture tri_bus_body of tri_bus is
component lpm_bustri
generic(lpm_width:positive);
port (data : in std_logic_vector(lpm_width-1 downto 0);
enabledt: in std_logic:=‘0’;
tridata:inout std_logic_vector(lpm_width-1 downto 0));
end component;
signal temp: std_logic_vector(7 downto 0);
begin
u1:lpm_bustri
generic map(lpm_width=》8)
port map(data=》a,enabledt=》aen,tridata=》temp);
u2:lpm_bustri
generic map(lpm_width=》8)
port map(data=》b,enabledt=》ben,tridata=》temp);
q《=temp;
end tri_bus_body;
以上程序很簡單,通過調用lpm中的三態模塊,以實現三態輸出傳輸至總線的功能。程序中將兩個三態模塊的輸出連接在一起,構成一個8位總線,總線輸出結果取決于兩個三態模塊中哪一個的使能信號有效。這段程序理論上不存在問題,然而編譯卻無法通過!編譯器報錯,指出信號temp被多次賦值。
顯然,在u1和u2中有兩次出現tridata=》temp,但這對于三態電路來說是允許的,因為三態輸出是可以并聯的。那么是否因為lpm_bustri模塊不能正確實現三態功能呢?我們首先用圖形方式來驗證該模塊的功能。由于只是驗證,這里只設置了一位的數據輸入和輸出,如圖1,圖中a為數據輸入端,q為數據輸出端,aen為使能端。

圖 1
該圖形文件成功地通過了編譯,而且仿真結果表明,三態功能完全正確,即使能aen有效,輸出為a,使能aen無效,輸出為高阻。然后,我們又用圖形方式搭建了前面的VHDL程序邏輯,建好的圖形文件如圖2所示。

圖 2
這個圖形文件所示邏輯同前面VHDL程序的內容完全相同。信號q的輸出取決于兩個使能端中哪一個有效。然而編譯還是出錯,這次指出的錯誤是兩個lpm_bustri的輸出tridata連接在一起了。
從理論上來說,兩個三態的輸出是可以接在一起的。為了證明這一點我們不再采用lpm_bustri模塊,而是在MAX+PLUSⅡ環境下用圖形方式直接畫出兩個三態元件,然后再將它們的輸出連接在一起,如圖3。

圖 3
這各圖形文件順利通過編譯!仿真結果也完全正確,當aen使能有效,q輸出為a;當ben使能有效,q輸出為b。如果沒有兩個使能端均無效,輸出為三態,如果兩個使能端均有效,輸出結果為a和b的線與。(由于在實際總線電路中,aen和ben不可能同時有效,所以此種情況并不影響結果的正確性,我們只要知道這種情況下的輸出結果是兩個信號的線與就可以了。)
修改后的三態電路應用程序
既然三態電路用圖形方式在MAX+PLUSⅡ環境下可以正確實現,那么VHDL程序也應該是可以的。前面編譯出錯的程序和電路都是因為用到了lpm_bustri模塊,如果不用它程序將如何修改呢?在這種疑問下我們改變了思路,修改后的VHDL程序如下:
library ieee;
use ieee.std_logic_1164.all;
entity tri_state is
port(a,b :in std_logic_vector(7 downto 0);
aen, ben :in std_logic;
q :out std_logic_vector(7 downto 0));
end tri_state;
architecture tri_state_body of tri_state is
signal control:std_logic_vector(1 downto 0);
begin
control(1)《=aen;
control(0)《=ben;
process(a,b,control)
begin
case control is
when “10”=》q《=a;
when “01”=》q《=b;
when others=》q《=(others=》‘Z’);
end case;
end process;
end tri_state_body;
這段VHDL程序同最初那段VHDL程序表達的功能是一樣的,當aen使能有效,輸出為a,當ben使能有效,輸出則為b,如果不是這兩種情況均輸出三態。這次經過編譯和仿真,功能正確實現了。
分析不同程序不同結果的原因
為什么最初的VHDL程序和用lpm模塊搭建的圖形會出錯呢?帶著這個問題將兩個程序進行對比便可找出問題的所在。在修改后的程序中,我們用了一個control二維數組來控制對輸出信號q的賦值,雖然輸出信號q也是有兩個輸入源a和b,但是程序控制了它們賦值的時間,也就是不可能同時被賦值,所以編譯器沒有報錯。而最初的程序的卻出現temp被多次賦值,再來看看源程序:
u1:lpm_bustri
generic map(lpm_width=》8)
port map(data=》a,enabledt=》aen,tridata=》temp);
u2:lpm_bustri
generic map(lpm_width=》8)
port map(data=》b,enabledt=》ben,tridata=》temp);
q《=temp;
其中,雖然實際中不可能讓三態的兩個使能同時有效,但是對于編譯器而言,它只能識別語句的邏輯,在上面那種邏輯下,aen和ben是完全可能同時有效的(僅僅是邏輯,只對語句而言)。如果這種情況發生,編譯器將無法正確對q賦值,所以報錯,提示信號temp被多次賦值,這完全是因為編譯器嚴謹的結果。
在一個編譯器中,語法的正確性檢查是基于一種規則和邏輯的,它是適用于一切的語言描述。雖然三態的輸出可以連接在一起,但是當程序直接將它們連接在一起的時候(也就是多源賦值的時候),編譯器不可能因為程序編的是三態邏輯而通過這種潛在的錯誤,它的編譯原理是基于語句而不是編出來的結果。這樣就可以解釋為什么簡單的元件搭建出來的三態輸出連接在一起可以通過編譯,而用lpm模塊描述出來的和我們最初的三態程序描述出來的三態輸出卻不能通過編譯。因為它們都需要通過編譯器的語法檢查。而多源賦值又是一種潛在的錯誤,所以不能通過。那么有些人會不理解,都是圖形描述,為何簡單的元件搭建可以通過而高級的lpm模塊搭建卻不行?答案是高級的lpm模塊也是用語言編寫出來的,它也要通過編譯器的語法檢查。簡單的元件搭建可以通過是因為在兩個使能都成立的情況下,軟件可以將輸出信號按線與處理,從而避免了沖突和不確定性。那么如何利用lpm模塊實現三態的功能?這就要看如何運用在具體的應用中了。如果僅僅需要將兩個三態的輸出連接在一起,通過各自的使能端控制輸出的話,可以在一個原理圖中分別建立兩個單獨的lpm模塊,不要將它們的輸出端連接在一起(否則編譯器會報錯),然后直接編譯,編譯通過后可以在配置FPGA的時候將建立的兩個lpm模塊的輸出連接到同一個管腳上,經過驗證,這樣在應用中也是可以正常實現三態功能的(因為其避免了在編譯前就將輸出口連接在一起而不能通過編譯的情況的發生)。
總結
通過以上的分析和說明,我們知道MAX+PLUSⅡ環境下,是可以正確實現三態電路應用的。主要有三種方法:
① 用類似于我們上面改編出來的程序來實現;
② 用自搭建的圖形描述實現;
③ 在配置FPGA時再將不同的三態輸出端連接到同一個管腳上。
需要注意的是在編寫程序或者利用軟件本身提供的模塊搭建電路時要了解軟件自身或者所調用的模塊在編譯時是否會引起編譯器的沖突。在了解了編譯器編譯原理后,才能在編寫和調試程序時游刃有余,及時發現和改正問題。
創新觀點:本文指出了在MAX+PLUSⅡ環境下運用三態電路常見錯誤的原因,并指明了幾種正確的實現方法。
責任編輯:gt
電子發燒友App

























評論