《LabVIEW ZYNQ FPGA宝典》第6章>>实验5:PS(ARM)端Linux RT读取PL端FPGA引脚电平(读取捕捉PL端FPGA相连的按键状态)

1、实验内容

        从本节实验开始,我们将向大家讲解如何使用LabVIEW开发同时ZYNQ芯片里面的PS端ARM和PL端FPGA程序,早在前面第五章入门实验里面,我们就已经向大家介绍了如果让PS端的Linux RT控制PL端FPGA引脚输出控制LED灯,相当于Host主机(PS端)控制Slave从机(PL端),二者之间走的通信桥梁是Reg寄存器,所以用的通道方向就是“PS2PL_Reg”,相当于下行。

        本节实验,我们要演示一下如何将PL端FPGA引脚状态传递给PS端ARM,也就是Slave从机(PL端FPGA)将布尔类型的开关量传递给Host主机端(PS端ARM),利用的寄存器通道是“PL2PS_Reg”,相当于上行。

        如果用户是跳着看书的,建议本书第五章是一定要看的,里面有很多概念、基础和开发流程都讲的很详细。对于这些低速的状态量,比如开关信号、通断信号、触发信号、使能信号等都可以借助我们给用户封装的寄存器Reg通断来实现。

        注意:跟前面实验3和实验4里面的纯PS(ARM)端寄存器不一样,这里提到的Reg寄存器通道是指ZYNQ PS端与PL端交互的桥梁,所以后面编程环节里面可以看到函数选板里面的Reg名称都有PS2PL或者PL2PS的前缀,来表达当前这个寄存器的数据传输方向,包括后续我们用到的Memory存储器传输通道、FIFO、DMA等都是分方向的,就跟我们Pro5宝典里面讲解的PCIe双向传输通道一样,相当于全双工通信。

2、实验目标

        本节实验我们先利用LabVIEW编写一个读取PL端FPGA引脚上3个KEY按键状态的FPGA程序,再编写一个可以读取PL端FPGA通过寄存器发送过来的按键状态的Linux RT程序;接着把写好的PL端FPGA程序框图编译成bit文件,再将Linux RT程序编译部署下载到ZYNQ芯片的PS端ARM里面去运行,利用LabVIEW Linux RT动态加载前面编译好的PL端FPGA bit文件,然后接上Xilinx JTAG下载器,就可以在线观察到FPGA VI前面板上的控件运行效果了;同时也可以利用Linux RT应用程序自身就有的在线前面板交互式运行功能,观察PL端FPGA传递过来的按键状态信息;最后着重复习并熟练掌握ZYNQ芯片PS(ARM)端LabVIEW Linux RT程序开发和PL端FPGA程序开发的过程和原理。

3、硬件介绍

        本节实验需要用到正点原子领航者ZYNQ开发板,Xilinx JTAG下载器和一根千兆网线。其中,Xilinx JTAG下载器可以用来在线观察ZYNQ芯片PL端的FPGA VI前面板实际运行效果;网线是用来将上位机编写好的ZYNQ PS(ARM)端Linux RT程序通过网络方式部署下载到ZYNQ PS端ARM里面去运行。提醒:这里的Xilinx JTAG下载器不需要下载PL端FPGA bit文件,因为,PS端可以动态加载编译好的FPGA bit文件,所以如果大家不准备观察FPGA VI前面板上的控件状态,实际上这个Xilinx JTAG下载器也可以不用接。

        原子领航者ZYNQ底板上有3个挂在PL端FPGA上的端物理按键,标识分别是“PL_RESET”、“PL_KEY0”和“PL_KEY1”,位于板子右下中部,如图5-1所示。这3个物理按键是原子为了展示PL端FPGA强大灵活的可编程引脚专门预留的。

图5-1:正点原子领航者ZYNQ开发板上挂在PL端FPGA上的3个物理按键

        提醒1其实从7系列(Artix7、Kintex7、Virtex7、KU、KU+、VU、VU+、ZYNQ)FPGA开始,就没有像传统单片机、ARM、DSP这类MCU所谓的RESET复位引脚了,所以很多厂家板子上预留的FPGA复位引脚本质上其实就是一个普通的IO引脚,没有任何实际意义,不管你按不按都不会起任何作用;但是之前的6系列FPGA比如Spartan6上面是有一个专门的Prog复位引脚,这个引脚的作用可以复位FPGA芯片重新加载Flash里面的bit文件,但是7系列FPGA包括ZYNQ里面的PL部分都没有这种功能的复位引脚了,因为FPGA不需要复位,它永远都不会死机,除非芯片坏了,只要FPGA芯片不坏,程序可以万年不变,这就是为什么FPGA芯片的可靠性和稳定性要远强于市面上任何MCU的原因。

        提醒2但是需要注意的是,ZYNQ芯片里面PS端ARM部分是有一个专门的复位引脚,它可以用来复位ARM部分,但是无法复位PL端FPGA部分,即使你的ARM程序重启了,FPGA部分照样运行的还是之前的bit文件,除非人为重新动态加载FPGA bit才能更新FPGA里面的程序。这个PS端ARM复位引脚一般都会引出来连到一个按钮上,比如,原子将这个PS端复位按键放在了ZYNQ核心板上,标识是“PS_RESET”,如图5-2所示。

图5-2:可以控制ZYNQ芯片PS端ARM芯片复位的引脚

4、原理图介绍

        正点原子ZYNQ领航者底板上挂在PL端的3个开关按键(PL_RESET、PL_KEY0和PL_KEY1)对应的FPGA引脚原理图,可以看出,这3个按键分别与ZYNQ芯片PL端的“N16、L14、K16”这3个引脚相连,如图5-4所示。请记住这3个PL端的FPGA引脚名称,后面我们用LabVIEW编写PL端FPGA VI程序的时候,需要调用这3个引脚。

图5-3:原子ZYNQ底板上的3个PL端按键对应的FPGA引脚原理图(N16、L14、K16)

5、驱动VI函数讲解

5.1:PL端FPGA Reg寄存器通道函数

        由于本节实验,我们只需要将PL端FPGA里面读到的引脚电平状态通过寄存器通道传递给PS端ARM部分就可以了,对于这类开关量,只需要利用ZYNQ FPGA终端里面的 “PS_System_Reg Data”这个Socket CLIP里面的3个PS_Reg寄存器通道就可以了,如图5-4所示。由于开关量可以用Bool类型表示,并且是PL端FPGA将信息传递给PS端ARM,所以我们可以借助PS_Reg寄存器PL2PS上行通道里面的32路Bool类型里面的任意3路就可以了,具体过程,我们在后续ZYNQ PL端FPGA VI编写环节再给大家讲解。

图5-4:ZYNQ PL端FPGA终端里面的PSPL之间的Reg寄存器桥梁通道(PL2PS)

5.2:PS(ARM)端Linux RT驱动函数选板

        正式开始采用LabVIEW编写ZYNQ PS端Linux RT 读取PL端FPGA里面的寄存器数据之前,我们先来了解一下本节实验要用到的Linux RT下的寄存器通道驱动VI函数功能。

        为了方便用户使用,我们提前将底层负责PS端与PL端沟通的寄存器通道函数封装到LabVIEW Linux RT环境下的“PowerGod-RIO-RT”选板里面,变成一个个图标,一目了然。

        要完成本节实验,我们需要用到4个函数选板,分别是“PS_Load_FPGA_bit”、“PS_Load_KO”、“PS_Reg_Address”和“PS_PL_Reg”,如图5-5所示。

图5-5:本节实验要用到的神电测控“PowerGod-RIO-RT”里面的4个函数选板

        下面,我们分别介绍一下这4个选板里面的VI功能和应用场合。

        1)由于本节需要访问ZYNQ芯片PL端FPGA部分的引脚,所以需要编写FPGA VI编译生成bit文件,然后由PS端Linux RT程序动态加载到ZYNQ芯片里面运行,所以Linux RT程序运行时的第一个VI就是“PS_Load_FPGA_bit.vi”这个函数。凡是需要调用ZYNQ芯片里面PL端FPGA参与的程序,都需要调用这个FPGA bit文件动态加载函数,切记!

        2)为了提高ZYNQ芯片PS端的内存使用率,我们将很多外设KO驱动做成了动态加载和卸载。比如本节实验,我们需要读取PL端FPGA里面的寄存器,这个寄存器本质上也属于通用IO,也就是GPIO类,所以在Linux RT程序初始化之前,我们需要利用下面图5-6里面的GPIO动态加载Load_GPIO_KO函数(PSLoadGPIOKO(SubVI).vi)加载GPIO驱动,等到Linux RT程序停止退出之前,再调用Unload_GPIO_KO卸载函数(PSUnloadGPIOKO(SubVI).vi)卸载GPIO驱动以便释放GPIO类占用的内存和资源。

图5-6:GPIO类外设驱动动态加载和卸载函数

        3)本节实验的重点就是要学会使用PS端和PL端之间的寄存器通道,因此,PS端少不了要对Reg寄存器初始化打开,等到Linux RT程序退出的时候,再关闭Reg寄存器,这两个VI函数就位于下图5-7所示的“PS_Reg_Address”寄存器函数选板里面。至于下图中间的两个PS端寄存器读写VI,本节实验用不到,因为负责与PL端进行沟通的Reg寄存器读写函数我们单独进行了封装,参考下面的第4)部分内容。

图5-7:ZYNQ芯片PS端ARM寄存器操作函数

        注意:只要是对PS端外设进行操作的场合,都需要调用上面“PS_Reg_Address”函数选板里面的第1个和第4个VI,也就是“PS_reg_Open”和“PS_Reg_Close”,相当于对寄存器函数的初始化和程序退出前的寄存器关闭,至于中间的Reg寄存器读写两个VI,可以根据实际情况选择,后续为了简化编程,我们对很多外设寄存器进行了二次封装,只需要调用相应的函数即可。

        4)为了让ZYNQ PS端ARM能够访问PL端FPGA里面的寄存器,我们特地在PS端Linux RT下封装了两个读写函数,分别是“PL_Reg_Write.vi”和“PL_Reg_Read.vi”,位于“PS2PL_Reg_Data”函数选板里面,如图5-8所示。其中,左侧的“PL_Reg_Write.vi”函数顾名思义,就是PS2PL下行通道,Linux RT程序可以通过这个VI将PS端的数据写入PL端FPGA里面;反之,右侧的“PL_Reg_Read.vi”函数则是PL2PS上行通道,也就是Linux RT可以利用这个函数读取到PL端FPGA里面的寄存器数值。

图5-8:负责PS端与PL端二者之间通信的Reg寄存器通道读写VI函数

        提醒:为了更好的区分ZYNQ芯片里面PS端和PL端的VI函数,我们特地在每个子VI图标里面加入了PS或者PL字样,如图5-9所示。如果这个子VI有PS字样,那么这个VI就可以被Linux RT主机端也就是PS端调用,反之如果是PL端字样,那就是被FPGA VI调用。

图5-9:子VI图标上有PS和PL字样(用于区分该VI是运行在PS端Linux RT里面还是在PL端FPGA里面)

6、ZYNQ程序开发讲解(PL(FPGA)+PS(ARM))

6.1:ZYNQ PL端FPGA程序开发过程

6.1.1:新建或者打开已有的LabVIEW ZYNQ PL FPGA终端

        1)前面第五章里面我们已经新建过了一个LabVIEW ZYNQ FPGA终端了,这里不再重复创建了,不记得的用户可以回顾一下前面第五章5.3.1节里面的相关内容。

        2)打开之前新建的项目浏览器“My_FPGA_Stater_Board_ZYNQ7020_PS+PL.lvproj”,如图5-10所示,可以看到该项目里面有两个终端分别是ZYNQ的PL端FPGA部分和PS端Linux RT部分。

图5-10:打开前面新建好的LabVIEW项目浏览器(My_FPGA_Stater_Board_ZYNQ7020_PS+PL.lvproj)

图5-11:右击FPGA终端新建一个虚拟文件夹

图5-12:将虚拟文件夹重命名为“实验5-读取FPGA按键状态(ZYNQ PL端)”

        2)右击虚拟文件夹“实验5-读取FPGA按键状态(ZYNQ PL端)”,选择“New/新建>>VI”,如图5-13所示;然后保存该VI,命名为“实验5-读取FPGA按键状态(ZYNQ PL端).vi”,如图5-14所示。

图5-13:右击虚拟文件夹新建一个VI程序

图5-14:将VI另存为“实验5-读取FPGA按键状态(ZYNQ PL端).vi”

        3)我们要读取原子领航者ZYNQ开发板底板上的3个PL(FPGA)端KEY按键状态,首先得找出来这3个物理按键对应的PL端FPGA引脚,前面第4节原理图部分,我们已知这3个按键对应的FPGA引脚是N16、L14、K16,位于BANK35里面。接下来,我们就可以通过右击添加FPGA I/O的方式,在FPGA可用资源列表里面找到这3个PL(FPGA)端引脚对应的使能和读写EIO资源,添加到右侧的表格里面。

        4)右击“FPGA Target(My_FPGA,ZYNQ_XC7Z020_2CLG400_Navigator_MyRIO_V3_All)”或者虚拟文件夹“实验5-读取FPGA按键状态(ZYNQ PL端)”,然后选择“New/新建>>FPGA I/O”,如图5-15所示。

图5-15:新建3个FPGA I/O资源

        5)然后在弹出来的“New FPGA I/O/新建FPGA IO”表里面,找到BANK35里面的ENA和IN文件夹,展开之后再把里面的3个按键对应的FPGA引脚(N16、L14、K16)添加到右侧表格里面,最后重命名为“PL_RESET”、“PL_KEY0”和“PL_KEY1”,如图5-16所示。

图5-16:找出3个PL端物理按键对应的FPGA引脚(N16、L14、K16)

        点击“OK/确定”按钮后,即可将这3个KEY按键添加到FPGA终端里面,如图5-17所示。

图5-17:将这3个PL端用户按键对应的EIO资源添加至FPGA终端

        6)鼠标左键按住3个控制IO读写方向的ENA使能EIO节点将其拖到FPGA程序框图里面,然后右击KEY按键ENA EIO节点切换为写入模式,如图5-18所示。并给这3个ENA端口赋值为假,这样就可以将EIO节点设置成高组态,也就是读取模式了。

图5-18:将按键ENA EIO节点拖拽至程序框图并切换成写入模式

        7)然后放置一个定时循环,将上6个EIO节点全部包含进去实现循环连续控制,其中,这个定时循环的时钟一定要选择我们提前封装好的PS端CLK,如图5-19所示。提醒:这个FLCK_CLK0_PS2PL时钟大小是50MHz,是由PS端ARM产生的,路由给PL端FPGA的。

图5-19:放置一个由PS端50MHz时钟驱动的定时循环

        8)将3个ENA端口赋值为“F”,3个IN端口分别创建3个指示灯显示控件,如图5-20所示,这样后续FPGA VI编译生成bit文件运行之后,可以通过Xilinx JTAG下载器观察到前面板上的指示灯状态是否跟我们预期设计的一样。

图5-20:将ENA使能端口设置为“假”即输入模式

        9)如果PS端Linux RT想要读取到PL端FPGA这3个KEY按键状态,该怎么处理呢?其实很简单,那就是将上面的IN端口输出的电平值通过Reg寄存器通道传递给PS端ARM就可以了。具体步骤如下:

        我们可以借助封装映射到PL(FPGA)端的Reg Socket CLIP端口,只需用到里面的布尔类型的Reg上行也就是PL2PS通道就可以了。

        展开位于FPGA终端下“PS_System_Reg Data”的这个Socket CLIP,展开之后,可以看到里面封装的4对8位、4对16位、4对32位和32对Bool类型的Reg寄存器通道,每一对表达的是双向通信的意思,如图5-21所示。提醒:其中CLIP里面的端口信号名称前缀带PS2PL说明这个通道方向是由PS(ARM)发送数据给PL(FPGA),我们称之为“下行”,因为PS端一般是Host主机端,PL端一般是Slave从机;反之,如果CLIP端口前缀是PL2PS,那就是FPGA发送数据给PS(ARM),俗称“上行”。

图5-21:ZYNQ PL FPGA终端下我们封装好的双向Reg寄存器通道

        10)显然,如果PS(ARM)端要想读取PL(FPGA)端数据,肯定是上行,也就是PL端将数据发送给PS端。由于本节实验里面要读取的PL端3个KEY按键状态,属于布尔类型,因此,我们可以从FPGA终端里面的32路PL2PS方向的Bool类型随便挑选3个拖拽到FPGA程序框图里面,然后将其与FPGA里面的“PL_RESET”、“PL_KEY0”和“PL_KEY1”关联起来,比如这里,我们选择“lv_PL2PS_Reg_Bool_1”、“lv_PL2PS_Reg_Bool_2”和“lv_PL2PS_Reg_Bool_3”这3个上行寄存器通道,如图5-22所示。

图5-22:PL端FPGA通过PL2PS_Reg寄存器通道将数据传递给PS端ARM

        需要注意的是:由于这些Socket CLIP通道负责PS(ARM)与PL(FPGA)之间的交互,因此它们需要一个共同的时钟来驱动,这里我们需要用到PS端产生的内部时钟FCLK,作为FPGA里面读写Socket CLIP下所有端口信号的时钟,虽然这个FLCK时钟频率我们之前配置的也是50MHz,但是这个FCLK跟ZYNQ板子上的50MHz晶振不是一回事,切记不要弄混了。那么这个FCLK时钟实际在哪呢?就在PWM这个Socket CLIP下面“Clock lv_FCLK_CLK0_PS2PL”,如图5-23所示。

图5-23:PWM这个CLIP里面PS(ARM)端给到PL(FPGA)端的时钟FCLK

        11)最终,编写完成的ZYNQ PL端FPGA VI程序前面板,如图5-24所示。

图5-24:ZYNQ PL端按键状态捕捉FPGA VI程序前面板

6.1.3:LabVIEW ZYNQ PL端FPGA仿真、编译、下载、运行和调试

        一般情况下,为了减少FPGA VI的编译次数和提高调试效率缩短开发周期,用户可以参考下面的5个步骤进行:仿真、编译、下载、在线前面板交互式运行和调试。

6.1.3.1:LabVIEW ZYNQ PL端FPGA VI离线仿真

        1)前面我们编写好的FPGA VI程序虽然比较简单,只有1个定时循环和3个IO读取,但是在编译下载前,我们还可以借助上位机LabVIEW对其进行功能性仿真,做到心中有数。如果FPGA程序里面有复杂的算法(比如FFT)或者时序(FIFO溢出)或者第三方网表(NGC/EDF),更需要如此。如果用户对LabVIEW非常熟练精通的话,也可以跳过这个步骤,直接进入编译下载环节。

        右击FPGA终端,选择“Select Execution Mode/执行VI>>Simulation(Simulated I/O)/带仿真I/O的计算机”,如图5-25所示。一旦切换到这个模式,表明位于该ZYNQ FPGA终端项目下的所有VI都会在PC机上进行在线模拟运行。

图5-25:将VI执行模式切换到计算机仿真模式

        2)然后打开“实验5-读取FPGA按键状态(ZYNQ PL端).vi”,点击左上角的“运行”箭头按钮,如图5-26所示。此时发现这个VI运行起来了,可以看到前面板上的“Running_FPGA”显示控件里面的数值以非常快的速度在增加,说明FPGA VI程序框图里面的定时循环开始执行了,但是运行速度达不到50MHz,这是因为上位机模拟仿真只是对整个程序框图的功能性仿真,而涉及到FPGA芯片驱动时钟的速度仿真,LabVIEW无法精确模拟时钟频率,但是不影响相对时钟之间的关系和时序结果。当然,用户还可以在程序框图里面用探针去观察每条线上的数据流变化。

图5-26:FPGA VI程序快速运行起来了(功能性仿真和时序仿真)

6.1.3.2:LabVIEW ZYNQ PL端FPGA VI程序编译

        1)在计算机仿真模式下,用户无法仿真FPGA真实的I/O电平,因为仿真计算机上没有对应的物理I/O引脚。所以,我们需要将VI执行模式切换回FPGA终端运行模式。右击FPGA终端,选择“Select Execution Mode/执行VI>>FPGA Target/FPGA终端”,如图5-27所示。

图5-27:将FPGA VI执行模式切换回FPGA终端模式

        2)提醒:开始编译前的准备工作(重要步骤)

        用过NI LabVIEW FPGA的用户知道,LabVIEW FPGA默认编译出来的是NI加密过的lvbitx文件,而不是原始的FPGA bit位文件,因此,我们需要想办法将FPGA编译完成后最原始的bit文件弄出来,为此,我们专门给大家提供了一个名为“License-ID-Bitfile-ZYNQ.vi”程序,只要在FPGA VI编译过程中一直打开运行这个VI就可以得到最原始的FPGA bit位文件了。为了防止用户忘记打开运行这个VI,我们可以将这个VI提前添加到LabVIEW项目下的“我的电脑”下面,然后打开点击运行箭头即可,直如图5-28所示。

图5-28:将获取原始ZYNQ FPGA bit文件的VI(License-ID-Bitfile-ZYNQ.vi)拖拽到项目里面的“我的电脑”下面,而不是拖到FPGA终端(切记)

        然后,在LabVIEW FPGA Bit文件导出路径里面选择开发电脑存在的路径,至于导出来的FPGA bit文件名称,可以自己随意取,比如,我们将实验5编译出来的ZYNQ FPGA bit文件存放到这个目录下(E:\ZYNQ FPGA Bit Files\5-PL2PS-KEY.bit),并取名为“5-PL2PS-KEY.bit”,如图5-29所示。唯一需要注意的是:导出来的FPGA bit文件存放路径最好不放在C盘根目录下,因为很多系统的C盘根目录没有复制权限会导致保存失败,选择其他的盘符更保险。

图5-29:选择合适的路径将编译成功后的原始的ZYNQ FPGA bit文件保存下来
(这个VI一直开着运行即可)

        需要注意的是:设置的FPGA bit文件路径不能太深,而且bit文件名称里面不能有中文字符,切记,否则后续下载会失败!

        3)然后点击FPGA VI前面板上的“运行”箭头按钮,LabVIEW会启动编译服务器提示对话框,如图5-30所示。里面有3行,分别是:

  1. 本地编译服务器:顾名思义,就是调用安装在本地计算机上的Xilinx ISE或者Vivado编译器来编译这个VI。这个最为常用。
  2. 连接至网络编译服务器:这个相当于将这个VI生成的VHDL代码传送给远程服务器上的ISE或者Vivado编译器进行编译,需要用户提前配置好一台安装有Xilinx编译环境的服务器。目的是可以借助服务器强大的性能来加速编译过程,缩短编译时间。需要联网,因此,这个用的很少。
  3. 连接至LabVIEW FPGA编译云服务:这个是NI官方提供的远程服务器,需要付费才能使用,而且编译速度也没有想象中快多少,所以这个功能基本上也就是NI内部使用的多。如果用户报名参考NI FPGA认证考试或者提供购买过NI硬件产品序列号的话,NI会提供一个试用期为30天的LabVIEW FPGA编译云服务,编译速度跟本地基本一样,没有多大优势。因此,用的也很少。

图5-30:FPGA编译服务器选择提示框

        此时,先不着急点击上图里面的“OK/确定”按钮,让我看看自动产生的FPGA程序生成规范里面是不是还有什么特殊的地方需要设置。因此,这里,我们选择“Cancel/取消”按钮,如图5-31所示。

图5-31:先取消编译(因为我们要检查一下FPGA程序生成规范)

        4)展开FPGA终端里面的“Build Specifications/程序生成规范”,如图5-32所示;然后双击打开这个程序生成规范(实验5-读取FPGA按键状态(ZYNQ PL端)),将里面的一个重要选项“Run when loaded to FPGA/加载至FPGA时运行”勾选上,如图5-33,否则后续编译出来的ZYNQ FPGA bit文件下载到FPGA芯片里面是运行不了的,所以这里一定要检查一下是否打勾了。最后点击“OK/确定”关闭程序生成规范对话框。

图5-32:展开FPGA终端里面的程序生成规范,然后直接双击打开即可

图5-33:将“加载至FPGA时运行”勾选上(一定要勾上,切记!!!

        5)接下来,再次点击FPGA VI左上角的运行箭头,触发重新编译对话框,这次就可以放心点击里面的“OK/确定”按钮了,如图5-34所示;然后就会自动进入“正在生成中间文件”对话框,如图5-35和5-36所示。里面一共有5个阶段,主要就是将LabVIEW编写的FPGA VI程序框图转换为VHDL代码,然后进行压缩传递给Xilinx编译器进行编译。

图5-34:再次点击FPGA VI左上角运行箭头触发重新编译对话框(这次点击OK)

图5-35:LabVIEW FPGA VI程序框图正在生成中间VHDL文件

图5-36:正在压缩打包生成好的中间VHDL文件

        6)等待中间文件生成完毕后,LabVIEW会启动“Compilation Status/编译状态”窗口,如图5-37所示。里面一共经历5个步骤:配置、综合、布局、时钟约束、时钟布线。如果是6代FPGA,例如,Spartan6,需要经过每一步的编译,每个步骤都不能报错,否则会无法生成bit文件。但是对于7系列FPGA来说,例如ZYNQ、A7、K7、V7,如果FPGA VI里面用的是普通while循环,或者用的定时循环时钟源是默认的,那么后面两项“估计定时”和“最终定时”是不起作用的,LabVIEW会跳过检查,直接生成可以运行的原始FPGA bit文件;如果定时循环用到了创建的衍生时钟,那么最后两项定时约束还是会进行的。

图5-37:Xilinx编译器正在执行综合

        7)在“Reports/报表”的下拉列表里面选择“Configuration/配置”,可以看到配置页面里面的信息汇总,如图5-38所示。可以发现LabVIEW FPGA调用的是64位的Xilinx Vivado 2019.1这个版本的编译器,7系列FPGA只支持Vivado编译器。

图5-38:Xilinx编译器“配置”页面里面的信息汇总

      8)等待综合完成后,切换到“Estimated device utilization(synthesis)/估计设备使用(综合)”,如图5-39所示。可以看到这个VI编译后的资源预估计占用情况。

图5-39:Xilinx编译器“Synthesis/综合”页面里面的资源预估计

        9)等待转换和映射完成之后,就能在“Final device utilization(placement)/最终设备使用(布局)”页面里面,看到Xilinx编译器反馈的FPGA芯片实际资源使用情况,如图5-40所示。可以看出实际编译的结果与前面的资源预估计相差无几,这样,用户可以根据在资源预估计阶段里面的资源占用情况,来判断是否直接结束编译过程,避免浪费不必要的编译时间。例如,如果预估计的资源使用率严重超过100%的话,那么建议用户直接终止编译,返回去优化程序后再编译。

图5-40:Xilinx编译器“placement/映射”页面里面的最终资源占用结果

        10)当用户在“Status/状态”提示框里面看到“Generating programming file/正在生成编程文件”,说明LabVIEW FPGA正在生成可执行bit文件,如图5-41所示。而且到这一步的时间只花了不到3分钟,相同的代码要比之前Spartan6里面的ISE编译器快了一倍多。这也是Vivado编译器改变编译策略后的一大优势。

图5-41:Xilinx Vivado编译器正在生成可编程bit文件

        11)编译完成,会自动启动弹出“Preparing for interactive execution/准备交互式运行”提示框,但是不会像第五章那样弹出一个路径选择对话框,这是因为,前面我们将配置Xilinx JTAG下载器下载还是仿真的ini.txt文件里面的1改成0了,所以就LabVIEW就会跳过选择FPGA bit文件和下载这个过程了。接着我们到这个“License-ID-Bitfile-ZYNQ.vi”里面指定的路径下,发现了刚刚编译出来的FPGA bit文件,如图5-42所示。

图5-42:到先前设置的路径里面找到刚刚编译出来的ZYNQ FPGA bit文件

        12)如果用户的Xilinx JTAG下载器驱动没有提前安装好,或者没有接入实际的下载器跟ZYNQ开发板的话,那么过一会会弹出一个错误代码位-310601的错误提示框,如图5-43所示。错误代码的意思就是LabVIEW无法识别到Xilinx JTAG下载器通信线缆,如果大家接了Xilinx下载器和板子上电之后还出现这种错误提示,可以参考前面第三章里面的Xilinx下载器驱动安装方法,重新安装一遍驱动即可。我们这里报错是因为我们还没有将Xilinx JTAG下载器跟板子接到电脑上,故意触发这个错误提醒用户的。另外,前面我们将ini.txt里面的1改成0,所以在PS端没有动态加载这里的FPGA bit之前,在线前面板也是无法运行的,切记!!!

图5-43:弹出-310601错误(提示LabVIEW没有识别到Xilinx JTAG下载器通信线缆)

        至此,关于LabVIEW ZYNQ FPGA VI程序的编译过程就结束了,并且我们成功得到了原始的ZYNQ FPGA bit文件,这为用户产品的批量部署奠定了基础。

6.1.3.3:将Xilinx下载器跟ZYNQ开发板连到电脑上

        为了验证一下上面编译出来的ZYNQ PL端FPGA bit文件功能是否正常,我们可以将其下载到真实的ZYNQ芯片里面跑一下看看实验现象,比如本书配套的是正点原子的领航者ZYNQ开发板。由于现在验证的是PL端FPGA VI程序,所以只需要JTAG下载器跟ZYNQ板子就可以了,至于千兆网线现在接不接都行,网线在后续的PS(ARM)端Linux RT实验里面才会用到,这里暂时不需要,而且学会后续PS端Linux RT程序开发和部署之后,其实连Xilinx JTAG下载器不接都行,因为PS端可以动态加载FPGA bit文件。

        下面将Xilinx JTAG下载器跟原子领航者ZYNQ开发板连接之后接到电脑上,实物接线如图5-44所示。

图5-44:将Xilinx下载器接到ZYNQ开发板上(板子未上电)

        此时,设备管理器会自动识别加载Xilinx USB Cable驱动,如图5-45所示,如果电脑上没有出现这个设备名称,那么应该前面第三章里面的下载器驱动安装一节看漏了,回过去重新参考里面的驱动安装方法安装一遍Xilinx JTAG下载器驱动就可以了。

图5-45:设备管理器里面识别出来的Xilinx JTAG下载器名称

        然后给ZYNQ开发板上电,此时Xilinx JTAG下载器上的指示灯由黄色变成了绿色,说明我们的硬件接线和驱动基本正常了,如图5-46所示。

图5-46:FPGA板子上电之后,Xilinx JTAG下载器指示灯会变成绿色才是正常的

6.1.3.5:LabVIEW自动下载ZYNQ PL端FPGA VI程序(强烈推荐

        可以看出,上面传统的手动Vivado下载FPGA bit文件非常的不智能,每一步都需要自己手动去操作Vivado实现,对于很多不熟悉Vivado工具的用户来说,还要花时间摸索一下,那么有没有一种简便的方式来完成下载和运行调试呢?答案是肯定的!

        为了让用户能够享受到跟使用NI FPGA板卡一样的自动下载和交互式运行效果。我们将底层FPGA bit文件的自动下载和交互式运行全部集成到LabVIEW里面了。用户只需要点击编译好的FPGA VI左上角的运行箭头即可自动弹出选择FPGA bit文件对话框,如图5-62所示,然后在对话框里面找到这个FPGA VI对应编译出来的bit文件,然后点击“OK/确定”按钮即可进入自动下载页面,等待一会就可以看到ZYNQ PL端FPGA VI前面板活了。说明我们的自动下载和自动运行完全OK,爽!

        提醒:要想让上位机LabVIEW FPGA VI通过Xilinx JTAG下载器自动下载bit文件,需要将ini.txt配置文件里面0改成1,如图5-63所示;如果想通过后续的PS端Linux RT系统动态加载FPGA bit文件的话,这里的下载步骤可以忽略,同时ini.txt文件里面的1要改成0

图5-62:运行FPGA VI会弹出FPGA bit文件选择对话框

图5-63:要想通过Xilinx JTAG下载器自动下载FPGA bit文件,ini文件改成1

6.1.3.6:LabVIEW ZYNQ PL端FPGA程序运行与在线调试(在线前面板交互式运行,直观方便)

        1)当FPGA VI编译出来的FPGA bit文件自动下载到ZYNQ芯片里面运行之后,此时,可以看到位于开发电脑上的这个ZYNQ PL端FPGA VI(实验5-读取FPGA按键状态(ZYNQ PL端).vi)前面板自动活了,也就是自动进入在线前面板交互式运行模式了,可以观察到FPGA VI前面板上的“PL_RESET”、“PL_KEY0”和“PL_KEY1”这3个状态指示灯全部点亮了,如图5-64所示。这是因为,原子在设计物理按键原理图的时候,为了防止噪声输入,默认3个FPGA引脚都是上拉处理的,也就是默认高电平。并且,定时循环的迭代值“Running_FPGA”显示控件里面的数值则是按照50MHz的速度递增,所以一瞬间就到了最大值,如图5-65所示。

图5-64:FPGA VI自动进入在线前面板交互式运行(3个按键松开状态默认上拉高电平)

图5-65:FPGA VI定时循环迭代值瞬间就到了最大值

        2)如果我们同时按下ZYNQ开发板底板上的3个PL端按键,如图5-66所示;此时,FPGA VI前面板上的3个指示灯全部熄灭了,如图5-67所示,这是因为按键按下的时候,对应的FPGA引脚会短接到GND,也就是低电平,所以指示灯熄灭了。

图5-66:同时按下ZYNQ开发板底板上的3个PL端按键

图5-67:ZYNQ PL端FPGA VI前面板上的3个指示灯全部熄灭了

        结论:说明我们设计的FPGA VI功能没有问题,同时也能看出,在不需要编写LabVIEW上位机的情况下,我们就能借助FPGA VI的在线前面板交互式运行方式快速的观察和控制我们的FPGA VI程序,不需要反复去编译这个FPGA VI,从而可以大幅减少FPGA程序开发调试的时间,降低开发调试成本,提高了调试效率,真正做到了降本增效。     

        提醒:接下来我们会在PS(ARM)端Linux RT里面编写LabVIEW程序来读取PL端FPGA传递过来的按键状态信息。

6.2:ZYNQ PS(ARM)端Linux RT程序开发过程

6.2.0:编程思路(PS端Linux RT)

        要想在ZYNQ芯片PS端Linux RT程序里面读取PL端FPGA通过寄存器通道发送过来的数据或者状态信息,必须按照下面的流程至少调用6个VI函数,调用次序如下,后面Linux RT程序编写就是参考这个流程来的:PS_Load_FPGA_bitàLoad_GPIO_KOàPS_Reg_OpenàPL_Reg_ReadàPS_Reg_CloseàUnload_GPIO_KO

        了解完ZYNQ芯片PS端GPIO通用类和Reg寄存器类驱动VI和操作流程后,接下来,我们就可以利用LabVIEW编写一个Linux RT程序读取PL端FPGA寄存器数值了,然后下载到ZYNQ PS端ARM里面去捕捉ZYNQ底板上的3个PL端物理按键状态了。

6.2.1:新建或者打开已有的LabVIEW ZYNQ Linux RT项目

  打开前面第五章我们新建好的LabVIEW ZYNQ项目(My_FPGA_Stater_Board_ZYNQ7020_PS+PL.lvproj),这个项目前面我们在编写ZYNQ PL端FPGA程序时已经打开过了,如图5-68所示。

图5-68:打开前面我们创建好的同时包含ZYNQ PS(ARM)端和PL(FPGA)端的LabVIEW ZYNQ项目

        由于前面FPGA VI已经编写完成了,并且生成了可用的FPGA bit文件,这里为了截图不至于过大,我们暂且先将FPGA Target终端收起来,如图5-69所示。

图5-69:将My FPGA终端暂时收起来(因为前面FPGA VI已经编写好了)

6.2.2:编写LabVIEW Linux RT应用程序(读取PL端FPGA寄存器关联的按键状态)

        1)右击Linux RT终端(ZYNQ7020_PS_Linux_RT)选择“New/新建”一个“Virtual Folder/虚拟文件夹”,如图5-70所示。将其重命名为“实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端)”,如图5-71所示,以示分类管理好区分。

图5-70:右击Linux RT终端选择新建一个虚拟文件夹

图5-71:将刚刚新建出来的虚拟文件夹重命名为“实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端)”

        2)接着,右击刚刚创建的虚拟文件夹“实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端)”选择“New/新建”一个VI程序,如图5-72所示,然后将这个VI另存为“实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端).vi”,如图5-73所示。

图5-72:右击虚拟文件夹新建一个VI

图5-73:将新建出来的VI保存并重命名为“实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端).vi”

        3)打开这个新建的VI,将前面第5.2节“PowerGod-RIO-RT”函数选板里面的6个子VI函数拖拽到程序框图里面,然后按照6.2.0节里面的步骤进行排序串联,最后在前面板上创建相应的控件,即可完成本节PS端读取PL端FPGA寄存器数值的程序,最终形成完整的Linux RT程序框图,如图5-74所示,提醒:看不清的用户可以缩放一下pdf,因为这里贴的程序框图是直接复制的LabVIEW原始矢量图,不是截图。

图5-74:完整的ZYNQ PS(ARM)端读取PL端FPGA寄存器数值的Linux RT程序框图

        提醒:我们将ZYNQ PL端32个布尔类型的寄存器做成了下拉枚举形式,这样大家就能直接根据PL端FPGA里面使用的寄存器通道,在PS端Linux RT程序框图的下拉列表里相应的选择一下即可。比如前面ZYNQ PL端FPGA VI里面我们放置的是PL2PS_Reg的前3个通道,因此这里PS端下拉列表也需要选择一下“PL2PS_Reg_Bool_1”、“PL2PS_Reg_Bool_2”、“PL2PS_Reg_Bool_3” 这3个通道。

        4)ZYNQ PS端读取PL端FPGA布尔类型寄存器通道数据的Linux RT应用程序前面板,如图5-75所示。用户可以按压ZYNQ底板上挂在PL端的3个物理按键,在PS端Linux RT程序前面板上观察这3个按键的电平状态。

图5-75:ZYNQ PS端读取PL端FPGA布尔类型寄存器的Linux RT应用程序前面板

        提醒:ZYNQ PS端Linux RT程序前面板上有一个FPGA bit文件加载路径,这个路径“/home/lvuser/natinst/bin/data/”是LabVIEW在Linux RT系统下的默认路径,如果用户自己编译出来的FPGA bit文件名称跟我们的不一样,只需要将路径里面最后的bit文件名称替换一下即可,前面的默认路径最好不要动。

7、硬件接线实物图

        提醒:由于本节实验用到了ZYNQ PL端FPGA部分,前面也编写好了FPGA VI程序,如果用户想在线观察ZYNQ PL端FPGA VI前面板实际运行情况,可以将Xilinx JTAG下载器接到ZYNQ开发板上;反之,如果不想观察FPGA VI的在线前面板交互式运行,这里也可以不用接下载器,因为PL端的FPGA bit文件可以通过PS端来动态加载,不需要通过下载器下载都行。

        对于ZYNQ PS端Linux RT程序的部署和下载,则需要一根CAT5+或者CAT6类千兆网线或者通过WiFi无线部署(参考第6章实验2),然后将ZYNQ开发板跟上位机开发电脑互联起来即可,上位机开发电脑通过网线和Xilinx JTAG下载器与正点原子ZYNQ开发板之间的硬件接线实物图,如图5-76所示。

图5-76:完整的硬件接线实物图(千兆网线接到PS端网口里面)

8、程序编译下载

8.1:准备工作(将前面编译好的PL端FPGA bit文件添加到PS端)

        由于本节实验用到了ZYNQ芯片PL端FPGA部分,为了让PS端Linux RT程序可以动态加载PL端的FPGA bit文件,我们需要将前面编译好的FPGA bit文件添加到ZYNQ PS端Linux RT终端里面来,步骤如下。

        右击ZYNQ PS端Linux RT终端下的“ZYNQ PL FPGA bit files”,选择“Add/添加>>File/文件”,如图5-77所示;然后在弹出来的文件选择对话框里面找到前面编译出来的PL端FPGA bit文件,如图5-78所示;添加成功后的效果如图5-79所示。

图5-77:右击Linux RT终端选择添加FPGA bit文件

图5-78:选择前面编译出来的PL端FPGA bit文件

图5-79:FPGA bit文件添加成功后的效果

8.2:ZYNQ PS端Linux RT应用程序编译、部署、下载

        1)由于ZYNQ开发板与上位机电脑之间是通过网线直连的,中间没有经过路由器,所以,上位机要利用ZYNQ PS端Linux RT默认的静态IP地址:192.168.2.99来部署下载上位机写好的Linux RT程序,因此,上位机网卡IP地址也要设置成同一个网段,比如192.168.2.10,如图5-80所示。

图5-80:将上位机开发电脑网卡IP地址设置成跟下位机ZYNQ里面的eth0:1虚拟网卡静态IP地址在同一个网段内

        2)然后检查一下LabVIEW ZYNQ PS端Linux RT终端里面的IP地址是否为下位机ZYNQ里面的固定IP地址(192.168.2.99),如果不是,则右击终端选择“Properties/属性”,如图5-81所示;再在属性设置页面里面修改一下即可,如图5-82所示。

图5-81:如果IP地址不一样的话,可以右击LabVIEW Linux RT终端选择属性

图5-82:在Linux RT属性配置里面将IP地址改成ZYNQ直连方式下的固定静态IP地址

        3)右击ZYNQ PS端Linux RT终端(ZYNQ7020_PS_Linux_RT)选择“Connect/连接”,如图5-83所示;不出意外的话,会弹出来一个“Deployment Progress”部署成功的提示框,如图5-84所示;最后点击一下“Close/关闭”该对话框即可,此时,可以看到LabVIEW Linux RT终端左下角的指示灯点亮了,如图5-85所示,表明上位机Linux RT终端与下位机ZYNQ板子通过网线建立起了连接。

图5-83:右击LabVIEW Linux RT终端(ZYNQ7020_PS_Linux_RT)选择“Connect/连接”

图5-84:弹出一个部署进度与部署成功的提示框(Close即可)

图5-85:连接成功后Linux RT终端logo图标指示灯会点亮

        4)右击Linux RT终端(ZYNQ7020_PS_Linux_RT)里面的程序生成规范,选择“New/新建”一个“Real-Time Application/实时应用程序”,如图5-86所示;然后在弹出来的RT应用程序属性配置页面里面,将程序生成规范重命名为“实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端)”,如图5-87所示;再选择左侧目录里面的“Source Files/源文件”里面的本节实验5编写的VI程序(实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端).vi)添加到右侧的“Startup Vis/启动VIs”列表里面,如图5-88所示;最后将中间文件夹“ZYNQ PL FPGA bit files”里面的FPGA bit文件(5-PL2PS-KEY.bit)作为附件添加到右下方的“Always Included/总是包含”里面,如图5-89所示。

图5-86:右击Linux RT终端下的程序生成规范新建一个RT应用程序规范

图5-87:将新建出来的Linux RT应用程序生成规范重命名以示区分

       图5-88:将源文件里面的本节实验5编写的Linux RT VI添加到右侧启动VIs列表里面

图5-89:将前面编译好的PL端FPGA bit文件添加到右侧“Always Included/总是包含”

        提醒:所有非LabVIEW静态调用的文件都可以放到这个“Always Included/总是包含”里面,这样后续部署下载的时候,上位机LabVIEW会把这些文件自动通过网络下载到下位机ZYNQ Linux RT系统里面去,免去了手动拷贝,简单实用可靠。

        5)接下来,右击刚刚创建的实验5对应的RT应用程序生成规范,选择“Build/编译”,如图5-90所示;大概几秒钟就能编译完成,并且会有一个编译成功的提示框,如图5-91所示;点击“Done/完成”按钮退出这个提示框,再右击实验5程序生成规范,选择“Deploy/部署”将刚刚编译出来的Startup.rtexe以及FPGA bit文件全部部署下载到ZYNQ板子里面去,如图5-92所示;一切顺利的话,会有一个部署进度条和部署成功的提示框出现,如图5-93所示。

图5-90:右击实验5 Linux RT应用程序生成规范进行“Build/编译”

图5-91:编译完成后会有一个编译进度条和编译成功提示框

图5-93:ZYNQ PS端Linux RT程序及其组件附件会一起部署下发到ZYNQ里面去

9、实验现象

        1)直接点击本节实验5 Linux RT程序(实验5-读取PL端FPGA寄存器映射的按键状态(ZYNQ PS端).vi)左上角的运行箭头,可以看到上位机LabVIEW会把这个VI程序及其组件、驱动和FPGA bit文件一起部署下载到ZYNQ芯片里面运行,如图5-94所示;同时PS端里面的Linux RT应用前面板活了,自动进入在线前面板交互式运行模式,此时,前面板上的“Running_PS”显示控件里面的数值开始递增,说明PS端的Linux RT程序里面的while循环开始运行起来了,如图5-95所示。

图5-94:上位机实验5对应的Linux RT程序和FPGA bit文件成功部署到了下位机ZYNQ芯片里面运行

图5-95:Running_PS显示控件数值递增,表明Linux RT程序里的while循环开始运行了

        2)为了同步观察ZYNQ PL端FPGA VI程序运行情况,我们可以借助Xilinx JTAG下载器和LabVIEW FPGA在线前面板交互式运行功能,由于PS端已经将PL端的FPGA bit加载到ZYNQ芯片里面运行了,所以这里不需要Xilinx下载器去下载FPGA bit文件了,因此,我们需要先将ini.txt文件里面的1改成0,如图5-96所示,让PL端FPGA VI直接进入在线前面板交互式运行,直接运行项目下的ZYNQ PL端My FPGA终端下的实验5这个FPGA VI,等待几秒可以看到,FPGA VI前面板活了,同时前面板上的“Running_FPGA”显示控件里面的数值变成了最大值,如图5-97,这是因为这个定时循环迭代值运行速度是50MHz,非常快。

图5-96:将Xilinx JTAG下载器配置文件ini改成0(跳过下载功能直接进入在线前面板)

图5-97:直接运行ZYNQ PL端My FPGA终端里面的FPGA VI(前面板活了)

        3)接下来,同时按下ZYNQ底板上挂在PL端的3个物理按键,如图5-98所示;此时,可以看到PL端FPGA VI前面板上的“PL_RESET”、“PL_KEY0”和“PL_KEY1”这3个指示灯全部熄灭了,如图5-99所示;同时,ZYNQ PS端Linux RT程序前面板上的“Reg_Data_Read_Bool-1”、“Reg_Data_Read_Bool-2”和“Reg_Data_Read_Bool-3”这3个指示灯也都熄灭了,如图5-100所示。说明PS端Linux RT程序读到PL端FPGA寄存器通道里面的布尔数值是“假”,根据前面介绍过的按键原理图可知,当按键按下的时候短接到GND了,所以是低电平。

图5-98:同时按下ZYNQ底板上挂在PL端FPGA上的3个物理按键

图5-99:ZYNQ PL端FPGA VI前面板上的3个指示灯全部熄灭了(接地就是低电平)

图5-100:ZYNQ PS端Linux RT程序前面板上的3个指示灯熄灭了(实时读取的寄存器)

        4)松开PL端FPGA上的3个按键,如图5-101所示,由于这3个物理按键对应的引脚默认上拉,读到的是高电平,所以PL端FPGA VI前面板和PS端Linux RT前面板上的3个按键指示灯又全部点亮了,分别如图5-102和5-103所示。

图5-101:松开ZYNQ底板上挂在PL端的3个物理按键

图5-102:ZYNQ PL端FPGA VI前面板上的3个按键指示灯全部点亮了

图5-103:ZYNQ PS端Linux RT程序前面板上的3个指示灯点亮了(上拉则是高电平)

11、实验总结

        我们总结一下本节实验学到的内容和需要注意的事项。

        本节实验我们借助布尔类型的寄存器通道实现了ZYNQ芯片内部PL端FPGA部分与PS(ARM)端Linux RT之间的通信和交互,与前面第五章开发过程类似,程序本身比较简单。但是由于涉及到利用LabVIEW同时开发ZYNQ里面的PL端与PS端部分,对于初学者来说,里面的每个步骤和操作过程都要熟练掌握,虽然都是一些基础知识,但是熟能生巧,后面的实验例程会越来越复杂,功能越来越多,希望大家都能轻松学会掌握。

        前面这几个实验相当于抛砖引玉,证明了,我们有能力搞定ZYNQ芯片内部PS端与PL端之间的通信和交互,下一个实验,我们将全方位讲解PS端与PL端进行双向通信的所有数据类型的寄存器通道,熟悉了这些寄存器通道,大家就能打通PS端与PL端之间不同位宽、不同数据类型的数据交互了。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值