一 : 建立新的vivado工程
在新建工程资源中,有以下两个文件:
top.v :新建的空白verilog工程文件,用作此次实验的rtl顶层
Zybo-Z7-Master.xdc: 对应开发板的芯片引脚约束文件
此次实验,我们的目的是使用开发板集成的switch,来控制开发板的led灯亮灭.
二:代码编写
根据实验目的,代码编写如下:
module top(
input sw,
output led
);
assign led = sw;
endmodule
三: 修改约束文件
我们需要将top声明的输入输出端口,与我们的约束文件对应。设置约束条件如下:
set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { sw }]; #IO_L19N_T3_VREF_35 Sch=sw[0]
set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { led }]; #IO_L23P_T3_35 Sch=led[0]
注意:{get_ports xxx}中的xxx,必须与我们的端口名称一致
四:开始综合
综合后的电路y原理图:
可以看到,在综合后,除了sw 和 led 两个pad之外,还新增了两个leaf cell : sw_IBUF_inst , led_OBUF_inst
其中sw_IBUF_inst的作用为输入缓冲,该缓冲的作用是限制电流的方向(其实就是一个二极管),剔除内部电路对外部的影响,和一些不必要的毛刺
同理,led_OBUF_inst作为输出缓冲使用。
在综合后,我们可以看到综合电路原理图板卡的资源使用情况:
由图中我们可以发现,该电路原理图只使用了板卡的IO资源。即上文提到的输入输出buffer,属于IO资源
在综合后,我们查看我们的设备:
发现有两处资源的点亮,放大观察:
出现了一根红色的箭头,查看其指向:
发现其由一个pad指向了另一个pad。其实G15就是我们top顶层中声明的sw端口,而M14就是led端口。
可以发现,如果要实现综合后的电路原理图,需要将这两个pad由实际的电路连接起来。但是综合后并没有连接,而是有一根红色的箭头指向。这跟红色箭头的作用实际上是一个虚拟的电路。而真实的电路必须在Run Implementation之后,才能得到。
在这里,我们需要明确Run Synthesis这一步的作用域。
1. 综合这一步的作用是将你的Rtl设计,综合成电路原理图。而这个电路原理图是理想的,其并不充分考虑由于FPGA芯片的实际物理情况,产生对应的电路。因此综合生成的电路很有可能使用的资源,要比实现后少,甚至少很多。
2.由于综合时产生的电路原理图,不考虑实现时的布局布线问题,因此决定是否能综合成功的限制条件,除了实际的代码的语法正确性外,还有在综合产生的理想电路原理图,是否会出现资源使用超出限制,以及理想电路的时序问题(千万注意是综合后的理想电路时序问题)。
3.综合产生的电路原理图,未考虑布局布线,因此除去一些io等一些特殊资源之外的其他资源时(例如lut,ram,布线资源),这些资源并不会在Device上展现出来。
因此看来,综合的作用是实现的预处理过程,其对于代码的严格程度是小于实现的。如果综合都不过,就更谈不上实现了。
四:实现
在成功综合得到理想电路原理图后,我们开始进行实现,以固定布局布线。
首先看实现后的原理图:
可以发现,实现后的原理图,与综合后的原理图没有任何区别。这是因为此次实验的工程非常简单,是pad到pad的直接连接,中间没有任何逻辑,因此实现前后原理图没有变化。但是如果资源使用较多的工程中,就会出现实现原理图和综合原理图不同的情况。
再查看Device页面:
可以看到,我们需要连接的两个pad之间,出现的一条绿线。这就是实现后的实际电路图。
继续放大SW端:
首先回顾一下在当前项目中,我们的sw端的定义:是一个开关的输入。我们知道,开关是被焊接在开发板上的。而开发板PCB的电路,又被连接在芯片的引脚上。目前我们的sw引脚,在Device页面中:
就是白色框框中的东西。而紧连着pad的,就是输入输出buffer了。为何叫输入输出buffer呢?因为在一个引脚,未定义其功能前,你不会知道它是用作输入还是输出。
现在好了,我们将他用作开关,是我们这个系统的输入。因此,我们配置其为输入buffer。放大来看看其结构:
这玩意有四个输入,一个输出。其中输入端口的PAD,就是直连我们的芯片外部引脚PAD的。那剩下的三个输入又是干什么的呢?
首先看INTERMDISABLE和BUFDISABLED:
这两个输入的连接线,连到了Site之外,连到了我们的布线资源之上
这就代表着,我们内部的逻辑,能与这两个输入交互。也就是说我们的逻辑,能够控制这两个输入的值是1还是0。
在xilinx 的官方文档 《ug471_7Series_SelectIO》中,有这样一段描述:
如果启用该原语,则会关闭输入缓冲,并将输出端口O的电平设置为逻辑高电平。如果没有启用该原语时,则IBUFDISABLE端口自动接地,并且我们可以不关心这个端口的值。这个特性/端口启用时,当当前的IO处于空闲状态时,我们可以减少芯片的功耗.
关于INTERMDISABLE,作用与IBUFDISABLE类似,都是用来降低芯片功耗的。其详细描述在下图中给出。
接下来,我们观察DIFFI_IN接口:
可以看到,DIFFI_IN接口的连接线,连接到了SIT H15上,而H15也是IO。再观察H15的DIFFI_IN接口,其连接到了G15上。
所以G15和H15可以作为一对差分输入的引脚使用。当我们配置G15和H15作为一对差分引脚时,我们可以选择G15或H15的任意一个输入缓冲资源,将双端口的差分输入,转换为单端口内部信号使用。
接下来,是iodelayctrl资源
iodelayctrl是用来调整IO输入输出延迟的(IO输入输出相位调整),延迟数量级为ps,以下是一些关于该资源的解释文档
对Xilinx FPGA的IDELAY的理解_xilinx idelay_君子爱财好色的博客-CSDN博客
目前我们的实验并未使用输入输出延迟,所以绿色的布局线只是通过它,而未作延迟。它也属于IO资源
接下来,就是一堆布线资源了
这几个内部有斜线的黑色框框,都是布线资源中的内部互联资源
接下来 ,又是一个iodelayctr资源:
最后就到我们的输出buffer和输出pad了:
观察输出的buf:
这个buf,除了in和out外,还带了一个tri输入。它是一个三态门。当我们使用inout时,就会启用这个输入,来控制这个pad的输入输出模式转变。
五:总结
本次实验,通过开关点亮小灯这个实验,初步了解了vivado工程的结构。以及FPGA是如何实现这些功能的。其中重点查看了综合后的原理图,和实现后的真实的布局布线。
其中:
1. 对于一个pad,我们可以用作输入,也可以用作输出。当用作输入时,会启用如下图的资源:
而作为输出时,会启用如下资源:
当我们用作inout时,就需要pad中的这三兄弟通力合作了:
而当我们用两个pad作为差分输入时,两个pad会通过内部线路,连接到其中一个pad的输入buf上:
2. 对于输入到输出,我们经历了这样一个过程:
输入pad -> IBUF -> idelayctrl -> 内部线路互联资源*N -> odelayctrl -> OBUF -> 输出pad
由于我们此次实验简单,内部没有逻辑运算资源和存储资源参与,因此在更大型的项目中,输入到输出的过程是这样的:
输入pad -> IBUF -> idelayctrl -> 内部线路互联资源*A+逻辑资源*B+存储资源*C -> odelayctrl -> OBUF -> 输出pad
如此看来,想在开发板上通过开关控制一个led灯,也是不容易的😂