Xilinx Zynq系列是带有ARM Cortex-A系列CPU核的FPGA,前几年流落到二手市场上的“矿板”就以Zynq 7010为核心,可以说是最廉价的Zynq实验平台了。淘个这样的板子,再另外找个Xilinx的JTAG就可以玩FPGA和ARM Linux. 因为玩的人多,网上有资料,还有别人做过的扩展板可以参考。本坛大佬们早就玩过了。我三年前就买了一块,但一直是闲置状态,直到现在才想来搞搞。
这块EBAZ4025板子接上12V电源就可以工作了,有RJ45网口,板子上有焊盘可以自己焊上TF卡座、UART接口、JTAG口,就相当于一个完整的ARM Linux板子(板载DDR3 SDRAM 256MB,NAND Flash 128MB),还有若干FPGA I/O引出来到双列排针座,方便自己分配用途。
EBAZ4025通电以后上面的Linux就启动了,通过UART连接可以看到uboot和Linux输出的信息。我是要把它作为FPGA开发来用的,所以先直接焊上JTAG排针连接调试器,电脑软件可以识别到JTAG 扫描链上有两个设备,一个是FPGA,一个是ARM CPU。
Zynq的内部分为两个系统,一个叫PS,就是ARM CPU以及外设,包括DDR内存控制器、DMA等等这些ARM运行依赖的部件;另一个系统叫PL,就相当于传统的FPGA. 这两部分之间有很多种方式可以通信,就可以比结合FPGA和ARM的各自优点来处理复杂的任务了。
Zynq 7000系列的IO引脚也分为PS和PL各自管理的的,PS部分引脚有固定的用途,和开发FPGA时写引脚约束不同。根据矿板的电路图了解到,两个LED是连接到PL部分的,而UART直接接的是PS的MIO。
学习Zynq的开发可以参考网上的教程。这玩意门槛稍微高一点,先得下载Vivado安装,为了开发ARM的程序还要安装SDK,都是很庞大的软件。如果熟悉了的话Vivado操作起来也很快,但头几次么……
先创建一个工程,选择器件型号,这和其它FPGA开发思路是一样的。
按照教程,然后是Create Block Design
添加IP——ZYNQ7 Processing System. 这种图形化的block design方式我最初学FPGA的时候就用,直观容易理解。
加上这个IP之后框图上就出现了一个模块,代表PS部分。
在图上双击这个ZYNQ Processing System模块,就打开配置窗口,进行时钟、IO、内存等设置了。这些需要根据矿板上的资源和连接关系来定。
首先这里有个PS部分的结构图,可以了解有那些片上外设可以供CPU用的。第一个实验为了让程序能打印输出,需要用UART。
看看时钟配置,默认的输入时钟33.333MHz 和矿板一致,就不用调整了。CPU和DDR的时钟频率用默认的不会有问题。PS部分给PL部分提供的时钟是实验需要的,默认输出一个50MHz。
DDR的配置,需要根据实际板子上的芯片调整一下,128M x16-bit. 我不确定SDK编写的程序是要在DDR内存中运行还是PS的片上RAM中运行,所以DDR还是要配置的。
MIO的配置,是为了要给UART分配引脚。根据电路图,UART是连接在A16和F15这两个脚的,查Xilinx手册得知是PS_MIO24和PS_MIO25,就在MIO Configuration中配置使用UART1(因为UART0没有MIO 24,25的映射)。
配置好之后Run Block Automation,自动生成必要的接口。
教程上说配置好之后要连一根线,把FCLK_CLK0和M_AXI_GP0_ACLK连起来。前者是Zynq PS输出的时钟(内部PLL从晶振给的时钟生成,可以给PL用),后者我理解是AXI总线的时钟。这里并不使用总线,我觉得不连也没关系。
接下来,按照教程说的是要Create HDL Wrapper,注意对话框中选择允许用户修改,不然自己编辑的会被覆盖掉。
做这一步的目的是把PS外面再包上一层,这样就方便加入自己编写的逻辑了。下面我要编写一点逻辑来点LED,就直接加到 system_wrapper.v 里面去。
注意Create HDL Wrapper之后,系统的层次结构变化了,顶层名称从design_1变成了design_1_wrapper。
由于矿板的PL是没有带晶振的(有空焊盘没装),要看FPGA跑起来的效果需要外接时钟信号到排针上面。实际在已经创建的PS模块上,FCLK_CLK0就是一个时钟信号,现在我要把它给PL用,还需要创建一个port把它引出来,不然顶层看不到。
在图上创建输出port, 命名叫PS_CLK0, 连接到时钟信号上。保存之后,design_1.v文件(自动生成的)并没有体现新的输出端口。于是我尝试一下“Generate Block Design”操作,看看是否更新。
结果这样是能重新产生design_1.v的:
然后我就在顶层的design_1_wrapper.v里面加自己的东西了:先加上两个输出口给矿板上的红绿LED。
再写一个计数器,利用PS引出的时钟计数,让LED能闪起来。
这样第一个实验工程的逻辑就设计完了,可以进行FPGA综合、实现和生成二进制码的流程了。
这里还缺少一件事情:矿板上的 LED6 (W13, W14引脚)是连接在FPGA IO上的,不是PS MIO,因此是像普通FPGA那样分配引脚的方式。而DDR、MIO则是固定引脚,不需要自己选。假如LED是接在MIO上,那么我们就要用软件去选择GPIO访问来点亮了,不属于FPGA逻辑部分。
在综合之后,可以查看design,然后手工分配LED使用的引脚。也可以直接写一个约束文件(.xdc)把引脚约束用Tcl命令写上去。
在最后Generate bitstream 生成bit文件之前看一下报告,确认引脚的分配是生效了的。
最后得到了.bit文件,就可以连接好JTAG之后,打开Hardware Manager, 将生成的design_1_wrapper.bit下载到FPGA中了。这个操作和Xilinx Spartan/Artix系列是相似的。
若此时看到了LED闪烁,说明PL部分的逻辑是工作的了。
此外,下载bit文件之后,从UART终端看到的Linux打印信息还在活动,说明PL部分的重配置没有影响PS的运行。关于PL和PS的关系我的了解还不够多。
如果单纯把Zynq当成FPGA来用,不使用PS部分,也是可以的。注意,这样也就不能用PS提供的时钟了,需要从PL的引脚输入时钟信号。开发工具用Vivado和ISE都可以,我另外进行过尝试。
推荐阅读