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。