6 自定义 IP 核-呼吸灯实验—PL

目录

1 简介

2 实验任务

3 硬件设计

step1:创建一个新的 IP 核

1-1 New IP Location

1-2 完成 Manage IP工程的创建

1-3 工程创建完成后,运行创建和封装 IP 向导。

1-4 选择创建一个带 AXI 接口的 IP 核

1-5 分别设置 IP 核名称(Name)、版本号(Version)、显示名(Display name)、描述(Description) 和路径(IP location)。

1-6 对 AXI 接口进行设置

1-7 将 IP 添加至 IP 库中,完成 IP 核的创建和封装。

1-8 对 breath_led_ip_v1.0 IP 核进行编辑

1-9 添加代码

1-10 添加代码

1-11 Add or Create design source

1-12 编辑breath_led.v

1-13 Run Synthesis

1-14 设置 IP 封装

1-15 点击 Compatibility,修改该 IP 核支持的器件。

1-16 点击 File Groups,然后点击界面上的“Merge Changes from Gile Groups Wizard”

1-17  点击 Customization Parameters,点击界面上的“Merge Changes from Customization Parameters Wizard”

1-18 调整参数在 GUI 显示的位置

1-19 更新总结界面,封装IP

step2:创建 Vivado 工程,将自定义的IP核添加至本工程的IP库中

 step3:使用 IP Integrator 创建 Processing System

3-1 Create Block Design

3-2 添加“ZYNQ7 Processing System”IP

3-3 添加 UART 控制器,修改 DDR3 的存储器类型型号,其它保持默认。

3-4 添加 Breath LED IP 核

3-5 Make External Regenerate Layout

step4:生成顶层 HDL 模块

4-1 Generate Output Products

4-2 Create HDL Wrapper

step5:生成 Bitstream 文件并导出到 SDK

5-1 Open Elaborated Design

5-2 保存管脚约束

5-3 Generate Bitstream

5-4 导出硬件

5-5 Launch SDK


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

1 简介

        Xilinx 官方为我们提供了非常丰富的 IP 核,如数学运算(乘法器、浮点运算器等)、信号处理(FFT、DDS 等),我们可以通过调用这些 IP 核来快速完成设计。然而随着系统的设计越来越复杂,官方提供的免费 IP 核有时并不能很好的适用我们的设计,这个时候就需要我们自己来实现这些功能。为了使这些模块或代码以后能够复用,可以通过自定义 IP 核的方式将这些模块集成到 Vivado 中的 IP 中,以达到简化系统设计和缩短产品上市时间的目的。
        在 Vivado 软件中,通过创建和封装 IP 向导的方式来自定义 IP 核,支持将当前工程、工程中的模块或者指定文件目录封装成 IP 核,当然也可以创建一个带有 AXI4 接口的 IP ,用于 PS PL 的数据通信。本次实验选择常用的方式,即创建一个带有 AXI 接口的 IP 核,该 IP 核通过 AXI 协议实现 PS PL 的数据通信。AXI 协议是一种高性能、高带宽、低延迟的片内总线,关于该协议的详细内容,我们会在后面的例程中向大家做详细的介绍。本次实验的系统框图如图 所示:
系统框图
        框图中的 UART 用于打印信息, Breath LED IP 核为自定义的 IP 核, PS 通过 AXI 接口为 LED IP 模块发送配置数据,从而来控制 PL LED 灯。

2 实验任务

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

3 硬件设计

step1:创建一个新的 IP

1-1 New IP Location

Vivado-->Tasks-->Manage IP-->New IP Location...
1 点击 Manage IP

1-2 完成 Manage IP工程的创建

 ​​​​​​        在弹出的界面中选择“Next

2 自定义 IP 核向导界面
        设置 Manage IP 核的属性,在“IP Location:”一栏指定工程的路径,路径为:D:/ZYNQ18/ Embedded_System/custom_ip,其它保持默认即可。注意,Part 一栏中设置开发板的型号,在后面的工程中会重新指定,这里直接保持默认。点击“Finish”完成 Manage IP工程的创建.
IP 设置选项

1-3 工程创建完成后,运行创建和封装 IP 向导。

选择创建和封装 IP 向导
封装 IP 向导界面

1-4 选择创建一个带 AXI 接口的 IP 核

封装 IP 选项

1-5 分别设置 IP 核名称(Name)、版本号(Version)、显示名(Display name)、描述(Description) 和路径(IP location)。

IP 参数设置

1-6 对 AXI 接口进行设置

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 库中,完成 IP 核的创建和封装。

创建和封装 IP 核总结界面
        在 IP Catalog 界面中可以看到刚刚添加的 IP 核,位于 User Repository 一栏中的 AXI Peripheral 下,名称为“breath_led_ip_v1.0 ”。
新添加的 IP 核

1-8 breath_led_ip_v1.0 IP 核进行编辑

        右击 breath_led_ip_v1.0 IP 核,选择“Edit in IP Packager ”,在弹出的界面中点击“ OK ”。
打开编辑 IP 核界面
设置工程名和路径

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

编辑 IP 核界面

1-9 添加代码

        双击 breath_led_ip_v1_0

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

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

output led ,
        添加完成后的代码如下图所示:
编辑 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 保存。如下图所示:

1-10 添加代码

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

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

读寄存器数据部分代码
        在创建和封装 IP 核向导中,我们总共定义了 4 个寄存器,代码中的 slv_reg0 slv_reg3 是寄存器地址0 至寄存器地址 3 对应的数据,通过例化呼吸灯模块,将寄存器地址对应的数据和呼吸灯模块的控制端口相连接,即可实现对呼吸灯的控制。
        我们接下来开始编辑代码,同样在代码的第 7 行添加如下代码:
        parameter START_FREQ_STEP = 10'd100 ,
        在代码的第 18 行添加如下代码:
        output led ,
        添加完成后的代码如下图所示:
编辑 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 保存代码,添加完成后的代码如下图所示:
例化 breath_led 代码

1-11 Add or Create design source

        此时工程中缺失 breath_led.v 文件, breath_led.v 文件用于实现呼吸灯的功能,这个代码是在“呼吸灯实验”的基础上修改而来。
        右击“Design Sources ”,选择“ Add Sources… ”,在弹出的界面中选择“ Add or Create design source ”,点击“NEXT ”,

        点击“ Create File ” 创 建 一 个 新 的 文 件 , 在 弹 出 的 界 面 输 入 名 称 breath_led , 路 径为../custom_ip/ip_repo/breath_led_ip_1.0/hdl ,点击“ OK ”按钮.
创建一个新的设计文件
设置设计文件的名称与路径
        点击“Finish ”按钮完成创建,如下图所示:

 

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

1-12 编辑breath_led.v

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

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

module breath_led(
	input 		sys_clk 		, //时钟信号
	input 		sys_rst_n 		, //复位信号
	input 		sw_ctrl			, //呼吸灯开关控制信号 1:亮 0:灭
	input 		set_en 			, //设置呼吸灯频率设置使能信号
	input [9:0] set_freq_step 	, //设置呼吸灯频率变化步长

	output 		led 			  //LED
);

//*****************************************************
//** main code
//*****************************************************

//parameter define
parameter START_FREQ_STEP = 10'd100; //设置频率步长初始值

//reg define
reg [15:0] period_cnt ; //周期计数器
reg [9:0] freq_step ; //呼吸灯频率间隔步长
reg [15:0] duty_cycle ; //设置高电平占空比的计数点
reg inc_dec_flag; //用于表示高电平占空比的计数值,是递增还是递减
//为 1 时表示占空比递减,为 0 时表示占空比递增
//wire define
wire led_t ;

//将周期信号计数值与占空比计数值进行比较,以输出驱动 led 的 PWM 信号
assign led_t = ( period_cnt <= duty_cycle ) ? 1'b1 : 1'b0 ;
assign led = led_t & sw_ctrl;

//周期信号计数器在 0-50_000 之间计数
always @ (posedge sys_clk) begin
	if (!sys_rst_n)
		period_cnt <= 16'd0;
	else if(!sw_ctrl)
		period_cnt <= 16'd0;
	else if( period_cnt == 16'd50_000 )
		period_cnt <= 16'd0;
	else
		period_cnt <= period_cnt + 16'd1;
end

//设置频率间隔
always @(posedge sys_clk) begin
	if(!sys_rst_n)
		freq_step <= START_FREQ_STEP;
	else if(set_en) begin
		if(set_freq_step == 0)
			freq_step <= 10'd1;
		else if(set_freq_step >= 10'd1_000)
			freq_step <= 10'd1_000;
		else 
			freq_step <= set_freq_step;
	end 
end

//设定高电平占空比的计数值
always @(posedge sys_clk) begin
	if (sys_rst_n == 1'b0) begin
		duty_cycle <= 16'd0;
		inc_dec_flag <= 1'b0;
	end 
	else if(!sw_ctrl) begin //呼吸灯开关关闭时,信号清零
		duty_cycle <= 16'd0;
		inc_dec_flag <= 1'b0;
	end 
	//每次计数完了一个周期,就调节占空比计数值
	else if( period_cnt == 16'd50_000 ) begin
		if( inc_dec_flag ) begin //占空比递减
			if( duty_cycle == 16'd0 )
                inc_dec_flag <= 1'b0;
			else if(duty_cycle < freq_step)
			    duty_cycle <= 16'd0;
			else 
			    duty_cycle <= duty_cycle - freq_step;
		end
		else begin //占空比递增
			if( duty_cycle >= 16'd50_000 ) 
				inc_dec_flag <= 1'b1;
			else
				duty_cycle <= duty_cycle + freq_step;
		end
	end
	else //未计数完一个周期时,占空比保持不变
		duty_cycle <= duty_cycle ;
end

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

1-13 Run Synthesis

        保存代码,并验证代码是否有语法错误。在左侧 Flow Navigator 导航栏中找到 SYNTHESIS ,点击该选项中的 “Run Synthesis” ,如下图所示:
编译代码
        在弹出的窗口中点击“OK ”按钮,等待代码编译完成。

1-14 设置 IP 封装

        接下来开始设置 IP 封装,将界面切换至 Package IP ,如果不小心关闭的话,可以通过 IP-XACT界面下的 component.xml 重新打开,如图:
打开 Package IP 界面
Package IP 界面
        Identification 这一栏的选项直接保持默认,需要注意的是,我们可以点击下图 Categories 选项下的“+ ”按钮来修改 IP 的分类,这里不做修改。
修改 IP 核分类

1-15 点击 Compatibility,修改该 IP 核支持的器件。

        点击 Family 一栏下的“ + ”图标,选择“Add Family Explicitly… ”,如下图所示:
“Compatibility 界面”
        这里勾选“zynq(zynq-7000) ”,表示该 IP 核支持 zynq 器件。而 Life-cycle 表明该 IP 核当前的产品生命周期,这里选择“Pre-Production ”。
选择支持的器件

1-16 点击 File Groups,然后点击界面上的“Merge Changes from Gile Groups Wizard

        如下图所示:

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

1-17  点击 Customization Parameters,点击界面上的“Merge Changes from Customization Parameters Wizard”

        如下图所示:
Customization Parameters 界面
        此时多了 Hidden Parameters 一栏,展开这个界面,可以看到程序中自定义的参数 START_FREQ_STEP ,右击这个参数,选择“Edit Parameter… ”,弹出编辑参数的界面,如下图 所示:
打开编辑参数界面
        在弹出的页面中勾选“Visible in Customization GUI ”,将此参数显示在 GUI 参数界面中;
        Format 格式改为“ long ”;
        勾选“Specify Range ”来设定此参数的范围。将 Type 改为“ Range of integers ”, Minimum 的值改为 1 ,Maximum 的值改为 1000 ,将 Default Value 的值改为 100 ,点击“ OK ”按钮,如下图所示:
参数设置

1-18 调整参数在 GUI 显示的位置

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

1-19 更新总结界面,封装IP

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

Review and Package 界面
关闭工程询问界面
        IP 核封装完成后,在 IP 核所在路径( ...\custom_ip\ip_repo\breath_led_ip_1.0\drivers\breath_led_ip_v1_0\src
目录下, Vivado 软件会自动生成 .c .h 文件,方便在 SDK 软件中对 IP 核进行操作 ,如下图所示:
软件生成的文件

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

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

step2:创建 Vivado 工程,将自定义的IP核添加至本工程的IP库中

        step1 是创建了一个自定义的 IP 核,接下来我们来创建 Vivado 工程,工程名为 user_led ,路径为 D:/ZYNQ18/Embedded_System/custom_ip 目录下,创建的步骤这里不再赘述。
        在开始下一个步骤之前,我们先把步骤1 自定义的 IP 核添加至本工程的 IP 库中,点击菜单栏的“ Tools ”,选择“Setting ”,如下图所示:
打开设置界面
        点击“IP”一栏下的“Repository ”,然后点击“ + ”来添加自定义的 IP 核,如下图所示:
IP 库添加界面
        接下来会弹出添加自定义 IP 核的路径,选择 ../custom_ip/ip_repo/breath_led_ip_1.0 ,点击“ Select ”,在弹出的界面中可以看到识别到的 IP 核,点击“ OK ”按钮添加 IP 核,如下图所示:
添加 IP 核
        最后点击“OK ”按钮,完成 IP 核的添加,如下图所示:
添加 IP 核完成

 step3:使用 IP Integrator 创建 Processing System

3-1 Create Block Design

3-2 添加“ZYNQ7 Processing System”IP

3-3 添加 UART 控制器,修改 DDR3 的存储器类型型号,其它保持默认。

         配置完成后,点击“ Run Block Automation ”,框图如下图所示:
ZYNQ7 框图

3-4 添加 Breath LED IP

        添加完成后,可以双击 led IP 核来设置参数。这里不作修改。

        接下来点击“Run Connection Automation ”来自动连线,连线完成后如图 所示:

3-5 Make External Regenerate Layout

        此时原理图中还没有 LED 的引脚,右击 breath_led_ip_0 led 引脚,选择“ Make External”。将引出的 led_0 改为 led。点击“ Regenerate Layout ”图标,最终原理图界面如图 所示:
最终原理图界面

step4:生成顶层 HDL 模块

4-1 Generate Output Products

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

4-2 Create HDL Wrapper

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

step5:生成 Bitstream 文件并导出到 SDK

5-1 Open Elaborated Design

        在左侧 Flow Navigator 导航栏中找到 RTL ANALYSIS ,点击该选项中的“ Open Elaborated Design ”。在弹出的对话框中点击“OK ”。如下图所示:
Elaborated Design 对话框
        在 ELABORATED DESIGN 界面下方找到 I/O Ports 一栏。如果没有找到则通过在菜单栏中点击 Layout ,然后在下拉列表中选择 I/O Planning 。我们将在 I/O Ports 一栏对 PL 部分的接口进行管脚分配, led 分配至BANK35 的 J16 引脚,该 BANK 的供电电压为 3.3V ,因此 I/O Std 一列对应的电平也需要修改。如图 所示:
管脚分配

5-2 保存管脚约束

         设置完成后按快捷 Ctrl+S 保存管脚约束,在弹出的对话框输入文件名“ user_led ”。
保存约束

5-3 Generate Bitstream

       点击“Generate Bitstream”。在连续弹出的对话框中依次点击“YES”、“OK”。Vivado 工具开始依次对设计进行 综合实现、并 生成 Bitstream 文件

5-4 导出硬件

         File > Export > Export hardware。,勾选 “Include bitstream”。

5-5 Launch SDK

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不做拖延王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值