ZYNQ7020芯片要发挥双处理器的协同作用,就要PS通过AXI总线来动态控制PL。要实现这个功能,就要创建一个IP核,PS端通过对寄存器地址的读写来实现对PL的控制。本实验采用米尔科技的Z-TURN(MYS-7Z020)开发板,控制三色灯 D34实现PS端占空比动态可调的PWM呼吸灯。
1 新建一个 Vivado 工程,命名为custom_pwm_ip,芯片选择:
2 添加 PS 的 IP 核并配置
点击这个 Add IP 添加 IP 核
输入 zynq,然后双击添加 zynq 核
双击 ZYNQ 核导入配置文件
这里导入的是custom_pwm_ip.tcl配置文件,可使用官方提供的axi_gpio.tcl 配置文件(重命名即可)。
3 创建自定义 IP
1) 点击菜单“Tools->Create and Package IP...”
2) 选择“Next”
3) 选择创建一个新的 AXI4 设备
4) 名称填写“ax_pwm” ,描述填写“alinx pwm”,然后选择一个合适的位置用来放 IP(默认位置即可,名称和描述可以根据自己的需要来改写,这里直接使用了alinx的项目命名)
5) 下面参数可以指定接口类型、寄存器数量等,这里不需要修改,使用 AXI Lite Slave 接口, 4
个寄存器。
6) 点击“Finish”完成 IP 的创建
7) 在“IP Catalog”中可以看到刚才创建的 IP
8) 这个时候的 IP 只有简单的寄存器读写功能,我们需要修改 IP,选择 IP,右键“Edit in IP
Packager
9) 这是弹出一个对话框,可以填写工程名称和路径,这里默认,点击“OK”
10) Vivado 打开了一个新的工程
11) 添加 PWM 功能的核心代码
12) 添加代码时选择复制代码到 IP 目录
13) 修改“ax_pwm_v1_0.v”,添加一个 pwm 输出端口
14) 修改“ax_pwm_v1_0.v”,在例化“ax_pwm_V1_0_S00_AXI” ,中添加 pwm 端口的例化
15) 修改“ax_pwm_v1_0_s00_AXI.v”文件,添加 pwm 端口,这个文件是实现 AXI4 Lite Slave 的
核心代码
16) 修改“ax_pwm_v1_0_s00_AXI.v”文件,例化 pwm 核心功能代码,将寄存器 slv_reg0 和 slv_reg1用于 pwm 模块的参数控制。
17) 双击“component.xml”文件
18) 在“File Groups”选项中点击“Merge changers from File Groups Wizard”
19) 在“Customization Parameters”选项中点击“Merge changes form Customization Parameters
Wizard
20) 点击“Re-Package IP”完成 IP 的修改
4 添加自定义 IP 到工程
1) 搜索“pwm”,添加“ax_pwm_v1.0
2) 点击“Run Connection Automation”
3) 导出 pwm 端口
最后的Diagram如下图所示: 4) 保存设计,并 Generate Output Products
5) 添加 xdc 文件分配管脚,把 pwm_0 输出端口分配给三色灯的一个Pin脚,做一个呼吸灯
(三色灯 D34对应的三个Pin脚:R14、Y16、Y17)
- set_property IOSTANDARD LVCMOS33 [get_ports pwm_0]
- set_property PACKAGE_PIN Y16 [get_ports pwm_0]
6) 编译生成 bit 文件,导出硬件
5 启动 SDK, 新建 fsbl
点击菜单栏上的 File->Launch SDK->OK 启动 SDK
点击 File->Application Project 新建工程
输入工程名为 fsbl
选择 Zynq FSBL
生成的 fsbl 如下图所示
6 新建一个 custom_pwm_ip 工程
点击 File->Application Project 新建工程
输入工程名 custom_pwm_ip(注意:Board Support Package选择:Use existing fsbl_bsp)
选择 hello_world 工程模板
新建 custom_pwm_ip工程完成后, 如下图所示
先看看 APP 的目录下的资源,可以找到一个 ax_pwm.h 的文件,这个文件里包含
里对自定义 IP 寄存器的读写宏定义
在 bsp 里找到“xparameters.h”文件,这个非常重要的文件,里面找到了自定 IP 的寄存器
基地址,可以找到自定义 IP 的基地址。
有个寄存器读写宏和自定义 IP 的基地址,我们开始编写代码,测试自定义 IP,我们先通过
写寄存器 AX_PWM_S00_AXI_SLV_REG0_OFFSET,控制 PWM 输出频率,然后通过写寄存器
AX_PWM_S00_AXI_SLV_REG1_OFFSET 控制 PWM 输出的占空比。
- #include <stdio.h>
- #include "platform.h"
- #include "xil_printf.h"
- #include "ax_pwm.h"
- #include "xil_io.h"
- #include "xparameters.h"
- #include "sleep.h"
-
- unsigned int duty;
-
- int main()
- {
- init_platform();
-
- print("Hello World\n\r");
-
- //pwm out period = frequency(pwm_out) * (2^N) / frequency(clk);
- AX_PWM_mWriteReg(XPAR_AX_PWM_0_S00_AXI_BASEADDR, AX_PWM_S00_AXI_SLV_REG0_OFFSET, 17179);//200hz
- //duty = (2^N) * (1 - (duty cycle)) - 1
- while (1) {
- for (duty = 0x8fffffff; duty < 0xffffffff; duty = duty + 100000) {
- AX_PWM_mWriteReg(XPAR_AX_PWM_0_S00_AXI_BASEADDR, AX_PWM_S00_AXI_SLV_REG1_OFFSET, duty);
- usleep(100);
- }
- }
-
- cleanup_platform();
- return 0;
- }
7 生成 BOOT.bin 文件
右击 custom_pwm_ip ->Create boot Image
点击 Create Image, 生成 BOOT.bin 启动文件
将这个 BOOT.bin 文件拷贝到 TF 卡
开发板打到 SD 卡启动模式, JP2 闭合、 JP1 断开
程序运行后可以看到三色灯 D34 会不停闪烁
按开发板的 RESET 复位按键可以看到串口打印 Hello World