1. 為何要使用三態邏輯電路
信息雙向傳輸的時候需要(I2C屬於半雙工)。 也就是引腳定義為inout的時候。
圖1

2. FPGA里面如何實現三態邏輯電路
最近有學生問tri-state buffer / Inverter(如下圖)怎么實現?有兩種辦法:
圖2

-
用Verilog語句 Vo = ( Enable) ?~A: 1'bz ; 實現該硬件電路:
圖3

-
或是直接在Quartus 工具里面調用 74240 :
圖4

3. FPGA中I2C總線的接口處理
Intel 的 IP 文檔:
https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_embedded_ip.pdf
圖5

所以我在我的工程里面添加了altera_avalon_i2c IP以后,我的top.v文件要這樣處理:
圖6

4. 三態邏輯電路如何輸出高電平
可能大家會好奇,上面I2C三態邏輯 直接給了1'b0,怎么輸出高電平1呢?
圖7

dir 是1時, out = sda,dir 是 0 時,三態門輸出高阻, 也就是電阻無限大 相當於斷開, 然后 外部加上拉電阻,於是輸出是1。
所以FPGA和外設之間要有個上拉電阻。
圖8

5. I2C的 三態緩沖器避免輸出高電平
原則是: I2C輸出1 的時候三態緩沖器應該是輸出 highz。 I2C輸出0 的時候三態緩沖器輸出0。
如果I2C輸出1的時候 三態緩沖器輸出1 了, 則可能會和總線上其他設備 輸出的0 短路。
而I2C的輸出1 由緩沖器外部上拉電阻得到就不會存在短路情況。
所以只需要給 1'b0 , 當要I2C輸出0的時候 三態緩沖器輸出0 。 I2C要輸出1的時候,直接關掉三態緩沖器使能。
如果圖7 拿I2C 的應用舉例的話,實際要更進一步保證不能輸出1才行,底層代碼也沒處理輸出 1的話, 那這種方式做成的 i2c 只適用於 一個master 對一個 slave。 多個master的時候可能會出現短路燒掉IO。
