之前点亮的LED灯都是通过PL资源来点亮,也就是通过FPGA的逻辑去点亮LED灯,这一个工程将尝试第一次调用ZYNQ的PS资源,去实现一个点LED灯的操作,由于板子上的LED资源是连接到PL端的,所以这里做了个联动,用PS的资源去点亮PL端的LED灯
(这种方式会占用PL的资源,一般推荐用EMIO的方式 ,会更节省资源)
本文在 vivado2018.3版本上 演示, 其他版本请自行研究
1创建Vivado工程
1) 具体步骤 新建一个VIVADO 工程,打开软件 选中Create Project, 如下图所示
2)点击NEXT ,在出现的第二个对话框“Project name”中输入工程名;在“Project location”中选择保存路径;勾选“Create project subdirectory”,最后点击“Next” 备注,所有的路径均不能出现中文名称
3)点击 RTL PROJECT 选项,点击NEXT
4) 第四步Add Sources 选项直接留空,NEXT
5)第五步Add Constraints 选项直接留空,NEXT
6)选择芯片型号 (板子生产了多个芯片型号,请根据自己板子的型号来进行选择,下图以XA7Z020来进行演示,其余型号自行选择,必须要按照实际型号去填写)
- XA7Z020 (直接选择xc7z020CLG400-1,因为系统识别到的是xc7z020-1)
- XC7Z010-1 (xc7z010CLG400-1) (7010 芯片)
- XC7Z020-1 (xc7z020CLG400-1) 后续生产
- XC7Z020-2 (xc7z020CLG400-2) 后续生产
备注 (7020 车规级版在vivado2018.3识别出的是xc7z020,如果工程选择xa7z020 ,在SDK环境下有时候会弹出警告,所以这里直接选择Xc7z020CLG400-1)
7)确认所选信息 点击“Finish”,完成vivado的工程创建
2 创建一个BLOCK设计
1)IP INTEGRATOR→Create Block Design,在弹出的对话框中输入设计名,最后点击“OK”,如下图所示
2)在右侧的窗口里 ,点击加号,在选择框里搜索ZYNQ,并找到ZYNQ7 PROCESSING SYSTEM ,双击并打开
3)软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
4)依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K256M16RE-125,数据位宽选择16bit 最后点击“OK”,如下图所示。
最后 点击“Run Block Automation”如下图所示。在弹出的选项中保持默认,点击“OK”,即可完成对ZYNQ7 Processing System的配置
5)再用同样的方法增加GPIO资源 点击加号,在设置里搜索GPIO并添加,然后双击并打开生成的GPIO资源进行设置
6)在GPIO的设置栏里将输入输出属性改成全部输出ALL Outputs ,因为我们板子上只有2个LED灯,所以将GPIO Width位宽设置成2位,点击OK
7)点击 上方的Run Connection Automation ,并将GPIO 和S_AXI前面的勾都选中,如下图所示 点击OK
8)软件将自动帮我们完整所有必要的连线,以及添加必要的模块
9)在框图中双击GPIO输出的管脚,并重新命名为LED,方便后面软件编程
10)source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示。
在弹出的对话框里保持默认
软件自动为我们生成HDL文件
3.创建约束文件,并且定义管脚
1)Add Source → Add or create constraints 点Next
因为这个项目没有创建过约束文件 所以这里创建一个约束文件,并在File name 里设置约束文件的名称,并且点击FINISH 完成约束文件的创建
2)Sources → Constraints 里找到刚才创建的约束文件 双击并打开该XDC约束文件
在约束文件里面复制下面代码来对输出的GPIO进行管脚(所有的管脚转接板上丝印都有实际标注对应的IO)
set_property IOSTANDARD LVCMOS33 [get_ports LED_tri_o[0]] set_property IOSTANDARD LVCMOS33 [get_ports LED_tri_o[1]] set_property PACKAGE_PIN K16 [get_ports LED_tri_o[0]] set_property PACKAGE_PIN J16 [get_ports LED_tri_o[1]]
4.生成bit文件
按下绿色箭头对工程进行编译
按下Generate Bitstream 完成综合以及生成bit文件
5.SDK程序编写
1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
系统将自动打开SDK开发环境
3)新建一个工程 file→new→Application Project,来新建一个“Application Project”,如下图所示。
4)在新建工程名中输入自己的工程名称,点击NEXT
5)选择空工程,点击完成FINISH
6)选择创建的LED_CODE_bsp → system.mss → axi_gpio_0 gpio → import Examples
7)选择 xgpio_example
8)这样系统就自动创建了一个参考例程
备注,可以直接下载参考设计 看效果,也可以参考代码 加入到自己的 main里。 这里我们选择直接下载参考代码看效果
6.下载到板子上进行验证
选中工程中的硬件平台,并点击右键→Program FPGA,在弹出的对话框中选择默认,点击“program”,完成FPGA PL部分的Program工作
2)选中我们生成的GPIO工程 展开绿色箭头(RUN)右边的图标,选择Run As→1 Launch on Hardware(System Debugger)
可以看到板子上的LED1灯在闪烁
备注 :如果 RUN 的时候弹出错误 可以按照下面的操作 进行设置 再进行DEBUG
之后点 APPLY 然后 再选择Run As→1 Launch on Hardware(System Debugger)看是否下载成功
代码解读
XGpio_SetDataDirection 设置GPIO为输入/输出
XGpio_DiscreteWrite 置位GPIO
XGpio_DiscreteClear 拉低GPIO
#define LED 0x01
继续看代码,LED在代码中的定义为 0X01 即代表 LED 在LED_CHANNEL中代表最低位 BIT0
看懂了上面这些 就很容易看懂程序里的代码
XGpio_DiscreteClear(&Gpio, LED_CHANNEL, LED); 代表拉低GPIO LED_CHANNEL中的 第0位
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, LED); 代表拉高GPIO LED_CHANNEL中的 第0位
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, ~LED); 设置为输出模式
for (Delay = 0; Delay < LED_DELAY; Delay++); 这是一个耗费系统资源的delay函数的简写
所以整个程序的效果就是LED 1 不停的点亮熄灭,反复循环。
如果想要将1个灯改成2个灯 只需要将
#define LED 0x01 更改为 #define LED 0x03即可, 07代表 0000_0111即使 bit0 bit1 bit2都置1, 修改之后 3个灯就能同步进行变换了
看懂这些 可以自己创建一个main函数 然后在里面参考这个例子写驱动LED的代码(本文中介绍一下如果利用参考设计来创建工程)
完整工程如下:(板子有多个版本,请按照对应板子的芯片型号进行下载测试)
以下网站是我自己整理的MIO EMIO AXIGPIO的不同点,有兴趣的可以看一下, 另外想了解EMIO去驱动GPIO的可以看下一个工程(工程7)
http://www.hellofpga.com/index.php/2021/08/08/zynq_emio_mio_axi_gpio/