1. 为何要使用三态逻辑电路

信息双向传输的时候需要(I2C属于半双工)。 也就是引脚定义为inout的时候。
图1
img

2. FPGA里面如何实现三态逻辑电路

最近有学生问tri-state buffer / Inverter(如下图)怎么实现?有两种办法:
图2
image-20210409162050483

  1. 用Verilog语句 Vo = ( Enable) ?~A: 1'bz ; 实现该硬件电路:
    图3
    img

  2. 或是直接在Quartus 工具里面调用 74240 :
    图4
    img

3. FPGA中I2C总线的接口处理

Intel 的 IP 文档:

https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_embedded_ip.pdf
图5
img
所以我在我的工程里面添加了altera_avalon_i2c IP以后,我的top.v文件要这样处理:
图6
image-20210409174325939

4. 三态逻辑电路如何输出高电平

可能大家会好奇,上面I2C三态逻辑 直接给了1'b0,怎么输出高电平1呢?

图7
img
dir 是1时, out = sda,dir 是 0 时,三态门输出高阻, 也就是电阻无限大 相当于断开, 然后 外部加上拉电阻,于是输出是1。

所以FPGA和外设之间要有个上拉电阻。
图8
img

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。