首先可以看特權同學的這篇文章http://www.eefocus.com/ilove314/blog/11-09/231507_10e01.html作個初步了解。
下面我們用三種方法去實現inout,先說明一下,第一種方法的結果與其他兩種方法不一樣,估計有問題,不推薦使用。
第一種方法和第二種方法的區別是inout作輸入時的寫法不一樣。第三種方法針對Xilinx FPGA,直接使用原語IOBUF。
代碼如下,綜合工具Vivado 2015.3,器件選擇k7325tffg900-2。
module inout_def( input clk, input z, inout dinout, input z2, inout dinout2, input z3, inout dinout3, output reg led_r1, output reg led_r2, output reg led_r3 ); reg dout = 0; wire din; assign dinout = z?1'bz:dout; assign din = z?dinout:1'bz; always @(posedge clk) begin if(din) led_r1 <= 1; else led_r1 <= 0; end reg dout2 = 0; wire din2; assign dinout2 = z2?1'bz:dout2; assign din2 = dinout2; always @(posedge clk) begin if(din2) led_r2 <= 1; else led_r2 <= 0; end reg dout3 = 0; wire din3; IOBUF IOBUF( .I(dout3), .O(din3), .T(z3), .IO(dinout3) ); always @(posedge clk) begin if(din3) led_r3 <= 1; else led_r3 <= 0; end endmodule
對代碼進行綜合,結果如下圖所示,可以看到,第二種方法和第三種方法綜合出來的結果是相同的,第一種方法的結果與其他兩種不同。所以inout作輸入時直接assign就行了。
放大IOBUF可以看到,IOBUF實際上由一個OBUFT和一個IBUF組成。
IBUF是輸入緩沖器,這個不多說。OBUFT是三態輸出緩沖器,其結構和真值表如下圖所示,可以看到,當T為1時,輸出是高阻態。當T為0時,輸出與輸入結果相同。
所謂高阻態,百度百科是這樣說的:電路分析時高阻態可做開路理解。你可以把它看作輸出(輸入)電阻非常大。它的極限狀態可以認為懸空(開路)。也就是說理論上高阻態不是懸空,它是對地或對電源電阻極大的狀態。而實際應用上與引腳的懸空幾乎是一樣的。
我們想象一下,OBUFT為高阻態時相當於開路,那dinout3和IBUF組成的通路和一般的輸入通路豈不是完全相同,所以此時可以當Input來用。
下面進行implementation,我們看dinout3實現的結果,可以看到IOBUF的IBUF和OBUFT以及相應的聯結關系。OBUFT的TRI對應的是z3。IBUF的OUT對應的是led_r3_reg。
最后,考慮到代碼的通用性,在使用inout端口的時候還是推薦用第二種方法。