《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​
  95kVyaJuybju 2023年11月02日 97 0

自定义IP核-呼吸灯实验​

在Vivado软件中,我们可以很方便的通过创建和封装IP向导的方式来自定义IP核。自定义IP核可以定制化系统设计,以达到设计重用的目的,可以很大程度上简化系统设计和缩短产品上市的时间。本章我们将向大家介绍自定义IP核的方法。

本章包括以下几个部分:

  1. 简介
  2. 实验任务
  3. 硬件设计
  4. 软件设计
  5. 下载验证



简介

Xilinx官方为我们提供了非常丰富的IP核,如数学运算(乘法器、浮点运算器等)、信号处理(FFT、DDS等),我们可以通过调用这些IP核来快速完成设计。然而随着系统的设计越来越复杂,官方提供的免费IP核有时并不能很好的适用我们的设计,这个时候就需要我们自己来实现这些功能。为了使这些模块或代码以后能够复用,可以通过自定义IP核的方式将这些模块集成到Vivado中的IP库中,以达到简化系统设计和缩短产品上市时间的目的。

在Vivado软件中,通过创建和封装IP向导的方式来自定义IP核,支持将当前工程、工程中的模块或者指定文件目录封装成IP核,当然也可以创建一个带有AXI4接口的IP核,用于PS和PL的数据通信。本次实验选择常用的方式,即创建一个带有AXI接口的IP核,该IP核通过AXI协议实现PS和PL的数据通信。AXI协议是一种高性能、高带宽、低延迟的片内总线,关于该协议的详细内容,我们会在后面的例程中向大家做详细的介绍。本次实验的系统框图如错误!未找到引用源。所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义


6.1.1系统框图

框图中的UART用于打印信息,Breath LED IP核为自定义的IP核,PS通过AXI接口为LED IP模块发送配置数据,从而来控制PL LED灯。

实验任务

本章的实验任务是通过自定义一个LED IP核,来控制PL LED呈现呼吸灯的效果,并且PS可以通过AXI接口来控制呼吸灯的开关和呼吸的频率。

硬件设计

step1:创建一个新的IP

1-1 打开Vivado,进入Vivado界面后,点击“Tasks”栏中的“Manage IP”。在弹出的选项中选择“New IP Location...”。如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_02


6.3.1点击Manage IP

1-2 在弹出的界面中选择“Next”,然后设置Manage IP核的属性,在“IP Location:”一栏指定工程的路径,路径为:F:/ZYNQ / Embedded_System/custom_ip,其它保持默认即可。点击“Finish”完成Manage IP工程的创建,如错误!未找到引用源。6.3.3所示。注意,Part一栏中设置开发板的型号,在后面的工程中会重新指定,这里直接保持默认。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_03


6.3.2自定义IP核向导界面

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_04


6.3.3 IP设置选项

点击“Finish完成工程的创建。

1-3工程创建完成后,运行创建和封装IP向导。点击菜单栏的“Tools”,选择“Create and Package New IP”,在弹出的界面中,点击“NEXT”。如错误!未找到引用源。4 和错误!未找到引用源。5所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_05


6.3.4选择创建和封装IP向导

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_06


6.3.5封装IP向导界面

1-4 接下来选择封装IP或者创建一个带AXI4接口的IP核,我们这里选择创建一个带AXI接口的IP核,选中“Creat a new AXI4 peripheral”,并点击“NEXT”按钮。如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_07


6.3.6封装IP选项

1-5 接下来分别设置IP核名称(Name)、版本号(Version)、显示名(Display name)、描述(Description)和路径(IP location)。在Name一栏设置IP核的名称,本次实验的功能是控制PL LED呈现呼吸灯的效果,因此这里在Name一栏,将名称改为“breath_led_ip”,此时Display name一栏会自动更改为“breath_led_ip_v1.0”。其它的设置直接保持默认即可,点击“NEXT”按钮,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_08


6.3.7 IP参数设置

1-6 接下来对AXI接口进行设置。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_09


6.3.8 AXI4接口设置

Name(名称):这里修改成S0_AXI

Interface Tpye(接口类型):共三种接口类型可选,分别是Lite、Full和Stream。AXI4-Lite接口是简化AXI4接口用于较少数据量的存储映射通信;AXI4-Full接口是高性能存储映射接口,用于较多数据量的存储映射通信;AXI4-Stream用于速数据流传输,非存储映射接口。本次实验只需少量数据的通信,因此接口类型选择默认的Lite接口。

Interface Mode(接口模式):接口模式有Slave(从机)和Master(主机)两种模式可选,AXI协议是主机和从机通过“握手”的方式建立连接,这里选择默认的Slave接口模式。

Data Width(数据宽度):数据位宽保持默认,即32位位宽。

Memory Size(存储器大小):在AXI4-Lite接口模式下,该选项不可设置。

Number of Registers(寄存器数量):用于配置PL LED呼吸灯寄存器的数量,这里保持默认。

点击“Next”按钮。

1-7 最后弹出封装接口的总结描述和下一步操作选项的界面。这里保持默认,即将IP添加至IP库中,点击“Finish”按钮完成IP核的创建和封装。如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_10


6.3.9创建和封装IP核总结界面

在IP Catalog界面中可以看到刚刚添加的IP核,位于User Repository一栏中的AXI Peripheral下,名称为“breath_led_ip_v1.0”,如错误!未找到引用源。10所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_11


6.3.10新添加的IP

1-8 创建好IP核后,我们接下来对breath_led_ip_v1.0 IP核进行编辑。右击breath_led_ip_v1.0 IP核,选择“Edit in IP Packager”,在弹出的界面中点击“OK”,如图6.3.11和图6.3.12所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_12


6.3.11打开编辑IP核界面

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_13


6.3.12设置工程名和路径

此时会打开一个新的工程,如图6.3.13所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_14


6.3.13编辑IP核界面

1-9 双击breath_led_ip_v1_0,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_15


6.3.14双击breath_led_ip_v1_0

打开breath_led_ip_v1_0.v文件后,接下来开始编辑代码,来添加控制PL LED呼吸灯所需要的参数和端口信号。在代码的第7行添加如下代码:

parameter START_FREQ_STEP = 10'd100,

这个参数用于设置呼吸灯默认的呼吸频率,然后在代码的第18行添加如下代码:

output led,

添加完成后的代码如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_16


6.3.15编辑breath_led_ip_v1_0.v文件

在代码例化breath_led_ip_v1_0_S0_AXI模块的地方,增加对参数START_FREQ_STEP和端口led的例化,代码如下:

.START_FREQ_STEP(START_FREQ_STEP),

.led(led),

代码添加后,按下键盘键Ctrl+S保存。如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_17


6.3.16添加对参数和端口的例化

1-10 双击breath_led_ip_v1_0下的breath_led_ip_v1_0_S0_AXI_inst,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_18


6.3.17双击breath_led_ip_v1_0_S0_AXI_inst

breath_led_ip_v1_0_S0_AXI模块实现了AXI4协议的读写寄存器的功能,我们只需要对该模块稍作修改,即可实现控制PL LED呼吸灯的功能。向寄存器中写入数据和读出数据的部分代码如6.3.18和6.3.19所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_19


6.3.18写寄存器数据部分代码

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_20


6.3.19读寄存器数据部分代码

在创建和封装IP核向导中,我们总共定义了4个寄存器,代码中的slv_reg0至slv_reg3是寄存器地址0至寄存器地址3对应的数据,通过例化呼吸灯模块,将寄存器地址对应的数据和呼吸灯模块的控制端口相连接,即可实现对呼吸灯的控制。

我们接下来开始编辑代码,同样在代码的第7行添加如下代码:

parameter START_FREQ_STEP = 10'd100,

在代码的第18行添加如下代码:

output led,

添加完成后的代码如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_21


6.3.20编辑breath_led_ip_v1_0_S0_AXI.v文件

同时我们还需要在代码的第401行例化breath_led.v文件,代码如下:

breath_led #(​
.START_FREQ_STEP(START_FREQ_STEP)​
)​
u_breath_led(​
.sys_clk (S_AXI_ACLK),​
.sys_rst_n (S_AXI_ARESETN),​
.sw_ctrl (slv_reg0[0]),​
.set_en (slv_reg1[31]),​
.set_freq_step (slv_reg1[9:0]),​
.led (led)​
);

代码中的slv_reg0和slv_reg1是寄存器地址0和寄存器地址1对应的数据,我们通过寄存器地址0对应的数据来控制呼吸灯的使能(sw_ctrl),寄存器地址1对应数据的最高位控制呼吸灯频率的设置有效信号(set_en),寄存器地址1对应数据的低10位控制呼吸灯频率的步长(set_freq_step)。

添加完代码后,按下键盘Ctrl+S保存代码,添加完成后的代码如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_22


6.3.21例化breath_led代码

1-11 此时工程中缺失breath_led.v文件,breath_led.v文件用于实现呼吸灯的功能,这个代码是在“呼吸灯实验”的基础上修改而来。

右击“Design Sources”,选择“Add Sources…”,在弹出的界面中选择“Add or Create design source”,点击“NEXT”,如6.3.22和6.3.23所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_23


6.3.22添加设计文件

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_24


6.3.23选择添加设计文件界面

点击“Create File”创建一个新的文件,在弹出的界面输入名称breath_led,路径为../custom_ip/ip_repo/breath_led_ip_1.0/hdl,点击“OK”按钮,如图6.3.24和图6.3.25所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_25


6.3.24创建一个新的设计文件

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_26


6.3.25设置设计文件的名称与路径

点击“Finish”按钮完成创建,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_27


6.3.26完成设计文件的添加

在弹出的模块定义界面中点击“OK”按钮,接下来在弹出的确认按钮中点击“YES”。

1-12 双击u_breath_led(breath_led.v)文件,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_28


6.3.27双击breath_led.v文件

打开breath_led.v文件后,开始编辑代码,代码如下:

1 module breath_led(​
2 input sys_clk , //时钟信号​
3 input sys_rst_n , //复位信号​
4 input sw_ctrl , //呼吸灯开关控制信号 1:亮 0:灭​
5 input set_en , //设置呼吸灯频率设置使能信号​
6 input [9:0] set_freq_step , //设置呼吸灯频率变化步长​
7 ​
8 output led //LED​
9 );​
10 ​
11 //*****************************************************​
12 //** main code​
13 //*****************************************************​
14 ​
15 //parameter define​
16 parameter START_FREQ_STEP = 10'd100; //设置频率步长初始值​
17 ​
18 //reg define​
19 reg [15:0] period_cnt ; //周期计数器​
20 reg [9:0] freq_step ; //呼吸灯频率间隔步长​
21 reg [15:0] duty_cycle ; //设置高电平占空比的计数点​
22 reg inc_dec_flag; //用于表示高电平占空比的计数值,是递增还是递减​
23 //为1时表示占空比递减,为0时表示占空比递增​
24 //wire define​
25 wire led_t ;​
26 ​
27 //将周期信号计数值与占空比计数值进行比较,以输出驱动led的PWM信号​
28 assign led_t = ( period_cnt <= duty_cycle ) ? 1'b1 : 1'b0 ;​
29 assign led = led_t & sw_ctrl;​
30 ​
31 //周期信号计数器在0-50_000之间计数​
32 always @ (posedge sys_clk) begin​
33 if (!sys_rst_n)​
34 period_cnt <= 16'd0;​
35 else if(!sw_ctrl)​
36 period_cnt <= 16'd0;​
37 else if( period_cnt == 16'd50_000 )​
38 period_cnt <= 16'd0;​
39 else​
40 period_cnt <= period_cnt + 16'd1;​
41 end​
42 ​
43 //设置频率间隔​
44 always @(posedge sys_clk) begin​
45 if(!sys_rst_n)​
46 freq_step <= START_FREQ_STEP;​
47 else if(set_en) begin​
48 if(set_freq_step == 0)​
49 freq_step <= 10'd1;​
50 else if(set_freq_step >= 10'd1_000)​
51 freq_step <= 10'd1_000;​
52 else ​
53 freq_step <= set_freq_step;​
54 end ​
55 end​
56 ​
57 //设定高电平占空比的计数值​
58 always @(posedge sys_clk) begin​
59 if (sys_rst_n == 1'b0) begin​
60 duty_cycle <= 16'd0;​
61 inc_dec_flag <= 1'b0;​
62 end ​
63 else if(!sw_ctrl) begin //呼吸灯开关关闭时,信号清零​
64 duty_cycle <= 16'd0;​
65 inc_dec_flag <= 1'b0;​
66 end ​
67 //每次计数完了一个周期,就调节占空比计数值​
68 else if( period_cnt == 16'd50_000 ) begin​
69 if( inc_dec_flag ) begin //占空比递减​
70 if( duty_cycle == 16'd0 ) ​
71 inc_dec_flag <= 1'b0;​
72 else if(duty_cycle < freq_step)​
73 duty_cycle <= 16'd0;​
74 else ​
75 duty_cycle <= duty_cycle - freq_step;​
76 end​
77 else begin //占空比递增​
78 if( duty_cycle >= 16'd50_000 ) ​
79 inc_dec_flag <= 1'b1;​
80 else​
81 duty_cycle <= duty_cycle + freq_step;​
82 end ​
83 end ​
84 else //未计数完一个周期时,占空比保持不变​
85 duty_cycle <= duty_cycle ;​
86 end​
87 ​
88 endmodule

模块实现了呼吸灯的功能。呼吸灯的使能由输入的端口信号sw_ctrl控制,呼吸灯的呼吸频率由输入的端口信号set_enset_freq_step控制。由代码的第43行至第55行代码可知,输入的set_freq_step范围是1~1000

1-13 保存代码,并验证代码是否有语法错误。在左侧Flow Navigator导航栏中找到SYNTHESIS,点击该选项中的 “Run Synthesis”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_29


6.3.28编译代码

在弹出的窗口中点击“OK”按钮,等待代码编译完成。

1-14 接下来开始设置IP封装,将界面切换至Package IP,如果不小心关闭的话,可以通过IP-XACT界面下的component.xml重新打开,如图:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_30


6.3.29打开Package IP界面

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_31


6.3.30 Package IP界面

Identification这一栏的选项直接保持默认,需要注意的是,我们可以点击6.3.31中Categories选项下的“+”按钮来修改IP的分类,这里不做修改。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_32


6.3.31修改IP核分类

1-15点击Compatibility,修改该IP核支持的器件。点击Family一栏下的“+”图标,选择“Add Family Explicitly…”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_33


6.3.32“Compatibility界面”

这里勾选“zynq”和“zynquplus两项,表示该IP核支持ZYNQ和ZYNQ MPSOC器件。而Life-cycle表明该IP核当前的产品生命周期,这里选择“Pre-Production”。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_34


6.3.33选择支持的器件

1-16 点击File Groups,然后点击界面上的“Merge Changes from File Groups Wizard”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_35


6.3.34 File Groups界面

此时可以在Verilog Synthesis一栏中查看工程中的三个模块。

1-17 点击Customization Parameters,点击界面上的“Merge Changes from Customization Parameters Wizard”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_36


6.3.35 Customization Parameters界面

此时多了Hidden Parameters一栏,展开这个界面,可以看到程序中自定义的参数START_FREQ_STEP,右击这个参数,选择“Edit Parameter…”,弹出编辑参数的界面,如图6.3.36所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_37


6.3.36打开编辑参数界面

在弹出的页面中勾选“Visible in Customization GUI”,将此参数显示在GUI参数界面中;

Format格式改为“long”;

勾选“Specify Range”来设定此参数的范围。将Type改为“Range of integers”,Minimum的值改为1,Maximum的值改为1000,将Default Value的值改为100,点击“OK”按钮,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_38


6.3.37参数设置

1-18 点击“Customization GUI”,可以在“Layout”界面拖动Page 0下的参数来调整参数在GUI显示的位置,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_39


6.3.38拖动参数

1-19 点击“Review and Package”,然后点击“IP has been modified”更新总结界面,最后点击“Re-Package IP”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_40


6.3.39 Review and Package界面

接下来会弹出一个是否关闭工程的询问界面,点击“YES”关闭工程,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_41


6.3.40关闭工程询问界面

IP核封装完成后,在IP核所在路径(...\custom_ip\ip_repo\breath_led_ip_1.0\drivers\breath_led_ip_v1_0\src)目录下,Vivado软件会自动生成.c和.h文件,方便在VITIS软件中对IP核进行操作,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_42


6.3.41软件生成的文件

在Manage IP工程界面下,点击菜单栏的“File”,选择“Close Project”关闭工程,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_43


6.3.42关闭工程

接下来在弹出的确认关闭界面选择“YES”确认关闭工程。

step2:创建 Vivado 工程

step1是创建了一个自定义的IP核,接下来我们来创建Vivado工程,工程名为user_led,路径为F:/ZYNQ/Embedded_System/custom_ip目录下,创建的步骤这里不再赘述。

在开始下一个步骤之前,我们先把步骤1自定义的IP核添加至本工程的IP库中,点击菜单栏的“Tools”,选择“Setting”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_44


6.3.43打开设置界面

点击“IP”一栏下的“Repository”,然后点击“+”来添加自定义的IP核,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_45


6.3.44 IP库添加界面

接下来会弹出添加自定义IP核的路径,选择../custom_ip/ip_repo/breath_led_ip_1.0,点击“Select”,在弹出的界面中可以看到识别到的IP核,点击“OK”按钮添加IP核,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_46


6.3.45 添加IP

最后点击“OK”按钮,完成IP核的添加,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_47


6.3.46 添加IP核完成

step3:使用IP Integrator创建Processing System

3-1 在左侧导航栏(Flow Navigator)中,单击IP Integrator下的Create Block Design。然
后在弹出的对话框中指定所创建的Block Design的名称,这里使用默认的“design_1”

3-2在Diagram窗口中给设计添加 IP。点击图中加号“+”,会打开IP目录(IP Catalog)。在搜索栏中键入“zynq”,找到并双击“ZYNQ Ultrascale+ MPSoC”,将MPSOC处理系统IP添加到设计中,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_48


6.3.47 添加MPSOC IP

3-3 添加完成后,ZYNQ Ultrascale+ MPSoC模块出现在Diagram中,双击这个模块进入编辑界面。需要注意的是,和前面搭建嵌入式最小系统不同的是,我们保留了pl_clk0、pl_resetn0、maxihpm0_lpd_aclk和 M_AXI_HPM0_LPD接口,只是添加了UART控制器(MIO42和MIO43),修改Bank电压和修改DDR4控制器,其它保持默认。配置完成后,框图如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_49


6.3.48 MPSOC框图

3-4 接下来添加Breath LED IP核,点击“+”图标,在搜索框中输入“led”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_50


6.3.49 添加Breath LED IP

双击“breath_led_ip_v1.0”,添加此IP核。添加完成后,可以双击led IP核来设置参数,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_51


6.3.50 Breath led IP核配置

从上图可以看到我们自定义的参数(Start Freq Step)和其它四个参数,这里不作修改,点击“Cancel”按钮。

接下来点击“Run Connection Automation”来自动连线,在弹出的窗口中勾选All Automation,然后点击OK,连线完成后如6.3.51所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_52


6.3.51 添加Breath LED IP核并连线

3-5 此时原理图中还没有LED的引脚,右击breath_led_ip_0的led引脚,选择“Make External”,如6.3.52所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_53


6.3.52 添加LED引脚

将引出的led_0改为led,如6.3.53所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_54


6.3.53 修改引脚名称

点击“Regenerate Layout”图标,最终原理图界面如6.3.54所示,按“Ctrl + S”保存。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_55


6.3.54 最终原理图界面

step4:生成顶层HDL模块

4-1 在Sources窗口中,选中Design Sources下的design_1.bd这就是我们刚刚完成的Block Design设计右键点击design_1.bd,在弹出的菜单栏中选择“Generate Output Products”,等待Generate完成

4-2 在Sources窗口中,右键点击design_1.bd,在弹出的菜单栏中选择“Create HDL Wrapper”

step5:生成Bitstream文件并导出Hardware

5-1 在左侧Flow Navigator导航栏中找到RTL ANALYSIS,点击该选项中的Open Elaborated Design。在弹出的对话框中点击OK”。如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_56


6.3.55 Elaborated Design对话框

在ELABORATED DESIGN界面下方找到I/O Ports一栏。如果没有找到则通过在菜单栏中点击Layout,然后在下拉列表中选择I/O Planning。我们将在I/O Ports一栏对PL部分的接口进行管脚分配,led分配至BANK43的AE10引脚,该BANK的供电电压为3.3V,因此I/O Std一列对应的电平也需要修改。如图6.3.56所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_57


6.3.56 管脚分配

5-2 设置完成后按快捷Ctrl+S保存管脚约束,在弹出的对话框输入文件名“user_led,如图6.3.57所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_58


6.3.57 保存约束

5-3 在左侧Flow Navigator导航栏中找到PROGRAM AND DEBUG,点击该选项中的“Generate Bitstream”。在连续弹出的对话框中依次点击“YES”、“OK”。然后Vivado工具开始依次对设计进行综合、实现、并生成Bitstream文件。

5-4 导出硬件

在菜单栏中选择File > Export > Export hardware。在弹出的对话框中,勾选“Include bitstream”,然后点击“OK”按钮。 如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_59


6.3.58 勾选“Include bitstream

5-5 新建vitis文件夹,将xsa文件拷贝到里面。

5-6选择菜单 Vitis。在弹出的界面中,指定路径到..\custom_ip\user_led\vitis下,点击“Launch”,打开Vitis软件。

软件设计

在硬件设计的最后,我们打开了Vitis开发环境。

step6:在Vitis中创建应用工程

6-1 在菜单栏中选择File->New->Application Project新建一个应用工程。

6-2 在弹出的界面中工程名命名为user_led,点击“NEXT”,添加硬件平台文件,然后点击“NEXT”,在弹出的页面中保持默认设置,然后点击“NEXT”,接下来选择“Empty Application”,点击“Finish”按钮完成Vitis应用工程的创建。

6-3 新建源文件。在user_led/src目录上右键,选择 New->Source File,6.4.1所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_IP_60


6.4.1 新建源文件

在弹出的对话框中File name一栏我们输入文件名“main.c”,然后点击“Finish”。

6-4 新建源文件之后,在左侧user_led/src目录下可以看到main.c文件,同时在主页面
已经打开了该文件的文本编辑框。我们在新建的main.c文件中输入以下代码:

1 #include "stdio.h"​
2 #include "xparameters.h"​
3 #include "xil_printf.h"​
4 #include "breath_led_ip.h"​
5 #include "xil_io.h"​
6 #include "sleep.h"​
7 ​
8 #define LED_IP_BASEADDR XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP基地址​
9 #define LED_IP_REG0 BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //LED IP寄存器地址0​
10 #define LED_IP_REG1 BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //LED IP寄存器地址1​
11 ​
12 //main函数​
13 int main()​
14 {​
15 int freq_flag; //定义频率状态,用于循环改变呼吸灯的呼吸频率​
16 int led_state; //定义LED灯的状态​
17 ​
18 xil_printf("LED User IP Test!\n\r");​
19 while(1){​
20 //根据freq_flag的标志位,切换呼吸灯的频率​
21 if(freq_flag == 0){​
22 BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x800000ef);​
23 freq_flag = 1;​
24 }​
25 else{​
26 BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x8000002f);​
27 freq_flag = 0;​
28 }​
29 //获取LED当前开关状态 1:打开 0:关闭​
30 led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);​
31 //如果开关关闭,打开呼吸灯​
32 if(led_state == 0){​
33 BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 1);​
34 xil_printf("Breath LED ON\n\r");​
35 }​
36 sleep(5);​
37 //获取LED当前开关状态 1:打开 0:关闭​
38 led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);​
39 //如果开关打开,关闭呼吸灯​
40 if(led_state == 1){​
41 BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 0);​
42 xil_printf("Breath LED OFF\n\r");​
43 }​
44 sleep(1);​
45 }​
46 }​
47

在代码的第8行至第10行,我们对Breath LED IP基地址、寄存器地址0和寄存器地址1进行了宏定义。按住Ctrl键不放将鼠标移动到这些参数上,单击鼠标左键,会自动跳转到定义这些参数的地方。其中BREATH LED IP寄存器地址0和寄存器地址1位于breath_led_ip.h文件内,这个文件是系统自动为我们生成的。

程序中的main函数实现了每6秒钟(点亮5秒+关闭1秒)打开和关闭LED呼吸灯的开关,并切换LED灯呼吸频率的功能。我们通过BREATH_LED_IP_mReadReg()函数来读取寄存器地址的数据,通过BREATH_LED_IP_mWriteReg()函数来写入寄存器地址的数据,这两个函数同样位于breath_led_ip.h文件中。

在硬件设计的自定义IP核部分中,我们例化breath_led代码的时候,将寄存器0的数据(slv_reg0)连接至呼吸灯的开关控制信号(sw_ctrl),寄存器1的数据高位(slv_reg1[31])连接至呼吸灯频率设置使能信号(set_en),寄存器1的数据低位(slv_reg1[9:0])连接至呼吸灯频率间隔设置(set_freq_step)。因此,在Vitis应用程序中,可以很方便的通过Breath LED IP寄存器地址0和寄存器地址1来控制LED呼吸灯的开关和频率。

值得一提的是,在Vitis中添加导出的硬件平台文件后,自定义IP核的库函数也会导入进来,而这个库函数是在自定义IP核时,由Vivado软件自动生成的,6.4.2所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_寄存器_61


6.4.2 Breath LED IP库函数

保存main.c文件,然后编译工程。软件设计部分到这里就完成了。

下载验证

首先我将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接然后使用USB连接线将USB_UART(开发板右上角PS PORT)接口与电脑连接,用于口通信。最后连接开发板的电源,给开发板上电。

step7:板级验证

7-1打开Vitis Terminal终端,设置连接串口。

7-2下载程序在应用工程user_led上右击,选择“Run As”,然后选择第一项“1 Launch on Hardware (System Debugger)”。软件程序下载完成后,在下方的Terminal中可以看到应用程序打印的信息如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_62


6.5.1 Terminal窗口打印字符

此时观察开发板可以发现,开发板上的PL_LED16秒钟LED灯的呼吸频率切换一次,在此切换频率之前,LED灯会熄灭一秒钟。如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第六章 自定义IP核-呼吸灯实验​_自定义_63


6.5.2 开发板实验现象


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  Vn37uiKQIsdv   2023年12月06日   23   0   0 网络层链路IP
  tprTMCWDkFAR   2023年12月06日   36   0   0 用户名APIIP
95kVyaJuybju