不积跬步,  
无以至千里!  

  猫巾的博客

                网址:  http://hihii11.github.io/GWJ_BLOG.html


 

AXI_IIC_Master IP核设计与vivado中三态门综合问题


前 言:

  这几天总算是将I2C通信协议的verilog设计写好了,并成功完成了与EEPROM的数据交互。虽说Vivado中有AXI_IIC模块,但博主认为IIC通信协议是用来训练自己逻辑的再好不过的选择了,因此自己手写一个硬件IIC还是有必要的。在设计过程中遇到了一个非常奇怪的问题,就是Vivado对于模块中内嵌例化的三态门无法综合的问题,简单来说就是无法综合inout定义的信号,故开篇来记录下解决的过程。

  废话不多说,先上开源下载链接。

开源资料:

 IP核及测试SOC

  (测试SOC)IIC_test

  (AXI_IIC接口IP)AXI_IIC_Master2

 软件库支持

  IIC_Master_user

IP核信号说明:

遇到的问题:

  在设计中,遇到的最头疼也是最奇怪的问题就是inout端口无法综合的问题,接下来写一下该问题的解决过程。

  IIC属于半双工通信总线,所以对于SDA数据线既要能够作为输出发送数据,又要作为输入接收数据。这就涉及到了输入输出端口的设计,代码如下。

  tri_t为三态门的输入输出方向控制信号,当tri_t=1'b1时,tri_p的值将等于tri_i,此时tri_p作为输出。当tri_t = 1'b0时,tri_p的值为高阻态,即此时tri_p值由外接设备决定,并将该值通过tri_o输出。

  以上代码综合出的电路按理如下。

  但在Vivado综合后,烧录进fpga的电路在设置该端口为输入情况下,无法进行高低电平的识别,甚至将IO口直接拉至电源电压,也无法识别高电平,该端口的读数永远为低电平。

  在百思不得其解的情况下,我列出了如下几个可能原因一一排查

  1.三态门代码错误。

  2.IIC设备SDA总线需要上拉,但在约束时未进行上下拉进行约束。

  3.Vivado无法综合inout逻辑。

  对于第一种可能性,我将代码在quartus上进行实现,并烧录调试,发现是可以实现输入检测的。说明代码是没有错误的。

  对于第二种可能性,我在约束文件中添加如下上拉约束。

  通过漫长的编译后下载到zynq中,结果显而易见,仍然为低电平。

  那就剩下第三种可能性了,如果Vivado无法综合inout逻辑,那这个三态门综合出的结果是什么呢? 打开RTL原理图后,发现三态门被综合成下面这个样子:

  没错,vivado将三态门综合成了LUT资源,图中的LUT1。

  对于这种综合结果,与三态门相差甚远,但也可以解释为什么读数总为0了。为了解决这个综合错误问题,我尝试将三态门的逻辑放置到顶层top中,具体做法是将三态门单独封装成一个IP核,并在bd设计中调用,自以为这种直接连接IO口的逻辑,应该不会综合错误了吧。但结果令人大跌眼镜,Vivado综合出的结果如下。

  这种综合结果仅在“形状”上与三态门相似,功能相差了十万八千里。也就是说在输入时,高阻逻辑被综合成了逻辑0。这就基本确定,Vivado无法综合inout逻辑。这让我突然想到前几个月在xilinx开发板上移植CPU时,总线错误问题,大概率和这个是一个原因了。

  那既然vivado无法综合三态门,难道真的无法设计输入输出口了吗,答案肯定是行的,如果无法综合inout逻辑,那三态门肯定是在FPGA上的既定的资源。问题是如何去使用。

  于是我寻找了外援,同学“储大佬”,

  储大佬提到一个我忽略的问题-总线接口。随机给我发来了手册截图。

  手册中提到了用三态缓冲器来间接定义三态门的方法,具体就是通过对tri_i tri_o tri_t三个信号绑定一个三态门总线。

  具体操作方法就是点击页面的加号在Interface Definition中找到gpio_rtl,再将信号一一绑定即可。重新设计完IP核后,进行综合和RTL分析,总算得到了心心念念的三态门。

  至此,三态门综合错误问题解决。总结一下,Vivado是无法综合inout逻辑的,三态门作为既定的资源,也只能对真正存在的物理IO使用,具体方法就是通过Interface进行总线绑定,通过三态缓冲器驱动三态门。最后再放一张修改后的IP核图。

 

 

2022年1月创 于 Github管理
http://hihii11.github.io/GWJ_BLOG.html
@猫巾