S02_CH13_ AXI_PWM 实验
S02_CH13_ AXI_PWM 实验
当学习了上一章的协议介绍内容后,开发基于这些协议的方案已经不是什么难事了,关键的一点就是从零到有的突破了。本章就以AXI-Lite总线实现8路LED自定义IP作为第一验证AXI-Lite总线应用的方案,带领大家快速进入实战状态。
13.1 自定义IP的封装
Step1:新建一个名为Miz_sys空的工程。
Step2:选择Tools Create and Package IP 创建IP
Step3:单击NEXT
Step4:由于我们需要挂在到总线上,因此创建一个带AXI总线的用户IP
Step5:设置IP的名字为PWM_LITE_ML版本号默认,并且记住IP的位置
Step6:设置总线形式为Lite总线,Lite总线是简化的AXI总线消耗的资源少,当然性能也是比完全版的AXI总线差一点,但是由于音频的速度并不高,因此采用Lite总线就够了,设置寄存器数量为16,因为后面我们需要用到16个寄存器。
Step7:选择Edit IP单击Finish完成

13.2 miz702_pwm用户IP的修改
IP创建完成后,并不能立马使用,还需要做一些修改。
Step1:打开PWM_AXI_ML.v文件在以下位置修改:
Step2:修改PWM_AXI_ML_v1_0_S00_AXI.v的端口部分
Step3:slv_reg0-slv_reg5为PS部分写入PL的寄存器。通过这个16个寄存器的值,我们可以控制PWM的占空比。
Step3:下面这段代码就是PS写PL部分的寄存器,一共有16个寄存器
|
always @( posedge S_AXI_ACLK ) begin if ( S_AXI_ARESETN == 1'b0 ) begin slv_reg0 <= 0; slv_reg1 <= 0; slv_reg2 <= 0; slv_reg3 <= 0; slv_reg4 <= 0; slv_reg5 <= 0; slv_reg6 <= 0; slv_reg7 <= 0; slv_reg8 <= 0; slv_reg9 <= 0; slv_reg10 <= 0; slv_reg11 <= 0; slv_reg12 <= 0; slv_reg13 <= 0; slv_reg14 <= 0; slv_reg15 <= 0; end else begin if (slv_reg_wren) begin case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] ) 4'h0: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 0 slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h1: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 1 slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h2: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 2 slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h3: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 3 slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h4: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 4 slv_reg4[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h5: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 5 slv_reg5[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h6: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 6 slv_reg6[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h7: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 7 slv_reg7[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h8: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 8 slv_reg8[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'h9: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 9 slv_reg9[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'hA: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 10 slv_reg10[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'hB: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 11 slv_reg11[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'hC: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 12 slv_reg12[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'hD: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 13 slv_reg13[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'hE: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 14 slv_reg14[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end 4'hF: for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) if ( S_AXI_WSTRB[byte_index] == 1 ) begin // Respective byte enables are asserted as per write strobes // Slave register 15 slv_reg15[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; end default : begin slv_reg0 <= slv_reg0; slv_reg1 <= slv_reg1; slv_reg2 <= slv_reg2; slv_reg3 <= slv_reg3; slv_reg4 <= slv_reg4; slv_reg5 <= slv_reg5; slv_reg6 <= slv_reg6; slv_reg7 <= slv_reg7; slv_reg8 <= slv_reg8; slv_reg9 <= slv_reg9; slv_reg10 <= slv_reg10; slv_reg11 <= slv_reg11; slv_reg12 <= slv_reg12; slv_reg13 <= slv_reg13; slv_reg14 <= slv_reg14; slv_reg15 <= slv_reg15; end endcase end end end |
Step4:新建一个PWM.v 文件实现PWM输出。
|
module PWM( input clk, input rst_n, input [31:0]fre_set, input [31:0]wav_set, output PWM_o ); reg [31:0]fre_cnt; always @(posedge clk)begin if(rst_n==1'b0)begin fre_cnt <=32'd0; end else begin if(fre_cnt<fre_set) begin fre_cnt <= fre_cnt+1'b1; end else begin fre_cnt<=32'd0; end end end assign PWM_o = (wav_set>fre_cnt); endmodule |
Step5:修改完成后重新封装一次自定义IP
Step6:单击NEXT
Step7:和第一次不同,这次选择第一个单选框然后单击NEXT
Step8:选择第一个单选框,然后单击NEXT
Step9:点击Overwrite
Step10:点击Finish 到此自定义IP结束

13.3 搭建硬件工程
Step1:另外新建一个VIVADO工程,根据自己的开发板正确配置芯片型号。
Step2:在Project manager区中单击Project settings。
Step3:选择IP设置区中的repository manager,将上一节我们封装好的IP的路劲添加进去。
Step:4:单击+号图标,将上一节封装的IP的路劲存放进去,单击OK。
Step5:新建一个BD文件,输入文件名,完成创建。
Step6:向BD文件中添加一个ZYNQ Processing system,根据自身硬件完成IP的配置。
Step7:单击添加IP图标,输入上一节我们自定义IP的模块名,将其添加入BD文件中。
Step8:直接点击Run connection automation,然后单击OK。
Step9:选中PWM_o,按Ctrl+T组合键引出端口。
Step10:单击IP icon
添加 ila CORE
Step11:双击打开ILA CORE
Step12:双击打开ILA CORE
General Options设置如下
Probe_Ports设置如下,之后单击OK
Step13:连接Probe0到PWM_o。
Step14:连接CLK接口到FCLK_CLK0接口。
Step15:右键单击Block文件,文件选择Generate the Output Products。
Step16:右键单击Block文件,选择Create a HDL wrapper,根据Block文件内容产生一个HDL 的顶层文件,并选择让vivado自动完成。
Step17:添加一个约束文件,打开对应自己硬件的原理图,查看LED部分引脚连接情况,此次我们只用4个LED完成实验。Miz702约束文件如下所示:
|
set_property SEVERITY {Warning} [get_drc_checks NSTD-1] set_property SEVERITY {Warning} [get_drc_checks UCIO-1] set_property PACKAGE_PIN T22 [get_ports {PWM_o[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[0]}] set_property PACKAGE_PIN T21 [get_ports {PWM_o[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[1]}] set_property PACKAGE_PIN U22 [get_ports {PWM_o[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[2]}] set_property PACKAGE_PIN U21 [get_ports {PWM_o[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {PWM_o[3]}] |
其他型号开发板参照对应型号的原理图的LED部分,修改成对应的引脚即可。
Step11:生成bit文件。
13.4 加载到SDK
Step1:导出硬件。
Step2:新建一个空SDK工程,并添加一个main.c的文件。
Step3:在main.c文件中添加以下程序,按Ctrl+S保存后自动开始编译。
|
#include <stdio.h> #include "xparameters.h" #include "xil_io.h" #include "sleep.h" #include "xil_types.h" int main() { Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR,99);//pwm0 fre Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+4,10);//pwm0 wav Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+8,99);//pwm1 fre Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+12,20);//pwm1 wav Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+16,99);//pwm2 fre Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+20,40);//pwm2 wav Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+24,99);//pwm3 fre Xil_Out32(XPAR_PWM_AXI_ML_0_BASEADDR+28,80);//pwm3 wav return 0; } |
Step4:右击工程,选择Debug as ->Debug configuration。
Step5:选中system Debugger,双击创建一个系统调试。
Step6:设置系统调试。
Step7:单击运行程序按钮
运行程序。
Step8:回到VIVADO单击Open Target->Auto Connect
Step9:加载完成后的界面
Step10:单击箭头所指向启动触发,窗口显示采集到的信号波形。

13.5 程序分析
Main函数中,根据之前章节的讲解我们可知,此处是分别向AXI总线的寄存器中写入数据。在13.2小节里,我们观察到,pwm_o[0]的频率设置和波形设置是通过slv_reg0和slv_reg1控制的。
由程序可知,程序中设置的pwm_o[0]的频率和波形频率分别为99和10,我们在ila中实际测量一下看看波形是否正确(将黄色测量线拖放到某一点,然后点击
,可设立一个参考点)。
由上图可知,我们写入的数据和实际的输出是完全一致的,验证了我们的想法。
13.6 本章小结
本章实现了第一个实现具体功能的8路PWM,通过点亮LED可以看到效果。这个简单的工程充分体现了SOC的优势。CPU无需参与就可以让8路PWM持续输出,这个输出是有PL控制的
S02_CH13_ AXI_PWM 实验的更多相关文章
- [原] 利用 OVS 建立 VxLAN 虚拟网络实验
OVS 配置 VxLAN HOST A ------------------------------------------ | zh-veth0(10.1.1.1) VM A | | ---|--- ...
- Android中Activity的四大启动模式实验简述
作为Android四大组件之一,Activity可以说是最基本也是最常见的组件,它提供了一个显示界面,从而实现与用户的交互,作为初学者,必须熟练掌握.今天我们就来通过实验演示,来帮助大家理解Activ ...
- SEED实验系列文章目录
美国雪城大学SEEDLabs实验列表 SEEDLabs是一套完整的信息安全实验,涵盖本科信息安全教学中的大部分基本原理.项目组2002年由杜文亮教授创建,目前开发了30个实验,几百所大学已采用.实验楼 ...
- 物联网实验4 alljoyn物联网实验之手机局域网控制设备
AllJoyn开源物联网协议框架,官方描述是一个能够使连接设备之间进行互操作的通用软件框架和系统服务核心集,也是一个跨制造商来创建动态近端网络的软件应用.高通已经将该项目捐赠给了一个名为“AllSee ...
- (转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)
一. HTTP请求的数据流总结#上传数据, yeelink的数据流如下POST /v1.0/device/4420/sensor/9089/datapoints HTTP/1.1Host: api. ...
- (原创) alljoyn物联网实验之手机局域网控制设备
AllJoyn开源物联网协议框架,官方描述是一个能够使连接设备之间进行互操作的通用软件框架和系统服务核心集,也是一个跨制造商来创建动态近端网络的软件应用.高通已经将该项目捐赠给了一个名为“AllSee ...
- 实验:Oracle直接拷贝物理存储文件迁移
实验目的:Oracle直接拷贝物理文件迁移,生产库有类似施工需求,故在实验环境简单验证一下. 实验环境: A主机:192.168.1.200 Solaris10 + Oracle 11.2.0.1 B ...
- Oracle RAC 更换存储实验
实验环境准备: RHEL 6.5 + Oracle 11.2.0.4 RAC (2nodes) OCR和Voting Disk使用的是OCR1磁盘组,底层对应3个1G大小的共享LUN,一般冗余: DA ...
- Vertica集群扩容实验过程记录
需求: 将3个节点的Vertica集群扩容,额外增加3个节点,即扩展到6个节点的Vertica集群. 实验环境: RHEL 6.5 + Vertica 7.2.2-2 步骤: 1.三节点Vertica ...
随机推荐
- BZOJ 4734 UOJ #269 如何优雅地求和 (多项式)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4734 (UOJ) http://uoj.ac/problem/269 题解 ...
- js/jQuery中的宽高
一.和window有关的宽高 window.innerWidth:浏览器窗口宽度 window.innerHeight:浏览器窗口高度(不包括导航,工具栏等的高度) window.outerWidth ...
- 【Golang】嗅探抓包,解决线上偶现问题来不及抓包的情况
背景 测试群里经常看到客户端的同学反馈发现了偶现Bug,但是来不及抓包,最后不了了之,最近出现得比较频繁,所以写个小脚本解决这个问题. 实现思路 实现的思路比较简单: 抓包 存日志 做日志管理 具体实 ...
- OpenResty之 lua_shared_dict 指令
1. lua_shared_dict 指令介绍 原文: lua_shared_dict syntax:lua_shared_dict <name> <size> default ...
- ybatis 逆向工程 自动生成的mapper文件没有 主键方法
1.数据表没有设置主键 设置个主键就好 2.在mybits配置文档里设置了某些属性值为false 在mybatis配置文档里查看 enableSelectByPrimaryKey="true ...
- BOM相关方法及属性
browser objec tmodel浏览器对象模型 BOM里面的方法大多在window对象底下,window代表窗口,也就是说,在BOM里面大多调用window下面的东西. 1.open方法是wi ...
- SpringBoot/SpringMVC 下载本地文件
页面代码: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Ty ...
- 对官网vue事件修饰符串联的顺序如何理解?
官网有一个提醒:使用修饰符时,顺序很重要:相应的代码会以同样的顺序产生.因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent ...
- SQL-W3School-高级:SQL LEFT JOIN 关键字
ylbtech-SQL-W3School-高级:SQL LEFT JOIN 关键字 1.返回顶部 1. SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1 ...
- Markdown 图片的简单处理
0. 前言 最近写 md 文章的时候发现,在 markdown 里插入一些很长的图片的时候,会显得很不好看,于是去查了一下如何实现 markdown 里图片的并排显示,参考了各个博客内的内容和 mar ...